Gate on H4xx docstrings for pep8
In an effort to help horizon more friendly to OpenStack hacking guidelines, we now gate on H40* violations. Change-Id: Id07294543660368d2f7f5ac363710176ab23b874 Signed-off-by: Paul Belanger <paul.belanger@polybeacon.com>
This commit is contained in:
parent
94129baebb
commit
da8c69afa6
|
@ -390,15 +390,13 @@ class Dashboard(Registry, HorizonComponent):
|
|||
self._panel_groups = None
|
||||
|
||||
def get_panel(self, panel):
|
||||
"""
|
||||
Returns the specified :class:`~horizon.Panel` instance registered
|
||||
"""Returns the specified :class:`~horizon.Panel` instance registered
|
||||
with this dashboard.
|
||||
"""
|
||||
return self._registered(panel)
|
||||
|
||||
def get_panels(self):
|
||||
"""
|
||||
Returns the :class:`~horizon.Panel` instances registered with this
|
||||
"""Returns the :class:`~horizon.Panel` instances registered with this
|
||||
dashboard in order, without any panel groupings.
|
||||
"""
|
||||
all_panels = []
|
||||
|
@ -787,8 +785,7 @@ class Site(Registry, HorizonComponent):
|
|||
|
||||
|
||||
class HorizonSite(Site):
|
||||
"""
|
||||
A singleton implementation of Site such that all dealings with horizon
|
||||
"""A singleton implementation of Site such that all dealings with horizon
|
||||
get the same instance no matter what. There can be only one.
|
||||
"""
|
||||
_instance = None
|
||||
|
|
|
@ -121,9 +121,8 @@ class ResourceBrowser(html.HTMLElement):
|
|||
% (attr_name, self.__class__.__name__))
|
||||
|
||||
def set_tables(self, tables):
|
||||
"""
|
||||
Sets the table instances on the browser from a dictionary mapping table
|
||||
names to table instances (as constructed by MultiTableView).
|
||||
"""Sets the table instances on the browser from a dictionary mapping
|
||||
table names to table instances (as constructed by MultiTableView).
|
||||
"""
|
||||
self.navigation_table = tables[self.navigation_table_class._meta.name]
|
||||
self.content_table = tables[self.content_table_class._meta.name]
|
||||
|
|
|
@ -43,8 +43,7 @@ class HorizonReporterFilter(SafeExceptionReporterFilter):
|
|||
# TODO(gabriel): This bugfix is cribbed from Django's code. When 1.4.1
|
||||
# is available we can remove this code.
|
||||
def get_traceback_frame_variables(self, request, tb_frame):
|
||||
"""
|
||||
Replaces the values of variables marked as sensitive with
|
||||
"""Replaces the values of variables marked as sensitive with
|
||||
stars (*********).
|
||||
"""
|
||||
# Loop through the frame's callers to see if the sensitive_variables
|
||||
|
@ -98,8 +97,7 @@ class HorizonException(Exception):
|
|||
|
||||
|
||||
class Http302(HorizonException):
|
||||
"""
|
||||
Error class which can be raised from within a handler to cause an
|
||||
"""Error class which can be raised from within a handler to cause an
|
||||
early bailout and redirect at the middleware level.
|
||||
"""
|
||||
status_code = 302
|
||||
|
@ -110,8 +108,7 @@ class Http302(HorizonException):
|
|||
|
||||
|
||||
class NotAuthorized(HorizonException):
|
||||
"""
|
||||
Raised whenever a user attempts to access a resource which they do not
|
||||
"""Raised whenever a user attempts to access a resource which they do not
|
||||
have permission-based access to (such as when failing the
|
||||
:func:`~horizon.decorators.require_perms` decorator).
|
||||
|
||||
|
@ -123,8 +120,8 @@ class NotAuthorized(HorizonException):
|
|||
|
||||
|
||||
class NotAuthenticated(HorizonException):
|
||||
"""
|
||||
Raised when a user is trying to make requests and they are not logged in.
|
||||
"""Raised when a user is trying to make requests and they are not logged
|
||||
in.
|
||||
|
||||
The included :class:`~horizon.middleware.HorizonMiddleware` catches
|
||||
``NotAuthenticated`` and handles it gracefully by displaying an error
|
||||
|
@ -144,9 +141,8 @@ class RecoverableError(HorizonException):
|
|||
|
||||
|
||||
class ServiceCatalogException(HorizonException):
|
||||
"""
|
||||
Raised when a requested service is not available in the ``ServiceCatalog``
|
||||
returned by Keystone.
|
||||
"""Raised when a requested service is not available in the
|
||||
``ServiceCatalog`` returned by Keystone.
|
||||
"""
|
||||
def __init__(self, service_name):
|
||||
message = 'Invalid service catalog service: %s' % service_name
|
||||
|
@ -154,8 +150,7 @@ class ServiceCatalogException(HorizonException):
|
|||
|
||||
|
||||
class AlreadyExists(HorizonException):
|
||||
"""
|
||||
Exception to be raised when trying to create an API resource which
|
||||
"""Exception to be raised when trying to create an API resource which
|
||||
already exists.
|
||||
"""
|
||||
def __init__(self, name, resource_type):
|
||||
|
@ -178,16 +173,14 @@ class WorkflowError(HorizonException):
|
|||
|
||||
|
||||
class WorkflowValidationError(HorizonException):
|
||||
"""
|
||||
Exception raised during workflow validation if required data is missing,
|
||||
"""Exception raised during workflow validation if required data is missing,
|
||||
or existing data is not valid.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class HandledException(HorizonException):
|
||||
"""
|
||||
Used internally to track exceptions that have gone through
|
||||
"""Used internally to track exceptions that have gone through
|
||||
:func:`horizon.exceptions.handle` more than once.
|
||||
"""
|
||||
def __init__(self, wrapped):
|
||||
|
@ -205,8 +198,7 @@ def error_color(msg):
|
|||
|
||||
|
||||
def check_message(keywords, message):
|
||||
"""
|
||||
Checks an exception for given keywords and raises a new ``ActionError``
|
||||
"""Checks an exception for given keywords and raises a new ``ActionError``
|
||||
with the desired message if the keywords are found. This allows selective
|
||||
control over API error messages.
|
||||
"""
|
||||
|
|
|
@ -32,15 +32,13 @@ class SelfHandlingMixin(object):
|
|||
|
||||
|
||||
class SelfHandlingForm(SelfHandlingMixin, forms.Form):
|
||||
"""
|
||||
A base :class:`Form <django:django.forms.Form>` class which includes
|
||||
"""A base :class:`Form <django:django.forms.Form>` class which includes
|
||||
processing logic in its subclasses.
|
||||
"""
|
||||
required_css_class = 'required'
|
||||
|
||||
def api_error(self, message):
|
||||
"""
|
||||
Adds an error to the form's error dictionary after validation
|
||||
"""Adds an error to the form's error dictionary after validation
|
||||
based on problems reported via the API. This is useful when you
|
||||
wish for API errors to appear as errors on the form rather than
|
||||
using the messages framework.
|
||||
|
|
|
@ -20,9 +20,8 @@ from django.forms import widgets
|
|||
|
||||
|
||||
class DynamicSelectWidget(widgets.Select):
|
||||
"""
|
||||
A subclass of the ``Select`` widget which renders extra attributes for use
|
||||
in callbacks to handle dynamic changes to the available choices.
|
||||
"""A subclass of the ``Select`` widget which renders extra attributes for
|
||||
use in callbacks to handle dynamic changes to the available choices.
|
||||
"""
|
||||
_data_add_url_attr = "data-add-item-url"
|
||||
|
||||
|
@ -46,8 +45,7 @@ class DynamicSelectWidget(widgets.Select):
|
|||
|
||||
|
||||
class DynamicChoiceField(fields.ChoiceField):
|
||||
"""
|
||||
A subclass of ``ChoiceField`` with additional properties that make
|
||||
"""A subclass of ``ChoiceField`` with additional properties that make
|
||||
dynamically updating its elements easier.
|
||||
|
||||
Notably, the field declaration takes an extra argument, ``add_item_link``
|
||||
|
|
|
@ -49,8 +49,7 @@ class ModalFormMixin(object):
|
|||
|
||||
|
||||
class ModalFormView(ModalFormMixin, generic.FormView):
|
||||
"""
|
||||
The main view class from which all views which handle forms in Horizon
|
||||
"""The main view class from which all views which handle forms in Horizon
|
||||
should inherit. It takes care of all details with processing
|
||||
:class:`~horizon.forms.base.SelfHandlingForm` classes, and modal concerns
|
||||
when the associated template inherits from
|
||||
|
@ -65,25 +64,21 @@ class ModalFormView(ModalFormMixin, generic.FormView):
|
|||
"""
|
||||
|
||||
def get_object_id(self, obj):
|
||||
"""
|
||||
For dynamic insertion of resources created in modals, this method
|
||||
"""For dynamic insertion of resources created in modals, this method
|
||||
returns the id of the created object. Defaults to returning the ``id``
|
||||
attribute.
|
||||
"""
|
||||
return obj.id
|
||||
|
||||
def get_object_display(self, obj):
|
||||
"""
|
||||
For dynamic insertion of resources created in modals, this method
|
||||
"""For dynamic insertion of resources created in modals, this method
|
||||
returns the display name of the created object. Defaults to returning
|
||||
the ``name`` attribute.
|
||||
"""
|
||||
return obj.name
|
||||
|
||||
def get_form(self, form_class):
|
||||
"""
|
||||
Returns an instance of the form to be used in this view.
|
||||
"""
|
||||
"""Returns an instance of the form to be used in this view."""
|
||||
return form_class(self.request, **self.get_form_kwargs())
|
||||
|
||||
def form_valid(self, form):
|
||||
|
|
|
@ -26,9 +26,7 @@ from django.utils.safestring import SafeData # noqa
|
|||
|
||||
|
||||
def add_message(request, level, message, extra_tags='', fail_silently=False):
|
||||
"""
|
||||
Attempts to add a message to the request using the 'messages' app.
|
||||
"""
|
||||
"""Attempts to add a message to the request using the 'messages' app."""
|
||||
if request.is_ajax():
|
||||
tag = constants.DEFAULT_TAGS[level]
|
||||
# if message is marked as safe, pass "safe" tag as extra_tags so that
|
||||
|
@ -44,40 +42,30 @@ def add_message(request, level, message, extra_tags='', fail_silently=False):
|
|||
|
||||
|
||||
def debug(request, message, extra_tags='', fail_silently=False):
|
||||
"""
|
||||
Adds a message with the ``DEBUG`` level.
|
||||
"""
|
||||
"""Adds a message with the ``DEBUG`` level."""
|
||||
add_message(request, constants.DEBUG, message, extra_tags=extra_tags,
|
||||
fail_silently=fail_silently)
|
||||
|
||||
|
||||
def info(request, message, extra_tags='', fail_silently=False):
|
||||
"""
|
||||
Adds a message with the ``INFO`` level.
|
||||
"""
|
||||
"""Adds a message with the ``INFO`` level."""
|
||||
add_message(request, constants.INFO, message, extra_tags=extra_tags,
|
||||
fail_silently=fail_silently)
|
||||
|
||||
|
||||
def success(request, message, extra_tags='', fail_silently=False):
|
||||
"""
|
||||
Adds a message with the ``SUCCESS`` level.
|
||||
"""
|
||||
"""Adds a message with the ``SUCCESS`` level."""
|
||||
add_message(request, constants.SUCCESS, message, extra_tags=extra_tags,
|
||||
fail_silently=fail_silently)
|
||||
|
||||
|
||||
def warning(request, message, extra_tags='', fail_silently=False):
|
||||
"""
|
||||
Adds a message with the ``WARNING`` level.
|
||||
"""
|
||||
"""Adds a message with the ``WARNING`` level."""
|
||||
add_message(request, constants.WARNING, message, extra_tags=extra_tags,
|
||||
fail_silently=fail_silently)
|
||||
|
||||
|
||||
def error(request, message, extra_tags='', fail_silently=False):
|
||||
"""
|
||||
Adds a message with the ``ERROR`` level.
|
||||
"""
|
||||
"""Adds a message with the ``ERROR`` level."""
|
||||
add_message(request, constants.ERROR, message, extra_tags=extra_tags,
|
||||
fail_silently=fail_silently)
|
||||
|
|
|
@ -75,8 +75,7 @@ class HorizonMiddleware(object):
|
|||
request.session['last_activity'] = timestamp
|
||||
|
||||
def process_exception(self, request, exception):
|
||||
"""
|
||||
Catches internal Horizon exception classes such as NotAuthorized,
|
||||
"""Catches internal Horizon exception classes such as NotAuthorized,
|
||||
NotFound and Http302 and handles them gracefully.
|
||||
"""
|
||||
if isinstance(exception, (exceptions.NotAuthorized,
|
||||
|
@ -108,8 +107,7 @@ class HorizonMiddleware(object):
|
|||
return shortcuts.redirect(exception.location)
|
||||
|
||||
def process_response(self, request, response):
|
||||
"""
|
||||
Convert HttpResponseRedirect to HttpResponse if request is via ajax
|
||||
"""Convert HttpResponseRedirect to HttpResponse if request is via ajax
|
||||
to allow ajax request to redirect url
|
||||
"""
|
||||
if request.is_ajax() and hasattr(request, 'horizon'):
|
||||
|
|
|
@ -101,16 +101,14 @@ class BaseAction(html.HTMLElement):
|
|||
pass
|
||||
|
||||
def get_default_classes(self):
|
||||
"""
|
||||
Returns a list of the default classes for the action. Defaults to
|
||||
"""Returns a list of the default classes for the action. Defaults to
|
||||
``["btn", "btn-small"]``.
|
||||
"""
|
||||
return getattr(settings, "ACTION_CSS_CLASSES", ACTION_CSS_CLASSES)
|
||||
|
||||
def get_default_attrs(self):
|
||||
"""
|
||||
Returns a list of the default HTML attributes for the action. Defaults
|
||||
to returning an ``id`` attribute with the value
|
||||
"""Returns a list of the default HTML attributes for the action.
|
||||
Defaults to returning an ``id`` attribute with the value
|
||||
``{{ table.name }}__action_{{ action.name }}__{{ creation counter }}``.
|
||||
"""
|
||||
if self.datum is not None:
|
||||
|
@ -434,8 +432,7 @@ class FilterAction(BaseAction):
|
|||
|
||||
|
||||
class FixedFilterAction(FilterAction):
|
||||
""" A filter action with fixed buttons.
|
||||
"""
|
||||
"""A filter action with fixed buttons."""
|
||||
filter_type = 'fixed'
|
||||
needs_preloading = True
|
||||
|
||||
|
@ -543,8 +540,7 @@ class BatchAction(Action):
|
|||
return super(BatchAction, self)._allowed(request, datum)
|
||||
|
||||
def _conjugate(self, items=None, past=False):
|
||||
"""
|
||||
Builds combinations like 'Delete Object' and 'Deleted
|
||||
"""Builds combinations like 'Delete Object' and 'Deleted
|
||||
Objects' based on the number of items and `past` flag.
|
||||
"""
|
||||
action_type = "past" if past else "present"
|
||||
|
@ -565,8 +561,8 @@ class BatchAction(Action):
|
|||
return msgstr % {'action': action, 'data_type': data_type}
|
||||
|
||||
def action(self, request, datum_id):
|
||||
"""
|
||||
Required. Accepts a single object id and performs the specific action.
|
||||
"""Required. Accepts a single object id and performs the specific
|
||||
action.
|
||||
|
||||
Return values are discarded, errors raised are caught and logged.
|
||||
"""
|
||||
|
@ -574,17 +570,13 @@ class BatchAction(Action):
|
|||
'BatchAction: %s' % self.data_type_singular)
|
||||
|
||||
def update(self, request, datum):
|
||||
"""
|
||||
Switches the action verbose name, if needed
|
||||
"""
|
||||
"""Switches the action verbose name, if needed."""
|
||||
if getattr(self, 'action_present', False):
|
||||
self.verbose_name = self._conjugate()
|
||||
self.verbose_name_plural = self._conjugate('plural')
|
||||
|
||||
def get_success_url(self, request=None):
|
||||
"""
|
||||
Returns the URL to redirect to after a successful action.
|
||||
"""
|
||||
"""Returns the URL to redirect to after a successful action."""
|
||||
if self.success_url:
|
||||
return self.success_url
|
||||
return request.get_full_path()
|
||||
|
|
|
@ -270,10 +270,9 @@ class Column(html.HTMLElement):
|
|||
return '<%s: %s>' % (self.__class__.__name__, self.name)
|
||||
|
||||
def get_raw_data(self, datum):
|
||||
"""
|
||||
Returns the raw data for this column, before any filters or formatting
|
||||
are applied to it. This is useful when doing calculations on data in
|
||||
the table.
|
||||
"""Returns the raw data for this column, before any filters or
|
||||
formatting are applied to it. This is useful when doing calculations
|
||||
on data in the table.
|
||||
"""
|
||||
# Callable transformations
|
||||
if callable(self.transform):
|
||||
|
@ -295,8 +294,8 @@ class Column(html.HTMLElement):
|
|||
return data
|
||||
|
||||
def get_data(self, datum):
|
||||
"""
|
||||
Returns the final display data for this column from the given inputs.
|
||||
"""Returns the final display data for this column from the given
|
||||
inputs.
|
||||
|
||||
The return value will be either the attribute specified for this column
|
||||
or the return value of the attr:`~horizon.tables.Column.transform`
|
||||
|
@ -355,8 +354,7 @@ class Column(html.HTMLElement):
|
|||
return self.link
|
||||
|
||||
def get_summation(self):
|
||||
"""
|
||||
Returns the summary value for the data in this column if a
|
||||
"""Returns the summary value for the data in this column if a
|
||||
valid summation method is specified for it. Otherwise returns ``None``.
|
||||
"""
|
||||
if self.summation not in self.summation_methods:
|
||||
|
@ -444,8 +442,7 @@ class Row(html.HTMLElement):
|
|||
self.cells = []
|
||||
|
||||
def load_cells(self, datum=None):
|
||||
"""
|
||||
Load the row's data (either provided at initialization or as an
|
||||
"""Load the row's data (either provided at initialization or as an
|
||||
argument to this function), initiailize all the cells contained
|
||||
by this row, and set the appropriate row properties which require
|
||||
the row's data to be determined.
|
||||
|
@ -537,8 +534,7 @@ class Row(html.HTMLElement):
|
|||
return "%s?%s" % (table_url, params)
|
||||
|
||||
def get_data(self, request, obj_id):
|
||||
"""
|
||||
Fetches the updated data for the row based on the object id
|
||||
"""Fetches the updated data for the row based on the object id
|
||||
passed in. Must be implemented by a subclass to allow AJAX updating.
|
||||
"""
|
||||
raise NotImplementedError("You must define a get_data method on %s"
|
||||
|
@ -565,8 +561,7 @@ class Cell(html.HTMLElement):
|
|||
|
||||
@property
|
||||
def value(self):
|
||||
"""
|
||||
Returns a formatted version of the data for final output.
|
||||
"""Returns a formatted version of the data for final output.
|
||||
|
||||
This takes into consideration the
|
||||
:attr:`~horizon.tables.Column.link`` and
|
||||
|
@ -1041,8 +1036,7 @@ class DataTable(object):
|
|||
return self._no_data_message
|
||||
|
||||
def get_object_by_id(self, lookup):
|
||||
"""
|
||||
Returns the data object from the table's dataset which matches
|
||||
"""Returns the data object from the table's dataset which matches
|
||||
the ``lookup`` parameter specified. An error will be raised if
|
||||
the match is not a single data object.
|
||||
|
||||
|
@ -1071,8 +1065,7 @@ class DataTable(object):
|
|||
|
||||
@property
|
||||
def has_actions(self):
|
||||
"""
|
||||
Boolean. Indicates whether there are any available actions on this
|
||||
"""Boolean. Indicates whether there are any available actions on this
|
||||
table.
|
||||
"""
|
||||
if not self.base_actions:
|
||||
|
@ -1081,8 +1074,7 @@ class DataTable(object):
|
|||
|
||||
@property
|
||||
def needs_form_wrapper(self):
|
||||
"""
|
||||
Boolean. Indicates whather this table should be rendered wrapped in
|
||||
"""Boolean. Indicates whather this table should be rendered wrapped in
|
||||
a ``<form>`` tag or not.
|
||||
"""
|
||||
# If needs_form_wrapper is explicitly set, defer to that.
|
||||
|
@ -1132,9 +1124,9 @@ class DataTable(object):
|
|||
return table_actions_template.render(context)
|
||||
|
||||
def render_row_actions(self, datum):
|
||||
"""Renders the actions specified in ``Meta.row_actions`` using the
|
||||
current row data.
|
||||
"""
|
||||
Renders the actions specified in ``Meta.row_actions`` using the
|
||||
current row data. """
|
||||
template_path = self._meta.row_actions_template
|
||||
row_actions_template = template.loader.get_template(template_path)
|
||||
bound_actions = self.get_row_actions(datum)
|
||||
|
@ -1145,8 +1137,7 @@ class DataTable(object):
|
|||
|
||||
@staticmethod
|
||||
def parse_action(action_string):
|
||||
"""
|
||||
Parses the ``action`` parameter (a string) sent back with the
|
||||
"""Parses the ``action`` parameter (a string) sent back with the
|
||||
POST data. By default this parses a string formatted as
|
||||
``{{ table_name }}__{{ action_name }}__{{ row_id }}`` and returns
|
||||
each of the pieces. The ``row_id`` is optional.
|
||||
|
@ -1163,8 +1154,7 @@ class DataTable(object):
|
|||
return table, action, object_id
|
||||
|
||||
def take_action(self, action_name, obj_id=None, obj_ids=None):
|
||||
"""
|
||||
Locates the appropriate action and routes the object
|
||||
"""Locates the appropriate action and routes the object
|
||||
data to it. The action should return an HTTP redirect
|
||||
if successful, or a value which evaluates to ``False``
|
||||
if unsuccessful.
|
||||
|
@ -1212,9 +1202,8 @@ class DataTable(object):
|
|||
return table, action, obj_id
|
||||
|
||||
def maybe_preempt(self):
|
||||
"""
|
||||
Determine whether the request should be handled by a preemptive action
|
||||
on this table or by an AJAX row update before loading any data.
|
||||
"""Determine whether the request should be handled by a preemptive
|
||||
action on this table or by an AJAX row update before loading any data.
|
||||
"""
|
||||
request = self.request
|
||||
table_name, action_name, obj_id = self.check_handler(request)
|
||||
|
@ -1247,9 +1236,8 @@ class DataTable(object):
|
|||
return None
|
||||
|
||||
def maybe_handle(self):
|
||||
"""
|
||||
Determine whether the request should be handled by any action on this
|
||||
table after data has been loaded.
|
||||
"""Determine whether the request should be handled by any action on
|
||||
this table after data has been loaded.
|
||||
"""
|
||||
request = self.request
|
||||
table_name, action_name, obj_id = self.check_handler(request)
|
||||
|
@ -1291,8 +1279,7 @@ class DataTable(object):
|
|||
return None
|
||||
|
||||
def has_more_data(self):
|
||||
"""
|
||||
Returns a boolean value indicating whether there is more data
|
||||
"""Returns a boolean value indicating whether there is more data
|
||||
available to this table from the source (generally an API).
|
||||
|
||||
The method is largely meant for internal use, but if you want to
|
||||
|
@ -1301,8 +1288,7 @@ class DataTable(object):
|
|||
return self._meta.has_more_data
|
||||
|
||||
def get_marker(self):
|
||||
"""
|
||||
Returns the identifier for the last object in the current data set
|
||||
"""Returns the identifier for the last object in the current data set
|
||||
for APIs that use marker/limit-based paging.
|
||||
"""
|
||||
return http.urlquote_plus(self.get_object_id(self.data[-1]))
|
||||
|
@ -1312,8 +1298,7 @@ class DataTable(object):
|
|||
return "=".join([self._meta.pagination_param, self.get_marker()])
|
||||
|
||||
def calculate_row_status(self, statuses):
|
||||
"""
|
||||
Returns a boolean value determining the overall row status
|
||||
"""Returns a boolean value determining the overall row status
|
||||
based on the dictionary of column name to status mappings passed in.
|
||||
|
||||
By default, it uses the following logic:
|
||||
|
@ -1339,8 +1324,7 @@ class DataTable(object):
|
|||
return True
|
||||
|
||||
def get_row_status_class(self, status):
|
||||
"""
|
||||
Returns a css class name determined by the status value. This class
|
||||
"""Returns a css class name determined by the status value. This class
|
||||
name is used to indicate the status of the rows in the table if
|
||||
any ``status_columns`` have been specified.
|
||||
"""
|
||||
|
|
|
@ -123,8 +123,7 @@ class MultiTableMixin(object):
|
|||
|
||||
|
||||
class MultiTableView(MultiTableMixin, generic.TemplateView):
|
||||
"""
|
||||
A class-based generic view to handle the display and processing of
|
||||
"""A class-based generic view to handle the display and processing of
|
||||
multiple :class:`~horizon.tables.DataTable` classes in a single view.
|
||||
|
||||
Three steps are required to use this view: set the ``table_classes``
|
||||
|
|
|
@ -30,8 +30,7 @@ CSS_DISABLED_TAB_CLASSES = ["disabled"]
|
|||
|
||||
|
||||
class TabGroup(html.HTMLElement):
|
||||
"""
|
||||
A container class which knows how to manage and render
|
||||
"""A container class which knows how to manage and render
|
||||
:class:`~horizon.tabs.Tab` objects.
|
||||
|
||||
.. attribute:: slug
|
||||
|
@ -110,9 +109,7 @@ class TabGroup(html.HTMLElement):
|
|||
return "<%s: %s>" % (self.__class__.__name__, self.slug)
|
||||
|
||||
def load_tab_data(self):
|
||||
"""
|
||||
Preload all data that for the tabs that will be displayed.
|
||||
"""
|
||||
"""Preload all data that for the tabs that will be displayed."""
|
||||
for tab in self._tabs.values():
|
||||
if tab.load and not tab.data_loaded:
|
||||
try:
|
||||
|
@ -122,15 +119,13 @@ class TabGroup(html.HTMLElement):
|
|||
exceptions.handle(self.request)
|
||||
|
||||
def get_id(self):
|
||||
"""
|
||||
Returns the id for this tab group. Defaults to the value of the tab
|
||||
"""Returns the id for this tab group. Defaults to the value of the tab
|
||||
group's :attr:`horizon.tabs.Tab.slug`.
|
||||
"""
|
||||
return self.slug
|
||||
|
||||
def get_default_classes(self):
|
||||
"""
|
||||
Returns a list of the default classes for the tab group. Defaults to
|
||||
"""Returns a list of the default classes for the tab group. Defaults to
|
||||
``["nav", "nav-tabs", "ajax-tabs"]``.
|
||||
"""
|
||||
default_classes = super(TabGroup, self).get_default_classes()
|
||||
|
@ -138,8 +133,7 @@ class TabGroup(html.HTMLElement):
|
|||
return default_classes
|
||||
|
||||
def tabs_not_available(self):
|
||||
"""
|
||||
In the event that no tabs are either allowed or enabled, this method
|
||||
"""In the event that no tabs are either allowed or enabled, this method
|
||||
is the fallback handler. By default it's a no-op, but it exists
|
||||
to make redirecting or raising exceptions possible for subclasses.
|
||||
"""
|
||||
|
@ -208,8 +202,7 @@ class TabGroup(html.HTMLElement):
|
|||
|
||||
|
||||
class Tab(html.HTMLElement):
|
||||
"""
|
||||
A reusable interface for constructing a tab within a
|
||||
"""A reusable interface for constructing a tab within a
|
||||
:class:`~horizon.tabs.TabGroup`.
|
||||
|
||||
.. attribute:: name
|
||||
|
@ -286,8 +279,7 @@ class Tab(html.HTMLElement):
|
|||
return getattr(self, "_data", None) is not None
|
||||
|
||||
def render(self):
|
||||
"""
|
||||
Renders the tab to HTML using the
|
||||
"""Renders the tab to HTML using the
|
||||
:meth:`~horizon.tabs.Tab.get_context_data` method and
|
||||
the :meth:`~horizon.tabs.Tab.get_template_name` method.
|
||||
|
||||
|
@ -309,8 +301,7 @@ class Tab(html.HTMLElement):
|
|||
return render_to_string(self.get_template_name(self.request), context)
|
||||
|
||||
def get_id(self):
|
||||
"""
|
||||
Returns the id for this tab. Defaults to
|
||||
"""Returns the id for this tab. Defaults to
|
||||
``"{{ tab_group.slug }}__{{ tab.slug }}"``.
|
||||
"""
|
||||
return SEPARATOR.join([self.tab_group.slug, self.slug])
|
||||
|
@ -319,8 +310,7 @@ class Tab(html.HTMLElement):
|
|||
return "=".join((self.tab_group.param_name, self.get_id()))
|
||||
|
||||
def get_default_classes(self):
|
||||
"""
|
||||
Returns a list of the default classes for the tab. Defaults to
|
||||
"""Returns a list of the default classes for the tab. Defaults to
|
||||
and empty list (``[]``), however additional classes may be added
|
||||
depending on the state of the tab as follows:
|
||||
|
||||
|
@ -338,8 +328,7 @@ class Tab(html.HTMLElement):
|
|||
return default_classes
|
||||
|
||||
def get_template_name(self, request):
|
||||
"""
|
||||
Returns the name of the template to be used for rendering this tab.
|
||||
"""Returns the name of the template to be used for rendering this tab.
|
||||
|
||||
By default it returns the value of the ``template_name`` attribute
|
||||
on the ``Tab`` class.
|
||||
|
@ -351,16 +340,14 @@ class Tab(html.HTMLElement):
|
|||
return self.template_name
|
||||
|
||||
def get_context_data(self, request):
|
||||
"""
|
||||
This method should return a dictionary of context data used to render
|
||||
the tab. Required.
|
||||
"""This method should return a dictionary of context data used to
|
||||
render the tab. Required.
|
||||
"""
|
||||
raise NotImplementedError("%s needs to define a get_context_data "
|
||||
"method." % self.__class__.__name__)
|
||||
|
||||
def enabled(self, request):
|
||||
"""
|
||||
Determines whether or not the tab should be accessible
|
||||
"""Determines whether or not the tab should be accessible
|
||||
(e.g. be rendered into the HTML on load and respond to a click event).
|
||||
|
||||
If a tab returns ``False`` from ``enabled`` it will ignore the value
|
||||
|
@ -371,8 +358,7 @@ class Tab(html.HTMLElement):
|
|||
return True
|
||||
|
||||
def allowed(self, request):
|
||||
"""
|
||||
Determines whether or not the tab is displayed.
|
||||
"""Determines whether or not the tab is displayed.
|
||||
|
||||
Tab instances can override this method to specify conditions under
|
||||
which this tab should not be shown at all by returning ``False``.
|
||||
|
@ -382,8 +368,7 @@ class Tab(html.HTMLElement):
|
|||
return True
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
Handles POST data sent to a tab.
|
||||
"""Handles POST data sent to a tab.
|
||||
|
||||
Tab instances can override this method to have tab-specific POST logic
|
||||
without polluting the TabView code.
|
||||
|
@ -394,8 +379,7 @@ class Tab(html.HTMLElement):
|
|||
|
||||
|
||||
class TableTab(Tab):
|
||||
"""
|
||||
A :class:`~horizon.tabs.Tab` class which knows how to deal with
|
||||
"""A :class:`~horizon.tabs.Tab` class which knows how to deal with
|
||||
:class:`~horizon.tables.DataTable` classes rendered inside of it.
|
||||
|
||||
This distinct class is required due to the complexity involved in handling
|
||||
|
@ -427,8 +411,7 @@ class TableTab(Tab):
|
|||
self._table_data_loaded = False
|
||||
|
||||
def load_table_data(self):
|
||||
"""
|
||||
Calls the ``get_{{ table_name }}_data`` methods for each table class
|
||||
"""Calls the ``get_{{ table_name }}_data`` methods for each table class
|
||||
and sets the data on the tables.
|
||||
"""
|
||||
# We only want the data to be loaded once, so we track if we have...
|
||||
|
@ -448,8 +431,7 @@ class TableTab(Tab):
|
|||
self._table_data_loaded = True
|
||||
|
||||
def get_context_data(self, request):
|
||||
"""
|
||||
Adds a ``{{ table_name }}_table`` item to the context for each table
|
||||
"""Adds a ``{{ table_name }}_table`` item to the context for each table
|
||||
in the :attr:`~horizon.tabs.TableTab.table_classes` attribute.
|
||||
|
||||
If only one table class is provided, a shortcut ``table`` context
|
||||
|
|
|
@ -19,8 +19,8 @@ from horizon.tabs.base import TableTab # noqa
|
|||
|
||||
|
||||
class TabView(generic.TemplateView):
|
||||
"""
|
||||
A generic class-based view for displaying a :class:`horizon.tabs.TabGroup`.
|
||||
"""A generic class-based view for displaying a
|
||||
:class:`horizon.tabs.TabGroup`.
|
||||
|
||||
This view handles selecting specific tabs and deals with AJAX requests
|
||||
gracefully.
|
||||
|
@ -57,8 +57,7 @@ class TabView(generic.TemplateView):
|
|||
return context
|
||||
|
||||
def handle_tabbed_response(self, tab_group, context):
|
||||
"""
|
||||
Sends back an AJAX-appropriate response for the tab group if
|
||||
"""Sends back an AJAX-appropriate response for the tab group if
|
||||
required, otherwise renders the response as normal.
|
||||
"""
|
||||
if self.request.is_ajax():
|
||||
|
@ -90,8 +89,7 @@ class TabbedTableView(tables.MultiTableMixin, TabView):
|
|||
self._table_dict = {}
|
||||
|
||||
def load_tabs(self):
|
||||
"""
|
||||
Loads the tab group, and compiles the table instances for each
|
||||
"""Loads the tab group, and compiles the table instances for each
|
||||
table attached to any :class:`horizon.tabs.TableTab` instances on
|
||||
the tab group. This step is necessary before processing any
|
||||
tab or table actions.
|
||||
|
@ -111,8 +109,7 @@ class TabbedTableView(tables.MultiTableMixin, TabView):
|
|||
return {}
|
||||
|
||||
def handle_table(self, table_dict):
|
||||
"""
|
||||
For the given dict containing a ``DataTable`` and a ``TableTab``
|
||||
"""For the given dict containing a ``DataTable`` and a ``TableTab``
|
||||
instance, it loads the table data for that tab and calls the
|
||||
table's :meth:`~horizon.tables.DataTable.maybe_handle` method. The
|
||||
return value will be the result of ``maybe_handle``.
|
||||
|
|
|
@ -30,8 +30,7 @@ register = template.Library()
|
|||
|
||||
@register.filter
|
||||
def has_permissions(user, component):
|
||||
"""
|
||||
Checks if the given user meets the permissions requirements for
|
||||
"""Checks if the given user meets the permissions requirements for
|
||||
the component.
|
||||
"""
|
||||
return user.has_perms(getattr(component, 'permissions', set()))
|
||||
|
@ -111,8 +110,7 @@ class JSTemplateNode(template.Node):
|
|||
|
||||
@register.tag
|
||||
def jstemplate(parser, token):
|
||||
"""
|
||||
Replaces ``[[[`` and ``]]]`` with ``{{{`` and ``}}}``,
|
||||
"""Replaces ``[[[`` and ``]]]`` with ``{{{`` and ``}}}``,
|
||||
``[[`` and ``]]`` with ``{{`` and ``}}`` and
|
||||
``[%`` and ``%]`` with ``{%`` and ``%}`` to avoid conflicts
|
||||
with Django's template engine when using any of the Mustache-based
|
||||
|
|
|
@ -32,8 +32,8 @@ register = template.Library()
|
|||
|
||||
class ParseDateNode(template.Node):
|
||||
def render(self, datestring):
|
||||
"""
|
||||
Parses a date-like input string into a timezone aware Python datetime.
|
||||
"""Parses a date-like input string into a timezone aware Python
|
||||
datetime.
|
||||
"""
|
||||
formats = ["%Y-%m-%dT%H:%M:%S.%f", "%Y-%m-%d %H:%M:%S.%f",
|
||||
"%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S"]
|
||||
|
|
|
@ -74,7 +74,8 @@ def mbformat(mb):
|
|||
@register.filter(name='mb_float_format')
|
||||
def mb_float_format(mb):
|
||||
"""Takes a size value in mb, and prints returns the data in a
|
||||
saner unit. """
|
||||
saner unit.
|
||||
"""
|
||||
if not mb:
|
||||
return 0
|
||||
return filesizeformat(mb * 1024 * 1024, float_format)
|
||||
|
|
|
@ -75,8 +75,7 @@ class RequestFactoryWithMessages(RequestFactory):
|
|||
@unittest.skipIf(os.environ.get('SKIP_UNITTESTS', False),
|
||||
"The SKIP_UNITTESTS env variable is set.")
|
||||
class TestCase(django_test.TestCase):
|
||||
"""
|
||||
Specialized base test case class for Horizon which gives access to
|
||||
"""Specialized base test case class for Horizon which gives access to
|
||||
numerous additional features:
|
||||
|
||||
* The ``mox`` mocking framework via ``self.mox``.
|
||||
|
@ -115,15 +114,13 @@ class TestCase(django_test.TestCase):
|
|||
del self.user._perm_cache
|
||||
|
||||
def assertNoMessages(self, response=None):
|
||||
"""
|
||||
Asserts that no messages have been attached by the ``contrib.messages``
|
||||
framework.
|
||||
"""Asserts that no messages have been attached by the
|
||||
``contrib.messages`` framework.
|
||||
"""
|
||||
self.assertMessageCount(response, success=0, warn=0, info=0, error=0)
|
||||
|
||||
def assertMessageCount(self, response=None, **kwargs):
|
||||
"""
|
||||
Asserts that the specified number of messages have been attached
|
||||
"""Asserts that the specified number of messages have been attached
|
||||
for various message types. Usage would look like
|
||||
``self.assertMessageCount(success=1)``.
|
||||
"""
|
||||
|
|
|
@ -102,12 +102,11 @@ class BaseHorizonTests(test.TestCase):
|
|||
dash.register(panel)
|
||||
|
||||
def _reload_urls(self):
|
||||
'''
|
||||
Clears out the URL caches, reloads the root urls module, and
|
||||
"""Clears out the URL caches, reloads the root urls module, and
|
||||
re-triggers the autodiscovery mechanism for Horizon. Allows URLs
|
||||
to be re-calculated after registering new dashboards. Useful
|
||||
only for testing and should never be used on a live site.
|
||||
'''
|
||||
"""
|
||||
urlresolvers.clear_url_caches()
|
||||
reload(import_module(settings.ROOT_URLCONF))
|
||||
base.Horizon._urls()
|
||||
|
|
|
@ -29,22 +29,22 @@ from horizon.test import helpers as test
|
|||
|
||||
|
||||
def single_line(text):
|
||||
''' Quick utility to make comparing template output easier. '''
|
||||
"""Quick utility to make comparing template output easier."""
|
||||
return re.sub(' +',
|
||||
' ',
|
||||
normalize_newlines(text).replace('\n', '')).strip()
|
||||
|
||||
|
||||
class TemplateTagTests(test.TestCase):
|
||||
'''Test Custom Template Tag'''
|
||||
"""Test Custom Template Tag."""
|
||||
def render_template_tag(self, tag_name, tag_require=''):
|
||||
'''Render a Custom Template Tag to string'''
|
||||
"""Render a Custom Template Tag to string."""
|
||||
template = Template("{%% load %s %%}{%% %s %%}"
|
||||
% (tag_require, tag_name))
|
||||
return template.render(Context())
|
||||
|
||||
def test_site_branding_tag(self):
|
||||
'''Test if site_branding tag renders the correct setting'''
|
||||
"""Test if site_branding tag renders the correct setting."""
|
||||
rendered_str = self.render_template_tag("site_branding", "branding")
|
||||
self.assertEqual(settings.SITE_BRANDING, rendered_str.strip(),
|
||||
"tag site_branding renders %s" % rendered_str.strip())
|
||||
|
|
|
@ -27,8 +27,7 @@ IPv6 = 2
|
|||
|
||||
|
||||
class IPField(forms.Field):
|
||||
"""
|
||||
Form field for entering IP/range values, with validation.
|
||||
"""Form field for entering IP/range values, with validation.
|
||||
Supports IPv4/IPv6 in the format:
|
||||
.. xxx.xxx.xxx.xxx
|
||||
.. xxx.xxx.xxx.xxx/zz
|
||||
|
@ -102,9 +101,7 @@ class IPField(forms.Field):
|
|||
|
||||
|
||||
class MultiIPField(IPField):
|
||||
"""
|
||||
Extends IPField to allow comma-separated lists of addresses
|
||||
"""
|
||||
"""Extends IPField to allow comma-separated lists of addresses."""
|
||||
def validate(self, value):
|
||||
self.addresses = []
|
||||
if value:
|
||||
|
@ -121,8 +118,7 @@ class MultiIPField(IPField):
|
|||
|
||||
|
||||
class SelectWidget(widgets.Select):
|
||||
"""
|
||||
Customizable select widget, that allows to render
|
||||
"""Customizable select widget, that allows to render
|
||||
data-xxx attributes from choices.
|
||||
|
||||
.. attribute:: data_attrs
|
||||
|
|
|
@ -29,8 +29,7 @@ def replace_underscores(string):
|
|||
|
||||
@register.filter
|
||||
def parse_isotime(timestr):
|
||||
"""
|
||||
This duplicates oslo timeutils parse_isotime but with a
|
||||
"""This duplicates oslo timeutils parse_isotime but with a
|
||||
@register.filter annotation.
|
||||
"""
|
||||
try:
|
||||
|
|
|
@ -22,22 +22,19 @@ class HTMLElement(object):
|
|||
self.classes = getattr(self, "classes", [])
|
||||
|
||||
def get_default_classes(self):
|
||||
"""
|
||||
Returns an iterable of default classes which should be combined with
|
||||
"""Returns an iterable of default classes which should be combined with
|
||||
any other declared classes.
|
||||
"""
|
||||
return []
|
||||
|
||||
def get_default_attrs(self):
|
||||
"""
|
||||
Returns a dict of default attributes which should be combined with
|
||||
"""Returns a dict of default attributes which should be combined with
|
||||
other declared attributes.
|
||||
"""
|
||||
return {}
|
||||
|
||||
def get_final_attrs(self):
|
||||
"""
|
||||
Returns a dict containing the final attributes of this element
|
||||
"""Returns a dict containing the final attributes of this element
|
||||
which will be rendered.
|
||||
"""
|
||||
final_attrs = copy.copy(self.get_default_attrs())
|
||||
|
@ -53,16 +50,13 @@ class HTMLElement(object):
|
|||
|
||||
@property
|
||||
def attr_string(self):
|
||||
"""
|
||||
Returns a flattened string of HTML attributes based on the
|
||||
"""Returns a flattened string of HTML attributes based on the
|
||||
``attrs`` dict provided to the class.
|
||||
"""
|
||||
return flatatt(self.get_final_attrs())
|
||||
|
||||
@property
|
||||
def class_string(self):
|
||||
"""
|
||||
Returns a list of class name of HTML Element in string
|
||||
"""
|
||||
"""Returns a list of class name of HTML Element in string."""
|
||||
classes_str = " ".join(self.classes)
|
||||
return classes_str
|
||||
|
|
|
@ -39,7 +39,7 @@ def password_validator_msg():
|
|||
|
||||
|
||||
def validate_port_or_colon_separated_port_range(port_range):
|
||||
"""accepts a port number or a single-colon separated range"""
|
||||
"""Accepts a port number or a single-colon separated range."""
|
||||
if port_range.count(':') > 1:
|
||||
raise ValidationError(_("One colon allowed in port range"))
|
||||
ports = port_range.split(':')
|
||||
|
|
|
@ -37,8 +37,7 @@ class APIView(generic.TemplateView):
|
|||
caught.
|
||||
"""
|
||||
def get_data(self, request, context, *args, **kwargs):
|
||||
"""
|
||||
This method should handle any necessary API calls, update the
|
||||
"""This method should handle any necessary API calls, update the
|
||||
context object, and return the context object at the end.
|
||||
"""
|
||||
raise NotImplementedError("You must define a get_data method "
|
||||
|
|
|
@ -76,8 +76,7 @@ class ActionMetaclass(forms.forms.DeclarativeFieldsMetaclass):
|
|||
|
||||
|
||||
class Action(forms.Form):
|
||||
"""
|
||||
An ``Action`` represents an atomic logical interaction you can have with
|
||||
"""An ``Action`` represents an atomic logical interaction you can have with
|
||||
the system. This is easier to understand with a conceptual example: in the
|
||||
context of a "launch instance" workflow, actions would include "naming
|
||||
the instance", "selecting an image", and ultimately "launching the
|
||||
|
@ -166,14 +165,11 @@ class Action(forms.Form):
|
|||
return safe(text)
|
||||
|
||||
def add_error(self, message):
|
||||
"""
|
||||
Adds an error to the Action's Step based on API issues.
|
||||
"""
|
||||
"""Adds an error to the Action's Step based on API issues."""
|
||||
self._get_errors()[NON_FIELD_ERRORS] = self.error_class([message])
|
||||
|
||||
def handle(self, request, context):
|
||||
"""
|
||||
Handles any requisite processing for this action. The method should
|
||||
"""Handles any requisite processing for this action. The method should
|
||||
return either ``None`` or a dictionary of data to be passed to
|
||||
:meth:`~horizon.workflows.Step.contribute`.
|
||||
|
||||
|
@ -183,8 +179,7 @@ class Action(forms.Form):
|
|||
|
||||
|
||||
class MembershipAction(Action):
|
||||
"""
|
||||
An action that allows a user to add/remove members from a group.
|
||||
"""An action that allows a user to add/remove members from a group.
|
||||
|
||||
Extend the Action class with additional helper method for membership
|
||||
management.
|
||||
|
@ -197,8 +192,7 @@ class MembershipAction(Action):
|
|||
|
||||
|
||||
class Step(object):
|
||||
"""
|
||||
A step is a wrapper around an action which defines its context in a
|
||||
"""A step is a wrapper around an action which defines its context in a
|
||||
workflow. It knows about details such as:
|
||||
|
||||
* The workflow's context data (data passed from step to step).
|
||||
|
@ -380,9 +374,8 @@ class Step(object):
|
|||
return self._action
|
||||
|
||||
def prepare_action_context(self, request, context):
|
||||
"""
|
||||
Allows for customization of how the workflow context is passed to the
|
||||
action; this is the reverse of what "contribute" does to make the
|
||||
"""Allows for customization of how the workflow context is passed to
|
||||
the action; this is the reverse of what "contribute" does to make the
|
||||
action outputs sane for the workflow. Changes to the context are not
|
||||
saved globally here. They are localized to the action.
|
||||
|
||||
|
@ -412,8 +405,7 @@ class Step(object):
|
|||
return True
|
||||
|
||||
def contribute(self, data, context):
|
||||
"""
|
||||
Adds the data listed in ``contributes`` to the workflow's shared
|
||||
"""Adds the data listed in ``contributes`` to the workflow's shared
|
||||
context. By default, the context is simply updated with all the data
|
||||
returned by the action.
|
||||
|
||||
|
@ -441,15 +433,11 @@ class Step(object):
|
|||
return safe(text)
|
||||
|
||||
def add_error(self, message):
|
||||
"""
|
||||
Adds an error to the Step based on API issues.
|
||||
"""
|
||||
"""Adds an error to the Step based on API issues."""
|
||||
self.action.add_error(message)
|
||||
|
||||
def has_required_fields(self):
|
||||
"""
|
||||
Returns True if action contains any required fields
|
||||
"""
|
||||
"""Returns True if action contains any required fields."""
|
||||
for key in self.contributes:
|
||||
field = self.action.fields.get(key, None)
|
||||
if (field and field.required):
|
||||
|
@ -503,8 +491,7 @@ class UpdateMembersStep(Step):
|
|||
|
||||
|
||||
class Workflow(html.HTMLElement):
|
||||
"""
|
||||
A Workflow is a collection of Steps. Its interface is very
|
||||
"""A Workflow is a collection of Steps. Its interface is very
|
||||
straightforward, but it is responsible for handling some very
|
||||
important tasks such as:
|
||||
|
||||
|
@ -705,8 +692,7 @@ class Workflow(html.HTMLElement):
|
|||
return steps
|
||||
|
||||
def get_entry_point(self):
|
||||
"""
|
||||
Returns the slug of the step which the workflow should begin on.
|
||||
"""Returns the slug of the step which the workflow should begin on.
|
||||
|
||||
This method takes into account both already-available data and errors
|
||||
within the steps.
|
||||
|
@ -750,8 +736,7 @@ class Workflow(html.HTMLElement):
|
|||
|
||||
@classmethod
|
||||
def unregister(cls, step_class):
|
||||
"""
|
||||
Unregisters a :class:`~horizon.workflows.Step` from the workflow.
|
||||
"""Unregisters a :class:`~horizon.workflows.Step` from the workflow.
|
||||
"""
|
||||
try:
|
||||
cls._cls_registry.remove(step_class)
|
||||
|
@ -760,15 +745,13 @@ class Workflow(html.HTMLElement):
|
|||
return cls._unregister(step_class)
|
||||
|
||||
def validate(self, context):
|
||||
"""
|
||||
Hook for custom context data validation. Should return a boolean
|
||||
"""Hook for custom context data validation. Should return a boolean
|
||||
value or raise :class:`~horizon.exceptions.WorkflowValidationError`.
|
||||
"""
|
||||
return True
|
||||
|
||||
def is_valid(self):
|
||||
"""
|
||||
Verified that all required data is present in the context and
|
||||
"""Verified that all required data is present in the context and
|
||||
calls the ``validate`` method to allow for finer-grained checks
|
||||
on the context data.
|
||||
"""
|
||||
|
@ -790,8 +773,7 @@ class Workflow(html.HTMLElement):
|
|||
return self.validate(self.context)
|
||||
|
||||
def finalize(self):
|
||||
"""
|
||||
Finalizes a workflow by running through all the actions in order
|
||||
"""Finalizes a workflow by running through all the actions in order
|
||||
and calling their ``handle`` methods. Returns ``True`` on full success,
|
||||
or ``False`` for a partial success, e.g. there were non-critical
|
||||
errors. (If it failed completely the function wouldn't return.)
|
||||
|
@ -814,15 +796,13 @@ class Workflow(html.HTMLElement):
|
|||
return not partial
|
||||
|
||||
def handle(self, request, context):
|
||||
"""
|
||||
Handles any final processing for this workflow. Should return a boolean
|
||||
value indicating success.
|
||||
"""Handles any final processing for this workflow. Should return a
|
||||
boolean value indicating success.
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_success_url(self):
|
||||
"""
|
||||
Returns a URL to redirect the user to upon completion. By default it
|
||||
"""Returns a URL to redirect the user to upon completion. By default it
|
||||
will attempt to parse a ``success_url`` attribute on the workflow,
|
||||
which can take the form of a reversible URL pattern name, or a
|
||||
standard HTTP URL.
|
||||
|
@ -833,8 +813,7 @@ class Workflow(html.HTMLElement):
|
|||
return self.success_url
|
||||
|
||||
def format_status_message(self, message):
|
||||
"""
|
||||
Hook to allow customization of the message returned to the user
|
||||
"""Hook to allow customization of the message returned to the user
|
||||
upon successful or unsuccessful completion of the workflow.
|
||||
|
||||
By default it simply inserts the workflow's name into the message
|
||||
|
@ -867,8 +846,7 @@ class Workflow(html.HTMLElement):
|
|||
return self.request.get_full_path().partition('?')[0]
|
||||
|
||||
def add_error_to_step(self, message, slug):
|
||||
"""
|
||||
Adds an error to the workflow's Step with the
|
||||
"""Adds an error to the workflow's Step with the
|
||||
specifed slug based on API issues. This is useful
|
||||
when you wish for API errors to appear as errors on
|
||||
the form rather than using the messages framework.
|
||||
|
|
|
@ -27,8 +27,7 @@ from horizon import messages
|
|||
|
||||
|
||||
class WorkflowView(generic.TemplateView):
|
||||
"""
|
||||
A generic class-based view which handles the intricacies of workflow
|
||||
"""A generic class-based view which handles the intricacies of workflow
|
||||
processing with minimal user configuration.
|
||||
|
||||
.. attribute:: workflow_class
|
||||
|
@ -65,8 +64,7 @@ class WorkflowView(generic.TemplateView):
|
|||
"on %s." % self.__class__.__name__)
|
||||
|
||||
def get_initial(self):
|
||||
"""
|
||||
Returns initial data for the workflow. Defaults to using the GET
|
||||
"""Returns initial data for the workflow. Defaults to using the GET
|
||||
parameters to allow pre-seeding of the workflow context values.
|
||||
"""
|
||||
return copy.copy(self.request.GET)
|
||||
|
@ -81,8 +79,7 @@ class WorkflowView(generic.TemplateView):
|
|||
return workflow
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""
|
||||
Returns the template context, including the workflow class.
|
||||
"""Returns the template context, including the workflow class.
|
||||
|
||||
This method should be overridden in subclasses to provide additional
|
||||
context data to the template.
|
||||
|
|
|
@ -67,7 +67,7 @@ class APIVersionManager(object):
|
|||
|
||||
|
||||
class APIResourceWrapper(object):
|
||||
""" Simple wrapper for api objects
|
||||
"""Simple wrapper for api objects.
|
||||
|
||||
Define _attrs on the child class and pass in the
|
||||
api object as the only argument to the constructor
|
||||
|
@ -146,8 +146,7 @@ class Quota(object):
|
|||
|
||||
|
||||
class QuotaSet(Sequence):
|
||||
"""
|
||||
Wrapper for client QuotaSet objects which turns the individual quotas
|
||||
"""Wrapper for client QuotaSet objects which turns the individual quotas
|
||||
into Quota objects for easier handling/iteration.
|
||||
|
||||
`QuotaSet` objects support a mix of `list` and `dict` methods; you can use
|
||||
|
@ -177,8 +176,9 @@ class QuotaSet(Sequence):
|
|||
return self.items[index]
|
||||
|
||||
def __add__(self, other):
|
||||
'''Merge another QuotaSet into this one. Existing quotas are
|
||||
not overriden.'''
|
||||
"""Merge another QuotaSet into this one. Existing quotas are
|
||||
not overriden.
|
||||
"""
|
||||
if not isinstance(other, QuotaSet):
|
||||
msg = "Can only add QuotaSet to QuotaSet, " \
|
||||
"but received %s instead" % type(other)
|
||||
|
|
|
@ -25,8 +25,7 @@ LOG = logging.getLogger(__name__)
|
|||
|
||||
|
||||
def is_iterable(var):
|
||||
""" Return True if the given is list or tuple.
|
||||
"""
|
||||
"""Return True if the given is list or tuple."""
|
||||
|
||||
return (isinstance(var, (list, tuple)) or
|
||||
issubclass(var.__class__, (list, tuple)))
|
||||
|
@ -71,15 +70,13 @@ def make_query(user_id=None, tenant_id=None, resource_id=None,
|
|||
|
||||
|
||||
class Meter(base.APIResourceWrapper):
|
||||
""" Represents one Ceilometer meter.
|
||||
"""
|
||||
"""Represents one Ceilometer meter."""
|
||||
_attrs = ['name', 'type', 'unit', 'resource_id', 'user_id',
|
||||
'project_id']
|
||||
|
||||
|
||||
class Resource(base.APIResourceWrapper):
|
||||
""" Represents one Ceilometer resource.
|
||||
"""
|
||||
"""Represents one Ceilometer resource."""
|
||||
_attrs = ['resource_id', 'source', 'user_id', 'project_id', 'metadata',
|
||||
'links']
|
||||
|
||||
|
@ -194,8 +191,7 @@ class ResourceAggregate(Resource):
|
|||
|
||||
|
||||
class Sample(base.APIResourceWrapper):
|
||||
""" Represents one Ceilometer sample.
|
||||
"""
|
||||
"""Represents one Ceilometer sample."""
|
||||
|
||||
_attrs = ['counter_name', 'user_id', 'resource_id', 'timestamp',
|
||||
'resource_metadata', 'source', 'counter_unit', 'counter_volume',
|
||||
|
@ -215,8 +211,7 @@ class Sample(base.APIResourceWrapper):
|
|||
|
||||
|
||||
class Statistic(base.APIResourceWrapper):
|
||||
""" Represents one Ceilometer statistic.
|
||||
"""
|
||||
"""Represents one Ceilometer statistic."""
|
||||
|
||||
_attrs = ['period', 'period_start', 'period_end',
|
||||
'count', 'min', 'max', 'sum', 'avg',
|
||||
|
@ -317,8 +312,7 @@ class GlobalObjectStoreUsage(base.APIResourceWrapper):
|
|||
|
||||
|
||||
def ceilometerclient(request):
|
||||
""" Initialization of Ceilometer client.
|
||||
"""
|
||||
"""Initialization of Ceilometer client."""
|
||||
|
||||
endpoint = base.url_for(request, 'metering')
|
||||
insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
|
||||
|
@ -475,7 +469,7 @@ class CeilometerUsage(object):
|
|||
self._users[u.id] = u
|
||||
|
||||
def get_tenant(self, tenant_id):
|
||||
""" Returns tenant fetched form API
|
||||
"""Returns tenant fetched form API.
|
||||
|
||||
Caching the result, so it doesn't contact API twice with the
|
||||
same query
|
||||
|
@ -536,8 +530,7 @@ class CeilometerUsage(object):
|
|||
def filter_resources(resource):
|
||||
"""Method for filtering resources by theirs links.rel attr.
|
||||
|
||||
The links.rel attributes contains all meters the resource
|
||||
have.
|
||||
The links.rel attributes contains all meters the resource have.
|
||||
"""
|
||||
for link in resource.links:
|
||||
if link['rel'] in used_cls.meters:
|
||||
|
@ -567,8 +560,7 @@ class CeilometerUsage(object):
|
|||
|
||||
def global_disk_usage(self, query=None, with_statistics=False,
|
||||
additional_query=None):
|
||||
""" Wrapper for specific call of global_data_get.
|
||||
"""
|
||||
"""Wrapper for specific call of global_data_get."""
|
||||
|
||||
return self.global_data_get(used_cls=GlobalDiskUsage,
|
||||
query=query,
|
||||
|
|
|
@ -68,8 +68,7 @@ def cinderclient(request):
|
|||
|
||||
|
||||
def volume_list(request, search_opts=None):
|
||||
"""
|
||||
To see all volumes in the cloud as an admin you can pass in a special
|
||||
"""To see all volumes in the cloud as an admin you can pass in a special
|
||||
search option: {'all_tenants': 1}
|
||||
"""
|
||||
c_client = cinderclient(request)
|
||||
|
@ -181,8 +180,7 @@ def list_extensions(request):
|
|||
|
||||
@memoized
|
||||
def extension_supported(request, extension_name):
|
||||
"""
|
||||
This method will determine if Cinder supports a given extension name.
|
||||
"""This method will determine if Cinder supports a given extension name.
|
||||
"""
|
||||
extensions = list_extensions(request)
|
||||
for extension in extensions:
|
||||
|
|
|
@ -24,7 +24,7 @@ neutronclient = neutron.neutronclient
|
|||
|
||||
|
||||
class Rule(neutron.NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron firewall rule"""
|
||||
"""Wrapper for neutron firewall rule."""
|
||||
|
||||
def get_dict(self):
|
||||
rule_dict = self._apidict
|
||||
|
@ -33,7 +33,7 @@ class Rule(neutron.NeutronAPIDictWrapper):
|
|||
|
||||
|
||||
class Policy(neutron.NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron firewall policy"""
|
||||
"""Wrapper for neutron firewall policy."""
|
||||
|
||||
def get_dict(self):
|
||||
policy_dict = self._apidict
|
||||
|
@ -42,7 +42,7 @@ class Policy(neutron.NeutronAPIDictWrapper):
|
|||
|
||||
|
||||
class Firewall(neutron.NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron firewall"""
|
||||
"""Wrapper for neutron firewall."""
|
||||
|
||||
def get_dict(self):
|
||||
firewall_dict = self._apidict
|
||||
|
|
|
@ -51,8 +51,7 @@ def image_delete(request, image_id):
|
|||
|
||||
|
||||
def image_get(request, image_id):
|
||||
"""
|
||||
Returns an Image object populated with metadata for image
|
||||
"""Returns an Image object populated with metadata for image
|
||||
with supplied identifier.
|
||||
"""
|
||||
return glanceclient(request).images.get(image_id)
|
||||
|
|
|
@ -216,8 +216,7 @@ def tenant_create(request, name, description=None, enabled=None, domain=None):
|
|||
|
||||
|
||||
def get_default_domain(request):
|
||||
"""
|
||||
Gets the default domain object to use when creating Identity object.
|
||||
"""Gets the default domain object to use when creating Identity object.
|
||||
Returns the domain context if is set, otherwise return the domain
|
||||
of the logon user.
|
||||
"""
|
||||
|
@ -556,8 +555,7 @@ def remove_group_roles(request, group, domain=None, project=None):
|
|||
|
||||
|
||||
def get_default_role(request):
|
||||
"""
|
||||
Gets the default role object from Keystone and saves it as a global
|
||||
"""Gets the default role object from Keystone and saves it as a global
|
||||
since this is configured in settings and should not change from request
|
||||
to request. Supports lookup by name or id.
|
||||
"""
|
||||
|
|
|
@ -22,14 +22,14 @@ neutronclient = neutron.neutronclient
|
|||
|
||||
|
||||
class Vip(neutron.NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron load balancer vip"""
|
||||
"""Wrapper for neutron load balancer vip."""
|
||||
|
||||
def __init__(self, apiresource):
|
||||
super(Vip, self).__init__(apiresource)
|
||||
|
||||
|
||||
class Pool(neutron.NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron load balancer pool"""
|
||||
"""Wrapper for neutron load balancer pool."""
|
||||
|
||||
def __init__(self, apiresource):
|
||||
if 'provider' not in apiresource:
|
||||
|
@ -75,7 +75,7 @@ class Pool(neutron.NeutronAPIDictWrapper):
|
|||
|
||||
|
||||
class Member(neutron.NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron load balancer member"""
|
||||
"""Wrapper for neutron load balancer member."""
|
||||
|
||||
def __init__(self, apiresource):
|
||||
super(Member, self).__init__(apiresource)
|
||||
|
@ -104,14 +104,14 @@ class Member(neutron.NeutronAPIDictWrapper):
|
|||
|
||||
|
||||
class PoolStats(neutron.NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron load balancer pool stats"""
|
||||
"""Wrapper for neutron load balancer pool stats."""
|
||||
|
||||
def __init__(self, apiresource):
|
||||
super(PoolStats, self).__init__(apiresource)
|
||||
|
||||
|
||||
class PoolMonitor(neutron.NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron load balancer pool health monitor"""
|
||||
"""Wrapper for neutron load balancer pool health monitor."""
|
||||
|
||||
def __init__(self, apiresource):
|
||||
super(PoolMonitor, self).__init__(apiresource)
|
||||
|
|
|
@ -62,7 +62,7 @@ class NeutronAPIDictWrapper(base.APIDictWrapper):
|
|||
|
||||
|
||||
class Agent(NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron agents"""
|
||||
"""Wrapper for neutron agents."""
|
||||
|
||||
def __init__(self, apiresource):
|
||||
apiresource['admin_state'] = \
|
||||
|
@ -71,7 +71,7 @@ class Agent(NeutronAPIDictWrapper):
|
|||
|
||||
|
||||
class Network(NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron Networks"""
|
||||
"""Wrapper for neutron Networks."""
|
||||
|
||||
def __init__(self, apiresource):
|
||||
apiresource['admin_state'] = \
|
||||
|
@ -84,7 +84,7 @@ class Network(NeutronAPIDictWrapper):
|
|||
|
||||
|
||||
class Subnet(NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron subnets"""
|
||||
"""Wrapper for neutron subnets."""
|
||||
|
||||
def __init__(self, apiresource):
|
||||
apiresource['ipver_str'] = get_ipver_str(apiresource['ip_version'])
|
||||
|
@ -92,7 +92,7 @@ class Subnet(NeutronAPIDictWrapper):
|
|||
|
||||
|
||||
class Port(NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron ports"""
|
||||
"""Wrapper for neutron ports."""
|
||||
|
||||
def __init__(self, apiresource):
|
||||
apiresource['admin_state'] = \
|
||||
|
@ -110,7 +110,7 @@ class Profile(NeutronAPIDictWrapper):
|
|||
|
||||
|
||||
class Router(NeutronAPIDictWrapper):
|
||||
"""Wrapper for neutron routers"""
|
||||
"""Wrapper for neutron routers."""
|
||||
|
||||
def __init__(self, apiresource):
|
||||
#apiresource['admin_state'] = \
|
||||
|
@ -412,7 +412,7 @@ class FloatingIpManager(network_base.FloatingIpManager):
|
|||
|
||||
|
||||
def get_ipver_str(ip_version):
|
||||
"""Convert an ip version number to a human-friendly string"""
|
||||
"""Convert an ip version number to a human-friendly string."""
|
||||
return IP_VERSION_DICT.get(ip_version, '')
|
||||
|
||||
|
||||
|
@ -476,8 +476,7 @@ def network_get(request, network_id, expand_subnet=True, **params):
|
|||
|
||||
|
||||
def network_create(request, **kwargs):
|
||||
"""
|
||||
Create a subnet on a specified network.
|
||||
"""Create a subnet on a specified network.
|
||||
:param request: request context
|
||||
:param tenant_id: (optional) tenant id of the network created
|
||||
:param name: (optional) name of the network created
|
||||
|
@ -519,8 +518,7 @@ def subnet_get(request, subnet_id, **params):
|
|||
|
||||
|
||||
def subnet_create(request, network_id, cidr, ip_version, **kwargs):
|
||||
"""
|
||||
Create a subnet on a specified network.
|
||||
"""Create a subnet on a specified network.
|
||||
:param request: request context
|
||||
:param network_id: network id a subnet is created on
|
||||
:param cidr: subnet IP address range
|
||||
|
@ -567,8 +565,7 @@ def port_get(request, port_id, **params):
|
|||
|
||||
|
||||
def port_create(request, network_id, **kwargs):
|
||||
"""
|
||||
Create a port on a specified network.
|
||||
"""Create a port on a specified network.
|
||||
:param request: request context
|
||||
:param network_id: network id a subnet is created on
|
||||
:param device_id: (optional) device id attached to the port
|
||||
|
|
|
@ -686,8 +686,7 @@ def list_extensions(request):
|
|||
|
||||
@memoized
|
||||
def extension_supported(extension_name, request):
|
||||
"""
|
||||
this method will determine if nova supports a given extension name.
|
||||
"""this method will determine if nova supports a given extension name.
|
||||
example values for the extension_name include AdminActions, ConsoleOutput,
|
||||
etc.
|
||||
"""
|
||||
|
|
|
@ -30,7 +30,7 @@ except ImportError:
|
|||
|
||||
|
||||
class TokenAuth(object):
|
||||
"""Simple Token Authentication handler for trove api"""
|
||||
"""Simple Token Authentication handler for trove api."""
|
||||
|
||||
def __init__(self, client, auth_strategy, auth_url, username, password,
|
||||
tenant, region, service_type, service_name, service_url):
|
||||
|
|
|
@ -98,7 +98,7 @@ class DomainFilterAction(tables.FilterAction):
|
|||
return multidomain_support
|
||||
|
||||
def filter(self, table, domains, filter_string):
|
||||
""" Naive case-insensitive search """
|
||||
"""Naive case-insensitive search."""
|
||||
q = filter_string.lower()
|
||||
|
||||
def comp(domain):
|
||||
|
|
|
@ -85,7 +85,7 @@ class ManageUsersLink(tables.LinkAction):
|
|||
|
||||
class GroupFilterAction(tables.FilterAction):
|
||||
def filter(self, table, groups, filter_string):
|
||||
""" Naive case-insensitive search """
|
||||
"""Naive case-insensitive search."""
|
||||
q = filter_string.lower()
|
||||
|
||||
def comp(group):
|
||||
|
@ -112,7 +112,7 @@ class GroupsTable(tables.DataTable):
|
|||
|
||||
class UserFilterAction(tables.FilterAction):
|
||||
def filter(self, table, users, filter_string):
|
||||
""" Naive case-insensitive search """
|
||||
"""Naive case-insensitive search."""
|
||||
q = filter_string.lower()
|
||||
return [user for user in users
|
||||
if q in user.name.lower()
|
||||
|
|
|
@ -84,7 +84,7 @@ class GlobalDiskUsageTab(tabs.TableTab):
|
|||
preload = False
|
||||
|
||||
def get_global_disk_usage_data(self):
|
||||
""" Disk usage table data aggregated by project """
|
||||
"""Disk usage table data aggregated by project."""
|
||||
request = self.tab_group.request
|
||||
return list_of_resource_aggregates(request,
|
||||
ceilometer.GlobalDiskUsage.meters)
|
||||
|
|
|
@ -57,7 +57,7 @@ class DeleteRolesAction(tables.DeleteAction):
|
|||
|
||||
class RoleFilterAction(tables.FilterAction):
|
||||
def filter(self, table, roles, filter_string):
|
||||
""" Naive case-insensitive search """
|
||||
"""Naive case-insensitive search."""
|
||||
q = filter_string.lower()
|
||||
return [role for role in roles
|
||||
if q in role.name.lower()]
|
||||
|
|
|
@ -115,7 +115,7 @@ class DeleteUsersAction(tables.DeleteAction):
|
|||
|
||||
class UserFilterAction(tables.FilterAction):
|
||||
def filter(self, table, users, filter_string):
|
||||
""" Naive case-insensitive search """
|
||||
"""Naive case-insensitive search."""
|
||||
q = filter_string.lower()
|
||||
return [user for user in users
|
||||
if q in user.name.lower()
|
||||
|
|
|
@ -47,8 +47,7 @@ class DeleteContainer(tables.DeleteAction):
|
|||
api.swift.swift_delete_container(request, obj_id)
|
||||
|
||||
def get_success_url(self, request=None):
|
||||
"""
|
||||
Returns the URL to redirect to after a successful action.
|
||||
"""Returns the URL to redirect to after a successful action.
|
||||
"""
|
||||
current_container = self.table.kwargs.get("container_name", None)
|
||||
|
||||
|
|
|
@ -65,8 +65,7 @@ class SetInstanceDetails(workflows.Step):
|
|||
|
||||
|
||||
class AddDatabasesAction(workflows.Action):
|
||||
"""
|
||||
Initialize the database with users/databases. This tab will honor
|
||||
"""Initialize the database with users/databases. This tab will honor
|
||||
the settings which should be a list of permissions required:
|
||||
|
||||
* TROVE_ADD_USER_PERMS = []
|
||||
|
|
|
@ -44,8 +44,7 @@ IMAGES_INDEX_URL = reverse('horizon:project:images_and_snapshots:index')
|
|||
|
||||
class CreateImageFormTests(test.TestCase):
|
||||
def test_no_location_or_file(self):
|
||||
"""
|
||||
The form will not be valid if both copy_from and image_file are not
|
||||
"""The form will not be valid if both copy_from and image_file are not
|
||||
provided.
|
||||
"""
|
||||
post = {
|
||||
|
@ -62,8 +61,7 @@ class CreateImageFormTests(test.TestCase):
|
|||
|
||||
@override_settings(HORIZON_IMAGES_ALLOW_UPLOAD=False)
|
||||
def test_image_upload_disabled(self):
|
||||
"""
|
||||
If HORIZON_IMAGES_ALLOW_UPLOAD is false, the image_file field widget
|
||||
"""If HORIZON_IMAGES_ALLOW_UPLOAD is false, the image_file field widget
|
||||
will be a HiddenInput widget instead of a FileInput widget.
|
||||
"""
|
||||
form = forms.CreateImageForm({})
|
||||
|
|
|
@ -18,8 +18,7 @@ from openstack_dashboard.api import glance
|
|||
|
||||
|
||||
def get_available_images(request, project_id=None, images_cache=None):
|
||||
"""
|
||||
Returns a list of images that are public or owned by the given
|
||||
"""Returns a list of images that are public or owned by the given
|
||||
project_id. If project_id is not specified, only public images
|
||||
are returned.
|
||||
|
||||
|
|
|
@ -217,7 +217,8 @@ class SetInstanceDetailsAction(workflows.Action):
|
|||
"""By default, returns the available flavors, sorted by RAM
|
||||
usage (ascending).
|
||||
Override these behaviours with a CREATE_INSTANCE_FLAVOR_SORT dict
|
||||
in local_settings.py."""
|
||||
in local_settings.py.
|
||||
"""
|
||||
try:
|
||||
flavors = api.nova.flavor_list(request)
|
||||
flavor_sort = getattr(settings, 'CREATE_INSTANCE_FLAVOR_SORT', {})
|
||||
|
|
|
@ -368,7 +368,7 @@ class CreateNetwork(workflows.Workflow):
|
|||
return False
|
||||
|
||||
def _delete_network(self, request, network):
|
||||
"""Delete the created network when subnet creation failed"""
|
||||
"""Delete the created network when subnet creation failed."""
|
||||
try:
|
||||
api.neutron.network_delete(request, network.id)
|
||||
msg = _('Delete the created network "%s" '
|
||||
|
|
|
@ -31,8 +31,7 @@ LOG = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class RuleCIDRField(fields.IPField):
|
||||
"""
|
||||
Extends IPField to allow ('any','external') keywords and requires CIDR
|
||||
"""Extends IPField to allow ('any','external') keywords and requires CIDR
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['mask'] = True
|
||||
|
|
|
@ -29,9 +29,7 @@ LOG = logging.getLogger(__name__)
|
|||
|
||||
|
||||
def exception_to_validation_msg(e):
|
||||
'''
|
||||
Extracts a validation message to display to the user.
|
||||
'''
|
||||
"""Extracts a validation message to display to the user."""
|
||||
try:
|
||||
error = json.loads(str(e))
|
||||
# NOTE(jianingy): if no message exists, we just return 'None'
|
||||
|
|
|
@ -140,9 +140,7 @@ def get_resource_status(status):
|
|||
|
||||
|
||||
def get_resource_image(status, type):
|
||||
'''
|
||||
Sets the image url and in_progress action sw based on status.
|
||||
'''
|
||||
"""Sets the image url and in_progress action sw based on status."""
|
||||
resource_type = get_resource_type(type)
|
||||
resource_status = get_resource_status(status)
|
||||
resource_state = resource_type + "_" + resource_status
|
||||
|
|
|
@ -132,8 +132,9 @@ def get_attachment_name(request, attachment):
|
|||
|
||||
|
||||
class AttachmentColumn(tables.Column):
|
||||
"""
|
||||
Customized column class that does complex processing on the attachments
|
||||
"""Customized column class.
|
||||
|
||||
So it that does complex processing on the attachments
|
||||
for a volume instance.
|
||||
"""
|
||||
def get_raw_data(self, volume):
|
||||
|
@ -230,8 +231,7 @@ class DetachVolume(tables.BatchAction):
|
|||
|
||||
|
||||
class AttachedInstanceColumn(tables.Column):
|
||||
"""
|
||||
Customized column class that does complex processing on the attachments
|
||||
"""Customized column class that does complex processing on the attachments
|
||||
for a volume instance.
|
||||
"""
|
||||
def get_raw_data(self, attachment):
|
||||
|
|
|
@ -60,7 +60,8 @@ def reset():
|
|||
|
||||
|
||||
def check(actions, request, target={}):
|
||||
"""
|
||||
"""Check user permission.
|
||||
|
||||
Check if the user has permission to the action according
|
||||
to policy setting.
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ from openstack_dashboard.test import helpers as test
|
|||
|
||||
|
||||
class APIResource(api_base.APIResourceWrapper):
|
||||
""" Simple APIResource for testing """
|
||||
"""Simple APIResource for testing."""
|
||||
_attrs = ['foo', 'bar', 'baz']
|
||||
|
||||
@staticmethod
|
||||
|
@ -44,7 +44,7 @@ class APIResource(api_base.APIResourceWrapper):
|
|||
|
||||
|
||||
class APIDict(api_base.APIDictWrapper):
|
||||
""" Simple APIDict for testing """
|
||||
"""Simple APIDict for testing."""
|
||||
_attrs = ['foo', 'bar', 'baz']
|
||||
|
||||
@staticmethod
|
||||
|
@ -116,7 +116,7 @@ class APIDictWrapperTests(test.TestCase):
|
|||
|
||||
|
||||
class ApiHelperTests(test.TestCase):
|
||||
""" Tests for functions that don't use one of the api objects """
|
||||
"""Tests for functions that don't use one of the api objects."""
|
||||
|
||||
def test_url_for(self):
|
||||
url = api_base.url_for(self.request, 'image')
|
||||
|
|
|
@ -50,8 +50,7 @@ class RoleAPITests(test.APITestCase):
|
|||
self.roles = self.roles.list()
|
||||
|
||||
def test_remove_tenant_user(self):
|
||||
"""
|
||||
Tests api.keystone.remove_tenant_user
|
||||
"""Tests api.keystone.remove_tenant_user
|
||||
|
||||
Verifies that remove_tenant_user is called with the right arguments
|
||||
after iterating the user's roles.
|
||||
|
|
|
@ -108,8 +108,7 @@ class RequestFactoryWithMessages(RequestFactory):
|
|||
@unittest.skipIf(os.environ.get('SKIP_UNITTESTS', False),
|
||||
"The SKIP_UNITTESTS env variable is set.")
|
||||
class TestCase(horizon_helpers.TestCase):
|
||||
"""
|
||||
Specialized base test case class for Horizon which gives access to
|
||||
"""Specialized base test case class for Horizon which gives access to
|
||||
numerous additional features:
|
||||
|
||||
* A full suite of test data through various attached objects and
|
||||
|
@ -180,8 +179,7 @@ class TestCase(horizon_helpers.TestCase):
|
|||
utils.get_user = get_user
|
||||
|
||||
def assertRedirectsNoFollow(self, response, expected_url):
|
||||
"""
|
||||
Asserts that the given response issued a 302 redirect without
|
||||
"""Asserts that the given response issued a 302 redirect without
|
||||
processing the view which is redirected to.
|
||||
"""
|
||||
assert (response.status_code / 100 == 3), \
|
||||
|
@ -191,8 +189,7 @@ class TestCase(horizon_helpers.TestCase):
|
|||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def assertNoFormErrors(self, response, context_name="form"):
|
||||
"""
|
||||
Asserts that the response either does not contain a form in its
|
||||
"""Asserts that the response either does not contain a form in its
|
||||
context, or that if it does, that form has no errors.
|
||||
"""
|
||||
context = getattr(response, "context", {})
|
||||
|
@ -204,8 +201,7 @@ class TestCase(horizon_helpers.TestCase):
|
|||
|
||||
def assertFormErrors(self, response, count=0, message=None,
|
||||
context_name="form"):
|
||||
"""
|
||||
Asserts that the response does contain a form in its
|
||||
"""Asserts that the response does contain a form in its
|
||||
context, and that form has errors, if count were given,
|
||||
it must match the exact numbers of errors
|
||||
"""
|
||||
|
@ -226,8 +222,7 @@ class TestCase(horizon_helpers.TestCase):
|
|||
|
||||
|
||||
class BaseAdminViewTests(TestCase):
|
||||
"""
|
||||
A ``TestCase`` subclass which sets an active user with the "admin" role
|
||||
"""A ``TestCase`` subclass which sets an active user with the "admin" role
|
||||
for testing admin-only views and functionality.
|
||||
"""
|
||||
def setActiveUser(self, *args, **kwargs):
|
||||
|
@ -248,8 +243,7 @@ class BaseAdminViewTests(TestCase):
|
|||
|
||||
|
||||
class APITestCase(TestCase):
|
||||
"""
|
||||
The ``APITestCase`` class is for use with tests which deal with the
|
||||
"""The ``APITestCase`` class is for use with tests which deal with the
|
||||
underlying clients rather than stubbing out the
|
||||
openstack_dashboard.api.* methods.
|
||||
"""
|
||||
|
@ -258,8 +252,7 @@ class APITestCase(TestCase):
|
|||
utils.patch_middleware_get_user()
|
||||
|
||||
def fake_keystoneclient(request, admin=False):
|
||||
"""
|
||||
Wrapper function which returns the stub keystoneclient. Only
|
||||
"""Wrapper function which returns the stub keystoneclient. Only
|
||||
necessary because the function takes too many arguments to
|
||||
conveniently be a lambda.
|
||||
"""
|
||||
|
@ -414,8 +407,7 @@ class SeleniumTestCase(horizon_helpers.SeleniumTestCase):
|
|||
|
||||
|
||||
class SeleniumAdminTestCase(SeleniumTestCase):
|
||||
"""
|
||||
A ``TestCase`` subclass which sets an active user with the "admin" role
|
||||
"""A ``TestCase`` subclass which sets an active user with the "admin" role
|
||||
for testing admin-only views and functionality.
|
||||
"""
|
||||
def setActiveUser(self, *args, **kwargs):
|
||||
|
|
|
@ -53,8 +53,7 @@ def load_test_data(load_onto=None):
|
|||
|
||||
|
||||
class TestData(object):
|
||||
"""
|
||||
Holder object for test data. Any functions passed to the init method
|
||||
"""Holder object for test data. Any functions passed to the init method
|
||||
will be called with the ``TestData`` object as their only argument. They
|
||||
can then load data onto the object as desired.
|
||||
|
||||
|
@ -103,8 +102,7 @@ class TestDataContainer(object):
|
|||
return self._objects
|
||||
|
||||
def filter(self, filtered=None, **kwargs):
|
||||
"""
|
||||
Returns objects in this container whose attributes match the given
|
||||
"""Returns objects in this container whose attributes match the given
|
||||
keyword arguments.
|
||||
"""
|
||||
if filtered is None:
|
||||
|
@ -121,8 +119,7 @@ class TestDataContainer(object):
|
|||
return self.filter(filtered=filter(get_match, filtered), **kwargs)
|
||||
|
||||
def get(self, **kwargs):
|
||||
"""
|
||||
Returns the single object in this container whose attributes match
|
||||
"""Returns the single object in this container whose attributes match
|
||||
the given keyword arguments. An error will be raised if the arguments
|
||||
provided don't return exactly one match.
|
||||
"""
|
||||
|
|
|
@ -23,7 +23,7 @@ from openstack_dashboard.test import helpers as test
|
|||
|
||||
|
||||
class ErrorPageTests(test.TestCase):
|
||||
""" Tests for error pages """
|
||||
"""Tests for error pages."""
|
||||
urls = 'openstack_dashboard.test.error_pages_urls'
|
||||
|
||||
def test_500_error(self):
|
||||
|
|
|
@ -25,7 +25,7 @@ class FakeUser(object):
|
|||
|
||||
|
||||
class TemplateRenderTest(test.TestCase):
|
||||
""" Tests for templates render """
|
||||
"""Tests for templates render."""
|
||||
|
||||
def test_openrc_html_escape(self):
|
||||
context = {
|
||||
|
|
|
@ -275,8 +275,7 @@ class ProjectUsage(BaseUsage):
|
|||
|
||||
class CsvDataMixin(object):
|
||||
|
||||
"""
|
||||
CSV data Mixin - provides handling for CSV data
|
||||
"""CSV data Mixin - provides handling for CSV data.
|
||||
|
||||
.. attribute:: columns
|
||||
|
||||
|
@ -318,10 +317,7 @@ class CsvDataMixin(object):
|
|||
|
||||
class BaseCsvResponse(CsvDataMixin, HttpResponse):
|
||||
|
||||
"""
|
||||
Base CSV response class. Provides handling of CSV data.
|
||||
|
||||
"""
|
||||
"""Base CSV response class. Provides handling of CSV data."""
|
||||
|
||||
def __init__(self, request, template, context, content_type, **kwargs):
|
||||
super(BaseCsvResponse, self).__init__()
|
||||
|
@ -358,8 +354,7 @@ if VERSION >= (1, 5, 0):
|
|||
|
||||
class BaseCsvStreamingResponse(CsvDataMixin, StreamingHttpResponse):
|
||||
|
||||
"""
|
||||
Base CSV Streaming class. Provides streaming response for CSV data.
|
||||
"""Base CSV Streaming class. Provides streaming response for CSV data.
|
||||
"""
|
||||
|
||||
def __init__(self, request, template, context, content_type, **kwargs):
|
||||
|
|
3
tox.ini
3
tox.ini
|
@ -34,8 +34,7 @@ builtins = _
|
|||
exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,panel_template,dash_template,local_settings.py
|
||||
# E127 continuation line over-indented for visual indent
|
||||
# E128 continuation line under-indented for visual indent
|
||||
# H4xx docstrings
|
||||
# H701 empty localization string
|
||||
# H702 Formatting operation should be outside of localization method call
|
||||
# H803 git commit title should not end with period (disabled on purpose, see bug #1236621)
|
||||
ignore = E127,E128,H4,H701,H702,H803
|
||||
ignore = E127,E128,H701,H702,H803
|
||||
|
|
Loading…
Reference in New Issue