You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit cae8e93
Browse filesBrowse the repository at this point in the historyBrowse files
authored
Report the output path and sizes, and fail when no package is produced (#16)
* feat: write a JSON report of the output path and sizes
The resolved output path and the two size figures currently exist only
inside log lines, so a script that calls this tool cannot find out which
file was just written without re-deriving the distribution name itself or
scraping stdout.
Add an opt-in `--report <path>` flag that writes a single JSON object once
packaging has succeeded:
{
"output_file": "/abs/path/my_app.zip",
"distribution_name": "my_app",
"output_bytes": 3460000,
"uncompressed_bytes": 412000000,
"compressed_bytes": 3456789,
"nested_zip": false
}
`output_bytes` is the size of the file at `output_file`, so it is correct
under both strategies. `compressed_bytes` remains the size of the
dependencies zip, which is the figure compared against the Lambda limit;
under the nested strategy the outer zip is larger, because it also holds
the loader and the stored inner zip.
Writing to a file rather than stdout keeps the report immune to anything
else the tool prints, and leaves existing output untouched for callers
that do not pass the flag.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: raise PackageTooLargeError instead of exiting 0 with no package
When the uncompressed size exceeds the Lambda limit and the compressed
size does too, the nested-zip strategy cannot help. The tool printed a
placeholder message, wrote no file, and returned normally, so the process
exited 0.
Under `set -euo pipefail` that reads as success: the build goes green with
no zip on disk, and whatever consumes the artifact next fails somewhere
far from the cause.
Raise instead, carrying both sizes and the limit so the message says how
much too large the package is. The traceback goes to stderr and the
process exits non-zero.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: replace TODO placeholder exceptions with real messages
Two ordinary user mistakes surfaced as bare tracebacks that named neither
the problem nor the fix:
- a venv path with no `lib/python*` directory raised `Exception("input_path")`
- a pyproject.toml with no `[project].name` or `[tool.poetry].name`
raised `Exception("TODO Exception find_value")`
Both now say what was looked for and where, and use a fitting builtin
exception type.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: pass re.UNICODE as flags rather than count
`re.sub`'s fourth positional parameter is `count`, not `flags`, so
`re.sub("[^\w\d.]+", "_", self.name, re.UNICODE)` meant "replace at most 32
occurrences". Names with more than 32 runs of characters to replace were
normalised only partway.
`re.UNICODE` is already the default for str patterns in Python 3, so it can
go entirely. The pattern also becomes a raw string: as a plain string it
contains the undefined escapes `\w` and `\d`, which is a SyntaxWarning on
current Python and is slated to become an error.
Passing `count` positionally is deprecated as of 3.13, so this also removes
a DeprecationWarning from the test run.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix: validate SOURCE_DATE_EPOCH before packaging
`date_time()` runs once per file written, so a bad $SOURCE_DATE_EPOCH was
only noticed after the venv had been built and while the zip was being
produced. Call it once at startup so the failure lands before any work.
A non-integer value also gave a bare ValueError traceback while a pre-1980
value gave SourceDateEpochError. Both now raise SourceDateEpochError, and
the message quotes the offending value.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat: make --output and --output-dir mutually exclusive
Passing both was accepted, with --output silently winning. Put them in an
argparse mutually exclusive group so the conflict is reported instead.
The group is not required: --output-dir keeps its default of the current
working directory, so invocations that pass neither are unaffected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs: document --report and the output filename contract
Document the new --report flag and each field of the JSON it writes.
State the output filename rule as a contract: `<output-dir>/<distribution_name>.zip`,
where the name comes from `[project].name` or `[tool.poetry].name`, and
case is preserved. The README previously said only "with dashes replaced
with underscores", which is both incomplete (every run of characters
outside `A-Za-z0-9_.` is replaced) and silent on case, so `My-App` yielding
`My_App.zip` was left for callers to discover. That also differs from the
lowercased wheel filename for the same project, which is a tempting and
wrong way to predict it.
Also correct "One of the following must be specified" for `--output` /
`--output-dir`: neither is required, and they cannot now be combined.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Dmytro Hrimov <dmytrohrimov@Dmytros-MacBook-Pro.local>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
**Case is preserved.** A project named `My-App` produces `My_App.zip`, not `my_app.zip`. Note that this differs from the
51
+
wheel your build tool produces for the same project, whose filename is lowercased — so a wheel's name is not a safe way
52
+
to predict the name of this file.
53
+
54
+
## Report file
55
+
56
+
Pass `--report <path>` to have the tool write a JSON description of what it produced, so a calling script does not have
57
+
to re-derive the output path or re-measure the package.
58
+
59
+
```json
60
+
{
61
+
"output_file": "/abs/path/lambda/my_app.zip",
62
+
"distribution_name": "my_app",
63
+
"output_bytes": 3460000,
64
+
"uncompressed_bytes": 412000000,
65
+
"compressed_bytes": 3456789,
66
+
"nested_zip": false
67
+
}
68
+
```
69
+
70
+
| Field | Meaning |
71
+
| --- | --- |
72
+
|`output_file`| Absolute path of the zip that was written. |
73
+
|`distribution_name`| The normalized project name, as described in [Output file name](#output-file-name). |
74
+
|`output_bytes`| Size of the file at `output_file`. This is the artifact you deploy. |
75
+
|`uncompressed_bytes`| Total size of the packaged files before compression. This is the figure compared against the AWS Lambda 250 MiB unzipped limit. |
76
+
|`compressed_bytes`| Size of the dependencies zip. Equal to `output_bytes` unless the nested-zip strategy was used, in which case the outer zip also holds the loader. |
77
+
|`nested_zip`| Whether the nested-zip strategy was used. |
78
+
79
+
The report is written only when packaging succeeds, so its presence is a reliable signal that the zip is really there.
arg_parser.add_argument("venv_dir", type=str, help="The directory path to the virtual environment to package into a zip file")
24
31
arg_parser.add_argument("--project", type=str, default='pyproject.toml', help="The path to the project's pyproject.toml file. Omit to use pyproject.toml in the current working directory.")
25
-
arg_parser.add_argument("--output-dir", type=str, default='.', help="The directory path to save the output zip file. Default is the current working directory.")
26
-
arg_parser.add_argument("--output", type=str, default='', help="The full file path for the output file. Use this instead of --output-dir if you want total control of the output file path.")
output_group.add_argument("--output-dir", type=str, default='.', help="The directory path to save the output zip file. Default is the current working directory.")
34
+
output_group.add_argument("--output", type=str, default='', help="The full file path for the output file. Use this instead of --output-dir if you want total control of the output file path.")
35
+
arg_parser.add_argument("--report", type=str, default='', help="The file path to write a JSON report of the packaging result to. Omit to write no report.")
0 commit comments