coretrace-python-analyzer 0.1.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.
Files changed (126) hide show
  1. coretrace_python/__init__.py +4 -0
  2. coretrace_python/__main__.py +4 -0
  3. coretrace_python/abstract/__init__.py +45 -0
  4. coretrace_python/abstract/constants.py +226 -0
  5. coretrace_python/abstract/heap.py +252 -0
  6. coretrace_python/abstract/ranges.py +285 -0
  7. coretrace_python/abstract/values.py +56 -0
  8. coretrace_python/analysis/__init__.py +31 -0
  9. coretrace_python/analysis/manager.py +165 -0
  10. coretrace_python/analysis/provider.py +73 -0
  11. coretrace_python/bundled/dependency/dependency_policy/dependency_policy.py +46 -0
  12. coretrace_python/bundled/dependency/dependency_policy/plugin.toml +9 -0
  13. coretrace_python/bundled/dependency/reachable_vulnerability/plugin.toml +9 -0
  14. coretrace_python/bundled/dependency/reachable_vulnerability/reachable_vulnerability.py +56 -0
  15. coretrace_python/bundled/dependency/sample_advisories/plugin.toml +9 -0
  16. coretrace_python/bundled/dependency/sample_advisories/sample_advisories.py +109 -0
  17. coretrace_python/bundled/dependency/vulnerable_dependency/plugin.toml +9 -0
  18. coretrace_python/bundled/dependency/vulnerable_dependency/vulnerable_dependency.py +43 -0
  19. coretrace_python/bundled/models/cli/cli_models.py +35 -0
  20. coretrace_python/bundled/models/cli/plugin.toml +9 -0
  21. coretrace_python/bundled/models/credentials/credential_models.py +43 -0
  22. coretrace_python/bundled/models/credentials/plugin.toml +9 -0
  23. coretrace_python/bundled/models/django/django_models.py +123 -0
  24. coretrace_python/bundled/models/django/plugin.toml +9 -0
  25. coretrace_python/bundled/models/fastapi/fastapi_models.py +29 -0
  26. coretrace_python/bundled/models/fastapi/plugin.toml +9 -0
  27. coretrace_python/bundled/models/flask/flask_models.py +53 -0
  28. coretrace_python/bundled/models/flask/plugin.toml +9 -0
  29. coretrace_python/bundled/models/http_clients/http_client_models.py +43 -0
  30. coretrace_python/bundled/models/http_clients/plugin.toml +9 -0
  31. coretrace_python/bundled/models/python_stdlib/plugin.toml +9 -0
  32. coretrace_python/bundled/models/python_stdlib/python_stdlib.py +68 -0
  33. coretrace_python/bundled/models/sqlalchemy/plugin.toml +9 -0
  34. coretrace_python/bundled/models/sqlalchemy/sqlalchemy_models.py +47 -0
  35. coretrace_python/bundled/secrets/config_secrets/config_secrets.py +38 -0
  36. coretrace_python/bundled/secrets/config_secrets/plugin.toml +9 -0
  37. coretrace_python/bundled/secrets/hardcoded_secrets/hardcoded_secrets.py +19 -0
  38. coretrace_python/bundled/secrets/hardcoded_secrets/plugin.toml +9 -0
  39. coretrace_python/bundled/security/command_injection/command_injection.py +17 -0
  40. coretrace_python/bundled/security/command_injection/plugin.toml +9 -0
  41. coretrace_python/bundled/security/insecure_deserialization/insecure_deserialization.py +17 -0
  42. coretrace_python/bundled/security/insecure_deserialization/plugin.toml +9 -0
  43. coretrace_python/bundled/security/open_redirect/open_redirect.py +17 -0
  44. coretrace_python/bundled/security/open_redirect/plugin.toml +9 -0
  45. coretrace_python/bundled/security/path_traversal/path_traversal.py +17 -0
  46. coretrace_python/bundled/security/path_traversal/plugin.toml +9 -0
  47. coretrace_python/bundled/security/plaintext_credentials/plaintext_credentials.py +21 -0
  48. coretrace_python/bundled/security/plaintext_credentials/plugin.toml +9 -0
  49. coretrace_python/bundled/security/sql_injection/plugin.toml +9 -0
  50. coretrace_python/bundled/security/sql_injection/sql_injection.py +17 -0
  51. coretrace_python/bundled/security/ssrf/plugin.toml +9 -0
  52. coretrace_python/bundled/security/ssrf/ssrf.py +17 -0
  53. coretrace_python/bundled/security/xss/plugin.toml +9 -0
  54. coretrace_python/bundled/security/xss/xss.py +17 -0
  55. coretrace_python/bundled/syntax/dangerous_eval/dangerous_eval.py +19 -0
  56. coretrace_python/bundled/syntax/dangerous_eval/plugin.toml +9 -0
  57. coretrace_python/bundled/syntax/flask_debug/flask_debug.py +63 -0
  58. coretrace_python/bundled/syntax/flask_debug/plugin.toml +9 -0
  59. coretrace_python/bundled/syntax/missing_timeout/missing_timeout.py +51 -0
  60. coretrace_python/bundled/syntax/missing_timeout/plugin.toml +9 -0
  61. coretrace_python/bundled/syntax/weak_crypto/plugin.toml +9 -0
  62. coretrace_python/bundled/syntax/weak_crypto/weak_crypto.py +19 -0
  63. coretrace_python/cache.py +310 -0
  64. coretrace_python/cfg/__init__.py +46 -0
  65. coretrace_python/cfg/builder.py +589 -0
  66. coretrace_python/cfg/dominance.py +183 -0
  67. coretrace_python/cfg/model.py +166 -0
  68. coretrace_python/cli.py +216 -0
  69. coretrace_python/dataflow/__init__.py +29 -0
  70. coretrace_python/dataflow/lattice.py +78 -0
  71. coretrace_python/dataflow/solver.py +96 -0
  72. coretrace_python/dependency/__init__.py +44 -0
  73. coretrace_python/dependency/advisories.py +168 -0
  74. coretrace_python/dependency/correlation.py +87 -0
  75. coretrace_python/dependency/graph.py +274 -0
  76. coretrace_python/dependency/policy.py +65 -0
  77. coretrace_python/dependency/sbom.py +65 -0
  78. coretrace_python/engine.py +688 -0
  79. coretrace_python/findings/__init__.py +13 -0
  80. coretrace_python/findings/coverage.py +45 -0
  81. coretrace_python/findings/model.py +49 -0
  82. coretrace_python/findings/refutation.py +427 -0
  83. coretrace_python/frontend/__init__.py +18 -0
  84. coretrace_python/frontend/ast_adapter.py +447 -0
  85. coretrace_python/frontend/parser.py +23 -0
  86. coretrace_python/hir/__init__.py +5 -0
  87. coretrace_python/hir/nodes.py +584 -0
  88. coretrace_python/hir/visitors.py +36 -0
  89. coretrace_python/interprocedural/__init__.py +49 -0
  90. coretrace_python/interprocedural/callgraph.py +291 -0
  91. coretrace_python/interprocedural/modulegraph.py +218 -0
  92. coretrace_python/interprocedural/summaries.py +463 -0
  93. coretrace_python/ir/__init__.py +5 -0
  94. coretrace_python/ir/defuse.py +74 -0
  95. coretrace_python/ir/lowering.py +575 -0
  96. coretrace_python/ir/model.py +481 -0
  97. coretrace_python/ir/printer.py +201 -0
  98. coretrace_python/ir/ssa.py +277 -0
  99. coretrace_python/plugins/__init__.py +58 -0
  100. coretrace_python/plugins/api.py +153 -0
  101. coretrace_python/plugins/detectors.py +114 -0
  102. coretrace_python/plugins/loader.py +84 -0
  103. coretrace_python/plugins/manifest.py +112 -0
  104. coretrace_python/plugins/registry.py +34 -0
  105. coretrace_python/plugins/secrets.py +330 -0
  106. coretrace_python/reporters/__init__.py +22 -0
  107. coretrace_python/reporters/json_format.py +48 -0
  108. coretrace_python/reporters/report.py +23 -0
  109. coretrace_python/reporters/sarif.py +70 -0
  110. coretrace_python/reporters/text.py +24 -0
  111. coretrace_python/semantic/__init__.py +9 -0
  112. coretrace_python/semantic/identity.py +39 -0
  113. coretrace_python/semantic/imports.py +131 -0
  114. coretrace_python/semantic/scopes.py +473 -0
  115. coretrace_python/semantic/symbols.py +87 -0
  116. coretrace_python/source/__init__.py +13 -0
  117. coretrace_python/source/manager.py +81 -0
  118. coretrace_python/source/model.py +57 -0
  119. coretrace_python/taint/__init__.py +55 -0
  120. coretrace_python/taint/engine.py +800 -0
  121. coretrace_python/taint/models.py +317 -0
  122. coretrace_python/taint/routes.py +99 -0
  123. coretrace_python_analyzer-0.1.0.dist-info/METADATA +74 -0
  124. coretrace_python_analyzer-0.1.0.dist-info/RECORD +126 -0
  125. coretrace_python_analyzer-0.1.0.dist-info/WHEEL +4 -0
  126. coretrace_python_analyzer-0.1.0.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,584 @@
1
+ """Immutable nodes for the Python high-level intermediate representation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import TypeAlias
7
+
8
+ from coretrace_python.source import SourceSpan
9
+
10
+ HIR_SCHEMA_VERSION = 1
11
+
12
+
13
+ @dataclass(frozen=True, slots=True)
14
+ class Name:
15
+ identifier: str
16
+ span: SourceSpan
17
+
18
+
19
+ @dataclass(frozen=True, slots=True)
20
+ class Constant:
21
+ value: object
22
+ span: SourceSpan
23
+
24
+
25
+ @dataclass(frozen=True, slots=True)
26
+ class BinaryOp:
27
+ operator: str
28
+ left: Expression
29
+ right: Expression
30
+ span: SourceSpan
31
+
32
+
33
+ @dataclass(frozen=True, slots=True)
34
+ class UnaryOp:
35
+ operator: str
36
+ operand: Expression
37
+ span: SourceSpan
38
+
39
+
40
+ @dataclass(frozen=True, slots=True)
41
+ class BoolOp:
42
+ """``and`` / ``or`` over two or more values; chained comparisons lower to ``and``."""
43
+
44
+ operator: str
45
+ values: tuple[Expression, ...]
46
+ span: SourceSpan
47
+
48
+
49
+ @dataclass(frozen=True, slots=True)
50
+ class Compare:
51
+ operator: str
52
+ left: Expression
53
+ right: Expression
54
+ span: SourceSpan
55
+
56
+
57
+ @dataclass(frozen=True, slots=True)
58
+ class Attribute:
59
+ value: Expression
60
+ name: str
61
+ span: SourceSpan
62
+
63
+
64
+ @dataclass(frozen=True, slots=True)
65
+ class Subscript:
66
+ value: Expression
67
+ key: Expression
68
+ span: SourceSpan
69
+
70
+
71
+ @dataclass(frozen=True, slots=True)
72
+ class Keyword:
73
+ """A keyword argument; ``name`` is ``None`` for ``**mapping`` unpacking."""
74
+
75
+ name: str | None
76
+ value: Expression
77
+ span: SourceSpan
78
+
79
+
80
+ @dataclass(frozen=True, slots=True)
81
+ class Call:
82
+ callee: Expression
83
+ arguments: tuple[Expression, ...]
84
+ keywords: tuple[Keyword, ...]
85
+ span: SourceSpan
86
+
87
+
88
+ @dataclass(frozen=True, slots=True)
89
+ class Tuple:
90
+ elements: tuple[Expression, ...]
91
+ span: SourceSpan
92
+
93
+
94
+ @dataclass(frozen=True, slots=True)
95
+ class List:
96
+ elements: tuple[Expression, ...]
97
+ span: SourceSpan
98
+
99
+
100
+ @dataclass(frozen=True, slots=True)
101
+ class Dict:
102
+ """Items are ``(key, value)``; a ``None`` key is a ``**mapping`` unpacking."""
103
+
104
+ items: tuple[tuple[Expression | None, Expression], ...]
105
+ span: SourceSpan
106
+
107
+
108
+ @dataclass(frozen=True, slots=True)
109
+ class FormattedString:
110
+ """An f-string: constant text and formatted expressions, in order. Conversions and
111
+ format specifications are dropped; expressions nested in a specification are parts."""
112
+
113
+ parts: tuple[Expression, ...]
114
+ span: SourceSpan
115
+
116
+
117
+ @dataclass(frozen=True, slots=True)
118
+ class Slice:
119
+ lower: Expression | None
120
+ upper: Expression | None
121
+ step: Expression | None
122
+ span: SourceSpan
123
+
124
+
125
+ @dataclass(frozen=True, slots=True)
126
+ class Starred:
127
+ """``*iterable`` in a call argument list or a list or tuple display."""
128
+
129
+ value: Expression
130
+ span: SourceSpan
131
+
132
+
133
+ @dataclass(frozen=True, slots=True)
134
+ class Set:
135
+ elements: tuple[Expression, ...]
136
+ span: SourceSpan
137
+
138
+
139
+ @dataclass(frozen=True, slots=True)
140
+ class Conditional:
141
+ """``body if test else orelse``; the CFG builder lays it out as a branch."""
142
+
143
+ test: Expression
144
+ body: Expression
145
+ orelse: Expression
146
+ span: SourceSpan
147
+
148
+
149
+ @dataclass(frozen=True, slots=True)
150
+ class Lambda:
151
+ """An anonymous function; its body is a scope of its own and is not lowered."""
152
+
153
+ parameters: tuple[Parameter, ...]
154
+ body: Expression
155
+ span: SourceSpan
156
+
157
+
158
+ @dataclass(frozen=True, slots=True)
159
+ class Await:
160
+ value: Expression
161
+ span: SourceSpan
162
+
163
+
164
+ @dataclass(frozen=True, slots=True)
165
+ class Yield:
166
+ value: Expression | None
167
+ span: SourceSpan
168
+
169
+
170
+ @dataclass(frozen=True, slots=True)
171
+ class ComprehensionGenerator:
172
+ """One ``for target in iterable if condition...`` clause of a comprehension."""
173
+
174
+ target: Target
175
+ iterable: Expression
176
+ conditions: tuple[Expression, ...]
177
+ span: SourceSpan
178
+
179
+
180
+ @dataclass(frozen=True, slots=True)
181
+ class Comprehension:
182
+ """A list, set, dict or generator comprehension; ``kind`` names which one. A dict
183
+ comprehension's ``element`` is the value and ``key`` its key."""
184
+
185
+ kind: str
186
+ element: Expression
187
+ generators: tuple[ComprehensionGenerator, ...]
188
+ span: SourceSpan
189
+ key: Expression | None = None
190
+
191
+
192
+ Expression: TypeAlias = (
193
+ Name
194
+ | Constant
195
+ | BinaryOp
196
+ | UnaryOp
197
+ | BoolOp
198
+ | Compare
199
+ | Attribute
200
+ | Subscript
201
+ | Call
202
+ | Tuple
203
+ | List
204
+ | Dict
205
+ | FormattedString
206
+ | Slice
207
+ | Starred
208
+ | Set
209
+ | Conditional
210
+ | Lambda
211
+ | Await
212
+ | Yield
213
+ | Comprehension
214
+ )
215
+
216
+ Target: TypeAlias = Name | Attribute | Subscript | Tuple
217
+
218
+
219
+ @dataclass(frozen=True, slots=True)
220
+ class Parameter:
221
+ """``kind`` is ``positional``, ``keyword``, ``var_positional`` or ``var_keyword``.
222
+ ``annotation`` is kept when it is an expression the HIR can represent."""
223
+
224
+ name: str
225
+ span: SourceSpan
226
+ default: Expression | None = None
227
+ kind: str = "positional"
228
+ annotation: Expression | None = None
229
+
230
+
231
+ @dataclass(frozen=True, slots=True)
232
+ class Assign:
233
+ target: Target
234
+ value: Expression
235
+ span: SourceSpan
236
+
237
+
238
+ @dataclass(frozen=True, slots=True)
239
+ class AugAssign:
240
+ target: Name | Attribute | Subscript
241
+ operator: str
242
+ value: Expression
243
+ span: SourceSpan
244
+
245
+
246
+ @dataclass(frozen=True, slots=True)
247
+ class Return:
248
+ value: Expression | None
249
+ span: SourceSpan
250
+
251
+
252
+ @dataclass(frozen=True, slots=True)
253
+ class ExpressionStatement:
254
+ expression: Expression
255
+ span: SourceSpan
256
+
257
+
258
+ @dataclass(frozen=True, slots=True)
259
+ class Pass:
260
+ span: SourceSpan
261
+
262
+
263
+ @dataclass(frozen=True, slots=True)
264
+ class Delete:
265
+ targets: tuple[Target, ...]
266
+ span: SourceSpan
267
+
268
+
269
+ @dataclass(frozen=True, slots=True)
270
+ class Declaration:
271
+ """``name: annotation`` without a value: a dataclass field or an annotated local."""
272
+
273
+ name: str
274
+ annotation: Expression | None
275
+ span: SourceSpan
276
+
277
+
278
+ @dataclass(frozen=True, slots=True)
279
+ class ValuePattern:
280
+ """``case <expression>``: equality with a value."""
281
+
282
+ value: Expression
283
+ span: SourceSpan
284
+
285
+
286
+ @dataclass(frozen=True, slots=True)
287
+ class SingletonPattern:
288
+ """``case None`` / ``True`` / ``False``: identity with a singleton."""
289
+
290
+ value: object
291
+ span: SourceSpan
292
+
293
+
294
+ @dataclass(frozen=True, slots=True)
295
+ class WildcardPattern:
296
+ span: SourceSpan
297
+
298
+
299
+ @dataclass(frozen=True, slots=True)
300
+ class CapturePattern:
301
+ """``case name`` or ``case <pattern> as name``: binds the subject."""
302
+
303
+ name: str
304
+ pattern: Pattern | None
305
+ span: SourceSpan
306
+
307
+
308
+ @dataclass(frozen=True, slots=True)
309
+ class OrPattern:
310
+ alternatives: tuple[Pattern, ...]
311
+ span: SourceSpan
312
+
313
+
314
+ @dataclass(frozen=True, slots=True)
315
+ class StarPattern:
316
+ """``*rest`` inside a sequence pattern; ``name`` is ``None`` for ``*_``."""
317
+
318
+ name: str | None
319
+ span: SourceSpan
320
+
321
+
322
+ @dataclass(frozen=True, slots=True)
323
+ class SequencePattern:
324
+ patterns: tuple[Pattern, ...]
325
+ span: SourceSpan
326
+
327
+
328
+ @dataclass(frozen=True, slots=True)
329
+ class MappingPattern:
330
+ """``{key: pattern, ..., **rest}``; keys are expressions, ``rest`` a name or ``None``."""
331
+
332
+ keys: tuple[Expression, ...]
333
+ patterns: tuple[Pattern, ...]
334
+ rest: str | None
335
+ span: SourceSpan
336
+
337
+
338
+ @dataclass(frozen=True, slots=True)
339
+ class ClassPattern:
340
+ """``Cls(p, ..., name=pattern, ...)``: positional sub-patterns need the class's
341
+ ``__match_args__``; keyword ones match attributes."""
342
+
343
+ cls: Expression
344
+ patterns: tuple[Pattern, ...]
345
+ keyword_names: tuple[str, ...]
346
+ keyword_patterns: tuple[Pattern, ...]
347
+ span: SourceSpan
348
+
349
+
350
+ @dataclass(frozen=True, slots=True)
351
+ class UnsupportedPattern:
352
+ """A pattern the HIR does not represent; the CFG builder reports it."""
353
+
354
+ kind: str
355
+ span: SourceSpan
356
+
357
+
358
+ Pattern: TypeAlias = (
359
+ ValuePattern
360
+ | SingletonPattern
361
+ | WildcardPattern
362
+ | CapturePattern
363
+ | OrPattern
364
+ | StarPattern
365
+ | SequencePattern
366
+ | MappingPattern
367
+ | ClassPattern
368
+ | UnsupportedPattern
369
+ )
370
+
371
+
372
+ @dataclass(frozen=True, slots=True)
373
+ class MatchCase:
374
+ pattern: Pattern
375
+ guard: Expression | None
376
+ body: tuple[Statement, ...]
377
+ span: SourceSpan
378
+
379
+
380
+ @dataclass(frozen=True, slots=True)
381
+ class Match:
382
+ """``match subject:``; the CFG builder lays it out as an ``if`` chain."""
383
+
384
+ subject: Expression
385
+ cases: tuple[MatchCase, ...]
386
+ span: SourceSpan
387
+
388
+
389
+ @dataclass(frozen=True, slots=True)
390
+ class Assert:
391
+ test: Expression
392
+ message: Expression | None
393
+ span: SourceSpan
394
+
395
+
396
+ @dataclass(frozen=True, slots=True)
397
+ class If:
398
+ condition: Expression
399
+ body: tuple[Statement, ...]
400
+ orelse: tuple[Statement, ...]
401
+ span: SourceSpan
402
+
403
+
404
+ @dataclass(frozen=True, slots=True)
405
+ class While:
406
+ condition: Expression
407
+ body: tuple[Statement, ...]
408
+ span: SourceSpan
409
+ orelse: tuple[Statement, ...] = ()
410
+
411
+
412
+ @dataclass(frozen=True, slots=True)
413
+ class For:
414
+ target: Name
415
+ iterable: Expression
416
+ body: tuple[Statement, ...]
417
+ is_async: bool
418
+ span: SourceSpan
419
+ orelse: tuple[Statement, ...] = ()
420
+
421
+
422
+ @dataclass(frozen=True, slots=True)
423
+ class Break:
424
+ span: SourceSpan
425
+
426
+
427
+ @dataclass(frozen=True, slots=True)
428
+ class Continue:
429
+ span: SourceSpan
430
+
431
+
432
+ @dataclass(frozen=True, slots=True)
433
+ class Raise:
434
+ exception: Expression | None
435
+ span: SourceSpan
436
+ cause: Expression | None = None
437
+
438
+
439
+ @dataclass(frozen=True, slots=True)
440
+ class WithItem:
441
+ context: Expression
442
+ target: Name | None
443
+ span: SourceSpan
444
+
445
+
446
+ @dataclass(frozen=True, slots=True)
447
+ class With:
448
+ items: tuple[WithItem, ...]
449
+ body: tuple[Statement, ...]
450
+ is_async: bool
451
+ span: SourceSpan
452
+
453
+
454
+ @dataclass(frozen=True, slots=True)
455
+ class EnterWith:
456
+ """Synthetic statement the CFG builder emits when a ``with`` body starts."""
457
+
458
+ item: WithItem
459
+ span: SourceSpan
460
+
461
+
462
+ @dataclass(frozen=True, slots=True)
463
+ class ExitWith:
464
+ """Synthetic statement the CFG builder emits when a ``with`` body falls through."""
465
+
466
+ item: WithItem
467
+ span: SourceSpan
468
+
469
+
470
+ @dataclass(frozen=True, slots=True)
471
+ class ExceptHandler:
472
+ """``except type as name:``; ``type`` is ``None`` for a bare ``except``."""
473
+
474
+ type: Expression | None
475
+ name: str | None
476
+ body: tuple[Statement, ...]
477
+ span: SourceSpan
478
+
479
+
480
+ @dataclass(frozen=True, slots=True)
481
+ class Try:
482
+ body: tuple[Statement, ...]
483
+ handlers: tuple[ExceptHandler, ...]
484
+ orelse: tuple[Statement, ...]
485
+ finalbody: tuple[Statement, ...]
486
+ span: SourceSpan
487
+
488
+
489
+ @dataclass(frozen=True, slots=True)
490
+ class EnterHandler:
491
+ """Synthetic statement the CFG builder emits at the start of a handler block."""
492
+
493
+ handler: ExceptHandler
494
+ span: SourceSpan
495
+
496
+
497
+ @dataclass(frozen=True, slots=True)
498
+ class ImportAlias:
499
+ name: str
500
+ as_name: str | None
501
+ span: SourceSpan
502
+
503
+
504
+ @dataclass(frozen=True, slots=True)
505
+ class Import:
506
+ names: tuple[ImportAlias, ...]
507
+ span: SourceSpan
508
+
509
+
510
+ @dataclass(frozen=True, slots=True)
511
+ class ImportFrom:
512
+ module: str | None
513
+ names: tuple[ImportAlias, ...]
514
+ level: int
515
+ span: SourceSpan
516
+
517
+
518
+ @dataclass(frozen=True, slots=True)
519
+ class Global:
520
+ names: tuple[str, ...]
521
+ span: SourceSpan
522
+
523
+
524
+ @dataclass(frozen=True, slots=True)
525
+ class Nonlocal:
526
+ names: tuple[str, ...]
527
+ span: SourceSpan
528
+
529
+
530
+ @dataclass(frozen=True, slots=True)
531
+ class Function:
532
+ name: str
533
+ parameters: tuple[Parameter, ...]
534
+ body: tuple[Statement, ...]
535
+ is_async: bool
536
+ span: SourceSpan
537
+ decorators: tuple[Expression, ...] = ()
538
+
539
+
540
+ @dataclass(frozen=True, slots=True)
541
+ class Class:
542
+ name: str
543
+ bases: tuple[Expression, ...]
544
+ body: tuple[Statement, ...]
545
+ span: SourceSpan
546
+ decorators: tuple[Expression, ...] = ()
547
+
548
+
549
+ Statement: TypeAlias = (
550
+ Assign
551
+ | AugAssign
552
+ | Return
553
+ | ExpressionStatement
554
+ | Pass
555
+ | Delete
556
+ | Match
557
+ | Declaration
558
+ | Assert
559
+ | If
560
+ | While
561
+ | For
562
+ | Break
563
+ | Continue
564
+ | Raise
565
+ | With
566
+ | EnterWith
567
+ | ExitWith
568
+ | Try
569
+ | EnterHandler
570
+ | Import
571
+ | ImportFrom
572
+ | Global
573
+ | Nonlocal
574
+ | Function
575
+ | Class
576
+ )
577
+
578
+
579
+ @dataclass(frozen=True, slots=True)
580
+ class Module:
581
+ name: str
582
+ body: tuple[Statement, ...]
583
+ span: SourceSpan
584
+ is_package: bool = False
@@ -0,0 +1,36 @@
1
+ """Generic traversal helpers over PyHIR nodes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Iterator
6
+ from dataclasses import fields
7
+
8
+ from coretrace_python.hir import nodes
9
+
10
+ Node = (
11
+ nodes.Statement
12
+ | nodes.Expression
13
+ | nodes.ComprehensionGenerator
14
+ | nodes.Keyword
15
+ | nodes.WithItem
16
+ | nodes.Parameter
17
+ )
18
+
19
+
20
+ def children(node: Node) -> Iterator[Node]:
21
+ """Yield the direct child nodes of ``node`` in source order."""
22
+
23
+ for field in fields(node):
24
+ yield from _nodes_in(getattr(node, field.name))
25
+
26
+
27
+ def _nodes_in(value: object) -> Iterator[Node]:
28
+ if _is_node(value):
29
+ yield value # type: ignore[misc]
30
+ elif isinstance(value, tuple):
31
+ for item in value:
32
+ yield from _nodes_in(item)
33
+
34
+
35
+ def _is_node(value: object) -> bool:
36
+ return hasattr(value, "span") and not isinstance(value, nodes.ImportAlias)
@@ -0,0 +1,49 @@
1
+ """Call graph and function summaries (architecture §19, §20)."""
2
+
3
+ from coretrace_python.interprocedural.callgraph import (
4
+ CallGraph,
5
+ CallGraphAnalysis,
6
+ CallSite,
7
+ ExternalSymbol,
8
+ KnownFunction,
9
+ Target,
10
+ UnknownTarget,
11
+ )
12
+ from coretrace_python.interprocedural.modulegraph import (
13
+ ModuleGraph,
14
+ build_module_graph,
15
+ discover_files,
16
+ discover_sources,
17
+ project_symbol,
18
+ )
19
+ from coretrace_python.interprocedural.summaries import (
20
+ ExternalCall,
21
+ FunctionSummary,
22
+ Mutation,
23
+ ProjectSummaries,
24
+ SummaryAnalysis,
25
+ SummaryIndex,
26
+ SummaryTable,
27
+ )
28
+
29
+ __all__ = [
30
+ "CallGraph",
31
+ "CallGraphAnalysis",
32
+ "CallSite",
33
+ "ExternalCall",
34
+ "ExternalSymbol",
35
+ "FunctionSummary",
36
+ "KnownFunction",
37
+ "ModuleGraph",
38
+ "Mutation",
39
+ "ProjectSummaries",
40
+ "SummaryAnalysis",
41
+ "SummaryIndex",
42
+ "SummaryTable",
43
+ "Target",
44
+ "UnknownTarget",
45
+ "build_module_graph",
46
+ "discover_files",
47
+ "discover_sources",
48
+ "project_symbol",
49
+ ]