Skip to content

Commit

Permalink
add something about parser
Browse files Browse the repository at this point in the history
  • Loading branch information
noklam committed Feb 2, 2025
1 parent dc91629 commit 07e8f50
Show file tree
Hide file tree
Showing 12 changed files with 240 additions and 4 deletions.
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
run:
python src/ruff_in_python/main.py
python src/ruff_in_python/main.py

lint:
ruff check . --fix & ruff format .
install:
pip install -e .

test:
pytest -vv
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,32 @@ linter.rs
message.rs
parser.rs

## Libraries used for 1st version of ruff
The first-ever version of Ruff used the following Rust packages

fern: for logging
rayon: for parallelizing computation
clap: for cli argument parsing
serde: for serializing and deserializing data
rustpython: for parsing, uses the provided AST
colored: for adding colors to the terminal
walkdir: for walking a directory recursively
anyhow: Flexible concrete Error type built on std::error::Error

## Libraries I used for the Python verrsion
logging: std logging library
?: parallel computation
typer: cli argument parsing
?: serialising
ast: Python native ast library
rich: color terminal
os/pathlib: walking directory
?: error
pytest: write simple tests

## Rebuild with Rust

Reference:
Blog: https://compileralchemy.substack.com/p/ruff-internals-of-a-rust-backed-python
Commit:

Binary file added images/cli.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions images/note.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
![alt text](cli.png)
Empty file added src/ruff_in_python/cache.py
Empty file.
Empty file added src/ruff_in_python/lib.py
Empty file.
Empty file added src/ruff_in_python/linter.py
Empty file.
36 changes: 33 additions & 3 deletions src/ruff_in_python/main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,37 @@
def main(name: str):
print(f"Hello {name}")
import logging
from rich.logging import RichHandler

logger = logging.getLogger()

logging.basicConfig(
level="NOTSET",
format="%(message)s",
datefmt="[%X]",
handlers=[RichHandler(rich_tracebacks=True)],
)


def main(filepath: str = None):
if not filepath:
filepath = "tests/bar.py"
logger.info(f"flie path: {filepath}")
set_up_logging()
run_once(filepath)


def set_up_logging():
logger.info("dummy: set up logging")


def run_once(filepath: str = None):
logger.info("run once")
logger.info("Identified files to lint in")
logger.info("Checked files in ")
logger.info("Found TODO errors")
errors = []
for error in errors:
logger.warning(error)


if __name__ == "__main__":
main("dummy")
main("dummy")
Empty file added src/ruff_in_python/message.py
Empty file.
15 changes: 15 additions & 0 deletions src/ruff_in_python/parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import ast
from pathlib import Path


def pretty_print_ast(self):
# Monkeypatch so it's easier to visualise the ast module
return ast.dump(self, indent=2)


ast.Module.__repr__ = pretty_print_ast


def parse(path: Path):
with open(path) as f:
return ast.parse(f.read())
150 changes: 150 additions & 0 deletions src/ruff_in_python/scratch.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"import ast"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"stmt = \"print(123)\""
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"parsed = ast.parse(stmt)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Module(\n",
" body=[\n",
" Expr(\n",
" value=Call(\n",
" func=Name(id='print', ctx=Load()),\n",
" args=[\n",
" Constant(value=123)],\n",
" keywords=[]))],\n",
" type_ignores=[])\n"
]
}
],
"source": [
"print(ast.dump(parsed, indent=2))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This works fine, but it's easier to make a pretty print function to avoid doing this everytime. Actually, in Python I can just monkeypatch the class to do this."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"ast.Module"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(parsed)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"def pretty_print_ast(self):\n",
" return ast.dump(self, indent=2)\n",
"ast.Module.__repr__ = pretty_print_ast"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Module(\n",
" body=[\n",
" Expr(\n",
" value=Call(\n",
" func=Name(id='print', ctx=Load()),\n",
" args=[\n",
" Constant(value=123)],\n",
" keywords=[]))],\n",
" type_ignores=[])"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"parsed"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "kedro",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.14"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
8 changes: 8 additions & 0 deletions tests/test_parse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import ast
from ruff_in_python.parser import parse


def test_parser():
stmt = "print(123)"
res = parse(stmt)
assert isinstance(res, ast.Module)

0 comments on commit 07e8f50

Please sign in to comment.