pywrit 0.1.2__tar.gz → 0.1.3__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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pywrit
3
- Version: 0.1.2
4
- Summary: Ask Writ before an agent writes — allow/deny gate with a tamper-evident audit log
3
+ Version: 0.1.3
4
+ Summary: Writ — the gate before the write. Allow/deny gate with a tamper-evident audit log
5
5
  Project-URL: Homepage, https://withwrit.com
6
6
  Project-URL: Documentation, https://docs.withwrit.com
7
7
  Keywords: agents,audit-log,authorization,api-keys
@@ -6,8 +6,8 @@ build-backend = "setuptools.build_meta"
6
6
  # Distribution name: pywrit (approved by Chad 2026-09-27).
7
7
  # The bare name "writ" is taken on PyPI.
8
8
  name = "pywrit"
9
- version = "0.1.2"
10
- description = "Ask Writ before an agent writes — allow/deny gate with a tamper-evident audit log"
9
+ version = "0.1.3"
10
+ description = "Writ — the gate before the write. Allow/deny gate with a tamper-evident audit log"
11
11
  readme = "README.md"
12
12
  requires-python = ">=3.9"
13
13
  keywords = ["agents", "audit-log", "authorization", "api-keys"]
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pywrit
3
- Version: 0.1.2
4
- Summary: Ask Writ before an agent writes — allow/deny gate with a tamper-evident audit log
3
+ Version: 0.1.3
4
+ Summary: Writ — the gate before the write. Allow/deny gate with a tamper-evident audit log
5
5
  Project-URL: Homepage, https://withwrit.com
6
6
  Project-URL: Documentation, https://docs.withwrit.com
7
7
  Keywords: agents,audit-log,authorization,api-keys
@@ -391,20 +391,49 @@ def _find_func(tree, func_name, site_lineno):
391
391
 
392
392
 
393
393
  def _helper_insert_index(lines, tree):
394
+ """Return line index after which to splice the helper (module level).
395
+
396
+ Always inserts before the first module-level function or class.
397
+ Returns -1 to insert at the start of the file (before line 0).
398
+ `_apply_edits` splices at ``idx + 1``, so -1 → position 0.
399
+ """
400
+ first_def = None
401
+ for node in tree.body:
402
+ if isinstance(node, (_ast.FunctionDef, _ast.AsyncFunctionDef,
403
+ _ast.ClassDef)):
404
+ first_def = node.lineno - 1
405
+ break
406
+
407
+ def _cap(idx):
408
+ # Never insert at or after the first def/class (would IndentationError).
409
+ if first_def is None:
410
+ return idx
411
+ return min(idx, first_def - 1)
412
+
394
413
  last_import_end = -1
395
414
  for node in tree.body:
396
415
  if isinstance(node, (_ast.Import, _ast.ImportFrom)):
397
- last_import_end = node.end_lineno - 1
416
+ end = node.end_lineno - 1
417
+ if first_def is not None and end >= first_def:
418
+ continue
419
+ last_import_end = end
398
420
  if last_import_end >= 0:
399
- return last_import_end
421
+ return _cap(last_import_end)
422
+
400
423
  if tree.body and isinstance(tree.body[0], _ast.Expr) and \
401
424
  isinstance(tree.body[0].value, _ast.Constant) and \
402
425
  isinstance(tree.body[0].value.value, str):
403
- return tree.body[0].end_lineno - 1
426
+ return _cap(tree.body[0].end_lineno - 1)
427
+
404
428
  idx = -1
405
429
  if lines and lines[0].startswith("#!"):
406
430
  idx = 0
407
- return idx
431
+ # PEP 263 encoding cookie on line 1 or 2
432
+ enc = 1 if idx == 0 else 0
433
+ if (len(lines) > enc and lines[enc].lstrip().startswith("#")
434
+ and "coding" in lines[enc]):
435
+ idx = enc
436
+ return _cap(idx)
408
437
 
409
438
 
410
439
  def _build_edits(path, rel_path, source, sites, gated):
File without changes
File without changes
File without changes
File without changes