log-foundry 0.10.2.dev120__tar.gz → 0.10.2.dev121__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 (59) hide show
  1. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/PKG-INFO +1 -1
  2. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/pyproject.toml +1 -1
  3. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/_lifecycle.py +33 -17
  4. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/worker.py +5 -4
  5. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/LICENSE +0 -0
  6. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/README.md +0 -0
  7. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/__init__.py +0 -0
  8. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/_diag.py +0 -0
  9. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/_fork.py +0 -0
  10. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/api.py +0 -0
  11. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/config.py +0 -0
  12. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/console.py +0 -0
  13. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/context.py +0 -0
  14. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/decorator.py +0 -0
  15. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/ids.py +0 -0
  16. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/model.py +0 -0
  17. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/py.typed +0 -0
  18. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/results.py +0 -0
  19. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sanitize.py +0 -0
  20. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/__init__.py +0 -0
  21. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/_batch.py +0 -0
  22. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/_chunk.py +0 -0
  23. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/_retry.py +0 -0
  24. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/_socket.py +0 -0
  25. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/_time.py +0 -0
  26. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/base.py +0 -0
  27. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/callback.py +0 -0
  28. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/clickhouse.py +0 -0
  29. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/datadog.py +0 -0
  30. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/elasticsearch.py +0 -0
  31. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/eventhubs.py +0 -0
  32. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/file.py +0 -0
  33. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/filtering.py +0 -0
  34. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/firehose.py +0 -0
  35. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/honeycomb.py +0 -0
  36. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/http.py +0 -0
  37. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/kafka.py +0 -0
  38. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/kinesis.py +0 -0
  39. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/logging_sink.py +0 -0
  40. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/logstash.py +0 -0
  41. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/loki.py +0 -0
  42. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/memory.py +0 -0
  43. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/mongodb.py +0 -0
  44. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/multi.py +0 -0
  45. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/nats.py +0 -0
  46. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/newrelic.py +0 -0
  47. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/null.py +0 -0
  48. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/postgres.py +0 -0
  49. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/pubsub.py +0 -0
  50. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/rabbitmq.py +0 -0
  51. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/redis.py +0 -0
  52. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/sentry.py +0 -0
  53. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/sns.py +0 -0
  54. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/splunk.py +0 -0
  55. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/sqlite.py +0 -0
  56. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/sqs.py +0 -0
  57. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/stdout.py +0 -0
  58. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/syslog.py +0 -0
  59. {log_foundry-0.10.2.dev120 → log_foundry-0.10.2.dev121}/src/log_foundry/sinks/transform.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: log-foundry
3
- Version: 0.10.2.dev120
3
+ Version: 0.10.2.dev121
4
4
  Summary: Generate logs for your console and JSON events for downstream consumption.
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -74,7 +74,7 @@ keywords = [
74
74
  # vulnerability-reporting channel. The repository is still named `log-forge` — the ORIGINAL name,
75
75
  # which PyPI rejected for the distribution — so these URLs deliberately do not match the package
76
76
  # name. See the note on `name` above before "correcting" them.
77
- version = "0.10.2.dev120"
77
+ version = "0.10.2.dev121"
78
78
 
79
79
  [project.urls]
80
80
  Homepage = "https://github.com/agriffi10/log-forge"
@@ -125,8 +125,11 @@ class _Lifecycle:
125
125
  harmlessly: it is a tuple of strings, which holds no primitive to replace and no sink to
126
126
  hook. The module-level tuple is unchanged and still needed; neither is the whole rule.
127
127
 
128
- Marking is not narrowed: :func:`_inheritance_roots` reads the slot directly, so a child still
129
- marks an inherited superseded sink foreign and still refuses to close it (SPEC-042 FR-001).
128
+ Marking is not narrowed: :func:`_inheritance_roots` reads the slot directly, so the walk
129
+ still reaches an inherited superseded sink and it is still refused (SPEC-042 FR-001) — on the
130
+ stamp ``configure()`` left, since :func:`_mark_inherited` ``setdefault``s and leaves an
131
+ existing record alone rather than writing ``_FOREIGN`` over it — or on ``_FOREIGN``, for a
132
+ sink held inside it that the bounded stamp walk never reached.
130
133
  """
131
134
 
132
135
  def __init__(self) -> None:
@@ -494,8 +497,10 @@ _FOREIGN = -1
494
497
  """The pid a record carries when the sink belongs to some earlier process.
495
498
 
496
499
  Never a real pid, so it can never match :func:`os.getpid`. Laid down by
497
- :func:`_mark_inherited` in a forked child over everything the child inherited, which is what
498
- gives "this process did not acquire it" a **terminal** state.
500
+ :func:`_mark_inherited` in a forked child over each inherited sink its walk reaches that the
501
+ parent never recorded —
502
+ it ``setdefault``s, so a sink already carrying the parent's own pid keeps it and is refused by
503
+ that — which is what gives "this process did not acquire it" a **terminal** state.
499
504
 
500
505
  Without it the record protects nothing where it is empty: ``stamp`` is write-once, and write-once
501
506
  defends only a record that already exists, so a child could ``configure()`` its way into *owning*
@@ -505,7 +510,7 @@ destroying the parent's transport. Unrecorded has to be unclaimable, not merely
505
510
  """
506
511
 
507
512
  _MARKING_CEILING = 100_000
508
- """Objects the child's marking walk may visit before it gives up and refuses everything.
513
+ """Objects the child's marking walk may visit before it gives up and refuses the unrecorded.
509
514
 
510
515
  **A cap is right here where SPEC-039 rejected one, and the difference is the fallback.** That
511
516
  spec declined to bound its repair walk because an unfound lock is a child that hangs with no
@@ -610,7 +615,9 @@ def _bounded_children(container: object) -> list[object]:
610
615
 
611
616
  Raises:
612
617
  None. A container that raises while being read contributes nothing, as it does in
613
- ``_fork``; what it holds is then unmarked, therefore unrecorded, therefore refused.
618
+ ``_fork``; what it holds is then unmarked. It keeps whatever ``stamp`` recorded, and
619
+ where nothing did it is unrecorded — refused through a recorded wrapper, and §13 item
620
+ 7's residual otherwise, since absorbing here leaves :data:`_marking_failed` clear.
614
621
  """
615
622
  try:
616
623
  if isinstance(container, dict):
@@ -623,7 +630,7 @@ def _bounded_children(container: object) -> list[object]:
623
630
  _diag.absorbed(
624
631
  "reading a container while marking a forked child's sinks",
625
632
  exc,
626
- "what it holds is not marked, so this child will refuse to close it",
633
+ "what it holds is not marked by this child",
627
634
  )
628
635
  return []
629
636
 
@@ -768,7 +775,7 @@ def _inheritance_roots() -> list[object]:
768
775
 
769
776
 
770
777
  def _mark_inherited() -> None:
771
- """Marks every sink this child inherited as foreign, before anything can claim it (FR-001).
778
+ """Records the sinks this child inherited, before any other fork handler runs (FR-001).
772
779
 
773
780
  Registered with ``_fork`` and run in the child, which is why it may take the library's locks:
774
781
  they were re-initialised moments earlier. It must run **before** any handler that could reach
@@ -863,10 +870,14 @@ def _mark_inherited() -> None:
863
870
  def reclaim(sink: object) -> None:
864
871
  """Records that a sink re-acquired its transport in this process (SPEC-042 FR-005).
865
872
 
866
- The one write that **overrides** an existing record, and it has to be: :func:`_mark_inherited`
867
- has already stamped everything inherited ``_FOREIGN`` by the time the hook roster is read, so
868
- a ``setdefault`` here would leave a sink that provably holds its own descriptor refused
869
- forever.
873
+ The one write that **overrides** an existing record, and it has to be: an inherited sink
874
+ **the marking walk reached** carries another process's pid by the time the hook roster is
875
+ read — the parent's own stamp, or the ``_FOREIGN`` :func:`_mark_inherited` ``setdefault``s
876
+ where the parent recorded nothing — so a ``setdefault`` here would leave a sink that provably
877
+ holds its own descriptor refused forever. Where the walk did *not* reach it the record is
878
+ empty and this write is the one that fills it — a walk can miss a sink with no exception at
879
+ all, and the loop calling this sits outside that walk's ``try`` so it also runs when the walk
880
+ ended badly.
870
881
 
871
882
  **It re-stamps the sink that re-acquired, and nothing above it** (FR-005 AC-8). A child
872
883
  inheriting ``MultiSink(FileSink, FileSink)`` re-stamps the two children — only they implement
@@ -942,7 +953,8 @@ def releasable(sink: object, *, owner: object = None) -> bool:
942
953
 
943
954
  The wrapper is what makes the two distinguishable, so it is asked:
944
955
 
945
- - Neither recorded — a graph the library never saw. The caller owns it; honour the close.
956
+ - Neither recorded — a graph nothing in the record reaches. The caller owns it; honour the
957
+ close.
946
958
  - The child recorded elsewhere — the inherited sink, or one :func:`_mark_inherited` marked
947
959
  ``_FOREIGN``. Refused however it was reached, which is what closes the wrapper route
948
960
  (FR-002 AC-3).
@@ -952,10 +964,14 @@ def releasable(sink: object, *, owner: object = None) -> bool:
952
964
  in §13.
953
965
 
954
966
  **"Unrecorded is the caller's" is only sound because a fork makes it false first.** In a
955
- child, :func:`_mark_inherited` records everything inherited as ``_FOREIGN`` *before* any
956
- handler runs, so an unrecorded sink there is one built after the fork. If that walk could
957
- not finish, :data:`_marking_failed` withdraws the assumption entirely and every unrecorded
958
- sink is refused.
967
+ child, :func:`_mark_inherited` records every inherited sink **its walk reaches** that the
968
+ parent did not record as ``_FOREIGN``, *before* any other handler runs — one the parent *did*
969
+ record keeps that stamp and is refused on it. What the walk reached is therefore stamped or
970
+ ``_FOREIGN``; what it missed stays unrecorded and is the §13 item 7 residual, not a case this
971
+ closes — measured, a sink built before the fork behind a container that raises is unrecorded
972
+ in the child, releasable, and closed. If the walk could not finish *at all*,
973
+ :data:`_marking_failed` withdraws the assumption entirely and every unrecorded sink is
974
+ refused.
959
975
 
960
976
  Identity is re-checked against the strong reference rather than trusting the ``id``. The
961
977
  reference is what makes an id collision impossible while a record stands, so this can only
@@ -290,10 +290,11 @@ class Worker:
290
290
  the shape ``_fork._SKIP_ATTRIBUTE`` describes: bookkeeping that pins objects is not live state
291
291
  to repair. Without the opt-out the walk reaches a superseded sink, replaces its locks — merely
292
292
  wasteful — and runs its fork hooks, which is not: ``_lifecycle.reclaim`` then overwrites the
293
- ``_FOREIGN`` stamp ``_mark_inherited`` set, leaving a child able to release a transport it
294
- never acquired. Nothing is lost by skipping it, for the reason ``_lifecycle._owned``'s entry
295
- gives: a sink that is still *live* is reached through ``self.sink`` and the config, neither of
296
- which is opted out.
293
+ foreign-pid record the child holds for it — the parent's own stamp, or the ``_FOREIGN``
294
+ ``_mark_inherited`` ``setdefault``s where the parent recorded nothing — leaving a child able
295
+ to release a transport it never acquired. Nothing is lost by skipping it, for the reason
296
+ ``_lifecycle._owned``'s entry gives: a sink that is still *live* is reached through
297
+ ``self.sink`` and the config, neither of which is opted out.
297
298
  """
298
299
 
299
300
  def __init__(