Contributing

Hard constraints, workflow, and style rules for contributors and agents working on PYNE.

This page

Manuals

Full PDFComplete

Contributing

Abstract

Contributions to PYNE are welcome when they respect the repo’s mechanical invariants: generated code boundaries, src-layout packaging, dual console scripts, test corpus costs, and encryption secrets. This page distills CONTRIBUTING.md and AGENTS.md into an operational contract for humans and agents.

Conceptual model

Diagram

Rendering…

Interface surface

Baseline workflow

  1. Fork and branch from main
  2. Install: make install or hatch envs
  3. Run tests: make test / hatch run test:test
  4. Implement with tests (prefer TDD for non-trivial behavior)
  5. Lint/format: make lint / make fmt or hatch run lint:style + lint:typing
  6. Open a PR with rationale + test evidence

Official short form also lives in root CONTRIBUTING.md.

Everyday commands

GoalCommand
Editable install + LSPmake install
Full testsmake test
LSP onlymake test-lsp
Backend onlymake test-backend
Lint / formatmake lint / make fmt
Fast build sanitymake build-check
APImake run
LSP processmake run-lsp

Hard constraints

Grammar & generated code

  • Edit only src/pynescript/ast/grammar/antlr4/resource/*.g4 for grammar work
  • Never hand-edit …/antlr4/generated/ or …/asdl/generated/
  • Regenerate via hatch lint:gen-parser / project scripts; see grammar guides under .opencode/context/

No stale backups

Do not recreate removed backups such as builder.py.bak or evaluator/builtins/technical_refactored.py. Live builder.py and technical.py are sole sources of truth.

Future annotations

Every new Python file must start with:

from __future__ import annotations

Enforced by ruff isort required-imports.

Console scripts

PreferredAliasRole
pynepynescriptClick CLI
pyne-lsppynescript-lspLanguage Server (pygls)

Import package remains pynescript. Do not conflate CLI and LSP entrypoints in docs, packaging, or process managers.

Optional example-script fixture

tests/conftest.py only expands pinescript_filepath when --example-scripts-dir points at a local directory of *.pine files. No third-party corpus is shipped in the repository.

tests/data/library/ is reference material, not auto-parametrized.

Builtin metadata

builtin_metadata.json is generated from code. After adding builtins:

python scripts/generate_builtin_metadata.py

Do not hand-maintain the catalog long-term.

Interpret / compile parity

When changing pynescript.runtime.Runtime, the compiler, or plot/series export, check series parity between mode="interpret" and mode="compile":

# Local corpus harness (default 50 scripts × 1000 bars)
python scripts/compare_interp_compile.py --bars 1000 --limit 50

# Broader pass from a path list; ignore one-sided hline/fill keys
python scripts/compare_interp_compile.py --file-list path.txt --limit 0 --workers 4 --timeout-sec 30 --ignore-hline-keys --ignore-fill-keys

Always-on unit coverage lives in tests/test_interp_compile_parity.py (harness helpers + a small smoke subset). Optional longer path:

pytest tests/test_interp_compile_parity.py -m interp_compile_full
# or: PYNE_INTERP_COMPILE_FULL=1 pytest tests/test_interp_compile_parity.py

Report artifact: .cache/interp_compile_parity.json. Value mismatches on shared series keys are regressions. First-party hline / fill / bgcolor / plotshape / barcolor / plotarrow / plotbar / plotcandle keys match (0.3.12); drawings is geometry-only. --ignore-hline-keys / --ignore-fill-keys are optional for leftover corpus noise. End-user mode semantics: Evaluate scripts — Runtime modes.

Secrets & crypto

  • scripts/build/.metadata.key is gitignored
  • CI must supply stable CRYPTO_KEY from METADATA_KEY / _METADATA_KEY for reproducible .enc blobs
  • Never commit Fernet keys or API admin tokens

Internals (where to change what)

Want to…Look at
Parse / unparsesrc/pynescript/ast/helper.py
Add builtinsrc/pynescript/ast/evaluator/builtins/<ns>.py + metadata generator
LSP featuresrc/pynescript/langserver/features/ + server.py
CLI subcommandsrc/pynescript/__main__.py
Grammarresource/*.g4 then regenerate
Pro API routebackend/api/preview.py, backend/app.py
Runtime modes / compile fallbacksrc/pynescript/runtime/host.py (Runtime.run); backend/runtime.py is a shim
Interp/compile series parityscripts/compare_interp_compile.py, tests/test_interp_compile_parity.py
TS librarysister repo hoox-sh/pynets / @hoox-sh/pynets

Style

  • Ruff line length 120; broad rule set in pyproject.toml
  • Black target py310 (via toolchain config)
  • Mypy strict-ish; exemptions for generated grammar, evaluator.builtins.*, tests
  • Voice for docs: academic nerdy-cool per docs/WRITING.md — no empty marketing adjectives

Release (this repo)

Match root CONTRIBUTING.md and .github/workflows/publish.yml / release.yml / ghcr.yml:

  1. Bump __version__ in src/pynescript/__about__.py and update CHANGELOG.md.
  2. Align vscode-extension/package.json when shipping the VSIX together.
  3. Ensure CI is green on main.
  4. Tag and push: git tag vX.Y.Z && git push origin vX.Y.Z.
  5. Publish (publish.yml) builds sdist/wheel (hoox_pyne-*.whl) and uploads to PyPI (PYPI_API_TOKEN or Trusted Publishing OIDC, environment pypi).
  6. Build & Release (release.yml) attaches Nuitka CLI/LSP binaries + VSIX to the GitHub Release.
  7. GHCR (ghcr.yml) publishes ghcr.io/hoox-sh/pyne/{cli,lsp,api}:X.Y.Z on v* tags.

Dry-run PyPI: Actions → Publish → Run workflow → dry_run=true. Local: python -m build && twine check dist/*.

AXIS charting releases live in hoox-sh/axis (historical fork: jango-blockchained/axis).

PyneTS contributions

  • Work in hoox-sh/pynets, not a pine-worker/ directory in this repo
  • Bun for install / test / typecheck; bun run generate after PYNE .g4 changes
  • Python remains the oracle — see PyneTS parity
  • Do not copy PyneTS sources into this tree; work in the standalone hoox-sh/pynets repo / @hoox-sh/pynets package
  • Python Runtime remains the oracle.

Failure modes for contributors

MistakeFallout
Editing generated ANTLR/ASDLOverwritten / review hell
Skipping corpus cost awareness10-minute “unit” tests
Hand-editing metadata JSONDrift from dispatch
Changing compile/export without parity checkSilent chart/series drift vs interpret
Committing .metadata.keySecret leak; rotate immediately
PR without lintCI red on ruff/mypy

See also