From da8c69afa6392c92b587a1a22eb8dd20768c617d Mon Sep 17 00:00:00 2001 From: Paul Belanger Date: Fri, 1 Nov 2013 14:02:41 -0400 Subject: [PATCH] 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 --- horizon/base.py | 47 ++++---- horizon/browsers/base.py | 5 +- horizon/browsers/breadcrumb.py | 2 +- horizon/context_processors.py | 2 +- horizon/decorators.py | 6 +- horizon/exceptions.py | 42 +++---- horizon/forms/base.py | 8 +- horizon/forms/fields.py | 10 +- horizon/forms/views.py | 13 +- horizon/messages.py | 24 +--- horizon/middleware.py | 10 +- horizon/tables/actions.py | 58 ++++----- horizon/tables/base.py | 112 ++++++++---------- horizon/tables/views.py | 9 +- horizon/tabs/base.py | 64 ++++------ horizon/tabs/views.py | 19 ++- horizon/templatetags/horizon.py | 12 +- horizon/templatetags/parse_date.py | 4 +- horizon/templatetags/sizeformat.py | 5 +- horizon/test/helpers.py | 11 +- horizon/test/tests/base.py | 15 ++- horizon/test/tests/tables.py | 2 +- horizon/test/tests/templatetags.py | 8 +- horizon/utils/fields.py | 10 +- horizon/utils/filters.py | 3 +- horizon/utils/html.py | 18 +-- horizon/utils/validators.py | 2 +- horizon/views.py | 7 +- horizon/workflows/base.py | 80 +++++-------- horizon/workflows/views.py | 17 ++- openstack_dashboard/api/base.py | 28 ++--- openstack_dashboard/api/ceilometer.py | 96 +++++++-------- openstack_dashboard/api/cinder.py | 6 +- openstack_dashboard/api/fwaas.py | 6 +- openstack_dashboard/api/glance.py | 3 +- openstack_dashboard/api/keystone.py | 24 ++-- openstack_dashboard/api/lbaas.py | 10 +- openstack_dashboard/api/neutron.py | 21 ++-- openstack_dashboard/api/nova.py | 5 +- openstack_dashboard/api/swift.py | 2 +- openstack_dashboard/api/trove.py | 2 +- openstack_dashboard/context_processors.py | 2 +- .../dashboards/admin/domains/tables.py | 2 +- .../dashboards/admin/flavors/tables.py | 2 +- .../dashboards/admin/groups/tables.py | 4 +- .../dashboards/admin/images/views.py | 2 +- .../dashboards/admin/instances/tables.py | 2 +- .../dashboards/admin/metering/tabs.py | 4 +- .../dashboards/admin/metering/views.py | 2 +- .../dashboards/admin/projects/tables.py | 2 +- .../dashboards/admin/roles/tables.py | 2 +- .../dashboards/admin/users/tables.py | 2 +- .../dashboards/admin/volumes/tables.py | 2 +- .../dashboards/project/containers/tables.py | 3 +- .../dashboards/project/containers/views.py | 6 +- .../databases/workflows/create_instance.py | 3 +- .../images_and_snapshots/images/tests.py | 6 +- .../project/images_and_snapshots/utils.py | 3 +- .../dashboards/project/instances/tables.py | 2 +- .../instances/workflows/create_instance.py | 3 +- .../dashboards/project/networks/workflows.py | 2 +- .../routers/extensions/routerrules/forms.py | 3 +- .../dashboards/project/stacks/forms.py | 4 +- .../dashboards/project/stacks/mappings.py | 4 +- .../dashboards/project/volumes/tables.py | 10 +- .../dashboards/router/nexus1000v/forms.py | 4 +- openstack_dashboard/policy.py | 3 +- .../test/api_tests/base_tests.py | 6 +- .../test/api_tests/keystone_tests.py | 3 +- openstack_dashboard/test/helpers.py | 24 ++-- openstack_dashboard/test/test_data/utils.py | 17 ++- openstack_dashboard/test/tests/error_pages.py | 2 +- openstack_dashboard/test/tests/templates.py | 2 +- openstack_dashboard/usage/base.py | 11 +- openstack_dashboard/usage/quotas.py | 8 +- tox.ini | 3 +- 76 files changed, 411 insertions(+), 577 deletions(-) diff --git a/horizon/base.py b/horizon/base.py index eefa47c1c4..327731d362 100644 --- a/horizon/base.py +++ b/horizon/base.py @@ -159,7 +159,7 @@ class Registry(object): class Panel(HorizonComponent): - """ A base class for defining Horizon dashboard panels. + """A base class for defining Horizon dashboard panels. All Horizon dashboard panels should extend from this class. It provides the appropriate hooks for automatically constructing URLconfs, and @@ -214,7 +214,7 @@ class Panel(HorizonComponent): return "" % self.slug def get_absolute_url(self): - """ Returns the default URL for this panel. + """Returns the default URL for this panel. The default URL is defined as the URL pattern with ``name="index"`` in the URLconf for this panel. @@ -243,7 +243,7 @@ class Panel(HorizonComponent): class PanelGroup(object): - """ A container for a set of :class:`~horizon.Panel` classes. + """A container for a set of :class:`~horizon.Panel` classes. When iterated, it will yield each of the ``Panel`` instances it contains. @@ -286,7 +286,7 @@ class PanelGroup(object): class Dashboard(Registry, HorizonComponent): - """ A base class for defining Horizon dashboards. + """A base class for defining Horizon dashboards. All Horizon dashboards should extend from this base class. It provides the appropriate hooks for automatic discovery of :class:`~horizon.Panel` @@ -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 = [] @@ -432,7 +430,7 @@ class Dashboard(Registry, HorizonComponent): return SortedDict(panel_groups) def get_absolute_url(self): - """ Returns the default URL for this dashboard. + """Returns the default URL for this dashboard. The default URL is defined as the URL pattern with ``name="index"`` in the URLconf for the :class:`~horizon.Panel` specified by @@ -478,7 +476,7 @@ class Dashboard(Registry, HorizonComponent): return urlpatterns, self.slug, self.slug def _autodiscover(self): - """ Discovers panels to register from the current dashboard module. """ + """Discovers panels to register from the current dashboard module.""" if getattr(self, "_autodiscover_complete", False): return @@ -520,7 +518,7 @@ class Dashboard(Registry, HorizonComponent): @classmethod def register(cls, panel): - """ Registers a :class:`~horizon.Panel` with this dashboard. """ + """Registers a :class:`~horizon.Panel` with this dashboard.""" panel_class = Horizon.register_panel(cls, panel) # Support template loading from panel template directories. panel_mod = import_module(panel.__module__) @@ -533,7 +531,7 @@ class Dashboard(Registry, HorizonComponent): @classmethod def unregister(cls, panel): - """ Unregisters a :class:`~horizon.Panel` from this dashboard. """ + """Unregisters a :class:`~horizon.Panel` from this dashboard.""" success = Horizon.unregister_panel(cls, panel) if success: # Remove the panel's template directory. @@ -578,7 +576,7 @@ class LazyURLPattern(SimpleLazyObject): class Site(Registry, HorizonComponent): - """ The overarching class which encompasses all dashboards and panels. """ + """The overarching class which encompasses all dashboards and panels.""" # Required for registry _registerable_class = Dashboard @@ -604,11 +602,11 @@ class Site(Registry, HorizonComponent): return self._conf['default_dashboard'] def register(self, dashboard): - """ Registers a :class:`~horizon.Dashboard` with Horizon.""" + """Registers a :class:`~horizon.Dashboard` with Horizon.""" return self._register(dashboard) def unregister(self, dashboard): - """ Unregisters a :class:`~horizon.Dashboard` from Horizon. """ + """Unregisters a :class:`~horizon.Dashboard` from Horizon.""" return self._unregister(dashboard) def registered(self, dashboard): @@ -626,11 +624,11 @@ class Site(Registry, HorizonComponent): return dash_instance._unregister(panel) def get_dashboard(self, dashboard): - """ Returns the specified :class:`~horizon.Dashboard` instance. """ + """Returns the specified :class:`~horizon.Dashboard` instance.""" return self._registered(dashboard) def get_dashboards(self): - """ Returns an ordered tuple of :class:`~horizon.Dashboard` modules. + """Returns an ordered tuple of :class:`~horizon.Dashboard` modules. Orders dashboards according to the ``"dashboards"`` key in ``HORIZON_CONFIG`` or else returns all registered dashboards @@ -658,7 +656,7 @@ class Site(Registry, HorizonComponent): return dashboards def get_default_dashboard(self): - """ Returns the default :class:`~horizon.Dashboard` instance. + """Returns the default :class:`~horizon.Dashboard` instance. If ``"default_dashboard"`` is specified in ``HORIZON_CONFIG`` then that dashboard will be returned. If not, the first dashboard @@ -672,7 +670,7 @@ class Site(Registry, HorizonComponent): raise NotRegistered("No dashboard modules have been registered.") def get_user_home(self, user): - """ Returns the default URL for a particular user. + """Returns the default URL for a particular user. This method can be used to customize where a user is sent when they log in, etc. By default it returns the value of @@ -710,7 +708,7 @@ class Site(Registry, HorizonComponent): return self.get_absolute_url() def get_absolute_url(self): - """ Returns the default URL for Horizon's URLconf. + """Returns the default URL for Horizon's URLconf. The default URL is determined by calling :meth:`~horizon.Dashboard.get_absolute_url` @@ -721,7 +719,7 @@ class Site(Registry, HorizonComponent): @property def _lazy_urls(self): - """ Lazy loading for URL patterns. + """Lazy loading for URL patterns. This method avoids problems associated with attempting to evaluate the the URLconf before the settings module has been loaded. @@ -732,7 +730,7 @@ class Site(Registry, HorizonComponent): return LazyURLPattern(url_patterns), self.namespace, self.slug def _urls(self): - """ Constructs the URLconf for Horizon from registered Dashboards. """ + """Constructs the URLconf for Horizon from registered Dashboards.""" urlpatterns = self._get_default_urlpatterns() self._autodiscover() @@ -764,7 +762,7 @@ class Site(Registry, HorizonComponent): return urlpatterns, self.namespace, self.slug def _autodiscover(self): - """ Discovers modules to register from ``settings.INSTALLED_APPS``. + """Discovers modules to register from ``settings.INSTALLED_APPS``. This makes sure that the appropriate modules get imported to register themselves with Horizon. @@ -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 diff --git a/horizon/browsers/base.py b/horizon/browsers/base.py index e8ff7f3bb2..362f162b10 100644 --- a/horizon/browsers/base.py +++ b/horizon/browsers/base.py @@ -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] diff --git a/horizon/browsers/breadcrumb.py b/horizon/browsers/breadcrumb.py index 9ce1abd83b..fac81a5e1b 100644 --- a/horizon/browsers/breadcrumb.py +++ b/horizon/browsers/breadcrumb.py @@ -41,7 +41,7 @@ class Breadcrumb(html.HTMLElement): return self._subfolders def render(self): - """ Renders the table using the template from the table options. """ + """Renders the table using the template from the table options.""" breadcrumb_template = template.loader.get_template(self.template) extra_context = {"breadcrumb": self} context = template.RequestContext(self.request, extra_context) diff --git a/horizon/context_processors.py b/horizon/context_processors.py index f5d2ecfdc6..6a17e76551 100644 --- a/horizon/context_processors.py +++ b/horizon/context_processors.py @@ -25,7 +25,7 @@ from horizon import conf def horizon(request): - """ The main Horizon context processor. Required for Horizon to function. + """The main Horizon context processor. Required for Horizon to function. It adds the Horizon config to the context as well as setting the names ``True`` and ``False`` in the context to their boolean equivalents diff --git a/horizon/decorators.py b/horizon/decorators.py index 865d843806..bd5ff4ef26 100644 --- a/horizon/decorators.py +++ b/horizon/decorators.py @@ -28,7 +28,7 @@ from django.utils.translation import ugettext_lazy as _ # noqa def _current_component(view_func, dashboard=None, panel=None): - """ Sets the currently-active dashboard and/or panel on the request. """ + """Sets the currently-active dashboard and/or panel on the request.""" @functools.wraps(view_func, assigned=available_attrs(view_func)) def dec(request, *args, **kwargs): if dashboard: @@ -40,7 +40,7 @@ def _current_component(view_func, dashboard=None, panel=None): def require_auth(view_func): - """ Performs user authentication check. + """Performs user authentication check. Similar to Django's `login_required` decorator, except that this throws :exc:`~horizon.exceptions.NotAuthenticated` exception if the user is not @@ -57,7 +57,7 @@ def require_auth(view_func): def require_perms(view_func, required): - """ Enforces permission-based access controls. + """Enforces permission-based access controls. :param list required: A tuple of permission names, all of which the request user must possess in order access the decorated view. diff --git a/horizon/exceptions.py b/horizon/exceptions.py index d1fb70e927..805d644cfc 100644 --- a/horizon/exceptions.py +++ b/horizon/exceptions.py @@ -36,15 +36,14 @@ LOG = logging.getLogger(__name__) class HorizonReporterFilter(SafeExceptionReporterFilter): - """ Error report filter that's always active, even in DEBUG mode. """ + """Error report filter that's always active, even in DEBUG mode.""" def is_active(self, request): return True # 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 @@ -93,13 +92,12 @@ class HorizonReporterFilter(SafeExceptionReporterFilter): class HorizonException(Exception): - """ Base exception class for distinguishing our own exception classes. """ + """Base exception class for distinguishing our own exception classes.""" pass 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 @@ -134,19 +131,18 @@ class NotAuthenticated(HorizonException): class NotFound(HorizonException): - """ Generic error to replace all "Not Found"-type API errors. """ + """Generic error to replace all "Not Found"-type API errors.""" status_code = 404 class RecoverableError(HorizonException): - """ Generic error to replace any "Recoverable"-type API errors. """ + """Generic error to replace any "Recoverable"-type API errors.""" status_code = 100 # HTTP status code "Continue" 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): @@ -173,21 +168,19 @@ class AlreadyExists(HorizonException): class WorkflowError(HorizonException): - """ Exception to be raised when something goes wrong in a workflow. """ + """Exception to be raised when something goes wrong in a workflow.""" pass 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. """ @@ -218,7 +210,7 @@ def check_message(keywords, message): def handle(request, message=None, redirect=None, ignore=False, escalate=False, log_level=None, force_log=None): - """ Centralized error handling for Horizon. + """Centralized error handling for Horizon. Because Horizon consumes so many different APIs with completely different ``Exception`` types, it's necessary to have a centralized diff --git a/horizon/forms/base.py b/horizon/forms/base.py index 605568a2ce..8a68d10a71 100644 --- a/horizon/forms/base.py +++ b/horizon/forms/base.py @@ -32,15 +32,13 @@ class SelfHandlingMixin(object): class SelfHandlingForm(SelfHandlingMixin, forms.Form): - """ - A base :class:`Form ` class which includes + """A base :class:`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. @@ -49,7 +47,7 @@ class SelfHandlingForm(SelfHandlingMixin, forms.Form): class DateForm(forms.Form): - """ A simple form for selecting a range of time. """ + """A simple form for selecting a range of time.""" start = forms.DateField(input_formats=("%Y-%m-%d",)) end = forms.DateField(input_formats=("%Y-%m-%d",)) diff --git a/horizon/forms/fields.py b/horizon/forms/fields.py index 38dd2250d6..473373ede4 100644 --- a/horizon/forms/fields.py +++ b/horizon/forms/fields.py @@ -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`` @@ -67,5 +65,5 @@ class DynamicChoiceField(fields.ChoiceField): class DynamicTypedChoiceField(DynamicChoiceField, fields.TypedChoiceField): - """ Simple mix of ``DynamicChoiceField`` and ``TypedChoiceField``. """ + """Simple mix of ``DynamicChoiceField`` and ``TypedChoiceField``.""" pass diff --git a/horizon/forms/views.py b/horizon/forms/views.py index 3a274bd387..ff0ec938d8 100644 --- a/horizon/forms/views.py +++ b/horizon/forms/views.py @@ -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): diff --git a/horizon/messages.py b/horizon/messages.py index b3cdeb7d06..57473b14e9 100644 --- a/horizon/messages.py +++ b/horizon/messages.py @@ -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) diff --git a/horizon/middleware.py b/horizon/middleware.py index 427d7c6e09..61fcdbbff3 100644 --- a/horizon/middleware.py +++ b/horizon/middleware.py @@ -43,12 +43,12 @@ LOG = logging.getLogger(__name__) class HorizonMiddleware(object): - """ The main Horizon middleware class. Required for use of Horizon. """ + """The main Horizon middleware class. Required for use of Horizon.""" logout_reason = None def process_request(self, request): - """ Adds data necessary for Horizon to function to the request. """ + """Adds data necessary for Horizon to function to the request.""" # Activate timezone handling tz = request.session.get('django_timezone') if tz: @@ -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'): diff --git a/horizon/tables/actions.py b/horizon/tables/actions.py index 4a7632a331..9ef6974207 100644 --- a/horizon/tables/actions.py +++ b/horizon/tables/actions.py @@ -39,7 +39,7 @@ STRING_SEPARATOR = "__" class BaseAction(html.HTMLElement): - """ Common base class for all ``Action`` classes. """ + """Common base class for all ``Action`` classes.""" table = None handles_multiple = False requires_input = False @@ -51,8 +51,8 @@ class BaseAction(html.HTMLElement): self.datum = datum def data_type_matched(self, datum): - """ Method to see if the action is allowed for a certain type of data. - Only affects mixed data type tables. + """Method to see if the action is allowed for a certain type of data. + Only affects mixed data type tables. """ if datum: action_data_types = getattr(self, "allowed_data_types", []) @@ -66,7 +66,7 @@ class BaseAction(html.HTMLElement): return True def get_policy_target(self, request, datum): - """ Provide the target for a policy request. + """Provide the target for a policy request. This method is meant to be overridden to return target details when one of the policy checks requires them. E.g., {"user_id": datum.id} @@ -74,7 +74,7 @@ class BaseAction(html.HTMLElement): return {} def allowed(self, request, datum): - """ Determine whether this action is allowed for the current request. + """Determine whether this action is allowed for the current request. This method is meant to be overridden with more specific checks. """ @@ -90,7 +90,7 @@ class BaseAction(html.HTMLElement): return self.allowed(request, datum) def update(self, request, datum): - """ Allows per-action customization based on current conditions. + """Allows per-action customization based on current conditions. This is particularly useful when you wish to create a "toggle" action that will be rendered differently based on the value of an @@ -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: @@ -126,7 +124,7 @@ class BaseAction(html.HTMLElement): class Action(BaseAction): - """ Represents an action which can be taken on this table's data. + """Represents an action which can be taken on this table's data. .. attribute:: name @@ -265,7 +263,7 @@ class Action(BaseAction): self.multiple = new.instancemethod(multiple, self) def get_param_name(self): - """ Returns the full POST parameter name for this action. + """Returns the full POST parameter name for this action. Defaults to ``{{ table.name }}__{{ action.name }}``. @@ -274,7 +272,7 @@ class Action(BaseAction): class LinkAction(BaseAction): - """ A table action which is simply a link rather than a form POST. + """A table action which is simply a link rather than a form POST. .. attribute:: name @@ -319,7 +317,7 @@ class LinkAction(BaseAction): self.attrs.update(attrs) def get_link_url(self, datum=None): - """ Returns the final URL based on the value of ``url``. + """Returns the final URL based on the value of ``url``. If ``url`` is callable it will call the function. If not, it will then try to call ``reverse`` on ``url``. @@ -346,7 +344,7 @@ class LinkAction(BaseAction): class FilterAction(BaseAction): - """ A base class representing a filter action for a table. + """A base class representing a filter action for a table. .. attribute:: name @@ -389,7 +387,7 @@ class FilterAction(BaseAction): self.param_name = param_name or 'q' def get_param_name(self): - """ Returns the full query parameter name for this action. + """Returns the full query parameter name for this action. Defaults to ``{{ table.name }}__{{ action.name }}__{{ action.param_name }}``. @@ -424,7 +422,7 @@ class FilterAction(BaseAction): return filtered_data def filter(self, table, data, filter_string): - """ Provides the actual filtering logic. + """Provides the actual filtering logic. This method must be overridden by subclasses and return the filtered data. @@ -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 @@ -480,9 +477,9 @@ class FixedFilterAction(FilterAction): class BatchAction(Action): - """ A table action which takes batch action on one or more - objects. This action should not require user input on a - per-object basis. + """A table action which takes batch action on one or more + objects. This action should not require user input on a + per-object basis. .. attribute:: name @@ -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() diff --git a/horizon/tables/base.py b/horizon/tables/base.py index d8930dc997..b035018a07 100644 --- a/horizon/tables/base.py +++ b/horizon/tables/base.py @@ -49,7 +49,7 @@ STRING_SEPARATOR = "__" class Column(html.HTMLElement): - """ A class which represents a single column in a :class:`.DataTable`. + """A class which represents a single column in a :class:`.DataTable`. .. attribute:: transform @@ -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` @@ -329,7 +328,7 @@ class Column(html.HTMLElement): return self.table._data_cache[self][datum_id] def get_link_url(self, datum): - """ Returns the final value for the column's ``link`` property. + """Returns the final value for the column's ``link`` property. If ``allowed_data_types`` of this column is not empty and the datum has an assigned type, check if the datum's type is in the @@ -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: @@ -376,7 +374,7 @@ class Column(html.HTMLElement): class Row(html.HTMLElement): - """ Represents a row in the table. + """Represents a row in the table. When iterated, the ``Row`` instance will yield each of its cells. @@ -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. @@ -526,7 +523,7 @@ class Row(html.HTMLElement): {"row": self}) def get_cells(self): - """ Returns the bound cells for this row in order. """ + """Returns the bound cells for this row in order.""" return self.cells.values() def get_ajax_update_url(self): @@ -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" @@ -546,7 +542,7 @@ class Row(html.HTMLElement): class Cell(html.HTMLElement): - """ Represents a single cell in the table. """ + """Represents a single cell in the table.""" def __init__(self, datum, data, column, row, attrs=None, classes=None): self.classes = classes or getattr(self, "classes", []) super(Cell, self).__init__() @@ -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 @@ -602,7 +597,7 @@ class Cell(html.HTMLElement): @property def status(self): - """ Gets the status for the column based on the cell's data. """ + """Gets the status for the column based on the cell's data.""" # Deal with status column mechanics based in this cell's data if hasattr(self, '_status'): return self._status @@ -619,7 +614,7 @@ class Cell(html.HTMLElement): return self._status def get_status_class(self, status): - """ Returns a css class name determined by the status value. """ + """Returns a css class name determined by the status value.""" if status is True: return "status_up" elif status is False: @@ -628,7 +623,7 @@ class Cell(html.HTMLElement): return "status_unknown" def get_default_classes(self): - """ Returns a flattened string of the cell's CSS classes. """ + """Returns a flattened string of the cell's CSS classes.""" if not self.url: self.column.classes = [cls for cls in self.column.classes if cls != "anchor"] @@ -640,7 +635,7 @@ class Cell(html.HTMLElement): class DataTableOptions(object): - """ Contains options for :class:`.DataTable` objects. + """Contains options for :class:`.DataTable` objects. .. attribute:: name @@ -823,7 +818,7 @@ class DataTableOptions(object): class DataTableMetaclass(type): - """ Metaclass to add options to DataTable class and collect columns. """ + """Metaclass to add options to DataTable class and collect columns.""" def __new__(mcs, name, bases, attrs): # Process options from Meta class_name = name @@ -896,7 +891,7 @@ class DataTableMetaclass(type): class DataTable(object): - """ A class which defines a table with all data and associated actions. + """A class which defines a table with all data and associated actions. .. attribute:: name @@ -1017,14 +1012,14 @@ class DataTable(object): return False def render(self): - """ Renders the table using the template from the table options. """ + """Renders the table using the template from the table options.""" table_template = template.loader.get_template(self._meta.template) extra_context = {self._meta.context_var_name: self} context = template.RequestContext(self.request, extra_context) return table_template.render(context) def get_absolute_url(self): - """ Returns the canonical URL for this table. + """Returns the canonical URL for this table. This is used for the POST action attribute on the form element wrapping the table. In many cases it is also useful for redirecting @@ -1037,12 +1032,11 @@ class DataTable(object): return self.request.get_full_path().partition('?')[0] def get_empty_message(self): - """ Returns the message to be displayed when there is no data. """ + """Returns the message to be displayed when there is no data.""" 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 ``
`` tag or not. """ # If needs_form_wrapper is explicitly set, defer to that. @@ -1092,14 +1084,14 @@ class DataTable(object): return self.has_actions def get_table_actions(self): - """ Returns a list of the action instances for this table. """ + """Returns a list of the action instances for this table.""" bound_actions = [self.base_actions[action.name] for action in self._meta.table_actions] return [action for action in bound_actions if self._filter_action(action, self.request)] def get_row_actions(self, datum): - """ Returns a list of the action instances for a specific row. """ + """Returns a list of the action instances for a specific row.""" bound_actions = [] for action in self._meta.row_actions: # Copy to allow modifying properties per row @@ -1120,7 +1112,7 @@ class DataTable(object): return bound_actions def render_table_actions(self): - """ Renders the actions specified in ``Meta.table_actions``. """ + """Renders the actions specified in ``Meta.table_actions``.""" template_path = self._meta.table_actions_template table_actions_template = template.loader.get_template(template_path) bound_actions = self.get_table_actions() @@ -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. @@ -1200,7 +1190,7 @@ class DataTable(object): @classmethod def check_handler(cls, request): - """ Determine whether the request should be handled by this table. """ + """Determine whether the request should be handled by this table.""" if request.method == "POST" and "action" in request.POST: table, action, obj_id = cls.parse_action(request.POST["action"]) elif "table" in request.GET and "action" in request.GET: @@ -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) @@ -1262,13 +1250,13 @@ class DataTable(object): return None def sanitize_id(self, obj_id): - """ Override to modify an incoming obj_id to match existing + """Override to modify an incoming obj_id to match existing API data types or modify the format. """ return obj_id def get_object_id(self, datum): - """ Returns the identifier for the object this row will represent. + """Returns the identifier for the object this row will represent. By default this returns an ``id`` attribute on the given object, but this can be overridden to return other values. @@ -1281,7 +1269,7 @@ class DataTable(object): return datum.id def get_object_display(self, datum): - """ Returns a display name that identifies this object. + """Returns a display name that identifies this object. By default, this returns a ``name`` attribute from the given object, but this can be overriden to return other values. @@ -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,19 +1288,17 @@ 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])) def get_pagination_string(self): - """ Returns the query parameter string to paginate this table. """ + """Returns the query parameter string to paginate this table.""" 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. """ @@ -1352,11 +1336,11 @@ class DataTable(object): return "status_unknown" def get_columns(self): - """ Returns this table's columns including auto-generated ones.""" + """Returns this table's columns including auto-generated ones.""" return self.columns.values() def get_rows(self): - """ Return the row data for this table broken out by columns. """ + """Return the row data for this table broken out by columns.""" rows = [] try: for datum in self.filtered_data: diff --git a/horizon/tables/views.py b/horizon/tables/views.py index d00b8f456e..986cd6aa00 100644 --- a/horizon/tables/views.py +++ b/horizon/tables/views.py @@ -22,7 +22,7 @@ from horizon.templatetags.horizon import has_permissions # noqa class MultiTableMixin(object): - """ A generic mixin which provides methods for handling DataTables. """ + """A generic mixin which provides methods for handling DataTables.""" data_method_pattern = "get_%s_data" def __init__(self, *args, **kwargs): @@ -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`` @@ -164,7 +163,7 @@ class MultiTableView(MultiTableMixin, generic.TemplateView): class DataTableView(MultiTableView): - """ A class-based generic view to handle basic DataTable processing. + """A class-based generic view to handle basic DataTable processing. Three steps are required to use this view: set the ``table_class`` attribute with the desired :class:`~horizon.tables.DataTable` class; @@ -211,7 +210,7 @@ class DataTableView(MultiTableView): class MixedDataTableView(DataTableView): - """ A class-based generic view to handle DataTable with mixed data + """A class-based generic view to handle DataTable with mixed data types. Basic usage is the same as DataTableView. diff --git a/horizon/tabs/base.py b/horizon/tabs/base.py index e0130740ef..6dc25fc2d1 100644 --- a/horizon/tabs/base.py +++ b/horizon/tabs/base.py @@ -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. """ @@ -169,15 +163,15 @@ class TabGroup(html.HTMLElement): return marked_active def render(self): - """ Renders the HTML output for this tab group. """ + """Renders the HTML output for this tab group.""" return render_to_string(self.template_name, {"tab_group": self}) def get_tabs(self): - """ Returns a list of the allowed tabs for this tab group. """ + """Returns a list of the allowed tabs for this tab group.""" return filter(lambda tab: tab._allowed, self._tabs.values()) def get_tab(self, tab_name, allow_disabled=False): - """ Returns a specific tab from this tab group. + """Returns a specific tab from this tab group. If the tab is not allowed or not enabled this method returns ``None``. @@ -193,7 +187,7 @@ class TabGroup(html.HTMLElement): return filter(lambda t: self.get_tab(t.slug), self._tabs.values()) def get_selected_tab(self): - """ Returns the tab specific by the GET request parameter. + """Returns the tab specific by the GET request parameter. In the event that there is no GET request parameter, the value of the query parameter is invalid, or the tab is not allowed/enabled, @@ -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 @@ -265,7 +258,7 @@ class Tab(html.HTMLElement): return "<%s: %s>" % (self.__class__.__name__, self.slug) def is_active(self): - """ Method to access whether or not this tab is the active tab. """ + """Method to access whether or not this tab is the active tab.""" if self._active is None: self.tab_group._set_active_tab() return self._active @@ -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 diff --git a/horizon/tabs/views.py b/horizon/tabs/views.py index ef38a6e517..9ac1895a74 100644 --- a/horizon/tabs/views.py +++ b/horizon/tabs/views.py @@ -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. @@ -39,13 +39,13 @@ class TabView(generic.TemplateView): "on %s." % self.__class__.__name__) def get_tabs(self, request, **kwargs): - """ Returns the initialized tab group for this view. """ + """Returns the initialized tab group for this view.""" if self._tab_group is None: self._tab_group = self.tab_group_class(request, **kwargs) return self._tab_group def get_context_data(self, **kwargs): - """ Adds the ``tab_group`` variable to the context data. """ + """Adds the ``tab_group`` variable to the context data.""" context = super(TabView, self).get_context_data(**kwargs) try: tab_group = self.get_tabs(self.request, **kwargs) @@ -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. @@ -105,14 +103,13 @@ class TabbedTableView(tables.MultiTableMixin, TabView): 'tab': tab} def get_tables(self): - """ A no-op on this class. Tables are handled at the tab level. """ + """A no-op on this class. Tables are handled at the tab level.""" # Override the base class implementation so that the MultiTableMixin # doesn't freak out. We do the processing at the TableTab level. 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``. diff --git a/horizon/templatetags/horizon.py b/horizon/templatetags/horizon.py index 1ede4e4c62..7db45977be 100644 --- a/horizon/templatetags/horizon.py +++ b/horizon/templatetags/horizon.py @@ -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())) @@ -45,7 +44,7 @@ def has_permissions_on_list(components, user): @register.inclusion_tag('horizon/_nav_list.html', takes_context=True) def horizon_main_nav(context): - """ Generates top-level dashboard navigation entries. """ + """Generates top-level dashboard navigation entries.""" if 'request' not in context: return {} current_dashboard = context['request'].horizon.get('dashboard', None) @@ -63,7 +62,7 @@ def horizon_main_nav(context): @register.inclusion_tag('horizon/_subnav_list.html', takes_context=True) def horizon_dashboard_nav(context): - """ Generates sub-navigation entries for the current dashboard. """ + """Generates sub-navigation entries for the current dashboard.""" if 'request' not in context: return {} dashboard = context['request'].horizon['dashboard'] @@ -97,7 +96,7 @@ def quota(val, units=None): class JSTemplateNode(template.Node): - """ Helper node for the ``jstemplate`` template tag. """ + """Helper node for the ``jstemplate`` template tag.""" def __init__(self, nodelist): self.nodelist = nodelist @@ -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 diff --git a/horizon/templatetags/parse_date.py b/horizon/templatetags/parse_date.py index dbf71a1922..c2117559d0 100644 --- a/horizon/templatetags/parse_date.py +++ b/horizon/templatetags/parse_date.py @@ -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"] diff --git a/horizon/templatetags/sizeformat.py b/horizon/templatetags/sizeformat.py index e56ee785c6..9239450276 100644 --- a/horizon/templatetags/sizeformat.py +++ b/horizon/templatetags/sizeformat.py @@ -73,8 +73,9 @@ 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. """ + """Takes a size value in mb, and prints returns the data in a + saner unit. + """ if not mb: return 0 return filesizeformat(mb * 1024 * 1024, float_format) diff --git a/horizon/test/helpers.py b/horizon/test/helpers.py index 92f01de523..69fe4e4481 100644 --- a/horizon/test/helpers.py +++ b/horizon/test/helpers.py @@ -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)``. """ diff --git a/horizon/test/tests/base.py b/horizon/test/tests/base.py index 3feb459aba..0a8e0b8847 100644 --- a/horizon/test/tests/base.py +++ b/horizon/test/tests/base.py @@ -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() @@ -116,7 +115,7 @@ class BaseHorizonTests(test.TestCase): class HorizonTests(BaseHorizonTests): def test_registry(self): - """ Verify registration and autodiscovery work correctly. + """Verify registration and autodiscovery work correctly. Please note that this implicitly tests that autodiscovery works by virtue of the fact that the dashboards listed in @@ -210,12 +209,12 @@ class HorizonTests(BaseHorizonTests): reversed(urlpatterns) def test_horizon_test_isolation_1(self): - """ Isolation Test Part 1: sets a value. """ + """Isolation Test Part 1: sets a value.""" cats = horizon.get_dashboard("cats") cats.evil = True def test_horizon_test_isolation_2(self): - """ Isolation Test Part 2: The value set in part 1 should be gone. """ + """Isolation Test Part 2: The value set in part 1 should be gone.""" cats = horizon.get_dashboard("cats") self.assertFalse(hasattr(cats, "evil")) @@ -299,7 +298,7 @@ class HorizonTests(BaseHorizonTests): class CustomPanelTests(BaseHorizonTests): - """ Test customization of dashboards and panels + """Test customization of dashboards and panels using 'customization_module' to HORIZON_CONFIG. """ @@ -334,7 +333,7 @@ class CustomPanelTests(BaseHorizonTests): class CustomPermissionsTests(BaseHorizonTests): - """ Test customization of permissions on panels + """Test customization of permissions on panels using 'customization_module' to HORIZON_CONFIG. """ diff --git a/horizon/test/tests/tables.py b/horizon/test/tests/tables.py index a835d5b1ca..29d4c13607 100644 --- a/horizon/test/tests/tables.py +++ b/horizon/test/tests/tables.py @@ -190,7 +190,7 @@ class NoActionsTable(tables.DataTable): class DataTableTests(test.TestCase): def test_table_instantiation(self): - """ Tests everything that happens when the table is instantiated. """ + """Tests everything that happens when the table is instantiated.""" self.table = MyTable(self.request, TEST_DATA) # Properties defined on the table self.assertEqual(self.table.data, TEST_DATA) diff --git a/horizon/test/tests/templatetags.py b/horizon/test/tests/templatetags.py index 25df8b6b97..ec4e9cea45 100644 --- a/horizon/test/tests/templatetags.py +++ b/horizon/test/tests/templatetags.py @@ -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()) diff --git a/horizon/utils/fields.py b/horizon/utils/fields.py index bf06248c4d..d800e89e47 100644 --- a/horizon/utils/fields.py +++ b/horizon/utils/fields.py @@ -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 diff --git a/horizon/utils/filters.py b/horizon/utils/filters.py index dff17f6331..00efca07cb 100644 --- a/horizon/utils/filters.py +++ b/horizon/utils/filters.py @@ -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: diff --git a/horizon/utils/html.py b/horizon/utils/html.py index d2c7effc88..2003f32a4b 100644 --- a/horizon/utils/html.py +++ b/horizon/utils/html.py @@ -16,28 +16,25 @@ from django.forms.util import flatatt # noqa class HTMLElement(object): - """ A generic base class that gracefully handles html-style attributes. """ + """A generic base class that gracefully handles html-style attributes.""" def __init__(self): self.attrs = getattr(self, "attrs", {}) 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 diff --git a/horizon/utils/validators.py b/horizon/utils/validators.py index e62a7f13e1..bb7522eb26 100644 --- a/horizon/utils/validators.py +++ b/horizon/utils/validators.py @@ -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(':') diff --git a/horizon/views.py b/horizon/views.py index 5329224cc4..eb188a29ab 100644 --- a/horizon/views.py +++ b/horizon/views.py @@ -22,12 +22,12 @@ from horizon import exceptions def user_home(request): - """ Reversible named view to direct a user to the appropriate homepage. """ + """Reversible named view to direct a user to the appropriate homepage.""" return shortcuts.redirect(horizon.get_user_home(request.user)) class APIView(generic.TemplateView): - """ A quick class-based view for putting API data into a template. + """A quick class-based view for putting API data into a template. Subclasses must define one method, ``get_data``, and a template name via the ``template_name`` attribute on the class. @@ -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 " diff --git a/horizon/workflows/base.py b/horizon/workflows/base.py index 1bc93e333d..45f8fd3d84 100644 --- a/horizon/workflows/base.py +++ b/horizon/workflows/base.py @@ -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 @@ -154,7 +153,7 @@ class Action(forms.Form): bound_field.choices = meth(request, context) def get_help_text(self, extra_context=None): - """ Returns the help text for this step. """ + """Returns the help text for this step.""" text = "" extra_context = extra_context or {} if self.help_text_template: @@ -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. @@ -391,7 +384,7 @@ class Step(object): return context def get_id(self): - """ Returns the ID for this step. Suitable for use in HTML markup. """ + """Returns the ID for this step. Suitable for use in HTML markup.""" return "%s__%s" % (self.workflow.slug, self.slug) def _verify_contributions(self, context): @@ -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. @@ -427,7 +419,7 @@ class Step(object): return context def render(self): - """ Renders the step. """ + """Renders the step.""" step_template = template.loader.get_template(self.template_name) extra_context = {"form": self.action, "step": self} @@ -435,21 +427,17 @@ class Step(object): return step_template.render(context) def get_help_text(self): - """ Returns the help text for this step. """ + """Returns the help text for this step.""" text = linebreaks(force_unicode(self.help_text)) text += self.action.get_help_text() 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: @@ -665,7 +652,7 @@ class Workflow(html.HTMLElement): return self._ordered_steps def get_step(self, slug): - """ Returns the instantiated step matching the given slug. """ + """Returns the instantiated step matching the given slug.""" for step in self.steps: if step.slug == slug: return step @@ -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. @@ -736,7 +722,7 @@ class Workflow(html.HTMLElement): @classmethod def register(cls, step_class): - """ Registers a :class:`~horizon.workflows.Step` with the workflow. """ + """Registers a :class:`~horizon.workflows.Step` with the workflow.""" if not inspect.isclass(step_class): raise ValueError('Only classes may be registered.') elif not issubclass(step_class, cls._registerable_class): @@ -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 @@ -846,7 +825,7 @@ class Workflow(html.HTMLElement): return message def render(self): - """ Renders the workflow. """ + """Renders the workflow.""" workflow_template = template.loader.get_template(self.template_name) extra_context = {"workflow": self} if self.request.is_ajax(): @@ -855,7 +834,7 @@ class Workflow(html.HTMLElement): return workflow_template.render(context) def get_absolute_url(self): - """ Returns the canonical URL for this workflow. + """Returns the canonical URL for this workflow. This is used for the POST action attribute on the form element wrapping the workflow. @@ -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. diff --git a/horizon/workflows/views.py b/horizon/workflows/views.py index beb9db12d9..2208e04db9 100644 --- a/horizon/workflows/views.py +++ b/horizon/workflows/views.py @@ -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,14 +64,13 @@ 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) def get_workflow(self): - """ Returns the instanciated workflow class. """ + """Returns the instanciated workflow class.""" extra_context = self.get_initial() entry_point = self.request.GET.get("step", None) workflow = self.workflow_class(self.request, @@ -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. @@ -99,7 +96,7 @@ class WorkflowView(generic.TemplateView): return context def get_template_names(self): - """ Returns the template name to use for this request. """ + """Returns the template name to use for this request.""" if self.request.is_ajax(): template = self.ajax_template_name else: @@ -122,13 +119,13 @@ class WorkflowView(generic.TemplateView): workflow.add_error_to_step(error_msg, step) def get(self, request, *args, **kwargs): - """ Handler for HTTP GET requests. """ + """Handler for HTTP GET requests.""" context = self.get_context_data(**kwargs) self.set_workflow_step_errors(context) return self.render_to_response(context) def post(self, request, *args, **kwargs): - """ Handler for HTTP POST requests. """ + """Handler for HTTP POST requests.""" context = self.get_context_data(**kwargs) workflow = context[self.context_object_name] if workflow.is_valid(): diff --git a/openstack_dashboard/api/base.py b/openstack_dashboard/api/base.py index b4735795f4..3ad9cfb091 100644 --- a/openstack_dashboard/api/base.py +++ b/openstack_dashboard/api/base.py @@ -34,7 +34,7 @@ LOG = logging.getLogger(__name__) class APIVersionManager(object): - """ Object to store and manage API versioning data and utility methods. """ + """Object to store and manage API versioning data and utility methods.""" SETTINGS_KEY = "OPENSTACK_API_VERSIONS" @@ -67,10 +67,10 @@ 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 + Define _attrs on the child class and pass in the + api object as the only argument to the constructor """ _attrs = [] @@ -97,14 +97,14 @@ class APIResourceWrapper(object): class APIDictWrapper(object): - """ Simple wrapper for api dictionaries + """Simple wrapper for api dictionaries - Some api calls return dictionaries. This class provides identical - behavior as APIResourceWrapper, except that it will also behave as a - dictionary, in addition to attribute accesses. + Some api calls return dictionaries. This class provides identical + behavior as APIResourceWrapper, except that it will also behave as a + dictionary, in addition to attribute accesses. - Attribute access is the preferred method of access, to be - consistent with api resource objects from novaclient. + Attribute access is the preferred method of access, to be + consistent with api resource objects from novaclient. """ def __init__(self, apidict): self._apidict = apidict @@ -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) diff --git a/openstack_dashboard/api/ceilometer.py b/openstack_dashboard/api/ceilometer.py index 54f84757c4..d0be2c5de0 100644 --- a/openstack_dashboard/api/ceilometer.py +++ b/openstack_dashboard/api/ceilometer.py @@ -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))) @@ -34,7 +33,7 @@ def is_iterable(var): def make_query(user_id=None, tenant_id=None, resource_id=None, user_ids=None, tenant_ids=None, resource_ids=None): - """ Returns query built form given parameters. + """Returns query built form given parameters. This query can be then used for querying resources, meters and statistics. @@ -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'] @@ -140,7 +137,7 @@ class Resource(base.APIResourceWrapper): class ResourceAggregate(Resource): - """ Represents aggregate of more resources together. + """Represents aggregate of more resources together. Aggregate of resources can be obtain by specifing multiple ids in one parameter or by not specifying @@ -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', @@ -224,11 +219,11 @@ class Statistic(base.APIResourceWrapper): class GlobalDiskUsage(base.APIResourceWrapper): - """ Represents collection of resources with statistic of defined meters. + """Represents collection of resources with statistic of defined meters. - Resources are filtered either by given default query or by - meters in python. It's preferred to use default_query as it is more - effective. + Resources are filtered either by given default query or by + meters in python. It's preferred to use default_query as it is more + effective. """ _attrs = ["id", "tenant", "user", "resource", "disk_read_bytes", @@ -247,11 +242,11 @@ class GlobalDiskUsage(base.APIResourceWrapper): class GlobalNetworkTrafficUsage(base.APIResourceWrapper): - """ Represents collection of resources with statistic of defined meters. + """Represents collection of resources with statistic of defined meters. - Resources are filtered either by given default query or by - meters in python. It's preferred to use default_query as it is more - effective. + Resources are filtered either by given default query or by + meters in python. It's preferred to use default_query as it is more + effective. """ _attrs = ["id", "tenant", "user", "resource", "network_incoming_bytes", @@ -270,11 +265,11 @@ class GlobalNetworkTrafficUsage(base.APIResourceWrapper): class GlobalNetworkUsage(base.APIResourceWrapper): - """ Represents collection of resources with statistic of defined meters. + """Represents collection of resources with statistic of defined meters. - Resources are filtered either by given default query or by - meters in python. It's preferred to use default_query as it is more - effective. + Resources are filtered either by given default query or by + meters in python. It's preferred to use default_query as it is more + effective. """ _attrs = ["id", "tenant", "user", "resource", "network", "network_create", @@ -294,11 +289,11 @@ class GlobalNetworkUsage(base.APIResourceWrapper): class GlobalObjectStoreUsage(base.APIResourceWrapper): - """ Represents collection of resources with statistic of defined meters. + """Represents collection of resources with statistic of defined meters. - Resources are filtered either by given default query or by - meters in python. It's preferred to use default_query as it is more - effective. + Resources are filtered either by given default query or by + meters in python. It's preferred to use default_query as it is more + effective. """ _attrs = ["id", "tenant", "user", "resource", "storage_objects", @@ -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) @@ -359,8 +353,8 @@ def statistic_list(request, meter_name, query=None, period=None): class ThreadedUpdateResourceWithStatistics(threading.Thread): - """ Multithread wrapper for update_with_statistics method of - resource_usage. + """Multithread wrapper for update_with_statistics method of + resource_usage. A join logic is placed in process_list class method. All resources will have its statistics attribute filled in separate threads. @@ -426,7 +420,7 @@ class ThreadedUpdateResourceWithStatistics(threading.Thread): class CeilometerUsage(object): - """ Represents wrapper of any Ceilometer queries. + """Represents wrapper of any Ceilometer queries. One instance of this class should be shared between resources as this class provides a place where users and tenants are @@ -448,7 +442,7 @@ class CeilometerUsage(object): self._tenants = {} def get_user(self, user_id): - """ Returns user fetched form API + """Returns user fetched form API Caching the result, so it doesn't contact API twice with the same query @@ -462,7 +456,7 @@ class CeilometerUsage(object): return user def preload_all_users(self): - """ Preloads all users into dictionary. + """Preloads all users into dictionary. It's more effective to preload all users, rather the fetching many users by separate API get calls. @@ -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 @@ -489,7 +483,7 @@ class CeilometerUsage(object): return tenant def preload_all_tenants(self): - """ Preloads all teannts into dictionary. + """Preloads all teannts into dictionary. It's more effective to preload all tenants, rather the fetching many tenants by separate API get calls. @@ -504,7 +498,7 @@ class CeilometerUsage(object): def global_data_get(self, used_cls=None, query=None, with_statistics=False, additional_query=None, with_users_and_tenants=True): - """ Obtaining a resources for table view. + """Obtaining a resources for table view. It obtains resources with statistics data according to declaration in used_cls class. @@ -534,10 +528,9 @@ class CeilometerUsage(object): filter_func = None def filter_resources(resource): - """ Method for filtering resources by theirs links.rel attr. + """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, @@ -577,7 +569,7 @@ class CeilometerUsage(object): def global_network_traffic_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=GlobalNetworkTrafficUsage, @@ -587,7 +579,7 @@ class CeilometerUsage(object): def global_network_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=GlobalNetworkUsage, @@ -597,7 +589,7 @@ class CeilometerUsage(object): def global_object_store_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. """ # TODO(lsmola) This call uses all tenants now. When ajax pagination # is added, it needs to obtain only paginated tenants. @@ -609,7 +601,7 @@ class CeilometerUsage(object): additional_query=additional_query) def query_from_object_id(self, object_id): - """ Obtaining a query from resource id. + """Obtaining a query from resource id. Query can be then used to identify a resource in resources or meters API calls. ID is being built in the Resource initializer, or returned @@ -625,7 +617,7 @@ class CeilometerUsage(object): def update_with_statistics(self, resource, meter_names=None, period=None, stats_attr=None, additional_query=None): - """ Adding statistical data into one Resource or ResourceAggregate. + """Adding statistical data into one Resource or ResourceAggregate. It adds each statistic of each meter_names into the resource attributes. Attribute name is the meter name with replaced '.' to '_'. @@ -684,7 +676,7 @@ class CeilometerUsage(object): def resources(self, query=None, filter_func=None, with_users_and_tenants=False): - """ Obtaining resources with the query or filter_func. + """Obtaining resources with the query or filter_func. Obtains resources and also fetch tenants and users associated with those resources if with_users_and_tenants flag is true. @@ -712,7 +704,7 @@ class CeilometerUsage(object): period=None, filter_func=None, stats_attr=None, additional_query=None, with_users_and_tenants=False): - """ Obtaining resources with statistics data inside. + """Obtaining resources with statistics data inside. :Parameters: - `query`: Query for fetching the Ceilometer Resources. @@ -745,7 +737,7 @@ class CeilometerUsage(object): return resources def resource_aggregates(self, queries=None): - """ Obtaining resource aggregates with queries. + """Obtaining resource aggregates with queries. Representing a resource aggregate by query is a most general way how to obtain a resource aggregates. @@ -764,7 +756,7 @@ class CeilometerUsage(object): def resource_aggregates_with_statistics(self, queries=None, meter_names=None, period=None, filter_func=None, stats_attr=None, additional_query=None): - """ Obtaining resource aggregates with statistics data inside. + """Obtaining resource aggregates with statistics data inside. :Parameters: - `queries`: Dictionary of named queries that defines a bulk of diff --git a/openstack_dashboard/api/cinder.py b/openstack_dashboard/api/cinder.py index 75801c83a0..62634cbb3f 100644 --- a/openstack_dashboard/api/cinder.py +++ b/openstack_dashboard/api/cinder.py @@ -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: diff --git a/openstack_dashboard/api/fwaas.py b/openstack_dashboard/api/fwaas.py index e2f327b558..13d2f85a0f 100644 --- a/openstack_dashboard/api/fwaas.py +++ b/openstack_dashboard/api/fwaas.py @@ -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 diff --git a/openstack_dashboard/api/glance.py b/openstack_dashboard/api/glance.py index dc500fd429..d0c1cca639 100644 --- a/openstack_dashboard/api/glance.py +++ b/openstack_dashboard/api/glance.py @@ -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) diff --git a/openstack_dashboard/api/keystone.py b/openstack_dashboard/api/keystone.py index 16dbfb5ec1..3bb3825e8e 100644 --- a/openstack_dashboard/api/keystone.py +++ b/openstack_dashboard/api/keystone.py @@ -74,7 +74,7 @@ except ImportError: class Service(base.APIDictWrapper): - """ Wrapper for a dict based on the service data from keystone. """ + """Wrapper for a dict based on the service data from keystone.""" _attrs = ['id', 'type', 'name'] def __init__(self, service, region, *args, **kwargs): @@ -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. """ @@ -482,7 +481,7 @@ def role_delete(request, role_id): def role_list(request): - """ Returns a global list of available roles. """ + """Returns a global list of available roles.""" return keystoneclient(request, admin=True).roles.list() @@ -496,7 +495,7 @@ def roles_for_user(request, user, project): def add_tenant_user_role(request, project=None, user=None, role=None, group=None, domain=None): - """ Adds a role for a user on a tenant. """ + """Adds a role for a user on a tenant.""" manager = keystoneclient(request, admin=True).roles if VERSIONS.active < 3: return manager.add_user_role(user, role, project) @@ -507,7 +506,7 @@ def add_tenant_user_role(request, project=None, user=None, role=None, def remove_tenant_user_role(request, project=None, user=None, role=None, group=None, domain=None): - """ Removes a given single role for a user from a tenant. """ + """Removes a given single role for a user from a tenant.""" manager = keystoneclient(request, admin=True).roles if VERSIONS.active < 3: return manager.remove_user_role(user, role, project) @@ -517,7 +516,7 @@ def remove_tenant_user_role(request, project=None, user=None, role=None, def remove_tenant_user(request, project=None, user=None, domain=None): - """ Removes all roles from a user on a tenant, removing them from it. """ + """Removes all roles from a user on a tenant, removing them from it.""" client = keystoneclient(request, admin=True) roles = client.roles.roles_for_user(user, project) for role in roles: @@ -531,22 +530,22 @@ def roles_for_group(request, group, domain=None, project=None): def add_group_role(request, role, group, domain=None, project=None): - """ Adds a role for a group on a domain or project .""" + """Adds a role for a group on a domain or project.""" manager = keystoneclient(request, admin=True).roles return manager.grant(role=role, group=group, domain=domain, project=project) def remove_group_role(request, role, group, domain=None, project=None): - """ Removes a given single role for a group from a domain or project. """ + """Removes a given single role for a group from a domain or project.""" manager = keystoneclient(request, admin=True).roles return manager.revoke(role=role, group=group, project=project, domain=domain) def remove_group_roles(request, group, domain=None, project=None): - """ Removes all roles from a group on a domain or project, - removing them from it. + """Removes all roles from a group on a domain or project, + removing them from it. """ client = keystoneclient(request, admin=True) roles = client.roles.list(group=group, domain=domain, project=project) @@ -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. """ diff --git a/openstack_dashboard/api/lbaas.py b/openstack_dashboard/api/lbaas.py index e8dafee192..008259ee0c 100644 --- a/openstack_dashboard/api/lbaas.py +++ b/openstack_dashboard/api/lbaas.py @@ -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) diff --git a/openstack_dashboard/api/neutron.py b/openstack_dashboard/api/neutron.py index 3bc8d821d1..4a688051e0 100644 --- a/openstack_dashboard/api/neutron.py +++ b/openstack_dashboard/api/neutron.py @@ -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 diff --git a/openstack_dashboard/api/nova.py b/openstack_dashboard/api/nova.py index 1a6afbc71f..fd61db8c61 100644 --- a/openstack_dashboard/api/nova.py +++ b/openstack_dashboard/api/nova.py @@ -166,7 +166,7 @@ class SecurityGroup(base.APIResourceWrapper): class SecurityGroupRule(base.APIResourceWrapper): - """ Wrapper for individual rules in a SecurityGroup. """ + """Wrapper for individual rules in a SecurityGroup.""" _attrs = ['id', 'ip_protocol', 'from_port', 'to_port', 'ip_range', 'group'] def __unicode__(self): @@ -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. """ diff --git a/openstack_dashboard/api/swift.py b/openstack_dashboard/api/swift.py index 115ee46a0e..f5e0a200dd 100644 --- a/openstack_dashboard/api/swift.py +++ b/openstack_dashboard/api/swift.py @@ -75,7 +75,7 @@ class PseudoFolder(base.APIDictWrapper): def _objectify(items, container_name): - """ Splits a listing of objects into their appropriate wrapper classes. """ + """Splits a listing of objects into their appropriate wrapper classes.""" objects = [] # Deal with objects and object pseudo-folders first, save subdirs for later diff --git a/openstack_dashboard/api/trove.py b/openstack_dashboard/api/trove.py index 9c7423d896..b6fc56866d 100644 --- a/openstack_dashboard/api/trove.py +++ b/openstack_dashboard/api/trove.py @@ -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): diff --git a/openstack_dashboard/context_processors.py b/openstack_dashboard/context_processors.py index 3ed396b0b9..ae83a1074c 100644 --- a/openstack_dashboard/context_processors.py +++ b/openstack_dashboard/context_processors.py @@ -25,7 +25,7 @@ from django.conf import settings # noqa def openstack(request): - """ Context processor necessary for OpenStack Dashboard functionality. + """Context processor necessary for OpenStack Dashboard functionality. The following variables are added to the request context: diff --git a/openstack_dashboard/dashboards/admin/domains/tables.py b/openstack_dashboard/dashboards/admin/domains/tables.py index 0a4f6188b2..a86cead935 100644 --- a/openstack_dashboard/dashboards/admin/domains/tables.py +++ b/openstack_dashboard/dashboards/admin/domains/tables.py @@ -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): diff --git a/openstack_dashboard/dashboards/admin/flavors/tables.py b/openstack_dashboard/dashboards/admin/flavors/tables.py index 557ad57919..72cfec2c1f 100644 --- a/openstack_dashboard/dashboards/admin/flavors/tables.py +++ b/openstack_dashboard/dashboards/admin/flavors/tables.py @@ -72,7 +72,7 @@ class ModifyAccess(tables.LinkAction): class FlavorFilterAction(tables.FilterAction): def filter(self, table, flavors, filter_string): - """ Really naive case-insensitive search. """ + """Really naive case-insensitive search.""" q = filter_string.lower() def comp(flavor): diff --git a/openstack_dashboard/dashboards/admin/groups/tables.py b/openstack_dashboard/dashboards/admin/groups/tables.py index bce8f5008b..b5614ae40a 100644 --- a/openstack_dashboard/dashboards/admin/groups/tables.py +++ b/openstack_dashboard/dashboards/admin/groups/tables.py @@ -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() diff --git a/openstack_dashboard/dashboards/admin/images/views.py b/openstack_dashboard/dashboards/admin/images/views.py index 41b302434b..456c7c2e19 100644 --- a/openstack_dashboard/dashboards/admin/images/views.py +++ b/openstack_dashboard/dashboards/admin/images/views.py @@ -68,5 +68,5 @@ class UpdateView(views.UpdateView): class DetailView(views.DetailView): - """ Admin placeholder for image detail view. """ + """Admin placeholder for image detail view.""" pass diff --git a/openstack_dashboard/dashboards/admin/instances/tables.py b/openstack_dashboard/dashboards/admin/instances/tables.py index d75cfa3c6e..0a49aad672 100644 --- a/openstack_dashboard/dashboards/admin/instances/tables.py +++ b/openstack_dashboard/dashboards/admin/instances/tables.py @@ -60,7 +60,7 @@ class AdminUpdateRow(project_tables.UpdateRow): class AdminInstanceFilterAction(tables.FilterAction): def filter(self, table, instances, filter_string): - """ Naive case-insensitive search. """ + """Naive case-insensitive search.""" q = filter_string.lower() return [instance for instance in instances if q in instance.name.lower()] diff --git a/openstack_dashboard/dashboards/admin/metering/tabs.py b/openstack_dashboard/dashboards/admin/metering/tabs.py index 04f3ca1a80..24745cf0f1 100644 --- a/openstack_dashboard/dashboards/admin/metering/tabs.py +++ b/openstack_dashboard/dashboards/admin/metering/tabs.py @@ -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) @@ -214,7 +214,7 @@ class GlobalStatsTab(tabs.Tab): meter_titles[name] = hint class MetersWrap(object): - """ A quick wrapper for meter and associated titles. """ + """A quick wrapper for meter and associated titles.""" def __init__(self, meter, meter_titles): self.name = meter self.title = meter_titles.get(meter, "") diff --git a/openstack_dashboard/dashboards/admin/metering/views.py b/openstack_dashboard/dashboards/admin/metering/views.py index b28b325d73..e79ff781f7 100644 --- a/openstack_dashboard/dashboards/admin/metering/views.py +++ b/openstack_dashboard/dashboards/admin/metering/views.py @@ -174,7 +174,7 @@ class SamplesView(TemplateView): query = [] def filter_by_meter_name(resource): - """ Function for filtering of the list of resources. + """Function for filtering of the list of resources. Will pick the right resources according to currently selected meter. diff --git a/openstack_dashboard/dashboards/admin/projects/tables.py b/openstack_dashboard/dashboards/admin/projects/tables.py index 77b8b79f2a..cce59339c0 100644 --- a/openstack_dashboard/dashboards/admin/projects/tables.py +++ b/openstack_dashboard/dashboards/admin/projects/tables.py @@ -109,7 +109,7 @@ class DeleteTenantsAction(tables.DeleteAction): class TenantFilterAction(tables.FilterAction): def filter(self, table, tenants, filter_string): - """ Really naive case-insensitive search. """ + """Really naive case-insensitive search.""" # FIXME(gabriel): This should be smarter. Written for demo purposes. q = filter_string.lower() diff --git a/openstack_dashboard/dashboards/admin/roles/tables.py b/openstack_dashboard/dashboards/admin/roles/tables.py index 37e731f0d4..ace953d271 100644 --- a/openstack_dashboard/dashboards/admin/roles/tables.py +++ b/openstack_dashboard/dashboards/admin/roles/tables.py @@ -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()] diff --git a/openstack_dashboard/dashboards/admin/users/tables.py b/openstack_dashboard/dashboards/admin/users/tables.py index ab153d4d08..cfbc903d02 100644 --- a/openstack_dashboard/dashboards/admin/users/tables.py +++ b/openstack_dashboard/dashboards/admin/users/tables.py @@ -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() diff --git a/openstack_dashboard/dashboards/admin/volumes/tables.py b/openstack_dashboard/dashboards/admin/volumes/tables.py index 8d32f4d365..c68314a0ad 100644 --- a/openstack_dashboard/dashboards/admin/volumes/tables.py +++ b/openstack_dashboard/dashboards/admin/volumes/tables.py @@ -36,7 +36,7 @@ class DeleteVolumeType(tables.DeleteAction): class VolumesFilterAction(tables.FilterAction): def filter(self, table, volumes, filter_string): - """ Naive case-insensitive search. """ + """Naive case-insensitive search.""" q = filter_string.lower() return [volume for volume in volumes if q in volume.display_name.lower()] diff --git a/openstack_dashboard/dashboards/project/containers/tables.py b/openstack_dashboard/dashboards/project/containers/tables.py index 786b942c8f..f641832da7 100644 --- a/openstack_dashboard/dashboards/project/containers/tables.py +++ b/openstack_dashboard/dashboards/project/containers/tables.py @@ -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) diff --git a/openstack_dashboard/dashboards/project/containers/views.py b/openstack_dashboard/dashboards/project/containers/views.py index d1ac13d082..f696377590 100644 --- a/openstack_dashboard/dashboards/project/containers/views.py +++ b/openstack_dashboard/dashboards/project/containers/views.py @@ -61,7 +61,7 @@ class ContainerView(browsers.ResourceBrowserView): @cached_property def objects(self): - """ Returns a list of objects given the subfolder's path. + """Returns a list of objects given the subfolder's path. The path is from the kwargs of the request. """ @@ -93,13 +93,13 @@ class ContainerView(browsers.ResourceBrowserView): return getattr(item, "content_type", None) == content_type def get_objects_data(self): - """ Returns a list of objects within the current folder. """ + """Returns a list of objects within the current folder.""" filtered_objects = [item for item in self.objects if not self.is_subdir(item)] return filtered_objects def get_subfolders_data(self): - """ Returns a list of subfolders within the current folder. """ + """Returns a list of subfolders within the current folder.""" filtered_objects = [item for item in self.objects if self.is_subdir(item)] return filtered_objects diff --git a/openstack_dashboard/dashboards/project/databases/workflows/create_instance.py b/openstack_dashboard/dashboards/project/databases/workflows/create_instance.py index e3342f73f3..c8d8ba44c9 100644 --- a/openstack_dashboard/dashboards/project/databases/workflows/create_instance.py +++ b/openstack_dashboard/dashboards/project/databases/workflows/create_instance.py @@ -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 = [] diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/images/tests.py b/openstack_dashboard/dashboards/project/images_and_snapshots/images/tests.py index b2f6bd2d10..f5181f9444 100644 --- a/openstack_dashboard/dashboards/project/images_and_snapshots/images/tests.py +++ b/openstack_dashboard/dashboards/project/images_and_snapshots/images/tests.py @@ -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({}) diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/utils.py b/openstack_dashboard/dashboards/project/images_and_snapshots/utils.py index 3d454e822d..ad26ac5ef9 100644 --- a/openstack_dashboard/dashboards/project/images_and_snapshots/utils.py +++ b/openstack_dashboard/dashboards/project/images_and_snapshots/utils.py @@ -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. diff --git a/openstack_dashboard/dashboards/project/instances/tables.py b/openstack_dashboard/dashboards/project/instances/tables.py index 6424c3df4a..ccf4dc64c0 100644 --- a/openstack_dashboard/dashboards/project/instances/tables.py +++ b/openstack_dashboard/dashboards/project/instances/tables.py @@ -548,7 +548,7 @@ TASK_DISPLAY_CHOICES = ( class InstancesFilterAction(tables.FilterAction): def filter(self, table, instances, filter_string): - """ Naive case-insensitive search. """ + """Naive case-insensitive search.""" q = filter_string.lower() return [instance for instance in instances if q in instance.name.lower()] diff --git a/openstack_dashboard/dashboards/project/instances/workflows/create_instance.py b/openstack_dashboard/dashboards/project/instances/workflows/create_instance.py index 94da6c185f..e2e322aee2 100644 --- a/openstack_dashboard/dashboards/project/instances/workflows/create_instance.py +++ b/openstack_dashboard/dashboards/project/instances/workflows/create_instance.py @@ -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', {}) diff --git a/openstack_dashboard/dashboards/project/networks/workflows.py b/openstack_dashboard/dashboards/project/networks/workflows.py index e8e3b087b8..54180f1956 100644 --- a/openstack_dashboard/dashboards/project/networks/workflows.py +++ b/openstack_dashboard/dashboards/project/networks/workflows.py @@ -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" ' diff --git a/openstack_dashboard/dashboards/project/routers/extensions/routerrules/forms.py b/openstack_dashboard/dashboards/project/routers/extensions/routerrules/forms.py index d5e58b761a..fdb4eb3a14 100644 --- a/openstack_dashboard/dashboards/project/routers/extensions/routerrules/forms.py +++ b/openstack_dashboard/dashboards/project/routers/extensions/routerrules/forms.py @@ -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 diff --git a/openstack_dashboard/dashboards/project/stacks/forms.py b/openstack_dashboard/dashboards/project/stacks/forms.py index f25ec53301..0370f96164 100644 --- a/openstack_dashboard/dashboards/project/stacks/forms.py +++ b/openstack_dashboard/dashboards/project/stacks/forms.py @@ -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' diff --git a/openstack_dashboard/dashboards/project/stacks/mappings.py b/openstack_dashboard/dashboards/project/stacks/mappings.py index 0353291248..c6e5acf93e 100644 --- a/openstack_dashboard/dashboards/project/stacks/mappings.py +++ b/openstack_dashboard/dashboards/project/stacks/mappings.py @@ -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 diff --git a/openstack_dashboard/dashboards/project/volumes/tables.py b/openstack_dashboard/dashboards/project/volumes/tables.py index 8d235819b4..f006c135d4 100644 --- a/openstack_dashboard/dashboards/project/volumes/tables.py +++ b/openstack_dashboard/dashboards/project/volumes/tables.py @@ -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): @@ -184,7 +185,7 @@ class VolumesTableBase(tables.DataTable): class VolumesFilterAction(tables.FilterAction): def filter(self, table, volumes, filter_string): - """ Naive case-insensitive search. """ + """Naive case-insensitive search.""" q = filter_string.lower() return [volume for volume in volumes if q in volume.display_name.lower()] @@ -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): diff --git a/openstack_dashboard/dashboards/router/nexus1000v/forms.py b/openstack_dashboard/dashboards/router/nexus1000v/forms.py index 53f5d936ce..3b6faa70e7 100644 --- a/openstack_dashboard/dashboards/router/nexus1000v/forms.py +++ b/openstack_dashboard/dashboards/router/nexus1000v/forms.py @@ -46,7 +46,7 @@ def get_tenant_choices(request): class CreateNetworkProfile(forms.SelfHandlingForm): - """ Create Network Profile form.""" + """Create Network Profile form.""" name = forms.CharField(max_length=255, label=_("Name"), @@ -115,7 +115,7 @@ class CreateNetworkProfile(forms.SelfHandlingForm): class UpdateNetworkProfile(forms.SelfHandlingForm): - """ Update Network Profile form.""" + """Update Network Profile form.""" profile_id = forms.CharField(label=_("ID"), widget=forms.HiddenInput()) diff --git a/openstack_dashboard/policy.py b/openstack_dashboard/policy.py index 75b228f741..6e41ca61f3 100644 --- a/openstack_dashboard/policy.py +++ b/openstack_dashboard/policy.py @@ -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. diff --git a/openstack_dashboard/test/api_tests/base_tests.py b/openstack_dashboard/test/api_tests/base_tests.py index ccf8966b71..c8c8657580 100644 --- a/openstack_dashboard/test/api_tests/base_tests.py +++ b/openstack_dashboard/test/api_tests/base_tests.py @@ -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') diff --git a/openstack_dashboard/test/api_tests/keystone_tests.py b/openstack_dashboard/test/api_tests/keystone_tests.py index 02223d4540..3ee9ebe315 100644 --- a/openstack_dashboard/test/api_tests/keystone_tests.py +++ b/openstack_dashboard/test/api_tests/keystone_tests.py @@ -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. diff --git a/openstack_dashboard/test/helpers.py b/openstack_dashboard/test/helpers.py index 0aefdadd48..22603332d1 100644 --- a/openstack_dashboard/test/helpers.py +++ b/openstack_dashboard/test/helpers.py @@ -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): diff --git a/openstack_dashboard/test/test_data/utils.py b/openstack_dashboard/test/test_data/utils.py index 6707f3d9df..5f8ac13ceb 100644 --- a/openstack_dashboard/test/test_data/utils.py +++ b/openstack_dashboard/test/test_data/utils.py @@ -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. @@ -79,7 +78,7 @@ class TestData(object): class TestDataContainer(object): - """ A container for test data objects. + """A container for test data objects. The behavior of this class is meant to mimic a "manager" class, which has convenient shortcuts for common actions like "list", "filter", "get", @@ -89,7 +88,7 @@ class TestDataContainer(object): self._objects = [] def add(self, *args): - """ Add a new object to this container. + """Add a new object to this container. Generally this method should only be used during data loading, since adding data during a test can affect the results of other tests. @@ -99,12 +98,11 @@ class TestDataContainer(object): self._objects.append(obj) def list(self): - """ Returns a list of all objects in this container. """ + """Returns a list of all objects in this container.""" 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. """ @@ -135,7 +132,7 @@ class TestDataContainer(object): return matches.pop() def first(self): - """ Returns the first object from this container. """ + """Returns the first object from this container.""" return self._objects[0] def count(self): diff --git a/openstack_dashboard/test/tests/error_pages.py b/openstack_dashboard/test/tests/error_pages.py index 8d910ef731..c6a1661215 100644 --- a/openstack_dashboard/test/tests/error_pages.py +++ b/openstack_dashboard/test/tests/error_pages.py @@ -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): diff --git a/openstack_dashboard/test/tests/templates.py b/openstack_dashboard/test/tests/templates.py index 91331e1252..1d791eb365 100644 --- a/openstack_dashboard/test/tests/templates.py +++ b/openstack_dashboard/test/tests/templates.py @@ -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 = { diff --git a/openstack_dashboard/usage/base.py b/openstack_dashboard/usage/base.py index a697b34f6d..9291876749 100644 --- a/openstack_dashboard/usage/base.py +++ b/openstack_dashboard/usage/base.py @@ -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): diff --git a/openstack_dashboard/usage/quotas.py b/openstack_dashboard/usage/quotas.py index 6b4e9202ab..0fe6aca70a 100644 --- a/openstack_dashboard/usage/quotas.py +++ b/openstack_dashboard/usage/quotas.py @@ -60,7 +60,7 @@ QUOTA_FIELDS = NOVA_QUOTA_FIELDS + CINDER_QUOTA_FIELDS + NEUTRON_QUOTA_FIELDS class QuotaUsage(dict): - """ Tracks quota limit, used, and available for a given set of quotas.""" + """Tracks quota limit, used, and available for a given set of quotas.""" def __init__(self): self.usages = defaultdict(dict) @@ -77,7 +77,7 @@ class QuotaUsage(dict): return repr(dict(self.usages)) def add_quota(self, quota): - """ Adds an internal tracking reference for the given quota. """ + """Adds an internal tracking reference for the given quota.""" if quota.limit is None or quota.limit == -1: # Handle "unlimited" quotas. self.usages[quota.name]['quota'] = float("inf") @@ -86,7 +86,7 @@ class QuotaUsage(dict): self.usages[quota.name]['quota'] = int(quota.limit) def tally(self, name, value): - """ Adds to the "used" metric for the given quota. """ + """Adds to the "used" metric for the given quota.""" value = value or 0 # Protection against None. # Start at 0 if this is the first value. if 'used' not in self.usages[name]: @@ -96,7 +96,7 @@ class QuotaUsage(dict): self.update_available(name) def update_available(self, name): - """ Updates the "available" metric for the given quota. """ + """Updates the "available" metric for the given quota.""" available = self.usages[name]['quota'] - self.usages[name]['used'] if available < 0: available = 0 diff --git a/tox.ini b/tox.ini index 27413e26df..23ad8d6a0b 100644 --- a/tox.ini +++ b/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