codeanalyzer-python 1.4.1__py3-none-any.whl → 1.5.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.
codeanalyzer/core.py CHANGED
@@ -19,6 +19,7 @@ from codeanalyzer.schema import (
19
19
  model_validate_json,
20
20
  )
21
21
  from codeanalyzer.schema.assign_ids import assign_ids
22
+ from codeanalyzer.schema.ids import external_id
22
23
  from codeanalyzer.schema.l1_body import populate_l1_body
23
24
  from codeanalyzer.schema.l2_callees import backfill_callees
24
25
  from codeanalyzer.schema.call_graph_ids import reidentify_call_graph
@@ -564,8 +565,7 @@ class Codeanalyzer:
564
565
  if sig in sig_to_id:
565
566
  continue
566
567
  module, name = sig.rsplit(".", 1) if "." in sig else (None, sig)
567
- ext_id = f"{app_id}/@external/{module}/{name}" if module else \
568
- f"{app_id}/@external/{name}"
568
+ ext_id = external_id(app_id, module, name)
569
569
  sig_to_id[sig] = ext_id
570
570
  externals[ext_id] = PyExternalSymbol(
571
571
  id=ext_id, name=name, module=module
@@ -41,8 +41,8 @@ Nodes are MERGE-upserted, never blindly deleted, so a declaration another
41
41
  MERGE-only.
42
42
 
43
43
  **Every destructive statement is scoped on the ``can://`` id prefix** (#173). The id is a
44
- path — ``can://python/<app>/<file>/...`` — so ``id = <module-id> OR id STARTS WITH
45
- <module-id> + '/'`` is containment, and it is one language, one application and one
44
+ path — ``can://<app>/python/<file>/...`` — so ``id = <module-id> OR id STARTS WITH
45
+ <module-id> + '/'`` is containment, and it is one application, one language and one
46
46
  module at once. That is what neither a label anchor nor the retired ``_module`` property
47
47
  could give: two python applications sharing ``src/foo.py`` carry identical labels and an
48
48
  identical file key, and only the id tells them apart. ``:PyCanNode`` anchors the predicate
@@ -115,10 +115,16 @@ def bolt_writer(rows: GraphRows, cfg: BoltConfig, full_run: bool, eager: bool =
115
115
  s.run(stmt)
116
116
 
117
117
  # The application anchor. Every destructive statement below is scoped to
118
- # ``can://python/<app>/``; an empty application id is refused up front rather
119
- # than becoming ``STARTS WITH ''`` (every node in the database).
118
+ # ``can://<app>/``; an empty application is refused up front rather than
119
+ # becoming ``STARTS WITH ''`` (every node in the database). The root row is
120
+ # keyed on its ``can://`` id now, so the name comes off its props — reading
121
+ # ``n.value`` here would build ``can://can://<app>/``.
120
122
  app_name = next(
121
- (n.value for n in rows.nodes if n.labels and n.labels[0] == "PyApplication"),
123
+ (
124
+ n.props.get("name")
125
+ for n in rows.nodes
126
+ if n.labels and n.labels[0] == "PyApplication"
127
+ ),
122
128
  None,
123
129
  )
124
130
  app_prefix = application_prefix(app_name)
@@ -195,7 +201,7 @@ def bolt_writer(rows: GraphRows, cfg: BoltConfig, full_run: bool, eager: bool =
195
201
  _upsert_edges(session, neo4j, edges)
196
202
 
197
203
  # 6. orphan prune — only safe on a full run (a targeted run can't tell deleted from untargeted).
198
- # Scoped to ``can://python/<app>/`` so a full run for application B never deletes
204
+ # Scoped to ``can://<app>/`` so a full run for application B never deletes
199
205
  # application A's modules from a shared database — even when both are python and
200
206
  # share a module path.
201
207
  if full_run and eager:
@@ -38,6 +38,7 @@ from codeanalyzer.neo4j.rows import (
38
38
  cypher_value,
39
39
  )
40
40
  from codeanalyzer.neo4j.schema import CONSTRAINTS, INDEXES
41
+ from codeanalyzer.schema.ids import application_id
41
42
 
42
43
  BATCH = 500
43
44
 
@@ -68,17 +69,24 @@ def render_cypher(rows: GraphRows, app_name: str) -> str:
68
69
 
69
70
 
70
71
  def _wipe(app_name: str) -> str:
71
- """Everything under ``can://python/<app>/`` plus the application anchor (#173).
72
- Scoped by id prefix, so it is one language and one application by construction —
73
- a second python app sharing a module path, a sibling analyzer's graph, and the
74
- cross-language :Artifact / :Package nodes are all outside it."""
72
+ """The application root by equality plus everything under ``can://<app>/`` (#173).
73
+ Scoped by id prefix, so it is one application by construction — a second python
74
+ app sharing a module path, and a sibling analyzer's :Py* graph, are outside it.
75
+ :Package nodes (``pkg:`` purls) stay outside too.
76
+
77
+ Two things moved with the app-outermost grammar. The root is matched by its
78
+ ``can://<app>`` id rather than by the free-text ``--app-name``, so two apps
79
+ sharing a name no longer wipe each other's root; and the app's :Artifact /
80
+ :ConfigKey nodes are now *inside* the prefix, so the snapshot rebuilds them
81
+ instead of leaving them to accumulate. That is deliberate, and it is the one
82
+ behavioural widening here: a cross-language edge into a shared :Artifact is
83
+ dropped by a python snapshot and restored on that analyzer's next push."""
75
84
  prefix = cypher_value(application_prefix(app_name))
76
- name = cypher_value(app_name)
85
+ app_id = cypher_value(application_id(app_name))
77
86
  return "\n".join(
78
87
  [
79
- f"MATCH (x:{CAN_NODE}) WHERE x.id STARTS WITH {prefix}",
88
+ f"MATCH (x:{CAN_NODE}) WHERE x.id = {app_id} OR x.id STARTS WITH {prefix}",
80
89
  "CALL { WITH x DETACH DELETE x } IN TRANSACTIONS OF 1000 ROWS;",
81
- f"MATCH (a:PyApplication {{name: {name}}}) DETACH DELETE a;",
82
90
  ]
83
91
  )
84
92
 
@@ -49,7 +49,7 @@ from codeanalyzer.schema import (
49
49
  PyVariableDeclaration,
50
50
  )
51
51
  from codeanalyzer.schema import model_dump
52
- from codeanalyzer.schema.ids import application_id, global_ordinal, purl_pypi
52
+ from codeanalyzer.schema.ids import application_id, external_id, global_ordinal, purl_pypi
53
53
  from codeanalyzer.schema.py_schema import PyDecorator
54
54
 
55
55
 
@@ -60,12 +60,17 @@ def project(app: PyApplication, app_name: str, sig_to_id: dict,
60
60
  passes it through so the :PyApplication node carries it as props."""
61
61
  b = RowBuilder()
62
62
 
63
+ # Keyed on the ``can://<app>`` id, not on ``--app-name``: two applications
64
+ # analyzed under the same free-text name used to MERGE onto one root, with
65
+ # no diagnostic. ``name`` survives as a display property.
63
66
  app_ref = b.node(
64
67
  ["PyApplication"],
65
- "name",
66
- app_name,
68
+ "id",
69
+ application_id(app_name),
67
70
  prune(
68
71
  {
72
+ "id": application_id(app_name),
73
+ "name": app_name,
69
74
  "schema_version": SCHEMA_VERSION,
70
75
  "analyzer_name": analyzer.name if analyzer else None,
71
76
  "analyzer_version": analyzer.version if analyzer else None,
@@ -290,7 +295,7 @@ def _import_ghost(b: RowBuilder, app_can_id: str, name: str) -> NodeRef:
290
295
  projected too, both rows collapse onto this one node — correctly, since
291
296
  they name the same real-world symbol."""
292
297
  return b.node(
293
- ["PySymbol", "PyExternal"], "id", f"{app_can_id}/@external/{name}", {"name": name}
298
+ ["PySymbol", "PyExternal"], "id", external_id(app_can_id, None, name), {"name": name}
294
299
  )
295
300
 
296
301
 
@@ -503,7 +508,7 @@ def _external_ghost(b: RowBuilder, app_can_id: str, signature: str) -> NodeRef:
503
508
  ``_home_external_symbols`` uses — ``<app>/@external/<module>/<name>`` — so it
504
509
  sits inside the application prefix (#173) and MERGEs with a homed twin."""
505
510
  module, name = signature.rsplit(".", 1) if "." in signature else (None, signature)
506
- ext_id = f"{app_can_id}/@external/{module}/{name}" if module else f"{app_can_id}/@external/{name}"
511
+ ext_id = external_id(app_can_id, module, name)
507
512
  return b.node(["PySymbol", "PyExternal"], "id", ext_id, prune({"name": name, "module": module}))
508
513
 
509
514
 
@@ -28,6 +28,8 @@ from __future__ import annotations
28
28
  from dataclasses import dataclass, field
29
29
  from typing import Dict, List, Optional, Union
30
30
 
31
+ from codeanalyzer.schema.ids import SCHEME, application_id
32
+
31
33
  # A property value: a primitive, or a homogeneous list of primitives.
32
34
  Scalar = Union[str, int, float, bool]
33
35
  Prop = Union[Scalar, List[str], List[int], List[float], List[bool]]
@@ -57,28 +59,37 @@ class NodeRow:
57
59
  module: Optional[str] = None
58
60
 
59
61
 
60
- # The marker label on every node keyed by a ``can://python/`` id (#173). It is an
62
+ # The marker label on every node keyed by a ``can://`` id (#173). It is an
61
63
  # INDEX ANCHOR, nothing more: Neo4j property indexes are label-scoped, so the
62
64
  # prefix predicate ``id STARTS WITH $p`` needs a label to seek on. Safety comes
63
- # from the prefix, which carries language, application and module.
65
+ # from the prefix, which carries application, language and module.
66
+ #
67
+ # The test is the SCHEME, never a language segment: since the app moved outermost
68
+ # an id no longer begins with the language, and ``can://python/`` now means "the
69
+ # application is called python". Testing that here would have quietly stripped the
70
+ # marker off every graph but one, taking the destructive statements' index — and
71
+ # their reach — with it.
64
72
  CAN_NODE = "PyCanNode"
65
- _PY_CAN_PREFIX = "can://python/"
66
73
 
67
74
 
68
75
  def descendant_prefix(can_id: str) -> str:
69
76
  """The prefix that matches a node's descendants and nothing else. The separator
70
- is the point: ``can://python/app/src/foo.py`` is also a prefix of
71
- ``can://python/app/src/foo.pyX``, so descendants match on ``id + '/'`` and the
77
+ is the point: ``can://app/python/src/foo.py`` is also a prefix of
78
+ ``can://app/python/src/foo.pyX``, so descendants match on ``id + '/'`` and the
72
79
  node itself by equality."""
73
80
  return f"{can_id}/"
74
81
 
75
82
 
76
83
  def application_prefix(app_name: Optional[str]) -> str:
77
- """``can://python/<app>/`` — the scope of every destructive statement. Refuses an
78
- empty application: ``STARTS WITH ''`` would match every node in the database."""
84
+ """``can://<app>/`` — the scope of every destructive statement. Refuses an
85
+ empty application: ``STARTS WITH ''`` would match every node in the database.
86
+
87
+ Since the app is the outermost segment this now covers the application's
88
+ artifacts and config keys too, which the old language-first prefix left
89
+ outside every scope and so never cleaned up."""
79
90
  if not app_name:
80
91
  raise ValueError("neo4j: refusing a destructive statement without an application id")
81
- return descendant_prefix(f"{_PY_CAN_PREFIX}{app_name}")
92
+ return descendant_prefix(application_id(app_name))
82
93
 
83
94
 
84
95
  @dataclass
@@ -131,7 +142,7 @@ class RowBuilder:
131
142
  node_id = f"{labels[0]} {value}"
132
143
  props = dict(props)
133
144
  module = props.pop("_module", None) # lifted off the graph (#173)
134
- if key_prop == "id" and value.startswith(_PY_CAN_PREFIX) and CAN_NODE not in labels:
145
+ if key_prop == "id" and value.startswith(SCHEME) and CAN_NODE not in labels:
135
146
  labels = [*labels, CAN_NODE]
136
147
  existing = self._nodes.get(node_id)
137
148
  if existing is not None:
@@ -57,7 +57,7 @@ class RelType:
57
57
 
58
58
 
59
59
  # Labels layered onto a node in addition to its primary/specific label.
60
- # ``PyCanNode`` (#173) rides every node keyed by a ``can://python/`` id — an index
60
+ # ``PyCanNode`` (#173) rides every node keyed by a ``can://`` id — an index
61
61
  # anchor for the prefix-scoped destructive statements (see ``rows.CAN_NODE``).
62
62
  MARKER_LABELS: List[str] = ["PyCanNode"]
63
63
 
@@ -68,8 +68,9 @@ NODE_LABELS: List[NodeLabel] = [
68
68
  NodeLabel(
69
69
  "PyApplication",
70
70
  "PyApplication",
71
- "name",
71
+ "id",
72
72
  {
73
+ "id": "string",
73
74
  "name": "string",
74
75
  "schema_version": "string",
75
76
  "analyzer_name": "string",
@@ -1,17 +1,30 @@
1
1
  """Canonical `can://` id construction for schema v2 (durable ids, ≥ callable).
2
2
  Ordinal ids (< callable) are `ordinal_id(callable_id, tag)`. Pure functions;
3
- ids are opaque handles (the <file> segment itself contains '/')."""
3
+ ids are opaque handles (the <file> segment itself contains '/').
4
+
5
+ The **application is the outermost segment** and the language sits inside it:
6
+ ``can://<app>/python/<file>/<type>/<callable-sig>``. So ``can://<app>`` is a
7
+ prefix of every id this analyzer mints for that application — code, externals
8
+ and artifacts alike — which is what the prefix-scoped destructive statements
9
+ (#173) rely on. Nothing may be identified by its *language* prefix any more:
10
+ an application named ``python`` mints ``can://python/python/...``, so a test
11
+ for ``can://python/`` no longer means "a python id"; test the scheme instead."""
4
12
  from __future__ import annotations
5
- from typing import List
13
+ from typing import List, Optional
6
14
 
7
- _SCHEME = "can://python"
15
+ SCHEME = "can://"
16
+
17
+ # This analyzer's language segment, which sits INSIDE the app rather than above it.
18
+ LANG = "python"
8
19
 
9
20
  def application_id(app_name: str) -> str:
10
- return f"{_SCHEME}/{app_name}"
21
+ """``can://<app>`` — the application root, and the prefix every id below it shares."""
22
+ return f"{SCHEME}{app_name}"
11
23
 
12
24
  def module_id(app_name: str, file_key: str) -> str:
25
+ """``can://<app>/python/<relative-file-key>`` (separators normalized to ``/``)."""
13
26
  rel = file_key.replace("\\", "/").lstrip("./")
14
- return f"{application_id(app_name)}/{rel}"
27
+ return f"{application_id(app_name)}/{LANG}/{rel}"
15
28
 
16
29
  def child_id(parent_id: str, segment: str) -> str:
17
30
  return f"{parent_id}/{segment}"
@@ -23,6 +36,22 @@ def ordinal_id(callable_id: str, tag: str) -> str:
23
36
  return f"{callable_id}@{tag}"
24
37
 
25
38
 
39
+ def external_id(app_id: str, module: Optional[str], name: str) -> str:
40
+ """``can://<app>/@external/<module>/<name>`` — the home of a call-graph
41
+ endpoint that is not declared in the symbol table (an imported library or
42
+ builtin member). ``module`` is ``None`` for a dot-less signature, which drops
43
+ the segment.
44
+
45
+ Language-NEUTRAL, like ``artifact``: ``@external`` sits in the position the
46
+ language occupies for code nodes, so sibling analyzers over the same ``<app>``
47
+ name a library symbol identically and it is one node in a merged graph. The
48
+ cost is real and was accepted deliberately — two analyzers' notions of
49
+ ``os.getcwd`` are not necessarily the same thing, and merging them says they
50
+ are. TypeScript's form; java follows it."""
51
+ base = f"{app_id}/@external"
52
+ return f"{base}/{module}/{name}" if module else f"{base}/{name}"
53
+
54
+
26
55
  def global_ordinal(callable_id: str, local_key: str) -> str:
27
56
  """The GLOBAL ordinal id of a body node from its LOCAL key: synthetic keys
28
57
  (`@entry`, `@formal_in:0`) already carry the `@`; positional keys (`15:2`,
@@ -41,12 +70,13 @@ def stamp_body_ids(callable) -> None:
41
70
 
42
71
 
43
72
  def artifact_id(app_name: str, rel_path: str) -> str:
44
- """Language-neutral artifact id: ``can://artifact/<app>/<rel-path>``.
73
+ """Language-neutral artifact id: ``can://<app>/artifact/<rel-path>``.
45
74
 
46
- The first segment is a namespace (a language for code nodes, the literal
47
- ``artifact`` for files), so sibling analyzers over the same repo emit the
48
- same id for the same file."""
49
- return f"can://artifact/{app_name}/{rel_path}"
75
+ ``artifact`` is a reserved segment in the same position the language
76
+ occupies for code nodes, so sibling analyzers over the same repo (same
77
+ ``<app>``) still emit the same id for the same file — and, unlike the old
78
+ ``can://artifact/<app>/...``, it now sits inside the application prefix."""
79
+ return f"{application_id(app_name)}/artifact/{rel_path}"
50
80
 
51
81
 
52
82
  def config_key_id(artifact_id: str, dotted_key: str) -> str:
@@ -481,7 +481,7 @@ class PyExternalSymbol(BaseModel):
481
481
  builtin member. An edge-endpoint id home, not a tree node: keyed in
482
482
  ``PyApplication.external_symbols`` by its ``can://…/@external/…`` id."""
483
483
 
484
- id: str = "" # can://python/<app>/@external/<module>/<name>
484
+ id: str = "" # can://<app>/@external/<module>/<name>
485
485
  kind: str = "external"
486
486
  name: str # the member/short name, e.g. "get" for "requests.get"
487
487
  module: Optional[str] = None # best-effort owning module, e.g. "requests"
@@ -510,7 +510,7 @@ class PyArtifact(BaseModel):
510
510
  plain data/binary) -- never dropped from the walk. Captured broadly (node
511
511
  + verbatim ``source``); *meaning* is extracted narrowly -- only
512
512
  ``dependency-manifest`` roles feed ``dependencies`` today. ``id`` is
513
- language-neutral (``can://artifact/<app>/<path>``)."""
513
+ language-neutral (``can://<app>/artifact/<path>``)."""
514
514
 
515
515
  id: str = ""
516
516
  kind: str = "artifact"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: codeanalyzer-python
3
- Version: 1.4.1
3
+ Version: 1.5.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
@@ -517,11 +517,11 @@ just populate more of the same tree:
517
517
  "k_limit": 3, // access-path depth bound (--graph-field-depth); L3+ only
518
518
  "analyzer": { "name": "codeanalyzer-python", "version": "1.0.0" },
519
519
  "application": {
520
- "id": "can://python/<app>",
520
+ "id": "can://<app>",
521
521
  "kind": "application",
522
522
  "symbol_table": { // relative POSIX path → module
523
523
  "pkg/mod.py": {
524
- "id": "can://python/<app>/pkg/mod.py",
524
+ "id": "can://<app>/python/pkg/mod.py",
525
525
  "kind": "module",
526
526
  "source": "…full file text, stored once per module…",
527
527
  "types": { "<Class>": { "id": "…", "kind": "class", "callables": { /* methods */ } } },
@@ -531,8 +531,8 @@ just populate more of the same tree:
531
531
  "call_graph": [ { "src": "can://…/main(a)", "dst": "can://…/helper(x)",
532
532
  "weight": 1, "prov": ["defuse", "jedi"] } ],
533
533
  "external_symbols": { // imported/builtin call targets, keyed by id
534
- "can://python/<app>/@external/os/getcwd":
535
- { "id": "can://python/<app>/@external/os/getcwd", "kind": "external",
534
+ "can://<app>/@external/os/getcwd":
535
+ { "id": "can://<app>/@external/os/getcwd", "kind": "external",
536
536
  "name": "getcwd", "module": "os" }
537
537
  },
538
538
  "param_in": [ { "src": "can://…/main(a)@6:4/actual_in:0", "dst": "can://…/helper(x)@formal_in:0" } ],
@@ -568,7 +568,7 @@ The application envelope also contains three substrate sections:
568
568
  - **`artifacts`** — discovered non-code files (manifests, configs, Docker files, CI workflows,
569
569
  packaging files, scripts, docs, and legal files) with extraction status (`none`, `partial`, or
570
570
  `full`; default `none`), keyed by relative path; each artifact carries the
571
- `can://artifact/<app>/<path>` id namespace. Config files carry extracted `config_keys`
571
+ `can://<app>/artifact/<path>` id namespace. Config files carry extracted `config_keys`
572
572
  (keys, values, namespaces, and references) and `DEFINES_CONFIG` Neo4j edges.
573
573
  - **`dependencies`** — declared packages with kind (`runtime`/`dev`/`optional`/`build`), spec,
574
574
  locked version, and provenance (`prov`): where each binding came from (manifest file, lock file,
@@ -579,7 +579,7 @@ The application envelope also contains three substrate sections:
579
579
  Notable properties:
580
580
 
581
581
  - **Durable `can://` ids** identify every node at callable granularity and above
582
- (`can://python/<app>/<file>/<callable-sig>`); nodes below a callable use ordinal ids
582
+ (`can://<app>/python/<file>/<callable-sig>`); nodes below a callable use ordinal ids
583
583
  (`@entry`, `@exit`, `line:col`, `@formal_in:N`, `line:col/actual_in:N`).
584
584
  - **`source` lives once per module**; every node's text is the `module.source[span.bytes]` slice.
585
585
  - **Cross-function edges** — `call_graph`, `param_in`, `param_out`, `config_uses` — live at **application** scope;
@@ -701,7 +701,7 @@ RETURN src.id, d.var, d.prov
701
701
 
702
702
  // interprocedural flow through a parameter (level 4)
703
703
  MATCH (a:PyBodyNode)-[:PY_PARAM_IN]->(f:PyBodyNode)
704
- WHERE f.id STARTS WITH "can://python/myapp/src/api.py"
704
+ WHERE f.id STARTS WITH "can://myapp/python/src/api.py"
705
705
  RETURN a.id, f.id
706
706
  ```
707
707
 
@@ -730,3 +730,25 @@ RETURN f.id, l.version
730
730
  ## License
731
731
 
732
732
  Apache 2.0 — see [LICENSE](./LICENSE).
733
+
734
+ ## Polyglot applications: all languages, or none
735
+
736
+ A `--emit neo4j` push is **destructive**. It sweeps everything under `can://<app>/` that this
737
+ analyzer marked, then rewrites what it found. Since the id grammar puts the application outermost,
738
+ every analyzer over the same `<app>` shares that prefix — so a push reclaims stale rows belonging to
739
+ *this* analyzer and, in the shared namespaces, sweeps rows a sibling wrote.
740
+
741
+ For most of what is shared that is harmless: the artifact walk is a whole-repo inventory, so an
742
+ `:Artifact` a sibling wrote is re-created by this push (with a thinner view of it — `roles` falls
743
+ back to `unknown` and its config keys and dependency edges are gone until that sibling pushes
744
+ again). `@external` ghosts are not inventoried that way: they are per-language, so a sibling's
745
+ ghosts are swept and not restored.
746
+
747
+ **So for an application analysed in more than one language, run every analyzer or none.** Running
748
+ one in isolation leaves the others' derived rows missing until they run again. Running them
749
+ together is always correct, in any order, because the last push restores everything the batch
750
+ swept.
751
+
752
+ Nothing here corrupts a graph: what is lost is derived and regenerates. But a partial run leaves a
753
+ partial answer, and nothing in the data says so.
754
+
@@ -1,6 +1,6 @@
1
1
  codeanalyzer/__init__.py,sha256=BZ3Kuwl-F_F-8H8cepLnVJ4Ku4NNUjjqg0Y6ujPQSsI,108
2
2
  codeanalyzer/__main__.py,sha256=o5_9ct61l3T7ryIsag8bz304NabVV-el_ooGD8tnbhA,15968
3
- codeanalyzer/core.py,sha256=tk_3dz81ECXXv8CEciWTIVfBAHHIfTVCsZte1GAZ080,46620
3
+ codeanalyzer/core.py,sha256=JfSsQEacBiVn38tQP34QWdJqQx7ecE70EXI8obISZN4,46598
4
4
  codeanalyzer/provenance.py,sha256=DT-DqwdVwO7g-GyK3sC0_4vDNCUjZYEY1fyYCt-7VRM,2306
5
5
  codeanalyzer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  codeanalyzer/artifacts/__init__.py,sha256=317sEeZLS1AYsfYDYIk7tLR3AdDFwWw_cmkeZDabkJo,906
@@ -45,21 +45,21 @@ codeanalyzer/entrypoints/rules.yml,sha256=sguICRfDDNGjJPfZz-JSwkI_hzbTJaau1liHV_
45
45
  codeanalyzer/jedi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
46
  codeanalyzer/jedi/jedi.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
47
  codeanalyzer/neo4j/__init__.py,sha256=8Ei6uThTOqmul6GhnKoGOjLXJZbyDwF5Jo-8I8NxnAk,1574
48
- codeanalyzer/neo4j/bolt.py,sha256=kcBhujHuUst6s1eZD-vARDn0iuKUAxSHrN14nrsKGM8,13472
49
- codeanalyzer/neo4j/cypher.py,sha256=y2AW9OUAbZJ4TVHkFpHChJU3r_K7q81tTZKt0VNve6g,5677
48
+ codeanalyzer/neo4j/bolt.py,sha256=8l70iGDjY3Kdm-W1sb3b3O1uqLjDrVPYTpXhnkXdZOY,13694
49
+ codeanalyzer/neo4j/cypher.py,sha256=-wledvXVrcLJRtSC5MCn1N3tqgC06rNfPBn0w6POqHo,6239
50
50
  codeanalyzer/neo4j/emit.py,sha256=OBCO77TDTaNpqk9Di3JIQzBouLpHPdgoXuPSs44iJuU,3587
51
- codeanalyzer/neo4j/project.py,sha256=zoLsr2XGywlZbqnwlYvlhIpgu1jmIvSMTyAgIJZkmeM,38494
52
- codeanalyzer/neo4j/rows.py,sha256=PMlJEyLVIrKITkkK5TOutIzDgBuKLA1RGAkrQ1HLpZo,9579
53
- codeanalyzer/neo4j/schema.py,sha256=TyT3-Tu9thfWJTuvRtZ3BAIM4kQk13uUEJ-sgr9YAdE,14716
51
+ codeanalyzer/neo4j/project.py,sha256=gw4qmoIyOy6LabbpmBawvvb7yGEvgDV4fdmoV128eJA,38774
52
+ codeanalyzer/neo4j/rows.py,sha256=n_J3NVIusLPsHMjPCWaYvlL5sFm6V-kl_Z6B_BTH8Fk,10140
53
+ codeanalyzer/neo4j/schema.py,sha256=ZRjBxpagBsQrPbD5BbeAZlj3ilTeYe4AsquztRDaH4M,14735
54
54
  codeanalyzer/options/__init__.py,sha256=6NewN0a-1HAEgKcxQjYyVn2WEDLrhax8h3WLgZddeqI,94
55
55
  codeanalyzer/options/options.py,sha256=2jDCcs74iSEOhz90LoRGts6PC8yV9IDPVxnLPNmonOA,1609
56
56
  codeanalyzer/schema/__init__.py,sha256=hIyz02abUJNPW8yUgguaeKflZjTmOZWbDiKICNBD7yk,4141
57
57
  codeanalyzer/schema/assign_ids.py,sha256=pQHluLaO5a6hFREp3vjVRsUeAfTYSJ95RXS9TZvnoys,1590
58
58
  codeanalyzer/schema/call_graph_ids.py,sha256=mWAhJDBsW8i-siJiINOHCXEm4qM6F_5se9-HuHWIFqU,568
59
- codeanalyzer/schema/ids.py,sha256=gBjpOlx4S_1JULlXoAHGommd5e81D5dwd5JSopYwdo8,2543
59
+ codeanalyzer/schema/ids.py,sha256=YuioNK3Y-M2NcCBiGH4AB4rDezlqu6ycNO0R3O-Jxho,4388
60
60
  codeanalyzer/schema/l1_body.py,sha256=_sca0mTkMRb-5lasep87faGjDxZJd9jGB0hmBx3uCgk,1757
61
61
  codeanalyzer/schema/l2_callees.py,sha256=CTcBeGoO04DstDC6h-1sHMbbIrHDEOMxP01U9VLBcfc,2327
62
- codeanalyzer/schema/py_schema.py,sha256=lbW7fIRWOdVLH0Ql0yYCYZzaS-iaACBLOuDPmXesjKs,24238
62
+ codeanalyzer/schema/py_schema.py,sha256=Ujre6PoBQZ3DUn9tjoPsqoYBPtAcYW-WI2JphLaMKyU,24231
63
63
  codeanalyzer/semantic_analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
64
  codeanalyzer/semantic_analysis/call_graph.py,sha256=6YEB_wTn5-oQYLrbIhJYE0BsHl4fpWPoy5Hwd9mTnGc,11918
65
65
  codeanalyzer/semantic_analysis/defuse_linker.py,sha256=bSn1rCun28OQqSd2NOc9aVBSm47Gt9Iul4r_gwfqO1w,64930
@@ -70,9 +70,9 @@ codeanalyzer/syntactic_analysis/symbol_table_builder.py,sha256=eTknBDlUuuQd3JEwb
70
70
  codeanalyzer/utils/__init__.py,sha256=hC6VWdR5rerSqBxzu9KQHTASWqwrrYJv-CMDwrTlzkc,137
71
71
  codeanalyzer/utils/logging.py,sha256=Fw0tattPAOMs3o0JMjjXhRVLIF64f-SCcygUXF9jqeg,904
72
72
  codeanalyzer/utils/progress_bar.py,sha256=C9JtzVdd10lIxTv-KA6PebqjKWueC_vMGwVzAtHuHIw,2818
73
- codeanalyzer_python-1.4.1.dist-info/METADATA,sha256=tmpHTz20bMUPMGvpJp66Guu8NtDqo-SIFso_Sk0BoHI,43485
74
- codeanalyzer_python-1.4.1.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
75
- codeanalyzer_python-1.4.1.dist-info/entry_points.txt,sha256=v4Vux0Nnx7sOntVk_CH7W9RX6SkIkvR1FQYq73oVlCQ,105
76
- codeanalyzer_python-1.4.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
77
- codeanalyzer_python-1.4.1.dist-info/licenses/NOTICE,sha256=MdVkNYqHJ20on2FmWvgD4WpMsX5mir33xdyPvTXd0A0,1223
78
- codeanalyzer_python-1.4.1.dist-info/RECORD,,
73
+ codeanalyzer_python-1.5.0.dist-info/METADATA,sha256=X4LXZPtqeXauN-M0hAsMBJCjJxqgOTeCj_KtYOBTgtI,44750
74
+ codeanalyzer_python-1.5.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
75
+ codeanalyzer_python-1.5.0.dist-info/entry_points.txt,sha256=v4Vux0Nnx7sOntVk_CH7W9RX6SkIkvR1FQYq73oVlCQ,105
76
+ codeanalyzer_python-1.5.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
77
+ codeanalyzer_python-1.5.0.dist-info/licenses/NOTICE,sha256=MdVkNYqHJ20on2FmWvgD4WpMsX5mir33xdyPvTXd0A0,1223
78
+ codeanalyzer_python-1.5.0.dist-info/RECORD,,