linkinpycli 0.0.1__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.
- linkinpycli/__init__.py +0 -0
- linkinpycli/crawler.py +18 -0
- linkinpycli/linkinpycli.py +117 -0
- linkinpycli-0.0.1.dist-info/METADATA +69 -0
- linkinpycli-0.0.1.dist-info/RECORD +8 -0
- linkinpycli-0.0.1.dist-info/WHEEL +4 -0
- linkinpycli-0.0.1.dist-info/entry_points.txt +2 -0
- linkinpycli-0.0.1.dist-info/licenses/LICENSE.txt +22 -0
linkinpycli/__init__.py
ADDED
|
File without changes
|
linkinpycli/crawler.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from importlib.metadata import EntryPoint, entry_points
|
|
2
|
+
|
|
3
|
+
LINKINPY_SCRIPT_PREFIX = "linkinpy"
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def find_linkinpy_entry_points() -> list[EntryPoint]:
|
|
7
|
+
"""Find all console-script entry points that start with 'linkinpy'."""
|
|
8
|
+
return [
|
|
9
|
+
ep
|
|
10
|
+
for ep in entry_points(group="console_scripts")
|
|
11
|
+
if ep.name.startswith(LINKINPY_SCRIPT_PREFIX)
|
|
12
|
+
and ep.name != "linkinpy-parse"
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def find_linkinpy_scripts() -> list[str]:
|
|
17
|
+
"""Find all console scripts that start with 'linkinpy'."""
|
|
18
|
+
return [ep.name for ep in find_linkinpy_entry_points()]
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import inspect
|
|
4
|
+
import json
|
|
5
|
+
from importlib import import_module
|
|
6
|
+
from importlib.metadata import EntryPoint
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from .crawler import find_linkinpy_entry_points
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
_IGNORED_SIGNATURE_PARAMETERS = {"argv", "args", "kwargs"}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _format_datatype(annotation: object) -> str:
|
|
16
|
+
if annotation is inspect.Signature.empty:
|
|
17
|
+
return "Any"
|
|
18
|
+
if isinstance(annotation, str):
|
|
19
|
+
return annotation.replace("pathlib.", "")
|
|
20
|
+
if getattr(annotation, "__module__", "") == "builtins":
|
|
21
|
+
return annotation.__name__
|
|
22
|
+
return str(annotation).replace("pathlib.", "")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _format_default(default: object) -> object:
|
|
26
|
+
if default is inspect.Signature.empty:
|
|
27
|
+
return None
|
|
28
|
+
if isinstance(default, (str, int, float, bool)) or default is None:
|
|
29
|
+
return default
|
|
30
|
+
return repr(default)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _signature_arguments(callable_object: object) -> list[dict[str, object]]:
|
|
34
|
+
signature = inspect.signature(callable_object)
|
|
35
|
+
arguments = []
|
|
36
|
+
for name, parameter in signature.parameters.items():
|
|
37
|
+
if name in _IGNORED_SIGNATURE_PARAMETERS:
|
|
38
|
+
continue
|
|
39
|
+
if parameter.kind in (
|
|
40
|
+
inspect.Parameter.VAR_POSITIONAL,
|
|
41
|
+
inspect.Parameter.VAR_KEYWORD,
|
|
42
|
+
):
|
|
43
|
+
continue
|
|
44
|
+
arguments.append(
|
|
45
|
+
{
|
|
46
|
+
"name": name,
|
|
47
|
+
"datatype": _format_datatype(parameter.annotation),
|
|
48
|
+
"required": parameter.default is inspect.Signature.empty,
|
|
49
|
+
"default": _format_default(parameter.default),
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
return arguments
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _entry_point_reference(entry_point: EntryPoint) -> str:
|
|
56
|
+
return f"{entry_point.module}:{entry_point.attr}"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _resolve_callable(entry_point: EntryPoint) -> object:
|
|
60
|
+
module = import_module(entry_point.module)
|
|
61
|
+
entry_callable = entry_point.load()
|
|
62
|
+
entry_arguments = _signature_arguments(entry_callable)
|
|
63
|
+
if entry_arguments:
|
|
64
|
+
return entry_callable
|
|
65
|
+
|
|
66
|
+
expected_name = entry_point.name.replace("-", "_")
|
|
67
|
+
expected_callable = getattr(module, expected_name, None)
|
|
68
|
+
if callable(expected_callable):
|
|
69
|
+
return expected_callable
|
|
70
|
+
|
|
71
|
+
linkinpy_callables = [
|
|
72
|
+
obj
|
|
73
|
+
for name, obj in inspect.getmembers(module, inspect.isfunction)
|
|
74
|
+
if name.startswith("linkinpy") and name not in {"linkinpy_parse"}
|
|
75
|
+
]
|
|
76
|
+
if len(linkinpy_callables) == 1:
|
|
77
|
+
return linkinpy_callables[0]
|
|
78
|
+
|
|
79
|
+
return entry_callable
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _script_details(entry_point: EntryPoint) -> dict[str, object]:
|
|
83
|
+
details: dict[str, object] = {
|
|
84
|
+
"name": entry_point.name,
|
|
85
|
+
"entry_point": _entry_point_reference(entry_point),
|
|
86
|
+
"arguments": [],
|
|
87
|
+
}
|
|
88
|
+
try:
|
|
89
|
+
callable_object = _resolve_callable(entry_point)
|
|
90
|
+
details["callable"] = (
|
|
91
|
+
f"{callable_object.__module__}:{callable_object.__name__}"
|
|
92
|
+
)
|
|
93
|
+
details["arguments"] = _signature_arguments(callable_object)
|
|
94
|
+
except Exception as exc:
|
|
95
|
+
details["error"] = str(exc)
|
|
96
|
+
return details
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def parse_linkinpy_scripts() -> None:
|
|
100
|
+
"""Find LinkinPy console scripts and write their argument metadata to scripts.json."""
|
|
101
|
+
scripts = [
|
|
102
|
+
_script_details(entry_point)
|
|
103
|
+
for entry_point in find_linkinpy_entry_points()
|
|
104
|
+
]
|
|
105
|
+
output_path = Path.cwd() / "scripts.json"
|
|
106
|
+
output_path.write_text(
|
|
107
|
+
json.dumps({"scripts": scripts}, indent=2) + "\n",
|
|
108
|
+
encoding="utf-8",
|
|
109
|
+
)
|
|
110
|
+
print(f"Saved {len(scripts)} scripts to {output_path}")
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class LinkinPyCLI:
|
|
114
|
+
"""Minimal example class generated by the template."""
|
|
115
|
+
|
|
116
|
+
def run(self) -> int:
|
|
117
|
+
return 1
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: linkinpycli
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: CLI finder for LinkinPy integration
|
|
5
|
+
Project-URL: Homepage, https://github.com/HenriquesLab/LinkinPy
|
|
6
|
+
Project-URL: Repository, https://github.com/HenriquesLab/LinkinPy
|
|
7
|
+
Project-URL: Issues, https://github.com/HenriquesLab/LinkinPy/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/HenriquesLab/LinkinPy/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: brunomsaraiva <bruno.msaraiva2@gmail.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE.txt
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# linkinpycli
|
|
21
|
+
|
|
22
|
+
CLI finder for LinkinPy integration
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
uv sync
|
|
28
|
+
uv run pytest
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The project pins its local development interpreter in `.python-version` and keeps package metadata in `pyproject.toml`.
|
|
32
|
+
|
|
33
|
+
## Common Commands
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
uv sync # create/update the local environment
|
|
37
|
+
uv run pytest # run the test suite
|
|
38
|
+
uv run ruff check . # lint the codebase
|
|
39
|
+
uv run ruff format . # format the codebase
|
|
40
|
+
uv run python -m build # build the source and wheel distributions
|
|
41
|
+
uv run pre-commit install
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
If you prefer shorter aliases, the same workflow is available through `make`:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
make sync
|
|
48
|
+
make test
|
|
49
|
+
make lint
|
|
50
|
+
make format
|
|
51
|
+
make build
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Project Layout
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
src/linkinpycli/
|
|
58
|
+
tests/
|
|
59
|
+
pyproject.toml
|
|
60
|
+
.python-version
|
|
61
|
+
GETTING_STARTED.md
|
|
62
|
+
CONTRIBUTING.md
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Documentation
|
|
66
|
+
|
|
67
|
+
- Start with [GETTING_STARTED.md](GETTING_STARTED.md) for first-time setup
|
|
68
|
+
- See [CONTRIBUTING.md](CONTRIBUTING.md) for the contributor workflow
|
|
69
|
+
- Track user-facing changes in [CHANGELOG.md](CHANGELOG.md)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
linkinpycli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
linkinpycli/crawler.py,sha256=lPhzleGG4JJCV2VuLIr3uQehVkKXwh-5dmVXyL13gU0,571
|
|
3
|
+
linkinpycli/linkinpycli.py,sha256=ZEHSOgjlfiVER4Jh0oE_qThNP599lOxVKhp-zomF-L4,3620
|
|
4
|
+
linkinpycli-0.0.1.dist-info/METADATA,sha256=c3Q8uQ02z0z1zcVhXsVXKPIPjyc9BITte40l7Kcd26c,1834
|
|
5
|
+
linkinpycli-0.0.1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
6
|
+
linkinpycli-0.0.1.dist-info/entry_points.txt,sha256=9IQg5_h0an5eW-A60MDc6N4Lv34cPGyFQC446H5kf4U,82
|
|
7
|
+
linkinpycli-0.0.1.dist-info/licenses/LICENSE.txt,sha256=WrrpqqQd_VEVy37iiIgoICGcWlYfAsWTsHC44JK0OGM,1079
|
|
8
|
+
linkinpycli-0.0.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
The MIT License (MIT)
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 linkinpycli
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in
|
|
14
|
+
all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
22
|
+
THE SOFTWARE.
|