Skip to content

Repository files navigation

Static Code Analyzer

Python Dependencies GitHub last commit GitHub repo size GitHub stars

A command-line static analysis tool for Python source code, built from scratch — no pycodestyle, no flake8, no third-party parser. It walks source files line-by-line (and, for the deeper checks, through Python's own ast module) to flag common PEP 8–style issues and reports them in a file: Line N: <code> <message> format familiar from tools like pylint and flake8.

The repository is organized as five progressive implementations (level1level5), each one a complete, runnable analyzer that builds on the last — going from a single 18-line line-length checker to a 785-line analyzer with 12 rules, AST-based checks, and multi-file/directory scanning.


Table of Contents


Overview

staticCodeAnalyzer inspects .py files and prints one diagnostic line per violation found, in the form:

<file>: Line <line_number>: <rule_code> <message>

It supports two run modes (from Level 3 onward):

  • Single file — pass a path to one .py file.
  • Directory — pass a path to a folder; every .py file inside is scanned and results are printed per file.

Each rule is implemented as its own custom Exception subclass, raised internally and immediately caught to print a formatted message — used as a lightweight, self-contained way to carry the line number, file path, and rule-specific context (e.g. the offending identifier) through to the point where it's printed.

Rules Reference

The final stage (level5) implements all 12 checks below. Earlier stages implement a subset — see Development Stages.

Code Rule What it flags
S001 Line too long Line exceeds 79 characters
S002 Indentation Indentation is not a multiple of four spaces
S003 Unnecessary semicolon A statement ends with a redundant ;
S004 Inline comment spacing Fewer than two spaces before an inline # comment
S005 TODO found A TODO marker (any case) appears in a comment
S006 Blank lines More than two consecutive blank lines precede a line of code
S007 Spacious constructor More than one space after class or def before the name
S008 Class naming Class name is not in CamelCase
S009 Function naming Function name is not in snake_case
S010 Argument naming A function argument name is not in snake_case
S011 Variable naming A local variable name is not in snake_case
S012 Mutable default argument A function default argument is a mutable object (e.g. [])

How It Works

The analyzer combines two complementary strategies depending on the check:

  1. Lexical / character-position scanning (S001S007) — for every line, indexFinder() locates the position of #, the first non-whitespace character, and any ;, and each rule function reasons about those positions (e.g. "is the ; before or after the comment marker?", "is the first character at a column divisible by 4?").
  2. AST-based structural analysis (S008S012, introduced in Level 5) — the file is additionally parsed with Python's built-in ast module to reliably extract class names, function names, argument names, assignment targets, and default argument values, which are then checked against naming conventions or mutability rules.

Single-file mode raises and prints each violation as it's found; directory mode accumulates violations per file into a shared dictionary (fileErrorDict) keyed by filename and line number, then reports them in file/line order once every file has been scanned.

Development Stages

Each level is a fully working analyzer in its own right — useful for seeing how the tool's rule set and I/O model grew over time.

Stage File Size Rules implemented Input mode
1 staticCodeAnalyzer - level1.py 18 lines S001 Single file, via input()
2 staticCodeAnalyzer - level2.py 254 lines S001S006 Single file, via input()
3 staticCodeAnalyzer - level3.py 421 lines S001S006 Single file or directory, via CLI arg
4 staticCodeAnalyzer - level4.py 573 lines S001S009 Single file or directory, via CLI arg
5 staticCodeAnalyzer - level5.py 785 lines S001S012 (adds AST-based checks) Single file or directory, via CLI arg

If you just want the most capable version of the tool, use level5.

Getting Started

Requirements

  • Python 3.6+ (the code relies on f-strings)
  • No third-party packages — only the standard library (ast, os, string, sys)

Installation

git clone https://github.com/AstronauticalCodes/staticCodeAnalyzer.git
cd staticCodeAnalyzer

There's nothing to pip install — each level is a standalone script.

Usage

From Level 3 onward, the target path is passed as a command-line argument:

# Analyze a single file
python "staticCodeAnalyzer - level5.py" path/to/your_file.py

# Analyze every .py file in a directory
python "staticCodeAnalyzer - level5.py" path/to/your_project/

Note on paths: the script currently prepends a hardcoded local development path (halfPath, near the top of the file — originally set to a path on the author's own machine) to any input that doesn't start with C. To run it in your own environment, either:

  • pass an absolute path starting with C (Windows-style, e.g. C:\Users\you\project\file.py), which bypasses the prefix entirely, or
  • edit the halfPath variable in the script to point at your own working directory (or blank it out to use paths as-is).

Levels 1 and 2 instead prompt for the file path via input():

python "staticCodeAnalyzer - level1.py"
# then type or paste the file path when prompted

Example

Given a file with a couple of style issues:

class bad_class_name:
    def BadFunctionName(self, X):
        y=1;
        print(y)  #no space before comment

Running the Level 5 analyzer against it would report something like:

example.py: Line 1: S008 Class name 'bad_class_name' should use CamelCase
example.py: Line 2: S009 Function name 'BadFunctionName' should use snake_case
example.py: Line 2: S010 Argument name 'X' should be written in snake_case
example.py: Line 3: S003 Unnecessary semicolon
example.py: Line 3: S011 Variable 'y' should be in snake_case
example.py: Line 4: S004 At least two spaces required before inline comments

Design Notes & Known Limitations

Documented here for transparency and as a map for anyone picking up the Roadmap:

  • Custom exceptions shadow built-ins. IndentationError is redefined as a custom exception class, shadowing Python's built-in exception of the same name within the module's scope.
  • Directory mode assumes Windows-style paths. File paths inside a scanned directory are joined with a literal '\\', so directory mode as currently written targets Windows; single-file mode is platform-agnostic.
  • Character-index parsing instead of tokenize. Comment/semicolon detection is done by scanning for literal # and ; characters rather than using Python's tokenize module, so a # or ; inside a string literal can produce a false positive.
  • Substring-based TODO detection. S005 checks for the literal substring todo (in various letter-case combinations) anywhere after a #, so it can also match words that merely contain "todo" rather than a deliberate TODO marker.
  • No automated tests. Correctness has been validated manually rather than with a test suite.

Roadmap

Ideas for anyone extending the project:

  • Replace manual character-index scanning with Python's tokenize module for more robust comment/string handling
  • Use pathlib and os.path.join for cross-platform directory scanning
  • Add a pyproject.toml and console-script entry point (static-code-analyzer <path> instead of invoking the .py file directly)
  • Add a pytest suite covering each rule, plus a CI workflow to run it on push
  • Support a config file / CLI flags for ignoring specific rules or codes
  • Add a machine-readable output mode (JSON) for editor and CI integration
  • Consolidate the five levels into a single versioned entry point, keeping the stage history in git tags/branches instead of parallel files

Contributing

Contributions are welcome:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-improvement)
  3. Commit your changes with a clear message
  4. Open a pull request describing what changed and why

For anything nontrivial, opening an issue first to discuss the approach is appreciated.

License

No license file is currently included in this repository, which by default means all rights are reserved by the author. If you intend for others to reuse or modify this code, consider adding a LICENSE file (e.g. MIT or Apache-2.0).

About

A simple static analyzer tool that finds common stylistic issues in Python code.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages