pjx 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pjx-0.0.1/.github/workflows/ci.yml +86 -0
- pjx-0.0.1/.github/workflows/release.yml +33 -0
- pjx-0.0.1/.gitignore +18 -0
- pjx-0.0.1/.python-version +1 -0
- pjx-0.0.1/.rumdl.toml +76 -0
- pjx-0.0.1/CLAUDE.md +106 -0
- pjx-0.0.1/LICENSE +21 -0
- pjx-0.0.1/PKG-INFO +430 -0
- pjx-0.0.1/README.md +393 -0
- pjx-0.0.1/docs/SECURITY.md +198 -0
- pjx-0.0.1/docs/dev/IDEA.md +1926 -0
- pjx-0.0.1/docs/dev/PLAN.md +830 -0
- pjx-0.0.1/docs/dev/SPEC.md +1673 -0
- pjx-0.0.1/docs/wiki/CLI-Reference.md +616 -0
- pjx-0.0.1/docs/wiki/CSS-and-Assets.md +449 -0
- pjx-0.0.1/docs/wiki/Compilation-Reference.md +562 -0
- pjx-0.0.1/docs/wiki/Component-Syntax.md +572 -0
- pjx-0.0.1/docs/wiki/Configuration-Reference.md +406 -0
- pjx-0.0.1/docs/wiki/Control-Flow.md +697 -0
- pjx-0.0.1/docs/wiki/Deployment.md +737 -0
- pjx-0.0.1/docs/wiki/FastAPI-Integration.md +558 -0
- pjx-0.0.1/docs/wiki/File-Based-Routing.md +512 -0
- pjx-0.0.1/docs/wiki/HTMX-Integration.md +1060 -0
- pjx-0.0.1/docs/wiki/Home.md +157 -0
- pjx-0.0.1/docs/wiki/Imports-and-Composition.md +406 -0
- pjx-0.0.1/docs/wiki/Installation.md +346 -0
- pjx-0.0.1/docs/wiki/Layout-Components.md +877 -0
- pjx-0.0.1/docs/wiki/Layouts-and-Inheritance.md +697 -0
- pjx-0.0.1/docs/wiki/Loading-States.md +589 -0
- pjx-0.0.1/docs/wiki/Middleware.md +510 -0
- pjx-0.0.1/docs/wiki/Project-Structure.md +516 -0
- pjx-0.0.1/docs/wiki/Props-and-Validation.md +601 -0
- pjx-0.0.1/docs/wiki/Quick-Start.md +575 -0
- pjx-0.0.1/docs/wiki/SSE-and-Realtime.md +707 -0
- pjx-0.0.1/docs/wiki/Security.md +653 -0
- pjx-0.0.1/docs/wiki/Slots.md +382 -0
- pjx-0.0.1/docs/wiki/State-and-Reactivity.md +919 -0
- pjx-0.0.1/docs/wiki/Template-Engines.md +559 -0
- pjx-0.0.1/docs/wiki/Troubleshooting.md +514 -0
- pjx-0.0.1/docs/wiki/_Footer.md +1 -0
- pjx-0.0.1/docs/wiki/_Sidebar.md +50 -0
- pjx-0.0.1/examples/demo/README.md +0 -0
- pjx-0.0.1/examples/demo/app/__init__.py +0 -0
- pjx-0.0.1/examples/demo/app/api/__init__.py +1 -0
- pjx-0.0.1/examples/demo/app/api/v1/__init__.py +5 -0
- pjx-0.0.1/examples/demo/app/api/v1/endpoints.py +22 -0
- pjx-0.0.1/examples/demo/app/core/__init__.py +1 -0
- pjx-0.0.1/examples/demo/app/core/config.py +13 -0
- pjx-0.0.1/examples/demo/app/main.py +147 -0
- pjx-0.0.1/examples/demo/app/middleware/__init__.py +9 -0
- pjx-0.0.1/examples/demo/app/middleware/security.py +51 -0
- pjx-0.0.1/examples/demo/app/models/__init__.py +5 -0
- pjx-0.0.1/examples/demo/app/models/schemas.py +19 -0
- pjx-0.0.1/examples/demo/app/pages/__init__.py +19 -0
- pjx-0.0.1/examples/demo/app/pages/routes.py +209 -0
- pjx-0.0.1/examples/demo/app/services/__init__.py +21 -0
- pjx-0.0.1/examples/demo/app/services/data.py +62 -0
- pjx-0.0.1/examples/demo/app/static/css/base.css +57 -0
- pjx-0.0.1/examples/demo/app/static/css/components.css +112 -0
- pjx-0.0.1/examples/demo/app/static/css/pjx-layout.css +32 -0
- pjx-0.0.1/examples/demo/app/static/images/alice.svg +1 -0
- pjx-0.0.1/examples/demo/app/static/images/bob.svg +1 -0
- pjx-0.0.1/examples/demo/app/static/images/charlie.svg +1 -0
- pjx-0.0.1/examples/demo/app/static/images/favicon.svg +4 -0
- pjx-0.0.1/examples/demo/app/static/js/app.js +27 -0
- pjx-0.0.1/examples/demo/app/templates/components/Clock.jinja +17 -0
- pjx-0.0.1/examples/demo/app/templates/components/Counter.jinja +10 -0
- pjx-0.0.1/examples/demo/app/templates/components/Navbar.jinja +13 -0
- pjx-0.0.1/examples/demo/app/templates/components/SearchBox.jinja +19 -0
- pjx-0.0.1/examples/demo/app/templates/components/SearchResult.jinja +15 -0
- pjx-0.0.1/examples/demo/app/templates/components/SearchResults.jinja +22 -0
- pjx-0.0.1/examples/demo/app/templates/components/ServerCounter.jinja +24 -0
- pjx-0.0.1/examples/demo/app/templates/components/Toast.jinja +10 -0
- pjx-0.0.1/examples/demo/app/templates/components/TodoItem.jinja +31 -0
- pjx-0.0.1/examples/demo/app/templates/components/TodoList.jinja +21 -0
- pjx-0.0.1/examples/demo/app/templates/components/TodoStats.jinja +15 -0
- pjx-0.0.1/examples/demo/app/templates/components/UserCard.jinja +18 -0
- pjx-0.0.1/examples/demo/app/templates/layouts/Base.jinja +84 -0
- pjx-0.0.1/examples/demo/app/templates/layouts/Basecoat.jinja +65 -0
- pjx-0.0.1/examples/demo/app/templates/pages/ClockDemo.jinja +15 -0
- pjx-0.0.1/examples/demo/app/templates/pages/ComponentsDemo.jinja +571 -0
- pjx-0.0.1/examples/demo/app/templates/pages/CounterDemo.jinja +23 -0
- pjx-0.0.1/examples/demo/app/templates/pages/Dashboard.jinja +29 -0
- pjx-0.0.1/examples/demo/app/templates/pages/Login.jinja +37 -0
- pjx-0.0.1/examples/demo/app/templates/pages/Protected.jinja +22 -0
- pjx-0.0.1/examples/demo/app/templates/pages/SearchDemo.jinja +20 -0
- pjx-0.0.1/examples/demo/app/templates/pages/TodoDemo.jinja +41 -0
- pjx-0.0.1/examples/demo/app/templates/ui/AspectRatio.jinja +12 -0
- pjx-0.0.1/examples/demo/app/templates/ui/Center.jinja +11 -0
- pjx-0.0.1/examples/demo/app/templates/ui/Container.jinja +12 -0
- pjx-0.0.1/examples/demo/app/templates/ui/Divider.jinja +7 -0
- pjx-0.0.1/examples/demo/app/templates/ui/Grid.jinja +14 -0
- pjx-0.0.1/examples/demo/app/templates/ui/HStack.jinja +14 -0
- pjx-0.0.1/examples/demo/app/templates/ui/Hide.jinja +13 -0
- pjx-0.0.1/examples/demo/app/templates/ui/Spacer.jinja +7 -0
- pjx-0.0.1/examples/demo/app/templates/ui/VStack.jinja +14 -0
- pjx-0.0.1/examples/demo/app/templates/ui/Wrap.jinja +12 -0
- pjx-0.0.1/examples/demo/package-lock.json +18 -0
- pjx-0.0.1/examples/demo/package.json +5 -0
- pjx-0.0.1/examples/demo/pjx.toml +23 -0
- pjx-0.0.1/examples/demo/pyproject.toml +7 -0
- pjx-0.0.1/pyproject.toml +122 -0
- pjx-0.0.1/skills/pjx/SKILL.md +891 -0
- pjx-0.0.1/src/pjx/__init__.py +38 -0
- pjx-0.0.1/src/pjx/__main__.py +5 -0
- pjx-0.0.1/src/pjx/assets.py +116 -0
- pjx-0.0.1/src/pjx/ast_nodes.py +355 -0
- pjx-0.0.1/src/pjx/checker.py +82 -0
- pjx-0.0.1/src/pjx/cli/__init__.py +24 -0
- pjx-0.0.1/src/pjx/cli/build.py +143 -0
- pjx-0.0.1/src/pjx/cli/dev.py +130 -0
- pjx-0.0.1/src/pjx/cli/init.py +615 -0
- pjx-0.0.1/src/pjx/cli/packages.py +85 -0
- pjx-0.0.1/src/pjx/compiler.py +619 -0
- pjx-0.0.1/src/pjx/config.py +109 -0
- pjx-0.0.1/src/pjx/css.py +129 -0
- pjx-0.0.1/src/pjx/engine.py +129 -0
- pjx-0.0.1/src/pjx/errors.py +65 -0
- pjx-0.0.1/src/pjx/handler.py +115 -0
- pjx-0.0.1/src/pjx/health.py +36 -0
- pjx-0.0.1/src/pjx/integration.py +710 -0
- pjx-0.0.1/src/pjx/layout.py +45 -0
- pjx-0.0.1/src/pjx/lexer.py +246 -0
- pjx-0.0.1/src/pjx/log.py +55 -0
- pjx-0.0.1/src/pjx/middleware/__init__.py +5 -0
- pjx-0.0.1/src/pjx/middleware/csrf.py +174 -0
- pjx-0.0.1/src/pjx/parser.py +971 -0
- pjx-0.0.1/src/pjx/props.py +202 -0
- pjx-0.0.1/src/pjx/registry.py +181 -0
- pjx-0.0.1/src/pjx/router.py +406 -0
- pjx-0.0.1/src/pjx/slots.py +44 -0
- pjx-0.0.1/src/pjx/sse.py +166 -0
- pjx-0.0.1/src/pjx/static/pjx-layout.css +32 -0
- pjx-0.0.1/src/pjx/ui/layouts/AspectRatio.jinja +12 -0
- pjx-0.0.1/src/pjx/ui/layouts/Center.jinja +11 -0
- pjx-0.0.1/src/pjx/ui/layouts/Container.jinja +12 -0
- pjx-0.0.1/src/pjx/ui/layouts/Divider.jinja +7 -0
- pjx-0.0.1/src/pjx/ui/layouts/Grid.jinja +14 -0
- pjx-0.0.1/src/pjx/ui/layouts/HStack.jinja +14 -0
- pjx-0.0.1/src/pjx/ui/layouts/Hide.jinja +13 -0
- pjx-0.0.1/src/pjx/ui/layouts/Spacer.jinja +7 -0
- pjx-0.0.1/src/pjx/ui/layouts/VStack.jinja +14 -0
- pjx-0.0.1/src/pjx/ui/layouts/Wrap.jinja +12 -0
- pjx-0.0.1/uv.lock +1021 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, master, dev]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Install uv
|
|
16
|
+
uses: astral-sh/setup-uv@v6
|
|
17
|
+
|
|
18
|
+
- name: Set up Python
|
|
19
|
+
run: uv python install 3.13
|
|
20
|
+
|
|
21
|
+
- name: Install dependencies
|
|
22
|
+
run: uv sync --group dev --group test
|
|
23
|
+
|
|
24
|
+
- name: Format check
|
|
25
|
+
run: uv run ruff format --check --output-format github .
|
|
26
|
+
|
|
27
|
+
- name: Lint
|
|
28
|
+
run: uv run ruff check --output-format github .
|
|
29
|
+
|
|
30
|
+
typecheck:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v4
|
|
34
|
+
|
|
35
|
+
- name: Install uv
|
|
36
|
+
uses: astral-sh/setup-uv@v6
|
|
37
|
+
|
|
38
|
+
- name: Set up Python
|
|
39
|
+
run: uv python install 3.13
|
|
40
|
+
|
|
41
|
+
- name: Install dependencies
|
|
42
|
+
run: uv sync --group dev --group test
|
|
43
|
+
|
|
44
|
+
- name: Type check
|
|
45
|
+
run: uv run ty check --output-format github src/
|
|
46
|
+
|
|
47
|
+
test:
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
strategy:
|
|
50
|
+
matrix:
|
|
51
|
+
python-version: ["3.13", "3.14"]
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v4
|
|
54
|
+
|
|
55
|
+
- name: Install uv
|
|
56
|
+
uses: astral-sh/setup-uv@v6
|
|
57
|
+
|
|
58
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
59
|
+
run: uv python install ${{ matrix.python-version }}
|
|
60
|
+
|
|
61
|
+
- name: Install dependencies
|
|
62
|
+
run: uv sync --group test
|
|
63
|
+
|
|
64
|
+
- name: Run tests
|
|
65
|
+
run: uv run pytest -v --ignore=tests/benchmark --tb=short
|
|
66
|
+
|
|
67
|
+
build:
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
needs: [lint, typecheck, test]
|
|
70
|
+
steps:
|
|
71
|
+
- uses: actions/checkout@v4
|
|
72
|
+
|
|
73
|
+
- name: Install uv
|
|
74
|
+
uses: astral-sh/setup-uv@v6
|
|
75
|
+
|
|
76
|
+
- name: Set up Python
|
|
77
|
+
run: uv python install 3.13
|
|
78
|
+
|
|
79
|
+
- name: Build package
|
|
80
|
+
run: uv build
|
|
81
|
+
|
|
82
|
+
- name: Upload artifacts
|
|
83
|
+
uses: actions/upload-artifact@v4
|
|
84
|
+
with:
|
|
85
|
+
name: dist
|
|
86
|
+
path: dist/
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
id-token: write
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
environment: pypi
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v6
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
run: uv python install 3.13
|
|
22
|
+
|
|
23
|
+
- name: Install dependencies
|
|
24
|
+
run: uv sync --group test
|
|
25
|
+
|
|
26
|
+
- name: Run tests
|
|
27
|
+
run: uv run pytest -v --ignore=tests/benchmark --tb=short
|
|
28
|
+
|
|
29
|
+
- name: Build package
|
|
30
|
+
run: uv build
|
|
31
|
+
|
|
32
|
+
- name: Publish to PyPI
|
|
33
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
pjx-0.0.1/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.14
|
pjx-0.0.1/.rumdl.toml
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# rumdl configuration file
|
|
2
|
+
|
|
3
|
+
# Inherit settings from another config file (relative to this file's directory)
|
|
4
|
+
# extends = "../base.rumdl.toml"
|
|
5
|
+
|
|
6
|
+
# Global configuration options
|
|
7
|
+
[global]
|
|
8
|
+
# List of rules to disable (uncomment and modify as needed)
|
|
9
|
+
# disable = ["MD013", "MD033"]
|
|
10
|
+
|
|
11
|
+
# List of rules to enable exclusively (replaces defaults; only these rules will run)
|
|
12
|
+
# enable = ["MD001", "MD003", "MD004"]
|
|
13
|
+
|
|
14
|
+
# Additional rules to enable on top of defaults (additive, does not replace)
|
|
15
|
+
# Use this to activate opt-in rules like MD060, MD063, MD072, MD073, MD074
|
|
16
|
+
# extend-enable = ["MD060", "MD063"]
|
|
17
|
+
|
|
18
|
+
# Additional rules to disable on top of the disable list (additive)
|
|
19
|
+
# extend-disable = ["MD041"]
|
|
20
|
+
|
|
21
|
+
# List of file/directory patterns to include for linting (if provided, only these will be linted)
|
|
22
|
+
# include = [
|
|
23
|
+
# "docs/*.md",
|
|
24
|
+
# "src/**/*.md",
|
|
25
|
+
# "README.md"
|
|
26
|
+
# ]
|
|
27
|
+
|
|
28
|
+
# List of file/directory patterns to exclude from linting
|
|
29
|
+
exclude = [
|
|
30
|
+
# Common directories to exclude
|
|
31
|
+
".git",
|
|
32
|
+
".github",
|
|
33
|
+
"node_modules",
|
|
34
|
+
"vendor",
|
|
35
|
+
"dist",
|
|
36
|
+
"build",
|
|
37
|
+
|
|
38
|
+
# Specific files or patterns
|
|
39
|
+
"CHANGELOG.md",
|
|
40
|
+
"LICENSE.md",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
# Respect .gitignore files when scanning directories (default: true)
|
|
44
|
+
respect-gitignore = true
|
|
45
|
+
|
|
46
|
+
# Markdown flavor/dialect (uncomment to enable)
|
|
47
|
+
# Options: standard (default), gfm, commonmark, mkdocs, mdx, quarto
|
|
48
|
+
# flavor = "mkdocs"
|
|
49
|
+
|
|
50
|
+
# Rule-specific configurations (uncomment and modify as needed)
|
|
51
|
+
|
|
52
|
+
# [MD003]
|
|
53
|
+
# style = "atx" # Heading style (atx, atx_closed, setext)
|
|
54
|
+
|
|
55
|
+
# [MD004]
|
|
56
|
+
# style = "asterisk" # Unordered list style (asterisk, plus, dash, consistent)
|
|
57
|
+
|
|
58
|
+
# [MD007]
|
|
59
|
+
# indent = 4 # Unordered list indentation
|
|
60
|
+
|
|
61
|
+
# [MD013]
|
|
62
|
+
# line-length = 100 # Line length
|
|
63
|
+
# code-blocks = false # Exclude code blocks from line length check
|
|
64
|
+
# tables = false # Exclude tables from line length check
|
|
65
|
+
# headings = true # Include headings in line length check
|
|
66
|
+
|
|
67
|
+
# [MD044]
|
|
68
|
+
# names = ["rumdl", "Markdown", "GitHub"] # Proper names that should be capitalized correctly
|
|
69
|
+
# code-blocks = false # Check code blocks for proper names (default: false, skips code blocks)
|
|
70
|
+
|
|
71
|
+
[MD013]
|
|
72
|
+
line-length = 0
|
|
73
|
+
|
|
74
|
+
[MD060]
|
|
75
|
+
enabled = true
|
|
76
|
+
style = "aligned"
|
pjx-0.0.1/CLAUDE.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project
|
|
6
|
+
|
|
7
|
+
PJX is a Python DSL for reactive `.jinja` components, inspired by JSX, Svelte
|
|
8
|
+
and SolidJS. It compiles a declarative component syntax (props, state, slots,
|
|
9
|
+
imports, control flow) down to Jinja2 + HTMX + Alpine.js. The full DSL
|
|
10
|
+
specification lives in `docs/dev/IDEA.md`, technical spec in `docs/dev/SPEC.md`.
|
|
11
|
+
|
|
12
|
+
## Stack
|
|
13
|
+
|
|
14
|
+
- **Language**: Python 3.14+
|
|
15
|
+
- **Package manager**: uv
|
|
16
|
+
- **Linter/Formatter**: ruff
|
|
17
|
+
- **Type checker**: ty
|
|
18
|
+
- **Test runner**: pytest
|
|
19
|
+
- **Markdown lint**: rumdl
|
|
20
|
+
- **Runtime deps**: FastAPI, Jinja2, minijinja, Pydantic, Rich, Typer, Uvicorn
|
|
21
|
+
|
|
22
|
+
## Quick Commands
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
rtk uv sync # Install deps from lockfile
|
|
26
|
+
rtk uv run task format # Format (ruff)
|
|
27
|
+
rtk uv run task lint # Lint + autofix (ruff)
|
|
28
|
+
rtk uv run task check # Format + lint + markdown lint
|
|
29
|
+
rtk uv run task typecheck # Type check (ty)
|
|
30
|
+
rtk uv run task test # Run all tests
|
|
31
|
+
rtk uv run task cov # Tests with coverage report
|
|
32
|
+
rtk uv run task ci # Full CI: check + typecheck + test
|
|
33
|
+
rtk uv run pytest tests/test_foo.py::test_bar -v # Single test
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Validation (run in order, fail fast)
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
rtk uv run task ci
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Or manually:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
rtk uv run task check
|
|
46
|
+
rtk uv run task typecheck
|
|
47
|
+
rtk uv run task test
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Skills
|
|
51
|
+
|
|
52
|
+
On-demand knowledge modules in `.agents/skills/`. Load the relevant skill
|
|
53
|
+
when working in its domain.
|
|
54
|
+
|
|
55
|
+
| Skill | When to use |
|
|
56
|
+
| ------------------- | ------------------------------------------------- |
|
|
57
|
+
| `python/SKILL.md` | Python code, conventions, async, uv toolchain |
|
|
58
|
+
| `fastapi/SKILL.md` | FastAPI routes, dependencies, middleware |
|
|
59
|
+
| `jx/SKILL.md` | Jinja server-rendered components (JX patterns) |
|
|
60
|
+
| `frontend/SKILL.md` | JS/CSS tooling, Tailwind, Alpine.js, HTMX |
|
|
61
|
+
| `commit/SKILL.md` | Small logical commits with conventional messages |
|
|
62
|
+
| `refactor/SKILL.md` | Code audit, clean code, SOLID, security review |
|
|
63
|
+
|
|
64
|
+
Each skill has a `references/` folder with detailed submodules. Load on demand.
|
|
65
|
+
|
|
66
|
+
## Conventions
|
|
67
|
+
|
|
68
|
+
- Use `pathlib` over `os.path`
|
|
69
|
+
- f-strings only
|
|
70
|
+
- `snake_case` functions/variables, `PascalCase` classes, `UPPER_SNAKE` constants
|
|
71
|
+
- Type all public functions
|
|
72
|
+
- Use `Annotated` style for FastAPI parameters and dependencies
|
|
73
|
+
- `logging` for app logs, `rich` for CLI output — never `print`
|
|
74
|
+
- Pydantic `BaseModel` for validation, `dataclass` for plain data
|
|
75
|
+
- IO at edges only — services and domain must be pure
|
|
76
|
+
- Prefer `uv` over direct `pip` workflows
|
|
77
|
+
- Never commit code that fails `ruff check`
|
|
78
|
+
|
|
79
|
+
## Code Quality
|
|
80
|
+
|
|
81
|
+
- **Clean Code**: small single-responsibility functions, descriptive names
|
|
82
|
+
that make comments unnecessary, no dead or duplicated code
|
|
83
|
+
- **Pythonic**: use language idioms (comprehensions, context managers,
|
|
84
|
+
itertools, `enumerate`, unpacking) — avoid C-style loops
|
|
85
|
+
- **SOLID**: each module/class has a single reason to change (SRP), depend
|
|
86
|
+
on abstractions not concrete implementations (DIP), prefer composition
|
|
87
|
+
over inheritance
|
|
88
|
+
- **Type safety**: type hints on all public functions and models; use
|
|
89
|
+
`Protocol` / `ABC` for contracts between layers
|
|
90
|
+
|
|
91
|
+
## Tests
|
|
92
|
+
|
|
93
|
+
- All new or changed code must include tests
|
|
94
|
+
- Keep coverage high — cover happy path, edge cases, and expected errors
|
|
95
|
+
- Unit tests for pure logic, integration tests for IO and endpoints
|
|
96
|
+
- Descriptive test names: `test_<unit>_<scenario>_<expected>`
|
|
97
|
+
- Use fixtures and parametrize to avoid repetition
|
|
98
|
+
|
|
99
|
+
## Documentation
|
|
100
|
+
|
|
101
|
+
- Update docstrings (Google style) on all public functions/classes created
|
|
102
|
+
or modified
|
|
103
|
+
- Keep `README.md` up to date when installation, usage, or architecture changes
|
|
104
|
+
- Add usage examples in `examples/` for each public feature — short
|
|
105
|
+
self-contained scripts that demonstrate real API usage
|
|
106
|
+
- Update `docs/dev/IDEA.md` if the implementation diverges from the spec
|
pjx-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fabio Souza
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|