python-abc


Namepython-abc JSON
Version 0.2.0 PyPI version JSON
download
home_pagehttps://github.com/eoinnoble/python-abc
SummaryA python implementation of the ABC Software metric
upload_time2022-06-26 21:36:06
maintainer
docs_urlNone
authorEoin Noble
requires_python
license
keywords
VCS
bugtrack_url
requirements attrs black click iniconfig joblib mypy mypy-extensions packaging pathspec pep517 pip-tools platformdirs pluggy py pyparsing pytest tomli typing-extensions wheel
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Python ABC

[![Python 3.9.5](https://img.shields.io/badge/python-3.9.5-blue.svg)][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[![Python 3.9.5](https://img.shields.io/badge/python-3.9.5-blue.svg)][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"
}
        
Elapsed time: 0.33797s