[Python-modules-commits] [python-mccabe] 01/09: Import python-mccabe_0.5.2.orig.tar.gz
Ondřej Nový
onovy at moszumanska.debian.org
Sun Aug 7 20:43:09 UTC 2016
This is an automated email from the git hooks/post-receive script.
onovy pushed a commit to branch master
in repository python-mccabe.
commit 80fa828b637fd83b885732ce7484607e649e43f2
Author: Ondřej Nový <onovy at debian.org>
Date: Sun Aug 7 22:28:16 2016 +0200
Import python-mccabe_0.5.2.orig.tar.gz
---
LICENSE | 25 ++++++
MANIFEST.in | 3 +
PKG-INFO | 61 +++++++++++--
README.rst | 47 +++++++++-
mccabe.egg-info/PKG-INFO | 61 +++++++++++--
mccabe.egg-info/SOURCES.txt | 4 +
mccabe.py | 115 +++++++++++++++---------
setup.cfg | 6 ++
setup.py | 15 +++-
test_mccabe.py | 211 ++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 487 insertions(+), 61 deletions(-)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8fd356e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,25 @@
+Copyright © <year> Ned Batchelder
+Copyright © 2011-2013 Tarek Ziade <tarek at ziade.org>
+Copyright © 2013 Florent Xicluna <florent.xicluna at gmail.com>
+
+Licensed under the terms of the Expat License
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation files
+(the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..0a584e0
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,3 @@
+include LICENSE
+include README.rst
+include test_mccabe.py
diff --git a/PKG-INFO b/PKG-INFO
index c6d4a24..19364d8 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,10 +1,10 @@
Metadata-Version: 1.1
Name: mccabe
-Version: 0.2.1
+Version: 0.5.2
Summary: McCabe checker, plugin for flake8
-Home-page: https://github.com/flintwork/mccabe
-Author: Florent Xicluna
-Author-email: florent.xicluna at gmail.com
+Home-page: https://github.com/pycqa/mccabe
+Author: Ian Cordasco
+Author-email: graffatcolmingov at gmail.com
License: Expat license
Description: McCabe complexity checker
=========================
@@ -55,7 +55,7 @@ Description: McCabe complexity checker
...
coolproject/mod.py:1204:1: C901 'CoolFactory.prepare' is too complex (14)
- This feature is quite useful to detect over-complex code. According to McCabe,
+ This feature is quite useful to detect over-complex code. According to McCabe,
anything that goes beyond 10 is too complex.
@@ -73,6 +73,49 @@ Description: McCabe complexity checker
Changes
-------
+ 0.5.2 - 2016-07-31
+ ``````````````````
+
+ * When opening files ourselves, make sure we always name the file variable
+
+ 0.5.1 - 2016-07-28
+ ``````````````````
+
+ * Set default maximum complexity to -1 on the class itself
+
+ 0.5.0 - 2016-05-30
+ ``````````````````
+
+ * PyCon 2016 PDX release
+
+ * Add support for Flake8 3.0
+
+ 0.4.0 - 2016-01-27
+ ``````````````````
+
+ * Stop testing on Python 3.2
+
+ * Add support for async/await keywords on Python 3.5 from PEP 0492
+
+ 0.3.1 - 2015-06-14
+ ``````````````````
+
+ * Include ``test_mccabe.py`` in releases.
+
+ * Always coerce the ``max_complexity`` value from Flake8's entry-point to an
+ integer.
+
+ 0.3 - 2014-12-17
+ ````````````````
+
+ * Computation was wrong: the mccabe complexity starts at 1, not 2.
+
+ * The ``max-complexity`` value is now inclusive. E.g.: if the
+ value is 10 and the reported complexity is 10, then it passes.
+
+ * Add tests.
+
+
0.2.1 - 2013-04-03
``````````````````
@@ -83,7 +126,7 @@ Description: McCabe complexity checker
0.2 - 2013-02-22
````````````````
- * Rename project ``flint-mccabe`` to ``mccabe``.
+ * Rename project to ``mccabe``.
* Provide ``flake8.extension`` setuptools entry point.
@@ -98,13 +141,17 @@ Description: McCabe complexity checker
Keywords: flake8 mccabe
Platform: UNKNOWN
-Classifier: Development Status :: 3 - Alpha
+Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Quality Assurance
diff --git a/README.rst b/README.rst
index 7025637..d9401d1 100644
--- a/README.rst
+++ b/README.rst
@@ -47,7 +47,7 @@ higher that the value::
...
coolproject/mod.py:1204:1: C901 'CoolFactory.prepare' is too complex (14)
-This feature is quite useful to detect over-complex code. According to McCabe,
+This feature is quite useful to detect over-complex code. According to McCabe,
anything that goes beyond 10 is too complex.
@@ -65,6 +65,49 @@ Links
Changes
-------
+0.5.2 - 2016-07-31
+``````````````````
+
+* When opening files ourselves, make sure we always name the file variable
+
+0.5.1 - 2016-07-28
+``````````````````
+
+* Set default maximum complexity to -1 on the class itself
+
+0.5.0 - 2016-05-30
+``````````````````
+
+* PyCon 2016 PDX release
+
+* Add support for Flake8 3.0
+
+0.4.0 - 2016-01-27
+``````````````````
+
+* Stop testing on Python 3.2
+
+* Add support for async/await keywords on Python 3.5 from PEP 0492
+
+0.3.1 - 2015-06-14
+``````````````````
+
+* Include ``test_mccabe.py`` in releases.
+
+* Always coerce the ``max_complexity`` value from Flake8's entry-point to an
+ integer.
+
+0.3 - 2014-12-17
+````````````````
+
+* Computation was wrong: the mccabe complexity starts at 1, not 2.
+
+* The ``max-complexity`` value is now inclusive. E.g.: if the
+ value is 10 and the reported complexity is 10, then it passes.
+
+* Add tests.
+
+
0.2.1 - 2013-04-03
``````````````````
@@ -75,7 +118,7 @@ Changes
0.2 - 2013-02-22
````````````````
-* Rename project ``flint-mccabe`` to ``mccabe``.
+* Rename project to ``mccabe``.
* Provide ``flake8.extension`` setuptools entry point.
diff --git a/mccabe.egg-info/PKG-INFO b/mccabe.egg-info/PKG-INFO
index c6d4a24..19364d8 100644
--- a/mccabe.egg-info/PKG-INFO
+++ b/mccabe.egg-info/PKG-INFO
@@ -1,10 +1,10 @@
Metadata-Version: 1.1
Name: mccabe
-Version: 0.2.1
+Version: 0.5.2
Summary: McCabe checker, plugin for flake8
-Home-page: https://github.com/flintwork/mccabe
-Author: Florent Xicluna
-Author-email: florent.xicluna at gmail.com
+Home-page: https://github.com/pycqa/mccabe
+Author: Ian Cordasco
+Author-email: graffatcolmingov at gmail.com
License: Expat license
Description: McCabe complexity checker
=========================
@@ -55,7 +55,7 @@ Description: McCabe complexity checker
...
coolproject/mod.py:1204:1: C901 'CoolFactory.prepare' is too complex (14)
- This feature is quite useful to detect over-complex code. According to McCabe,
+ This feature is quite useful to detect over-complex code. According to McCabe,
anything that goes beyond 10 is too complex.
@@ -73,6 +73,49 @@ Description: McCabe complexity checker
Changes
-------
+ 0.5.2 - 2016-07-31
+ ``````````````````
+
+ * When opening files ourselves, make sure we always name the file variable
+
+ 0.5.1 - 2016-07-28
+ ``````````````````
+
+ * Set default maximum complexity to -1 on the class itself
+
+ 0.5.0 - 2016-05-30
+ ``````````````````
+
+ * PyCon 2016 PDX release
+
+ * Add support for Flake8 3.0
+
+ 0.4.0 - 2016-01-27
+ ``````````````````
+
+ * Stop testing on Python 3.2
+
+ * Add support for async/await keywords on Python 3.5 from PEP 0492
+
+ 0.3.1 - 2015-06-14
+ ``````````````````
+
+ * Include ``test_mccabe.py`` in releases.
+
+ * Always coerce the ``max_complexity`` value from Flake8's entry-point to an
+ integer.
+
+ 0.3 - 2014-12-17
+ ````````````````
+
+ * Computation was wrong: the mccabe complexity starts at 1, not 2.
+
+ * The ``max-complexity`` value is now inclusive. E.g.: if the
+ value is 10 and the reported complexity is 10, then it passes.
+
+ * Add tests.
+
+
0.2.1 - 2013-04-03
``````````````````
@@ -83,7 +126,7 @@ Description: McCabe complexity checker
0.2 - 2013-02-22
````````````````
- * Rename project ``flint-mccabe`` to ``mccabe``.
+ * Rename project to ``mccabe``.
* Provide ``flake8.extension`` setuptools entry point.
@@ -98,13 +141,17 @@ Description: McCabe complexity checker
Keywords: flake8 mccabe
Platform: UNKNOWN
-Classifier: Development Status :: 3 - Alpha
+Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Quality Assurance
diff --git a/mccabe.egg-info/SOURCES.txt b/mccabe.egg-info/SOURCES.txt
index d3d8176..ae3a707 100644
--- a/mccabe.egg-info/SOURCES.txt
+++ b/mccabe.egg-info/SOURCES.txt
@@ -1,6 +1,10 @@
+LICENSE
+MANIFEST.in
README.rst
mccabe.py
+setup.cfg
setup.py
+test_mccabe.py
mccabe.egg-info/PKG-INFO
mccabe.egg-info/SOURCES.txt
mccabe.egg-info/dependency_links.txt
diff --git a/mccabe.py b/mccabe.py
index 4ea34be..c40381a 100644
--- a/mccabe.py
+++ b/mccabe.py
@@ -7,6 +7,8 @@ from __future__ import with_statement
import optparse
import sys
+import tokenize
+
from collections import defaultdict
try:
import ast
@@ -14,7 +16,7 @@ try:
except ImportError: # Python 2.5
from flake8.util import ast, iter_child_nodes
-__version__ = '0.2.1'
+__version__ = '0.5.2'
class ASTVisitor(object):
@@ -67,6 +69,8 @@ class PathGraph(object):
def connect(self, n1, n2):
self.nodes[n1].append(n2)
+ # Ensure that the destination node is always counted.
+ self.nodes[n2] = []
def to_dot(self):
print('subgraph {')
@@ -131,6 +135,8 @@ class PathGraphingAstVisitor(ASTVisitor):
self.graphs["%s%s" % (self.classname, node.name)] = self.graph
self.reset()
+ visitAsyncFunctionDef = visitFunctionDef
+
def visitClassDef(self, node):
old_classname = self.classname
self.classname += node.name + "."
@@ -156,38 +162,41 @@ class PathGraphingAstVisitor(ASTVisitor):
visitAssert = visitAssign = visitAugAssign = visitDelete = visitPrint = \
visitRaise = visitYield = visitImport = visitCall = visitSubscript = \
visitPass = visitContinue = visitBreak = visitGlobal = visitReturn = \
- visitSimpleStatement
+ visitAwait = visitSimpleStatement
def visitLoop(self, node):
name = "Loop %d" % node.lineno
+ self._subgraph(node, name)
+
+ visitAsyncFor = visitFor = visitWhile = visitLoop
+ def visitIf(self, node):
+ name = "If %d" % node.lineno
+ self._subgraph(node, name)
+
+ def _subgraph(self, node, name, extra_blocks=()):
+ """create the subgraphs representing any `if` and `for` statements"""
if self.graph is None:
# global loop
self.graph = PathGraph(name, name, node.lineno)
pathnode = PathNode(name)
- self.tail = pathnode
- self.dispatch_list(node.body)
+ self._subgraph_parse(node, pathnode, extra_blocks)
self.graphs["%s%s" % (self.classname, name)] = self.graph
self.reset()
else:
pathnode = self.appendPathNode(name)
- self.tail = pathnode
- self.dispatch_list(node.body)
- bottom = PathNode("", look='point')
- self.graph.connect(self.tail, bottom)
- self.graph.connect(pathnode, bottom)
- self.tail = bottom
+ self._subgraph_parse(node, pathnode, extra_blocks)
- # TODO: else clause in node.orelse
-
- visitFor = visitWhile = visitLoop
-
- def visitIf(self, node):
- name = "If %d" % node.lineno
- pathnode = self.appendPathNode(name)
+ def _subgraph_parse(self, node, pathnode, extra_blocks):
+ """parse the body and any `else` block of `if` and `for` statements"""
loose_ends = []
+ self.tail = pathnode
self.dispatch_list(node.body)
loose_ends.append(self.tail)
+ for extra in extra_blocks:
+ self.tail = pathnode
+ self.dispatch_list(extra.body)
+ loose_ends.append(self.tail)
if node.orelse:
self.tail = pathnode
self.dispatch_list(node.orelse)
@@ -202,25 +211,17 @@ class PathGraphingAstVisitor(ASTVisitor):
def visitTryExcept(self, node):
name = "TryExcept %d" % node.lineno
- pathnode = self.appendPathNode(name)
- loose_ends = []
- self.dispatch_list(node.body)
- loose_ends.append(self.tail)
- for handler in node.handlers:
- self.tail = pathnode
- self.dispatch_list(handler.body)
- loose_ends.append(self.tail)
- if pathnode:
- bottom = PathNode("", look='point')
- for le in loose_ends:
- self.graph.connect(le, bottom)
- self.tail = bottom
+ self._subgraph(node, name, extra_blocks=node.handlers)
+
+ visitTry = visitTryExcept
def visitWith(self, node):
name = "With %d" % node.lineno
self.appendPathNode(name)
self.dispatch_list(node.body)
+ visitAsyncWith = visitWith
+
class McCabeChecker(object):
"""McCabe cyclomatic complexity checker."""
@@ -228,20 +229,33 @@ class McCabeChecker(object):
version = __version__
_code = 'C901'
_error_tmpl = "C901 %r is too complex (%d)"
- max_complexity = 0
+ max_complexity = -1
def __init__(self, tree, filename):
self.tree = tree
@classmethod
def add_options(cls, parser):
- parser.add_option('--max-complexity', default=-1, action='store',
- type='int', help="McCabe complexity threshold")
- parser.config_options.append('max-complexity')
+ flag = '--max-complexity'
+ kwargs = {
+ 'default': -1,
+ 'action': 'store',
+ 'type': 'int',
+ 'help': 'McCabe complexity threshold',
+ 'parse_from_config': 'True',
+ }
+ config_opts = getattr(parser, 'config_options', None)
+ if isinstance(config_opts, list):
+ # Flake8 2.x
+ kwargs.pop('parse_from_config')
+ parser.add_option(flag, **kwargs)
+ parser.config_options.append('max-complexity')
+ else:
+ parser.add_option(flag, **kwargs)
@classmethod
def parse_options(cls, options):
- cls.max_complexity = options.max_complexity
+ cls.max_complexity = int(options.max_complexity)
def run(self):
if self.max_complexity < 0:
@@ -249,7 +263,7 @@ class McCabeChecker(object):
visitor = PathGraphingAstVisitor()
visitor.preorder(self.tree, visitor)
for graph in visitor.graphs.values():
- if graph.complexity() >= self.max_complexity:
+ if graph.complexity() > self.max_complexity:
text = self._error_tmpl % (graph.entity, graph.complexity())
yield graph.lineno, 0, text, type(self)
@@ -280,18 +294,36 @@ def get_module_complexity(module_path, threshold=7):
return get_code_complexity(code, threshold, filename=module_path)
-def main(argv):
+def _read(filename):
+ if (2, 5) < sys.version_info < (3, 0):
+ with open(filename, 'rU') as f:
+ return f.read()
+ elif (3, 0) <= sys.version_info < (4, 0):
+ """Read the source code."""
+ try:
+ with open(filename, 'rb') as f:
+ (encoding, _) = tokenize.detect_encoding(f.readline)
+ except (LookupError, SyntaxError, UnicodeError):
+ # Fall back if file encoding is improperly declared
+ with open(filename, encoding='latin-1') as f:
+ return f.read()
+ with open(filename, 'r', encoding=encoding) as f:
+ return f.read()
+
+
+def main(argv=None):
+ if argv is None:
+ argv = sys.argv[1:]
opar = optparse.OptionParser()
opar.add_option("-d", "--dot", dest="dot",
help="output a graphviz dot file", action="store_true")
opar.add_option("-m", "--min", dest="threshold",
help="minimum complexity for output", type="int",
- default=2)
+ default=1)
options, args = opar.parse_args(argv)
- with open(args[0], "rU") as mod:
- code = mod.read()
+ code = _read(args[0])
tree = compile(code, args[0], "exec", ast.PyCF_ONLY_AST)
visitor = PathGraphingAstVisitor()
visitor.preorder(tree, visitor)
@@ -299,7 +331,8 @@ def main(argv):
if options.dot:
print('graph {')
for graph in visitor.graphs.values():
- if graph.complexity() >= options.threshold:
+ if (not options.threshold or
+ graph.complexity() >= options.threshold):
graph.to_dot()
print('}')
else:
diff --git a/setup.cfg b/setup.cfg
index 861a9f5..878645d 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,3 +1,9 @@
+[wheel]
+universal = 1
+
+[aliases]
+test = pytest
+
[egg_info]
tag_build =
tag_date = 0
diff --git a/setup.py b/setup.py
index af7c7d3..e59903d 100644
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
+
from setuptools import setup
@@ -26,26 +27,32 @@ setup(
keywords='flake8 mccabe',
author='Tarek Ziade',
author_email='tarek at ziade.org',
- maintainer='Florent Xicluna',
- maintainer_email='florent.xicluna at gmail.com',
- url='https://github.com/flintwork/mccabe',
+ maintainer='Ian Cordasco',
+ maintainer_email='graffatcolmingov at gmail.com',
+ url='https://github.com/pycqa/mccabe',
license='Expat license',
py_modules=['mccabe'],
zip_safe=False,
+ setup_requires=['pytest-runner'],
+ tests_require=['pytest'],
entry_points={
'flake8.extension': [
'C90 = mccabe:McCabeChecker',
],
},
classifiers=[
- 'Development Status :: 3 - Alpha',
+ 'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.3',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Software Development :: Quality Assurance',
],
diff --git a/test_mccabe.py b/test_mccabe.py
new file mode 100644
index 0000000..44fb565
--- /dev/null
+++ b/test_mccabe.py
@@ -0,0 +1,211 @@
+import unittest
+import sys
+try:
+ from StringIO import StringIO
+except ImportError:
+ from io import StringIO
+
+import pytest
+
+import mccabe
+from mccabe import get_code_complexity
+
+
+# Snippets are put outside of testcases because of spacing issue that would
+# otherwise occur with triple quoted strings.
+trivial = 'def f(): pass'
+
+
+sequential = """\
+def f(n):
+ k = n + 4
+ s = k + n
+ return s
+"""
+
+
+sequential_unencapsulated = """\
+k = 2 + 4
+s = k + 3
+"""
+
+
+if_elif_else_dead_path = """\
+def f(n):
+ if n > 3:
+ return "bigger than three"
+ elif n > 4:
+ return "is never executed"
+ else:
+ return "smaller than or equal to three"
+"""
+
+
+for_loop = """\
+def f():
+ for i in range(10):
+ print(i)
+"""
+
+
+for_else = """\
+def f(mylist):
+ for i in mylist:
+ print(i)
+ else:
+ print(None)
+"""
+
+
+recursive = """\
+def f(n):
+ if n > 4:
+ return f(n - 1)
+ else:
+ return n
+"""
+
+
+nested_functions = """\
+def a():
+ def b():
+ def c():
+ pass
+ c()
+ b()
+"""
+
+try_else = """\
+try:
+ print(1)
+except TypeA:
+ print(2)
+except TypeB:
+ print(3)
+else:
+ print(4)
+"""
+
+async_keywords = """\
+async def foobar(a, b, c):
+ await whatever(a, b, c)
+ if await b:
+ pass
+
+ async with c:
+ pass
+
+ async for x in a:
+ pass
+"""
+
+
+def get_complexity_number(snippet, strio, max=0):
+ """Get the complexity number from the printed string."""
+ # Report from the lowest complexity number.
+ get_code_complexity(snippet, max)
+ strio_val = strio.getvalue()
+ if strio_val:
+ return int(strio_val.split()[-1].strip("()"))
+ else:
+ return None
+
+
+class McCabeTestCase(unittest.TestCase):
+ def setUp(self):
+ # If not assigned to sys.stdout then getvalue() won't capture anything.
+ self._orig_stdout = sys.stdout
+ sys.stdout = self.strio = StringIO()
+
+ def tearDown(self):
+ # https://mail.python.org/pipermail/tutor/2012-January/088031.html
+ self.strio.close()
+ sys.stdout = self._orig_stdout
+
+ def assert_complexity(self, snippet, max):
+ complexity = get_complexity_number(snippet, self.strio)
+ self.assertEqual(complexity, max)
+
+ # should have the same complexity when inside a function as well.
+ infunc = 'def f():\n ' + snippet.replace('\n', '\n ')
+ complexity = get_complexity_number(infunc, self.strio)
+ self.assertEqual(complexity, max)
+
+ def test_print_message(self):
+ get_code_complexity(sequential, 0)
+ printed_message = self.strio.getvalue()
+ self.assertEqual(printed_message,
+ "stdin:1:1: C901 'f' is too complex (1)\n")
+
+ def test_sequential_snippet(self):
+ complexity = get_complexity_number(sequential, self.strio)
+ self.assertEqual(complexity, 1)
+
+ def test_sequential_unencapsulated_snippet(self):
+ complexity = get_complexity_number(sequential_unencapsulated,
+ self.strio)
+ self.assertEqual(complexity, None)
+
+ def test_if_elif_else_dead_path_snippet(self):
+ complexity = get_complexity_number(if_elif_else_dead_path, self.strio)
+ # Paths that will never be executed are counted!
+ self.assertEqual(complexity, 3)
+
+ def test_for_loop_snippet(self):
+ complexity = get_complexity_number(for_loop, self.strio)
+ # The for loop adds an execution path; sometimes it won't be run.
+ self.assertEqual(complexity, 2)
+
+ def test_for_else_snippet(self):
+ complexity = get_complexity_number(for_else, self.strio)
+ # The for loop doesn't add an execution path, but its `else` does
+ self.assertEqual(complexity, 2)
+
+ def test_recursive_snippet(self):
+ complexity = get_complexity_number(recursive, self.strio)
+ self.assertEqual(complexity, 2)
+
+ def test_nested_functions_snippet(self):
+ complexity = get_complexity_number(nested_functions, self.strio)
+ self.assertEqual(complexity, 3)
+
+ def test_trivial(self):
+ """The most-trivial program should pass a max-complexity=1 test"""
+ complexity = get_complexity_number(trivial, self.strio, max=1)
+ self.assertEqual(complexity, None)
+ printed_message = self.strio.getvalue()
+ self.assertEqual(printed_message, "")
+
+ def test_try_else(self):
+ self.assert_complexity(try_else, 4)
+
+ @pytest.mark.skipif(sys.version_info < (3, 5),
+ reason="Async keywords are only valid on Python 3.5+")
+ def test_async_keywords(self):
+ """Validate that we properly process async keyword usage."""
+ complexity = get_complexity_number(async_keywords, self.strio)
+ self.assertEqual(complexity, 3)
+
+
+class RegressionTests(unittest.TestCase):
+ def setUp(self):
+ self.original_complexity = mccabe.McCabeChecker.max_complexity
+
+ def tearDown(self):
+ mccabe.McCabeChecker.max_complexity = self.original_complexity
+
+ def test_max_complexity_is_always_an_int(self):
+ """Ensure bug #32 does not regress."""
+ class _options(object):
+ max_complexity = None
+
+ options = _options()
+ options.max_complexity = '16'
+
+ self.assertEqual(0, mccabe.McCabeChecker.max_complexity)
+ mccabe.McCabeChecker.parse_options(options)
+ self.assertEqual(16, mccabe.McCabeChecker.max_complexity)
+
+
+if __name__ == "__main__":
+ unittest.main()
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-mccabe.git
More information about the Python-modules-commits
mailing list