diff --git a/.gitignore b/.gitignore deleted file mode 100644 index fbfa355..0000000 --- a/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -# Compiled files -*.py[co] -*.a -*.o -*.so - -# Sphinx -_build - -# Packages/installer info -*.egg -*.egg-info -dist -build -eggs -parts -bin -var -sdist -develop-eggs -.installed.cfg - -# Other -.testrepository -.tox -.*.swp -.coverage -cover -AUTHORS -ChangeLog - -# Editors -*~ diff --git a/.gitreview b/.gitreview deleted file mode 100644 index 6eb747d..0000000 --- a/.gitreview +++ /dev/null @@ -1,4 +0,0 @@ -[gerrit] -host=review.openstack.org -port=29418 -project=openstack-dev/hacking.git diff --git a/.mailmap b/.mailmap deleted file mode 100644 index 114bb10..0000000 --- a/.mailmap +++ /dev/null @@ -1,3 +0,0 @@ -# Format is: -# Name -Joe Gordon diff --git a/.testr.conf b/.testr.conf deleted file mode 100644 index 748029b..0000000 --- a/.testr.conf +++ /dev/null @@ -1,8 +0,0 @@ -[DEFAULT] -test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ - OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ - OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ - ${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION - -test_id_option=--load-list $IDFILE -test_list_option=--list diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index 2c01362..0000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,16 +0,0 @@ -If you would like to contribute to the development of OpenStack, -you must follow the steps in this page: - - http://docs.openstack.org/infra/manual/developers.html - -Once those steps have been completed, changes to OpenStack -should be submitted for review via the Gerrit tool, following -the workflow documented at: - - http://docs.openstack.org/infra/manual/developers.html#development-workflow - -Pull requests submitted through GitHub will be ignored. - -Bugs should be filed on Launchpad, not GitHub: - - https://bugs.launchpad.net/hacking diff --git a/HACKING.rst b/HACKING.rst deleted file mode 100644 index a7cd30f..0000000 --- a/HACKING.rst +++ /dev/null @@ -1,352 +0,0 @@ -.. _StyleGuide: - -OpenStack Style Guidelines -========================== - -OpenStack has a set of style guidelines for clarity. OpenStack is a -very large code base (over 1 Million lines of python), spanning dozens -of git trees, with over a thousand developers contributing every 12 -months. As such common style helps developers understand code in -reviews, move between projects smoothly, and overall make the code -more maintainable. - - -Step 0 ------- - -- Step 1: Read `pep8`_ -- Step 2: Read `pep8`_ again -- Step 3: Read on - -.. _`pep8`: http://www.python.org/dev/peps/pep-0008/ - -General -------- -- [H903] Use only UNIX style newlines (``\n``), not Windows style (``\r\n``) -- It is preferred to wrap long lines in parentheses and not a backslash - for line continuation. -- [H201] Do not write ``except:``, use ``except Exception:`` at the very least. - When catching an exception you should be as specific so you don't mistakenly - catch unexpected exceptions. -- [H101] Include your name with TODOs as in ``# TODO(yourname)``. This makes - it easier to find out who the author of the comment was. -- [H105] Don't use author tags. We use version control instead. -- [H106] Don't put vim configuration in source files (off by default). -- [H904] Delay string interpolations at logging calls (off by default). -- Do not shadow a built-in or reserved word. Shadowing built -in or reserved - words makes the code harder to understand. Example:: - - def list(): - return [1, 2, 3] - - mylist = list() # BAD, shadows `list` built-in - - class Foo(object): - def list(self): - return [1, 2, 3] - - mylist = Foo().list() # OKAY, does not shadow built-in - - -Imports -------- - -- Do not import objects, only modules (*) -- [H301] Do not import more than one module per line (*) -- [H303] Do not use wildcard ``*`` import (*) -- [H304] Do not make relative imports -- [H306] Alphabetically order your imports by the full module path. - Organize your imports according to the `Import order - template`_ and `Real-world Import Order Examples`_ below. - -(*) exceptions are: - -- imports from ``migrate`` package -- imports from ``sqlalchemy`` package -- function imports from ``i18n`` module - -Import order template -^^^^^^^^^^^^^^^^^^^^^ - -:: - - {{stdlib imports in human alphabetical order}} - \n - {{third-party lib imports in human alphabetical order}} - \n - {{project imports in human alphabetical order}} - \n - \n - {{begin your code}} - -Real-world Import Order Examples -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Example:: - - import httplib - import logging - import random - import StringIO - import time - import unittest - - import eventlet - import webob.exc - - import nova.api.ec2 - from nova.api import manager - from nova.api import openstack - from nova.auth import users - from nova.endpoint import cloud - import nova.flags - from nova.i18n import _, _LC - from nova import test - - -Docstrings ----------- -- [H401] Docstrings should not start with a space. -- [H403] Multi line docstrings should end on a new line. -- [H404] Multi line docstrings should start without a leading new line. -- [H405] Multi line docstrings should start with a one line summary followed - by an empty line. - -Example:: - - """A multi line docstring has a one-line summary, less than 80 characters. - - Then a new paragraph after a newline that explains in more detail any - general information about the function, class or method. Example usages - are also great to have here if it is a complex class or function. - - When writing the docstring for a class, an extra line should be placed - after the closing quotations. For more in-depth explanations for these - decisions see http://www.python.org/dev/peps/pep-0257/ - - If you are going to describe parameters and return values, use Sphinx, the - appropriate syntax is as follows. - - :param foo: the foo parameter - :param bar: the bar parameter - :returns: return_type -- description of the return value - :returns: description of the return value - :raises: AttributeError, KeyError - """ - - -Dictionaries/Lists ------------------- -If a dictionary (dict) or list object is longer than 80 characters, its items -should be split with newlines. Embedded iterables should have their items -indented. Additionally, the last item in the dictionary should have a trailing -comma. This increases readability and simplifies future diffs. - -Example:: - - my_dictionary = { - "image": { - "name": "Just a Snapshot", - "size": 2749573, - "properties": { - "user_id": 12, - "arch": "x86_64", - }, - "things": [ - "thing_one", - "thing_two", - ], - "status": "ACTIVE", - }, - } - - -- [H501] Do not use ``locals()`` or ``self.__dict__`` for formatting strings, - it is not clear as using explicit dictionaries and can hide errors during - refactoring. - -Calling Methods ---------------- -Calls to methods 80 characters or longer should format each argument with -newlines. This is not a requirement, but a guideline:: - - unnecessarily_long_function_name('string one', - 'string two', - kwarg1=constants.ACTIVE, - kwarg2=['a', 'b', 'c']) - - -Rather than constructing parameters inline, it is better to break things up:: - - list_of_strings = [ - 'what_a_long_string', - 'not as long', - ] - - dict_of_numbers = { - 'one': 1, - 'two': 2, - 'twenty four': 24, - } - - object_one.call_a_method('string three', - 'string four', - kwarg1=list_of_strings, - kwarg2=dict_of_numbers) - - -Internationalization (i18n) Strings ------------------------------------ -In order to support multiple languages, we have a mechanism to support -automatic translations of exception and log strings. - -Example:: - - msg = _("An error occurred") - raise HTTPBadRequest(explanation=msg) - -- [H702] If you have a variable to place within the string, first - internationalize the template string then do the replacement. - - Example:: - - msg = _LE("Missing parameter: %s") - LOG.error(msg, "flavor") - -- [H703] If you have multiple variables to place in the string, use keyword - parameters. This helps our translators reorder parameters when needed. - - Example:: - - msg = _LE("The server with id %(s_id)s has no key %(m_key)s") - LOG.error(msg, {"s_id": "1234", "m_key": "imageId"}) - -.. seealso:: - - * `oslo.i18n Guidelines `__ - -Python 3.x compatibility ------------------------- -OpenStack code should become Python 3.x compatible. That means all Python 2.x-only -constructs or dependencies should be avoided. In order to start making code -Python 3.x compatible before it can be fully Python 3.x compatible, we have checks for Python 2.x-only constructs: - -- [H231] ``except``. Instead of:: - - except x,y: - - Use:: - - except x as y: - -- [H232] Python 3.x has become more strict regarding octal string - literals. Use ``0o755`` instead of ``0755``. Similarly, explicit use of long - literals (``01234L``) should be avoided. - -- [H233] The ``print`` operator can be avoided by using:: - - from __future__ import print_function - - at the top of your module. - -- [H234] ``assertEquals()`` logs a DeprecationWarning in Python 3.x, use - ``assertEqual()`` instead. The same goes for ``assertNotEquals()``. - -- [H235] ``assert_()`` is deprecated in Python 3.x, use ``assertTrue()`` instead. - -- [H236] Use ``six.add_metaclass`` instead of ``__metaclass__``. - - Example:: - - import six - - @six.add_metaclass(Meta) - class YourClass(): - -- [H237] Don't use modules that were removed in Python 3. Removed module list: - http://python3porting.com/stdlib.html#removed-modules - -- [H238] Old style classes are deprecated and no longer available in Python 3 - (they are converted to new style classes). In order to avoid any unwanted side - effects all classes should be declared using new style. See `the new-style - class documentation `_ for reference on - the differences. - - Example:: - - class Foo(object): - pass - -Creating Unit Tests -------------------- -For every new feature, unit tests should be created that both test and -(implicitly) document the usage of said feature. If submitting a patch for a -bug that had no unit test, a new passing unit test should be added. If a -submitted bug fix does have a unit test, be sure to add a new one that fails -without the patch and passes with the patch. - -Unit Tests and assertRaises ---------------------------- - -A properly written test asserts that particular behavior occurs. This can -be a success condition or a failure condition, including an exception. -When asserting that a particular exception is raised, the most specific -exception possible should be used. - -- [H202] Testing for ``Exception`` being raised is almost always a - mistake since it will match (almost) every exception, even those - unrelated to the exception intended to be tested. - - This applies to catching exceptions manually with a try/except block, - or using ``assertRaises()``. - - Example:: - - with self.assertRaises(exception.InstanceNotFound): - db.instance_get_by_uuid(elevated, instance_uuid) - -- [H203] Use assertIs(Not)None to check for None (off by default) - Unit test assertions tend to give better messages for more specific - assertions. As a result, ``assertIsNone(...)`` is preferred over - ``assertEqual(None, ...)`` and ``assertIs(None, ...)``, and - ``assertIsNotNone(...)`` is preferred over ``assertNotEqual(None, ...)`` - and ``assertIsNot(None, ...)``. Off by default. - -OpenStack Trademark -------------------- - -OpenStack is a registered trademark of the OpenStack Foundation, and uses the -following capitalization:: - - OpenStack - - -OpenStack Licensing -------------------- - -- [H102 H103] Newly contributed Source Code should be licensed under the - Apache 2.0 license. All source files should have the following header:: - - # Licensed under the Apache License, Version 2.0 (the "License"); you may - # not use this file except in compliance with the License. You may obtain - # a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - # License for the specific language governing permissions and limitations - # under the License. - -- [H104] Files with no code shouldn't contain any license header nor comments, - and must be left completely empty. - -Commit Messages ---------------- -Using a common format for commit messages will help keep our git history -readable. - -For further information on constructing high quality commit messages, -and how to split up commits into a series of changes, consult the -project wiki: -https://wiki.openstack.org/GitCommitMessages diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 68c771a..0000000 --- a/LICENSE +++ /dev/null @@ -1,176 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 0aceb71..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,9 +0,0 @@ -include AUTHORS -include ChangeLog -include README.rst -include requirements.txt -include test-requirements.txt -exclude .gitignore -exclude .gitreview - -global-exclude *.pyc diff --git a/README b/README new file mode 100644 index 0000000..8fcd2b2 --- /dev/null +++ b/README @@ -0,0 +1,14 @@ +This project is no longer maintained. + +The contents of this repository are still available in the Git +source code management system. To see the contents of this +repository before it reached its end of life, please check out the +previous commit with "git checkout HEAD^1". + +For ongoing work on maintaining OpenStack packages in the Debian +distribution, please see the Debian OpenStack packaging team at +https://wiki.debian.org/OpenStack/. + +For any further questions, please email +openstack-dev@lists.openstack.org or join #openstack-dev on +Freenode. diff --git a/README.rst b/README.rst deleted file mode 100644 index 88a0c22..0000000 --- a/README.rst +++ /dev/null @@ -1,131 +0,0 @@ -Introduction -============ - -hacking is a set of flake8 plugins that test and enforce the :ref:`StyleGuide`. - -Hacking pins its dependencies, as a new release of some dependency can break -hacking based gating jobs. This is because new versions of dependencies can -introduce new rules, or make existing rules stricter. - -Installation -============ - -hacking is available from pypi, so just run:: - - pip install hacking - -This will install specific versions of ``flake8`` with the ``hacking``, -``pep8``, ``mccabe`` and ``pyflakes`` plugins. - -Origin -====== - -Hacking started its life out as a text file in Nova's first commit. It was -initially based on the `Google Python Style Guide`_, and over time more -OpenStack specific rules were added. Hacking serves several purposes: - -1. Agree on a common style guide so reviews don't get bogged down on style - nit picks. (example: docstring guidelines) -2. Make code written by many different authors easier to read by making the - style more uniform. (example: unix vs windows newlines) -3. Call out dangerous patterns and avoid them. (example: shadowing built-in - or reserved words) - -Initially the hacking style guide was enforced manually by reviewers, but this -was a big waste of time so hacking, the tool, was born to automate -the process and remove the extra burden from human reviewers. - -.. _`Google Python Style Guide`: https://google.github.io/styleguide/pyguide.html - -Versioning -========== - -hacking uses the ``major.minor.maintenance`` release notation, where maintenance -releases cannot contain new checks. This way projects can gate on hacking -by pinning on the ``major.minor`` number while accepting maintenance updates -without being concerned that a new version will break the gate with a new -check. - -For example a project can depend on ``hacking>=0.10.0,<0.11.0``, and can know -that ``0.10.1`` will not fail in places where ``0.10.0`` passed. - - -Adding additional checks -======================== - -Each check is a pep8 plugin so read - -- https://github.com/jcrocholl/pep8/blob/master/docs/developer.rst#contribute - -The focus of new or changed rules should be to do one of the following - -- Substantially increase the reviewability of the code (eg: H301, H303) - as they make it easy to understand where symbols come from) -- Catch a common programming error that may arise in the future (H201) -- Prevent a situation that would 100% of the time be -1ed by - developers (H903) - -But, as always, remember that these are Guidelines. Treat them as -such. There are always times for exceptions. All new rules should -support noqa. - -If a check needs to be staged in, or it does not apply to every project or its -branch, it can be added as off by default. - -Requirements ------------- -- The check must already have community support. We do not want to dictate - style, only enforce it. -- The canonical source of the OpenStack Style Guidelines is :ref:`StyleGuide`, - and hacking just enforces - them; so when adding a new check, it must be in ``HACKING.rst`` -- False negatives are ok, but false positives are not -- Cannot be project specific, project specific checks should be `Local Checks`_ -- Include extensive tests -- Registered as entry_points in ``setup.cfg`` -- Error code must be in the relevant ``Hxxx`` group -- The check should not attempt to import modules from the code being checked. - Importing random modules, has caused all kinds of trouble for us in the past. - - -Enabling off-by-default checks -============================== - -Some of the available checks are disabled by default. These checks are: - -- [H106] Don't put vim configuration in source files. -- [H203] Use assertIs(Not)None to check for None. -- [H904] Delay string interpolations at logging calls. - -To enable these checks, edit the ``flake8`` section of the ``tox.ini`` file. -For example to enable H106 and H203: - -.. code-block:: ini - - [flake8] - enable-extensions = H106,H203 - -Local Checks -============ - -hacking supports having local changes in a source tree. They can be configured -to run in two different ways. They can be registered individually, or with -a factory function. - -For individual registration, put a comma separated list of pep8 compatible -check functions into the hacking section of tox.ini. E.g.: - -.. code-block:: ini - - [hacking] - local-check = nova.tests.hacking.bad_code_is_terrible - -Alternately, you can specify the location of a callable that will be called -at registration time and will be passed the registration function. The callable -should expect to call the passed in function on everything if wants to -register. Such as: - -.. code-block:: ini - - [hacking] - local-check-factory = nova.tests.hacking.factory diff --git a/doc/source/conf.py b/doc/source/conf.py deleted file mode 100644 index 7a8088b..0000000 --- a/doc/source/conf.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- - -import os -import sys - -sys.path.insert(0, os.path.abspath('../..')) -# -- General configuration ---------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'openstackdocstheme'] - -# openstackdocstheme options -repository_name = 'openstack-dev/hacking' -bug_project = 'hacking' -bug_tag = '' - -# autodoc generation is a bit aggressive and a nuisance when doing heavy -# text edit cycles. -# execute "export SPHINX_DEBUG=1" in your terminal to disable - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'hacking' -copyright = u'2013, OpenStack Foundation' - -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = True - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# -- Options for HTML output -------------------------------------------------- - -html_theme = 'openstackdocs' -html_last_updated_fmt = '%Y-%m-%d %H:%M' - -# Output file base name for HTML help builder. -htmlhelp_basename = '%sdoc' % project - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass -# [howto/manual]). -latex_documents = [ - ('index', - '%s.tex' % project, - u'%s Documentation' % project, - u'OpenStack Foundation', 'manual'), -] diff --git a/doc/source/index.rst b/doc/source/index.rst deleted file mode 100644 index adcd65e..0000000 --- a/doc/source/index.rst +++ /dev/null @@ -1,14 +0,0 @@ -================================================ -hacking: OpenStack Hacking Guideline Enforcement -================================================ - -hacking is a set of flake8 plugins that test and enforce the :ref:`StyleGuide`. - -Hacking pins its dependencies, as a new release of some dependency can break -hacking based gating jobs. This is because new versions of dependencies can -introduce new rules, or make existing rules stricter. - -.. toctree:: - :maxdepth: 3 - - user/index diff --git a/doc/source/user/hacking.rst b/doc/source/user/hacking.rst deleted file mode 100644 index 96ab88e..0000000 --- a/doc/source/user/hacking.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../../HACKING.rst diff --git a/doc/source/user/index.rst b/doc/source/user/index.rst deleted file mode 100644 index 23165d0..0000000 --- a/doc/source/user/index.rst +++ /dev/null @@ -1,9 +0,0 @@ -================== -User Documentation -================== - -.. toctree:: - :maxdepth: 2 - - hacking - usage diff --git a/doc/source/user/usage.rst b/doc/source/user/usage.rst deleted file mode 100644 index 4b93474..0000000 --- a/doc/source/user/usage.rst +++ /dev/null @@ -1,5 +0,0 @@ -============= -Using hacking -============= - -.. include:: ../../../README.rst diff --git a/hacking/__init__.py b/hacking/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/hacking/checks/__init__.py b/hacking/checks/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/hacking/checks/comments.py b/hacking/checks/comments.py deleted file mode 100644 index 96eaa8f..0000000 --- a/hacking/checks/comments.py +++ /dev/null @@ -1,182 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re -import tokenize - -from hacking import core - - -AUTHOR_TAG_RE = (re.compile("^\s*#\s*@?(a|A)uthors?:"), - re.compile("^\.\.\s+moduleauthor::")) - - -@core.flake8ext -def hacking_todo_format(physical_line, tokens): - """Check for 'TODO()'. - - OpenStack HACKING guide recommendation for TODO: - Include your name with TODOs as in "# TODO(termie)" - - Okay: # TODO(sdague) - H101: # TODO fail - H101: # TODO - H101: # TODO (jogo) fail - Okay: TODO = 5 - """ - # TODO(jogo): make the following doctests pass: - # H101: #TODO(jogo fail - # H101: #TODO(jogo - # TODO(jogo): make this check docstrings as well (don't have to be at top - # of function) - for token_type, text, start_index, _, _ in tokens: - if token_type == tokenize.COMMENT: - pos = text.find('TODO') - pos1 = text.find('TODO(') - if (pos != pos1): - return pos + start_index[1], "H101: Use TODO(NAME)" - - -@core.flake8ext -def hacking_has_license(physical_line, filename, lines, line_number): - """Check for Apache 2.0 license. - - H102 license header not found - """ - # don't work about init files for now - # TODO(sdague): enforce license in init file if it's not empty of content - license_found = False - - # skip files that are < 10 lines, which isn't enough for a license to fit - # this allows us to handle empty files, as well as not fail on the Okay - # doctests. - if line_number is 1 and len(lines) > 10 and _project_is_apache(): - for idx, line in enumerate(lines): - # if it's more than 10 characters in, it's probably not in the - # header - if 0 <= line.find('Licensed under the Apache License') < 10: - license_found = True - if not license_found: - return (0, "H102: Apache 2.0 license header not found") - - -@core.flake8ext -def hacking_has_correct_license(physical_line, filename, lines, line_number): - """Check for Apache 2.0 license. - - H103 header does not match Apache 2.0 License notice - """ - # don't work about init files for now - # TODO(sdague): enforce license in init file if it's not empty of content - - # skip files that are < 10 lines, which isn't enough for a license to fit - # this allows us to handle empty files, as well as not fail on the Okay - # doctests. - if line_number is 1 and len(lines) > 10 and _project_is_apache(): - for idx, line in enumerate(lines): - column = line.find('Licensed under the Apache License') - if (0 < column < 10 and not - _check_for_exact_apache(idx, lines)): - return (column, "H103: Header does not match Apache 2.0 " - "License notice") - - -EMPTY_LINE_RE = re.compile("^\s*(#.*|$)") - - -@core.flake8ext -def hacking_has_only_comments(physical_line, filename, lines, line_number): - """Check for empty files with only comments - - H104 empty file with only comments - """ - if line_number == 1 and all(map(EMPTY_LINE_RE.match, lines)): - return (0, "H104: File contains nothing but comments") - - -_is_apache_cache = None - - -def _project_is_apache(): - """Determine if a project is Apache. - - Look for a key string in a set of possible license files to figure out - if a project looks to be Apache. This is used as a precondition for - enforcing license headers. - """ - - global _is_apache_cache - if _is_apache_cache is not None: - return _is_apache_cache - license_files = ["LICENSE"] - for filename in license_files: - try: - with open(filename, "r") as file: - for line in file: - if re.search('Apache License', line): - _is_apache_cache = True - return True - except IOError: - pass - _is_apache_cache = False - return False - - -def _check_for_exact_apache(start, lines): - """Check for the Apache 2.0 license header. - - We strip all the newlines and extra spaces so this license string - should work regardless of indentation in the file. - """ - APACHE2 = """ -Licensed under the Apache License, Version 2.0 (the "License"); you may -not use this file except in compliance with the License. You may obtain -a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -License for the specific language governing permissions and limitations -under the License.""" - - # out of all the formatting I've seen, a 12 line version seems to be the - # longest in the source tree. So just take the 12 lines starting with where - # the Apache starting words were found, strip all the '#' and collapse the - # spaces. - content = ''.join(lines[start:(start + 12)]) - content = re.sub('\#', '', content) - content = re.sub('\s+', ' ', content).strip() - stripped_apache2 = re.sub('\s+', ' ', APACHE2).strip() - - if stripped_apache2 in content: - return True - else: - print("!=:\n'%s' !=\n'%s'" % - (content, stripped_apache2)) - return False - - -@core.flake8ext -def hacking_no_author_tags(physical_line): - """Check that no author tags are used. - - H105 don't use author tags - """ - for regex in AUTHOR_TAG_RE: - if regex.match(physical_line): - physical_line = physical_line.lower() - pos = physical_line.find('moduleauthor') - if pos < 0: - pos = physical_line.find('author') - return (pos, "H105: Don't use author tags") diff --git a/hacking/checks/dictlist.py b/hacking/checks/dictlist.py deleted file mode 100644 index 0d0da9f..0000000 --- a/hacking/checks/dictlist.py +++ /dev/null @@ -1,46 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import tokenize - -from hacking import core - - -LOCALS_TEXT_MAP = { - 'locals': 'locals()', - 'self': 'self.__dict__' -} - - -@core.flake8ext -def hacking_no_locals(logical_line, tokens, noqa): - """Do not use locals() or self.__dict__ for string formatting. - - Okay: 'locals()' - Okay: 'locals' - Okay: locals() - Okay: print(locals()) - H501: print("%(something)" % locals()) - H501: LOG.info(_("%(something)") % self.__dict__) - Okay: print("%(something)" % locals()) # noqa - """ - if noqa: - return - for_formatting = False - for token_type, text, start, _, _ in tokens: - if text == "%" and token_type == tokenize.OP: - for_formatting = True - if for_formatting and token_type == tokenize.NAME: - for k, v in LOCALS_TEXT_MAP.items(): - if text == k and v in logical_line: - yield (start[1], - "H501: Do not use %s for string formatting" % v) diff --git a/hacking/checks/docstrings.py b/hacking/checks/docstrings.py deleted file mode 100644 index 6c6b894..0000000 --- a/hacking/checks/docstrings.py +++ /dev/null @@ -1,161 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import tokenize - -from hacking import core - -START_DOCSTRING_TRIPLE = ['u"""', 'r"""', '"""', "u'''", "r'''", "'''"] -END_DOCSTRING_TRIPLE = ['"""', "'''"] - - -@core.flake8ext -def hacking_docstring_start_space(physical_line, previous_logical, tokens): - r"""Check for docstring not starting with space. - - OpenStack HACKING guide recommendation for docstring: - Docstring should not start with space - - Okay: def foo():\n '''This is good.''' - Okay: def foo():\n r'''This is good.''' - Okay: def foo():\n a = ''' This is not a docstring.''' - Okay: def foo():\n pass\n ''' This is not.''' - H401: def foo():\n ''' This is not.''' - H401: def foo():\n r''' This is not.''' - """ - docstring = is_docstring(tokens, previous_logical) - if docstring: - start, start_triple = _find_first_of(docstring, START_DOCSTRING_TRIPLE) - if docstring[len(start_triple)] == ' ': - # docstrings get tokenized on the last line of the docstring, so - # we don't know the exact position. - return (0, "H401: docstring should not start with" - " a space") - - -@core.flake8ext -def hacking_docstring_multiline_end(physical_line, previous_logical, tokens): - r"""Check multi line docstring end. - - OpenStack HACKING guide recommendation for docstring: - Docstring should end on a new line - - Okay: '''foobar\nfoo\nbar\n''' - Okay: def foo():\n '''foobar\n\nfoo\nbar\n''' - Okay: class Foo(object):\n '''foobar\n\nfoo\nbar\n''' - Okay: def foo():\n a = '''not\na\ndocstring''' - Okay: def foo():\n a = '''not\na\ndocstring''' # blah - Okay: def foo():\n pass\n'''foobar\nfoo\nbar\n d''' - H403: def foo():\n '''foobar\nfoo\nbar\ndocstring''' - H403: def foo():\n '''foobar\nfoo\nbar\npretend raw: r''' - H403: class Foo(object):\n '''foobar\nfoo\nbar\ndocstring'''\n\n - """ - docstring = is_docstring(tokens, previous_logical) - if docstring: - if '\n' not in docstring: - # not a multi line - return - else: - last_line = docstring.split('\n')[-1] - pos = max(last_line.rfind(i) for i in END_DOCSTRING_TRIPLE) - if len(last_line[:pos].strip()) > 0: - # Something before the end docstring triple - return (pos, - "H403: multi line docstrings should end on a new line") - - -@core.flake8ext -def hacking_docstring_multiline_start(physical_line, previous_logical, tokens): - r"""Check multi line docstring starts immediately with summary. - - OpenStack HACKING guide recommendation for docstring: - Docstring should start with a one-line summary, less than 80 characters. - - Okay: '''foobar\n\nfoo\nbar\n''' - Okay: def foo():\n a = '''\nnot\na docstring\n''' - H404: def foo():\n '''\nfoo\nbar\n'''\n\n - H404: def foo():\n r'''\nfoo\nbar\n'''\n\n - """ - docstring = is_docstring(tokens, previous_logical) - if docstring: - if '\n' not in docstring: - # single line docstring - return - start, start_triple = _find_first_of(docstring, START_DOCSTRING_TRIPLE) - lines = docstring.split('\n') - if lines[0].strip() == start_triple: - # docstrings get tokenized on the last line of the docstring, so - # we don't know the exact position. - return (0, "H404: multi line docstring " - "should start without a leading new line") - - -@core.flake8ext -def hacking_docstring_summary(physical_line, previous_logical, tokens): - r"""Check multi line docstring summary is separated with empty line. - - OpenStack HACKING guide recommendation for docstring: - Docstring should start with a one-line summary, less than 80 characters. - - Okay: def foo():\n a = '''\nnot\na docstring\n''' - Okay: '''foobar\n\nfoo\nbar\n''' - H405: def foo():\n '''foobar\nfoo\nbar\n''' - H405: def foo():\n r'''foobar\nfoo\nbar\n''' - H405: def foo():\n '''foobar\n''' - """ - docstring = is_docstring(tokens, previous_logical) - if docstring: - if '\n' not in docstring: - # not a multi line docstring - return - lines = docstring.split('\n') - if len(lines) > 1 and len(lines[1].strip()) is not 0: - # docstrings get tokenized on the last line of the docstring, so - # we don't know the exact position. - return (0, "H405: multi line docstring " - "summary not separated with an empty line") - - -def is_docstring(tokens, previous_logical): - """Return found docstring - - 'A docstring is a string literal that occurs as the first statement in a - module, function, class,' - http://www.python.org/dev/peps/pep-0257/#what-is-a-docstring - """ - for token_type, text, start, _, _ in tokens: - if token_type == tokenize.STRING: - break - elif token_type != tokenize.INDENT: - return False - else: - return False - line = text.lstrip() - start, start_triple = _find_first_of(line, START_DOCSTRING_TRIPLE) - if (previous_logical.startswith("def ") or - previous_logical.startswith("class ")): - if start == 0: - return text - - -def _find_first_of(line, substrings): - """Find earliest occurrence of one of substrings in line. - - Returns pair of index and found substring, or (-1, None) - if no occurrences of any of substrings were found in line. - """ - starts = ((line.find(i), i) for i in substrings) - found = [(i, sub) for i, sub in starts if i != -1] - if found: - return min(found) - else: - return -1, None diff --git a/hacking/checks/except_checks.py b/hacking/checks/except_checks.py deleted file mode 100644 index fc61264..0000000 --- a/hacking/checks/except_checks.py +++ /dev/null @@ -1,224 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# module cannot be called except since that is a reserved word - -import ast -import re - -from six import PY2 - -from hacking import core - -RE_ASSERT_RAISES_EXCEPTION = re.compile(r"self\.assertRaises\(Exception[,\)]") - - -@core.flake8ext -def hacking_except_format(logical_line, noqa): - r"""Check for 'except:'. - - OpenStack HACKING guide recommends not using except: - Do not write "except:", use "except Exception:" at the very least - - Okay: try:\n pass\nexcept Exception:\n pass - H201: try:\n pass\nexcept:\n pass - H201: except: - Okay: try:\n pass\nexcept: # noqa\n pass - """ - if noqa: - return - if logical_line.startswith("except:"): - yield 6, "H201: no 'except:' at least use 'except Exception:'" - - -@core.flake8ext -def hacking_except_format_assert(logical_line, noqa): - r"""Check for 'assertRaises(Exception'. - - OpenStack HACKING guide recommends not using assertRaises(Exception...): - Do not use overly broad Exception type - - Okay: self.assertRaises(NovaException, foo) - Okay: self.assertRaises(ExceptionStrangeNotation, foo) - H202: self.assertRaises(Exception, foo) - H202: self.assertRaises(Exception) - Okay: self.assertRaises(Exception) # noqa - Okay: self.assertRaises(Exception, foo) # noqa - """ - if noqa: - return - if RE_ASSERT_RAISES_EXCEPTION.search(logical_line): - yield 1, "H202: assertRaises Exception too broad" - - -def is_none(node): - '''Check whether an AST node corresponds to None. - - In Python 2 None uses the same ast.Name class that variables etc. use, - but in Python 3 there is a new ast.NameConstant class. - ''' - if PY2: - return isinstance(node, ast.Name) and node.id == 'None' - return isinstance(node, ast.NameConstant) and node.value is None - - -def _get_local_func_name(node): - if isinstance(node.func, ast.Attribute): - return node.func.attr - elif isinstance(node.func, ast.Name): - return node.func.id - else: - return None - - -class NoneArgChecker(ast.NodeVisitor): - '''NodeVisitor to check function calls for None arguments. - - :param func_name: only check calls to functions with this name - :param num_args: number of arguments to check for None - - self.none_found will be True if any None arguments were found. - ''' - def __init__(self, func_name, num_args=2): - self.func_name = func_name - self.num_args = num_args - self.none_found = False - - def visit_Call(self, node): - local_func_name = _get_local_func_name(node) - - if local_func_name == self.func_name: - args_to_check = node.args[:self.num_args] - self.none_found |= any(is_none(x) for x in args_to_check) - self.generic_visit(node) - - -@core.flake8ext -@core.off_by_default -def hacking_assert_is_none(logical_line, noqa): - """Use assertIs(Not)None to check for None in assertions. - - Okay: self.assertEqual('foo', 'bar') - Okay: self.assertNotEqual('foo', {}.get('bar', None)) - Okay: self.assertIs('foo', 'bar') - Okay: self.assertIsNot('foo', 'bar', None) - Okay: foo(self.assertIsNot('foo', 'bar')) - H203: self.assertEqual(None, 'foo') - H203: self.assertNotEqual('foo', None) - H203: self.assertIs(None, 'foo', 'bar') - H203: self.assertIsNot('foo', None, 'bar') - H203: foo(self.assertIsNot('foo', None, 'bar')) - Okay: self.assertEqual(None, 'foo') # noqa - Okay: self.assertIs(None, 'foo') # noqa - Okay: self.assertIsNone('foo') - """ - if noqa: - return - for func_name in ('assertEqual', 'assertIs', 'assertNotEqual', - 'assertIsNot'): - try: - start = logical_line.index('.%s(' % func_name) + 1 - except ValueError: - continue - checker = NoneArgChecker(func_name) - checker.visit(ast.parse(logical_line)) - if checker.none_found: - yield start, "H203: Use assertIs(Not)None to check for None" - - -class AssertTrueFalseChecker(ast.NodeVisitor): - '''NodeVisitor to find "assert[True|False](some comparison)" statements. - - :param method_names: methods to look for: assertTrue and/or assertFalse - :param ops: list of comparisons we want to look for (objects from the ast - module) - ''' - def __init__(self, method_names, ops): - self.method_names = method_names - self.ops = tuple(ops) - self.error = False - - def visit_Call(self, node): - # No need to keep visiting the AST if we already found something. - if self.error: - return - - self.generic_visit(node) - - local_func_name = _get_local_func_name(node) - - if (local_func_name in self.method_names and - len(node.args) == 1 and - isinstance(node.args[0], ast.Compare) and - len(node.args[0].ops) == 1 and - isinstance(node.args[0].ops[0], self.ops)): - self.error = True - - -@core.flake8ext -@core.off_by_default -def hacking_assert_equal(logical_line, noqa): - r"""Check that self.assertEqual and self.assertNotEqual are used. - - Okay: self.assertEqual(x, y) - Okay: self.assertNotEqual(x, y) - H204: self.assertTrue(x == y) - H204: self.assertTrue(x != y) - H204: self.assertFalse(x == y) - H204: self.assertFalse(x != y) - """ - if noqa: - return - - methods = ['assertTrue', 'assertFalse'] - for method in methods: - start = logical_line.find('.%s' % method) + 1 - if start != 0: - break - else: - return - comparisons = [ast.Eq, ast.NotEq] - checker = AssertTrueFalseChecker(methods, comparisons) - checker.visit(ast.parse(logical_line)) - if checker.error: - yield start, 'H204: Use assert(Not)Equal()' - - -@core.flake8ext -@core.off_by_default -def hacking_assert_greater_less(logical_line, noqa): - r"""Check that self.assert{Greater,Less}[Equal] are used. - - Okay: self.assertGreater(x, y) - Okay: self.assertGreaterEqual(x, y) - Okay: self.assertLess(x, y) - Okay: self.assertLessEqual(x, y) - H205: self.assertTrue(x > y) - H205: self.assertTrue(x >= y) - H205: self.assertTrue(x < y) - H205: self.assertTrue(x <= y) - """ - if noqa: - return - - methods = ['assertTrue', 'assertFalse'] - for method in methods: - start = logical_line.find('.%s' % method) + 1 - if start != 0: - break - else: - return - comparisons = [ast.Gt, ast.GtE, ast.Lt, ast.LtE] - checker = AssertTrueFalseChecker(methods, comparisons) - checker.visit(ast.parse(logical_line)) - if checker.error: - yield start, 'H205: Use assert{Greater,Less}[Equal]' diff --git a/hacking/checks/imports.py b/hacking/checks/imports.py deleted file mode 100644 index 13a0c21..0000000 --- a/hacking/checks/imports.py +++ /dev/null @@ -1,104 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re - -from hacking import core - -RE_RELATIVE_IMPORT = re.compile('^from\s*[.]') - - -@core.flake8ext -def hacking_import_rules(logical_line, filename, noqa): - r"""Check for imports. - - OpenStack HACKING guide recommends one import per line: - Do not import more than one module per line - - Examples: - Okay: from nova.compute import api - H301: from nova.compute import api, utils - - - Do not use wildcard import - - Do not make relative imports - - Examples: - Okay: from os import path - Okay: from os import path as p - Okay: from os import (path as p) - Okay: import os.path - Okay: from nova.compute import rpcapi - Okay: from six.moves.urllib import parse - H303: from os.path import * - H304: from .compute import rpcapi - """ - # TODO(jogo): make the following doctests pass: - # H301: import os, sys - # TODO(mordred: We need to split this into different checks so that they - # can be disabled by command line switches properly - - if noqa: - return - - split_line = logical_line.split() - split_line_len = len(split_line) - if (split_line_len > 1 and split_line[0] in ('import', 'from') and - not core.is_import_exception(split_line[1])): - pos = logical_line.find(',') - if pos != -1: - if split_line[0] == 'from': - yield pos, "H301: one import per line" - pos = logical_line.find('*') - if pos != -1: - yield pos, "H303: No wildcard (*) import." - return - - if split_line_len in (2, 4, 6) and split_line[1] != "__future__": - if 'from' == split_line[0] and split_line_len > 3: - mod = '.'.join((split_line[1], split_line[3])) - if core.is_import_exception(mod): - return - if RE_RELATIVE_IMPORT.search(logical_line): - yield logical_line.find('.'), ( - "H304: No relative imports. '%s' is a relative import" - % logical_line) - return - - -@core.flake8ext -def hacking_import_alphabetical(logical_line, blank_before, previous_logical, - indent_level, previous_indent_level): - r"""Check for imports in alphabetical order. - - OpenStack HACKING guide recommendation for imports: - imports in human alphabetical order - - Okay: import os\nimport sys\n\nimport nova\nfrom nova import test - Okay: import os\nimport sys - H306: import sys\nimport os - Okay: import sys\n\n# foo\nimport six - """ - # handle import x - # use .lower since capitalization shouldn't dictate order - if blank_before < 1 and indent_level == previous_indent_level: - split_line = core.import_normalize(logical_line. - strip()).lower().split() - split_previous = core.import_normalize(previous_logical. - strip()).lower().split() - length = [2, 4] - if (len(split_line) in length and len(split_previous) in length and - split_line[0] == "import" and split_previous[0] == "import"): - if split_line[1] < split_previous[1]: - yield (0, "H306: imports not in alphabetical order (%s, %s)" - % (split_previous[1], split_line[1])) diff --git a/hacking/checks/localization.py b/hacking/checks/localization.py deleted file mode 100644 index 79335a9..0000000 --- a/hacking/checks/localization.py +++ /dev/null @@ -1,141 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re -import tokenize - -from hacking import core - - -FORMAT_RE = re.compile("%(?:" - "%|" # Ignore plain percents - "(\(\w+\))?" # mapping key - "([#0 +-]?" # flag - "(?:\d+|\*)?" # width - "(?:\.\d+)?" # precision - "[hlL]?" # length mod - "\w))") # type - - -class LocalizationError(Exception): - pass - - -def check_i18n(): - """Generator that checks token stream for localization errors. - - Expects tokens to be ``send``ed one by one. - Raises LocalizationError if some error is found. - """ - while True: - try: - token_type, text, _, _, line = yield - except GeneratorExit: - return - - if text == "def" and token_type == tokenize.NAME: - # explicitly ignore function definitions, as oslo defines these - return - if (token_type == tokenize.NAME and - text in ["_", "_LI", "_LW", "_LE", "_LC"]): - - while True: - token_type, text, start, _, _ = yield - if token_type != tokenize.NL: - break - if token_type != tokenize.OP or text != "(": - continue # not a localization call - - format_string = '' - while True: - token_type, text, start, _, _ = yield - if token_type == tokenize.STRING: - format_string += eval(text) - elif token_type == tokenize.NL: - pass - else: - break - - if not format_string: - raise LocalizationError( - start, "H701: Empty localization string") - if token_type != tokenize.OP: - raise LocalizationError( - start, "H701: Invalid localization call") - if text != ")": - if text == "%": - raise LocalizationError( - start, - "H702: Formatting operation should be outside" - " of localization method call") - elif text == "+": - raise LocalizationError( - start, - "H702: Use bare string concatenation instead of +") - else: - raise LocalizationError( - start, "H702: Argument to _, _LI, _LW, _LC, or _LE " - "must be just a string") - - format_specs = FORMAT_RE.findall(format_string) - positional_specs = [(key, spec) for key, spec in format_specs - if not key and spec] - # not spec means %%, key means %(smth)s - if len(positional_specs) > 1: - raise LocalizationError( - start, "H703: Multiple positional placeholders") - - -@core.flake8ext -def hacking_localization_strings(logical_line, tokens, noqa): - r"""Check localization in line. - - Okay: _("This is fine") - Okay: _LI("This is fine") - Okay: _LW("This is fine") - Okay: _LE("This is fine") - Okay: _LC("This is fine") - Okay: _("This is also fine %s") - Okay: _("So is this %s, %(foo)s") % {foo: 'foo'} - H701: _('') - Okay: def _(msg):\n pass - Okay: def _LE(msg):\n pass - H701: _LI('') - H701: _LW('') - H701: _LE('') - H701: _LC('') - Okay: _('') # noqa - H702: _("Bob" + " foo") - H702: _LI("Bob" + " foo") - H702: _LW("Bob" + " foo") - H702: _LE("Bob" + " foo") - H702: _LC("Bob" + " foo") - Okay: _("Bob" + " foo") # noqa - H702: _("Bob %s" % foo) - H702: _LI("Bob %s" % foo) - H702: _LW("Bob %s" % foo) - H702: _LE("Bob %s" % foo) - H702: _LC("Bob %s" % foo) - H702: _("%s %s" % (foo, bar)) - H703: _("%s %s") % (foo, bar) - """ - if noqa: - return - gen = check_i18n() - next(gen) - try: - list(map(gen.send, tokens)) - gen.close() - except LocalizationError as e: - yield e.args - -# TODO(jogo) Dict and list objects diff --git a/hacking/checks/other.py b/hacking/checks/other.py deleted file mode 100644 index 98feea7..0000000 --- a/hacking/checks/other.py +++ /dev/null @@ -1,54 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re - -from hacking import core - - -log_string_interpolation = re.compile(r".*LOG\.(?:error|warn|warning|info" - r"|critical|exception|debug)" - r"\([^,]*%[^,]*[,)]") - - -@core.flake8ext -def hacking_no_cr(physical_line): - r"""Check that we only use newlines not carriage returns. - - Okay: import os\nimport sys - # pep8 doesn't yet replace \r in strings, will work on an - # upstream fix - H903 import os\r\nimport sys - """ - pos = physical_line.find('\r') - if pos != -1 and pos == (len(physical_line) - 2): - return (pos, "H903: Windows style line endings not allowed in code") - - -@core.flake8ext -@core.off_by_default -def hacking_delayed_string_interpolation(logical_line, noqa): - r"""String interpolation should be delayed at logging calls. - - H904: LOG.debug('Example: %s' % 'bad') - Okay: LOG.debug('Example: %s', 'good') - """ - msg = ("H904: String interpolation should be delayed to be " - "handled by the logging code, rather than being done " - "at the point of the logging call. " - "Use ',' instead of '%'.") - - if noqa: - return - - if log_string_interpolation.match(logical_line): - yield 0, msg diff --git a/hacking/checks/python23.py b/hacking/checks/python23.py deleted file mode 100644 index 4315cab..0000000 --- a/hacking/checks/python23.py +++ /dev/null @@ -1,228 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re -import tokenize - -from hacking import core - -RE_OCTAL = re.compile(r"0+([1-9]\d*)") -RE_PRINT = re.compile(r"\bprint(?:$|\s+[^\(])") - - -@core.skip_on_py3 -@core.flake8ext -def hacking_python3x_except_compatible(logical_line, noqa): - r"""Check for except statements to be Python 3.x compatible - - As of Python 3.x, the construct 'except x,y:' has been removed. - Use 'except x as y:' instead. - - - Okay: try:\n pass\nexcept Exception:\n pass - Okay: try:\n pass\nexcept (Exception, AttributeError):\n pass - H231: try:\n pass\nexcept AttributeError, e:\n pass - Okay: try:\n pass\nexcept AttributeError, e: # noqa\n pass - """ - if noqa: - return - - def is_old_style_except(logical_line): - return (',' in logical_line and - ')' not in logical_line.rpartition(',')[2]) - - if (logical_line.startswith("except ") and - logical_line.endswith(':') and - is_old_style_except(logical_line)): - yield 0, "H231: Python 3.x incompatible 'except x,y:' construct" - - -@core.skip_on_py3 -@core.flake8ext -def hacking_python3x_octal_literals(logical_line, tokens, noqa): - r"""Check for octal literals in Python 3.x compatible form. - - As of Python 3.x, the construct "0755" has been removed. - Use "0o755" instead". - - - Okay: f(0o755) - Okay: 'f(0755)' - Okay: f(755) - Okay: f(0) - Okay: f(000) - Okay: MiB = 1.0415 - H232: f(0755) - Okay: f(0755) # noqa - """ - if noqa: - return - - for token_type, text, _, _, _ in tokens: - if token_type == tokenize.NUMBER: - match = RE_OCTAL.match(text) - if match: - yield 0, ("H232: Python 3.x incompatible octal %s should be " - "written as 0o%s " % - (match.group(0)[1:], match.group(1))) - - -@core.skip_on_py3 -@core.flake8ext -def hacking_python3x_print_function(logical_line, noqa): - r"""Check that all print occurrences look like print functions. - - Check that all occurrences of print look like functions, not - print operator. As of Python 3.x, the print operator has - been removed. - - - Okay: print(msg) - Okay: print (msg) - Okay: print msg # noqa - Okay: print() - H233: print msg - H233: print >>sys.stderr, "hello" - H233: print msg, - H233: print - """ - if noqa: - return - for match in RE_PRINT.finditer(logical_line): - yield match.start(0), ( - "H233: Python 3.x incompatible use of print operator") - - -@core.flake8ext -def hacking_no_assert_equals(logical_line, tokens, noqa): - r"""assert(Not)Equals() is deprecated, use assert(Not)Equal instead. - - Okay: self.assertEqual(0, 0) - Okay: self.assertNotEqual(0, 1) - H234: self.assertEquals(0, 0) - H234: self.assertNotEquals(0, 1) - Okay: self.assertEquals(0, 0) # noqa - Okay: self.assertNotEquals(0, 1) # noqa - """ - - if noqa: - return - for token_type, text, start_index, _, _ in tokens: - - if token_type == tokenize.NAME: - if text == "assertEquals" or text == "assertNotEquals": - yield (start_index[1], - "H234: %s is deprecated, use %s" % (text, text[:-1])) - - -@core.flake8ext -def hacking_no_assert_underscore(logical_line, tokens, noqa): - r"""assert_() is deprecated, use assertTrue instead. - - Okay: self.assertTrue(foo) - H235: self.assert_(foo) - Okay: self.assert_(foo) # noqa - """ - if noqa: - return - for token_type, text, start_index, _, _ in tokens: - - if token_type == tokenize.NAME and text == "assert_": - yield ( - start_index[1], - "H235: assert_ is deprecated, use assertTrue") - - -@core.flake8ext -def hacking_python3x_metaclass(logical_line, noqa): - r"""Check for metaclass to be Python 3.x compatible. - - Okay: @six.add_metaclass(Meta)\nclass Foo(object):\n pass - Okay: @six.with_metaclass(Meta)\nclass Foo(object):\n pass - Okay: class Foo(object):\n '''docstring\n\n __metaclass__ = Meta\n''' - H236: class Foo(object):\n __metaclass__ = Meta - H236: class Foo(object):\n foo=bar\n __metaclass__ = Meta - H236: class Foo(object):\n '''docstr.'''\n __metaclass__ = Meta - H236: class Foo(object):\n __metaclass__ = \\\n Meta - Okay: class Foo(object):\n __metaclass__ = Meta # noqa - """ - if noqa: - return - split_line = logical_line.split() - if(len(split_line) > 2 and split_line[0] == '__metaclass__' and - split_line[1] == '='): - yield (logical_line.find('__metaclass__'), - "H236: Python 3.x incompatible __metaclass__, " - "use six.add_metaclass()") - - -# NOTE(guochbo): This is removed module list: -# http://python3porting.com/stdlib.html#removed-modules -removed_modules = [ - 'audiodev', 'Bastion', 'bsddb185', 'bsddb3', - 'Canvas', 'cfmfile', 'cl', 'commands', 'compiler' - 'dircache', 'dl', 'exception', 'fpformat', - 'htmllib', 'ihooks', 'imageop', 'imputil' - 'linuxaudiodev', 'md5', 'mhlib', 'mimetools' - 'MimeWriter', 'mimify', 'multifile', 'mutex', - 'new', 'popen2', 'posixfile', 'pure', 'rexec' - 'rfc822', 'sha', 'sgmllib', 'sre', 'stat' - 'stringold', 'sunaudio' 'sv', 'test.testall', - 'thread', 'timing', 'toaiff', 'user' -] - - -@core.flake8ext -def hacking_no_removed_module(logical_line, noqa): - r"""Check for removed modules in Python 3. - - Examples: - Okay: from os import path - Okay: from os import path as p - Okay: from os import (path as p) - Okay: import os.path - H237: import thread - Okay: import thread # noqa - H237: import commands - H237: import md5 as std_md5 - """ - if noqa: - return - line = core.import_normalize(logical_line.strip()) - if line and line.split()[0] == 'import': - module_name = line.split()[1].split('.')[0] - if module_name in removed_modules: - yield 0, ("H237: module %s is " - "removed in Python 3" % module_name) - - -RE_NEW_STYLE_CLASS = re.compile(r"^class [^(]+\(.+\):") - - -@core.flake8ext -def hacking_no_old_style_class(logical_line, noqa): - r"""Check for old style classes. - - Examples: - Okay: class Foo(object):\n pass - Okay: class Foo(Bar, Baz):\n pass - Okay: class Foo(object, Baz):\n pass - Okay: class Foo(somefunc()):\n pass - H238: class Bar:\n pass - H238: class Bar():\n pass - """ - if noqa: - return - line = core.import_normalize(logical_line.strip()) - if line.startswith("class ") and not RE_NEW_STYLE_CLASS.match(line): - yield (0, "H238: old style class declaration, " - "use new style (inherit from `object`)") diff --git a/hacking/checks/vim_check.py b/hacking/checks/vim_check.py deleted file mode 100644 index a9c695a..0000000 --- a/hacking/checks/vim_check.py +++ /dev/null @@ -1,39 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re - -from hacking import core - - -vim_header_re = re.compile(r"^#\s+vim?:.+") - - -@core.flake8ext -@core.off_by_default -def no_vim_headers(physical_line, line_number, lines): - r"""Check for vim editor configuration in source files. - - By default vim modelines can only appear in the first or - last 5 lines of a source file. - - Examples: - H106: # vim: set tabstop=4 shiftwidth=4\n#\n#\n#\n#\n# - H106: # Lic\n# vim: set tabstop=4 shiftwidth=4\n#\n#\n#\n#\n# - H106: # Lic\n#\n#\n#\n#\n#\n#\n#\n#\n# vim: set tabstop=4 shiftwidth=4 - Okay: # Lic\n#\n#\n#\n#\n#\n#\n# - Okay: # viminal hill is located in Rome - Okay: # vim, ze nemluvis cesky - """ - if ((line_number <= 5 or line_number > len(lines) - 5) and - vim_header_re.match(physical_line)): - return 0, "H106: Don't put vim configuration in source files" diff --git a/hacking/config.py b/hacking/config.py deleted file mode 100644 index 79e3503..0000000 --- a/hacking/config.py +++ /dev/null @@ -1,48 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from six import moves - - -class Config(object): - def __init__(self, default_section=None, tox_file='tox.ini'): - conf = moves.configparser.RawConfigParser() - conf.read(tox_file) - - self.conf = conf - self.default_section = default_section - - def get(self, option, section=None, default=None): - section = section or self.default_section - - if not self.conf.has_section(section): - return default - - if self.conf.has_option(section, option): - return self.conf.get(section, option).strip() - - return default - - def get_multiple(self, option, section=None, default=None): - section = section or self.default_section - - values = self.get(option, section) - if not values: - return default - - values = [v.strip() for v in values.split('\n') if v.strip()] - result = [] - for vals in values: - result.extend([v.strip() for v in vals.split(',') if v.strip()]) - - return result diff --git a/hacking/core.py b/hacking/core.py deleted file mode 100644 index 338f81f..0000000 --- a/hacking/core.py +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright (c) 2012, Cloudscaling -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""OpenStack HACKING file compliance testing - -Built as a sets of pep8 checks using flake8. -""" - -import gettext -import sys - -import pbr.util -import pep8 - -from hacking import config - -# Import tests need to inject _ properly into the builtins -kwargs = {} -if sys.version_info[0] < 3: - # In Python2, ensure that the _() that gets installed into built-ins - # always returns unicodes. This matches the default behavior under Python - # 3, although the keyword argument is not present in the Python 3 API. - kwargs['unicode'] = True -gettext.install('hacking', **kwargs) - - -def flake8ext(f): - f.name = __name__ - f.version = '0.0.1' - f.skip_on_py3 = False - if not hasattr(f, 'off_by_default'): - f.off_by_default = False - return f - - -def off_by_default(f): - """Decorator to turn check off by default. - - To enable the check use the flake8 select setting in - tox.ini. - - flake8 documentation: - http://flake8.readthedocs.org/en/latest/extensions.html. - """ - f.off_by_default = True - return f - - -def skip_on_py3(f): - f.skip_on_py3 = True - return f - -# Error code block layout - -# H1xx comments -# H20x except -# H23x Python 2.x -> 3.x portability issues -# H3xx imports -# H4xx docstrings -# H5xx dictionaries/lists -# H6xx calling methods -# H7xx localization -# H8xx git commit messages -# H9xx other - - -CONF = config.Config('hacking') - - -DEFAULT_IMPORT_EXCEPTIONS = [ - 'sqlalchemy', - 'migrate', -] - -IMPORT_EXCEPTIONS = CONF.get_multiple('import_exceptions', default=[]) -IMPORT_EXCEPTIONS += DEFAULT_IMPORT_EXCEPTIONS - - -def is_import_exception(mod): - """Check module name to see if import has been whitelisted. - - Import based rules should not run on any whitelisted module - """ - return (mod in IMPORT_EXCEPTIONS or - any(mod.startswith(m + '.') for m in IMPORT_EXCEPTIONS)) - - -def import_normalize(line): - # convert "from x import y" to "import x.y" - # handle "from x import y as z" to "import x.y as z" - split_line = line.split() - if ("import" in line and line.startswith("from ") and "," not in line and - split_line[2] == "import" and split_line[3] != "*" and - split_line[1] != "__future__" and - (len(split_line) == 4 or - (len(split_line) == 6 and split_line[4] == "as"))): - return "import %s.%s" % (split_line[1], split_line[3]) - else: - return line - - -class GlobalCheck(object): - """Base class for checks that should be run only once.""" - - name = None - version = '0.0.1' - skip_on_py3 = False - _has_run = set() - - def __init__(self, tree, *args): - pass - - def run(self): - """Make run a no-op if run() has been called before. - - Store in a global registry the list of checks we've run. If we have - run that one before, just skip doing anything the subsequent times. - This way, since pep8 is file/line based, we don't wind up re-running - a check on a git commit message over and over again. - """ - if self.name and self.name not in self.__class__._has_run: - self.__class__._has_run.add(self.name) - ret = self.run_once() - if ret is not None: - yield ret - - def run_once(self): - pass - - -class ProxyChecks(GlobalCheck): - """Provide a mechanism for locally defined checks.""" - name = 'ProxyChecker' - - @classmethod - def add_options(cls, parser): - # We're looking for local checks, so we need to include the local - # dir in the search path - sys.path.append('.') - - local_check = CONF.get_multiple('local-check', default=[]) - for check_path in set(local_check): - if check_path.strip(): - checker = pbr.util.resolve_name(check_path) - pep8.register_check(checker) - - local_check_fact = CONF.get('local-check-factory') - if local_check_fact: - factory = pbr.util.resolve_name(local_check_fact) - factory(pep8.register_check) - - sys.path.pop() diff --git a/hacking/tests/__init__.py b/hacking/tests/__init__.py deleted file mode 100644 index 5061b08..0000000 --- a/hacking/tests/__init__.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -import fixtures -import testtools - - -_TRUE_VALUES = ('True', 'true', '1', 'yes') - - -class TestCase(testtools.TestCase): - """Test case base class for all unit tests.""" - - def setUp(self): - """Run before each test method to initialize test environment.""" - super(TestCase, self).setUp() - test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0) - try: - test_timeout = int(test_timeout) - except ValueError: - # If timeout value is invalid do not set a timeout. - test_timeout = 0 - if test_timeout > 0: - self.useFixture(fixtures.Timeout(test_timeout, gentle=True)) - - if os.environ.get('OS_STDOUT_CAPTURE') in _TRUE_VALUES: - stdout = self.useFixture(fixtures.StringStream('stdout')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout)) - if os.environ.get('OS_STDERR_CAPTURE') in _TRUE_VALUES: - stderr = self.useFixture(fixtures.StringStream('stderr')).stream - self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr)) - - def assertCheckFails(self, check_func, *args, **kwargs): - if not list(check_func(*args, **kwargs)): - raise AssertionError("Check %s did not fail." % - check_func.__name__) - - def assertCheckPasses(self, check_func, *args, **kwargs): - try: - self.assertCheckFails(check_func, *args, **kwargs) - except AssertionError: - return - else: - raise AssertionError("Check %s failed." % check_func.__name__) diff --git a/hacking/tests/checks/__init__.py b/hacking/tests/checks/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/hacking/tests/checks/test_comments.py b/hacking/tests/checks/test_comments.py deleted file mode 100644 index 5e2d711..0000000 --- a/hacking/tests/checks/test_comments.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (c) 2013 eNovance -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from hacking.checks import comments -from hacking import tests - - -class CoreTestCase(tests.TestCase): - def test_H104_regex(self): - """Verify that the H104 regex matches correct lines.""" - self.assertTrue(comments.hacking_has_only_comments( - None, - None, - ['# foo', - '# bar'], - 1)) - self.assertTrue(comments.hacking_has_only_comments( - None, - None, - ['# foo', - '# bar', - ''], - 1)) - self.assertTrue(comments.hacking_has_only_comments( - None, - None, - ['# foo', - ' ', - '# bar'], - 1)) - - self.assertIsNone(comments.hacking_has_only_comments( - None, - None, - ['# foo', - ' ', - '"""foobar"""'], - 1)) - self.assertIsNone(comments.hacking_has_only_comments( - None, - None, - ['# foo', - '', - 'print(42)'], - 1)) - self.assertIsNone(comments.hacking_has_only_comments( - None, - None, - ['# foo'], - 100)) - - def test_H105(self): - self.assertTrue(comments.hacking_no_author_tags( - '# @author: Foo Bar')) - - self.assertTrue(comments.hacking_no_author_tags( - '# @Author: Foo Bar')) - - self.assertTrue(comments.hacking_no_author_tags( - '# author: Foo Bar')) - - self.assertTrue(comments.hacking_no_author_tags( - '# authors: Foo Bar')) - - self.assertTrue(comments.hacking_no_author_tags( - '# Author: Foo Bar')) - - self.assertTrue(comments.hacking_no_author_tags( - '# Authors: Foo Bar')) - - self.assertTrue(comments.hacking_no_author_tags( - '.. moduleauthor:: Foo Bar')) diff --git a/hacking/tests/test_config.py b/hacking/tests/test_config.py deleted file mode 100644 index 610f6dc..0000000 --- a/hacking/tests/test_config.py +++ /dev/null @@ -1,58 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -import fixtures - -from hacking import config -from hacking import tests - - -TEST_TOX_INI = """[hacking] -option_1 = val_1 -option_2 = - val_2 -option_3 = - val_1,val_2, val_3, - val_4 , val_5 , val_6, - val_7 - , - val_8 - val_9 -""" - - -class ConfigTest(tests.TestCase): - def setUp(self): - tox_ini_path = os.path.join(self.useFixture(fixtures.TempDir()).path, - 'tox.ini') - - with open(tox_ini_path, 'w') as tox_ini: - tox_ini.write(TEST_TOX_INI) - self.conf = config.Config('hacking', tox_ini_path) - super(ConfigTest, self).setUp() - - def test_get(self): - self.assertEqual('val_1', self.conf.get('option_1')) - self.assertEqual('val_2', self.conf.get('option_2')) - self.assertEqual('val_3', self.conf.get('option_4', default='val_3')) - - def test_get_multiple(self): - self.assertEqual(['val_1', 'val_2', 'val_3', 'val_4', 'val_5', 'val_6', - 'val_7', 'val_8', 'val_9'], - self.conf.get_multiple('option_3')) - - self.assertEqual(['val_1', 'val_2'], - self.conf.get_multiple('option_4', - default=['val_1', 'val_2'])) diff --git a/hacking/tests/test_doctest.py b/hacking/tests/test_doctest.py deleted file mode 100644 index 1259613..0000000 --- a/hacking/tests/test_doctest.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import re - -from flake8 import engine -import pep8 -import pkg_resources -import six -import testscenarios -from testtools import content -from testtools import matchers - -import hacking -import hacking.tests - -SELFTEST_REGEX = re.compile(r'\b(Okay|[HEW]\d{3}):\s(.*)') -# Each scenario is (name, dict(lines=.., options=..., code=...)) -file_cases = [] - - -class HackingTestCase(hacking.tests.TestCase): - - scenarios = file_cases - - def test_pep8(self): - - # NOTE(jecarey): Add tests marked as off_by_default to enable testing - turn_on = set(['H106', 'H203', 'H904', 'H204', 'H205']) - if self.options.select: - turn_on.update(self.options.select) - self.options.select = tuple(turn_on) - - report = pep8.BaseReport(self.options) - checker = pep8.Checker(lines=self.lines, options=self.options, - report=report) - checker.check_all() - self.addDetail('doctest', content.text_content(self.raw)) - if self.code == 'Okay': - self.assertThat( - len(report.counters), - matchers.Not(matchers.GreaterThan( - len(self.options.benchmark_keys))), - "incorrectly found %s" % ', '.join( - [key for key in report.counters - if key not in self.options.benchmark_keys])) - else: - self.addDetail('reason', - content.text_content("Failed to trigger rule %s" % - self.code)) - self.assertIn(self.code, report.counters) - - -def _get_lines(check): - for line in check.__doc__.splitlines(): - line = line.lstrip() - match = SELFTEST_REGEX.match(line) - if match is None: - continue - yield (line, match.groups()) - - -def load_tests(loader, tests, pattern): - - flake8_style = engine.get_style_guide(parse_argv=False, - # Ignore H104 otherwise it's - # raised on doctests. - ignore=('F', 'H104')) - options = flake8_style.options - - for entry in pkg_resources.iter_entry_points('flake8.extension'): - if not entry.module_name.startswith('hacking.'): - continue - check = entry.load() - name = entry.attrs[0] - if check.skip_on_py3 and six.PY3: - continue - for (lineno, (raw, (code, source))) in enumerate(_get_lines(check)): - lines = [part.replace(r'\t', '\t') + '\n' - for part in source.split(r'\n')] - file_cases.append(("%s-%s-line-%s" % (entry.name, name, lineno), - dict(lines=lines, raw=raw, options=options, - code=code))) - return testscenarios.load_tests_apply_scenarios(loader, tests, pattern) diff --git a/hacking/tests/test_import_exceptions.py b/hacking/tests/test_import_exceptions.py deleted file mode 100644 index 3901825..0000000 --- a/hacking/tests/test_import_exceptions.py +++ /dev/null @@ -1,53 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -import fixtures - -from hacking import config -from hacking import core -from hacking import tests - - -TEST_TOX_INI = """[hacking] -import_exceptions = - a.b.c - z.x -""" - - -class ImportExceptionsTest(tests.TestCase): - def _setUpConfig(self, content): - tox_ini_path = os.path.join(self.useFixture(fixtures.TempDir()).path, - 'tox.ini') - - with open(tox_ini_path, 'w') as tox_ini: - tox_ini.write(content) - - return config.Config('hacking', tox_ini_path) - - def setUp(self): - super(ImportExceptionsTest, self).setUp() - - def test_default_import_exceptions(self): - conf = self._setUpConfig("") - self.assertEqual(core.DEFAULT_IMPORT_EXCEPTIONS, - conf.get_multiple( - 'import_exceptions', - default=core.DEFAULT_IMPORT_EXCEPTIONS)) - - def test_import_exceptions(self): - conf = self._setUpConfig(TEST_TOX_INI) - self.assertEqual(['a.b.c', 'z.x'], - conf.get_multiple('import_exceptions')) diff --git a/hacking/tests/test_local.py b/hacking/tests/test_local.py deleted file mode 100644 index e4dcc23..0000000 --- a/hacking/tests/test_local.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from flake8 import engine -import pep8 - -import hacking.tests - - -def check(physical_line): - """Test check to make sure local-checks are working.""" - if physical_line.strip() == "#this-is-the-test-phrase": - return (0, "L100: Found local-check test case") - - -class HackingTestCase(hacking.tests.TestCase): - def test_local_check(self): - flake8_style = engine.get_style_guide(parse_argv=False, ignore='F') - report = pep8.BaseReport(flake8_style.options) - line = ["#this-is-the-test-phrase"] - checker = pep8.Checker(lines=line, options=flake8_style.options, - report=report) - checker.check_all() - self.assertIn("L100", report.counters) diff --git a/integration-test/test.sh b/integration-test/test.sh deleted file mode 100755 index dfb8af1..0000000 --- a/integration-test/test.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash - -# Usage: test.sh openstack keystone path-to-repo -# path-to-repo is an optional parameter, if it exists -# no cloning will happen and the local directory will be used, -# the first two parameter get ignored. -# Note: you can clone from a local file with REPO_ROOT=file:////~/path/to/repo - -set -x -set -e - -REPO_ROOT=${REPO_ROOT:-git://git.openstack.org} - -if [[ $# -lt 2 ]] ; then - echo "Script needs at least two arguments:" - echo "$0 organization name [path-to-repo]" - exit 1 -fi -org=$1 -project=$2 - -if [[ $# -eq 3 ]] ; then - projectdir=$3 - clone=0 -else - projectdir=$project - clone=1 -fi - -if [ "$clone" = "1" ] ; then - - tempdir="$(mktemp -d)" - - trap "rm -rf $tempdir" EXIT - pushd $tempdir - git clone $REPO_ROOT/$org/$project --depth=1 -fi - -pushd $projectdir -set +e -flake8 --select H --statistics -popd - -if [ "$clone" = "1" ] ; then - popd -fi diff --git a/releasenotes/notes/.placeholder b/releasenotes/notes/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/releasenotes/source/_static/.placeholder b/releasenotes/source/_static/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py deleted file mode 100644 index f078a3a..0000000 --- a/releasenotes/source/conf.py +++ /dev/null @@ -1,283 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pbr.version - -# Hacking Release Notes documentation build configuration file, created by -# sphinx-quickstart on Tue Nov 3 17:40:50 2015. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'openstackdocstheme', - 'reno.sphinxext', -] - -# openstackdocstheme options -repository_name = 'openstack-dev/hacking' -bug_project = 'hacking' -bug_tag = '' - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'Hacking Release Notes' -copyright = u'2015, Hacking Developers' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. - -version_info = pbr.version.VersionInfo('hacking') -# The short X.Y version. -release = version_info.version_string_with_vcs() -# The short X.Y version. -version = version_info.canonical_version_string() - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'openstackdocs' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -html_last_updated_fmt = '%Y-%m-%d %H:%M' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'HackingReleaseNotesdoc' - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # 'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ('index', 'HackingReleaseNotes.tex', - u'Hacking Release Notes Documentation', - u'Hacking Developers', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'hackingreleasenotes', u'Hacking Release Notes Documentation', - [u'Hacking Developers'], 1) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'HackingReleaseNotes', u'Hacking Release Notes Documentation', - u'Hacking Developers', 'HackingReleaseNotes', - 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False - -# -- Options for Internationalization output ------------------------------ -locale_dirs = ['locale/'] diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst deleted file mode 100644 index 8074b31..0000000 --- a/releasenotes/source/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -======================= - Hacking Release Notes -======================= - -.. toctree:: - :maxdepth: 1 - - unreleased diff --git a/releasenotes/source/unreleased.rst b/releasenotes/source/unreleased.rst deleted file mode 100644 index cd22aab..0000000 --- a/releasenotes/source/unreleased.rst +++ /dev/null @@ -1,5 +0,0 @@ -============================== - Current Series Release Notes -============================== - -.. release-notes:: diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 3fd3f6a..0000000 --- a/requirements.txt +++ /dev/null @@ -1,11 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -pbr>=1.8 # Apache-2.0 - -pep8==1.5.7 # MIT -pyflakes==0.8.1 # MIT -flake8<2.6.0,>=2.5.4 # MIT -mccabe==0.2.1 # MIT License - -six>=1.9.0 # MIT diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 6096754..0000000 --- a/setup.cfg +++ /dev/null @@ -1,77 +0,0 @@ -[metadata] -name = hacking -author = OpenStack -author-email = openstack-dev@lists.openstack.org -summary = OpenStack Hacking Guideline Enforcement -description-file = - README.rst -home-page = https://docs.openstack.org/hacking/latest/ -classifier = - Development Status :: 4 - Beta - Environment :: Console - Environment :: OpenStack - Intended Audience :: Developers - Intended Audience :: Information Technology - License :: OSI Approved :: Apache Software License - Operating System :: OS Independent - Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.4 - Programming Language :: Python :: 3.5 - -[files] -packages = - hacking - -[entry_points] -flake8.extension = - H000 = hacking.core:ProxyChecks - H101 = hacking.checks.comments:hacking_todo_format - H102 = hacking.checks.comments:hacking_has_license - H103 = hacking.checks.comments:hacking_has_correct_license - H104 = hacking.checks.comments:hacking_has_only_comments - H105 = hacking.checks.comments:hacking_no_author_tags - H106 = hacking.checks.vim_check:no_vim_headers - H201 = hacking.checks.except_checks:hacking_except_format - H202 = hacking.checks.except_checks:hacking_except_format_assert - H203 = hacking.checks.except_checks:hacking_assert_is_none - H204 = hacking.checks.except_checks:hacking_assert_equal - H205 = hacking.checks.except_checks:hacking_assert_greater_less - H231 = hacking.checks.python23:hacking_python3x_except_compatible - H232 = hacking.checks.python23:hacking_python3x_octal_literals - H233 = hacking.checks.python23:hacking_python3x_print_function - H234 = hacking.checks.python23:hacking_no_assert_equals - H235 = hacking.checks.python23:hacking_no_assert_underscore - H236 = hacking.checks.python23:hacking_python3x_metaclass - H237 = hacking.checks.python23:hacking_no_removed_module - H238 = hacking.checks.python23:hacking_no_old_style_class - H301 = hacking.checks.imports:hacking_import_rules - H306 = hacking.checks.imports:hacking_import_alphabetical - H401 = hacking.checks.docstrings:hacking_docstring_start_space - H403 = hacking.checks.docstrings:hacking_docstring_multiline_end - H404 = hacking.checks.docstrings:hacking_docstring_multiline_start - H405 = hacking.checks.docstrings:hacking_docstring_summary - H501 = hacking.checks.dictlist:hacking_no_locals - H700 = hacking.checks.localization:hacking_localization_strings - H903 = hacking.checks.other:hacking_no_cr - H904 = hacking.checks.other:hacking_delayed_string_interpolation - -[extras] -pep257 = - flake8-docstrings==0.2.1.post1 # MIT - -[build_sphinx] -all_files = 1 -build-dir = doc/build -source-dir = doc/source -warning-is-error = 1 - -[egg_info] -tag_build = -tag_date = 0 -tag_svn_revision = 0 - -[wheel] -universal = 1 diff --git a/setup.py b/setup.py deleted file mode 100644 index 782bb21..0000000 --- a/setup.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT -import setuptools - -# In python < 2.7.4, a lazy loading of package `pbr` will break -# setuptools if some other modules registered functions in `atexit`. -# solution from: http://bugs.python.org/issue15881#msg170215 -try: - import multiprocessing # noqa -except ImportError: - pass - -setuptools.setup( - setup_requires=['pbr>=1.8'], - pbr=True) diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index 53f7da5..0000000 --- a/test-requirements.txt +++ /dev/null @@ -1,21 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -coverage>=4.0 # Apache-2.0 -fixtures>=3.0.0 # Apache-2.0/BSD -mock>=2.0 # BSD -python-subunit>=0.0.18 # Apache-2.0/BSD -sphinx>=1.6.2 # BSD -openstackdocstheme>=1.11.0 # Apache-2.0 -testrepository>=0.0.18 # Apache-2.0/BSD -testscenarios>=0.4 # Apache-2.0/BSD -testtools>=1.4.0 # MIT - -# hacking doesn't use this anywhere, but nova imports this in nova/__init__.py -# since eventlet is such a common universal import, add it to the hacking test -# virtualenv, so importing things like 'nova.hacking.checks.factory' will just -# work. -# See https://bugs.launchpad.net/hacking/+bug/1403270 -eventlet!=0.18.3,>=0.18.2 # MIT - -reno>=1.8.0 # Apache-2.0 diff --git a/tools/tox_install.sh b/tools/tox_install.sh deleted file mode 100755 index e61b63a..0000000 --- a/tools/tox_install.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -# Client constraint file contains this client version pin that is in conflict -# with installing the client from source. We should remove the version pin in -# the constraints file before applying it for from-source installation. - -CONSTRAINTS_FILE="$1" -shift 1 - -set -e - -# NOTE(tonyb): Place this in the tox enviroment's log dir so it will get -# published to logs.openstack.org for easy debugging. -localfile="$VIRTUAL_ENV/log/upper-constraints.txt" - -if [[ "$CONSTRAINTS_FILE" != http* ]]; then - CONSTRAINTS_FILE="file://$CONSTRAINTS_FILE" -fi -# NOTE(tonyb): need to add curl to bindep.txt if the project supports bindep -curl "$CONSTRAINTS_FILE" --insecure --progress-bar --output "$localfile" - -pip install -c"$localfile" openstack-requirements - -# This is the main purpose of the script: Allow local installation of -# the current repo. It is listed in constraints file and thus any -# install will be constrained and we need to unconstrain it. -edit-constraints "$localfile" -- "$CLIENT_NAME" - -pip install -c"$localfile" -U "$@" -exit $? diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 61ef19e..0000000 --- a/tox.ini +++ /dev/null @@ -1,48 +0,0 @@ -[tox] -minversion = 2.0 -skipsdist = True -envlist = py{35,34,27},pep8,pypy - -[testenv] -usedevelop = True -install_command = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages} -setenv = - VIRTUAL_ENV={envdir} - BRANCH_NAME=master - CLIENT_NAME=hacking -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt -commands = - python setup.py testr --slowest --testr-args='{posargs}' - -[tox:jenkins] -sitepackages = True - -[testenv:pep8] -commands = flake8 {posargs} - -[testenv:integration] -whitelist_externals = bash -commands = - bash integration-test/test.sh {posargs} - -[testenv:cover] -commands = - python setup.py testr --coverage - -[testenv:venv] -commands = {posargs} - -[testenv:docs] -commands = python setup.py build_sphinx - -[testenv:releasenotes] -commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html - -[flake8] -exclude = .venv,.tox,dist,doc,*.egg,build -show-source = true -enable-extensions = H106 - -[hacking] -local-check = hacking.tests.test_local.check