splatfold 0.2.0__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.
- splatfold-0.2.0/CHANGELOG.md +70 -0
- splatfold-0.2.0/CONTRIBUTING.md +32 -0
- splatfold-0.2.0/DESIGN.md +58 -0
- splatfold-0.2.0/LICENSE +21 -0
- splatfold-0.2.0/MANIFEST.in +9 -0
- splatfold-0.2.0/MIGRATING.md +66 -0
- splatfold-0.2.0/PKG-INFO +1911 -0
- splatfold-0.2.0/RELEASING.md +31 -0
- splatfold-0.2.0/SECURITY.md +27 -0
- splatfold-0.2.0/pyproject.toml +85 -0
- splatfold-0.2.0/readme.md +1869 -0
- splatfold-0.2.0/setup.cfg +4 -0
- splatfold-0.2.0/splatfold.egg-info/PKG-INFO +1911 -0
- splatfold-0.2.0/splatfold.egg-info/SOURCES.txt +18 -0
- splatfold-0.2.0/splatfold.egg-info/dependency_links.txt +1 -0
- splatfold-0.2.0/splatfold.egg-info/entry_points.txt +2 -0
- splatfold-0.2.0/splatfold.egg-info/requires.txt +16 -0
- splatfold-0.2.0/splatfold.egg-info/top_level.txt +1 -0
- splatfold-0.2.0/splatfold.py +1035 -0
- splatfold-0.2.0/tests/test_splatfold.py +605 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Splatfold will be documented here.
|
|
4
|
+
|
|
5
|
+
The project follows Semantic Versioning once its public API is released.
|
|
6
|
+
|
|
7
|
+
## Unreleased
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Renamed the project from Obtuse/preprocessor to Splatfold.
|
|
12
|
+
- Added a side-effect-free Python build API and `BuildResult.write()`.
|
|
13
|
+
- Added conventional `__version__` metadata and explicit public exports.
|
|
14
|
+
- Added positional CLI input while retaining `-i` and `--input`.
|
|
15
|
+
- Matched Python's package-before-module import resolution precedence.
|
|
16
|
+
- Kept output writing compatible with Python 3.9.
|
|
17
|
+
- Made output replacement atomic, synchronized file contents before replacement,
|
|
18
|
+
and preserved existing or input-file permissions.
|
|
19
|
+
- Added Python 3.9-3.14 CI, 90% branch-coverage enforcement, distribution package
|
|
20
|
+
checks, and a Trusted Publishing release workflow with commit-pinned actions.
|
|
21
|
+
- Added focused macOS and Windows CI jobs to verify the package's
|
|
22
|
+
operating-system-independent claim.
|
|
23
|
+
- Added Dependabot maintenance for Python tooling and GitHub Actions.
|
|
24
|
+
- Made the wheel smoke test install outside the source checkout so local build
|
|
25
|
+
metadata cannot masquerade as an installed distribution.
|
|
26
|
+
- Added release-tag/version validation, serialized publishing, artifact
|
|
27
|
+
presence checks, and an isolated smoke test of the exact release wheel.
|
|
28
|
+
- The release workflow now reruns lint, formatting, tests, and branch coverage
|
|
29
|
+
against the exact release commit before building publishable artifacts.
|
|
30
|
+
- Checkout credentials are not persisted into CI or release workspaces; the
|
|
31
|
+
workflows pass a dedicated GitHub Actions security audit.
|
|
32
|
+
- Added a required CI job that continuously enforces the GitHub Actions
|
|
33
|
+
security audit instead of relying only on manual release review.
|
|
34
|
+
- Documented the Python API result contract, exception hierarchy, filesystem
|
|
35
|
+
mutation boundary, CLI streams, and exit statuses.
|
|
36
|
+
- Added strict static type checking for the standalone implementation to local,
|
|
37
|
+
CI, and release quality gates, using the newest mypy line that still models
|
|
38
|
+
the supported Python 3.9 syntax target.
|
|
39
|
+
- Added full `pyproject.toml` schema, dependency-version, and SPDX license
|
|
40
|
+
validation to package and release gates.
|
|
41
|
+
- Added wheel-layout validation to local, CI, and release gates.
|
|
42
|
+
- Added an Obtuse-to-Splatfold migration guide covering compatible commands,
|
|
43
|
+
renamed surfaces, corrected prototype behavior, and the new release model.
|
|
44
|
+
- Defined the supported security release line and explicitly retired copied
|
|
45
|
+
Obtuse/preprocessor scripts from security support.
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
|
|
49
|
+
- Dependency `__main__` guards with `else` clauses now fail safely instead of
|
|
50
|
+
silently discarding code that normal imports would execute.
|
|
51
|
+
- Encoding-cookie removal no longer mistakes ordinary first-line source text
|
|
52
|
+
containing `coding:` for a declaration.
|
|
53
|
+
- Standalone `BuildResult` values now use safe default permissions when no
|
|
54
|
+
included source path is available.
|
|
55
|
+
- Rewritten wildcard and future imports now reject physical lines shared with
|
|
56
|
+
other statements instead of silently discarding neighboring code.
|
|
57
|
+
- Future-import hoisting now rejects root docstrings that share their final
|
|
58
|
+
physical line with another statement.
|
|
59
|
+
- Included files without a final newline no longer join their last statement
|
|
60
|
+
to the importing file's following source line.
|
|
61
|
+
- Indented comments beginning with `#!` are preserved instead of being
|
|
62
|
+
mistaken for executable shebang lines.
|
|
63
|
+
- Future features are deduplicated individually even when source files group
|
|
64
|
+
them into different multi-feature import statements.
|
|
65
|
+
- User-path expansion and resolution failures now use the stable public error
|
|
66
|
+
hierarchy instead of leaking raw filesystem exceptions.
|
|
67
|
+
- `BuildResult.write()` now revalidates its current source immediately before
|
|
68
|
+
filesystem mutation, including for directly constructed or modified results.
|
|
69
|
+
- Output protection now detects existing filesystem aliases of included source
|
|
70
|
+
files instead of relying only on textual path equality.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Splatfold keeps its complete runtime implementation in `splatfold.py` so the
|
|
4
|
+
tool itself remains easy to copy and run as one file. Tests, documentation,
|
|
5
|
+
packaging metadata, and automation live beside it.
|
|
6
|
+
|
|
7
|
+
## Development checks
|
|
8
|
+
|
|
9
|
+
From this directory, run:
|
|
10
|
+
|
|
11
|
+
```zsh
|
|
12
|
+
python3 -m pip install -e ".[dev,release]"
|
|
13
|
+
ruff check splatfold.py tests
|
|
14
|
+
ruff format --check splatfold.py tests
|
|
15
|
+
mypy splatfold.py
|
|
16
|
+
python3 -m coverage run -m pytest
|
|
17
|
+
python3 -m coverage report
|
|
18
|
+
uvx zizmor .github/workflows
|
|
19
|
+
python3 -m compileall -q splatfold.py
|
|
20
|
+
validate-pyproject pyproject.toml
|
|
21
|
+
python3 -m build
|
|
22
|
+
python3 -m twine check dist/*
|
|
23
|
+
check-wheel-contents dist/*.whl
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Changes to resolution or rendering semantics must include a focused regression
|
|
27
|
+
test. Tests should compare generated behavior with normal Python behavior when
|
|
28
|
+
Splatfold claims equivalence, and should make intentional differences explicit.
|
|
29
|
+
|
|
30
|
+
Before a release, install the built wheel into a clean virtual environment and
|
|
31
|
+
use that installed CLI—not the source checkout—to fold and run the Acute
|
|
32
|
+
integration fixture.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Splatfold design contract
|
|
2
|
+
|
|
3
|
+
Splatfold is a source preprocessor, not an import-system emulator. It gives a
|
|
4
|
+
restricted set of valid Python wildcard imports an additional build-time
|
|
5
|
+
meaning: include the referenced local source once at the import location.
|
|
6
|
+
|
|
7
|
+
## Invariants
|
|
8
|
+
|
|
9
|
+
1. Development sources remain valid Python and continue to work without
|
|
10
|
+
Splatfold when their ordinary imports are valid.
|
|
11
|
+
2. Project source is read and parsed, never imported or executed during a
|
|
12
|
+
build.
|
|
13
|
+
3. Only module-level `from ... import *` statements are candidates for local
|
|
14
|
+
inclusion. Every other import is preserved.
|
|
15
|
+
4. A source file is emitted at most once. Active recursion edges are reported
|
|
16
|
+
as cycles and omitted from the generated module.
|
|
17
|
+
5. The generated source is UTF-8 and is compiled for syntax validity both when
|
|
18
|
+
built and immediately before it can be written.
|
|
19
|
+
6. Writing is explicit in the Python API and atomic with respect to the final
|
|
20
|
+
destination path.
|
|
21
|
+
7. The input and every included source path are protected from accidental
|
|
22
|
+
output overwrite, including filesystem aliases of the same file.
|
|
23
|
+
8. The implementation remains a standalone standard-library-only Python file.
|
|
24
|
+
|
|
25
|
+
## Resolution
|
|
26
|
+
|
|
27
|
+
Absolute imports are searched in `root` followed by each configured search
|
|
28
|
+
path. Relative imports are resolved from the importing file. On each path
|
|
29
|
+
entry, `name/__init__.py` takes precedence over `name.py`, matching Python.
|
|
30
|
+
|
|
31
|
+
An unresolved wildcard import is preserved by default because it may refer to
|
|
32
|
+
the standard library or an installed dependency. Strict mode rejects it.
|
|
33
|
+
|
|
34
|
+
## Rendering
|
|
35
|
+
|
|
36
|
+
Inclusion is depth-first at the original import location. Dependency shebangs
|
|
37
|
+
and encoding cookies are removed. The root shebang is retained and the output
|
|
38
|
+
declares UTF-8. Future imports are deduplicated and hoisted after the root
|
|
39
|
+
module docstring.
|
|
40
|
+
|
|
41
|
+
Conventional dependency `if __name__ == "__main__":` blocks without `else`
|
|
42
|
+
are removed by default. A guard with `else` is rejected because deleting the
|
|
43
|
+
whole statement would discard code that normal importing executes.
|
|
44
|
+
|
|
45
|
+
Statements that Splatfold removes or replaces must occupy their own physical
|
|
46
|
+
lines. A trailing comment is allowed. Sharing such a line with another Python
|
|
47
|
+
statement is rejected explicitly rather than risking silent loss of code.
|
|
48
|
+
|
|
49
|
+
## Intentional limits
|
|
50
|
+
|
|
51
|
+
All included definitions share one global namespace. Per-module values of
|
|
52
|
+
`__name__`, `__package__`, `__file__`, module dictionaries, `sys.modules`
|
|
53
|
+
entries, import hooks, and initialization isolation are not reproduced.
|
|
54
|
+
`__all__` remains ordinary source metadata but does not hide code that has been
|
|
55
|
+
physically included.
|
|
56
|
+
|
|
57
|
+
These limits are fundamental to source folding and must remain visible in user
|
|
58
|
+
documentation and tests.
|
splatfold-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 WithoutSophie
|
|
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.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Migrating from Obtuse
|
|
2
|
+
|
|
3
|
+
Splatfold is the production continuation of the project previously published
|
|
4
|
+
on GitHub as **Obtuse**. It keeps the wildcard-include model while replacing
|
|
5
|
+
the prototype's script-only release process with a tested Python distribution.
|
|
6
|
+
|
|
7
|
+
## Source compatibility
|
|
8
|
+
|
|
9
|
+
Existing module-level directives remain valid:
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
from module import *
|
|
13
|
+
from package.module import *
|
|
14
|
+
from .local import *
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The original `-i` and `--input` CLI forms remain supported, along with the
|
|
18
|
+
output, root, search-path, strictness, marker, tracing, dependency-listing, and
|
|
19
|
+
check-only behavior. The preferred form now uses a positional input:
|
|
20
|
+
|
|
21
|
+
```zsh
|
|
22
|
+
splatfold main.py -o dist/app.py
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Names that changed
|
|
26
|
+
|
|
27
|
+
- The command and standalone implementation are now named `splatfold` and
|
|
28
|
+
`splatfold.py`; no `preprocessor` or `obtuse` package is installed.
|
|
29
|
+
- Generated comments identify `splatfold` instead of the prototype script.
|
|
30
|
+
- The importable API is `splatfold.build(...)`, returning a `BuildResult` whose
|
|
31
|
+
`write()` method performs the explicit filesystem mutation.
|
|
32
|
+
|
|
33
|
+
Code that invokes an old checkout as `python3 preprocessor.py ...` should
|
|
34
|
+
install Splatfold and invoke the `splatfold` console command instead. Existing
|
|
35
|
+
automation may keep `-i/--input` while migrating.
|
|
36
|
+
|
|
37
|
+
## Intentional safety changes
|
|
38
|
+
|
|
39
|
+
Several prototype behaviors were bugs and are not preserved:
|
|
40
|
+
|
|
41
|
+
- When `name.py` and `name/__init__.py` coexist on one search entry, the
|
|
42
|
+
package now wins, matching Python's import system.
|
|
43
|
+
- A dependency `if __name__ == "__main__": ... else: ...` is rejected unless
|
|
44
|
+
`--keep-main-guards` is requested; the prototype silently discarded the
|
|
45
|
+
import-time `else` branch.
|
|
46
|
+
- Wildcard and future imports that share a physical line with another Python
|
|
47
|
+
statement are rejected instead of silently deleting neighboring code.
|
|
48
|
+
- Output writes work on Python 3.9, are atomic, preserve appropriate file
|
|
49
|
+
permissions, and refuse to overwrite any included source.
|
|
50
|
+
- Future features are deduplicated individually and included files missing a
|
|
51
|
+
final newline cannot merge with the importing file's next statement.
|
|
52
|
+
|
|
53
|
+
These changes favor explicit failure over generating code with altered
|
|
54
|
+
semantics. Projects relying on a rejected edge case should first rewrite the
|
|
55
|
+
source into ordinary multi-line Python; `--keep-main-guards` is available only
|
|
56
|
+
when literal guard inclusion is genuinely intended.
|
|
57
|
+
|
|
58
|
+
## Release and packaging changes
|
|
59
|
+
|
|
60
|
+
Splatfold requires Python 3.9 or newer and has no runtime dependencies outside
|
|
61
|
+
the standard library. Releases provide both a universal wheel and source
|
|
62
|
+
distribution. The version is available as `splatfold.__version__`, and the CLI
|
|
63
|
+
reports the same value with `splatfold --version`.
|
|
64
|
+
|
|
65
|
+
PyPI publication uses GitHub OIDC Trusted Publishing. The obsolete Obtuse
|
|
66
|
+
workflow and long-lived upload tokens must not be reused.
|