Package: chasten
💫 chasten🎉 IntroductionChastenis a Python program that usesXPathexpressions to find
patterns in theabstract syntax
tree(AST) of a Python program. You
can use Chasten to quickly implement your own configurable linting rules,
without having to use a complex AST analysis framework or resorting to imprecise
regular expressions.Do you want to ensure that a Python program has does not have any
triple-nestedforloops inside ofasyncfunctions? Or, do you want to
confirm that every function inside your Python program has type annotations and
a docstring comment?Chasten can help! It allows you to express these checks
— and many other types of analyses as well — in simple YAML files
that contain XPath expressions.😂 Definitionschasten(transitive verb) "to make someone aware of failure or of having
done something wrong",Cambridge
Dictionary.Example Sentence: "Her remarks are a gift to me even as they chasten
and redirect my efforts to expand the arguments of this book into a larger
one.",Cambridge English
Corpuschasten(uncountable or singular noun) "a tool that analyzes the abstract
syntax tree of a Python program to detect potential sources of programmer
mistakes so as to prevent program failure",AstuteSource
Developers.Student Sentence: "I'm glad thatchastenreminded me to add
docstrings and type annotations to all of the functions inmain.py. It was
easy to see what to fix!"Instructor Sentence: "chastenmakes it easy for me to reliably
confirm that student programs have the required coding constructs. It's much
better than using regular expressions!"Developer Sentence: "Since I was already familiar with XPath
expressions,chastenmade it fun and easy for me to do an automate
analysis of a Python codebase that I maintain."Researcher Sentence: "In addition to helping me quickly scan the
source code of Python projects,chasten's analysis dashboard lets me
effectively explore the data I collect."🔋Features✨ Easy-to-configure, automated analysis of a Python program's abstract syntax tree📃 Flexible and easy-to-use YAML-based configuration file for describing analyses and checks🪂 Automated generation and verification of the YAML configuration files for an analysis🚀 Configurable saving of analysis results in the JSON, CSV, or SQLite formats🚧 Automated integration of result files that arise from multiple runs of the tool🌄 Interactive results analysis through the use of a locally running datasette server🌎 Automated deployment of a datasette server on platforms like Fly or Vercel🦚 Detailed console and syslog logging to furnish insights into the tool's behavior💠 Rich command-line interface with robust verification of arguments and options🤯 Interactive command-line generation through an easy-to-use terminal user interface⚡️ RequirementsPython 3.11Chasten leverages numerous Python packages, including notable ones such as:Datasette: Interactive data analysis dashboardsPyastgrep: XPath-based analysis of a Python program's ASTPydantic: Automated generation and validation of configuration filesRich: Full-featured formatting and display of text in the terminalTrogon: Automated generation of terminal user interfaces for a command-line toolTyper: Easy-to-implement and fun-to-use command-line interfacesThe developers of Chasten usePoetryfor packaging and dependency management🔽 InstallationFollow these steps to install thechastenprogram:Install Python 3.11 for your operating systemInstallpipxto support program installation in isolated environmentsTypepipx install chastento install ChastenTypepipx listand confirm that Chasten is installedTypechasten --helpto learn how to use the tool🪂 ConfigurationYou can configurechastenwith two YAML files, normally calledconfig.ymlandchecks.yml. Althoughchastencan generate a starting configuration, you
can check out the 📦AstuteSource/chasten-configurationrepository for example(s) of configuration files that setup the tool. Although
theconfig.ymlfile can reference multiple check configuration files, this
example shows how to specify a singlechecks.ymlfile:# chasten configuration
chasten:
  # point to a single checks file
  checks-file:
    - checks.ymlThechecks.ymlfile must contain one or more checks. What follows is an
example of a check configuration file with two checks that respectively find the
first executable line of non-test and test-case functions in a Python project.
Note that thepatternattribute specifies the XPath version 2.0 expression
thatchastenwill use to detect the specified type of Python function. You can
typechasten configure validate --config <path to chasten-configuration/ directory | config url>after filling in<path to chasten-configuration/directory | config url>with the
fully-qualified name of your configuration directory and the tool will confirm
that your configuration meets the tool's specification. You can also use the
commandchasten configure createcommand to automatically generate a starting
configuration! Typingchasten configure --helpwill explain how to configure
the tool.checks:
  - name: "all-non-test-function-definition"
    code: "FUNC"
    id: "FUNC001"
    description: "First executable line of a non-test function, skipping over docstrings and/or comments"
    pattern: '//FunctionDef[not(contains(@name, "test_"))]/body/Expr[value/Constant]/following-sibling::*[1] | //FunctionDef[not(contains(@name, "test_"))]/body[not(Expr/value/Constant)]/*[1]'
  - name: "all-test-function-definition"
    code: "FUNC"
    id: "FUNC002"
    description: "First executable line of a test function, skipping over docstrings and/or comments"
    pattern: '//FunctionDef[starts-with(@name, "test_")]/body/Expr[value/Constant]/following-sibling::*[1] | //AsyncFunctionDef[starts-with(@name, "test_")]/body/Expr[value/Constant]/following-sibling::*[1] | //FunctionDef[starts-with(@name, "test_")]/body[not(Expr/value/Constant)]/*[1] | //AsyncFunctionDef[starts-with(@name, "test_")]/body[not(Expr/value/Constant)]/*[1]'
    count:
      min: 1
      max: 10✨ AnalysisSincechastenneeds a project with Python source code as the input to itsanalysissub-command, you can clone the
📦AstuteSource/lazytrackerand
📦AstuteSource/multicounterrepositories that are forks of existing Python projects created for convenient
analysis. To incrementally analyze these two projects withchasten, you can
type the following commands to produce a results JSON file for each project:After creating asubject-data/directory that contains alazytracker/directory, you can run thechasten analyzecommand for thelazytrackerprogram:chastenanalyzelazytracker\--config<pathtothechasten-configuration/directory|configurl>\--search-path<pathtothelazytracker/directory>\--save-directory<pathtothesubject-data/lazytracker/directory>\--saveNow you can scan the output to confirm that, for instance,chastenfinds6test functions in thelazytrackerproject. If you look in thesubject-data/lazytrackerdirectory you will find a JSON file with a name likechasten-results-lazytracker-20230823162341-4c23fc443a6b4c4aa09886f1ecb96e9f.json.
Runningchastenon this program more than once will produce a new results file
with a different timestamp (i.e.,20230823162341) and unique identifier (i.e.,4c23fc443a6b4c4aa09886f1ecb96e9f) in its name, thus ensuring that you do not
accidentally write over your prior results when using--save.After creating amulticounter/directory in the existingsubject-data/directory, you can run thechasten analyzecommand for themulticounterprogram:chastenanalyzemulticounter\--config<pathtothechasten-configuration/directory|configurl>\--search-path<pathtothemulticounter/directory>\--save-directory<pathtothesubject-data/lazytracker/directory>\--saveNow you can scan the output to confirm that, as an example,chastenfinds10test functions in themulticounterproject. If you look in thesubject-data/lazytrackerdirectory you will find a JSON file with a name likechasten-results-multicounter-20230821171712-5c52f2f1b61b4cce97624cc34cb39d4f.jsonand name components that are similar to the JSON file created for themulticounterprogram.Since theall-test-function-definitioncheck specifies that the program must
have between1and10tests you will notice that this check passes for bothlazytrackerandmulticounter. This means thatchastenreturns a0error
code to communicate to your operating system that the check passed.You can learn more about how to use theanalyzesub-command by typingchasten analyze --help. For instance,chastensupports the--check-includeand--check-excludeoptions that allow you to respectively include and exclude
specific checks according to fuzzy matching rules that you can specify for any
of a check's attributes specified in thechecks.ymlfile.🚧 IntegrationAfter runningchastenon thelazytrackerandmulticounterprograms you can
integrate their individual JSON files into a single JSON file, related CSV
files, and a SQLite database. Once you have made anintegrated-data/directory, you can type this command to perform the integration:chastenintegrateall-programs\<pathtosubject-data>/**/*.json\--save-directory<pathtotheintegrated-data/directory>This command will produce a directory likechasten-flattened-csvs-sqlite-db-all-programs-20230823171016-2061b524276b4299b04359ba30452923/that contains a SQLite database calledchasten.dband acsv/directory with
CSV files that correspond to each of the tables inside of the database.You can learn more about theintegratesub-command by typingchasten integrate --help.💠 Verbose OutputWhen utilizing thechastencommand, appending this--verboseflag can significantly enhance your troubleshooting experience and provide a detailed understanding of the tool's functionality. Here is an example withchasten analyze lazytracker:chastenanalyzelazytracker\--config<pathtothechasten-configuration/directory>\--search-path<pathtothelazytracker/directory>\--save-directory<pathtothesubject-data/lazytracker/directory>\--save--verboseUpon executing this command, you can expect the output to contain informative messages such as✨ Matching source code:indicating that the tool is actively comparing the source code against the specified patterns. Additionally, you will receive detailed match results, providing insights into the identified checks.🌄 ResultsIf you want to create an interactive analysis dashboard that uses 📦simonw/datasetteyou can runchasten datasette-serve <path containing integrated results>/chasten.db --port 8001.
Now you can use the dashboard in your web browser to analyze the results while
you study the source code for these projects with your editor! Examining the
results will reveal thatchasten, through its use of 📦spookylukey/pyastgrep, correctly
uses the XPath expression forall-test-function-definitionto find the first
line of executable source code inside of each test, skipping over a function's
docstring and leading comments.For thelazytrackerprogram you will notice thatchastenreports that there
are6test cases even thoughpytestonly finds and runs5tests. This is
due to the fact thattests/test_tracked.pytest suite inlazytrackercontains a function starting withtest_inside of another function starting
withtest_. This example illustrates the limitations of static analysis withchasten! Even though the tool correctly detected all of the "test functions",
the nesting of the functions in the test suite means thatpytestwill run the
outertest_function and use the innertest_function for testing purposes.With that said,chastencorrectly finds each of the tests for themulticounterproject. You can follow each of the previous steps in this
document to applychastento your own Python program!🌎 DeploymentIf you want to make yourchasten.dbpublicly available for everyone to study,
you can use thechasten datasette-publishsub-command. As long as you have
followed the installation instructions for 📦simonw/datasette-publish-flyand 📦simonw/datasette-publish-vercel,
you can use the plugins to deploy a publicdatasetteserver that hosts yourchasten.db. For instance, running the commandchasten datasette-publish <path containing integrated results>/chasten.db --platform vercelwill publish the
results from runningchastenonlazytrackerandmulticounterto theVercelplatform.Importantly, the use of thechasten datasette-publishcommand with the--platform verceloption requires you to have previously followed the
instructions for thedatasette-publish-vercelplugin to install thevercelcommand-line tool. This is necessary because, althoughdatasette-publish-vercelis one ofchasten's dependencies neitherchastennordatasette-publish-vercelprovide theverceltool even though they use
it. You must take similar steps before publishing your database toFly!🤯 InteractionEven thoughchastenis a command-line application, you create interactively
create the tool's command-line arguments and options through a terminal user
interface (TUI). To use TUI-based way to create a complete command-line forchastenyou can type the commandchasten interact.📊LogChastenhas a built-in system log. While using chasten you can use the commandchasten login your terminal. The system log feature allows the user to see
events and messages that are produced bychasten. In addition, thechasten logfeature will assist in finding bugs and the events that led to the bug happening.
For thechastenprogram to display to the system log you will have to open a
separate terminal and use the commandchasten log. In addition for each command
that is run the--debug-level <choice of level>and--debug-dest SYSLOGwill
need to be added.For example,chasten datasette-serve --debug-level DEBUG --debug-dest SYSLOG  < database path to file>will produce the following output in the system log.💫 chasten: Analyze the AST of Python Source Code
🔗 GitHub: https://github.com/gkapfham/chasten
✨ Syslog server for receiving debugging information

Display verbose output? False
Debug level? DEBUG
Debug destination? SYSLOGIn each command inchasten, there is an option to add a--debug-level. The debug level has 5 options debug, info, warning, error, and critical. Each level will show different issues in the system log where debug is the lowest level of issue from the input where critical is the highest level of error. To leverage more info on this you can referencedebug.pyfile:classDebugLevel(str,Enum):"""The predefined levels for debugging."""DEBUG="DEBUG"INFO="INFO"WARNING="WARNING"ERROR="ERROR"CRITICAL="CRITICAL"✨ chasten --helpUsage:chasten[OPTIONS]COMMAND[ARGS]...╭─Options───────────────────────────────────────────────────────────────────────────────────╮
│--install-completionInstallcompletionforthecurrentshell.│
│--show-completionShowcompletionforthecurrentshell,tocopyitor│
│customizetheinstallation.│
│--helpShowthismessageandexit.│
╰─────────────────────────────────────────────────────────────────────────────────────────────╯
╭─Commands──────────────────────────────────────────────────────────────────────────────────╮
│analyze💫AnalyzetheASTofPythonsourcecode.│
│configure🪂Managechasten'sconfiguration.│
│datasette-publish🌎PublishadatasettetoFlyorVercel.│
│datasette-serve🏃Startalocaldatasetteserver.│
│integrate🚧Integratefilesandmakeadatabase.│
│interact🚀Interactivelyconfigureandrun.│
│log🦚Starttheloggingserver.│
╰─────────────────────────────────────────────────────────────────────────────────────────────╯🧑‍💻 Development Enviroment🏠 LocalFollow these steps to install thechastentool for future development:The development and use of Chasten requiresPython 3.11, must be greater or equal to version 3.11.5.The developers of Chasten usePoetryfor packaging and dependency management.Once Python and Poetry is installed, please go to theChastenrepository on github and install the tool using thegit clonecommand in your terminal. Then navigate to the Chasten directory and run the commandpoetry installto install all the dependencies.🐋 DockerThere is also the option to useDockerto usechastenFollow these steps to utilize Docker:InstallDocker Desktopfor your operating systemEnsure Docker Desktop is runningcdinto the chasten directory where theDockerfileis locatedTypedocker build -t chasten .to build the containerType one of the following commands to run the container:Windows (Command Prompt) ->docker run --rm -v "%cd%":/root/src -it chastenWindows (Powershell) ->docker run --rm -v ${pwd}:/root/src -it chastenMac/Ubuntu ->docker run --rm -v $(pwd):/root/src -it chastenInside the container typepoetry installOutside of the container typedocker psto view running container informationOutside of the container typedocker commit <your-container-id> <your-image-name>to save the dependecy installationNow you can use Docker for all of yourchastenneeds!📋 Development TasksLinting and FormattingWe use the linting toolsBlackandRuffon Chasten to ensure code consistency, readability, and adherence to predefined formatting standards across the entire project, ultimately enhancing maintainability and collaboration among developers.Please ensure all content in the project follow the appropriate format by running the following commands:poetry run task fiximportsand/orpoetry run task fixformatbefore shipping new features. If features are shipped with linting issues, the build will break on github due to the failure of the test suite.Testing and CoverageChasten uses the testing toolsPytestandHypothesiswhich enables us to fortify code consistency, readability, and alignment with established formatting standards throughout the project. When writing test cases for features, create a new file in the tests directory with the naming conventiontest_(name of file).Please ensure all content in the project passes the tests by running the following commands:poetry run task testfor most cases or if you would like to test the OpenAI API based featurespoetry run task test-apibefore shipping. If features are shipped without a test suite, the coverage will be lowered on github due to the addition of untested code and may potenitally lead to larger issues in the future.🤗 LearningCurious about the nodes that are available in a Python program's AST?Abstract Syntax Tree
documentationintroduces the
nodes of a Python ASTGreen Tea
Snakesprovides the "missing Python AST docs"Textual AST Viewprovides a
terminal-based tool for browsing a Python program's ASTWant to learn more about how to write XPath expressions for a Python AST?Pyastgrepoffers examples of
XPath expressions for querying a Python program's ASTXPath Documentationdescribes how to write XPath expressionsXPath Axessummaries the
ways that XPath axes relate a note to other nodesInterested in exploring other approaches to querying source code?srcMLsupports XPath-based querying of programs
implemented in C, C#, C++, and JavaTreesitterprovides a
general-purpose approach to modelling and querying source codePython Treesitteroffers
a Python language bindings for to parsing and querying with Treesitter🤓 Chasten vs. SymbexChasten and Symbex, which was created by Simon Willison, are both tools designed for analyzing Python source code, particularly focusing on searching for functions and classes within files. While they share a common goal, there are notable differences between the two, especially in terms of their command-line interfaces and functionality.In terms of Command-Line Interface, Symbex employs a concise CLI, utilizing abbreviations for various options. For instance, the command to search for function signatures in a file namedtest_debug.pyis as follows:command:symbex-s-fsymbex/test_debug.pydeftest_debug_level_values():deftest_debug_level_isinstance():deftest_debug_level_iteration():deftest_debug_destination_values():deftest_debug_destination_isinstance():deftest_debug_destination_iteration():deftest_level_destination_invalid():deftest_debug_destination_invalid():Chasten, on the other hand, leverages Python packages such as Typer and Rich to provide a user-friendly and feature-rich command-line interface. The available commands for Chasten include:analyze               💫 Analyze the AST of Python source codeconfigure             🪂 Manage chasten's configurationdatasette-publish     🌎 Publish a datasette to Fly or Verceldatasette-serve       🏃 Start a local datasette serverintegrate             🚧 Integrate files and make a databaseinteract              🚀 Interactively configure and runlog                  🦚 Start the logging server.In terms of functionality, Symbex is designed to search Python code for functions and classes by name or wildcard. It provides the ability to filter results based on various criteria, including function type (async or non-async), documentation presence, visibility, and type annotations.On the other hand, Chasten'sanalyzecommand performs AST analysis on Python source code. It allows users to specify a project name, XPATH version, search path, and various filtering criteria. Chasten supports checks for inclusion and exclusion based on attributes, values, and match confidence levels. The tool also provides extensive configuration options and the ability to save results in different formats, including markdown.In summary, while both Chasten and Symbex serve the common purpose of analyzing Python source code, Chasten offers a more versatile and user-friendly CLI with additional features of configuration and result management. Symbex, on the other hand, adopts a concise CLI with a focus on searching and filtering functionalities. The choice between the two tools depends on the user's preferences and specific requirements for Python code analysis.📦 Similar ToolsIn addition to Chasten and Symbex, several other tools offer unique capabilities for analyzing and searching through Python source code, each catering to specific use cases.pyastgrepis a tool developed by Luke Plant that provides advanced capabilities for viewing and searching AST using XPath expressions. It allows users to define complex patterns and queries to navigate and extract information from Python code, making it a powerful tool for in-depth code analysis.treesitteroffers a generic and efficient approach to parsing source code and building AST. It supports multiple languages, providing a consistent API for interacting with parsed code across different language ecosystems.🧗ImprovementFound a bug or have a feature that the development team should implement?Raise an issue!Interesting in learning more about tool usage details?Check the
wiki!Want to discuss ways to use the tool?Participate in
discussions!