# Python ABC
[][1]
A python implementation of [the ABC Software metric][2]:
> The ABC software metric was introduced by Jerry Fitzpatrick in 1997 to overcome the drawbacks of the LOC. The metric defines an ABC score as a triplet of values that represent the size of a set of source code statements. An ABC score is calculated by counting the number of assignments (A), number of branches (B), and number of conditionals (C) in a program. ABC score can be applied to individual methods, functions, classes, modules or files within a program.
Fitzpatrick's original paper is, at the time of writing, only [available via the Wayback
Machine][3], so [a copy of it is included in this repo][4] as well.
The paper lists the counting rules for C, C++ and Java, so here are the rules this repo uses for
Python:
- Add one to the assignment count when:
- Occurrence of an assignment operator (excluding default parameter assignments).
- Add one to the branch count when:
- Occurrence of a function call/await or a class method call/await.
- Occurrence of a class instantiation.
- Add one to the condition count when:
- Occurrence of a conditional operator.
- Occurrence of the following keywords: `else`, `elif`, `except`.
- Occurrence of an `assert` statement without a conditional operator.
## Usage
Install the requirements in your virtual environment of choice, then you can see the command line
arguments that are available:
```bash
$ python -m python_abc --help
usage: python_abc [-h] [--debug DEBUG] [--sort SORT] [--verbose VERBOSE] path
A python implementation of the ABC Software metric: https://en.wikipedia.org/wiki/ABC_Software_Metric
positional arguments:
path path to directory or file
optional arguments:
-h, --help show this help message and exit
--debug DEBUG display AST output for each element in the parsed tree
--sort SORT sort files from highest to lowest magnitude
--verbose VERBOSE display marked-up file
```
Given `file.py` that contains the following text:
```python
if a and b:
print(a)
else:
print(b)
a = sum(i for i in range(1000) if i % 3 == 0 and i % 5 == 0)
def f(n):
def inner(n):
return n ** 2
if n == 0:
return 1
elif n == 1:
return n
elif n < 5:
return (n - 1) ** 2
return n * pow(inner(n), f(n - 1), n - 3)
```
You can get the barebones output as follows:
```bash
$ python -m python_abc /path/to/file.py
/path/to/file.py <1, 7, 10> (12.2)
```
Passing the `verbose` flag will give more detail:
```bash
$ python -m python_abc file.py --verbose=true
cc | if a and b:
b | print(a)
c | else:
b | print(b)
|
abbcc | a = sum(i for i in range(1000) if i % 3 == 0 and i % 5 == 0)
|
| def f(n):
| def inner(n):
| return n ** 2
c | if n == 0:
| return 1
cc | elif n == 1:
| return n
cc | elif n < 5:
| return (n - 1) ** 2
bbb | return n * pow(inner(n), f(n - 1), n - 3)
file.py <1, 7, 10> (12.2)
```
If you want to inspect the abstract syntax tree for the file you can pass the `debug` flag, which
will print out each node from the tree and the vector that resulted from it.
The `path` argument can also be a path to a directory, in which case all Python files in that
directory (and its sub-directories) will be scanned, at which point it can be useful to pass the
`sort` flag to rank the files by ABC magnitude:
```bash
$ python -m python_abc . --sort
./calculate.py <18, 56, 23> (63.2)
./vector.py <12, 23, 11> (28.2)
./main.py <10, 23, 8> (26.3)
./tests/test_vector.py <4, 19, 10> (21.8)
./tests/__init__.py <4, 12, 1> (12.7)
./tests/test_radon_test_cases.py <1, 2, 1> (2.4)
./tests/test_calculate_condition.py <1, 2, 1> (2.4)
./tests/test_calculate_empty.py <1, 2, 1> (2.4)
./tests/test_calculate_assignment.py <1, 2, 1> (2.4)
./tests/test_calculate_branch.py <1, 2, 1> (2.4)
```
Finally you can pass a `cores` argument to tell the library how many CPU cores to use. By
default the library will try to use all the cores that are available on your machine.
[1]: https://www.python.org/downloads/release/python-395/
[2]: https://en.wikipedia.org/wiki/ABC_Software_Metric
[3]: https://web.archive.org/web/20210606115110/https://www.softwarerenovation.com/ABCMetric.pdf
[4]: https://github.com/eoinnoble/python-abc/blob/main/ABCMetric.pdf
Raw data
{
"_id": null,
"home_page": "https://github.com/eoinnoble/python-abc",
"name": "python-abc",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "",
"author": "Eoin Noble",
"author_email": "eoin@eoinnoble.com",
"download_url": "https://files.pythonhosted.org/packages/17/e3/5973ccea7302dfe994331e2824bfc8cc4e4c8ba7f0b9d1f16bcda5ef26a3/python-abc-0.2.0.tar.gz",
"platform": null,
"description": "# Python ABC\n\n[][1]\n\nA python implementation of [the ABC Software metric][2]:\n\n> The ABC software metric was introduced by Jerry Fitzpatrick in 1997 to overcome the drawbacks of the LOC. The metric defines an ABC score as a triplet of values that represent the size of a set of source code statements. An ABC score is calculated by counting the number of assignments (A), number of branches (B), and number of conditionals (C) in a program. ABC score can be applied to individual methods, functions, classes, modules or files within a program.\n\nFitzpatrick's original paper is, at the time of writing, only [available via the Wayback\nMachine][3], so [a copy of it is included in this repo][4] as well.\n\nThe paper lists the counting rules for C, C++ and Java, so here are the rules this repo uses for\nPython:\n\n- Add one to the assignment count when:\n - Occurrence of an assignment operator (excluding default parameter assignments).\n- Add one to the branch count when:\n - Occurrence of a function call/await or a class method call/await.\n - Occurrence of a class instantiation.\n- Add one to the condition count when:\n - Occurrence of a conditional operator.\n - Occurrence of the following keywords: `else`, `elif`, `except`.\n - Occurrence of an `assert` statement without a conditional operator.\n\n## Usage\n\nInstall the requirements in your virtual environment of choice, then you can see the command line\narguments that are available:\n\n```bash\n$ python -m python_abc --help\nusage: python_abc [-h] [--debug DEBUG] [--sort SORT] [--verbose VERBOSE] path\n\nA python implementation of the ABC Software metric: https://en.wikipedia.org/wiki/ABC_Software_Metric\n\npositional arguments:\n path path to directory or file\n\noptional arguments:\n -h, --help show this help message and exit\n --debug DEBUG display AST output for each element in the parsed tree\n --sort SORT sort files from highest to lowest magnitude\n --verbose VERBOSE display marked-up file\n```\n\nGiven `file.py` that contains the following text:\n\n```python\nif a and b:\n print(a)\nelse:\n print(b)\n\na = sum(i for i in range(1000) if i % 3 == 0 and i % 5 == 0)\n\ndef f(n):\n def inner(n):\n return n ** 2\n if n == 0:\n return 1\n elif n == 1:\n return n\n elif n < 5:\n return (n - 1) ** 2\n return n * pow(inner(n), f(n - 1), n - 3)\n```\n\nYou can get the barebones output as follows:\n\n```bash\n$ python -m python_abc /path/to/file.py\n/path/to/file.py <1, 7, 10> (12.2)\n```\n\nPassing the `verbose` flag will give more detail:\n\n```bash\n$ python -m python_abc file.py --verbose=true\ncc | if a and b:\nb | print(a)\nc | else:\nb | print(b)\n |\nabbcc | a = sum(i for i in range(1000) if i % 3 == 0 and i % 5 == 0)\n |\n | def f(n):\n | def inner(n):\n | return n ** 2\nc | if n == 0:\n | return 1\ncc | elif n == 1:\n | return n\ncc | elif n < 5:\n | return (n - 1) ** 2\nbbb | return n * pow(inner(n), f(n - 1), n - 3)\nfile.py <1, 7, 10> (12.2)\n```\n\nIf you want to inspect the abstract syntax tree for the file you can pass the `debug` flag, which\nwill print out each node from the tree and the vector that resulted from it.\n\nThe `path` argument can also be a path to a directory, in which case all Python files in that\ndirectory (and its sub-directories) will be scanned, at which point it can be useful to pass the\n`sort` flag to rank the files by ABC magnitude:\n\n```bash\n$ python -m python_abc . --sort\n./calculate.py <18, 56, 23> (63.2)\n./vector.py <12, 23, 11> (28.2)\n./main.py <10, 23, 8> (26.3)\n./tests/test_vector.py <4, 19, 10> (21.8)\n./tests/__init__.py <4, 12, 1> (12.7)\n./tests/test_radon_test_cases.py <1, 2, 1> (2.4)\n./tests/test_calculate_condition.py <1, 2, 1> (2.4)\n./tests/test_calculate_empty.py <1, 2, 1> (2.4)\n./tests/test_calculate_assignment.py <1, 2, 1> (2.4)\n./tests/test_calculate_branch.py <1, 2, 1> (2.4)\n```\n\nFinally you can pass a `cores` argument to tell the library how many CPU cores to use. By\ndefault the library will try to use all the cores that are available on your machine.\n\n[1]: https://www.python.org/downloads/release/python-395/\n[2]: https://en.wikipedia.org/wiki/ABC_Software_Metric\n[3]: https://web.archive.org/web/20210606115110/https://www.softwarerenovation.com/ABCMetric.pdf\n[4]: https://github.com/eoinnoble/python-abc/blob/main/ABCMetric.pdf",
"bugtrack_url": null,
"license": "",
"summary": "A python implementation of the ABC Software metric",
"version": "0.2.0",
"project_urls": {
"Homepage": "https://github.com/eoinnoble/python-abc"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "17e35973ccea7302dfe994331e2824bfc8cc4e4c8ba7f0b9d1f16bcda5ef26a3",
"md5": "ac059f6103feb9045b0b95ef797a554a",
"sha256": "90017d09fbac7bde4b64b2c7e1b5d22da9055b64b821d1a2b4dc805b450b251a"
},
"downloads": -1,
"filename": "python-abc-0.2.0.tar.gz",
"has_sig": false,
"md5_digest": "ac059f6103feb9045b0b95ef797a554a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 7423,
"upload_time": "2022-06-26T21:36:06",
"upload_time_iso_8601": "2022-06-26T21:36:06.156883Z",
"url": "https://files.pythonhosted.org/packages/17/e3/5973ccea7302dfe994331e2824bfc8cc4e4c8ba7f0b9d1f16bcda5ef26a3/python-abc-0.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2022-06-26 21:36:06",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "eoinnoble",
"github_project": "python-abc",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "attrs",
"specs": [
[
"==",
"21.4.0"
]
]
},
{
"name": "black",
"specs": [
[
"==",
"22.3.0"
]
]
},
{
"name": "click",
"specs": [
[
"==",
"8.1.3"
]
]
},
{
"name": "iniconfig",
"specs": [
[
"==",
"1.1.1"
]
]
},
{
"name": "joblib",
"specs": [
[
"==",
"1.1.0"
]
]
},
{
"name": "mypy",
"specs": [
[
"==",
"0.961"
]
]
},
{
"name": "mypy-extensions",
"specs": [
[
"==",
"0.4.3"
]
]
},
{
"name": "packaging",
"specs": [
[
"==",
"21.3"
]
]
},
{
"name": "pathspec",
"specs": [
[
"==",
"0.9.0"
]
]
},
{
"name": "pep517",
"specs": [
[
"==",
"0.12.0"
]
]
},
{
"name": "pip-tools",
"specs": [
[
"==",
"6.6.2"
]
]
},
{
"name": "platformdirs",
"specs": [
[
"==",
"2.5.2"
]
]
},
{
"name": "pluggy",
"specs": [
[
"==",
"1.0.0"
]
]
},
{
"name": "py",
"specs": [
[
"==",
"1.11.0"
]
]
},
{
"name": "pyparsing",
"specs": [
[
"==",
"3.0.9"
]
]
},
{
"name": "pytest",
"specs": [
[
"==",
"7.1.2"
]
]
},
{
"name": "tomli",
"specs": [
[
"==",
"2.0.1"
]
]
},
{
"name": "typing-extensions",
"specs": [
[
"==",
"4.2.0"
]
]
},
{
"name": "wheel",
"specs": [
[
"==",
"0.37.1"
]
]
}
],
"lcname": "python-abc"
}