skim-python 0.0.1__tar.gz → 0.0.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: skim-python
3
- Version: 0.0.1
3
+ Version: 0.0.2
4
4
  Summary: Language-aware, AST-resilient outline and verbatim code extractor for Python tailored for AI agents
5
5
  Project-URL: Homepage, https://github.com/benedictjohannes/programming-helper-utils
6
6
  Project-URL: Repository, https://github.com/benedictjohannes/programming-helper-utils
@@ -335,6 +335,7 @@ skim-py glance tests/fixtures/syntax_error.py -s
335
335
  ```
336
336
  ```text
337
337
  === tests/fixtures/syntax_error.py (12 lines) [! 1 syntax error] ===
338
+ # parsed with 1 line masked (L7)
338
339
  Syntax Notice: L7: invalid syntax
339
340
 
340
341
  Outline:
@@ -343,12 +344,13 @@ Outline:
343
344
  L11-L12 def valid_after()
344
345
  ```
345
346
 
346
- Surrounding valid functions remain fully extractable via `block`:
347
+ Surrounding valid functions remain fully extractable via `block` (masking warnings are surfaced via stderr):
347
348
 
348
349
  ```bash
349
350
  skim-py block tests/fixtures/syntax_error.py valid_after
350
351
  ```
351
352
  ```text
353
+ tests/fixtures/syntax_error.py: # parsed with 1 line masked (L7)
352
354
  === tests/fixtures/syntax_error.py (L11-L12) ===
353
355
  11 | def valid_after():
354
356
  12 | return 2
@@ -360,6 +362,7 @@ And if an extracted block contains a syntax error within its line span, the warn
360
362
  skim-py block tests/fixtures/syntax_error.py broken_function
361
363
  ```
362
364
  ```text
365
+ tests/fixtures/syntax_error.py: # parsed with 1 line masked (L7)
363
366
  === tests/fixtures/syntax_error.py (L5-L8) [! 1 syntax error] ===
364
367
  Syntax Notice: L7: invalid syntax
365
368
  5 | def broken_function():
@@ -368,6 +371,34 @@ skim-py block tests/fixtures/syntax_error.py broken_function
368
371
  8 | return x
369
372
  ```
370
373
 
374
+ For cascade-prone mid-edit states (such as an unclosed `def foo(x,` header or unclosed bracket structure), `skim-py` masks the entire broken block in one step, marks the masked line range in the notice, and salvages the broken declaration in the outline so it remains targetable by `block`:
375
+
376
+ ```bash
377
+ skim-py glance tests/fixtures/syntax_error_cascade.py -s
378
+ ```
379
+ ```text
380
+ === tests/fixtures/syntax_error_cascade.py (11 lines) [! 1 syntax error] ===
381
+ # parsed with 3 lines masked (L5, L6, L7)
382
+ Syntax Notice: L5: '(' was never closed (L5-L7 masked)
383
+
384
+ Outline:
385
+ L1-L2 def valid_before()
386
+ L5-L7 def broken_header [syntax error]
387
+ L10-L11 def valid_after()
388
+ ```
389
+
390
+ ```bash
391
+ skim-py block tests/fixtures/syntax_error_cascade.py broken_header
392
+ ```
393
+ ```text
394
+ tests/fixtures/syntax_error_cascade.py: # parsed with 3 lines masked (L5, L6, L7)
395
+ === tests/fixtures/syntax_error_cascade.py (L5-L7) [! 1 syntax error] ===
396
+ Syntax Notice: L5: '(' was never closed (L5-L7 masked)
397
+ 5 | def broken_header(x,
398
+ 6 | y = 1
399
+ 7 | return y
400
+ ```
401
+
371
402
  ---
372
403
 
373
404
  ### 2. `block` Subcommand
@@ -310,6 +310,7 @@ skim-py glance tests/fixtures/syntax_error.py -s
310
310
  ```
311
311
  ```text
312
312
  === tests/fixtures/syntax_error.py (12 lines) [! 1 syntax error] ===
313
+ # parsed with 1 line masked (L7)
313
314
  Syntax Notice: L7: invalid syntax
314
315
 
315
316
  Outline:
@@ -318,12 +319,13 @@ Outline:
318
319
  L11-L12 def valid_after()
319
320
  ```
320
321
 
321
- Surrounding valid functions remain fully extractable via `block`:
322
+ Surrounding valid functions remain fully extractable via `block` (masking warnings are surfaced via stderr):
322
323
 
323
324
  ```bash
324
325
  skim-py block tests/fixtures/syntax_error.py valid_after
325
326
  ```
326
327
  ```text
328
+ tests/fixtures/syntax_error.py: # parsed with 1 line masked (L7)
327
329
  === tests/fixtures/syntax_error.py (L11-L12) ===
328
330
  11 | def valid_after():
329
331
  12 | return 2
@@ -335,6 +337,7 @@ And if an extracted block contains a syntax error within its line span, the warn
335
337
  skim-py block tests/fixtures/syntax_error.py broken_function
336
338
  ```
337
339
  ```text
340
+ tests/fixtures/syntax_error.py: # parsed with 1 line masked (L7)
338
341
  === tests/fixtures/syntax_error.py (L5-L8) [! 1 syntax error] ===
339
342
  Syntax Notice: L7: invalid syntax
340
343
  5 | def broken_function():
@@ -343,6 +346,34 @@ skim-py block tests/fixtures/syntax_error.py broken_function
343
346
  8 | return x
344
347
  ```
345
348
 
349
+ For cascade-prone mid-edit states (such as an unclosed `def foo(x,` header or unclosed bracket structure), `skim-py` masks the entire broken block in one step, marks the masked line range in the notice, and salvages the broken declaration in the outline so it remains targetable by `block`:
350
+
351
+ ```bash
352
+ skim-py glance tests/fixtures/syntax_error_cascade.py -s
353
+ ```
354
+ ```text
355
+ === tests/fixtures/syntax_error_cascade.py (11 lines) [! 1 syntax error] ===
356
+ # parsed with 3 lines masked (L5, L6, L7)
357
+ Syntax Notice: L5: '(' was never closed (L5-L7 masked)
358
+
359
+ Outline:
360
+ L1-L2 def valid_before()
361
+ L5-L7 def broken_header [syntax error]
362
+ L10-L11 def valid_after()
363
+ ```
364
+
365
+ ```bash
366
+ skim-py block tests/fixtures/syntax_error_cascade.py broken_header
367
+ ```
368
+ ```text
369
+ tests/fixtures/syntax_error_cascade.py: # parsed with 3 lines masked (L5, L6, L7)
370
+ === tests/fixtures/syntax_error_cascade.py (L5-L7) [! 1 syntax error] ===
371
+ Syntax Notice: L5: '(' was never closed (L5-L7 masked)
372
+ 5 | def broken_header(x,
373
+ 6 | y = 1
374
+ 7 | return y
375
+ ```
376
+
346
377
  ---
347
378
 
348
379
  ### 2. `block` Subcommand
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "skim-python"
7
- version = "0.0.1"
7
+ version = "0.0.2"
8
8
  description = "Language-aware, AST-resilient outline and verbatim code extractor for Python tailored for AI agents"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -7,7 +7,7 @@ from pathlib import Path
7
7
  from typing import List, Optional
8
8
 
9
9
  from .types import OutlineItem, ParsedFile
10
- from .parser import parse_source_file
10
+ from .parser import parse_source_file, split_source_lines
11
11
 
12
12
 
13
13
  def collect_all_items(items: List[OutlineItem]) -> List[OutlineItem]:
@@ -38,6 +38,8 @@ def run_block(
38
38
  return 1
39
39
 
40
40
  parsed = parse_source_file(file_path, content, include_tests=include_tests)
41
+ if parsed.masking_warning:
42
+ sys.stderr.write(f"{file_path}: {parsed.masking_warning}\n")
41
43
  all_items = collect_all_items(parsed.items)
42
44
 
43
45
  matches: List[OutlineItem] = []
@@ -123,7 +125,7 @@ def run_block(
123
125
  return 3
124
126
 
125
127
  chosen = matches[0]
126
- src_lines = content.splitlines()
128
+ src_lines = split_source_lines(content, keepends=False)
127
129
  block_lines = src_lines[chosen.start_line - 1 : chosen.end_line]
128
130
 
129
131
  # Check for syntax errors within block range
@@ -8,7 +8,7 @@ from pathlib import Path
8
8
  from typing import List, Optional
9
9
 
10
10
  from .types import OutlineItem, ParsedFile
11
- from .parser import parse_source_file, is_test_file
11
+ from .parser import parse_source_file, is_test_file, split_source_lines
12
12
 
13
13
 
14
14
  IGNORED_DIRS = {
@@ -121,7 +121,7 @@ def run_glance(
121
121
  sys.stderr.write(f"Error reading {file_path}: {err}\n")
122
122
  continue
123
123
 
124
- src_lines = content.splitlines()
124
+ src_lines = split_source_lines(content, keepends=False)
125
125
  parsed = parse_source_file(file_path, content, include_tests=include_tests)
126
126
 
127
127
  if filters:
@@ -155,6 +155,8 @@ def run_glance(
155
155
  rel_path = file_path
156
156
 
157
157
  print(f"=== {rel_path} ({parsed.total_lines} lines){test_info}{error_tag} ===")
158
+ if parsed.masking_warning:
159
+ print(parsed.masking_warning)
158
160
 
159
161
  for err in parsed.syntax_errors:
160
162
  print(f" Syntax Notice: L{err.line}: {err.message}")