codeanalyzer-python 0.2.1__py3-none-any.whl → 0.3.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.
@@ -173,7 +173,7 @@ def jedi_call_graph_edges(
173
173
 
174
174
  Edges are coalesced on ``(source, target)``: ``weight`` is the count of
175
175
  matching sites. Provenance is always ``["jedi"]``; combine with
176
- CodeQL-derived edges via ``merge_edges``.
176
+ PyCG-derived edges via ``merge_edges``.
177
177
  """
178
178
  counts: Counter = Counter()
179
179
  for caller in iter_callables_in_symbol_table(symbol_table):
@@ -191,7 +191,7 @@ def jedi_call_graph_edges(
191
191
  def resolve_unresolved_constructors(symbol_table: Dict[str, PyModule]) -> int:
192
192
  """Fill in ``PyCallsite.callee_signature`` for unresolved constructor sites.
193
193
 
194
- When both Jedi and CodeQL fail to resolve a constructor call (commonly
194
+ When Jedi fails to resolve a constructor call (commonly
195
195
  for classes nested inside functions or methods, where static-analysis
196
196
  points-to is weakest), Jedi still flags the site as
197
197
  ``is_constructor_call=True`` with ``method_name`` set to the class's
@@ -246,12 +246,33 @@ def resolve_unresolved_constructors(symbol_table: Dict[str, PyModule]) -> int:
246
246
  return resolved
247
247
 
248
248
 
249
+ def filter_external_edges(
250
+ edges: List[PyCallEdge],
251
+ symbol_table: Dict[str, PyModule],
252
+ ) -> List[PyCallEdge]:
253
+ """Remove edges where both source and target are outside the app namespace.
254
+
255
+ Edges where an app callable calls a library function (or vice-versa) are
256
+ retained; only lib→lib edges are dropped. The app symbol set is built by
257
+ walking every callable in the symbol table recursively (including nested
258
+ functions and closures via ``inner_callables``) plus every class, so
259
+ PyCG-discovered closure nodes are correctly recognised as app symbols.
260
+ """
261
+ app_symbols: set = {c.signature for c in iter_callables_in_symbol_table(symbol_table)}
262
+ app_symbols.update(cls.signature for cls in iter_classes_in_symbol_table(symbol_table))
263
+
264
+ return [
265
+ e for e in edges
266
+ if e.source in app_symbols or e.target in app_symbols
267
+ ]
268
+
269
+
249
270
  def merge_edges(*edge_lists: list) -> list:
250
271
  """Merge multiple ``List[PyCallEdge]`` into one.
251
272
 
252
273
  Edges with the same ``(source, target)`` are coalesced: weights sum,
253
274
  provenance is the sorted union. Useful for combining edges produced
254
- by different backends (e.g. Jedi + CodeQL).
275
+ by different backends (e.g. Jedi + PyCG).
255
276
  """
256
277
  by_key: Dict[Tuple[str, str], PyCallEdge] = {}
257
278
  for edges in edge_lists:
@@ -0,0 +1,20 @@
1
+ ################################################################################
2
+ # Copyright IBM Corporation 2025
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ ################################################################################
16
+
17
+ from codeanalyzer.semantic_analysis.pycg.pycg_analysis import PyCG
18
+ from codeanalyzer.semantic_analysis.pycg.pycg_exceptions import PyCGExceptions
19
+
20
+ __all__ = ["PyCG", "PyCGExceptions"]