CASTanet is a tool created by students at
Allegheny College, allowing users to understand
the contents of Python (.py
) files. Through
using concrete abstract syntax trees (CASTs), a
combination of abstract syntax trees (ASTs) and
concrete syntax trees (CSTs), CASTanet uses
LibCST
to reorganize and name node types and
fields. CASTanet has functionality to iterate
through a user-specified directory and generate
metrics associated with the Python files in that
given directory. This tool can be used by
educators interested in evaluating students'
code, or individual developers who would like to
better understand their own implementation
strategies.
Currently, CASTanet is able to count:
- Number of if statements in a Python file (and total in directory)
- Number of looping constructs in a Python file (and total in directory)
- Number of comments in a Python file (and total in directory)
- Number of arguments for a specified Python function
- Number of functions in a specified Python file (and total in directory)
- Number of function definitions without docstrings in a Python file (and total in directory)
- Number of classes in a Python file (and total in directory)
- Number of class definitions without docstrings in a Python file (and total in directory)
- Number of assignment statements in a Python file (and total in directory)
- Whether a specified function has a docstring or not
- Number of import statements in a Python file (and total in directory)
Run the command to install: pip install castanet
In the appropriate directory, clone the CASTanet repository following GitFlow and the GitHub documentation
The documentation and instructions on installing Poetry can be found here.
Poetry allows dependency installation with ease. After cloning the CASTanet repository, and installing Poetry, install all necessary dependencies for the tool with the command:
poetry install
CASTanet is a fully-functional tool with a dynamic command line interface, built with the user in mind. To run the CASTanet CLI, in the base directory of your local, cloned repository and type the command:
castanet [command-here]
Without specifying a command, you will receive this error in your terminal:
Usage: castanet [OPTIONS] COMMAND [ARGS]...
Try 'castanet --help' for help.
Error: Missing command.
Please refer to the next section to see what functionality CASTanet has, and what commands to run.
CASTanet's command line interface is created with Typer, a library for building CLI applications based on Python 3.6+ type hints.
In order to familiarize yourself with the commands for
CASTanet, run the command: poetry run castanet --help
CASTanet's commands are as follows:
PLEASE NOTE: Each of the following commands must be run with the file path of the directory of interest given as input. This directory must be present on your machine, and CASTanet will provide output pertaining to this specified directory.
Determine number of assignment statements.
Usage:
castanet assignment [OPTIONS] PATH
Arguments:
PATH
: [required]
Determine number of classes without docstrings.
Usage:
castanet total-classes [OPTIONS] PATH
Arguments:
PATH
: [required]
Determine number of classes without docstrings.
Usage:
castanet classes-without-docstrings [OPTIONS] PATH
Arguments:
PATH
: [required]
Determine number of comments.
Usage:
castanet comments [OPTIONS] PATH
Arguments:
PATH
: [required]
Determine the number of parameters for a given function.
Usage:
castanet function-arguments [OPTIONS] PATH FUNCTION_NAME
Arguments:
PATH
: [required]FUNCTION_NAME
: [required]
Determine if a given function has a docstring.
Usage:
castanet function-docstring-exists [OPTIONS] PATH FUNCTION_NAME
Arguments:
PATH
: [required]FUNCTION_NAME
: [required]
Determine number of functions without docstrings.
Usage:
castanet functions-without-docstrings [OPTIONS] PATH
Arguments:
PATH
: [required]
Determine number of if statements in a Python directory.
Usage:
castanet if-statements [OPTIONS] PATH
Arguments:
PATH
: [required]
Determine number of import statements.
Usage:
castanet imports [OPTIONS] PATH
Arguments:
PATH
: [required]
Determine number of looping constructs.
Usage:
castanet looping-constructs [OPTIONS] PATH
Arguments:
PATH
: [required]
Determine number of functions in a Python directory.
Usage:
castanet functions-per-module [OPTIONS] PATH
Arguments:
PATH
: [required]
Determine total number of functions in a Python directory.
Usage:
castanet total-functions [OPTIONS] PATH
Arguments:
PATH
: [required]
Currently, CASTanet only has functionality for one metric to be calculated at a time. As a result, if you are interested in one or more metric, you must run CASTanet for the first metric (with the corresponding CLI command), and then run CASTanet subsequently for each additional metric (with the corresponding CLI command).
CASTanet is also available on PyPI to be used as a Python library. Find it here. With the CASTanet library, a user is able to investigate their Python files with many different function calls. Specifically, CASTanet is broken down into two parts:
generate_trees
: Traverses a directory and generates concrete-abstract-syntax trees of Python files using LibCSTcounter
: Uses concrete-abstract-syntax-trees to calculate metrics associated with the contents of a Python module
from castanet import counter
Calculate the sums of values from dictionaries.
Called to get number values from the result of a
function. Must always be run on the results of
count
functions to get final numbers.
counter.sum_dict_vals(values_dict)
ARGUMENTS:
- values_dict: dictionary of total values for metrics
RETURNS:
- int: total number of items in dictionary
Count the number of import statements in a Python file.
counter.count_imports(path)
ARGUMENTS:
- path: A string path corresponding to a Python file or a directory
RETURNS:
- dict: files and the corresponding amount of import statements
Count the number of function definitions in a Python file.
counter.count_functions(path)
ARGUMENTS:
- path: A string path corresponding to a Python file or a directory
RETURNS:
*dict: files and the corresponding amount of function definitions
Count the number of comments in a Python file.
counter.count_comments(path)
ARGUMENTS:
- path: A string path corresponding to a Python file or a directory
RETURNS:
- dict: files and the corresponding amount of comments
Count the number of while loops in a Python file.
counter.count_while_loops(path)
ARGUMENTS:
- path: A string path corresponding to a Python file or a directory
RETURNS:
- dict: files and the corresponding amount of while loops
Count the number of for loops in a Python file.
counter.count_for_loops(path)
ARGUMENTS:
- path: A string path corresponding to a Python file or a directory
RETURNS:
- dict: files and the corresponding amount of for loops
Count the number of if statements in a Python file.
counter.count_if_statements(path)
ARGUMENTS:
- path: A string path corresponding to a Python file or a directory
RETURNS:
- dict: files and the corresponding amount of if statements
Count the number of function definitions in a Python file.
counter.count_func_defs(path)
ARGUMENTS:
- path: A string path corresponding to a Python file or a directory
RETURNS:
- dict: files and the corresponding amount of function_definitions
Count the number of functions without docstrings.
counter.count_function_without_docstrings(func_count)
ARGUMENTS:
- dict: A dictionary of functions and docstring counts per file
RETURNS:
- int: total number of functions - total number of docstrings
Note: It is required to first call count_func_defs
in
order for this function call to work correctly.
Determine if a docstring exists for a specified function.
counter.docstring_exists(path, function_name)
ARGUMENTS:
- path: A string path corresponding to a Python file or a directory
- function_name (str): Name of function to check for docstrings
RETURNS:
- -1: function does not exist
- 0: function exists without docstring
- 1: function exists with docstring
Count the number of class definitions in a Python file.
counter.count_class_defs(cast_dict)
ARGUMENTS:
- path: A string path corresponding to a Python file or a directory
RETURNS:
- dict: files and the corresponding amount of class definitions
Count the number of class definitions without docstrings.
counter.count_class_defs_without_docstrings(class_count)
ARGUMENTS:
- dict: A dictionary of classes and docstring counts per file
RETURNS:
- int: total number of classes - total number of docstrings
Note: It is required to first call count_class_defs
in
order for this function call to work correctly.
Count the number of arguments for a specified function.
counter.count_function_arguments(path, function_name)
ARGUMENTS:
- path: A string path corresponding to a Python file or a directory
- function_name: User-specified file of interest
RETURNS:
- -1: Function was not found
- else: The amount of parameters for the given function
Count the number of assignment statements in a Python file.
(does not include augmented assignment)
counter.count_assignments(path)
ARGUMENTS:
- path: A string path corresponding to a Python file or a directory
RETURNS:
- dict: files and the corresponding amount of assignment statements
Count the number of aug assignment statements (x += 5) in a Python file.
counter.count_aug_assignment(path)
ARGUMENTS:
- path: A string path corresponding to a Python file or a directory
RETURNS:
- dict: files and the corresponding amount of aug assignment statements
Developers of this program can run the test suite with Pytest with the command:
poetry run task test
We welcome everyone who is interested in helping to improve CASTanet! If you are interested in being a contributor, please review our Code of Conduct and Guidelines for Contributors before raising an issue, or beginning a contribution.
To raise an issue in CASTanet's Issue Tracker please follow these templates:
To create a pull request, please follow this template:
If you have any questions or concerns about CASTanet, please contact:
- Madelyn Kapfhammer ([email protected])
- Thomas Antle ([email protected])
- Nolan Thompson ([email protected])
- Caden Hinckley ([email protected])
- Bailey Matrascia ([email protected])