pretty-mod 0.0.1__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.
@@ -0,0 +1,20 @@
1
+ name: Publish to PyPI
2
+ on:
3
+ release:
4
+ types: [published]
5
+ workflow_dispatch:
6
+
7
+ jobs:
8
+ publish-pypi-release:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: Checkout
12
+ uses: actions/checkout@v4
13
+ with:
14
+ fetch-depth: 0
15
+ - run: python3 -m pip install --upgrade build && python3 -m build
16
+ - name: Publish package
17
+ uses: pypa/gh-action-pypi-publish@release/v1
18
+ with:
19
+ password: ${{ secrets.PYPI_API_TOKEN }}
20
+ verbose: true
@@ -0,0 +1,26 @@
1
+ name: Run static analysis
2
+
3
+ on:
4
+ push:
5
+ branches: ["main"]
6
+ pull_request:
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ static_analysis:
14
+ timeout-minutes: 1
15
+
16
+ runs-on: ubuntu-latest
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ - name: Install uv and set the python version
21
+ uses: astral-sh/setup-uv@v5
22
+ with:
23
+ python-version: "3.10"
24
+ - uses: extractions/setup-just@v3
25
+ - name: Run pre-commit
26
+ run: uv run pre-commit run --all-files
@@ -0,0 +1,41 @@
1
+ name: Run tests
2
+
3
+ on:
4
+ push:
5
+ branches: ["main"]
6
+ paths:
7
+ - "src/**/*.py"
8
+ - "tests/**/*.py"
9
+
10
+ pull_request:
11
+ paths:
12
+ - "src/**/*.py"
13
+ - "tests/**/*.py"
14
+ workflow_dispatch:
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ run_tests:
21
+ # Skip the entire job for fork PRs
22
+ if: ${{ !(github.event.pull_request.head.repo.fork) }}
23
+ name: Python ${{ matrix.python-version }} on ${{ matrix.os }}
24
+ timeout-minutes: 10
25
+ strategy:
26
+ matrix:
27
+ os: [ubuntu-latest]
28
+ python-version: ["3.10"]
29
+
30
+ runs-on: ${{ matrix.os }}
31
+
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+
35
+ - name: Install uv and set the python version
36
+ uses: astral-sh/setup-uv@v5
37
+ with:
38
+ python-version: ${{ matrix.python-version }}
39
+
40
+ - name: Run tests
41
+ run: uv run --frozen pytest
@@ -0,0 +1,13 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ # Environment variables
13
+ .env
@@ -0,0 +1,21 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ # Ruff version.
4
+ rev: v0.9.1
5
+ hooks:
6
+ # Run the linter.
7
+ - id: ruff
8
+ args: [--fix]
9
+ # Run the formatter.
10
+ - id: ruff-format
11
+ - repo: https://github.com/astral-sh/uv-pre-commit
12
+ rev: 0.7.3
13
+ hooks:
14
+ - id: uv-lock
15
+ - repo: local
16
+ hooks:
17
+ - id: ty-check
18
+ name: Typecheck
19
+ entry: just typecheck
20
+ language: system
21
+ pass_filenames: false
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.4
2
+ Name: pretty-mod
3
+ Version: 0.0.1
4
+ Summary: A module tree explorer for humans and LLMs
5
+ Author-email: zzstoatzz <thrast36@gmail.com>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+
9
+ # pretty-mod
10
+
11
+ A module tree explorer for humans and LLMs.
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ uv add pretty-mod
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ```python
22
+ from pretty_mod.explorer import ModuleTreeExplorer
23
+
24
+ # Explore a module structure
25
+ explorer = ModuleTreeExplorer("json", max_depth=2)
26
+ explorer.explore()
27
+ print(explorer.get_tree_string())
28
+ ```
29
+
30
+ <details>
31
+ <summary>Example output</summary>
32
+
33
+ ```text
34
+ 📦 json
35
+ └── 📜 __all__: dump, dumps, load, loads, JSONDecoder, JSONDecodeError, JSONEncoder
36
+ ├── ⚡ functions: dump, dumps, load, loads
37
+ ├── 📦 decoder
38
+ ├── 📜 __all__: JSONDecoder, JSONDecodeError
39
+ ├── 🔷 classes: JSONDecodeError, JSONDecoder
40
+ ├── 📦 encoder
41
+ ├── 🔷 classes: JSONEncoder
42
+ ├── ⚡ functions: py_encode_basestring, py_encode_basestring_ascii
43
+ ├── 📦 scanner
44
+ ├── 📜 __all__: make_scanner
45
+ └── 📦 tool
46
+ └── ⚡ functions: main
47
+ ```
48
+ </details>
49
+
50
+
51
+
52
+ ```python
53
+ from pretty_mod.explorer import display_signature
54
+
55
+ # Display function signatures
56
+ print(display_signature("json:loads"))
57
+ ```
58
+
59
+ <details>
60
+ <summary>Example output</summary>
61
+
62
+ ```text
63
+ 📎 loads
64
+ ├── Parameters:
65
+ ├── s
66
+ ├── cls = None (keyword-only)
67
+ ├── object_hook = None (keyword-only)
68
+ ├── parse_float = None (keyword-only)
69
+ ├── parse_int = None (keyword-only)
70
+ ├── parse_constant = None (keyword-only)
71
+ ├── object_pairs_hook = None (keyword-only)
72
+ └── kw (**kwargs)
73
+ ```
74
+ </details>
75
+
76
+ ## Examples
77
+
78
+ See the [`examples/`](examples/) directory for more detailed usage patterns and advanced features.
79
+
80
+ ## Development
81
+
82
+ ```bash
83
+ git clone https://github.com/zzstoatzz/pretty-mod.git
84
+ cd pretty-mod
85
+ uv sync
86
+ uv run pytest
87
+ ```
@@ -0,0 +1,79 @@
1
+ # pretty-mod
2
+
3
+ A module tree explorer for humans and LLMs.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ uv add pretty-mod
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```python
14
+ from pretty_mod.explorer import ModuleTreeExplorer
15
+
16
+ # Explore a module structure
17
+ explorer = ModuleTreeExplorer("json", max_depth=2)
18
+ explorer.explore()
19
+ print(explorer.get_tree_string())
20
+ ```
21
+
22
+ <details>
23
+ <summary>Example output</summary>
24
+
25
+ ```text
26
+ 📦 json
27
+ └── 📜 __all__: dump, dumps, load, loads, JSONDecoder, JSONDecodeError, JSONEncoder
28
+ ├── ⚡ functions: dump, dumps, load, loads
29
+ ├── 📦 decoder
30
+ ├── 📜 __all__: JSONDecoder, JSONDecodeError
31
+ ├── 🔷 classes: JSONDecodeError, JSONDecoder
32
+ ├── 📦 encoder
33
+ ├── 🔷 classes: JSONEncoder
34
+ ├── ⚡ functions: py_encode_basestring, py_encode_basestring_ascii
35
+ ├── 📦 scanner
36
+ ├── 📜 __all__: make_scanner
37
+ └── 📦 tool
38
+ └── ⚡ functions: main
39
+ ```
40
+ </details>
41
+
42
+
43
+
44
+ ```python
45
+ from pretty_mod.explorer import display_signature
46
+
47
+ # Display function signatures
48
+ print(display_signature("json:loads"))
49
+ ```
50
+
51
+ <details>
52
+ <summary>Example output</summary>
53
+
54
+ ```text
55
+ 📎 loads
56
+ ├── Parameters:
57
+ ├── s
58
+ ├── cls = None (keyword-only)
59
+ ├── object_hook = None (keyword-only)
60
+ ├── parse_float = None (keyword-only)
61
+ ├── parse_int = None (keyword-only)
62
+ ├── parse_constant = None (keyword-only)
63
+ ├── object_pairs_hook = None (keyword-only)
64
+ └── kw (**kwargs)
65
+ ```
66
+ </details>
67
+
68
+ ## Examples
69
+
70
+ See the [`examples/`](examples/) directory for more detailed usage patterns and advanced features.
71
+
72
+ ## Development
73
+
74
+ ```bash
75
+ git clone https://github.com/zzstoatzz/pretty-mod.git
76
+ cd pretty-mod
77
+ uv sync
78
+ uv run pytest
79
+ ```
@@ -0,0 +1,44 @@
1
+ # Pretty-Mod Examples
2
+
3
+ This directory contains practical examples demonstrating how to use `pretty-mod` for module exploration and code understanding.
4
+
5
+ ## Examples
6
+
7
+ ### 📚 `basic_usage.py`
8
+ Demonstrates core functionality:
9
+ - Exploring module structures with `ModuleTreeExplorer`
10
+ - Displaying function signatures with `display_signature`
11
+ - Dynamic imports with `import_object`
12
+ - Working with different exploration depths
13
+
14
+ **Run it:**
15
+ ```bash
16
+ uv run python examples/basic_usage.py
17
+ ```
18
+
19
+ ### 🚀 `advanced_exploration.py`
20
+ Shows practical use cases:
21
+ - Comparing APIs across related modules
22
+ - Generating module summaries
23
+ - Finding similar functions across codebases
24
+ - Interactive exploration patterns for unfamiliar code
25
+
26
+ **Run it:**
27
+ ```bash
28
+ uv run python examples/advanced_exploration.py
29
+ ```
30
+
31
+ ## Key Use Cases
32
+
33
+ - **Code Discovery**: Quickly understand the structure of unfamiliar modules
34
+ - **API Comparison**: Compare similar libraries to understand differences
35
+ - **Documentation**: Generate overviews of module capabilities
36
+ - **LLM Integration**: Perfect for AI assistants exploring codebases
37
+ - **Interactive Development**: Dynamically explore and test code
38
+
39
+ ## Tips
40
+
41
+ - Start with shallow exploration (`max_depth=1`) for quick overviews
42
+ - Use deeper exploration for detailed analysis
43
+ - Combine signature display with dynamic imports for testing
44
+ - Great for exploring both built-in and third-party modules
@@ -0,0 +1,200 @@
1
+ """
2
+ Advanced exploration examples for pretty-mod.
3
+
4
+ This example shows practical use cases for exploring and understanding codebases,
5
+ particularly useful for LLMs and developers working with unfamiliar modules.
6
+ """
7
+
8
+ from pretty_mod.explorer import ModuleTreeExplorer, display_signature
9
+
10
+
11
+ def compare_module_apis():
12
+ """Compare APIs of related modules to understand their differences."""
13
+ print("🔄 Comparing related module APIs:")
14
+ print("=" * 60)
15
+
16
+ modules = ["json", "pickle", "csv"]
17
+
18
+ for module_name in modules:
19
+ print(f"\n📦 {module_name.upper()} module API:")
20
+ print("-" * 30)
21
+
22
+ explorer = ModuleTreeExplorer(module_name, max_depth=1)
23
+ tree = explorer.explore()
24
+
25
+ api = tree.get("api", {})
26
+
27
+ if api.get("functions"):
28
+ print(f"Functions: {', '.join(sorted(api['functions']))}")
29
+ if api.get("classes"):
30
+ print(f"Classes: {', '.join(sorted(api['classes']))}")
31
+ if api.get("constants"):
32
+ print(f"Constants: {', '.join(sorted(api['constants']))}")
33
+
34
+
35
+ def explore_third_party_module():
36
+ """Example of exploring a third-party module (if available)."""
37
+ print("\n🌐 Exploring third-party modules:")
38
+ print("=" * 60)
39
+
40
+ # Try to explore common third-party modules
41
+ modules_to_try = ["requests", "numpy", "pandas", "pathlib"]
42
+
43
+ for module_name in modules_to_try:
44
+ try:
45
+ explorer = ModuleTreeExplorer(module_name, max_depth=1)
46
+ tree = explorer.explore()
47
+
48
+ if tree.get("api"):
49
+ print(f"\n✅ Found {module_name}:")
50
+ print(explorer.get_tree_string())
51
+ break
52
+ except Exception:
53
+ continue
54
+ else:
55
+ print("\n⚠️ No common third-party modules found.")
56
+ print("Try installing requests or another package to see this in action!")
57
+
58
+
59
+ def function_signature_analysis():
60
+ """Analyze function signatures to understand usage patterns."""
61
+ print("\n🔍 Function Signature Analysis:")
62
+ print("=" * 60)
63
+
64
+ # Functions with different signature patterns
65
+ functions = [
66
+ ("builtins:print", "Built-in with *args"),
67
+ ("json:dumps", "Serialization function"),
68
+ ("os.path:join", "Path manipulation"),
69
+ ("re:match", "Pattern matching"),
70
+ ]
71
+
72
+ for func_path, description in functions:
73
+ try:
74
+ print(f"\n{description}:")
75
+ print(display_signature(func_path))
76
+ except Exception as e:
77
+ print(f"❌ Could not analyze {func_path}: {e}")
78
+
79
+
80
+ def find_similar_functions():
81
+ """Find functions with similar names across different modules."""
82
+ print("\n🎯 Finding similar functions across modules:")
83
+ print("=" * 60)
84
+
85
+ target_functions = ["loads", "dumps", "open"]
86
+ modules = ["json", "pickle", "os"]
87
+
88
+ for func_name in target_functions:
89
+ print(f"\nLooking for '{func_name}' functions:")
90
+
91
+ for module_name in modules:
92
+ try:
93
+ explorer = ModuleTreeExplorer(module_name, max_depth=1)
94
+ tree = explorer.explore()
95
+ functions = tree.get("api", {}).get("functions", [])
96
+
97
+ matching = [f for f in functions if func_name in f.lower()]
98
+ if matching:
99
+ print(f" 📦 {module_name}: {', '.join(matching)}")
100
+ except Exception:
101
+ continue
102
+
103
+
104
+ def generate_module_summary():
105
+ """Generate a comprehensive summary of a module."""
106
+ print("\n📊 Module Summary Generator:")
107
+ print("=" * 60)
108
+
109
+ module_name = "datetime"
110
+ explorer = ModuleTreeExplorer(module_name, max_depth=2)
111
+ tree = explorer.explore()
112
+
113
+ print(f"Summary for '{module_name}' module:")
114
+ print("-" * 40)
115
+
116
+ api = tree.get("api", {})
117
+ submodules = tree.get("submodules", {})
118
+
119
+ # Main module stats
120
+ print(f"Classes: {len(api.get('classes', []))}")
121
+ print(f"Functions: {len(api.get('functions', []))}")
122
+ print(f"Constants: {len(api.get('constants', []))}")
123
+ print(f"Submodules: {len(submodules)}")
124
+
125
+ if api.get("all"):
126
+ print(f"Public API (__all__): {len(api['all'])} items")
127
+
128
+ # Show class details
129
+ if api.get("classes"):
130
+ print(f"\nMain classes: {', '.join(api['classes'][:5])}")
131
+ if len(api["classes"]) > 5:
132
+ print(f"... and {len(api['classes']) - 5} more")
133
+
134
+ # Show submodule details
135
+ if submodules:
136
+ print("\nSubmodules:")
137
+ for sub_name, sub_tree in list(submodules.items())[:3]:
138
+ sub_api = sub_tree.get("api", {})
139
+ total_items = (
140
+ len(sub_api.get("classes", []))
141
+ + len(sub_api.get("functions", []))
142
+ + len(sub_api.get("constants", []))
143
+ )
144
+ print(f" 📦 {sub_name}: {total_items} public items")
145
+
146
+
147
+ def interactive_exploration():
148
+ """Show how to use pretty-mod for interactive exploration."""
149
+ print("\n🎮 Interactive Exploration Pattern:")
150
+ print("=" * 60)
151
+
152
+ print("Here's how you might explore an unfamiliar module step by step:")
153
+ print()
154
+
155
+ # Step 1: High-level overview
156
+ print("1. Get a high-level overview:")
157
+ print(" explorer = ModuleTreeExplorer('os', max_depth=1)")
158
+ print(" print(explorer.get_tree_string())")
159
+ print()
160
+
161
+ # Step 2: Deep dive
162
+ print("2. Deep dive into interesting submodules:")
163
+ print(" explorer = ModuleTreeExplorer('os.path', max_depth=2)")
164
+ print(" print(explorer.get_tree_string())")
165
+ print()
166
+
167
+ # Step 3: Function analysis
168
+ print("3. Analyze specific functions:")
169
+ print(" print(display_signature('os.path:join'))")
170
+ print(" print(display_signature('os:getcwd'))")
171
+ print()
172
+
173
+ # Step 4: Dynamic testing
174
+ print("4. Dynamically import and test:")
175
+ print(" join_func = import_object('os.path:join')")
176
+ print(" result = join_func('home', 'user', 'documents')")
177
+ print()
178
+
179
+ # Demonstrate this pattern
180
+ print("Let's run this pattern on the 'pathlib' module:")
181
+ try:
182
+ explorer = ModuleTreeExplorer("pathlib", max_depth=1)
183
+ explorer.explore()
184
+ print(explorer.get_tree_string())
185
+ except Exception as e:
186
+ print(f"Could not explore pathlib: {e}")
187
+
188
+
189
+ if __name__ == "__main__":
190
+ print("🚀 Advanced pretty-mod exploration examples")
191
+ print("=" * 70)
192
+
193
+ compare_module_apis()
194
+ explore_third_party_module()
195
+ function_signature_analysis()
196
+ find_similar_functions()
197
+ generate_module_summary()
198
+ interactive_exploration()
199
+
200
+ print("\n🎯 These patterns help you quickly understand any Python codebase!")
@@ -0,0 +1,93 @@
1
+ """
2
+ Basic usage examples for pretty-mod.
3
+
4
+ This example demonstrates how to explore module structures and display function signatures.
5
+ """
6
+
7
+ from pretty_mod.explorer import ModuleTreeExplorer, display_signature, import_object
8
+
9
+
10
+ def explore_json_module():
11
+ """Example: Explore the built-in json module structure."""
12
+ print("🔍 Exploring the json module:")
13
+ print("=" * 50)
14
+
15
+ explorer = ModuleTreeExplorer("json", max_depth=2)
16
+ explorer.explore()
17
+
18
+ # Display the tree structure
19
+ tree_string = explorer.get_tree_string()
20
+ print(tree_string)
21
+ print()
22
+
23
+
24
+ def explore_function_signature():
25
+ """Example: Display function signatures in a readable format."""
26
+ print("📋 Function Signature Examples:")
27
+ print("=" * 50)
28
+
29
+ # Example with a built-in function
30
+ print("Built-in function:")
31
+ print(display_signature("builtins:len"))
32
+ print()
33
+
34
+ # Example with a module function
35
+ print("Module function:")
36
+ print(display_signature("json:loads"))
37
+ print()
38
+
39
+
40
+ def import_and_use_objects():
41
+ """Example: Import objects dynamically using import paths."""
42
+ print("📦 Dynamic Import Examples:")
43
+ print("=" * 50)
44
+
45
+ # Import using colon syntax
46
+ json_loads = import_object("json:loads")
47
+ print(f"Imported json.loads: {json_loads}")
48
+
49
+ # Test the imported function
50
+ test_data = '{"name": "pretty-mod", "type": "module"}'
51
+ parsed = json_loads(test_data)
52
+ print(f"Parsed JSON: {parsed}")
53
+ print()
54
+
55
+ # Import using dot syntax
56
+ sys_version = import_object("sys.version_info")
57
+ print(
58
+ f"Python version: {sys_version.major}.{sys_version.minor}.{sys_version.micro}"
59
+ )
60
+ print()
61
+
62
+
63
+ def explore_custom_depth():
64
+ """Example: Explore modules with different depth limits."""
65
+ print("🏗️ Exploring with different depths:")
66
+ print("=" * 50)
67
+
68
+ # Shallow exploration
69
+ print("Shallow exploration (depth=1):")
70
+ explorer_shallow = ModuleTreeExplorer("urllib", max_depth=1)
71
+ explorer_shallow.explore()
72
+ print(explorer_shallow.get_tree_string())
73
+ print()
74
+
75
+ # Deeper exploration
76
+ print("Deeper exploration (depth=2):")
77
+ explorer_deep = ModuleTreeExplorer("urllib", max_depth=2)
78
+ explorer_deep.explore()
79
+ print(explorer_deep.get_tree_string())
80
+ print()
81
+
82
+
83
+ if __name__ == "__main__":
84
+ print("🎉 Welcome to pretty-mod examples!")
85
+ print("=" * 60)
86
+ print()
87
+
88
+ explore_json_module()
89
+ explore_function_signature()
90
+ import_and_use_objects()
91
+ explore_custom_depth()
92
+
93
+ print("✨ That's pretty-mod in action! ✨")
@@ -0,0 +1,36 @@
1
+ # Check for uv installation
2
+ check-uv:
3
+ #!/usr/bin/env sh
4
+ if ! command -v uv >/dev/null 2>&1; then
5
+ echo "uv is not installed or not found in expected locations."
6
+ case "$(uname)" in
7
+ "Darwin")
8
+ echo "To install uv on macOS, run one of:"
9
+ echo "• brew install uv"
10
+ echo "• curl -LsSf https://astral.sh/uv/install.sh | sh"
11
+ ;;
12
+ "Linux")
13
+ echo "To install uv, run:"
14
+ echo "• curl -LsSf https://astral.sh/uv/install.sh | sh"
15
+ ;;
16
+ *)
17
+ echo "To install uv, visit: https://github.com/astral-sh/uv"
18
+ ;;
19
+ esac
20
+ exit 1
21
+ fi
22
+
23
+ # Install development dependencies
24
+ install: check-uv
25
+ uv sync
26
+
27
+ typecheck: check-uv
28
+ uv run ty check
29
+
30
+ # Clean up environment
31
+ clean: check-uv
32
+ deactivate || true
33
+ rm -rf .venv
34
+
35
+ run-pre-commits: check-uv
36
+ uv run pre-commit run --all-files
@@ -0,0 +1,34 @@
1
+ [project]
2
+ name = "pretty-mod"
3
+ description = "A module tree explorer for humans and LLMs"
4
+ readme = "README.md"
5
+ authors = [{ name = "zzstoatzz", email = "thrast36@gmail.com" }]
6
+ requires-python = ">=3.10"
7
+ dynamic = ["version"]
8
+ dependencies = []
9
+
10
+ [dependency-groups]
11
+ dev = ["pytest-sugar", "ruff", "ty", "ipython", "pre-commit"]
12
+
13
+ [build-system]
14
+ requires = ["hatchling>=1.21.0", "hatch-vcs>=0.4.0"]
15
+ build-backend = "hatchling.build"
16
+
17
+ [tool.hatch.build.targets.wheel]
18
+ packages = ["src/pretty_mod"]
19
+
20
+ [tool.hatch.metadata]
21
+ allow-direct-references = true
22
+
23
+ [tool.hatch.version]
24
+ source = "vcs"
25
+
26
+ [tool.ruff.lint]
27
+ extend-select = ["I", "UP"]
28
+
29
+ [tool.ty.src]
30
+ root = "./src"
31
+
32
+ [tool.pytest.ini_options]
33
+ testpaths = ["tests"]
34
+ addopts = ["-v", "--strict-markers"]