Skip to content

Commit

Permalink
Merge pull request #3 from soda480/0.1.2
Browse files Browse the repository at this point in the history
Renamed task to radon
  • Loading branch information
soda480 authored Mar 7, 2021
2 parents 0f0bc0a + b097d27 commit d2ef787
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 56 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
run: |
apk update
apk add bash curl
sed -e 's,filename="mpcurses/,filename="src/main/python/mpcurses/,g' target/reports/coverage.xml > coverage.xml
sed -e 's,filename="pybuilder-radon/,filename="src/main/python/pybuilder_radon/,g' target/reports/coverage.xml > coverage.xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

# pybuilder-radon #

A pybuilder plugin that checks the cyclomatic complexity of your project using `radon`. For more information about radon refer to the [radon home page](https://pypi.org/project/radon/).
A pybuilder plugin that checks the cyclomatic complexity of your project using `radon`. For more information about radon refer to the [radon pypi page](https://pypi.org/project/radon/).

To add this plugin into your pybuilder project, add the following line at the top of your build.py:
To add this plugin into your pybuilder project, add the following line near the top of your build.py:
```python
use_plugin('pypi:pybuilder_radon', '~=0.1.0')
```
Expand All @@ -29,7 +29,7 @@ Refer to [cyclomatic complexity](https://www.c-sharpcorner.com/article/code-metr

### Pybuilder radon properties ###

The pybuilder task `pyb complexity` will use radon to to analyze your project and display the overall average cyclomatic complexity, verbose mode will display complexity of all classes, functions and methods analyzed. The following plugin properties can be set to fail the build if a complexity threshold has been exceeded.
The pybuilder task `pyb radon` will use radon to to analyze your project and display the average cyclomatic complexity, verbose mode will display complexity of all classes, functions and methods analyzed. The following plugin properties are available to further configure the plugin's execution.

Name | Type | Default Value | Description
-- | -- | -- | --
Expand Down
10 changes: 5 additions & 5 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from pybuilder.core import Author

# only for functional testing plugin
# from pybuilder_radon import complexity
# from pybuilder_radon import radon

use_plugin("python.core")
use_plugin("python.unittest")
Expand All @@ -16,9 +16,9 @@

name = 'pybuilder-radon'
authors = [Author('Emilio Reyes', '[email protected]')]
summary = 'Pybuilder plugin for radon'
summary = 'Pybuilder plugin for radon cyclomatic complexity'
url = 'https://github.com/soda480/pybuilder-radon'
version = '0.1.1'
version = '0.1.2'
default_task = ['clean', 'analyze']
license = 'Apache License, Version 2.0'
description = summary
Expand Down Expand Up @@ -51,5 +51,5 @@ def set_properties(project):
'Programming Language :: Python :: 3.6',
'Topic :: Software Development :: Build Tools'])
# only for functional testing plugin
# project.set_property('radon_break_build_average_complexity_threshold', 3.2)
# project.set_property('radon_break_build_complexity_threshold', 6)
# project.set_property('radon_break_build_average_complexity_threshold', 2.8)
# project.set_property('radon_break_build_complexity_threshold', 5)
2 changes: 1 addition & 1 deletion src/main/python/pybuilder_radon/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# -*- coding: utf-8 -*-
from .task import complexity
from .task import radon
27 changes: 16 additions & 11 deletions src/main/python/pybuilder_radon/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,22 @@


@init
def init_complexity(project):
""" initialize complexity task properties
def init_radon(project):
""" initialize radon task properties
"""
project.set_property_if_unset('radon_break_build_average_complexity_threshold', None)
project.set_property_if_unset('radon_break_build_complexity_threshold', None)
project.plugin_depends_on('radon')


@task('complexity', description='checks cyclomatic complexity')
@task('radon', description='execute radon cyclomatic complexity')
@depends('prepare')
def complexity(project, logger):
""" checks cyclomatic complexity
def radon(project, logger):
""" execute radon cyclomatic complexity
"""
set_verbose_property(project)
command = get_command(project)
logger.info(f'Executing radon cyclomatic complexity: \"{command.as_string}\"')
# assert_can_execute(command.parts, prerequisite='radon', caller='complexity')
result = command.run_on_production_source_files(logger)
if not verify_result(result, logger, command):
Expand All @@ -43,14 +45,21 @@ def get_command(project):
return command


def set_verbose_property(project):
""" set verbose property
"""
verbose = project.get_property('verbose')
project.set_property('radon_verbose_output', verbose)


def verify_result(result, logger, command):
""" return True if result contains lines, False otherwise
"""
if not result.report_lines:
logger.warn(f"Command {command.as_string()} produced no output")
logger.warn(f"Command {command.as_string} produced no output")
return False
if len(result.error_report_lines) > 0:
logger.error(f"Command {command.as_string()} produced errors, see {result.error_report_file}")
logger.error(f"Command {command.as_string} produced errors, see {result.error_report_file}")
return False
return True

Expand All @@ -68,10 +77,6 @@ def get_complexity(project, result, logger):
regex_line = r'[A-Z] \d+:\d+ (?P<name>.*) - [A-Z] \((?P<score>\d+)\)'
for line in result.report_lines[:-1]:
line = line.strip()
# using this place to conform to pybuilder verbosity
verbose = project.get_property('verbose')
if verbose:
logger.debug(line)
match = re.match(regex_line, line)
if match:
score = float(match.group('score'))
Expand Down
51 changes: 16 additions & 35 deletions src/unittest/python/test_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
from mock import call
from mock import Mock

from pybuilder_radon.task import init_complexity
from pybuilder_radon.task import complexity
from pybuilder_radon.task import init_radon
from pybuilder_radon.task import radon
from pybuilder_radon.task import get_command
from pybuilder_radon.task import set_verbose_property
from pybuilder_radon.task import verify_result
from pybuilder_radon.task import get_complexity
from pybuilder_radon.task import verify_complexity
Expand All @@ -27,41 +28,41 @@ def tearDown(self):
"""
pass

def test__init_complexity_Should_CallExpected_When_Called(self, *patches):
def test__init_radon_Should_CallExpected_When_Called(self, *patches):
project_mock = Mock()
init_complexity(project_mock)
init_radon(project_mock)
self.assertTrue(call('radon_break_build_average_complexity_threshold', None) in project_mock.set_property_if_unset.mock_calls)
self.assertTrue(call('radon_break_build_complexity_threshold', None) in project_mock.set_property_if_unset.mock_calls)

@patch('pybuilder_radon.task.get_command')
@patch('pybuilder_radon.task.process_complexity')
@patch('pybuilder_radon.task.verify_result')
def test__complexity_Should_CallExpected_When_VerifyResultFalse(self, verify_result_patch, process_complexity_patch, *patches):
def test__radon_Should_CallExpected_When_VerifyResultFalse(self, verify_result_patch, process_complexity_patch, *patches):
verify_result_patch.return_value = False
project_mock = Mock()
complexity(project_mock, Mock())
radon(project_mock, Mock())
process_complexity_patch.assert_not_called()

@patch('pybuilder_radon.task.get_command')
@patch('pybuilder_radon.task.process_complexity')
@patch('pybuilder_radon.task.get_complexity')
@patch('pybuilder_radon.task.verify_result')
def test__complexity_Should_CallExpected_When_VerifyResultTrue(self, verify_result_patch, get_complexity_patch, process_complexity_patch, *patches):
def test__radon_Should_CallExpected_When_VerifyResultTrue(self, verify_result_patch, get_complexity_patch, process_complexity_patch, *patches):
verify_result_patch.return_value = True
project_mock = Mock()
complexity(project_mock, Mock())
radon(project_mock, Mock())
process_complexity_patch.assert_called_once_with(project_mock, get_complexity_patch.return_value)

@patch('pybuilder_radon.task.get_command')
@patch('pybuilder_radon.task.get_complexity')
@patch('pybuilder_radon.task.process_complexity')
@patch('pybuilder_radon.task.verify_complexity')
@patch('pybuilder_radon.task.verify_result')
def test__complexity_Should_CallExpected_When_VerifyComplexityFalse(self, verify_result_patch, verify_complexity_patch, process_complexity_patch, *patches):
def test__radon_Should_CallExpected_When_VerifyComplexityFalse(self, verify_result_patch, verify_complexity_patch, process_complexity_patch, *patches):
verify_result_patch.return_value = True
verify_complexity_patch.return_value = False
project_mock = Mock()
complexity(project_mock, Mock())
radon(project_mock, Mock())
process_complexity_patch.assert_not_called()

@patch('pybuilder_radon.task.ExternalCommandBuilder')
Expand All @@ -71,6 +72,11 @@ def test__get_command_Should_CallAndReturnExpected_When_Called(self, external_co
external_command_builder_patch.assert_called_once_with('radon', project_mock)
self.assertEqual(result, external_command_builder_patch.return_value)

def test__set_verbose_property_Should_CallExpected_When_Called(self, *patches):
project_mock = Mock()
set_verbose_property(project_mock)
project_mock.set_property.assert_called_once_with('radon_verbose_output', project_mock.get_property.return_value)

def test__verify_result_Should_ReturnFalse_When_NoReportLines(self, *patches):
result_mock = Mock()
result_mock.report_lines = []
Expand All @@ -91,30 +97,6 @@ def test__verify_result_Should_ReturnTrue_When_ReportLinesAndNoErrorReportLines(
result = verify_result(result_mock, Mock(), Mock())
self.assertTrue(result)

def test__get_complexity_Should_ReturnExpected_When_CalledVerbose(self, *patches):
result_mock = Mock()
result_mock.report_lines = [
'\n',
' M 81:4 class.ma - C (14)\n',
' M 231:4 class.mb - A (4)\n',
'src/main/python/package/module.py\n',
' C 40:0 class.mc - B (9)\n',
'\n',
'Average complexity: A (3.557377049180328)']
project_mock = Mock()
project_mock.get_property.return_value = True
logger_mock = Mock()
result = get_complexity(project_mock, result_mock, logger_mock)
expected_result = {
'average': 3.557377049180328,
'highest': {
'name': 'class.ma',
'score': 14
}
}
self.assertEqual(result, expected_result)
self.assertEqual(len(logger_mock.debug.mock_calls), 6)

def test__get_complexity_Should_ReturnExpected_When_CalledNoVerbose(self, *patches):
result_mock = Mock()
result_mock.report_lines = [
Expand Down Expand Up @@ -160,7 +142,6 @@ def test__get_complexity_Should_ReturnExpected_When_NoMatch(self, *patches):
}
}
self.assertEqual(result, expected_result)
self.assertEqual(len(logger_mock.debug.mock_calls), 6)

def test__verify_complexity_Should_ReturnFalse_When_AverageIsNone(self, *patches):
complexity = {
Expand Down

0 comments on commit d2ef787

Please sign in to comment.