From 37349c1ffaa9853c4482461cf259de6b5db91d2d Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Tue, 12 Sep 2017 15:59:39 -0600 Subject: [PATCH] Retire Packaging Deb project repos This commit is part of a series to retire the Packaging Deb project. Step 2 is to remove all content from the project repos, replacing it with a README notification where to find ongoing work, and how to recover the repo if needed at some future point (as in https://docs.openstack.org/infra/manual/drivers.html#retiring-a-project). Change-Id: I6ca27a94cfb35256d71966ea300245365d210350 --- .gitignore | 33 --- .gitreview | 4 - .mailmap | 3 - .testr.conf | 8 - CONTRIBUTING.rst | 16 -- HACKING.rst | 352 ----------------------- LICENSE | 176 ------------ MANIFEST.in | 9 - README | 14 + README.rst | 131 --------- doc/source/conf.py | 61 ---- doc/source/index.rst | 14 - doc/source/user/hacking.rst | 1 - doc/source/user/index.rst | 9 - doc/source/user/usage.rst | 5 - hacking/__init__.py | 0 hacking/checks/__init__.py | 0 hacking/checks/comments.py | 182 ------------ hacking/checks/dictlist.py | 46 --- hacking/checks/docstrings.py | 161 ----------- hacking/checks/except_checks.py | 224 --------------- hacking/checks/imports.py | 104 ------- hacking/checks/localization.py | 141 --------- hacking/checks/other.py | 54 ---- hacking/checks/python23.py | 228 --------------- hacking/checks/vim_check.py | 39 --- hacking/config.py | 48 ---- hacking/core.py | 164 ----------- hacking/tests/__init__.py | 58 ---- hacking/tests/checks/__init__.py | 0 hacking/tests/checks/test_comments.py | 84 ------ hacking/tests/test_config.py | 58 ---- hacking/tests/test_doctest.py | 97 ------- hacking/tests/test_import_exceptions.py | 53 ---- hacking/tests/test_local.py | 36 --- integration-test/test.sh | 46 --- releasenotes/notes/.placeholder | 0 releasenotes/source/_static/.placeholder | 0 releasenotes/source/conf.py | 283 ------------------ releasenotes/source/index.rst | 8 - releasenotes/source/unreleased.rst | 5 - requirements.txt | 11 - setup.cfg | 77 ----- setup.py | 29 -- test-requirements.txt | 21 -- tools/tox_install.sh | 30 -- tox.ini | 48 ---- 47 files changed, 14 insertions(+), 3157 deletions(-) delete mode 100644 .gitignore delete mode 100644 .gitreview delete mode 100644 .mailmap delete mode 100644 .testr.conf delete mode 100644 CONTRIBUTING.rst delete mode 100644 HACKING.rst delete mode 100644 LICENSE delete mode 100644 MANIFEST.in create mode 100644 README delete mode 100644 README.rst delete mode 100644 doc/source/conf.py delete mode 100644 doc/source/index.rst delete mode 100644 doc/source/user/hacking.rst delete mode 100644 doc/source/user/index.rst delete mode 100644 doc/source/user/usage.rst delete mode 100644 hacking/__init__.py delete mode 100644 hacking/checks/__init__.py delete mode 100644 hacking/checks/comments.py delete mode 100644 hacking/checks/dictlist.py delete mode 100644 hacking/checks/docstrings.py delete mode 100644 hacking/checks/except_checks.py delete mode 100644 hacking/checks/imports.py delete mode 100644 hacking/checks/localization.py delete mode 100644 hacking/checks/other.py delete mode 100644 hacking/checks/python23.py delete mode 100644 hacking/checks/vim_check.py delete mode 100644 hacking/config.py delete mode 100644 hacking/core.py delete mode 100644 hacking/tests/__init__.py delete mode 100644 hacking/tests/checks/__init__.py delete mode 100644 hacking/tests/checks/test_comments.py delete mode 100644 hacking/tests/test_config.py delete mode 100644 hacking/tests/test_doctest.py delete mode 100644 hacking/tests/test_import_exceptions.py delete mode 100644 hacking/tests/test_local.py delete mode 100755 integration-test/test.sh delete mode 100644 releasenotes/notes/.placeholder delete mode 100644 releasenotes/source/_static/.placeholder delete mode 100644 releasenotes/source/conf.py delete mode 100644 releasenotes/source/index.rst delete mode 100644 releasenotes/source/unreleased.rst delete mode 100644 requirements.txt delete mode 100644 setup.cfg delete mode 100644 setup.py delete mode 100644 test-requirements.txt delete mode 100755 tools/tox_install.sh delete mode 100644 tox.ini 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