codeanalyzer-python 1.2.0__py3-none-any.whl → 1.4.0__py3-none-any.whl

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.
@@ -37,8 +37,12 @@ class AnalysisOptions:
37
37
  rebuild_analysis: bool = False
38
38
  skip_tests: bool = True
39
39
  no_venv: bool = False
40
+ resolve_installed: bool = False
40
41
  file_name: Optional[Path] = None
41
42
  cache_dir: Optional[Path] = None
42
43
  clear_cache: bool = False
43
44
  verbosity: int = 0
44
45
  entrypoint_rules: Tuple[Path, ...] = ()
46
+ # Artifact text capture (#157 follow-up): whether to capture `source` at
47
+ # all. There is no byte cap -- `source` is the whole file or "" (#172).
48
+ artifact_text: bool = True
@@ -21,3 +21,24 @@ def callable_sig_segment(name: str, param_names: List[str]) -> str:
21
21
 
22
22
  def ordinal_id(callable_id: str, tag: str) -> str:
23
23
  return f"{callable_id}@{tag}"
24
+
25
+
26
+ def artifact_id(app_name: str, rel_path: str) -> str:
27
+ """Language-neutral artifact id: ``can://artifact/<app>/<rel-path>``.
28
+
29
+ The first segment is a namespace (a language for code nodes, the literal
30
+ ``artifact`` for files), so sibling analyzers over the same repo emit the
31
+ same id for the same file."""
32
+ return f"can://artifact/{app_name}/{rel_path}"
33
+
34
+
35
+ def config_key_id(artifact_id: str, dotted_key: str) -> str:
36
+ """A ``PyConfigKey`` extracted from an artifact: ``<artifact-id>@key/<dotted.key>``.
37
+ ``dotted_key`` uses numeric segments for array indices (e.g.
38
+ ``services.web.ports.0``); ids are opaque, do not re-split them."""
39
+ return f"{artifact_id}@key/{dotted_key}"
40
+
41
+
42
+ def purl_pypi(name: str) -> str:
43
+ """Package URL for a (PEP 503 normalized) PyPI distribution name."""
44
+ return f"pkg:pypi/{name}"
@@ -306,6 +306,17 @@ class PyCallArgument(BaseModel):
306
306
 
307
307
  ast_kind: str
308
308
  inferred_type: Optional[str] = None
309
+ # Literal capture (#162): populated only for an `ast.Constant` argument
310
+ # whose value is str/int/float/bool/None, JSON-encoded (`json.dumps`) --
311
+ # decode with `json.loads` to recover the Python constant. `None` for
312
+ # every non-constant argument (and for a Constant of another type, e.g.
313
+ # bytes/complex/Ellipsis).
314
+ value: Optional[str] = None
315
+ # Bare-identifier capture (#162): the `id` of an `ast.Name` argument
316
+ # (e.g. `f(KEY)` -> `"KEY"`) -- ships alongside `value` as the dataflow
317
+ # tier's join point back to the variable's own definitions. `None` for
318
+ # every other argument shape.
319
+ name: Optional[str] = None
309
320
 
310
321
 
311
322
  # BodyNode.arguments forward-references PyCallArgument (defined later);
@@ -470,6 +481,103 @@ class PyExternalSymbol(BaseModel):
470
481
  module: Optional[str] = None # best-effort owning module, e.g. "requests"
471
482
 
472
483
 
484
+ @builder
485
+ class PyConfigKey(BaseModel):
486
+ """A configuration key flattened out of a config-bearing ``PyArtifact``
487
+ (#152). Graph vocabulary stays neutral (label ``ConfigKey``, edge
488
+ ``DEFINES_CONFIG``) -- the ``Py`` prefix here is only the ``PyArtifact``
489
+ naming precedent, not a Python-specific claim. L1 data, identical at
490
+ every analysis level; nested under the owning artifact, containment
491
+ mirrors ``DEFINES_CONFIG``."""
492
+
493
+ id: str = "" # <artifact-id>@key/<dotted.key>
494
+ key: str # dotted path; numeric segments for arrays, e.g. "services.web.ports.0"
495
+ namespace: str # env|yaml|json|toml|ini|properties|dockerfile
496
+ value: Optional[str] = None # populated only when options.artifact_text is on
497
+ span: Optional[Span] = None # into the artifact's source; best-effort for yaml/json/toml
498
+ references: List[str] = [] # raw recognized tokens, order of appearance, deduplicated
499
+
500
+
501
+ @builder
502
+ class PyArtifact(BaseModel):
503
+ """Any non-`.py` project file (config, manifest, CI, container spec, or
504
+ plain data/binary) -- never dropped from the walk. Captured broadly (node
505
+ + verbatim ``source``); *meaning* is extracted narrowly -- only
506
+ ``dependency-manifest`` roles feed ``dependencies`` today. ``id`` is
507
+ language-neutral (``can://artifact/<app>/<path>``)."""
508
+
509
+ id: str = ""
510
+ kind: str = "artifact"
511
+ path: str # repo-relative POSIX path (also the map key)
512
+ format: str # toml|yaml|json|ini|properties|requirements|dockerfile|text|binary
513
+ roles: List[str] = []
514
+ size_bytes: int = 0
515
+ sha256: str = "" # always the full file's hash, even when source is empty
516
+ source: str = "" # the WHOLE file, or "" for binary / when capture is disabled -- never a prefix
517
+ extraction: str = "none" # none|partial|full
518
+ config_keys: List[PyConfigKey] = [] # flattened config keys (#152); [] when not namespace-eligible
519
+
520
+
521
+ @builder
522
+ class PyConfigUseEdge(BaseModel):
523
+ """One resolved config read (#162): a detector-matched call's key
524
+ argument closed on exactly one string literal that matches a declared
525
+ ``PyConfigKey``. ``src`` is the call's GLOBAL ordinal id
526
+ (``<callable-id>@<local-id>``); ``dst`` is the matched ``PyConfigKey.id``
527
+ -- application scope, mirroring ``param_in`` (endpoints span callables/
528
+ artifacts). Superset-monotonic across levels, same additive contract as
529
+ the DDG's ``prov`` widening: literal (``-a 2``+) subset of +dataflow
530
+ (``-a 3``/``-a 4``)."""
531
+
532
+ src: str
533
+ dst: str
534
+ prov: List[Literal["literal", "dataflow"]] = []
535
+
536
+
537
+ @builder
538
+ class PyConfigRead(BaseModel):
539
+ """A detector-matched call whose key did not close on exactly one string
540
+ literal -- first-class so a config read nobody can trace is as visible
541
+ as one that resolves (#162). ``key`` is the decoded literal text only
542
+ when it IS a literal but matches no declared ``PyConfigKey``
543
+ (``reason="undefined-key"``); ``None`` for a key that never closed on a
544
+ literal at all (``reason="non-literal"``). ``prov`` lists every tier
545
+ that was attempted before giving up."""
546
+
547
+ site: str # GLOBAL ordinal id
548
+ callee: str # external id (can://.../@external/<module>/<name>)
549
+ key: Optional[str] = None
550
+ reason: Literal["non-literal", "undefined-key"]
551
+ prov: List[Literal["literal", "dataflow"]] = []
552
+
553
+
554
+ @builder
555
+ class PyDependency(BaseModel):
556
+ """One declared third-party dependency, evidence-tagged via ``prov``."""
557
+
558
+ name: str # PEP 503 normalized
559
+ ecosystem: str = "pypi" # SDK symmetry with purl (#152 rider); the only ecosystem this analyzer emits
560
+ spec: str = ""
561
+ kind: str = "runtime" # runtime|dev|optional|build
562
+ extras: List[str] = []
563
+ declared_in: str = "" # PyArtifact id
564
+ # False for lockfile-only (transitive) dependencies -- pinned in a lock
565
+ # with no manifest declaration (#152 reconciliation).
566
+ direct: bool = True
567
+ locked_version: Optional[str] = None
568
+ provides_imports: List[str] = []
569
+ prov: List[str] = [] # declared|lockfile|installed-metadata|heuristic
570
+
571
+
572
+ @builder
573
+ class PyImportBinding(BaseModel):
574
+ """A top-level import no declared dependency accounts for."""
575
+
576
+ module: str
577
+ bound_to: Optional[str] = None # best-effort distribution name
578
+ prov: List[str] = []
579
+
580
+
473
581
  @builder
474
582
  class PyRepositoryInfo(BaseModel):
475
583
  """Where the analyzed source came from: git provenance captured at analysis time."""
@@ -502,6 +610,11 @@ class PyApplication(BaseModel):
502
610
  # builtin members), keyed by signature. Populated by the analyzer so every
503
611
  # backend (JSON and Neo4j) shares one authoritative external-symbol set.
504
612
  external_symbols: Dict[str, PyExternalSymbol] = {}
613
+ # Non-code artifacts, declared dependencies, and undeclared imports
614
+ # (spec 2026-08-27). L1 data: identical at every analysis level.
615
+ artifacts: Dict[str, PyArtifact] = {}
616
+ dependencies: List[PyDependency] = []
617
+ unresolved_imports: List[PyImportBinding] = []
505
618
  # Coverage/failure record for the entrypoint pass; see PyEntrypointReport (#27).
506
619
  entrypoint_report: PyEntrypointReport = PyEntrypointReport()
507
620
  # Git provenance of the analyzed checkout, captured at analysis time.
@@ -509,6 +622,10 @@ class PyApplication(BaseModel):
509
622
  # Interprocedural parameter-passing edges (formal↔actual); populated at L4.
510
623
  param_in: List[ParamEdge] = []
511
624
  param_out: List[ParamEdge] = []
625
+ # config_use (#162): PY_USES_CONFIG edges + first-class unresolved reads.
626
+ # Literal tier from L2; dataflow tiers widen the set at L3/L4 (additive).
627
+ config_uses: List[PyConfigUseEdge] = []
628
+ config_reads_unresolved: List[PyConfigRead] = []
512
629
 
513
630
 
514
631
  @builder
@@ -1,5 +1,6 @@
1
1
  import ast
2
2
  import hashlib
3
+ import json
3
4
  import os
4
5
  import tokenize
5
6
  from ast import AST, ClassDef
@@ -786,6 +787,16 @@ class SymbolTableBuilder:
786
787
  PyCallArgument(
787
788
  ast_kind=type(arg).__name__,
788
789
  inferred_type=self._infer_type(script, arg.lineno, arg.col_offset),
790
+ # Literal/name capture (#162): value JSON-encoded for a
791
+ # Constant of a JSON-safe type; name for a bare Name --
792
+ # never both, per the AST shapes involved.
793
+ value=(
794
+ json.dumps(arg.value)
795
+ if isinstance(arg, ast.Constant)
796
+ and isinstance(arg.value, (str, int, float, bool, type(None)))
797
+ else None
798
+ ),
799
+ name=arg.id if isinstance(arg, ast.Name) else None,
789
800
  )
790
801
  for arg in node.args
791
802
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: codeanalyzer-python
3
- Version: 1.2.0
3
+ Version: 1.4.0
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
@@ -21,6 +21,7 @@ Requires-Dist: ray==2.0.0; python_version < '3.11'
21
21
  Requires-Dist: requests<3.0.0,>=2.20.0; python_version >= '3.11'
22
22
  Requires-Dist: rich<14.0.0,>=12.6.0; python_version < '3.11'
23
23
  Requires-Dist: rich<15.0.0,>=14.0.0; python_version >= '3.11'
24
+ Requires-Dist: tomli>=2.0; python_version < '3.11'
24
25
  Requires-Dist: typer<1.0.0,>=0.9.0; python_version < '3.11'
25
26
  Requires-Dist: typer<2.0.0,>=0.9.0; python_version >= '3.11'
26
27
  Requires-Dist: typing-extensions<5.0.0,>=4.0.0; python_version < '3.11'
@@ -98,7 +99,9 @@ needs.
98
99
  **interprocedural SDG** (synthetic parameter vertices, `param_in`/`param_out`/`summary`,
99
100
  alias-aware DDG) at level 4 — all built in-process from the stdlib `ast`.
100
101
  - **Neo4j output** — project the analysis into a labeled property graph: a self-contained
101
- `graph.cypher` snapshot, or an **incremental** push to a live database over Bolt.
102
+ `graph.cypher` snapshot, or an **incremental** push to a live database over Bolt. A push is
103
+ **additive by default** and never deletes: `--eager` is what permits it to remove declarations
104
+ and edges the source no longer has.
102
105
  - **Versioned schema** — a machine-readable, version-stamped Neo4j schema contract (`--emit schema`),
103
106
  checked in as `schema.neo4j.json` (`2.0.0`) and shipped with every release.
104
107
  - **Incremental cache** — per-file results are cached under `.codeanalyzer`; `--lazy` (default)
@@ -299,7 +302,19 @@ $ canpy --help
299
302
  │ --eager --lazy Enable eager or │
300
303
  │ lazy analysis. │
301
304
  │ Defaults to │
302
- │ lazy.
305
+ │ lazy. Also gates
306
+ │ every │
307
+ │ destructive step │
308
+ │ of a '--emit │
309
+ │ neo4j' Bolt │
310
+ │ push: a lazy │
311
+ │ push only adds │
312
+ │ and updates, an │
313
+ │ eager one also │
314
+ │ removes │
315
+ │ declarations and │
316
+ │ edges the source │
317
+ │ no longer has. │
303
318
  │ [default: lazy] │
304
319
  │ --skip-tests --include-tests Skip test files │
305
320
  │ in analysis. │
@@ -315,6 +330,16 @@ $ canpy --help
315
330
  │ environment │
316
331
  │ instead. │
317
332
  │ [default: venv] │
333
+ │ --resolve-instal… Additionally │
334
+ │ bind imports via │
335
+ │ the project │
336
+ │ venv's installed │
337
+ │ metadata │
338
+ │ (*.dist-info); │
339
+ │ output becomes │
340
+ │ machine-depende… │
341
+ │ (prov: │
342
+ │ installed-metad… │
318
343
  │ --file-name <path> Analyze only the │
319
344
  │ specified file │
320
345
  │ (relative to │
@@ -346,6 +371,22 @@ $ canpy --help
346
371
  │ shipped rules. A │
347
372
  │ malformed file │
348
373
  │ is an error. │
374
+ │ --artifact-text --no-artifact-… Capture verbatim │
375
+ │ `source` text on │
376
+ │ discovered │
377
+ │ artifacts. │
378
+ │ `source` is the │
379
+ │ whole file; │
380
+ │ --no-artifact-t… │
381
+ │ empties it │
382
+ │ everywhere │
383
+ │ (inventory │
384
+ │ unchanged). │
385
+ │ sha256/size_byt… │
386
+ │ always reflect │
387
+ │ the full file. │
388
+ │ [default: │
389
+ │ artifact-text] │
349
390
  │ --help Show this │
350
391
  │ message and │
351
392
  │ exit. │
@@ -517,14 +558,29 @@ A **callable** (function or method) carries its own CPG, keyed by node id:
517
558
  }
518
559
  ```
519
560
 
561
+ The application envelope also contains three substrate sections:
562
+
563
+ - **`artifacts`** — discovered non-code files (manifests, configs, Docker files, CI workflows,
564
+ packaging files, scripts, docs, and legal files) with extraction status (`none`, `partial`, or
565
+ `full`; default `none`), keyed by relative path; each artifact carries the
566
+ `can://artifact/<app>/<path>` id namespace. Config files carry extracted `config_keys`
567
+ (keys, values, namespaces, and references) and `DEFINES_CONFIG` Neo4j edges.
568
+ - **`dependencies`** — declared packages with kind (`runtime`/`dev`/`optional`/`build`), spec,
569
+ locked version, and provenance (`prov`): where each binding came from (manifest file, lock file,
570
+ installed metadata).
571
+ - **`unresolved_imports`** — modules imported but not resolvable in the declared dependency set,
572
+ one entry per module.
573
+
520
574
  Notable properties:
521
575
 
522
576
  - **Durable `can://` ids** identify every node at callable granularity and above
523
577
  (`can://python/<app>/<file>/<callable-sig>`); nodes below a callable use ordinal ids
524
578
  (`@entry`, `@exit`, `line:col`, `@formal_in:N`, `line:col/actual_in:N`).
525
579
  - **`source` lives once per module**; every node's text is the `module.source[span.bytes]` slice.
526
- - **Cross-function edges** — `call_graph`, `param_in`, `param_out` — live at **application** scope;
580
+ - **Cross-function edges** — `call_graph`, `param_in`, `param_out`, `config_uses` — live at **application** scope;
527
581
  the intraprocedural `cfg`/`cdg`/`ddg` and the `summary` edges live **on the callable**.
582
+ `config_uses` resolve from call-site key arguments to `ConfigKey` nodes; unresolved reads
583
+ go to `config_reads_unresolved`.
528
584
  - **No dangling endpoints** — every `call_graph` `src`/`dst` joins the id space: declared
529
585
  callables by their tree id, imported/builtin targets by a `…/@external/<module>/<name>` id
530
586
  homed in `application.external_symbols`.
@@ -545,9 +601,13 @@ binary format).
545
601
 
546
602
  ### Neo4j graph
547
603
 
548
- `--emit neo4j` projects the same schema v2.0.0 analysis into a labeled property graph. Every node
549
- label is `Py`-prefixed and every relationship type is `PY_`-prefixed (e.g. `:PyClass`, `PY_CALLS`)
550
- so multiple language analyzers can share one database without label or relationship-type collisions.
604
+ `--emit neo4j` projects the same schema v2.0.0 analysis into a labeled property graph. Every
605
+ Python-specific node label is `Py`-prefixed and every Python-specific relationship type is
606
+ `PY_`-prefixed (e.g. `:PyClass`, `PY_CALLS`) so multiple language analyzers can share one database
607
+ without label or relationship-type collisions. The one deliberate exception is the language-neutral
608
+ `Artifact`/`Package` subgraph (non-code files and third-party dependencies) — those nodes carry no
609
+ `Py` prefix, since they are meant as cross-language merge targets: a sibling-language analyzer over
610
+ the same repo should land on the same `Artifact`/`Package` nodes, not a per-language duplicate.
551
611
  Declarations are keyed by their **`can://` id** under a shared `:PySymbol` label; calls, imports,
552
612
  inheritance, decorators, and call sites are relationships. At `-a 3`/`-a 4` the projection gains the
553
613
  **CPG overlay** — `:PyBodyNode` nodes (statements, and at level 4 the parameter vertices) wired by
@@ -608,6 +668,56 @@ runtime (Docker or Podman) and is enabled with an environment variable:
608
668
  RUN_CONTAINER_TESTS=1 uv run pytest test/test_neo4j_bolt.py -s
609
669
  ```
610
670
 
671
+ ## Graph query cookbook
672
+
673
+ Example Cypher over the projected graph (`--emit neo4j`, then load `graph.cypher` or push via Bolt).
674
+
675
+ ```cypher
676
+ // who calls this function? (direct callers)
677
+ MATCH (c:PyCallable)-[:PY_CALLS]->(t:PyCallable {name: "process_payment"})
678
+ RETURN c.id
679
+
680
+ // every callable that reaches a given library, via the external ghosts
681
+ MATCH (c:PyCallable)-[:PY_CALLS]->(e:PyExternal)
682
+ WHERE e.id CONTAINS "/@external/requests/"
683
+ RETURN DISTINCT c.id
684
+
685
+ // entrypoints and the frameworks that invoke them
686
+ MATCH (m:PyCallable {is_entrypoint: true})
687
+ RETURN m.id, m.entrypoint_frameworks
688
+
689
+ // data dependences into one statement (level 3+)
690
+ MATCH (s:PyBodyNode {id: $stmt})<-[d:PY_DDG]-(src:PyBodyNode)
691
+ RETURN src.id, d.var, d.prov
692
+
693
+ // interprocedural flow through a parameter (level 4)
694
+ MATCH (a:PyBodyNode)-[:PY_PARAM_IN]->(f:PyBodyNode)
695
+ WHERE f.id STARTS WITH "can://python/myapp/src/api.py"
696
+ RETURN a.id, f.id
697
+ ```
698
+
699
+ Artifact and dependency queries (1.3.0+):
700
+
701
+ ```cypher
702
+ // all container/orchestration configs in the app
703
+ MATCH (a:PyApplication)-[:HAS_ARTIFACT]->(f:Artifact)
704
+ WHERE any(r IN f.roles WHERE r IN ["service-topology", "container-image"])
705
+ RETURN f.id, f.format
706
+
707
+ // every callable that reaches code from a declared package
708
+ MATCH (c:PyCallable)-[:PY_CALLS]->(:PyExternal)<-[:PY_PROVIDES]-(p:Package {id: "pkg:pypi/requests"})
709
+ RETURN c.id
710
+
711
+ // undeclared imports (dependency hygiene)
712
+ MATCH (a:PyApplication)-[u:PY_UNRESOLVED_IMPORT]->(e:PyExternal)
713
+ WHERE NOT (e)<-[:PY_PROVIDES]-(:Package)
714
+ RETURN e.id, u.prov
715
+
716
+ // which lock file pins this package, and to what
717
+ MATCH (f:Artifact)-[l:LOCKS]->(p:Package {id: "pkg:pypi/numpy"})
718
+ RETURN f.id, l.version
719
+ ```
720
+
611
721
  ## License
612
722
 
613
723
  Apache 2.0 — see [LICENSE](./LICENSE).
@@ -1,12 +1,19 @@
1
1
  codeanalyzer/__init__.py,sha256=BZ3Kuwl-F_F-8H8cepLnVJ4Ku4NNUjjqg0Y6ujPQSsI,108
2
- codeanalyzer/__main__.py,sha256=hmuIKxpW7TFfGaBGb1HiHCFS02dCQxVhG7FkruXECWQ,14954
3
- codeanalyzer/core.py,sha256=vkU8djqKmyX4mXmb5rOz3oRjlMWYjMB7dWB_toIHnu4,42140
2
+ codeanalyzer/__main__.py,sha256=o5_9ct61l3T7ryIsag8bz304NabVV-el_ooGD8tnbhA,15968
3
+ codeanalyzer/core.py,sha256=tk_3dz81ECXXv8CEciWTIVfBAHHIfTVCsZte1GAZ080,46620
4
4
  codeanalyzer/provenance.py,sha256=DT-DqwdVwO7g-GyK3sC0_4vDNCUjZYEY1fyYCt-7VRM,2306
5
5
  codeanalyzer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ codeanalyzer/artifacts/__init__.py,sha256=317sEeZLS1AYsfYDYIk7tLR3AdDFwWw_cmkeZDabkJo,906
7
+ codeanalyzer/artifacts/config_keys.py,sha256=ovwptAErLYutlCzUwvyim2kH6-6vUKxuRcBV2KJS71Y,26843
8
+ codeanalyzer/artifacts/config_use.py,sha256=1-jGacW249dwF7b6DOrTFuJ7sA5Ho9khgrgZqND0nro,27173
9
+ codeanalyzer/artifacts/config_use_rules.yml,sha256=fNgI6IceOsj78LYmgoDH-vQ4-Mfb2ZFGKIQhLuoL4ik,1483
10
+ codeanalyzer/artifacts/dependencies.py,sha256=h_-XV5KhrT-1Ytguw0c4fyI9zSFzn9Aj7kR66omvL3M,10853
11
+ codeanalyzer/artifacts/discovery.py,sha256=cUVRSdV82G2hVGhkRGV7u24-tEAxUBmH9nkTg24ur0Y,5968
12
+ codeanalyzer/artifacts/parsers.py,sha256=xOjC53tT0Mv0k7ONGwzl5XUvpBLnZlEcGmyrX5DS45k,9035
6
13
  codeanalyzer/dataflow/__init__.py,sha256=HCNOH24rAGLUMG94N9aC-2SsAWSntk3uys7e39ipU5o,1725
7
14
  codeanalyzer/dataflow/access_paths.py,sha256=wC8Q9qD-RZzkoFWMVvu_6uNNmYP8z48OGp9h9v3F1d4,23623
8
15
  codeanalyzer/dataflow/alias.py,sha256=ZYKY0DiR3GHv6YJr7C001Lode9rZsk6-gxdomUyIvwg,3928
9
- codeanalyzer/dataflow/builder.py,sha256=sCngN3MWfCbHteSHiue8l7AUVQNttETJInsgVMy_xkY,31317
16
+ codeanalyzer/dataflow/builder.py,sha256=KiISa2bIuBf_0N0v_PzlgMGm0sFtMICEwA-Y6DFXiM4,32687
10
17
  codeanalyzer/dataflow/cfg.py,sha256=u5YXJjAaDshdgv-9kWWITbBJFP-MwXKq6hbNh0fhDm8,25307
11
18
  codeanalyzer/dataflow/defuse.py,sha256=LrX1ToOZzR79NlAGg5T647UAFkpiEqEnT7t0K5RXOiI,4377
12
19
  codeanalyzer/dataflow/dominance.py,sha256=X7Ki1QRdVqaseYsJtiUL7m9MbcC2WHEv9b8bczSLFUA,5086
@@ -14,9 +21,9 @@ codeanalyzer/dataflow/identity.py,sha256=WAIal6XchmQqdnXbvbEgu8J6vJdXNRdie1KHz1v
14
21
  codeanalyzer/dataflow/pdg.py,sha256=1Bm7AnoRqXBryZulII2idPw0feV8eZQ1VqqprQ8PW-g,3731
15
22
  codeanalyzer/dataflow/scalpel_oracle.py,sha256=FxRadKrTWar0VKHyQJM40n3cq25sld3Sj4lMdOm5NFk,11494
16
23
  codeanalyzer/dataflow/scc.py,sha256=Doa_0-5f3agCu_5UmeEDlCUErg34TtniKIv8Uqd7Jiw,3493
17
- codeanalyzer/dataflow/sdg.py,sha256=sTUUlYMB9uTKg9Yxiw-ScTBXogaQKcrSP6vksKXG14M,17841
24
+ codeanalyzer/dataflow/sdg.py,sha256=taDXkIg0BZUtDEJUjRJB_dxrFl6tKNOUdFyj0zCiso0,18533
18
25
  codeanalyzer/dataflow/slicing.py,sha256=lWZ7jHhlR8m7rECWJQXvwfs5GNZeJY55Cud3Ji5UbNU,3654
19
- codeanalyzer/dataflow/summaries.py,sha256=DOgesiymL6WgePrtkQBiS_Rd7SuCr3McD4Eq05Msb50,8023
26
+ codeanalyzer/dataflow/summaries.py,sha256=TLtc5h4bLBC4lViuMhMlEp5rp_nBpDPOl4_wfBuRUY4,9210
20
27
  codeanalyzer/dataflow/syntactic.py,sha256=AbHyXjKX_1xkGgKH48BpXYCWBauActGUwSMF_OD-uys,1124
21
28
  codeanalyzer/dataflow/scalpel/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
22
29
  codeanalyzer/dataflow/scalpel/README.md,sha256=YN-LxqYYDekIdhx39AG28sg9UySMmqvLQJivTvR2Fz8,1543
@@ -38,34 +45,34 @@ codeanalyzer/entrypoints/rules.yml,sha256=rgDglVOcUNXnQ5FXLMfnJbfI7xHRiRmegTP5bm
38
45
  codeanalyzer/jedi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
46
  codeanalyzer/jedi/jedi.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
47
  codeanalyzer/neo4j/__init__.py,sha256=8Ei6uThTOqmul6GhnKoGOjLXJZbyDwF5Jo-8I8NxnAk,1574
41
- codeanalyzer/neo4j/bolt.py,sha256=qEBtQlBjaMPpLQPUCOAR9jEqLxpXYJG5mtxdYAhjtMI,10134
48
+ codeanalyzer/neo4j/bolt.py,sha256=wobEBSQn5z9uCER3fNtTl98Q1z5WuXG-O1rPRoFwFWI,11949
42
49
  codeanalyzer/neo4j/cypher.py,sha256=a7YSmxxDbPcYc5gI4TW9sM6_WOE3RgLXTGBR9K8W8kw,5321
43
- codeanalyzer/neo4j/emit.py,sha256=QdrZWG3_IQHMcKCX4bFINpXvqZU2Qfsi9beIJovC2p4,3493
44
- codeanalyzer/neo4j/project.py,sha256=LFj8O_2DYA_dvMTbSYK_PYxmnP2UJ4h_3J8rCIoK1w8,25927
50
+ codeanalyzer/neo4j/emit.py,sha256=OBCO77TDTaNpqk9Di3JIQzBouLpHPdgoXuPSs44iJuU,3587
51
+ codeanalyzer/neo4j/project.py,sha256=U-2ZurR3aYFY0k8WGpEIYTE4YEET2pJeOyxqb9i_Xyo,35044
45
52
  codeanalyzer/neo4j/rows.py,sha256=med0XFa63PPUVUhJMq1TtVcJxgaVW39sgxBRZJDIJ_w,7811
46
- codeanalyzer/neo4j/schema.py,sha256=kx134hxG_Uv6b5PkHFfkX7L1STpxSaW4pGTDe_Wruf0,10768
53
+ codeanalyzer/neo4j/schema.py,sha256=88F_biHRhd4NV1RSNvFCwLa062gKJb12_P_-vV6L-rE,15379
47
54
  codeanalyzer/options/__init__.py,sha256=6NewN0a-1HAEgKcxQjYyVn2WEDLrhax8h3WLgZddeqI,94
48
- codeanalyzer/options/options.py,sha256=5gmKNxb51vWmIknE4e8kyT9nJRchL0VYspZxe_PAsws,1389
55
+ codeanalyzer/options/options.py,sha256=2jDCcs74iSEOhz90LoRGts6PC8yV9IDPVxnLPNmonOA,1609
49
56
  codeanalyzer/schema/__init__.py,sha256=hIyz02abUJNPW8yUgguaeKflZjTmOZWbDiKICNBD7yk,4141
50
57
  codeanalyzer/schema/assign_ids.py,sha256=pQHluLaO5a6hFREp3vjVRsUeAfTYSJ95RXS9TZvnoys,1590
51
58
  codeanalyzer/schema/call_graph_ids.py,sha256=mWAhJDBsW8i-siJiINOHCXEm4qM6F_5se9-HuHWIFqU,568
52
- codeanalyzer/schema/ids.py,sha256=G5NGPjJ3UdJ1k0opy2MrvgWRWNBZgKU1PwY1MR6hDT4,829
59
+ codeanalyzer/schema/ids.py,sha256=aOzsgVaOo6x72dnRgNxlnt6b5wbZzhTm0JOz6pdI57I,1672
53
60
  codeanalyzer/schema/l1_body.py,sha256=5Su347kwAPNflJDf7SvBR3sNXx9PVdGEml2pOpQCwo0,1684
54
61
  codeanalyzer/schema/l2_callees.py,sha256=CTcBeGoO04DstDC6h-1sHMbbIrHDEOMxP01U9VLBcfc,2327
55
- codeanalyzer/schema/py_schema.py,sha256=VwwRqr_jFolkbRKi8ytiwUScKZmscJBZvh16Y2tDbII,18449
62
+ codeanalyzer/schema/py_schema.py,sha256=5G8K6uqBopU5iLwlUW30AE5A8jgTEdNaQmOeizhccag,23885
56
63
  codeanalyzer/semantic_analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
64
  codeanalyzer/semantic_analysis/call_graph.py,sha256=6YEB_wTn5-oQYLrbIhJYE0BsHl4fpWPoy5Hwd9mTnGc,11918
58
65
  codeanalyzer/semantic_analysis/defuse_linker.py,sha256=bSn1rCun28OQqSd2NOc9aVBSm47Gt9Iul4r_gwfqO1w,64930
59
66
  codeanalyzer/syntactic_analysis/__init__.py,sha256=EUQkJEh6wHjWx2qTTKbTbUgwSbfKeNieKHNy7RknVXA,476
60
67
  codeanalyzer/syntactic_analysis/exceptions.py,sha256=whs_n0vIu655Jkk1a7iOoXY6iIca4pZqJnU40V9Ejaw,537
61
68
  codeanalyzer/syntactic_analysis/import_resolver.py,sha256=Q8noZwSdDNt4P4NMqDTB9FaS-M0_d4ASK9GnJop9MDI,2751
62
- codeanalyzer/syntactic_analysis/symbol_table_builder.py,sha256=2bp9S5Z9Atx0Ovd70nMzAbutoNx_FD0VYBY397GAAVo,47343
69
+ codeanalyzer/syntactic_analysis/symbol_table_builder.py,sha256=eTknBDlUuuQd3JEwbRtJt5pGVU89kOnzfmT4D5J_GKQ,47917
63
70
  codeanalyzer/utils/__init__.py,sha256=hC6VWdR5rerSqBxzu9KQHTASWqwrrYJv-CMDwrTlzkc,137
64
71
  codeanalyzer/utils/logging.py,sha256=Fw0tattPAOMs3o0JMjjXhRVLIF64f-SCcygUXF9jqeg,904
65
72
  codeanalyzer/utils/progress_bar.py,sha256=C9JtzVdd10lIxTv-KA6PebqjKWueC_vMGwVzAtHuHIw,2818
66
- codeanalyzer_python-1.2.0.dist-info/METADATA,sha256=Un9ZuyLWDpzfB_CNuAXiXGvM8eN0HQmr_0r2jGsBqqA,36319
67
- codeanalyzer_python-1.2.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
68
- codeanalyzer_python-1.2.0.dist-info/entry_points.txt,sha256=v4Vux0Nnx7sOntVk_CH7W9RX6SkIkvR1FQYq73oVlCQ,105
69
- codeanalyzer_python-1.2.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
70
- codeanalyzer_python-1.2.0.dist-info/licenses/NOTICE,sha256=MdVkNYqHJ20on2FmWvgD4WpMsX5mir33xdyPvTXd0A0,1223
71
- codeanalyzer_python-1.2.0.dist-info/RECORD,,
73
+ codeanalyzer_python-1.4.0.dist-info/METADATA,sha256=DJKj-64VCcSuUoxUbwsesDi7jSkBv69YSrsePcgAzGM,42786
74
+ codeanalyzer_python-1.4.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
75
+ codeanalyzer_python-1.4.0.dist-info/entry_points.txt,sha256=v4Vux0Nnx7sOntVk_CH7W9RX6SkIkvR1FQYq73oVlCQ,105
76
+ codeanalyzer_python-1.4.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
77
+ codeanalyzer_python-1.4.0.dist-info/licenses/NOTICE,sha256=MdVkNYqHJ20on2FmWvgD4WpMsX5mir33xdyPvTXd0A0,1223
78
+ codeanalyzer_python-1.4.0.dist-info/RECORD,,