pkgq 0.1.0__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.
pkgq-0.1.0/.gitignore ADDED
@@ -0,0 +1,37 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.pyo
5
+ *.egg-info/
6
+ .eggs/
7
+ *.egg
8
+ dist/
9
+ build/
10
+
11
+ # Virtual environments
12
+ .venv/
13
+ venv/
14
+ env/
15
+
16
+ # IDE
17
+ .vscode/
18
+ .idea/
19
+ *.swp
20
+ *.swo
21
+
22
+ # Testing
23
+ .pytest_cache/
24
+ .coverage
25
+ htmlcov/
26
+ .tox/
27
+
28
+ # Type checking
29
+ .mypy_cache/
30
+
31
+ # System
32
+ .DS_Store
33
+ Thumbs.db
34
+
35
+ # Local
36
+ *.local.*
37
+ .env
pkgq-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Christophe VG
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
pkgq-0.1.0/Makefile ADDED
@@ -0,0 +1,37 @@
1
+ # pkgq Makefile
2
+
3
+ .PHONY: help install test lint build publish clean
4
+
5
+ # Installation
6
+ help:
7
+ @echo "pkgq - Package Query"
8
+ @echo ""
9
+ @echo "Commands:"
10
+ @echo " make install - Install dependencies"
11
+ @echo " make test - Run tests"
12
+ @echo " make lint - Run linter"
13
+ @echo " make build - Build package"
14
+ @echo " make publish - Publish to PyPI"
15
+ @echo " make clean - Clean build artifacts"
16
+
17
+ install:
18
+ uv sync
19
+
20
+ test:
21
+ uv run pytest -v
22
+
23
+ lint:
24
+ uv run ruff check src/
25
+ uv run mypy src/
26
+
27
+ build:
28
+ uv build
29
+
30
+ publish: build
31
+ uv publish
32
+
33
+ clean:
34
+ rm -rf dist/
35
+ rm -rf .venv/
36
+ find . -type d -name "__pycache__" -exec rm -rf {} +
37
+ find . -type f -name "*.pyc" -delete
pkgq-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,155 @@
1
+ Metadata-Version: 2.4
2
+ Name: pkgq
3
+ Version: 0.1.0
4
+ Summary: Package Query - Find API information for Python packages
5
+ Project-URL: Homepage, https://github.com/christophevg/pkgq
6
+ Project-URL: Documentation, https://github.com/christophevg/pkgq#readme
7
+ Project-URL: Repository, https://github.com/christophevg/pkgq
8
+ Project-URL: Issues, https://github.com/christophevg/pkgq/issues
9
+ Author-email: Christophe VG <contact@christophe.vg>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: agent,api,documentation,mcp,package,query
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: httpx>=0.27.0
23
+ Requires-Dist: pydantic>=2.0.0
24
+ Requires-Dist: rich>=13.0.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: build>=1.0.0; extra == 'dev'
27
+ Requires-Dist: mypy>=1.13.0; extra == 'dev'
28
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
29
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
30
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
31
+ Requires-Dist: ruff>=0.8.0; extra == 'dev'
32
+ Requires-Dist: twine>=6.0.0; extra == 'dev'
33
+ Provides-Extra: mcp
34
+ Requires-Dist: fastmcp>=3.0.0; extra == 'mcp'
35
+ Description-Content-Type: text/markdown
36
+
37
+ # pkgq
38
+
39
+ **PacKaGe Query** - Find API information for Python packages.
40
+
41
+ A fast, agent-friendly tool for discovering Python package documentation, capabilities, and migration guides.
42
+
43
+ ## Installation
44
+
45
+ ```bash
46
+ # Install with uv
47
+ uv add pkgq
48
+
49
+ # Or with pip
50
+ pip install pkgq
51
+
52
+ # For MCP server support
53
+ uv add "pkgq[mcp]"
54
+ ```
55
+
56
+ ## Usage
57
+
58
+ ### Python Module
59
+
60
+ ```python
61
+ from pkgq import find
62
+
63
+ # Find package documentation
64
+ result = find("yoker")
65
+ print(result.content)
66
+
67
+ # Find specific version
68
+ result = find("yoker", version="2.1.0")
69
+
70
+ # Check for updates
71
+ result = find("yoker", from_version="1.5.0")
72
+ if result.version != "1.5.0":
73
+ print(f"Update available: {result.version}")
74
+
75
+ # Save to cache
76
+ result.save_to_cache()
77
+ ```
78
+
79
+ ### Command Line
80
+
81
+ ```bash
82
+ # Find package documentation
83
+ pkgq find yoker
84
+
85
+ # Find specific version
86
+ pkgq find yoker --version 2.1.0
87
+
88
+ # Check for updates
89
+ pkgq find yoker --from-version 1.5.0
90
+
91
+ # Save to cache
92
+ pkgq find yoker --save
93
+
94
+ # Output as JSON
95
+ pkgq find yoker --json
96
+
97
+ # Manage cache
98
+ pkgq cache --list
99
+ pkgq cache --clear
100
+ pkgq cache --dir
101
+ ```
102
+
103
+ ### MCP Server
104
+
105
+ ```bash
106
+ # Run MCP server
107
+ pkgq-mcp-server
108
+
109
+ # Or with uvx
110
+ uvx --from pkgq pkgq-mcp-server
111
+ ```
112
+
113
+ The MCP server provides a `find_package` tool for use with Claude Code and other MCP-compatible agents.
114
+
115
+ ## Cache
116
+
117
+ Package documentation is cached locally:
118
+
119
+ - Default: `~/.cache/pkgq/packages/`
120
+ - Custom: Set `PKGQ_CACHE` environment variable
121
+
122
+ Cache structure:
123
+ ```
124
+ ~/.cache/pkgq/packages/
125
+ ├── yoker/
126
+ │ ├── PACKAGE.md # Package documentation
127
+ │ └── metadata.json # Version and source info
128
+ └── roomz/
129
+ ├── PACKAGE.md
130
+ └── metadata.json
131
+ ```
132
+
133
+ ## Development
134
+
135
+ ```bash
136
+ # Clone repository
137
+ git clone https://github.com/christophevg/pkgq.git
138
+ cd pkgq
139
+
140
+ # Install dependencies
141
+ uv sync
142
+
143
+ # Run tests
144
+ uv run pytest
145
+
146
+ # Run linter
147
+ uv run ruff check src/
148
+
149
+ # Run MCP server
150
+ uv run pkgq-mcp-server
151
+ ```
152
+
153
+ ## License
154
+
155
+ MIT License - See [LICENSE](LICENSE) for details.
pkgq-0.1.0/README.md ADDED
@@ -0,0 +1,119 @@
1
+ # pkgq
2
+
3
+ **PacKaGe Query** - Find API information for Python packages.
4
+
5
+ A fast, agent-friendly tool for discovering Python package documentation, capabilities, and migration guides.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ # Install with uv
11
+ uv add pkgq
12
+
13
+ # Or with pip
14
+ pip install pkgq
15
+
16
+ # For MCP server support
17
+ uv add "pkgq[mcp]"
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Python Module
23
+
24
+ ```python
25
+ from pkgq import find
26
+
27
+ # Find package documentation
28
+ result = find("yoker")
29
+ print(result.content)
30
+
31
+ # Find specific version
32
+ result = find("yoker", version="2.1.0")
33
+
34
+ # Check for updates
35
+ result = find("yoker", from_version="1.5.0")
36
+ if result.version != "1.5.0":
37
+ print(f"Update available: {result.version}")
38
+
39
+ # Save to cache
40
+ result.save_to_cache()
41
+ ```
42
+
43
+ ### Command Line
44
+
45
+ ```bash
46
+ # Find package documentation
47
+ pkgq find yoker
48
+
49
+ # Find specific version
50
+ pkgq find yoker --version 2.1.0
51
+
52
+ # Check for updates
53
+ pkgq find yoker --from-version 1.5.0
54
+
55
+ # Save to cache
56
+ pkgq find yoker --save
57
+
58
+ # Output as JSON
59
+ pkgq find yoker --json
60
+
61
+ # Manage cache
62
+ pkgq cache --list
63
+ pkgq cache --clear
64
+ pkgq cache --dir
65
+ ```
66
+
67
+ ### MCP Server
68
+
69
+ ```bash
70
+ # Run MCP server
71
+ pkgq-mcp-server
72
+
73
+ # Or with uvx
74
+ uvx --from pkgq pkgq-mcp-server
75
+ ```
76
+
77
+ The MCP server provides a `find_package` tool for use with Claude Code and other MCP-compatible agents.
78
+
79
+ ## Cache
80
+
81
+ Package documentation is cached locally:
82
+
83
+ - Default: `~/.cache/pkgq/packages/`
84
+ - Custom: Set `PKGQ_CACHE` environment variable
85
+
86
+ Cache structure:
87
+ ```
88
+ ~/.cache/pkgq/packages/
89
+ ├── yoker/
90
+ │ ├── PACKAGE.md # Package documentation
91
+ │ └── metadata.json # Version and source info
92
+ └── roomz/
93
+ ├── PACKAGE.md
94
+ └── metadata.json
95
+ ```
96
+
97
+ ## Development
98
+
99
+ ```bash
100
+ # Clone repository
101
+ git clone https://github.com/christophevg/pkgq.git
102
+ cd pkgq
103
+
104
+ # Install dependencies
105
+ uv sync
106
+
107
+ # Run tests
108
+ uv run pytest
109
+
110
+ # Run linter
111
+ uv run ruff check src/
112
+
113
+ # Run MCP server
114
+ uv run pkgq-mcp-server
115
+ ```
116
+
117
+ ## License
118
+
119
+ MIT License - See [LICENSE](LICENSE) for details.
@@ -0,0 +1,106 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "pkgq"
7
+ version = "0.1.0"
8
+ description = "Package Query - Find API information for Python packages"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{name = "Christophe VG", email = "contact@christophe.vg"}]
14
+ keywords = ["package", "query", "api", "documentation", "mcp", "agent"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Typing :: Typed",
24
+ ]
25
+
26
+ dependencies = [
27
+ "httpx>=0.27.0",
28
+ "pydantic>=2.0.0",
29
+ "rich>=13.0.0",
30
+ ]
31
+
32
+ [project.optional-dependencies]
33
+ mcp = [
34
+ "fastmcp>=3.0.0",
35
+ ]
36
+ dev = [
37
+ "pytest>=8.0.0",
38
+ "pytest-asyncio>=0.23.0",
39
+ "pytest-cov>=5.0.0",
40
+ "mypy>=1.13.0",
41
+ "ruff>=0.8.0",
42
+ "build>=1.0.0",
43
+ "twine>=6.0.0",
44
+ ]
45
+
46
+ [project.scripts]
47
+ pkgq = "pkgq.cli:main"
48
+ pkgq-mcp-server = "pkgq.mcp:run"
49
+
50
+ [project.urls]
51
+ Homepage = "https://github.com/christophevg/pkgq"
52
+ Documentation = "https://github.com/christophevg/pkgq#readme"
53
+ Repository = "https://github.com/christophevg/pkgq"
54
+ Issues = "https://github.com/christophevg/pkgq/issues"
55
+
56
+ [tool.hatch.build.targets.wheel]
57
+ packages = ["src/pkgq"]
58
+
59
+ [tool.pytest.ini_options]
60
+ testpaths = ["tests"]
61
+ asyncio_mode = "auto"
62
+ addopts = "-v --cov=pkgq --cov-report=term-missing"
63
+
64
+ [tool.mypy]
65
+ python_version = "3.10"
66
+ strict = true
67
+ warn_return_any = true
68
+ warn_unused_ignores = true
69
+
70
+ [tool.ruff]
71
+ line-length = 100
72
+ target-version = "py310"
73
+ indent-width = 2
74
+
75
+ [tool.ruff.lint]
76
+ select = [
77
+ "E", # pycodestyle errors
78
+ "W", # pycodestyle warnings
79
+ "F", # pyflakes
80
+ "I", # isort
81
+ "B", # flake8-bugbear
82
+ "C4", # flake8-comprehensions
83
+ "UP", # pyupgrade
84
+ ]
85
+ ignore = [
86
+ "E501", # line too long (handled by formatter)
87
+ ]
88
+
89
+ [tool.ruff.lint.isort]
90
+ known-first-party = ["pkgq"]
91
+
92
+ [tool.ruff.format]
93
+ quote-style = "double"
94
+ indent-style = "space"
95
+
96
+ [tool.coverage.run]
97
+ source = ["src"]
98
+ branch = true
99
+
100
+ [tool.coverage.report]
101
+ exclude_lines = [
102
+ "pragma: no cover",
103
+ "def __repr__",
104
+ "raise NotImplementedError",
105
+ "if TYPE_CHECKING:",
106
+ ]
@@ -0,0 +1,11 @@
1
+ """
2
+ pkgq - Package Query
3
+
4
+ Find API information for Python packages.
5
+ """
6
+
7
+ __version__ = "0.1.0"
8
+
9
+ from pkgq.find import FindResult, find
10
+
11
+ __all__ = ["find", "FindResult"]
@@ -0,0 +1,155 @@
1
+ """
2
+ pkgq CLI - Command line interface for package query.
3
+ """
4
+
5
+ import argparse
6
+ import json
7
+ import sys
8
+ from pathlib import Path
9
+
10
+ from rich.console import Console
11
+ from rich.markdown import Markdown
12
+
13
+ from pkgq import find
14
+ from pkgq.find import get_cache_dir
15
+
16
+
17
+ def main():
18
+ """Main CLI entry point."""
19
+ parser = argparse.ArgumentParser(
20
+ prog="pkgq",
21
+ description="Package Query - Find API information for Python packages",
22
+ )
23
+ subparsers = parser.add_subparsers(dest="command", help="Commands")
24
+
25
+ # find command
26
+ find_parser = subparsers.add_parser("find", help="Find package documentation")
27
+ find_parser.add_argument("package", help="Package name")
28
+ find_parser.add_argument(
29
+ "--version", "-v", help="Desired version (default: latest)"
30
+ )
31
+ find_parser.add_argument(
32
+ "--from-version", "-f", help="Current cached version (for update check)"
33
+ )
34
+ find_parser.add_argument(
35
+ "--cache-dir", "-c", type=Path, help="Cache directory"
36
+ )
37
+ find_parser.add_argument(
38
+ "--save", "-s", action="store_true", help="Save to cache"
39
+ )
40
+ find_parser.add_argument(
41
+ "--json", "-j", action="store_true", help="Output as JSON"
42
+ )
43
+ find_parser.add_argument(
44
+ "--verbose", "-V", action="store_true", help="Verbose output"
45
+ )
46
+
47
+ # cache command
48
+ cache_parser = subparsers.add_parser("cache", help="Manage cache")
49
+ cache_parser.add_argument(
50
+ "--clear", action="store_true", help="Clear cache"
51
+ )
52
+ cache_parser.add_argument(
53
+ "--list", action="store_true", help="List cached packages"
54
+ )
55
+ cache_parser.add_argument(
56
+ "--dir", action="store_true", help="Show cache directory"
57
+ )
58
+
59
+ args = parser.parse_args()
60
+
61
+ if args.command == "find":
62
+ cmd_find(args)
63
+ elif args.command == "cache":
64
+ cmd_cache(args)
65
+ else:
66
+ parser.print_help()
67
+ sys.exit(1)
68
+
69
+
70
+ def cmd_find(args):
71
+ """Handle find command."""
72
+ console = Console()
73
+
74
+ try:
75
+ result = find(
76
+ package=args.package,
77
+ version=args.version,
78
+ from_version=args.from_version,
79
+ cache_dir=args.cache_dir,
80
+ verbose=args.verbose,
81
+ )
82
+
83
+ if args.save:
84
+ cache_path = result.save_to_cache(args.cache_dir)
85
+ console.print(f"[green]Saved to:[/green] {cache_path}")
86
+
87
+ if args.json:
88
+ print(json.dumps(result.to_dict(), indent=2))
89
+ else:
90
+ # Print version info
91
+ status = "[green]cached[/green]" if result.cached else "[blue]fetched[/blue]"
92
+ console.print(f"[bold]{result.package}[/bold] {result.version} ({status})")
93
+ console.print(f"[dim]Source: {result.source}[/dim]")
94
+ console.print()
95
+
96
+ # Print content as markdown
97
+ md = Markdown(result.content)
98
+ console.print(md)
99
+
100
+ except Exception as e:
101
+ console.print(f"[red]Error:[/red] {e}")
102
+ sys.exit(1)
103
+
104
+
105
+ def cmd_cache(args):
106
+ """Handle cache command."""
107
+ console = Console()
108
+ cache_dir = get_cache_dir()
109
+
110
+ if args.dir:
111
+ console.print(str(cache_dir))
112
+ return
113
+
114
+ if args.clear:
115
+ import shutil
116
+ if cache_dir.exists():
117
+ shutil.rmtree(cache_dir)
118
+ console.print(f"[green]Cleared cache:[/green] {cache_dir}")
119
+ else:
120
+ console.print("[yellow]Cache is empty[/yellow]")
121
+ return
122
+
123
+ if args.list:
124
+ if not cache_dir.exists():
125
+ console.print("[yellow]Cache is empty[/yellow]")
126
+ return
127
+
128
+ packages = sorted(cache_dir.iterdir())
129
+ if not packages:
130
+ console.print("[yellow]Cache is empty[/yellow]")
131
+ return
132
+
133
+ console.print(f"[bold]Cached packages ({len(packages)}):[/bold]")
134
+ for pkg_dir in packages:
135
+ metadata_file = pkg_dir / "metadata.json"
136
+ if metadata_file.exists():
137
+ metadata = json.loads(metadata_file.read_text())
138
+ version = metadata.get("version", "?")
139
+ source = metadata.get("source", "?")
140
+ console.print(f" {pkg_dir.name} {version} ({source})")
141
+ else:
142
+ console.print(f" {pkg_dir.name} (no metadata)")
143
+ return
144
+
145
+ # Default: show cache info
146
+ console.print(f"Cache directory: {cache_dir}")
147
+ if cache_dir.exists():
148
+ packages = list(cache_dir.iterdir())
149
+ console.print(f"Cached packages: {len(packages)}")
150
+ else:
151
+ console.print("Cache is empty")
152
+
153
+
154
+ if __name__ == "__main__":
155
+ main()