diffimpactscout 0.4.0__tar.gz → 0.5.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 (45) hide show
  1. {diffimpactscout-0.4.0/src/diffimpactscout.egg-info → diffimpactscout-0.5.0}/PKG-INFO +1 -1
  2. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/setup.py +1 -1
  3. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/__init__.py +1 -1
  4. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/impact/impact.py +2 -0
  5. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/impact/python_analyzer.py +19 -1
  6. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/impact/route_linker.py +37 -9
  7. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0/src/diffimpactscout.egg-info}/PKG-INFO +1 -1
  8. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/LICENSE +0 -0
  9. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/README.md +0 -0
  10. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/pyproject.toml +0 -0
  11. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/setup.cfg +0 -0
  12. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/__main__.py +0 -0
  13. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/base.py +0 -0
  14. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/checks/__init__.py +0 -0
  15. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/checks/base.py +0 -0
  16. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/checks/eslint.py +0 -0
  17. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/checks/hygiene.py +0 -0
  18. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/checks/prettier.py +0 -0
  19. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/checks/repo_checks.py +0 -0
  20. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/checks/ruff.py +0 -0
  21. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/checks/syntax.py +0 -0
  22. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/cli.py +0 -0
  23. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/config.py +0 -0
  24. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/dependency_check.py +0 -0
  25. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/detect.py +0 -0
  26. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/env.py +0 -0
  27. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/gitrun.py +0 -0
  28. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/guard.py +0 -0
  29. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/impact/__init__.py +0 -0
  30. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/impact/_parse.py +0 -0
  31. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/impact/cache.py +0 -0
  32. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/impact/diff_parser.py +0 -0
  33. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/impact/reporter.py +0 -0
  34. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/launcher.py +0 -0
  35. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/profiles/django.json +0 -0
  36. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/profiles/fastapi.json +0 -0
  37. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/profiles/frontend.json +0 -0
  38. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/profiles/generic.json +0 -0
  39. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/profiles/python.json +0 -0
  40. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout/scope.py +0 -0
  41. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout.egg-info/SOURCES.txt +0 -0
  42. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout.egg-info/dependency_links.txt +0 -0
  43. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout.egg-info/entry_points.txt +0 -0
  44. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/src/diffimpactscout.egg-info/top_level.txt +0 -0
  45. {diffimpactscout-0.4.0 → diffimpactscout-0.5.0}/tests/test_fixture_smoke.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diffimpactscout
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: Incremental pre-push guard and AST blast-radius impact analyzer for git repositories.
5
5
  Author: DiffImpactScout contributors
6
6
  License: MIT
@@ -7,7 +7,7 @@ with io.open("README.md", encoding="utf-8") as fh:
7
7
 
8
8
  setup(
9
9
  name="diffimpactscout",
10
- version="0.4.0",
10
+ version="0.5.0",
11
11
  description="Incremental pre-push guard and AST blast-radius impact analyzer for git repositories.",
12
12
  long_description=long_description,
13
13
  long_description_content_type="text/markdown",
@@ -1,3 +1,3 @@
1
1
  """diffimpactscout: incremental pre-push guard and AST blast-radius impact analyzer."""
2
2
 
3
- __version__ = "0.4.0"
3
+ __version__ = "0.5.0"
@@ -299,6 +299,8 @@ def _handler_leaf(handler):
299
299
  def _route_binds_handler(urls_entry, handler, mods, path, weak):
300
300
  if not mods:
301
301
  return True
302
+ if _module_of(path) in mods:
303
+ return True
302
304
  analysis = _peel(urls_entry)
303
305
  if not isinstance(analysis, dict):
304
306
  return True
@@ -177,7 +177,25 @@ def _usage_resolves(analysis, usage, name, entity_mods, path, weak):
177
177
  base = usage.get("base") or ""
178
178
  if not base:
179
179
  return True
180
- return _imports_from(analysis, base.split(".")[0], entity_mods, path)
180
+ head = base.split(".")[0]
181
+ if _imports_from(analysis, head, entity_mods, path):
182
+ return True
183
+ if _is_imported(analysis, head):
184
+ return False
185
+ return _module_of(path) in entity_mods
186
+
187
+
188
+ def _is_imported(analysis, name):
189
+ """Return True when the file binds ``name`` through any import (name or alias)."""
190
+ usages = (analysis or {}).get("usages")
191
+ if not isinstance(usages, list):
192
+ return False
193
+ for usage in usages:
194
+ if usage.get("kind") != "import":
195
+ continue
196
+ if usage.get("name") == name or usage.get("alias") == name:
197
+ return True
198
+ return False
181
199
 
182
200
 
183
201
  def _module_of(path):
@@ -320,7 +320,13 @@ def compose_url_prefixes(root, urls_globs, cfg=None):
320
320
  prefix_map[module] = (ppath, pregex)
321
321
  for inc_path, inc_regex, target in includes.get(module, []):
322
322
  if target in files and target not in prefix_map:
323
- queue.append((target, ppath + (inc_path or ""), _concat_regex(pregex, inc_regex)))
323
+ if inc_path is not None:
324
+ child_path = ppath + inc_path
325
+ child_regex = _concat_regex(pregex, _route_regex_source(inc_path))
326
+ else:
327
+ child_path = ppath + _literal_from_regex(inc_regex)
328
+ child_regex = _concat_regex(pregex, inc_regex)
329
+ queue.append((target, child_path, child_regex))
324
330
  return prefix_map
325
331
 
326
332
 
@@ -347,27 +353,29 @@ def extract_django_routes(root, urls_globs, cfg=None):
347
353
  continue
348
354
  name_val = _str_value(_call_kwarg_value(node, "name"))
349
355
  if func.id == "path":
350
- composed = ppath + path_val
356
+ composed_path = ppath + path_val
357
+ composed_regex = _concat_regex(pregex, _route_regex_source(path_val))
351
358
  routes.append(
352
359
  Route(
353
360
  name_val,
354
361
  path_val,
355
362
  handler,
356
363
  posix,
357
- full=composed,
358
- regex=_route_regex(composed),
364
+ full=composed_path,
365
+ regex=_anchored_regex(composed_regex),
359
366
  )
360
367
  )
361
368
  else:
362
- composed = _concat_regex(pregex, path_val)
369
+ composed_path = ppath + _literal_from_regex(path_val)
370
+ composed_regex = _concat_regex(pregex, path_val)
363
371
  routes.append(
364
372
  Route(
365
373
  name_val,
366
374
  path_val,
367
375
  handler,
368
376
  posix,
369
- full=composed,
370
- regex=_anchored_regex(composed),
377
+ full=composed_path,
378
+ regex=_anchored_regex(composed_regex),
371
379
  )
372
380
  )
373
381
  return routes
@@ -487,7 +495,7 @@ def extract_frontend_refs(root, frontend_globs, cfg=None, vendor=False, needles=
487
495
  return refs
488
496
 
489
497
 
490
- def _route_regex(route_path):
498
+ def _route_regex_source(route_path):
491
499
  parts = []
492
500
  i = 0
493
501
  n = len(route_path)
@@ -510,7 +518,27 @@ def _route_regex(route_path):
510
518
  else:
511
519
  parts.append(re.escape(ch))
512
520
  i += 1
513
- return re.compile("^" + "".join(parts) + "$")
521
+ return "".join(parts)
522
+
523
+
524
+ def _route_regex(route_path):
525
+ return re.compile("^" + _route_regex_source(route_path) + "$")
526
+
527
+
528
+ def _literal_from_regex(source):
529
+ """Best-effort literal path for a regex prefix/route (strips ``^`` and ``$``).
530
+
531
+ Used to compose the human-readable ``full`` URL when a path prefix and a
532
+ regex prefix are mixed in the include chain; matching still uses ``regex``.
533
+ """
534
+ if not source:
535
+ return ""
536
+ s = source
537
+ if s.startswith("^"):
538
+ s = s[1:]
539
+ if s.endswith("$"):
540
+ s = s[:-1]
541
+ return s
514
542
 
515
543
 
516
544
  def _is_path_prefix(ref, route_path):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diffimpactscout
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: Incremental pre-push guard and AST blast-radius impact analyzer for git repositories.
5
5
  Author: DiffImpactScout contributors
6
6
  License: MIT
File without changes