emmykit 0.3.2__tar.gz → 0.4.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.
Files changed (56) hide show
  1. emmykit-0.4.0/CHANGELOG.md +164 -0
  2. {emmykit-0.3.2 → emmykit-0.4.0}/PKG-INFO +474 -844
  3. {emmykit-0.3.2 → emmykit-0.4.0}/README.md +472 -842
  4. {emmykit-0.3.2 → emmykit-0.4.0}/docs/design.md +3 -2
  5. {emmykit-0.3.2 → emmykit-0.4.0}/scripts/smoke_pypi.sh +15 -5
  6. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/__init__.py +7 -15
  7. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/_version.py +1 -1
  8. emmykit-0.4.0/src/emmykit/embedded_scripts.py +27 -0
  9. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/json_io.py +232 -1
  10. {emmykit-0.3.2 → emmykit-0.4.0}/tests/_baseline_signatures.json +11 -18
  11. emmykit-0.4.0/tests/test_json_registry.py +444 -0
  12. emmykit-0.4.0/tests/test_readme_generator.py +99 -0
  13. {emmykit-0.3.2 → emmykit-0.4.0}/tools/_layout.json +2 -2
  14. {emmykit-0.3.2 → emmykit-0.4.0}/tools/generate_readme.py +258 -14
  15. emmykit-0.3.2/CHANGELOG.md +0 -83
  16. emmykit-0.3.2/src/emmykit/embedded_scripts.py +0 -560
  17. emmykit-0.3.2/tests/test_readme_generator.py +0 -40
  18. {emmykit-0.3.2 → emmykit-0.4.0}/.gitignore +0 -0
  19. {emmykit-0.3.2 → emmykit-0.4.0}/LICENSE +0 -0
  20. {emmykit-0.3.2 → emmykit-0.4.0}/pyproject.toml +0 -0
  21. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/constants.py +0 -0
  22. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/datetime_utils.py +0 -0
  23. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/diff_view.py +0 -0
  24. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/docker_utils.py +0 -0
  25. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/extensions.py +0 -0
  26. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/file_io.py +0 -0
  27. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/files.py +0 -0
  28. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/hosts.py +0 -0
  29. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/html_files.py +0 -0
  30. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/humanize.py +0 -0
  31. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/inflect_utils.py +0 -0
  32. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/introspection.py +0 -0
  33. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/io_subprocess.py +0 -0
  34. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/lint.py +0 -0
  35. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/llm.py +0 -0
  36. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/logging_utils.py +0 -0
  37. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/media.py +0 -0
  38. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/net_targets.py +0 -0
  39. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/network.py +0 -0
  40. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/numeric_helpers.py +0 -0
  41. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/options.py +0 -0
  42. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/paths_ensure.py +0 -0
  43. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/prompts.py +0 -0
  44. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/py.typed +0 -0
  45. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/python_env.py +0 -0
  46. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/safe_paths.py +0 -0
  47. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/system.py +0 -0
  48. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/text.py +0 -0
  49. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/text_constants.py +0 -0
  50. {emmykit-0.3.2 → emmykit-0.4.0}/src/emmykit/treeview.py +0 -0
  51. {emmykit-0.3.2 → emmykit-0.4.0}/tests/__init__.py +0 -0
  52. {emmykit-0.3.2 → emmykit-0.4.0}/tests/_baseline_pure_helpers.json +0 -0
  53. {emmykit-0.3.2 → emmykit-0.4.0}/tests/test_public_api.py +0 -0
  54. {emmykit-0.3.2 → emmykit-0.4.0}/tests/test_pure_helpers.py +0 -0
  55. {emmykit-0.3.2 → emmykit-0.4.0}/tools/__init__.py +0 -0
  56. {emmykit-0.3.2 → emmykit-0.4.0}/tools/extract_symbols.py +0 -0
@@ -0,0 +1,164 @@
1
+ # Changelog
2
+
3
+ All notable changes to `emmykit` are documented here. Format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning is
5
+ [SemVer](https://semver.org/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ### Planned for 0.5.0 (potential breaking changes)
10
+
11
+ - Drop the 24 stdlib re-exports (`os`, `sys`, `re`, `Path`, `chain`,
12
+ `Enum`, `dataclass`, `field`, `replace`, `annotations`, plus 11
13
+ `typing` names) from the public surface. They were preserved in 0.3.0
14
+ for byte-for-byte parity with the legacy `from univ_defs import *`
15
+ surface, but `import emmykit as ek` users will find `ek.os` /
16
+ `ek.sys` confusing. After that release, callers should import these
17
+ directly from the stdlib. (Deferred from 0.4.0.)
18
+
19
+ ## [0.4.0] - 2026-08-14
20
+
21
+ Adds a public extension point to the JSON round trip, and removes the
22
+ five embedded command-line programs plus the `sys.path` shim.
23
+
24
+ ### Added
25
+
26
+ - `register_json_type()` / `unregister_json_type()` in
27
+ `emmykit.json_io`, re-exported from the top-level namespace. A
28
+ consuming package can now teach `to_jsonable` / `from_jsonable` about
29
+ its own types without `emmykit` importing that package — the library
30
+ supplies the mechanism, the consumer supplies the knowledge. This also
31
+ reaches `save_options_to_json` / `load_options_from_json`, which call
32
+ the converters internally.
33
+
34
+ Previously an unrecognized object fell through to `str(obj)`. That
35
+ fails silently, not loudly: the reloaded file holds a repr string
36
+ where a lookup object should be, and membership tests degrade to
37
+ substring matching (`"ma" in restored` is `True` because the repr
38
+ happens to contain those letters). Nothing raises; the answers are
39
+ just wrong.
40
+
41
+ - Dispatch is by `isinstance`, so subclasses of a registered class are
42
+ handled. When two registrations match, the more specific class wins;
43
+ unrelated ties resolve to the most recently registered handler.
44
+ - A registered handler is consulted before every built-in encoder and
45
+ before the `str()` fallback.
46
+ - With `roundtrip=True` the result is `{"__type__": tag, **encode(obj)}`;
47
+ with `roundtrip=False` the bare payload is returned, untagged.
48
+ - The mapping returned by `encode` is itself passed back through the
49
+ converter, so it may contain `Path`, `set`, `datetime`, or another
50
+ registered type. The recursion guard stays in effect across that call.
51
+ - **Encode-only registration** — omitting *both* `tag` and `decode`
52
+ (supplying one without the other raises) serializes the object
53
+ through its encoder but never tags it, in either `roundtrip` mode, so
54
+ it reloads as a plain `dict`. This is a first-class mode, not an
55
+ oversight: some objects can be *described* faithfully but not
56
+ *rebuilt* faithfully, and a readable snapshot plus an honest `dict`
57
+ beats a decoder that fabricates a plausible-but-wrong object.
58
+ - Reusing a registered tag or class raises unless `replace=True`;
59
+ the built-in tags now exposed as `BUILTIN_JSON_TAGS` are rejected
60
+ outright.
61
+
62
+ - `BUILTIN_JSON_TAGS` — the frozenset of `__type__` tags owned by the
63
+ built-in encoders, so callers can see what a custom tag must avoid.
64
+
65
+ - `tests/test_json_registry.py` — 42 tests covering round trips, nesting
66
+ inside `dict`/`list`/`set`, `roundtrip=False`, encode-only mode,
67
+ subclass and specificity dispatch, duplicate/built-in tag rejection,
68
+ the recursion guard reached through a registered encoder, and
69
+ unregistration.
70
+
71
+ ### Removed (breaking)
72
+
73
+ - `PRINTALL_SCRIPT`, `MYDIFF_SCRIPT`, `MYAUDIT_SCRIPT`,
74
+ `MULTIREPLACE_SCRIPT`, and `TREEVIEW_SCRIPT` — the five standalone
75
+ command-line programs carried as string constants in
76
+ `emmykit.embedded_scripts`. They now live as real `.py` files in
77
+ [killett/utilities](https://github.com/killett/utilities), where they
78
+ can be linted, type-checked, tested and imported like ordinary code —
79
+ none of which is possible for a string constant inside the library
80
+ they import.
81
+ - `UNIV_DEFS_SYS_PATH_SCRIPT` — deleted outright, not moved. It existed
82
+ because `univ_defs.py` was a loose file that no `sys.path` entry
83
+ pointed at, so a standalone script could not import it. `emmykit` is
84
+ an installed package, so `import emmykit` already works anywhere the
85
+ package is installed; the shim solves a problem packaging has already
86
+ solved. It was also already broken: the constant pointed `sys.path` at
87
+ the *inner* `.../site-packages/emmykit` directory, which would expose
88
+ `json_io`, `constants` and friends as top-level modules and still
89
+ would not make `import emmykit` work.
90
+ - `SETUP_CARTOPY_SCRIPT` is unaffected and stays in
91
+ `emmykit.embedded_scripts`.
92
+
93
+ ### Changed
94
+
95
+ - Public surface: 208 → 205 names (six constants removed, three names
96
+ added).
97
+ - `tests/_baseline_signatures.json` updated to match. This is the first
98
+ deliberate divergence from the legacy `dir(univ_defs)` surface.
99
+
100
+ ## [0.3.0] - 2026-06-05
101
+
102
+ First public release. Splits the historical single-file `univ_defs.py`
103
+ module (9 922 LOC, 243 top-level symbols) into a 32-module layered
104
+ package.
105
+
106
+ ### Added
107
+
108
+ - `pyproject.toml` with hatchling build backend, Python ≥3.12,<3.14.
109
+ - `[project.optional-dependencies]` covering 22 lazily-imported
110
+ third-party packages, grouped into 8 domains (`datetime`, `text`,
111
+ `lint`, `llm`, `media`, `files`, `inflection`, `html`) plus an `all`
112
+ umbrella.
113
+ - Apache-2.0 LICENSE.
114
+ - 208-symbol `__all__` matching the legacy `dir(univ_defs)` surface.
115
+ - `tests/test_public_api.py` — pins the post-split surface against
116
+ `tests/_baseline_signatures.json` (name set, callable signatures,
117
+ submodule importability).
118
+ - `tests/test_pure_helpers.py` — parametrized byte-comparison of ~30
119
+ pre-recorded pure-helper outputs against `tests/_baseline_pure_helpers.json`.
120
+ - `tools/extract_symbols.py` — AST-based extractor used to produce
121
+ each module's source verbatim from `univ_defs.py`; handles decorators
122
+ and auto-emits `typing` / `collections.abc` imports.
123
+
124
+ ### Changed
125
+
126
+ - Package now exposes 32 submodules across 9 dependency layers:
127
+ - **L0**: `constants`, `extensions`, `net_targets`, `embedded_scripts`
128
+ - **L1**: `_version`, `paths_ensure`, `options`, `text_constants`,
129
+ `numeric_helpers`, `inflect_utils`, `logging_utils`
130
+ - **L2**: `safe_paths`, `file_io`
131
+ - **L3**: `io_subprocess`
132
+ - **L4**: `prompts`, `introspection`, `humanize`, `datetime_utils`,
133
+ `json_io`, `diff_view`
134
+ - **L5**: `text`, `hosts`, `network`, `python_env`, `files`
135
+ - **L6**: `lint`
136
+ - **L7**: `treeview`, `docker_utils`, `system`, `media`, `html_files`
137
+ - **L8**: `llm`
138
+ - `import emmykit` is side-effect-free; every third-party dep is
139
+ imported lazily inside the function that uses it.
140
+ - Module-level annotations now compile cleanly under
141
+ `typing.get_type_hints()` (Task-2 review caught missing `Final`/`Any`
142
+ imports masked by PEP 563).
143
+
144
+ ### Removed
145
+
146
+ - The flat `univ_defs.py` module (replaced by the layered package).
147
+
148
+ ### Migration
149
+
150
+ For consumers of the legacy `univ_defs.py`:
151
+
152
+ ```python
153
+ # before
154
+ import univ_defs
155
+ from univ_defs import parse_datetime, Options, LLMs
156
+
157
+ # after
158
+ import emmykit as ek
159
+ from emmykit import parse_datetime, Options, LLMs
160
+ ```
161
+
162
+ A single string replacement (`univ_defs` → `emmykit`) covers every
163
+ documented import path. Underscore-prefixed names are not part of the
164
+ public API and may break across releases.