shadow-tools 0.2.1__tar.gz → 0.2.2__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.
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/PKG-INFO +10 -1
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/README.md +9 -0
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/pyproject.toml +1 -1
- shadow_tools-0.2.2/release-0.2.1/shadow_tools-0.2.1-py3-none-any.whl +0 -0
- shadow_tools-0.2.2/release-0.2.1/shadow_tools-0.2.1.tar.gz +0 -0
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/src/shadowtools/__init__.py +3 -3
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/src/shadowtools/network.py +14 -0
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/tests/test_core.py +2 -1
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/.gitignore +0 -0
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/LICENSE +0 -0
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/release-0.2.0/shadow_tools-0.2.0-py3-none-any.whl +0 -0
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/release-0.2.0/shadow_tools-0.2.0.tar.gz +0 -0
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/src/shadowtools/ai.py +0 -0
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/src/shadowtools/async_tools.py +0 -0
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/src/shadowtools/cli.py +0 -0
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/src/shadowtools/data.py +0 -0
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/src/shadowtools/files.py +0 -0
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/src/shadowtools/http.py +0 -0
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/src/shadowtools/validation.py +0 -0
- {shadow_tools-0.2.1 → shadow_tools-0.2.2}/src/shadowtools/websocket.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: shadow-tools
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A practical all-in-one Python toolkit for HTTP, WebSockets, files, data, validation, async work, and CLIs.
|
|
5
5
|
Project-URL: Homepage, https://github.com/WilliamLaurento/shadow-tools
|
|
6
6
|
Project-URL: Issues, https://github.com/WilliamLaurento/shadow-tools/issues
|
|
@@ -68,6 +68,15 @@ print(generate_random_ips(5)) # mixed private, public, and special IPv4 address
|
|
|
68
68
|
print(generate_random_ips(3, family=6))
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
+
Reverse-DNS lookup for IP addresses:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from shadowtools import generate_random_ips, reverse_dns
|
|
75
|
+
|
|
76
|
+
for ip in generate_random_ips(5):
|
|
77
|
+
print(reverse_dns(ip))
|
|
78
|
+
```
|
|
79
|
+
|
|
71
80
|
## AI app helpers
|
|
72
81
|
|
|
73
82
|
```python
|
|
@@ -44,6 +44,15 @@ print(generate_random_ips(5)) # mixed private, public, and special IPv4 address
|
|
|
44
44
|
print(generate_random_ips(3, family=6))
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
Reverse-DNS lookup for IP addresses:
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from shadowtools import generate_random_ips, reverse_dns
|
|
51
|
+
|
|
52
|
+
for ip in generate_random_ips(5):
|
|
53
|
+
print(reverse_dns(ip))
|
|
54
|
+
```
|
|
55
|
+
|
|
47
56
|
## AI app helpers
|
|
48
57
|
|
|
49
58
|
```python
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "shadow-tools"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "A practical all-in-one Python toolkit for HTTP, WebSockets, files, data, validation, async work, and CLIs."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
Binary file
|
|
Binary file
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
from .data import read_csv, read_json, write_csv, write_json
|
|
4
4
|
from .files import append_text, ensure_dir, read_text, write_text
|
|
5
5
|
from .http import get, request
|
|
6
|
-
from .network import generate_random_ips, generate_test_ips, is_subdomain_of, make_subdomain, resolve_dns
|
|
6
|
+
from .network import generate_random_ips, generate_test_ips, is_subdomain_of, make_subdomain, resolve_dns, reverse_dns
|
|
7
7
|
from .validation import is_email, is_url, require_keys
|
|
8
8
|
|
|
9
|
-
__version__ = "0.2.
|
|
9
|
+
__version__ = "0.2.2"
|
|
10
10
|
|
|
11
11
|
__all__ = [
|
|
12
12
|
"append_text", "ensure_dir", "generate_random_ips", "generate_test_ips", "get", "is_email", "is_subdomain_of", "is_url", "make_subdomain", "read_csv",
|
|
13
13
|
"read_json", "read_text", "request", "require_keys", "write_csv",
|
|
14
|
-
"write_json", "write_text", "resolve_dns",
|
|
14
|
+
"write_json", "write_text", "resolve_dns", "reverse_dns",
|
|
15
15
|
]
|
|
@@ -17,6 +17,20 @@ def resolve_dns(hostname: str) -> dict[str, list[str]]:
|
|
|
17
17
|
return {kind: sorted(addresses) for kind, addresses in results.items()}
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
def reverse_dns(ip: str) -> dict[str, object]:
|
|
21
|
+
"""Look up the DNS name assigned to one IPv4 or IPv6 address.
|
|
22
|
+
|
|
23
|
+
An address without a PTR record returns ``hostname: None`` instead of
|
|
24
|
+
raising an exception.
|
|
25
|
+
"""
|
|
26
|
+
address = ipaddress.ip_address(ip)
|
|
27
|
+
try:
|
|
28
|
+
hostname, aliases, _ = socket.gethostbyaddr(str(address))
|
|
29
|
+
return {"ip": str(address), "hostname": hostname, "aliases": aliases}
|
|
30
|
+
except (socket.herror, socket.gaierror):
|
|
31
|
+
return {"ip": str(address), "hostname": None, "aliases": []}
|
|
32
|
+
|
|
33
|
+
|
|
20
34
|
def is_subdomain_of(hostname: str, domain: str) -> bool:
|
|
21
35
|
"""Return whether hostname is the domain itself or one of its subdomains."""
|
|
22
36
|
cleaned_host = hostname.lower().rstrip(".")
|
|
@@ -5,7 +5,7 @@ import pytest
|
|
|
5
5
|
from shadowtools.async_tools import run_all
|
|
6
6
|
from shadowtools.data import read_csv, read_json, write_csv, write_json
|
|
7
7
|
from shadowtools.files import append_text, read_text, write_text
|
|
8
|
-
from shadowtools.network import generate_random_ips, generate_test_ips, is_subdomain_of, make_subdomain
|
|
8
|
+
from shadowtools.network import generate_random_ips, generate_test_ips, is_subdomain_of, make_subdomain, reverse_dns
|
|
9
9
|
from shadowtools.ai import prompt, tool_schema
|
|
10
10
|
from shadowtools.validation import is_email, is_url, require_keys
|
|
11
11
|
|
|
@@ -43,5 +43,6 @@ def test_network_and_ai_helpers():
|
|
|
43
43
|
assert generate_test_ips(1)[0].startswith("192.0.2.")
|
|
44
44
|
assert len(generate_random_ips(3)) == 3
|
|
45
45
|
assert len(generate_random_ips(2, family=6)) == 2
|
|
46
|
+
assert reverse_dns("0.0.0.0")["hostname"] is None
|
|
46
47
|
assert prompt("Hi {name}", name="Will") == "Hi Will"
|
|
47
48
|
assert tool_schema("lookup_dns", "Lookup DNS", {"host": {"type": "string"}})["name"] == "lookup_dns"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|