inito 0.0.1b0__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.
Files changed (118) hide show
  1. inito-0.0.1b0/.github/workflows/ci.yml +65 -0
  2. inito-0.0.1b0/.github/workflows/release.yml +46 -0
  3. inito-0.0.1b0/.gitignore +25 -0
  4. inito-0.0.1b0/.pre-commit-config.yaml +14 -0
  5. inito-0.0.1b0/CHANGELOG.md +43 -0
  6. inito-0.0.1b0/CLAUDE.md +105 -0
  7. inito-0.0.1b0/CONTRIBUTING.md +64 -0
  8. inito-0.0.1b0/LICENSE +21 -0
  9. inito-0.0.1b0/PKG-INFO +161 -0
  10. inito-0.0.1b0/README.md +121 -0
  11. inito-0.0.1b0/TASKS.md +280 -0
  12. inito-0.0.1b0/benchmarks/conftest.py +156 -0
  13. inito-0.0.1b0/benchmarks/import_time.py +50 -0
  14. inito-0.0.1b0/benchmarks/memory_profile.py +82 -0
  15. inito-0.0.1b0/benchmarks/pyperf_suite.py +67 -0
  16. inito-0.0.1b0/benchmarks/test_attribute_access_benchmark.py +8 -0
  17. inito-0.0.1b0/benchmarks/test_builder_benchmark.py +11 -0
  18. inito-0.0.1b0/benchmarks/test_construction_benchmark.py +6 -0
  19. inito-0.0.1b0/benchmarks/test_decoration_benchmark.py +6 -0
  20. inito-0.0.1b0/benchmarks/test_equality_benchmark.py +8 -0
  21. inito-0.0.1b0/benchmarks/test_hash_benchmark.py +7 -0
  22. inito-0.0.1b0/benchmarks/test_repr_benchmark.py +7 -0
  23. inito-0.0.1b0/docs/api.md +144 -0
  24. inito-0.0.1b0/docs/conf.py +41 -0
  25. inito-0.0.1b0/docs/examples.md +71 -0
  26. inito-0.0.1b0/docs/faq.md +58 -0
  27. inito-0.0.1b0/docs/index.md +36 -0
  28. inito-0.0.1b0/docs/installation.md +31 -0
  29. inito-0.0.1b0/docs/migration.md +72 -0
  30. inito-0.0.1b0/docs/performance.md +113 -0
  31. inito-0.0.1b0/docs/quickstart.md +97 -0
  32. inito-0.0.1b0/docs/troubleshooting.md +86 -0
  33. inito-0.0.1b0/examples/all_args_constructor_basic.py +18 -0
  34. inito-0.0.1b0/examples/builder_basic.py +72 -0
  35. inito-0.0.1b0/examples/data_basic.py +35 -0
  36. inito-0.0.1b0/examples/equals_and_hash_code_basic.py +20 -0
  37. inito-0.0.1b0/examples/getter_basic.py +20 -0
  38. inito-0.0.1b0/examples/no_args_constructor_basic.py +18 -0
  39. inito-0.0.1b0/examples/required_args_constructor_basic.py +18 -0
  40. inito-0.0.1b0/examples/setter_basic.py +20 -0
  41. inito-0.0.1b0/examples/to_string_basic.py +19 -0
  42. inito-0.0.1b0/pyproject.toml +109 -0
  43. inito-0.0.1b0/scripts/check_all.sh +7 -0
  44. inito-0.0.1b0/src/inito/__init__.py +62 -0
  45. inito-0.0.1b0/src/inito/builders/__init__.py +5 -0
  46. inito-0.0.1b0/src/inito/builders/builder_generator.py +140 -0
  47. inito-0.0.1b0/src/inito/core/__init__.py +5 -0
  48. inito-0.0.1b0/src/inito/core/attach.py +39 -0
  49. inito-0.0.1b0/src/inito/decorators/__init__.py +57 -0
  50. inito-0.0.1b0/src/inito/decorators/all_args_constructor.py +25 -0
  51. inito-0.0.1b0/src/inito/decorators/builder.py +25 -0
  52. inito-0.0.1b0/src/inito/decorators/data.py +44 -0
  53. inito-0.0.1b0/src/inito/decorators/equals_and_hash_code.py +26 -0
  54. inito-0.0.1b0/src/inito/decorators/getter.py +25 -0
  55. inito-0.0.1b0/src/inito/decorators/no_args_constructor.py +29 -0
  56. inito-0.0.1b0/src/inito/decorators/required_args_constructor.py +30 -0
  57. inito-0.0.1b0/src/inito/decorators/setter.py +25 -0
  58. inito-0.0.1b0/src/inito/decorators/to_string.py +25 -0
  59. inito-0.0.1b0/src/inito/exceptions/__init__.py +23 -0
  60. inito-0.0.1b0/src/inito/exceptions/errors.py +35 -0
  61. inito-0.0.1b0/src/inito/generators/__init__.py +26 -0
  62. inito-0.0.1b0/src/inito/generators/accessors.py +38 -0
  63. inito-0.0.1b0/src/inito/generators/base.py +52 -0
  64. inito-0.0.1b0/src/inito/generators/constructor.py +164 -0
  65. inito-0.0.1b0/src/inito/generators/equality.py +56 -0
  66. inito-0.0.1b0/src/inito/generators/registry.py +41 -0
  67. inito-0.0.1b0/src/inito/generators/repr_.py +23 -0
  68. inito-0.0.1b0/src/inito/metadata/__init__.py +13 -0
  69. inito-0.0.1b0/src/inito/metadata/class_metadata.py +31 -0
  70. inito-0.0.1b0/src/inito/metadata/extractor.py +73 -0
  71. inito-0.0.1b0/src/inito/metadata/field.py +29 -0
  72. inito-0.0.1b0/src/inito/py.typed +0 -0
  73. inito-0.0.1b0/src/inito/reflection/__init__.py +1 -0
  74. inito-0.0.1b0/src/inito/reflection/introspection.py +32 -0
  75. inito-0.0.1b0/src/inito/typing/__init__.py +5 -0
  76. inito-0.0.1b0/src/inito/utils/__init__.py +1 -0
  77. inito-0.0.1b0/src/inito/utils/codegen.py +33 -0
  78. inito-0.0.1b0/src/inito/utils/decorator_factory.py +51 -0
  79. inito-0.0.1b0/tests/builders/__init__.py +0 -0
  80. inito-0.0.1b0/tests/builders/test_builder_generator.py +136 -0
  81. inito-0.0.1b0/tests/core/__init__.py +0 -0
  82. inito-0.0.1b0/tests/core/test_attach.py +65 -0
  83. inito-0.0.1b0/tests/decorators/__init__.py +0 -0
  84. inito-0.0.1b0/tests/decorators/test_all_args_constructor.py +36 -0
  85. inito-0.0.1b0/tests/decorators/test_builder.py +81 -0
  86. inito-0.0.1b0/tests/decorators/test_data.py +103 -0
  87. inito-0.0.1b0/tests/decorators/test_equals_and_hash_code.py +56 -0
  88. inito-0.0.1b0/tests/decorators/test_getter.py +46 -0
  89. inito-0.0.1b0/tests/decorators/test_no_args_constructor.py +33 -0
  90. inito-0.0.1b0/tests/decorators/test_required_args_constructor.py +25 -0
  91. inito-0.0.1b0/tests/decorators/test_setter.py +47 -0
  92. inito-0.0.1b0/tests/decorators/test_to_string.py +49 -0
  93. inito-0.0.1b0/tests/exceptions/__init__.py +0 -0
  94. inito-0.0.1b0/tests/exceptions/test_errors.py +41 -0
  95. inito-0.0.1b0/tests/generators/__init__.py +0 -0
  96. inito-0.0.1b0/tests/generators/test_accessors_generator.py +48 -0
  97. inito-0.0.1b0/tests/generators/test_base.py +32 -0
  98. inito-0.0.1b0/tests/generators/test_constructor_generator.py +61 -0
  99. inito-0.0.1b0/tests/generators/test_equality_generator.py +46 -0
  100. inito-0.0.1b0/tests/generators/test_no_args_constructor_generator.py +58 -0
  101. inito-0.0.1b0/tests/generators/test_registry.py +24 -0
  102. inito-0.0.1b0/tests/generators/test_repr_generator.py +29 -0
  103. inito-0.0.1b0/tests/generators/test_required_args_constructor_generator.py +75 -0
  104. inito-0.0.1b0/tests/integration/__init__.py +0 -0
  105. inito-0.0.1b0/tests/integration/test_composition.py +79 -0
  106. inito-0.0.1b0/tests/integration/test_edge_cases.py +99 -0
  107. inito-0.0.1b0/tests/integration/test_frozen.py +58 -0
  108. inito-0.0.1b0/tests/integration/test_generics.py +28 -0
  109. inito-0.0.1b0/tests/integration/test_invalid_usage.py +54 -0
  110. inito-0.0.1b0/tests/metadata/__init__.py +0 -0
  111. inito-0.0.1b0/tests/metadata/test_class_metadata.py +27 -0
  112. inito-0.0.1b0/tests/metadata/test_extractor.py +85 -0
  113. inito-0.0.1b0/tests/metadata/test_field_metadata.py +31 -0
  114. inito-0.0.1b0/tests/reflection/__init__.py +0 -0
  115. inito-0.0.1b0/tests/reflection/test_introspection.py +54 -0
  116. inito-0.0.1b0/tests/utils/__init__.py +0 -0
  117. inito-0.0.1b0/tests/utils/test_codegen.py +34 -0
  118. inito-0.0.1b0/tests/utils/test_decorator_factory.py +66 -0
@@ -0,0 +1,65 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ concurrency:
9
+ group: ${{ github.workflow }}-${{ github.ref }}
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ quality:
14
+ name: lint, format, typecheck, test (py${{ matrix.python-version }})
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
20
+ steps:
21
+ - uses: actions/checkout@v7
22
+ - name: Install uv
23
+ uses: astral-sh/setup-uv@v8.2.0
24
+ with:
25
+ python-version: ${{ matrix.python-version }}
26
+ - name: Install project (dev extras)
27
+ run: |
28
+ uv venv --python ${{ matrix.python-version }}
29
+ uv pip install -e ".[dev]"
30
+ - name: Ruff check
31
+ run: uv run ruff check .
32
+ - name: Ruff format check
33
+ run: uv run ruff format --check .
34
+ - name: Mypy
35
+ run: uv run mypy src
36
+ - name: Pytest with coverage
37
+ run: uv run pytest --cov-report=html
38
+ - name: Build docs (warnings-as-errors)
39
+ if: matrix.python-version == '3.13'
40
+ run: uv run sphinx-build -b html docs docs/_build -W
41
+ - name: Upload coverage artifact
42
+ if: matrix.python-version == '3.13'
43
+ uses: actions/upload-artifact@v7
44
+ with:
45
+ name: coverage-html
46
+ path: htmlcov
47
+
48
+ build:
49
+ name: build sdist and wheel
50
+ runs-on: ubuntu-latest
51
+ needs: quality
52
+ steps:
53
+ - uses: actions/checkout@v7
54
+ - name: Install uv
55
+ uses: astral-sh/setup-uv@v8.2.0
56
+ with:
57
+ python-version: "3.13"
58
+ - name: Build
59
+ run: uv build
60
+ - name: Check metadata with twine
61
+ run: uvx twine check dist/*
62
+ - uses: actions/upload-artifact@v7
63
+ with:
64
+ name: dist
65
+ path: dist
@@ -0,0 +1,46 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ concurrency:
9
+ group: release-${{ github.ref }}
10
+ cancel-in-progress: false
11
+
12
+ jobs:
13
+ build:
14
+ name: Build distribution
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v7
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v8.2.0
20
+ with:
21
+ python-version: "3.13"
22
+ - name: Build
23
+ run: uv build
24
+ - name: Check metadata with twine
25
+ run: uvx twine check dist/*
26
+ - uses: actions/upload-artifact@v7
27
+ with:
28
+ name: release-dist
29
+ path: dist
30
+
31
+ publish:
32
+ name: Publish to PyPI
33
+ needs: build
34
+ runs-on: ubuntu-latest
35
+ environment:
36
+ name: pypi
37
+ url: https://pypi.org/project/inito/
38
+ permissions:
39
+ id-token: write # required for PyPI trusted publishing (OIDC) - no API token needed
40
+ steps:
41
+ - uses: actions/download-artifact@v8
42
+ with:
43
+ name: release-dist
44
+ path: dist
45
+ - name: Publish to PyPI
46
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,25 @@
1
+ local_dev/
2
+
3
+ # Python
4
+ __pycache__/
5
+ *.pyc
6
+ *.pyo
7
+ *.egg-info/
8
+ .venv/
9
+ .venv*/
10
+ venv/
11
+
12
+ # Build artifacts
13
+ dist/
14
+ build/
15
+
16
+ # Tooling caches
17
+ .mypy_cache/
18
+ .ruff_cache/
19
+ .pytest_cache/
20
+ .coverage
21
+ htmlcov/
22
+
23
+ # Docs
24
+ site/
25
+ docs/_build/
@@ -0,0 +1,14 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.6.9
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
8
+ - repo: https://github.com/pre-commit/mirrors-mypy
9
+ rev: v1.11.2
10
+ hooks:
11
+ - id: mypy
12
+ additional_dependencies: []
13
+ args: [src]
14
+ pass_filenames: false
@@ -0,0 +1,43 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.0.1-beta] - 2026-07-01
11
+
12
+ ### Added
13
+ - Core metadata/reflection/code-generation engine: decoration-time-only
14
+ field metadata extraction, an `exec()`-based method-generation utility,
15
+ a shared dual-mode (`@dec`/`@dec(...)`) decorator factory, and a
16
+ generator registry for capability-based reuse across decorators.
17
+ - `@Data`: constructor, `__repr__`, `__eq__`, `__hash__`, and
18
+ `get_`/`set_` accessors for every declared field.
19
+ - `@Getter`, `@Setter`: accessors only.
20
+ - `@NoArgsConstructor`: no-argument constructor using field defaults.
21
+ - `@AllArgsConstructor`, `@RequiredArgsConstructor`: constructor-only
22
+ decorators accepting every field or only required fields, respectively.
23
+ - `@Builder`/`builder`: a fluent, chainable builder (`.builder()...build()`)
24
+ with `to_builder()` support (`to_builder=True`), `setter_prefix`, and
25
+ `build_method_name` options. Works standalone on plain classes and
26
+ composes with `@dataclass`.
27
+ - `@ToString`: `__repr__` only.
28
+ - `@EqualsAndHashCode`: `__eq__`/`__hash__` only.
29
+ - Full test suite (176 tests, 100% line+branch coverage), a
30
+ pytest-benchmark/pyperf/tracemalloc/import-time benchmark suite, and
31
+ Sphinx + Furo documentation (installation, quickstart, API reference,
32
+ examples, migration guide, performance report, FAQ, troubleshooting).
33
+ - GitHub Actions CI (lint/format/typecheck/test/build across Python
34
+ 3.9-3.13) and a tag-triggered PyPI trusted-publishing release workflow.
35
+
36
+ ### Known limitations
37
+ - Static type checkers (mypy/pyright) don't see generated members without
38
+ a dedicated plugin (tracked for a future release).
39
+ - Stacking any constructor-generating decorator with
40
+ `@dataclass(frozen=True)` raises `FrozenInstanceError` (expected, not a
41
+ bug — see the README/troubleshooting docs).
42
+ - Self-referential forward references (e.g. `next: Node`) aren't supported,
43
+ since annotations resolve eagerly at decoration time.
@@ -0,0 +1,105 @@
1
+ # CLAUDE.md
2
+
3
+ Guidance for working on `inito` in this repository.
4
+
5
+ ## Project summary
6
+
7
+ `inito` is a Lombok-inspired, zero-runtime-dependency Python library. It
8
+ eliminates boilerplate (constructors, `repr`, equality/hashing, accessors,
9
+ builders) via decorators that generate real methods once, at class-decoration
10
+ time, then attach them directly to the class.
11
+
12
+ ## Authoritative specs
13
+
14
+ `local_dev/inito.md` (product/technical spec) and `local_dev/engineering.md`
15
+ (coding standards) are the governing documents for this project. Both are
16
+ gitignored and dev-machine-only — if they're missing on a fresh clone, ask
17
+ the user for them before doing feature work. Read them before implementing
18
+ anything not already covered here.
19
+
20
+ ## The non-negotiable performance rule
21
+
22
+ All reflection/annotation inspection happens **exactly once, at decoration
23
+ time**. Never inspect annotations or defaults at instance-construction or
24
+ method-call time. Generated methods are real Python functions built from
25
+ source text via `exec()` and attached directly to the class — never
26
+ `__getattr__`/`__getattribute__` overrides, proxies, descriptors, or
27
+ monkeypatching after class creation.
28
+
29
+ Two sanctioned mutation points, and only two:
30
+ - `src/inito/utils/codegen.py` (`build_function`) — the only `exec()` call site.
31
+ - `src/inito/core/attach.py` (`attach_method` / `attach_capability`) — the
32
+ only place a class is mutated after code generation.
33
+
34
+ ## Naming convention
35
+
36
+ - Canonical decorator names are PascalCase, matching Lombok and `inito.md`'s
37
+ Initial Features list: `Data`, `Getter`, `Setter`, `Builder`, `ToString`,
38
+ `EqualsAndHashCode`, `NoArgsConstructor`, `AllArgsConstructor`,
39
+ `RequiredArgsConstructor`.
40
+ - Each is built by `make_decorator` (a factory function, not a class) so it
41
+ supports both `@Data` and `@Data(frozen=True)`.
42
+ - Lowercase aliases are exported bound to the same object (`data = Data`,
43
+ `builder = Builder`, ...) to satisfy the `from inito import builder`
44
+ examples from the spec, while keeping one canonical name.
45
+ - Internal generator classes always use the `*Generator` suffix
46
+ (`ConstructorGenerator`, `ReprGenerator`, ...) and are never exported at the
47
+ top level.
48
+
49
+ ## Architecture map
50
+
51
+ - `decorators/` — public decorators (`@Data`, ...); each is a thin
52
+ ~10–35 line module wiring generators together via `make_decorator`.
53
+ - `generators/` — one atomic capability per generator (`constructor`, `repr`,
54
+ `eq`+`hash`, `getter`+`setter`), registered under a capability name in
55
+ `generators/registry.py`.
56
+ - `builders/` — the `@Builder` generator (not yet implemented — see Phase 8).
57
+ - `reflection/` — low-level MRO/annotation-walking helpers used once by
58
+ `MetadataExtractor`.
59
+ - `typing/` — reserved for Protocol/generic typing support (currently empty).
60
+ - `metadata/` — `FieldMetadata`/`ClassMetadata` value types and
61
+ `MetadataExtractor`, which builds and caches metadata once per class.
62
+ - `utils/` — `codegen.build_function` and
63
+ `decorator_factory.make_decorator`, the two cross-cutting utilities every
64
+ decorator/generator depends on.
65
+ - `core/` — `attach.py`, the sole class-mutation choke point.
66
+ - `exceptions/` — the `InitoError` hierarchy.
67
+
68
+ **How to add a new decorator:** implement a generator (matching the
69
+ `MethodGenerator` or `MultiMethodGenerator` protocol in `generators/base.py`),
70
+ register it under a new capability name in `generators/__init__.py`, then
71
+ write a small decorator module that resolves that capability via
72
+ `core.attach.attach_capability` and wraps it with `make_decorator`. Never
73
+ modify an existing generator to add a new decorator.
74
+
75
+ ## Commands
76
+
77
+ ```bash
78
+ uv pip install -e ".[dev]" # or: pip install -e ".[dev]"
79
+ pytest # run tests + coverage
80
+ pytest tests/decorators/test_data.py -v # run a single test file
81
+ pytest --cov-report=html # generate an HTML coverage report
82
+ ruff check . # lint
83
+ ruff format . # format
84
+ ruff format --check . # format check (CI mode)
85
+ mypy src # typecheck
86
+ uv build # build sdist + wheel
87
+ ./scripts/check_all.sh # run all of the above
88
+ pytest benchmarks/ --benchmark-only # run the pytest-benchmark suite
89
+ python benchmarks/pyperf_suite.py # process-isolated pyperf construction comparison
90
+ python benchmarks/memory_profile.py # per-instance memory footprint comparison
91
+ python benchmarks/import_time.py # cold-import overhead comparison
92
+ sphinx-build -b html docs docs/_build -W # build docs, warnings-as-errors
93
+ ```
94
+
95
+ ## Testing conventions
96
+
97
+ `tests/` mirrors `src/inito/`'s package structure. Test files are named
98
+ `test_<module>.py`. Prefer shared fixtures in `conftest.py` over redefining
99
+ sample classes per test file (DRY).
100
+
101
+ ## Progress tracking
102
+
103
+ `TASKS.md` is the single source of truth for what's implemented versus
104
+ planned across sessions. Always update its checkboxes as work completes —
105
+ a future session should be able to resume by finding the first unchecked box.
@@ -0,0 +1,64 @@
1
+ # Contributing
2
+
3
+ ## Setup
4
+
5
+ ```bash
6
+ uv pip install -e ".[dev]"
7
+ # or: pip install -e ".[dev]"
8
+ pre-commit install
9
+ ```
10
+
11
+ ## Workflow
12
+
13
+ ```bash
14
+ ruff check . # lint
15
+ ruff format . # format
16
+ mypy src # typecheck
17
+ pytest # test + coverage
18
+ ./scripts/check_all.sh # all of the above
19
+ sphinx-build -b html docs docs/_build -W # build docs, warnings-as-errors
20
+ ```
21
+
22
+ ## Standards
23
+
24
+ Follow `local_dev/engineering.md`'s SOLID/DRY/cognitive-complexity/error-handling
25
+ rules and `local_dev/inito.md`'s performance rules (reflection only at
26
+ decoration time, generated methods attached once, zero runtime dependencies).
27
+ See [CLAUDE.md](./CLAUDE.md) for the architecture map and naming conventions.
28
+
29
+ ## Progress tracking
30
+
31
+ [TASKS.md](./TASKS.md) is the single source of truth for what's implemented
32
+ versus planned. Update its checkboxes as work lands.
33
+
34
+ ## Versioning
35
+
36
+ Semantic versioning. Version is single-sourced from `src/inito/__init__.py`'s
37
+ `__version__` — hatchling reads it via a regex, so bumping it there is the
38
+ only place that needs to change.
39
+
40
+ ## Release process
41
+
42
+ 1. Bump `__version__` in `src/inito/__init__.py`, following semver.
43
+ 2. Update `CHANGELOG.md`: move the `[Unreleased]` entries under a new
44
+ `[X.Y.Z] - YYYY-MM-DD` heading.
45
+ 3. Commit, then tag: `git tag vX.Y.Z && git push origin vX.Y.Z`.
46
+ 4. Pushing a `v*` tag triggers `.github/workflows/release.yml`, which builds
47
+ the sdist/wheel, runs `twine check`, and publishes to PyPI via trusted
48
+ publishing (OIDC) — no API token needed in CI.
49
+
50
+ **One-time setup required before the first release** (not something CI or
51
+ this repo's config can do on its own):
52
+
53
+ - On [PyPI](https://pypi.org/manage/account/publishing/), register a
54
+ "trusted publisher" for the `inito` project pointing at this repo, the
55
+ `release.yml` workflow filename, and a `pypi` environment name (this can
56
+ be done *before* the first release — PyPI supports pending publishers for
57
+ projects that don't exist yet).
58
+ - In the GitHub repo settings, create an environment named `pypi` (matches
59
+ `release.yml`'s `environment: name: pypi`) — optionally with protection
60
+ rules (e.g. required reviewers) before it can publish.
61
+
62
+ Without that one-time PyPI-side setup, `release.yml`'s publish job will
63
+ fail with an OIDC/trusted-publisher authentication error — that's expected
64
+ until the trusted publisher is registered.
inito-0.0.1b0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Swetank Subham
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.
inito-0.0.1b0/PKG-INFO ADDED
@@ -0,0 +1,161 @@
1
+ Metadata-Version: 2.4
2
+ Name: inito
3
+ Version: 0.0.1b0
4
+ Summary: A Lombok-inspired boilerplate-elimination library for Python.
5
+ Project-URL: Homepage, https://github.com/swtnk/inito
6
+ Project-URL: Repository, https://github.com/swtnk/inito
7
+ Project-URL: Documentation, https://github.com/swtnk/inito#readme
8
+ Project-URL: Changelog, https://github.com/swtnk/inito/blob/main/CHANGELOG.md
9
+ Project-URL: Issues, https://github.com/swtnk/inito/issues
10
+ Author-email: Swetank Subham <swetanksubham.r@gmail.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: boilerplate,builder,codegen,dataclass,lombok
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.9
27
+ Provides-Extra: dev
28
+ Requires-Dist: attrs>=23; extra == 'dev'
29
+ Requires-Dist: furo>=2024.1; extra == 'dev'
30
+ Requires-Dist: mypy<2,>=1.11; extra == 'dev'
31
+ Requires-Dist: myst-parser>=3; extra == 'dev'
32
+ Requires-Dist: pre-commit>=3.7; extra == 'dev'
33
+ Requires-Dist: pyperf>=2.6; extra == 'dev'
34
+ Requires-Dist: pytest-benchmark>=4; extra == 'dev'
35
+ Requires-Dist: pytest-cov>=5; extra == 'dev'
36
+ Requires-Dist: pytest>=8; extra == 'dev'
37
+ Requires-Dist: ruff>=0.6; extra == 'dev'
38
+ Requires-Dist: sphinx>=7; extra == 'dev'
39
+ Description-Content-Type: text/markdown
40
+
41
+ # inito
42
+
43
+ A Lombok-inspired boilerplate-elimination library for Python. `inito`
44
+ generates constructors, `repr`, equality/hashing, accessors, and fluent
45
+ builders once at class-decoration time — never at instance construction or
46
+ attribute-access time — so the generated classes perform like handwritten
47
+ ones. Zero runtime dependencies.
48
+
49
+ ## Install
50
+
51
+ ```bash
52
+ pip install inito
53
+ ```
54
+
55
+ or
56
+
57
+ ```bash
58
+ uv add inito
59
+ ```
60
+
61
+ ## Quick start
62
+
63
+ ```python
64
+ from inito import Data
65
+
66
+
67
+ @Data
68
+ class User:
69
+ name: str
70
+ age: int = 0
71
+
72
+
73
+ user = User("Ada", age=30)
74
+ print(user) # User(name='Ada', age=30)
75
+ print(user.get_name()) # Ada
76
+ user.set_age(31)
77
+ ```
78
+
79
+ `@Data` also accepts options:
80
+
81
+ ```python
82
+ from inito import Data
83
+
84
+
85
+ @Data(frozen=True)
86
+ class Point:
87
+ x: int
88
+ y: int
89
+ ```
90
+
91
+ `@builder` generates a fluent, chainable builder, and composes with
92
+ `@dataclass`:
93
+
94
+ ```python
95
+ from dataclasses import dataclass
96
+ from inito import builder
97
+
98
+
99
+ @builder(to_builder=True)
100
+ @dataclass
101
+ class Request:
102
+ prompt: str
103
+ temperature: float = 0.7
104
+
105
+
106
+ request = Request.builder().prompt("hello").build()
107
+ revised = request.to_builder().temperature(0.9).build()
108
+ ```
109
+
110
+ ## Status
111
+
112
+ Implemented today: `@Data` (constructor, `__repr__`, `__eq__`, `__hash__`,
113
+ getters, setters), `@Getter` (getters only), `@Setter` (setters only),
114
+ `@NoArgsConstructor` (no-argument constructor using field defaults),
115
+ `@AllArgsConstructor` (constructor only, every field),
116
+ `@RequiredArgsConstructor` (constructor only accepting required fields),
117
+ `@Builder`/`builder` (fluent builder, `to_builder=True` support),
118
+ `@ToString` (`__repr__` only — pairs well with `@Builder` for a readable
119
+ repr without pulling in `@Data`'s constructor/eq/hash/accessors), and
120
+ `@EqualsAndHashCode` (`__eq__`/`__hash__` only).
121
+
122
+ All of `inito.md`'s Initial Features (v1) are now implemented. See
123
+ [docs/performance.md](./docs/performance.md) for benchmarks against
124
+ handwritten classes, `dataclasses`, and `attrs`. See [TASKS.md](./TASKS.md)
125
+ for what's left: docs, CI hardening, and release.
126
+
127
+ ### Known limitation: static type checkers don't see generated members yet
128
+
129
+ Every generated member (`get_x`, `set_x`, `.builder()`, `.to_builder()`, the
130
+ generated constructor's parameters, ...) is attached to your class via
131
+ `setattr` at decoration time — real attributes at runtime, but invisible to
132
+ `mypy`/`pyright` today, since neither tool has a plugin for inito yet. Your
133
+ code will run correctly; `mypy --strict`/`pyright` will flag those accesses
134
+ as unknown attributes in the meantime. `attrs` and Pydantic hit the same
135
+ problem and solved it with dedicated mypy plugins — that's tracked as a
136
+ future initiative (see `TASKS.md` Phase 17), not required for this release.
137
+
138
+ ### Known limitations: frozen dataclasses and self-referential fields
139
+
140
+ Stacking any inito constructor-generating decorator (`@Data`, `@Builder`,
141
+ `@AllArgsConstructor`, ...) with `@dataclass(frozen=True)` — in either
142
+ order — raises `dataclasses.FrozenInstanceError`. This is expected, not a
143
+ bug: the generated `__init__`/`build()` assign fields with plain
144
+ `self.x = value`, which correctly respects the frozen class's blocking
145
+ `__setattr__` rather than silently bypassing the immutability you asked
146
+ for. If you want inito's own frozen-style behavior, use `@Data(frozen=True)`
147
+ (which just omits setters) instead of also stacking `@dataclass(frozen=True)`.
148
+
149
+ Self-referential type hints (e.g. a linked-list `next: Node`) also aren't
150
+ supported: inito resolves annotations eagerly, once, at decoration time —
151
+ before the class's own name is bound in its module's globals — so a forward
152
+ reference to the class currently being decorated can't resolve. Forward
153
+ references to any other, already-defined class work normally.
154
+
155
+ ## Contributing
156
+
157
+ See [CONTRIBUTING.md](./CONTRIBUTING.md).
158
+
159
+ ## License
160
+
161
+ MIT — see [LICENSE](./LICENSE).
@@ -0,0 +1,121 @@
1
+ # inito
2
+
3
+ A Lombok-inspired boilerplate-elimination library for Python. `inito`
4
+ generates constructors, `repr`, equality/hashing, accessors, and fluent
5
+ builders once at class-decoration time — never at instance construction or
6
+ attribute-access time — so the generated classes perform like handwritten
7
+ ones. Zero runtime dependencies.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pip install inito
13
+ ```
14
+
15
+ or
16
+
17
+ ```bash
18
+ uv add inito
19
+ ```
20
+
21
+ ## Quick start
22
+
23
+ ```python
24
+ from inito import Data
25
+
26
+
27
+ @Data
28
+ class User:
29
+ name: str
30
+ age: int = 0
31
+
32
+
33
+ user = User("Ada", age=30)
34
+ print(user) # User(name='Ada', age=30)
35
+ print(user.get_name()) # Ada
36
+ user.set_age(31)
37
+ ```
38
+
39
+ `@Data` also accepts options:
40
+
41
+ ```python
42
+ from inito import Data
43
+
44
+
45
+ @Data(frozen=True)
46
+ class Point:
47
+ x: int
48
+ y: int
49
+ ```
50
+
51
+ `@builder` generates a fluent, chainable builder, and composes with
52
+ `@dataclass`:
53
+
54
+ ```python
55
+ from dataclasses import dataclass
56
+ from inito import builder
57
+
58
+
59
+ @builder(to_builder=True)
60
+ @dataclass
61
+ class Request:
62
+ prompt: str
63
+ temperature: float = 0.7
64
+
65
+
66
+ request = Request.builder().prompt("hello").build()
67
+ revised = request.to_builder().temperature(0.9).build()
68
+ ```
69
+
70
+ ## Status
71
+
72
+ Implemented today: `@Data` (constructor, `__repr__`, `__eq__`, `__hash__`,
73
+ getters, setters), `@Getter` (getters only), `@Setter` (setters only),
74
+ `@NoArgsConstructor` (no-argument constructor using field defaults),
75
+ `@AllArgsConstructor` (constructor only, every field),
76
+ `@RequiredArgsConstructor` (constructor only accepting required fields),
77
+ `@Builder`/`builder` (fluent builder, `to_builder=True` support),
78
+ `@ToString` (`__repr__` only — pairs well with `@Builder` for a readable
79
+ repr without pulling in `@Data`'s constructor/eq/hash/accessors), and
80
+ `@EqualsAndHashCode` (`__eq__`/`__hash__` only).
81
+
82
+ All of `inito.md`'s Initial Features (v1) are now implemented. See
83
+ [docs/performance.md](./docs/performance.md) for benchmarks against
84
+ handwritten classes, `dataclasses`, and `attrs`. See [TASKS.md](./TASKS.md)
85
+ for what's left: docs, CI hardening, and release.
86
+
87
+ ### Known limitation: static type checkers don't see generated members yet
88
+
89
+ Every generated member (`get_x`, `set_x`, `.builder()`, `.to_builder()`, the
90
+ generated constructor's parameters, ...) is attached to your class via
91
+ `setattr` at decoration time — real attributes at runtime, but invisible to
92
+ `mypy`/`pyright` today, since neither tool has a plugin for inito yet. Your
93
+ code will run correctly; `mypy --strict`/`pyright` will flag those accesses
94
+ as unknown attributes in the meantime. `attrs` and Pydantic hit the same
95
+ problem and solved it with dedicated mypy plugins — that's tracked as a
96
+ future initiative (see `TASKS.md` Phase 17), not required for this release.
97
+
98
+ ### Known limitations: frozen dataclasses and self-referential fields
99
+
100
+ Stacking any inito constructor-generating decorator (`@Data`, `@Builder`,
101
+ `@AllArgsConstructor`, ...) with `@dataclass(frozen=True)` — in either
102
+ order — raises `dataclasses.FrozenInstanceError`. This is expected, not a
103
+ bug: the generated `__init__`/`build()` assign fields with plain
104
+ `self.x = value`, which correctly respects the frozen class's blocking
105
+ `__setattr__` rather than silently bypassing the immutability you asked
106
+ for. If you want inito's own frozen-style behavior, use `@Data(frozen=True)`
107
+ (which just omits setters) instead of also stacking `@dataclass(frozen=True)`.
108
+
109
+ Self-referential type hints (e.g. a linked-list `next: Node`) also aren't
110
+ supported: inito resolves annotations eagerly, once, at decoration time —
111
+ before the class's own name is bound in its module's globals — so a forward
112
+ reference to the class currently being decorated can't resolve. Forward
113
+ references to any other, already-defined class work normally.
114
+
115
+ ## Contributing
116
+
117
+ See [CONTRIBUTING.md](./CONTRIBUTING.md).
118
+
119
+ ## License
120
+
121
+ MIT — see [LICENSE](./LICENSE).