codeanalyzer-python 1.1.0__tar.gz → 1.1.1__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 (89) hide show
  1. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/PKG-INFO +1 -1
  2. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/builder.py +58 -1
  3. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/pyproject.toml +1 -1
  4. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/.gitignore +0 -0
  5. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/LICENSE +0 -0
  6. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/NOTICE +0 -0
  7. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/README.md +0 -0
  8. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/__init__.py +0 -0
  9. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/__main__.py +0 -0
  10. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/config/__init__.py +0 -0
  11. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/config/config.py +0 -0
  12. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/core.py +0 -0
  13. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/__init__.py +0 -0
  14. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/access_paths.py +0 -0
  15. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/alias.py +0 -0
  16. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/cfg.py +0 -0
  17. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/defuse.py +0 -0
  18. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/dominance.py +0 -0
  19. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/identity.py +0 -0
  20. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/pdg.py +0 -0
  21. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/scalpel/LICENSE +0 -0
  22. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/scalpel/README.md +0 -0
  23. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/scalpel/SSA/__init__.py +0 -0
  24. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/scalpel/SSA/const.py +0 -0
  25. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/scalpel/__init__.py +0 -0
  26. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/scalpel/cfg/__init__.py +0 -0
  27. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/scalpel/cfg/builder.py +0 -0
  28. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/scalpel/cfg/model.py +0 -0
  29. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/scalpel/core/__init__.py +0 -0
  30. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/scalpel/core/func_call_visitor.py +0 -0
  31. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/scalpel/core/vars_visitor.py +0 -0
  32. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/scalpel_oracle.py +0 -0
  33. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/scc.py +0 -0
  34. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/sdg.py +0 -0
  35. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/slicing.py +0 -0
  36. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/summaries.py +0 -0
  37. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/dataflow/syntactic.py +0 -0
  38. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/jedi/__init__.py +0 -0
  39. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/jedi/jedi.py +0 -0
  40. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/neo4j/__init__.py +0 -0
  41. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/neo4j/bolt.py +0 -0
  42. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/neo4j/cypher.py +0 -0
  43. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/neo4j/emit.py +0 -0
  44. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/neo4j/project.py +0 -0
  45. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/neo4j/rows.py +0 -0
  46. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/neo4j/schema.py +0 -0
  47. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/options/__init__.py +0 -0
  48. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/options/options.py +0 -0
  49. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/provenance.py +0 -0
  50. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/py.typed +0 -0
  51. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/schema/__init__.py +0 -0
  52. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/schema/assign_ids.py +0 -0
  53. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/schema/call_graph_ids.py +0 -0
  54. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/schema/ids.py +0 -0
  55. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/schema/l1_body.py +0 -0
  56. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/schema/l2_callees.py +0 -0
  57. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/schema/py_schema.py +0 -0
  58. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/semantic_analysis/__init__.py +0 -0
  59. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/semantic_analysis/call_graph.py +0 -0
  60. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/semantic_analysis/pycg/__init__.py +0 -0
  61. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/semantic_analysis/pycg/pycg_analysis.py +0 -0
  62. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/semantic_analysis/pycg/pycg_exceptions.py +0 -0
  63. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/semantic_analysis/pycg/shard_planner.py +0 -0
  64. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/syntactic_analysis/__init__.py +0 -0
  65. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/syntactic_analysis/exceptions.py +0 -0
  66. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/syntactic_analysis/import_resolver.py +0 -0
  67. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/syntactic_analysis/symbol_table_builder.py +0 -0
  68. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/utils/__init__.py +0 -0
  69. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/utils/logging.py +0 -0
  70. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/codeanalyzer/utils/progress_bar.py +0 -0
  71. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/docs/handoff/README.md +0 -0
  72. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/docs/handoff/schema.neo4j.json +0 -0
  73. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/schema-uml.drawio +0 -0
  74. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/schema.neo4j.json +0 -0
  75. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/flask/README.md +0 -0
  76. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/flask/examples/celery/README.md +0 -0
  77. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/flask/requirements-skip/README.md +0 -0
  78. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/flask/src/flask/sansio/README.md +0 -0
  79. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/requests/LICENSE +0 -0
  80. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/requests/NOTICE +0 -0
  81. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/requests/README.md +0 -0
  82. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/requests/docs/_themes/LICENSE +0 -0
  83. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/requests/ext/LICENSE +0 -0
  84. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/xarray/LICENSE +0 -0
  85. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/xarray/README.md +0 -0
  86. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/xarray/properties/README.md +0 -0
  87. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/xarray/xarray/datatree_/LICENSE +0 -0
  88. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/xarray/xarray/datatree_/README.md +0 -0
  89. {codeanalyzer_python-1.1.0 → codeanalyzer_python-1.1.1}/test/fixtures/whole_applications/xarray/xarray/datatree_/docs/README.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeanalyzer-python
3
- Version: 1.1.0
3
+ Version: 1.1.1
4
4
  Summary: Static analysis for Python — canonical schema v2 (symbol table, call graph, and native CFG/PDG/SDG dataflow) as analysis.json or a Neo4j property graph.
5
5
  Author-email: Rahul Krishna <i.m.ralk@gmail.com>
6
6
  License-File: LICENSE
@@ -283,6 +283,23 @@ def emit_l3_body(
283
283
  continue
284
284
  pycallable.body[local] = BodyNode(kind=node.kind, span=span)
285
285
 
286
+ # #115: anchor nested call vertices to their statement. A bare-call
287
+ # statement shares its key with its CFG node (handled above); a call
288
+ # nested inside a larger statement (`y = f(x)`) has its own key and
289
+ # no cfg contact, so it carries `parent` = the enclosing statement's
290
+ # local id — the same anchoring actual_in/actual_out vertices use.
291
+ for node in pdg.cfg.nodes:
292
+ if node.ast_node is None:
293
+ continue
294
+ stmt_local = im.local(node.id)
295
+ for call in _calls_in(node.ast_node):
296
+ call_key = f"{call.lineno}:{call.col_offset}"
297
+ child = pycallable.body.get(call_key)
298
+ if child is None or call_key == stmt_local:
299
+ continue
300
+ if child.kind == "call":
301
+ child.parent = stmt_local
302
+
286
303
  if want_cfg:
287
304
  pycallable.cfg = [
288
305
  CfgEdge(
@@ -437,7 +454,12 @@ def emit_l4(
437
454
  points-to provenance and taint are *not* emitted here (later tasks).
438
455
  """
439
456
  from codeanalyzer.dataflow.identity import IdentityMap
440
- from codeanalyzer.schema.py_schema import BodyNode, ParamEdge, SummaryEdge
457
+ from codeanalyzer.schema.py_schema import (
458
+ BodyNode,
459
+ DdgEdge,
460
+ ParamEdge,
461
+ SummaryEdge,
462
+ )
441
463
 
442
464
  # L4 emission is additive (it *appends* summary/param edges), so it must
443
465
  # first clear any L4 state a reused cache left on these live objects —
@@ -517,6 +539,41 @@ def emit_l4(
517
539
  )
518
540
  (app.param_in if e.type == "PARAM_IN" else app.param_out).append(edge)
519
541
 
542
+ # (e) statement ↔ port ddg wiring (#115). The IR's ``extra_edges`` — the
543
+ # def→actual_in, actual_out→callsite, formal_in→use and def→formal_out
544
+ # bindings ``assemble_sdg`` wires — are what connect the port lattice to
545
+ # the statement-level ddg; without them the SDG is two disconnected
546
+ # graphs and no end-to-end flows_to walk can cross a call. Emitted with
547
+ # ``prov=["reaching-defs"]`` (the label codeanalyzer-typescript ships for
548
+ # its port-routing ddg edges, so the vocabulary stays keystone-shared).
549
+ # CDG-typed extras (callsite → actual_in containment) are skipped — the
550
+ # actual vertices already carry that anchoring in ``parent``.
551
+ for sig, fg in ir.functions.items():
552
+ pycallable = sig_to_callable.get(sig)
553
+ im = ims.get(sig)
554
+ if pycallable is None or im is None:
555
+ continue
556
+ # Idempotency under cache reuse, mirroring the points-to delta: strip
557
+ # any reaching-defs edges a prior run appended before re-emitting.
558
+ pycallable.ddg = [e for e in pycallable.ddg if e.prov != ["reaching-defs"]]
559
+ seen: set = set()
560
+ rows = []
561
+ for e in fg.extra_edges:
562
+ if e.type != "DDG":
563
+ continue
564
+ src, dst = im.local(e.source), im.local(e.target)
565
+ if src not in pycallable.body or dst not in pycallable.body:
566
+ continue
567
+ key = (src, dst, e.var)
568
+ if key in seen:
569
+ continue
570
+ seen.add(key)
571
+ rows.append(
572
+ DdgEdge(src=src, dst=dst, var=e.var, prov=["reaching-defs"])
573
+ )
574
+ rows.sort(key=lambda r: (r.src, r.dst, r.var or ""))
575
+ pycallable.ddg.extend(rows)
576
+
520
577
 
521
578
  def _ddg_local_set(im, pdg) -> Set[Tuple[str, str, Optional[str]]]:
522
579
  """The DDG edges of ``pdg`` as a set of ``(local_src, local_dst, var)``.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codeanalyzer-python"
3
- version = "1.1.0"
3
+ version = "1.1.1"
4
4
  description = "Static analysis for Python — canonical schema v2 (symbol table, call graph, and native CFG/PDG/SDG dataflow) as analysis.json or a Neo4j property graph."
5
5
  readme = "README.md"
6
6
  authors = [