codemap-python 0.1.1__tar.gz → 0.1.3__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 (75) hide show
  1. {codemap_python-0.1.1 → codemap_python-0.1.3}/PKG-INFO +1 -1
  2. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/call_graph/call_extractor.py +6 -1
  3. codemap_python-0.1.3/analysis/core/ast_parser.py +31 -0
  4. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/core/import_extractor.py +6 -0
  5. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/explain/explain_runner.py +6 -1
  6. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/runners/phase4_runner.py +6 -1
  7. codemap_python-0.1.3/analysis/utils/bom_handler.py +55 -0
  8. {codemap_python-0.1.1 → codemap_python-0.1.3}/codemap_python.egg-info/PKG-INFO +1 -1
  9. {codemap_python-0.1.1 → codemap_python-0.1.3}/codemap_python.egg-info/SOURCES.txt +1 -0
  10. {codemap_python-0.1.1 → codemap_python-0.1.3}/pyproject.toml +1 -1
  11. {codemap_python-0.1.1 → codemap_python-0.1.3}/ui/app.py +13 -9
  12. codemap_python-0.1.1/analysis/core/ast_parser.py +0 -8
  13. {codemap_python-0.1.1 → codemap_python-0.1.3}/README.md +0 -0
  14. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/__init__.py +0 -0
  15. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/architecture/__init__.py +0 -0
  16. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/architecture/architecture_engine.py +0 -0
  17. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/architecture/dependency_cycles.py +0 -0
  18. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/architecture/risk_radar.py +0 -0
  19. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/call_graph/__init__.py +0 -0
  20. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/call_graph/call_graph_builder.py +0 -0
  21. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/call_graph/call_resolver.py +0 -0
  22. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/call_graph/context_models.py +0 -0
  23. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/call_graph/cross_file_resolver.py +0 -0
  24. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/call_graph/execution_tracker.py +0 -0
  25. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/call_graph/flow_builder.py +0 -0
  26. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/call_graph/models.py +0 -0
  27. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/core/__init__.py +0 -0
  28. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/core/ast_context.py +0 -0
  29. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/core/class_extractor.py +0 -0
  30. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/core/function_extractor.py +0 -0
  31. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/explain/__init__.py +0 -0
  32. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/explain/docstring_extractor.py +0 -0
  33. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/explain/repo_summary_generator.py +0 -0
  34. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/explain/return_analyzer.py +0 -0
  35. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/explain/risk_flags.py +0 -0
  36. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/explain/signature_extractor.py +0 -0
  37. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/explain/summary_generator.py +0 -0
  38. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/graph/__init__.py +0 -0
  39. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/graph/callgraph_index.py +0 -0
  40. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/graph/entrypoint_detector.py +0 -0
  41. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/graph/impact_analyzer.py +0 -0
  42. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/indexing/__init__.py +0 -0
  43. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/indexing/import_resolver.py +0 -0
  44. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/indexing/symbol_index.py +0 -0
  45. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/runners/__init__.py +0 -0
  46. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/utils/__init__.py +0 -0
  47. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/utils/ast_helpers.py +0 -0
  48. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/utils/cache_manager.py +0 -0
  49. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/utils/path_resolver.py +0 -0
  50. {codemap_python-0.1.1 → codemap_python-0.1.3}/analysis/utils/repo_fetcher.py +0 -0
  51. {codemap_python-0.1.1 → codemap_python-0.1.3}/cli.py +0 -0
  52. {codemap_python-0.1.1 → codemap_python-0.1.3}/codemap_cli.py +0 -0
  53. {codemap_python-0.1.1 → codemap_python-0.1.3}/codemap_python.egg-info/dependency_links.txt +0 -0
  54. {codemap_python-0.1.1 → codemap_python-0.1.3}/codemap_python.egg-info/entry_points.txt +0 -0
  55. {codemap_python-0.1.1 → codemap_python-0.1.3}/codemap_python.egg-info/requires.txt +0 -0
  56. {codemap_python-0.1.1 → codemap_python-0.1.3}/codemap_python.egg-info/top_level.txt +0 -0
  57. {codemap_python-0.1.1 → codemap_python-0.1.3}/security_utils.py +0 -0
  58. {codemap_python-0.1.1 → codemap_python-0.1.3}/setup.cfg +0 -0
  59. {codemap_python-0.1.1 → codemap_python-0.1.3}/tests/test_cache_cli_commands.py +0 -0
  60. {codemap_python-0.1.1 → codemap_python-0.1.3}/tests/test_cache_retention.py +0 -0
  61. {codemap_python-0.1.1 → codemap_python-0.1.3}/tests/test_no_key_persistence.py +0 -0
  62. {codemap_python-0.1.1 → codemap_python-0.1.3}/tests/test_registry_session_mode.py +0 -0
  63. {codemap_python-0.1.1 → codemap_python-0.1.3}/tests/test_security_cli_integration.py +0 -0
  64. {codemap_python-0.1.1 → codemap_python-0.1.3}/tests/test_security_redaction.py +0 -0
  65. {codemap_python-0.1.1 → codemap_python-0.1.3}/tests/test_symbol_explain_cache.py +0 -0
  66. {codemap_python-0.1.1 → codemap_python-0.1.3}/tests/test_symbol_info_endpoint.py +0 -0
  67. {codemap_python-0.1.1 → codemap_python-0.1.3}/tests/test_ui_private_mode_security.py +0 -0
  68. {codemap_python-0.1.1 → codemap_python-0.1.3}/tests/test_ui_retention_controls.py +0 -0
  69. {codemap_python-0.1.1 → codemap_python-0.1.3}/ui/__init__.py +0 -0
  70. {codemap_python-0.1.1 → codemap_python-0.1.3}/ui/device_id.py +0 -0
  71. {codemap_python-0.1.1 → codemap_python-0.1.3}/ui/static/app.js +0 -0
  72. {codemap_python-0.1.1 → codemap_python-0.1.3}/ui/static/styles.css +0 -0
  73. {codemap_python-0.1.1 → codemap_python-0.1.3}/ui/templates/index.html +0 -0
  74. {codemap_python-0.1.1 → codemap_python-0.1.3}/ui/utils/__init__.py +0 -0
  75. {codemap_python-0.1.1 → codemap_python-0.1.3}/ui/utils/registry_manager.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codemap-python
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: Local Python code analysis tool - understand architecture, dependencies, and call graphs
5
5
  Author-email: ADITYA <aditykushwaha69@gmail.com>
6
6
  License: MIT
@@ -1,6 +1,7 @@
1
1
  # AST Call detection
2
2
 
3
3
  import ast
4
+ from analysis.utils.bom_handler import remove_bom
4
5
 
5
6
  class FunctionCallVisitor(ast.NodeVisitor):
6
7
  def __init__(self, file_path):
@@ -83,7 +84,11 @@ class FunctionCallVisitor(ast.NodeVisitor):
83
84
 
84
85
  def extract_function_calls(file_path):
85
86
  with open(file_path, "r", encoding="utf-8") as f:
86
- tree = ast.parse(f.read())
87
+ source = f.read()
88
+
89
+ # Remove BOM if present
90
+ source = remove_bom(source)
91
+ tree = ast.parse(source)
87
92
 
88
93
  visitor = FunctionCallVisitor(file_path)
89
94
  visitor.visit(tree)
@@ -0,0 +1,31 @@
1
+ # AST Parser Module
2
+ import ast
3
+ from analysis.utils.bom_handler import remove_bom
4
+
5
+
6
+ def parse_python_file(file_path):
7
+ """Parse a Python file, automatically handling UTF-8 BOM.
8
+
9
+ This function:
10
+ 1. Reads the file with UTF-8 encoding
11
+ 2. Removes any BOM characters automatically
12
+ 3. Parses the cleaned source code
13
+
14
+ Args:
15
+ file_path: Path to Python file to parse
16
+
17
+ Returns:
18
+ ast.Module: Parsed AST tree
19
+
20
+ Raises:
21
+ SyntaxError: If source code has syntax errors
22
+ FileNotFoundError: If file doesn't exist
23
+ """
24
+ with open(file_path, "r", encoding="utf-8") as f:
25
+ source = f.read()
26
+
27
+ # Remove BOM if present (handles files from Windows editors, etc.)
28
+ source = remove_bom(source)
29
+
30
+ return ast.parse(source)
31
+
@@ -2,11 +2,17 @@
2
2
  # analysis/import_extractor.py
3
3
 
4
4
  import ast
5
+ from analysis.utils.bom_handler import remove_bom
6
+
5
7
 
6
8
  def extract_imports(file_path):
9
+ """Extract imports from a Python file, handling UTF-8 BOM automatically."""
7
10
  with open(file_path, "r", encoding="utf-8") as f:
8
11
  source = f.read()
9
12
 
13
+ # Remove BOM if present
14
+ source = remove_bom(source)
15
+
10
16
  tree = ast.parse(source)
11
17
  imports = []
12
18
 
@@ -8,6 +8,7 @@ from typing import Optional, Dict, Any
8
8
  import ast
9
9
  import json
10
10
  import os
11
+ from analysis.utils.bom_handler import remove_bom
11
12
 
12
13
  from analysis.indexing.symbol_index import SymbolIndex, SymbolInfo
13
14
  from analysis.graph.callgraph_index import CallGraphIndex, CallSite
@@ -27,8 +28,12 @@ def collect_python_files(root_dir: str):
27
28
 
28
29
 
29
30
  def parse_ast(file_path: str) -> ast.AST:
31
+ """Parse a Python file, automatically handling UTF-8 BOM."""
30
32
  with open(file_path, "r", encoding="utf-8") as f:
31
- return ast.parse(f.read())
33
+ source = f.read()
34
+ # Remove BOM if present
35
+ source = remove_bom(source)
36
+ return ast.parse(source)
32
37
 
33
38
 
34
39
  def file_to_module(file_path: str, repo_root: str) -> str:
@@ -12,6 +12,7 @@ from analysis.call_graph.cross_file_resolver import CrossFileResolver
12
12
  from analysis.call_graph.call_extractor import extract_function_calls
13
13
  from analysis.core.import_extractor import extract_imports
14
14
  from analysis.graph.callgraph_index import build_caller_fqn
15
+ from analysis.utils.bom_handler import remove_bom
15
16
 
16
17
 
17
18
  PROJECT_ROOT = os.path.dirname(os.path.dirname(__file__))
@@ -29,8 +30,12 @@ def collect_python_files(root_dir: str) -> List[str]:
29
30
 
30
31
 
31
32
  def parse_ast(file_path: str):
33
+ """Parse a Python file, automatically handling UTF-8 BOM."""
32
34
  with open(file_path, "r", encoding="utf-8") as f:
33
- return ast.parse(f.read())
35
+ source = f.read()
36
+ # Remove BOM if present
37
+ source = remove_bom(source)
38
+ return ast.parse(source)
34
39
 
35
40
 
36
41
  def file_to_module(file_path: str, repo_root: str) -> str:
@@ -0,0 +1,55 @@
1
+ """BOM (Byte Order Mark) handling utilities for CodeMap.
2
+
3
+ This module provides utilities to handle UTF-8 BOM characters that are
4
+ sometimes added to Python files by certain editors (especially on Windows).
5
+
6
+ BOM (U+FEFF) is an invisible character that Python's AST parser cannot handle,
7
+ causing: "invalid non-printable character U+FEFF"
8
+
9
+ Solution: Strip BOM before parsing Python files.
10
+ """
11
+
12
+
13
+ def remove_bom(source: str) -> str:
14
+ """Remove UTF-8 BOM (Byte Order Mark) from source code if present.
15
+
16
+ BOM is a special character (U+FEFF) that some editors (especially Notepad
17
+ on Windows) add to the start of files. Python's AST parser doesn't handle it.
18
+
19
+ This function silently removes it if present, or returns the source unchanged.
20
+
21
+ Args:
22
+ source: Python source code as string
23
+
24
+ Returns:
25
+ Source code with BOM removed if present
26
+
27
+ Example:
28
+ >>> source_with_bom = '\\ufeffdef hello(): pass'
29
+ >>> clean_source = remove_bom(source_with_bom)
30
+ >>> print(clean_source)
31
+ def hello(): pass
32
+ """
33
+ if source.startswith('\ufeff'):
34
+ return source[1:]
35
+ return source
36
+
37
+
38
+ def read_source_file(file_path: str) -> str:
39
+ """Read a Python file and remove BOM if present.
40
+
41
+ This is a convenience function that combines file reading with BOM removal.
42
+
43
+ Args:
44
+ file_path: Path to Python file to read
45
+
46
+ Returns:
47
+ Source code with BOM removed
48
+
49
+ Raises:
50
+ FileNotFoundError: If file doesn't exist
51
+ UnicodeDecodeError: If file encoding is not UTF-8
52
+ """
53
+ with open(file_path, "r", encoding="utf-8") as f:
54
+ source = f.read()
55
+ return remove_bom(source)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codemap-python
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: Local Python code analysis tool - understand architecture, dependencies, and call graphs
5
5
  Author-email: ADITYA <aditykushwaha69@gmail.com>
6
6
  License: MIT
@@ -42,6 +42,7 @@ analysis/runners/__init__.py
42
42
  analysis/runners/phase4_runner.py
43
43
  analysis/utils/__init__.py
44
44
  analysis/utils/ast_helpers.py
45
+ analysis/utils/bom_handler.py
45
46
  analysis/utils/cache_manager.py
46
47
  analysis/utils/path_resolver.py
47
48
  analysis/utils/repo_fetcher.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "codemap-python"
7
- version = "0.1.1"
7
+ version = "0.1.3"
8
8
  description = "Local Python code analysis tool - understand architecture, dependencies, and call graphs"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -36,20 +36,24 @@ from security_utils import redact_payload, redact_secrets
36
36
 
37
37
 
38
38
  # Custom cache class that doesn't cache (to avoid TypeError with unhashable Request objects)
39
- class NoCache:
40
- """A cache implementation that doesn't cache anything.
39
+ class NoCache(dict):
40
+ """A dict-like cache implementation that doesn't actually cache anything.
41
41
 
42
42
  This prevents Jinja2 from trying to cache templates with unhashable objects
43
- like the Starlette Request in the context.
43
+ like the Starlette Request in the context. Inherits from dict to satisfy
44
+ Jinja2's duck-typing requirements while not actually storing anything.
44
45
  """
45
- def get(self, key: Any, default: Any = None) -> Any:
46
- return default
47
-
48
- def set(self, key: Any, value: Any, timeout: Any = None) -> None:
46
+ def __setitem__(self, key: Any, value: Any) -> None:
47
+ """Silently ignore all cache assignments."""
49
48
  pass
50
49
 
51
- def clear(self) -> None:
52
- pass
50
+ def __getitem__(self, key: Any) -> Any:
51
+ """Always return KeyError to indicate cache miss."""
52
+ raise KeyError(key)
53
+
54
+ def get(self, key: Any, default: Any = None) -> Any:
55
+ """Always return the default value (cache miss)."""
56
+ return default
53
57
 
54
58
 
55
59
  PROJECT_ROOT = os.path.dirname(os.path.dirname(__file__))
@@ -1,8 +0,0 @@
1
- # AST Parser Module
2
- import ast
3
- def parse_python_file(file_path):
4
- with open(file_path, "r", encoding="utf-8") as f:
5
- source = f.read()
6
-
7
- return ast.parse(source)
8
-
File without changes
File without changes
File without changes