netboot 0.2.1__tar.gz → 0.2.2__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 (67) hide show
  1. {netboot-0.2.1 → netboot-0.2.2}/CHANGELOG.md +25 -1
  2. {netboot-0.2.1 → netboot-0.2.2}/PKG-INFO +3 -3
  3. {netboot-0.2.1 → netboot-0.2.2}/pyproject.toml +8 -8
  4. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/AGENTS.md +14 -7
  5. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/utils/net.py +2 -2
  6. {netboot-0.2.1 → netboot-0.2.2}/tests/test_config_discovery.py +19 -0
  7. {netboot-0.2.1 → netboot-0.2.2}/.gitignore +0 -0
  8. {netboot-0.2.1 → netboot-0.2.2}/AGENTS.md +0 -0
  9. {netboot-0.2.1 → netboot-0.2.2}/LICENSE +0 -0
  10. {netboot-0.2.1 → netboot-0.2.2}/README.md +0 -0
  11. {netboot-0.2.1 → netboot-0.2.2}/benchmarks/README.md +0 -0
  12. {netboot-0.2.1 → netboot-0.2.2}/benchmarks/bench_netboot.py +0 -0
  13. {netboot-0.2.1 → netboot-0.2.2}/benchmarks/results/netboot.json +0 -0
  14. {netboot-0.2.1 → netboot-0.2.2}/docs/api.md +0 -0
  15. {netboot-0.2.1 → netboot-0.2.2}/docs/changelog.md +0 -0
  16. {netboot-0.2.1 → netboot-0.2.2}/docs/cli.md +0 -0
  17. {netboot-0.2.1 → netboot-0.2.2}/docs/configuration.md +0 -0
  18. {netboot-0.2.1 → netboot-0.2.2}/docs/extending.md +0 -0
  19. {netboot-0.2.1 → netboot-0.2.2}/docs/index.md +0 -0
  20. {netboot-0.2.1 → netboot-0.2.2}/examples/README.md +0 -0
  21. {netboot-0.2.1 → netboot-0.2.2}/examples/config/pixie.yaml +0 -0
  22. {netboot-0.2.1 → netboot-0.2.2}/examples/plugins/recording.py +0 -0
  23. {netboot-0.2.1 → netboot-0.2.2}/examples/templates/debian/boot.cfg +0 -0
  24. {netboot-0.2.1 → netboot-0.2.2}/examples/templates/debian/install.ks.j2 +0 -0
  25. {netboot-0.2.1 → netboot-0.2.2}/mkdocs.yml +0 -0
  26. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/__init__.py +0 -0
  27. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/__main__.py +0 -0
  28. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/_version.py +0 -0
  29. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/cmds/__init__.py +0 -0
  30. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/cmds/complete.py +0 -0
  31. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/cmds/initiate.py +0 -0
  32. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/content/__init__.py +0 -0
  33. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/dhcp/__init__.py +0 -0
  34. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/dhcp/dhcpd.py +0 -0
  35. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/dhcp/dnsmasq.py +0 -0
  36. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/dhcp/kea.py +0 -0
  37. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/dhcp/options.py +0 -0
  38. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/dhcp/windhcp.py +0 -0
  39. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/engine.py +0 -0
  40. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/logging.py +0 -0
  41. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/main.py +0 -0
  42. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/py.typed +0 -0
  43. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/templates/__init__.py +0 -0
  44. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/templates/common.py +0 -0
  45. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/templates/jinja.py +0 -0
  46. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/templates/shell.py +0 -0
  47. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/utils/__init__.py +0 -0
  48. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/utils/config.py +0 -0
  49. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/utils/dicts.py +0 -0
  50. {netboot-0.2.1 → netboot-0.2.2}/src/netboot/utils/misc.py +0 -0
  51. {netboot-0.2.1 → netboot-0.2.2}/tests/conftest.py +0 -0
  52. {netboot-0.2.1 → netboot-0.2.2}/tests/test_api_contracts.py +0 -0
  53. {netboot-0.2.1 → netboot-0.2.2}/tests/test_cli.py +0 -0
  54. {netboot-0.2.1 → netboot-0.2.2}/tests/test_cli_discovery.py +0 -0
  55. {netboot-0.2.1 → netboot-0.2.2}/tests/test_content.py +0 -0
  56. {netboot-0.2.1 → netboot-0.2.2}/tests/test_dhcp.py +0 -0
  57. {netboot-0.2.1 → netboot-0.2.2}/tests/test_dhcp_dhcpd.py +0 -0
  58. {netboot-0.2.1 → netboot-0.2.2}/tests/test_dhcp_dnsmasq.py +0 -0
  59. {netboot-0.2.1 → netboot-0.2.2}/tests/test_dhcp_kea.py +0 -0
  60. {netboot-0.2.1 → netboot-0.2.2}/tests/test_dhcp_options.py +0 -0
  61. {netboot-0.2.1 → netboot-0.2.2}/tests/test_dhcp_windhcp.py +0 -0
  62. {netboot-0.2.1 → netboot-0.2.2}/tests/test_engine_robustness.py +0 -0
  63. {netboot-0.2.1 → netboot-0.2.2}/tests/test_hooks.py +0 -0
  64. {netboot-0.2.1 → netboot-0.2.2}/tests/test_lookup.py +0 -0
  65. {netboot-0.2.1 → netboot-0.2.2}/tests/test_render.py +0 -0
  66. {netboot-0.2.1 → netboot-0.2.2}/tests/test_target.py +0 -0
  67. {netboot-0.2.1 → netboot-0.2.2}/tests/test_utils.py +0 -0
@@ -6,6 +6,29 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.2.2] - 2026-09-21
10
+
11
+ netboot moves to netimps 0.3.1 and yaconfiglib 0.13. If a plugin, hook or
12
+ template compares `target.mac` with text, read the `MACAddress` entry below.
13
+
14
+ ### Changed
15
+ - Dependencies move to their new series: `netimps>=0.3.1,<0.4` and
16
+ `yaconfiglib>=0.13.0,<0.14`. The old ceilings made netboot uninstallable
17
+ beside either release. netimps 0.3.0 is skipped on purpose: it raised from
18
+ `resolve()` when no resolver was reachable, which would have failed every
19
+ command at startup, and 0.3.1 answers `[]` again. netboot uses none of the
20
+ yaconfiglib APIs 0.13.0 removed.
21
+ - **`MACAddress` no longer equals a `str`** (netimps 0.3.0, re-exported as
22
+ `netboot.utils.net.MACAddress`). `target.mac == "aa:bb:cc:dd:ee:ff"` is now
23
+ `False` — in a plugin, a hook or a Jinja template alike. Compare with
24
+ `MACAddress.try_parse(text) == target.mac`. In exchange a MAC is found in a
25
+ set or dict whichever spelling built it. netboot's own target lookup already
26
+ compared parsed MACs and is unaffected. A MAC that mixes separators
27
+ (`00-11:22-33:44-55`) is now rejected, and `aa.bb.cc.dd.ee.ff` is accepted.
28
+ - `resolve()` keeps trying backends after an empty answer, so a hostname
29
+ target known only to the hosts file or NSS now gets its IP on Windows and
30
+ macOS. A name that exists nowhere costs two or three lookups instead of one.
31
+
9
32
  ## [0.2.1] - 2026-09-17
10
33
 
11
34
  netboot ships DHCP backends. Additive: nothing documented changed behaviour,
@@ -520,7 +543,8 @@ First packaged release: the `netboot` library with the `pixie` command line.
520
543
  config value construction no longer swallows non-`TypeError` errors; repo
521
544
  `joinpath` keeps `.local` a path so chained joins work.
522
545
 
523
- [Unreleased]: https://github.com/jose-pr/netboot/compare/v0.2.1...HEAD
546
+ [Unreleased]: https://github.com/jose-pr/netboot/compare/v0.2.2...HEAD
547
+ [0.2.2]: https://github.com/jose-pr/netboot/compare/v0.2.1...v0.2.2
524
548
  [0.2.1]: https://github.com/jose-pr/netboot/compare/v0.2.0...v0.2.1
525
549
  [0.2.0]: https://github.com/jose-pr/netboot/compare/v0.1.3...v0.2.0
526
550
  [0.1.3]: https://github.com/jose-pr/netboot/compare/v0.1.2...v0.1.3
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: netboot
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: PXE provisioning management: render netboot artifacts and drive DHCP for targets
5
5
  Project-URL: Homepage, https://github.com/jose-pr/netboot/
6
6
  Project-URL: Issues, https://github.com/jose-pr/netboot/issues
@@ -27,9 +27,9 @@ Classifier: Typing :: Typed
27
27
  Requires-Python: >=3.9
28
28
  Requires-Dist: duho<0.6,>=0.5.0
29
29
  Requires-Dist: jinja2<4,>=3.0
30
- Requires-Dist: netimps<0.3,>=0.2.1
30
+ Requires-Dist: netimps<0.4,>=0.3.1
31
31
  Requires-Dist: pathlib-next[uri]<0.10,>=0.9.9
32
- Requires-Dist: yaconfiglib<0.13,>=0.12.0
32
+ Requires-Dist: yaconfiglib<0.14,>=0.13.0
33
33
  Provides-Extra: config
34
34
  Requires-Dist: pyyaml; extra == 'config'
35
35
  Provides-Extra: dev
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "netboot"
7
- version = "0.2.1"
7
+ version = "0.2.2"
8
8
  authors = [{ name = "Jose A." }]
9
9
  description = "PXE provisioning management: render netboot artifacts and drive DHCP for targets"
10
10
  readme = "README.md"
@@ -30,10 +30,12 @@ classifiers = [
30
30
  ]
31
31
  dependencies = [
32
32
  "duho>=0.5.0,<0.6",
33
- # Above the .0 deliberately: netboot calls netimps' resolve() with no
34
- # rdtype, and 0.2.1 is the release that auto-selects it ("ptr" for an
35
- # address literal, "a" otherwise). Don't normalize this back to 0.2.0.
36
- "netimps>=0.2.1,<0.3",
33
+ # Above the .0 deliberately: 0.3.0 made resolve() raise ResolutionError
34
+ # when no backend could even ask (a resolver outage), and 0.3.1 restored
35
+ # [] as the default (strict=False). PixieTarget and Host.try_ip rely on
36
+ # that: every target is built at startup, so a raise would fail every
37
+ # command. Don't normalize this back to 0.3.0.
38
+ "netimps>=0.3.1,<0.4",
37
39
  # Above the .0 deliberately, measured 2026-09-17: recursive `!include`
38
40
  # globs (`sub/**/*.yaml`) break on pathlib_next >=0.9.5 unless yaconfiglib
39
41
  # is >=0.12.0, and yaconfiglib 0.12.0 itself requires pathlib-next>=0.9.9.
@@ -44,9 +46,7 @@ dependencies = [
44
46
  # markupsafe.soft_unicode, removed in MarkupSafe 2.1, so an unpinned
45
47
  # resolve can install a jinja2/markupsafe pair that fails on import.
46
48
  "jinja2>=3.0,<4",
47
- # Above a bare series base for the same measured reason: with the
48
- # pathlib-next this project uses, recursive config discovery needs 0.12.0.
49
- "yaconfiglib>=0.12.0,<0.13",
49
+ "yaconfiglib>=0.13.0,<0.14",
50
50
  ]
51
51
 
52
52
  [project.optional-dependencies]
@@ -110,9 +110,10 @@ is the same object. `netboot.netutils` remains an alias for
110
110
  non-MAC `_id` fills `hostname`; then, if `ip` is still unset and a hostname
111
111
  is known, **exactly one** forward lookup
112
112
  (`netboot.utils.net.resolve`, no reverse lookup) fills it. A name that does
113
- not resolve leaves `ip` unset and logs a warning — it is never retried, and
114
- never raises. `hostname` is lower-cased. The `dns` extra is optional: without
115
- it netimps still resolves through its system/`nslookup` backends.
113
+ not resolve — including when no resolver is reachable at all — leaves `ip`
114
+ unset and logs a warning; it is never retried, and never raises. `hostname`
115
+ is lower-cased. The `dns` extra is optional: without it netimps still
116
+ resolves through its system/`nslookup` backends.
116
117
 
117
118
  - **`PixieImage(**kwargs)`** (`content.Resource`) — `template_path`,
118
119
  `globals`, plus `Resource`'s `src`/`path`, which address the image's
@@ -337,7 +338,8 @@ servers identifies a reservation by it.
337
338
  - **`Host(address: str | Host | None = None)`** — a hostname-or-IP repo
338
339
  address. **`.try_ip() -> IPAddress | str`** — resolves to an `IPAddress`
339
340
  (an IP literal as-is, a hostname through one forward lookup); falls back to
340
- the original string on resolution failure. The `dns` extra is optional —
341
+ the original string on resolution failure, an unreachable resolver
342
+ included. The `dns` extra is optional —
341
343
  without it netimps resolves through its system/`nslookup` backends.
342
344
  Equality/hash by `.address`.
343
345
  - **`flatten(map, _prefix="") -> dict`** — recursively flattens a
@@ -368,13 +370,18 @@ servers identifies a reservation by it.
368
370
  - `parse(value, type, **kw)` raises on bad input; `try_parse(value, type)`
369
371
  returns `None` instead; `is_valid(value, type)` returns a bool. Networks
370
372
  parse non-strict, so `"10.0.0.5/24"` normalises rather than raising.
371
- - `MACAddress` — colon/hyphen/Cisco-dot/bare text, `int` or `bytes`;
372
- `.as_str(sep)`, `.packed`, `.oui`, hashable and ordered.
373
+ - `MACAddress` — colon/hyphen/per-octet-dot/Cisco-dot/bare text (one
374
+ separator per address), `int` or `bytes`; `.as_str(sep)`, `.packed`,
375
+ `.oui`, hashable and ordered. It equals only another `MACAddress`, never a
376
+ `str` — compare text with `MACAddress.try_parse(text) == mac`.
373
377
  - `resolve(query, rdtype=None)` → a list of **native** records (`A`/`AAAA`
374
378
  are `IPv4Address`/`IPv6Address`, not strings); `[]` on a genuine lookup
375
379
  failure, but a malformed query or unknown record type raises `ValueError`
376
380
  rather than looking like "no such record". `rdtype=None` auto-selects:
377
- `"ptr"` when `query` is an address literal, `"a"` otherwise.
381
+ `"ptr"` when `query` is an address literal, `"a"` otherwise. Backends are
382
+ tried until one answers non-empty, so hosts-file and NSS-only names
383
+ resolve too. An unreachable resolver also answers `[]`; netimps'
384
+ `strict=True` raises `netimps.ResolutionError` instead.
378
385
  - `ping(dst)` → a `PingResult` that is truthy on success and also carries
379
386
  `.rtt_ms`/`.ttl`.
380
387
  - `get_interfaces()` / `iter_addresses()` — real adapter enumeration with
@@ -3,8 +3,8 @@
3
3
  The IP/MAC machinery used to live in an in-tree copy of an earlier version of
4
4
  that library. It has since been published, gaining fixes this copy never had --
5
5
  real prefix lengths and MTU in interface enumeration, DNS errors that surface
6
- instead of being swallowed, and a ``ping`` that behaves the same on every
7
- platform -- so the copy is gone.
6
+ instead of being swallowed, and a ``ping`` that speaks each platform's own
7
+ flags -- so the copy is gone.
8
8
 
9
9
  This module re-exports netimps under netboot's own name rather than wrapping
10
10
  it: the point of adopting a library is to use its vocabulary. Only
@@ -90,3 +90,22 @@ def test_resolve_auto_selects_the_record_type():
90
90
  "netimps.resolve no longer defaults rdtype to None (auto-select); "
91
91
  "Host.try_ip relies on that, netimps >= 0.2.1"
92
92
  )
93
+
94
+
95
+ def test_resolve_is_not_strict_by_default():
96
+ """Guards `netimps>=0.3.1`: a resolver outage answers `[]`, not a raise.
97
+
98
+ 0.3.0 raised `ResolutionError` from `resolve()` when no backend could even
99
+ ask; 0.3.1 made that opt-in with `strict=True`. `PixieTarget` handles `[]`
100
+ with a warning, but a raise would escape its construction -- and every
101
+ target is built at startup, so one outage would fail every command.
102
+ """
103
+ strict = inspect.signature(netutils.resolve).parameters.get("strict")
104
+ assert strict is not None, (
105
+ "netimps.resolve has no strict parameter: an unreachable resolver "
106
+ "raises instead of answering [] (netimps >= 0.3.1)"
107
+ )
108
+ assert strict.default is False, (
109
+ "netimps.resolve is strict by default; PixieTarget relies on [] for "
110
+ "an unreachable resolver (netimps >= 0.3.1)"
111
+ )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes