hacking-0.12.0/0000775000567000056710000000000013010162515014331 5ustar jenkinsjenkins00000000000000hacking-0.12.0/tox.ini0000664000567000056710000000174413010162402015645 0ustar jenkinsjenkins00000000000000[tox] minversion = 1.6 skipsdist = True envlist = py34,py26,py27,pep8,pypy [testenv] usedevelop = True install_command = pip install -U {opts} {packages} setenv = VIRTUAL_ENV={envdir} 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] setenv = VIRTUAL_ENV={envdir} 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 hacking-0.12.0/AUTHORS0000664000567000056710000001345713010162515015413 0ustar jenkinsjenkins00000000000000Aaron Rosen Adrian Smith Akihiro MOTOKI Alessandro Pilotti Alex Gaynor Alex Meade Andreas Jaeger Andreas Jaeger Andrew Bogott Andrew Laski Andy Smith Andy Smith Anthony Young Arvind Somy Arvind Somya asomya@cisco.com <> Asbjørn Sannes Attila Fazekas Ben Nemec Bhuvan Arumugam Brant Knudson Brian Elliott Brian Lamar Brian Waldon Brian Waldon Chang Bo Guo ChangBo Guo(gcb) Chet Burgess Chris Behrens Chris Yeoh Christian Berendt Chuck Short Chuck Short Clark Boylan Clay Gerrard Cyril Roelandt Cyril Roelandt Dan Prince Dan Smith Dan Wendlandt Daniel P. Berrange Darragh Bailey Davanum Srinivas David Pravec David Ripton Derek Higgins Devin Carlen Devin Carlen Dirk Mueller Dolph Mathews Dominik Heidler Doug Hellmann Doug Hellmann Dougal Matthews Ed Leafe Eldar Nugaev Eoghan Glynn Erno Kuvaja Ewan Mellor Ghe Rivero Hengqing Hu Ian Cordasco Ian Cordasco Ilya Alekseyev Ilya Alekseyev Ivan A. Melnikov Ivan A. Melnikov James Carey James E. Blair James E. Blair James E. Blair James E. Blair James Polley Jason Koelker Jason Kölker Jay Lau Jeremy Stanley Jesse Andrews Joe Gordon Joe Heck Johannes Erdfelt John L. Villalovos John Tran Josh Kearney Julien Danjou Justin Santa Barbara Justin Santa Barbara Justin Shepherd Ken Pepple Kui Shi Kurt Taylor Lei Zhang Lorin Hochstein Luis Fernandez Alvarez Marc Abramowitz Mark McLoughlin Mate Lakat Matt Joyce Matt Riedemann Matthew Treinish Michael Gundlach Michal Dulko Mike Perez Mike Pittaro Monty Taylor Nachi Ueno Nattaphoom Chaipreecha Naveed Massjouni Nikola Dipanov Ondřej Nový Paul Voccio Pádraig Brady Radomir Dopieralski Rick Clark Rick Harris Robert Collins Robert Collins Roger Luethi Russell Bryant Samuel Merritt Sandy Walsh Sascha Peilicke Sean Dague Sean Dague Sergey Lukjanov Soren Hansen Soren Hansen Spencer Krum Stanislaw Pitucha Steven Dake Sulochan Acharya Surojit Pathak Thierry Carrez Tim Burke Todd Willey Todd Willey Trey Morris Tushar Patil Vishvananda Ishaya Vishvananda Ishaya William Wolf YAMAMOTO Takashi Yaguang Tang Yong Sheng Gong Yosef Berman Yun Mao Yuriy Taraday ZhiQiang Fan ZhiQiang Fan Zhongyue Luo Zhongyue Luo andy fujioka yuuichi janonymous jaypipes@gmail.com <> jmeridth lzyeval matt.dietz@rackspace.com <> root sateesh termie vladimir.p hacking-0.12.0/setup.py0000664000567000056710000000200413010162402016032 0ustar jenkinsjenkins00000000000000# 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) hacking-0.12.0/LICENSE0000664000567000056710000002363713010162402015344 0ustar jenkinsjenkins00000000000000 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. hacking-0.12.0/setup.cfg0000664000567000056710000000520213010162515016151 0ustar jenkinsjenkins00000000000000[metadata] name = hacking author = OpenStack author-email = openstack-dev@lists.openstack.org summary = OpenStack Hacking Guideline Enforcement description-file = README.rst home-page = http://docs.openstack.org/developer/hacking/ 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.6 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.3 Programming Language :: Python :: 3.4 [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 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 [pbr] warnerrors = True [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 [wheel] universal = 1 hacking-0.12.0/releasenotes/0000775000567000056710000000000013010162515017022 5ustar jenkinsjenkins00000000000000hacking-0.12.0/releasenotes/notes/0000775000567000056710000000000013010162515020152 5ustar jenkinsjenkins00000000000000hacking-0.12.0/releasenotes/notes/.placeholder0000664000567000056710000000000013010162402022416 0ustar jenkinsjenkins00000000000000hacking-0.12.0/releasenotes/source/0000775000567000056710000000000013010162515020322 5ustar jenkinsjenkins00000000000000hacking-0.12.0/releasenotes/source/unreleased.rst0000664000567000056710000000016013010162402023173 0ustar jenkinsjenkins00000000000000============================== Current Series Release Notes ============================== .. release-notes:: hacking-0.12.0/releasenotes/source/index.rst0000664000567000056710000000016613010162402022161 0ustar jenkinsjenkins00000000000000======================= Hacking Release Notes ======================= .. toctree:: :maxdepth: 1 unreleased hacking-0.12.0/releasenotes/source/conf.py0000664000567000056710000002167713010162402021631 0ustar jenkinsjenkins00000000000000# -*- 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 = [ 'oslosphinx', 'reno.sphinxext', ] # 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 = 'default' # 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 = '%b %d, %Y' # 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/'] hacking-0.12.0/releasenotes/source/_static/0000775000567000056710000000000013010162515021750 5ustar jenkinsjenkins00000000000000hacking-0.12.0/releasenotes/source/_static/.placeholder0000664000567000056710000000000013010162402024214 0ustar jenkinsjenkins00000000000000hacking-0.12.0/requirements.txt0000664000567000056710000000053213010162402017610 0ustar jenkinsjenkins00000000000000# 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.6 # 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 hacking-0.12.0/.mailmap0000664000567000056710000000016213010162402015744 0ustar jenkinsjenkins00000000000000# Format is: # Name Joe Gordon hacking-0.12.0/CONTRIBUTING.rst0000664000567000056710000000103213010162402016761 0ustar jenkinsjenkins00000000000000If 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 hacking-0.12.0/integration-test/0000775000567000056710000000000013010162515017631 5ustar jenkinsjenkins00000000000000hacking-0.12.0/integration-test/test.sh0000775000567000056710000000156013010162402021144 0ustar jenkinsjenkins00000000000000#!/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 hacking-0.12.0/PKG-INFO0000664000567000056710000001477313010162515015442 0ustar jenkinsjenkins00000000000000Metadata-Version: 1.1 Name: hacking Version: 0.12.0 Summary: OpenStack Hacking Guideline Enforcement Home-page: http://docs.openstack.org/developer/hacking/ Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description: 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 Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Environment :: Console Classifier: Environment :: OpenStack Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Information Technology Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 hacking-0.12.0/.testr.conf0000664000567000056710000000050013010162402016405 0ustar jenkinsjenkins00000000000000[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 hacking-0.12.0/test-requirements.txt0000664000567000056710000000153313010162402020567 0ustar jenkinsjenkins00000000000000# 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>=3.6 # Apache-2.0 discover # BSD fixtures>=3.0.0 # Apache-2.0/BSD mock>=2.0 # BSD python-subunit>=0.0.18 # Apache-2.0/BSD sphinx!=1.3b1,<1.4,>=1.2.1 # BSD oslosphinx>=4.7.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 # Apache2 hacking-0.12.0/MANIFEST.in0000664000567000056710000000025013010162402016057 0ustar jenkinsjenkins00000000000000include AUTHORS include ChangeLog include README.rst include requirements.txt include test-requirements.txt exclude .gitignore exclude .gitreview global-exclude *.pyc hacking-0.12.0/hacking.egg-info/0000775000567000056710000000000013010162515017427 5ustar jenkinsjenkins00000000000000hacking-0.12.0/hacking.egg-info/not-zip-safe0000664000567000056710000000000113010162513021653 0ustar jenkinsjenkins00000000000000 hacking-0.12.0/hacking.egg-info/SOURCES.txt0000664000567000056710000000230113010162515021307 0ustar jenkinsjenkins00000000000000.mailmap .testr.conf AUTHORS CONTRIBUTING.rst ChangeLog HACKING.rst LICENSE MANIFEST.in README.rst requirements.txt setup.cfg setup.py test-requirements.txt tox.ini doc/source/conf.py doc/source/index.rst doc/source/readme.rst hacking/__init__.py hacking/config.py hacking/core.py hacking.egg-info/PKG-INFO hacking.egg-info/SOURCES.txt hacking.egg-info/dependency_links.txt hacking.egg-info/entry_points.txt hacking.egg-info/not-zip-safe hacking.egg-info/pbr.json hacking.egg-info/requires.txt hacking.egg-info/top_level.txt hacking/checks/__init__.py hacking/checks/comments.py hacking/checks/dictlist.py hacking/checks/docstrings.py hacking/checks/except_checks.py hacking/checks/imports.py hacking/checks/localization.py hacking/checks/other.py hacking/checks/python23.py hacking/checks/vim_check.py hacking/tests/__init__.py hacking/tests/test_config.py hacking/tests/test_doctest.py hacking/tests/test_import_exceptions.py hacking/tests/test_local.py hacking/tests/checks/__init__.py hacking/tests/checks/test_comments.py integration-test/test.sh releasenotes/notes/.placeholder releasenotes/source/conf.py releasenotes/source/index.rst releasenotes/source/unreleased.rst releasenotes/source/_static/.placeholderhacking-0.12.0/hacking.egg-info/pbr.json0000664000567000056710000000005613010162515021106 0ustar jenkinsjenkins00000000000000{"is_release": true, "git_version": "6be124c"}hacking-0.12.0/hacking.egg-info/dependency_links.txt0000664000567000056710000000000113010162515023475 0ustar jenkinsjenkins00000000000000 hacking-0.12.0/hacking.egg-info/entry_points.txt0000664000567000056710000000312113010162515022722 0ustar jenkinsjenkins00000000000000[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 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 hacking-0.12.0/hacking.egg-info/PKG-INFO0000664000567000056710000001477313010162515020540 0ustar jenkinsjenkins00000000000000Metadata-Version: 1.1 Name: hacking Version: 0.12.0 Summary: OpenStack Hacking Guideline Enforcement Home-page: http://docs.openstack.org/developer/hacking/ Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description: 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 Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Environment :: Console Classifier: Environment :: OpenStack Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Information Technology Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 hacking-0.12.0/hacking.egg-info/requires.txt0000664000567000056710000000020213010162515022021 0ustar jenkinsjenkins00000000000000pbr>=1.6 pep8==1.5.7 pyflakes==0.8.1 flake8<2.6.0,>=2.5.4 mccabe==0.2.1 six>=1.9.0 [pep257] flake8-docstrings==0.2.1.post1 # MIT hacking-0.12.0/hacking.egg-info/top_level.txt0000664000567000056710000000001013010162515022150 0ustar jenkinsjenkins00000000000000hacking hacking-0.12.0/hacking/0000775000567000056710000000000013010162515015735 5ustar jenkinsjenkins00000000000000hacking-0.12.0/hacking/tests/0000775000567000056710000000000013010162515017077 5ustar jenkinsjenkins00000000000000hacking-0.12.0/hacking/tests/test_local.py0000664000567000056710000000245513010162402021603 0ustar jenkinsjenkins00000000000000# 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) hacking-0.12.0/hacking/tests/__init__.py0000664000567000056710000000422313010162402021204 0ustar jenkinsjenkins00000000000000# 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__) hacking-0.12.0/hacking/tests/checks/0000775000567000056710000000000013010162515020337 5ustar jenkinsjenkins00000000000000hacking-0.12.0/hacking/tests/checks/test_comments.py0000664000567000056710000000464413010162402023600 0ustar jenkinsjenkins00000000000000# 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')) hacking-0.12.0/hacking/tests/checks/__init__.py0000664000567000056710000000000013010162402022431 0ustar jenkinsjenkins00000000000000hacking-0.12.0/hacking/tests/test_config.py0000664000567000056710000000341713010162402021755 0ustar jenkinsjenkins00000000000000# 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'])) hacking-0.12.0/hacking/tests/test_import_exceptions.py0000664000567000056710000000315313010162402024260 0ustar jenkinsjenkins00000000000000# 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')) hacking-0.12.0/hacking/tests/test_doctest.py0000664000567000056710000000665413010162402022163 0ustar jenkinsjenkins00000000000000#!/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']) 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) hacking-0.12.0/hacking/core.py0000664000567000056710000001105613010162402017235 0ustar jenkinsjenkins00000000000000# 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() hacking-0.12.0/hacking/__init__.py0000664000567000056710000000000013010162402020027 0ustar jenkinsjenkins00000000000000hacking-0.12.0/hacking/checks/0000775000567000056710000000000013010162515017175 5ustar jenkinsjenkins00000000000000hacking-0.12.0/hacking/checks/other.py0000664000567000056710000000342513010162402020667 0ustar jenkinsjenkins00000000000000# 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 hacking-0.12.0/hacking/checks/imports.py0000664000567000056710000000744713010162402021253 0ustar jenkinsjenkins00000000000000# 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])) hacking-0.12.0/hacking/checks/docstrings.py0000664000567000056710000001406513010162402021727 0ustar jenkinsjenkins00000000000000# 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 hacking-0.12.0/hacking/checks/dictlist.py0000664000567000056710000000275613010162402021373 0ustar jenkinsjenkins00000000000000# 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) hacking-0.12.0/hacking/checks/comments.py0000664000567000056710000001424713010162402021377 0ustar jenkinsjenkins00000000000000# 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") hacking-0.12.0/hacking/checks/__init__.py0000664000567000056710000000000013010162402021267 0ustar jenkinsjenkins00000000000000hacking-0.12.0/hacking/checks/localization.py0000664000567000056710000001111713010162402022233 0ustar jenkinsjenkins00000000000000# 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 hacking-0.12.0/hacking/checks/python23.py0000664000567000056710000001615013010162402021233 0ustar jenkinsjenkins00000000000000# 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`)") hacking-0.12.0/hacking/checks/except_checks.py0000664000567000056710000001062313010162402022354 0ustar jenkinsjenkins00000000000000# 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 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): if isinstance(node.func, ast.Attribute): local_func_name = node.func.attr elif isinstance(node.func, ast.Name): local_func_name = node.func.id else: # ast.Subscript, etc. -- ignore local_func_name = None 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" hacking-0.12.0/hacking/checks/vim_check.py0000664000567000056710000000257013010162402021476 0ustar jenkinsjenkins00000000000000# 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" hacking-0.12.0/hacking/config.py0000664000567000056710000000302113010162402017543 0ustar jenkinsjenkins00000000000000# 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 hacking-0.12.0/ChangeLog0000664000567000056710000010166613010162515016115 0ustar jenkinsjenkins00000000000000CHANGES ======= 0.12.0 ------ * Enable release notes translation * Updated from global requirements * Updated from global requirements * Fix issues detected by pycodestyle * Add documentation about off-by-default options * Add optional H203 to check that assertIs(Not)None is used * Updated from global requirements * Add a check for delayed string interpolation * Fix releasenote building * Clean up check signatures * Fix Google Python Style Guide link * Updated from global requirements * Updated from global requirements * Updated from global requirements * Fix H703 test * Updated from global requirements * Updated from global requirements * Add reno and release notes tracking 0.11.0 ------ * Updated from global requirements * Update the assertRaises example to be more modern * Updated from global requirements * Run all flake8 checks * Updated from global requirements * Updated from global requirements * Update flake8 requirement for 0.11.0 * Updated from global requirements * Avoid git clone in integration test * Remove oslo-incubator section in HACKING.rst * Do not call "rm -rf" on arbitrary user input * Update setup.cfg * Put py34 first in the env order of tox * Minor text cleanup * Deprecated tox -downloadcache option removed * Updated from global requirements * Add support for PEP257 * Update docs for i18n exception * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Add editor files to .gitignore * Take advantage of RST formatting for links * Revise adding additional checks section of README * Add example to versioning section of README * Expand origin section of README * Document the reasoning behind general hacking rules * Expand depends documentation in readme * Fix a typo * Add support for flake8 off_by_default for optional checks * Updated from global requirements * whitelist bash in integration test * Drop py33 as a target * Don't shallow clone from file:// in integration test * Updated from global requirements * Updated from global requirements * Change integration test to use git.o.o * tests: allow to run the same test for different code * Updated from global requirements * Fix string formatting in example * Updated from global requirements * Updated from global requirements 0.10.1 ------ * Updated from global requirements * Fix H238 to allow parent classes to be returned by a function * H105: also check for Authors and authors 0.10.0 ------ * Add docstring to is_import_exception * Remove complex import rules * Remove Git commit message checks * Add eventlet to test-requirements * Workflow documentation is now in infra-manual * Allow import redirections * Fixing broken while loop in imports.py * Updated from global requirements * Updated from global requirements * Updated from global requirements * Add H237 to HACKING.rst * Don't change log level as import side effect * Include example of multiple imports using from syntax * Updated from global requirements * Updated from global requirements * Pin mccabe to prevent it from breaking hacking * Updated from global requirements * Updated from global requirements * Add hacking check H105: don't use author tags * Add a check for old style class declarations * Updated from global requirements * Update H501 to check for self.__dict__ * Updated from global requirements * Stop using intersphinx * Updated from global requirements * Work toward Python 3.4 support and testing * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Relax H305 and H307 checks * Fix import check interaction with namespace modules * remove H904 * Updated from global requirements * remove H402 * remove H803, it's mostly an old flamewar * add hacking preamble * Updated from global requirements * Updated from global requirements * Mark hacking as being a universal wheel 0.9.2 ----- * Fixed warning H302 when used with six.moves 0.9.1 ----- * Fix a typo in HACKING.rst * Make import checks properly detect blank lines and comments * Clarify where the "following template" is 0.9.0 ----- * Update localization checks to understand separate catalogs * Update examples for i18n * Updated from global requirements * update Commit Message guidelines * Drop 'not in' and 'is not' tests from HACKING.rst * Add Installation section to the readme * Include rule numbers in HACKING.rst * Add link to readme at bottom of docs.openstack.org/developer/hacking/ * Update pointer to HACKING.rst in the readme * Updated from global requirements * Consider sys.real_prefix for _get_import_type * Add TestCase assertion methods for testing checks * Speed up hacking_import_alphabetical * Speed up hacking_has_correct_license * Fix py33, make sure skip_on_py3 is part of every check * Add noqa everywhere that it is easy to do so * Remove H901,H902 since it is a duplicate of H714,H713 * Move other checks into their own file * Cleanup hacking doc generation * Move git checks into their own file * Move localization checks into their own file * Move docstring/list checks into their own file * Keep setup.cfg flake8.extensions in numerical order * Move docstring checks into their own file * Move import checks into their own file * Compile python 2-> regular expressions * Move python 2->3 checks into their own module * Speed up license checks * Only compile regex for hacking_except_format once * Move except checks into their own module * Move comment checks into their own module * Make test_doctest use entry points * Fix typo: backsplash=>backslash * Updated from global requirements * Import Guideline Exception for gettextutils * Use pep8's noqa argument * Move hacking to pep8 1.5.6 * Minor README.rst tweaks * Updated from global requirements * Add posargs to tox -epep8 * Make hacking pass pep8 1.5.x * Bump pep8, pyflakes and flake8 versions * Disable logging correctly * Make H202 check honor pep8 #noqa comment * Make hacking Python 3 compatible * Updated from global requirements * Updated from global requirements * Switch over to oslosphinx * HACKING.rst: Fix odd indentation in an example code * Remove tox locale overrides * Updated from global requirements * Clarify H403 message * More portable way to detect modules for H302 * Fix python 3 incompatibility in _get_import_type * Trigger warnings for raw and unicode docstrings * Enhance H233 rule * Add check for removed modules in Python 3 * Add Python3 deprecated assert* to HACKING.rst * Turn Python3 section into a list * Re-Add section on assertRaises(Exception * Cleanup HACKING.rst * Move hacking guide to root directory * Fix typo in package summary * Add H904: don't wrap lines using a backslash * checking for metaclass to be Python 3.x compatible * Remove unnecessary headers * Add -U to pip install command in tox.ini * Fix typos of comment in module core * Updated from global requirements * Add a check for file with only comments * Enforce grouping like imports together * Add noqa support for H201 (bare except) * Enforce import grouping * Clean up how test env variables are parsed * Fix the escape character * Remove vim modeline sample * Add a check for newline after docstring summary 0.8.0 ----- * Updated from global requirements * Continue reserving H6xx namespace for calling methods * Fix import grouping * Add assertNotEquals check to H602 * Sync requirements with OS requirements * Allow APL text to start on the first text column * Add noqa support for H231 and H233 * Revert "Adds ability to ignore hacking validations with noqa" * Move the hacking guidelines to sphinx docs * Replace OpenStack LLC with OpenStack Foundation * Update tox to use develop and custom pip command * Add check for deprecated method assert_ * hacking should conform with OS requirements * Redirect stderr for git rev-parse * Use the name for this attribute that exists on Python3 * Add pypy on tox envlist * Adds ability to ignore hacking validations with noqa * Update requirements * Improve H202 to cover more cases * Add check for deprecated method assertEquals * Reword H404 description to match check 0.7.0 ----- * Synced with global requirements * Fix typo in HACKING.rst * python3: Fix tracebacks while running testsuites * Import exceptions list is now configurable * python3: Fix unicode and gettext * python3: Fix python3 tox installation * Extract configs-related code to the configs helper * Update I18N code style * Make H202 work again * Don't crash on tests when git is not installed 0.6.0 ----- * Make H103 Invalid Apache throw error on correct line * Make H232 message mention its py3 related * Add information about the Google style guide * Avoid crash when git commit title cannot be found * Add no locals() for string formatting test * Fix typo in HACKING.rst compatility=>compatibility * Add H233 check for usages of the print operator * Add H232 check for octal number literals * Determine git workdir properly * Reserver a H23x range for Python 3.x compat checks * Add documentation for Apache License check * Strip leading/trailing whitespace from reference License * Add note about checks have community support * Ignore import lines with noqa * Add check for end of title line of commit messages * Include HACKING.rst in MANIFEST.in * Split H102 into 2 checks and enable them * Actually tie pbr versions in setup_requires 0.5.5 ----- * update HACKING.rst to be OpenStack Style Commandments * Add local-check test * Enable all checks during integration test * Add H203: Check for Python 3.x compatible except * Add integration test option to tox * python3: Introduce py33 to tox.ini * Add H402 doctest and other doc cleanups * Update H3xx doctests * Add doctests to H201, H202 and fix False Positive in H202 * Expand H101 docstring tests * Fix tests to redirect stdout * Style-fixes to hacking/core.py * Disable H102 until ready to add new checks * add check that python files have Apache 2.0 license stanza * Remove trailing whitespace in setup.cfg * Add proper README for how to develop on hacking * Rename README to HACKING * Pin the versions of pep8/pyflakes here * Remove an extra word from the H901 error message * Cleanup some docstrings * Fix yield bug for GlobalCheck * Improve unit test output * Add .mailmap file * Stop referencing nova HACKING guide 0.5.4 ----- * Update indentation in setup.cfg * Implement a proxy checker class * Add back in git commit message checking * Remove H307 no db in virt * Add gettext install * Fix homepage location 0.5.2 ----- * Moved hacking to core * Clean up flakes warnings 0.5.1 ----- * Add tests * Fix requirements distribution 0.5.0 ----- * Make hacking a flake8 plugin * Switch to flake8 for pep8 testing * Switch to final 1.1.0 oslo.config release * websockify 0.4 is busted * Pin SQLAlchemy to 0.7.x * Update to Quantum Client 2.2.0 * Update tox.ini to support RHEL 6.x * Switch to oslo.config * docs should indicate proper git commit limit * Fixes oslo-config update for deprecated_group * Regenerate nova.conf.sample * Prevent hacking.py from crashing on unexpected import exception * Bump python-quantumclient version to 2.1.2 * Update OpenStack LLC to Foundation * Improve hackings docstring detection * Unpin PasteDeploy dependency version * Unpin routes dependency version * Unpin suds dependency version * Unpin Cheetah dependency version * Fix hacking.py to handle 'cannot import x' * Fix hacking.py to handle parenthesise in from import as * Remove function redefinitions * Sync latest install_venv_common.py * Fix broken logging imports * Fix hacking test to handle namespace packages * Use oslo-config-2013.1b4 * Fix hacking tests on osx * Harmonize PEP8 checking between tox and run_tests.sh * Fix script argument parsing * Module import style checking changes * Add "is not" test to hacking.py * Update tools/regression_tester * support reloctable venv roots in testing framework * Add regression testing tool * Sync latest install_venv_common from oslo * replace ssh-keygen -m with a python equivalent * Added Postgres CI opportunistic test case * Fix import for install_venv.py * Add 'not in' test to tools/hacking.py * import tools/flakes from oslo * Make sure there are no unused import * Use install_venv_common.py from oslo * Fix hacking N302 import only modules * Make failures in the periodic tests more detailed * Add version constraint for coverage * xenapi: Add cleanup_sm_locks script * Add version constraint for cinder * Cleanup of extract_opts.py * Unpin testtools * Sync latest cfg from oslo-incubator * Avoid testtools 0.9.25 * Go back to the original branch after pylint check * Fix multi line docstring tests in hacking.py * don't allow crs in the code * Pull NovaWebSocketProxy class out of nova-novncproxy binary * Use testrepository setuptools support * Revert "Use testr setuptools commands." * enable hacking.py self tests * Use testr setuptools commands * Try out a new nova.conf.sample format * Regenerate nova.conf.sample * fix N402 on tools/ * Fix lintstack check for multi-patch reviews * fix N401 errors, stop ignoring all N4* errors * Upgrade WebOb to 1.2.3 * Make WebOb version specification more flexible * Import cfg module in extract_opts.py * Replace fixtures.DetailStream with fixtures.StringStream * Use testr to run nova unittests * Move zombie_instance_updated_at_window option * Port to argparse based cfg * Correctly init XenAPIDriver in vm_vdi_cleaner.py * i18n raise Exception messages * Unpin lxml requirements * Update tools/flakes to work with pydoc * Fix pep8 exclude logic for 1.3.3 * Add pyflakes option to tox * Allow newer boto library versions * Add generic customization hooks via decorator * Pin pep8 to 1.3.3 * Use CONF.import_opt() for nova.config opts * Remove nova.config.CONF * Add keystoneclient to pip-requires * Remove nova.flags * Unpin amqplib and kombu requirements * Isolate tests from the environment variable http_proxy * Ban db import from nova/virt * Switch from FLAGS to CONF in misc modules * Remove flags.DECLARE * Move parse_args to nova.config * move python-cinderclient to pip-requires * Force earlier version of sqlalchemy * Remove extra print line in hacking.py * Use testtools as the base testcase class * Change hacking.py N306 to use logical_lines * Fix hacking.py naivete regarding lines that look like imports * Change install_venv to use setup.py develop * Fixes syntax error in nova.tools.esx.guest_tools.py * Proxy floating IP calls to quantum * Remove dependency on python-ldap for tests * Update tools hacking for pep8 1.2 and beyond * Revert "Add full test environment." * Loosen anyjson dependency to avoid clash with ceilometer * Bump the version of SQLAlchemy in pip-requires * Replaced default hostname function from gethostname to getfqdn * Move fakeldap.py from auth dir to tests * Added script to find unused config options * Add flag cinder_endpoint_template to volume.cinder * More specific lxml versions in tools/pip-requires * Set install_requires in setup.py * Nail the pip requirement at 1.1 * Update requires to glanceclient >=0.5.0 * Add lintstack error checker based on pylint * Include CommonConfigOpts options in sample config * Ensure log formats are quoted in sample conf * Don't include hostname and IP in generated sample conf * Allow generate_sample.sh to be run from toplevel dir * Fix hacking.py git checks to propagate errors * Add nosehtmloutput as a test dependency * Cleanup pip dependencies * Make missing imports flag in hacking settable * update python-quantumclient dependency to >=2.0 * Rewrite image code to use python-glanceclient * Add a 50 char git title limit test to hacking * Drop AES functions and pycrypto dependency * Improve external lock implementation * Require eventlet >= 0.9.17 * Fix broken pep8 exclude processing * XenAPI: Add script to destroy cached images * Replace subprocess.check_output with Popen * Xen: Add race-condition troubleshooting script * Add git commit message validation to hacking.py * Fixes XenAPI driver import in vm_vdi_cleaner * Fix venv wrapper to clean *.pyc * modify hacking.py to not choke on the def of _() * Correct typo in tools/hacking.py l18n -> i18n * Implement nova network API for quantum API 2.0 * Switch to common logging * Use setuptools-git plugin for MANIFEST * Align run_tests.py pep8 with tox * Switch to using new config parsing for vm_vdi_cleaner.py * Fix several PEP-8 issues * Add full test environment * Remove unknown shutdown kwarg in call to vmops._destroy * Refactor vm_vdi_cleaner.py connection use * add nova-manage bash completion script * Replaces functions in utils.py with openstack/common/timeutils.py * Finalize tox config * Removing double quotes from sample config file * Backslash continuation removal (Nova folsom-2) * Sample config file tool updates * Use cfg's new global CONF object * Grammar fixes * Cleanup tools/hacking using flake8 * Update pep8 dependency to v1.1 * Nail pep8 dependencies to 1.0.1 * Make validate_compacted_migration into general diff tool * Remove unused tools/rfc.sh * Remove wsgiref from requirements * Add migration compaction validation tool * Modify vm_vdi_cleaner to handle `-orig` * Remove old flagfile support * Trivial spelling fix * Imports to human alphabetical order * Enable InnoDB checking * Use instance_get_by_uuid since we're looking up a UUID * Use nova_uuid attribute instead of trying to parse out name_label * Number of missing imports should always be shown * Improved tools/hacking.py * nova.virt.xenapi_conn -> nova.virt.xenapi.connection * xenapi_conn -> xenapi.connection * Remove python-novaclient dependency from nova * Improved localization testing * Remove nova Direct API * bug 968452 * HACKING fixes, sqlalchemy fix * Remove nova.rpc.impl_carrot * Updated docstrings in /tools as per HACKING * Remove tools/nova-debug * Add VDI chain cleanup script * Hack to fixup absolute pybasedir in nova.conf.sample * Require a more recent version of glance * HACKING fixes, all but sqlalchemy * Remove trailing whitespaces in regular file * Cleans up the create_conf tool * Add assertRaises check to tools/hacking.py as N202 * Clean stale lockfiles on service startup : fixes bug 785955 * Nova options tool enhancements * Support tox-based unittests * nova.conf sample tool * Support non-UTC timestamps in changes-since filter * Get rid of distutils.extra * Require newer versions of SA and SA-Migrate * Remove ajaxterm from Nova * Excise M2Crypto! * Boto 2.2.x failes. Capping pip-requires at 2.1.1 * Add HACKING compliance testing to run_test.sh * Cleanup Imports to match HACKING guidelines * greenlet version inconsistency * Tell users what is about to be installed via sudo * PEP8 remove direct type comparisons * Install a good version of pip in the venv * Rename .nova-venv to .venv * revert using git for novaclient * Relax novaclient and remove redis dependency * Relax dependency on boto 1.9b and nova-adminclient * Add ability to see deleted and active records * Use system M2Crypto package on Oneiric, bug 892271 * Separate metadata api into its own service * install_venv: apply eventlet patch correctly with python 2.7 (#890461) * Workaround for eventlet bug with unit tests in RHEL6.1 * Apply M2Crypto fix for all Fedora-based distributions * Optional --no-site-packages in venv * venv: update distribute as well as pip * Remove nova dependency on vconfig on Linux * Upgrade pip in the venv when we build it * Utility script that makes enforcing PEP8 within git's pre-commit hook as easy as possible * Further changes to the cleaner * Reference orphaned_instance instead of instance * Continue to the next iteration of the loop if an instance is not found * Add support for header version parameter to specify API version * Adds a script that can automatically delete orphaned VDIs. Also had to move some flags around to avoid circular imports * Added ==1.0.4 version specifier to kombu in pip-requires to ensure tests pass in a clean venv * install_venv: pip install M2Crypto doesn't work on Fedora * install_venv: add support for distro specific code * install_venv: remove versioned M2Crypto dependency * install_venv: don't use --no-site-packages with virtualenv * install_venv: pass the --upgrade argument to pip install * install_venv: refactor out pip_install helper * Use latest version of SQLAlchemy * use git config's review.username for rfc.sh * Don't use GitPython for authors check * Fix rfc.sh's check for the project * Add rfc.sh to help with gerrit workflow * cleaned up * Multi-NIC support for vmwareapi virt driver in nova. Does injection of Multi-NIC information to instances with Operating system flavors Ubuntu, Windows and RHEL. vmwareapi virt driver now relies on calls to network manager instead of nova db calls for network configuration information of instance. Re-oranized VMWareVlanBridgeDriver and added session parmeter to methods to use existing session. Also removed session creation code as session comes as argument. Added check for flat_inject flag before attempting an inject operation * Multi-NIC support for vmwareapi virt driver in nova. Does injection of Multi-NIC information to instances with Operating system flavors Ubuntu, Windows and RHEL. vmwareapi virt driver now relies on calls to network manager instead of nova db calls for network configuration information of instance. Ensure if port group is properly associated with vlan_interface specified in case of VLAN networking for instances. Re-oranized VMWareVlanBridgeDriver and added session parmeter to methods to use existing session. Also removed session creation code as session comes as argument. Added check for flat_inject flag before attempting an inject operation. Removed stale code from vmwareapi stubs. Also updated some comments to be more meaningful. Did pep8 and pylint checks. Tried to improve pylint score for newly added lines of code * Adding feedparser to pip-requires * add kombu to pip-requires and contrib/nova.sh * merged with volume_types. no code refactoring yet * Merged with trunk * Added Test Code, doc string, and fixed pip-requiresw * Added monkey patching notification code function w * Merged with trunk * merged with nova-1411 * Resolve conflicts and fixed broken unit testcases * merged with 1382 * Moves image creation from POST /images to POST /servers//action * removing compute monitor * bumping novaclient version * Merged with trunk and fixed broken unit test cases * merged with 1320 * some file attrib changes * - Fixed the conflift in vmops.py * VSA: first cut. merged with 1279 * Changed broken perms * Updates some of the extra scripts in contrib and tools to current versions * merged trunk * This branch adds additional capability to the hosts API extension. The new options allow an admin to reboot or shutdown a host. I also added code to hide this extension if the --allow-admin-api is False, as regular users should have no access to host API calls * uses 2.6.0 novaclient (OS API 1.1 support) * Removed duplicate xattr from pip-requires * Merged trunk * Fixed several typos * Fixing lxml version requirement * Added xml schema validation for extensions resources. Added corresponding xml schemas. Added lxml dep, which is needed for doing xml schema validation * merged trunk * merged trunk * merged trunk * merged trunk * python-novaclient 2.5.8 is required * trunk merge with migration renumbering * trunk merge * merged trunk, fixed the floating_ip fixed_ip exception stupidity * updated pip-requires for novaclient * pip requires * moved migration again & trunk merge * Re-worked some of the WSGI and WSGIService code to make launching WSGI services easier, less error prone, and more testable. Added tests for WSGI server, new WSGI loader, and modified integration tests where needed * Adds support for "extra specs", additional capability requirements associated with instance types * Added floating IP support in OS API * trunk merge, getting fierce. * Merged trunk * - Modified NOTE in vm_util.py - Changed gettext line to nova default in guest_tool.py * missed the bin line * make nova-debug work with new style instances * remove extra stuff from clean vlans * Upstream merge * Renamed _inst_type_query_to_dict -> _dict_with_extra_specs * trunk merged. conflicts resolved * Fixed the default arguments to None instead of an empty list * Fixing PEP8 compliance issues * trunk merge * trunk merge and migration bump * pip-requires * Stop trying to set a body for HTTP methods that do not allow it. It renders the unit tests useless (since they're testing a situation that can never arise) and webob 1.0.8 fails if you do this * Bump WebOb requirement to 1.0.8 in pip-requires * Cleanup and addition of tests for WSGI server * Fix for lp:796834 * merged trunk * floating_ips extension is loading to api now * pip novaclient bump * fixed up some little project_id things with new novaclient * tests working after merge-3 update * merged koelkers tests branch * tweaks * Dropped requirement for IPy * merge with trey * Fixed pip-requires double requirement * added nova_adminclient to tools/pip-requires * merged trunk * Added paramiko to tools/pip-requires * fix pep8 issues * pep8 fixes * now pip-requires mox version 0.5.3 * Fixed all pep8 errors in tools/install_venv.py. All tests pass * fixed pep8 spacing issue * merge from trunk and update .mailmap file * Added GitPython to [install_dir]/tools/pip-requires * Added Python packages needed for coverage reports to virtualenv packages * got rid of extra whitespace * Update tools/pip-requires and tools/install_venv.py for python2.7 support (works in ubuntu 11.04) * Remove zope.interface from the requires file since it is not used anywhere * remove zope.interface requires * use 'is not None' instead of '!= None' * Add a patch for python eventlet, when using install_venv.py (see FAQ # 1485) * Removed adminclient.py and added reference to the new nova-adminclient project in tools/pip-requires * Add euca2ools import * Make euca-get-ajax-console work with Euca2ools 1.3 * Removed adminclient and referred to pypi nova_adminclient module * The VNC Proxy is an OpenStack component that allows users of Nova to access their instances through a websocket enabled browser (like Google Chrome) * Removed iso8601 dep from pip-requires * Added MUCH more flexiable iso8601 parser dep for added stability * merge trunk * incorporate feedback from termie * Implementation of blueprint hypervisor-vmware-vsphere-support. (Link to blueprint: https://blueprints.launchpad.net/nova/+spec/hypervisor-vmware-vsphere-support) * Enable flat manager support for ipv6 * disable-msg -> disable * * Updated document vmware_readme.rst to mention VLAN networking * Corrected docstrings as per pep0257 recommentations. * Stream-lined the comments. * Updated code with locals() where ever applicable. * VIM : It stands for VMware Virtual Infrastructure Methodology. We have used the terminology from VMware. we have added a question in FAQ inside vmware_readme.rst in doc/source * New fake db: vmwareapi fake module uses a different set of fields and hence the structures required are different. Ex: bridge : 'xenbr0' does not hold good for VMware environment and bridge : 'vmnic0' is used instead. Also return values varies, hence went for implementing separate fake db. * Now using eventlet library instead and removed io_utils.py from branch. * Now using glance.client.Client instead of homegrown code to talk to Glance server to handle images. * Corrected all mis-spelled function names and corresponding calls. Yeah, an auto-complete side-effect! * Reverted unmodified files * fixed conflicts after merging with trunk with 787 * Introduces the ZoneManager to the Scheduler which polls the child zones and caches their availability and capabilities * Moved guest_tool.py from etc/esx directory to tools/esx directory * * Updated readme file with installation of suds-0.4 through easy_install. * Removed pass functions * Fixed pep8 errors * Few bug fixes and other commits * trunk merge, pip-requires and novatools to novaclient changes * initial commit of vnc support * replaced ConnectionFailed with Exception in tools/euca-get-ajax-console was not working for me with euca2tools 1.2 (version 2007-10-10, release 31337) * pip requires novatools * fixes doc build and setup.py fail in virtualenv * merge from upstream and fix small issues * Implement support for streaming images from Glance when using the XenAPI virtualization backend, as per the bexar-xenapi-support-for-glance blueprint * This removes the need for the custom udev rule for iscsi devices. It instead attaches the device based on /dev/disk/by-path/ which should make the setup of nova-volume a little easier * merge from upstream * Merged with trunk revno 565 * Added netaddr for pip-requires * add support for database migration * Merged with trunk * merge trunk, fix conflict * use by-path instead of custom udev script * Now tries to install virtualenv via easy_install if not present * Add glance to pip-requires, as we're now using the Glance client code from Nova * consolidate boto_extensions.py and euca-get-ajax-console, fix bugs from previous trunk merge * merge trunk * add timeout constant, set to 5 minutes * merge trunk * merged trunk, resolved trivial conflict * merged trunk, resolved conflict * better bin name, and pep8 * add license * move euca-get-ajax-console up one directory * merge trunk * rewrite proxy to not use twisted * working connection security * connecting ajax proxy to rabbit to allow token based security * remove a debugging line * merging in trunk * prototype works with kvm. now moving call from api to compute * Use paste.deploy for running the api server * Make nova work even when user has LANG or LC_ALL configured * Added Twisted version dependency into pip-requires * add bzr to the dev dependencies * merged Justin Santa Barbara's raw-disk-image back into the latest trunk * Adds nova-debug to tools directory, for debugging of instances that lose networking * basics to get proxied ajaxterm working with virsh * renamed target_id to iscsi_target * nova-debug, relaunch an instance with a serial console * Duplicate the two trivial escaping functions remaining from tornado's code and remove the dependency * ISCSI Volume support * merge lp:nova * fix typo in boto line of pip-requires * reverted python-boto version in pip-requires to 1.9b1.\ * Merged with trunk, fixed broken stuff * Cleans up the unit tests that are meant to be run with nosetests * improved commenting * reorganize iptables clear and make sure use_nova_chains is a boolean * disable output drop for the moment because it is too restrictive * allow mgmt ip access to api * flush the nova chains * add a reset command * improved the shell script for iptables * put setup_iptables in the right dir * renamed ipchains to iptables * merged fix-iptables * Support querying version list, per the RS API spec. Fixes bug 613117 * A small fix to the install_venv program to allow us to run it on the tarmac box as part of the tarmac build * add in a few comments * s/\t/ /g, and add some comments * add security and session timeout to ajaxterm * initial commit of ajaxterm * Added iptables host initial configuration * Support querying version list * New version of eventlet handles Twisted & eventlet running at the same time * add sqlalchemy to pip requires * Fix a pep8 violation * A few small changes to install_venv to let venv builds work on the tarmac box * Merged with trunk * Fix to better reflect (my believed intent) as to the meaning of error_ok (ignore stderr vs accept failure) * Merged with trunk * pep8 typo * Changed our minds: keep pylint equal to Ubuntu Lucid version, and use disable-msg throughout * Fix pep8 violation * See description of change... what's the difference between that message and this message again? * Simpler installation, and, can run install_venv from anywhere instead of just from checkout root * Make WSGI routing support routing to WSGI apps or to controller+action * updated virtualenv to add eventlet, which is now a requirement * Changes the run_tests.sh and /tools/install_venv.py scripts to be more user-friendly and not depend on PIP while not in the virtual environment * work on a router that works with wsgi and non-wsgi routing * Oops, we need eventlet as well * Quick fix on location of printouts when trying to install virtualenv * Changes the run_tests.sh and /tools/install_venv.py scripts to be more user-friendly and not depend on PIP while not in the virtual environment. Running run_tests.sh should not just work out of the box on all systems supporting easy_install.. * 2 changes in doing PEP8 & Pylint cleaning: * adding pep8 and pylint to the PIP requirements files for Tools * light cleaning work (mostly formatting) on nova/endpoints/cloud.py * Run correctly even if called while in tools/ directory, as 'python install_venv.py' * Greater compliance with pep8/pylint style checks * adding pep8 and pylint for regular cleanup tasks * Added Cheetah to pip-requires * Added exit code checking to process.py (twisted process utils). A bit of class refactoring to make it work & cleaner. Also added some more instructive messages to install_venv.py, because otherwise people that don't know what they're doing will install the wrong pip... i.e. I did :-) * resolving conflict w/ merge, cleaning up virtenv setups * Fixes to the virtualenv installer * Move virtualenv installation out of the makefile * Adds a Makefile to fill dependencies for testing * update copyrights * Removed trailing whitespace from header * Updated licenses * Removed trailing whitespace from header * Updated licenses * tools to clean vlans and run our old install script hacking-0.12.0/HACKING.rst0000664000567000056710000002554713010162402016137 0ustar jenkinsjenkins00000000000000.. _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 hacking-0.12.0/README.rst0000664000567000056710000001106213010162402016013 0ustar jenkinsjenkins00000000000000Introduction ============ 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 hacking-0.12.0/doc/0000775000567000056710000000000013010162515015076 5ustar jenkinsjenkins00000000000000hacking-0.12.0/doc/source/0000775000567000056710000000000013010162515016376 5ustar jenkinsjenkins00000000000000hacking-0.12.0/doc/source/index.rst0000664000567000056710000000012713010162402020232 0ustar jenkinsjenkins00000000000000.. include:: ../../HACKING.rst Readme ====== .. toctree:: :maxdepth: 1 readme hacking-0.12.0/doc/source/conf.py0000664000567000056710000000315313010162402017672 0ustar jenkinsjenkins00000000000000# -*- 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', 'oslosphinx'] # 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 -------------------------------------------------- # 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'), ] hacking-0.12.0/doc/source/readme.rst0000664000567000056710000000003613010162402020357 0ustar jenkinsjenkins00000000000000.. include:: ../../README.rst