skip-trace 0.1.0__py3-none-any.whl → 0.1.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.
- skip_trace/__about__.py +13 -3
- skip_trace/__init__.py +0 -2
- skip_trace/analysis/content_scanner.py +189 -0
- skip_trace/analysis/evidence.py +1 -1
- skip_trace/analysis/scoring.py +46 -1
- skip_trace/analysis/source_scanner.py +1 -1
- skip_trace/cli.py +1 -1
- skip_trace/collectors/__init__.py +2 -2
- skip_trace/collectors/github_files.py +359 -0
- skip_trace/collectors/package_files.py +232 -41
- skip_trace/collectors/pypi.py +1 -1
- skip_trace/collectors/pypi_attestations.py +160 -0
- skip_trace/collectors/sigstore.py +160 -0
- skip_trace/collectors/urls.py +96 -0
- skip_trace/m.py +287 -0
- skip_trace/main.py +103 -85
- skip_trace/reporting/md_reporter.py +68 -4
- skip_trace/schemas.py +21 -0
- skip_trace/utils/http_client.py +18 -0
- {skip_trace-0.1.0.dist-info → skip_trace-0.1.1.dist-info}/METADATA +7 -3
- skip_trace-0.1.1.dist-info/RECORD +39 -0
- skip_trace-0.1.0.dist-info/RECORD +0 -33
- {skip_trace-0.1.0.dist-info → skip_trace-0.1.1.dist-info}/WHEEL +0 -0
- {skip_trace-0.1.0.dist-info → skip_trace-0.1.1.dist-info}/entry_points.txt +0 -0
- {skip_trace-0.1.0.dist-info → skip_trace-0.1.1.dist-info}/licenses/LICENSE +0 -0
@@ -7,7 +7,7 @@ from typing import IO
|
|
7
7
|
from rich.console import Console
|
8
8
|
from rich.table import Table
|
9
9
|
|
10
|
-
from ..schemas import PackageResult
|
10
|
+
from ..schemas import EvidenceKind, EvidenceSource, PackageResult
|
11
11
|
|
12
12
|
|
13
13
|
def render(result: PackageResult, file: IO[str] = sys.stdout):
|
@@ -28,6 +28,12 @@ def render(result: PackageResult, file: IO[str] = sys.stdout):
|
|
28
28
|
)
|
29
29
|
console.print("-" * 80)
|
30
30
|
|
31
|
+
# --- Pre-process to find Sigstore evidence ---
|
32
|
+
sigstore_evidence = [
|
33
|
+
ev for ev in result.evidence if ev.source == EvidenceSource.SIGSTORE
|
34
|
+
]
|
35
|
+
sigstore_evidence_ids = {ev.id for ev in sigstore_evidence}
|
36
|
+
|
31
37
|
# --- OWNERS TABLE ---
|
32
38
|
if not result.owners:
|
33
39
|
console.print("\n[bold]## 🕵️ Owner Candidates[/bold]")
|
@@ -40,7 +46,7 @@ def render(result: PackageResult, file: IO[str] = sys.stdout):
|
|
40
46
|
owner_table = Table(
|
41
47
|
show_header=True,
|
42
48
|
header_style="bold magenta",
|
43
|
-
title="Top Owner Candidates",
|
49
|
+
title="Top Owner Candidates (by inferred score)",
|
44
50
|
title_style="bold",
|
45
51
|
)
|
46
52
|
owner_table.add_column("Owner", style="cyan", width=30, no_wrap=True)
|
@@ -81,14 +87,45 @@ def render(result: PackageResult, file: IO[str] = sys.stdout):
|
|
81
87
|
else "[italic]No notes.[/italic]"
|
82
88
|
)
|
83
89
|
|
90
|
+
# Check if this owner is backed by Sigstore evidence
|
91
|
+
is_verified = bool(sigstore_evidence_ids.intersection(owner.evidence))
|
92
|
+
owner_display_name = f"🛡️ {owner.name}" if is_verified else owner.name
|
93
|
+
|
84
94
|
owner_table.add_row(
|
85
|
-
|
95
|
+
owner_display_name,
|
86
96
|
owner.kind.value,
|
87
97
|
f"[{score_style}]{score_str}[/]",
|
88
98
|
contacts_str,
|
89
99
|
key_evidence_str,
|
90
100
|
)
|
91
101
|
console.print(owner_table)
|
102
|
+
console.print(
|
103
|
+
"[dim]Owners marked with 🛡️ are supported by cryptographic evidence.[/dim]"
|
104
|
+
)
|
105
|
+
|
106
|
+
# --- CRYPTOGRAPHIC EVIDENCE (SIGSTORE) ---
|
107
|
+
if sigstore_evidence:
|
108
|
+
console.print("\n[bold]## 🛡️ Cryptographic Evidence (from Sigstore)[/bold]")
|
109
|
+
sig_table = Table(
|
110
|
+
show_header=True,
|
111
|
+
header_style="bold green",
|
112
|
+
title="Verified Signatures and Provenance",
|
113
|
+
title_style="bold",
|
114
|
+
)
|
115
|
+
sig_table.add_column("Kind", style="cyan", width=25)
|
116
|
+
sig_table.add_column("Identity or Source")
|
117
|
+
sig_table.add_column("Notes")
|
118
|
+
|
119
|
+
for ev in sigstore_evidence:
|
120
|
+
kind_str = ev.kind.value.replace("sigstore-", "").replace("-", " ").title()
|
121
|
+
primary_value = ""
|
122
|
+
if ev.kind == EvidenceKind.SIGSTORE_SIGNER_IDENTITY:
|
123
|
+
primary_value = ev.value.get("identity", "[unknown]")
|
124
|
+
elif ev.kind == EvidenceKind.SIGSTORE_BUILD_PROVENANCE:
|
125
|
+
primary_value = ev.value.get("repo_uri", "[unknown]")
|
126
|
+
|
127
|
+
sig_table.add_row(kind_str, primary_value, ev.notes)
|
128
|
+
console.print(sig_table)
|
92
129
|
|
93
130
|
# --- MAINTAINERS TABLE ---
|
94
131
|
if result.maintainers:
|
@@ -96,7 +133,7 @@ def render(result: PackageResult, file: IO[str] = sys.stdout):
|
|
96
133
|
maintainer_table = Table(
|
97
134
|
show_header=True,
|
98
135
|
header_style="bold cyan",
|
99
|
-
title="Directly Listed Maintainers",
|
136
|
+
title="Directly Listed Maintainers (from PyPI)",
|
100
137
|
title_style="bold",
|
101
138
|
)
|
102
139
|
maintainer_table.add_column("Name", style="cyan")
|
@@ -112,4 +149,31 @@ def render(result: PackageResult, file: IO[str] = sys.stdout):
|
|
112
149
|
|
113
150
|
console.print(maintainer_table)
|
114
151
|
|
152
|
+
# --- URL STATUS TABLE ---
|
153
|
+
url_status_evidence = [
|
154
|
+
ev for ev in result.evidence if ev.kind == EvidenceKind.URL_STATUS
|
155
|
+
]
|
156
|
+
if url_status_evidence:
|
157
|
+
console.print("\n[bold]## 🔗 URL Analysis[/bold]")
|
158
|
+
url_table = Table(
|
159
|
+
show_header=True, header_style="bold blue", title="Checked URLs"
|
160
|
+
)
|
161
|
+
url_table.add_column("URL", style="cyan", no_wrap=True)
|
162
|
+
url_table.add_column("HTTP Status", justify="center")
|
163
|
+
|
164
|
+
for ev in sorted(url_status_evidence, key=lambda x: x.locator):
|
165
|
+
status = ev.value.get("status_code", "N/A")
|
166
|
+
status_str = str(status)
|
167
|
+
if status == -1:
|
168
|
+
status_str = "Connection Error"
|
169
|
+
style = "bold red"
|
170
|
+
elif 200 <= status < 300:
|
171
|
+
style = "green"
|
172
|
+
elif 300 <= status < 400:
|
173
|
+
style = "yellow"
|
174
|
+
else:
|
175
|
+
style = "red"
|
176
|
+
url_table.add_row(ev.locator, f"[{style}]{status_str}[/]")
|
177
|
+
console.print(url_table)
|
178
|
+
|
115
179
|
console.print("-" * 80)
|
skip_trace/schemas.py
CHANGED
@@ -2,10 +2,13 @@
|
|
2
2
|
from __future__ import annotations
|
3
3
|
|
4
4
|
import datetime
|
5
|
+
import logging
|
5
6
|
from dataclasses import dataclass, field
|
6
7
|
from enum import Enum
|
7
8
|
from typing import Any, List, Optional
|
8
9
|
|
10
|
+
logger = logging.getLogger(__name__)
|
11
|
+
|
9
12
|
# --- Enums for controlled vocabularies ---
|
10
13
|
|
11
14
|
|
@@ -44,6 +47,8 @@ class EvidenceSource(str, Enum):
|
|
44
47
|
WHOIS = "whois"
|
45
48
|
VENV_SCAN = "venv-scan"
|
46
49
|
LLM_NER = "llm-ner"
|
50
|
+
URL = "url" # For evidence from scanned homepages
|
51
|
+
PYPI_ATTESTATION = "pypi-attestation" # New source
|
47
52
|
|
48
53
|
|
49
54
|
class EvidenceKind(str, Enum):
|
@@ -66,6 +71,12 @@ class EvidenceKind(str, Enum):
|
|
66
71
|
# GitHub profile-specific evidence kinds
|
67
72
|
USER_PROFILE = "user-profile"
|
68
73
|
USER_COMPANY = "user-company"
|
74
|
+
URL_STATUS = "url-status" # To track HTTP status of found URLs
|
75
|
+
# Sigstore-specific evidence kinds
|
76
|
+
SIGSTORE_SIGNER_IDENTITY = "sigstore-signer-identity"
|
77
|
+
SIGSTORE_BUILD_PROVENANCE = "sigstore-build-provenance"
|
78
|
+
# PyPI Attestation-specific evidence kind
|
79
|
+
PYPI_PUBLISHER_ATTESTATION = "pypi-publisher-attestation"
|
69
80
|
|
70
81
|
|
71
82
|
# --- Core Data Schemas ---
|
@@ -94,6 +105,16 @@ class EvidenceRecord:
|
|
94
105
|
confidence: float = 0.0
|
95
106
|
notes: str = ""
|
96
107
|
|
108
|
+
def __post_init__(self) -> None:
|
109
|
+
"""Logs every instantiation."""
|
110
|
+
logger.info(
|
111
|
+
"EvidenceRecord created: id=%s source=%s kind=%s notes=%r",
|
112
|
+
self.id,
|
113
|
+
self.source,
|
114
|
+
self.kind,
|
115
|
+
self.notes,
|
116
|
+
)
|
117
|
+
|
97
118
|
|
98
119
|
@dataclass
|
99
120
|
class OwnerCandidate:
|
skip_trace/utils/http_client.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# skip_trace/utils/http_client.py
|
2
2
|
from __future__ import annotations
|
3
3
|
|
4
|
+
import logging
|
4
5
|
from typing import Optional
|
5
6
|
|
6
7
|
import httpx
|
@@ -9,6 +10,7 @@ from ..config import CONFIG
|
|
9
10
|
from ..exceptions import NetworkError
|
10
11
|
|
11
12
|
_client: Optional[httpx.Client] = None
|
13
|
+
logger = logging.getLogger(__name__)
|
12
14
|
|
13
15
|
|
14
16
|
def get_client() -> httpx.Client:
|
@@ -32,6 +34,7 @@ def make_request(url: str) -> httpx.Response:
|
|
32
34
|
:raises NetworkError: If the request fails due to network issues or an error status code.
|
33
35
|
:return: The httpx.Response object.
|
34
36
|
"""
|
37
|
+
logger.info(f"Looking at {url}")
|
35
38
|
client = get_client()
|
36
39
|
try:
|
37
40
|
response = client.get(url)
|
@@ -43,3 +46,18 @@ def make_request(url: str) -> httpx.Response:
|
|
43
46
|
raise NetworkError(
|
44
47
|
f"Request to {e.request.url} failed with status {e.response.status_code}"
|
45
48
|
) from e
|
49
|
+
|
50
|
+
|
51
|
+
def make_request_safe(url: str) -> Optional[httpx.Response]:
|
52
|
+
"""
|
53
|
+
Makes a GET request but returns the response even on HTTP error codes,
|
54
|
+
or None if a connection-level error occurs.
|
55
|
+
"""
|
56
|
+
logger.info(f"Looking at {url}")
|
57
|
+
client = get_client()
|
58
|
+
try:
|
59
|
+
response = client.get(url)
|
60
|
+
return response
|
61
|
+
except httpx.RequestError as e:
|
62
|
+
logger.warning(f"Network request to {e.request.url} failed: {e}")
|
63
|
+
return None # Indicate a connection-level error
|
@@ -1,12 +1,15 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: skip-trace
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.1
|
4
4
|
Summary: Ownership Attribution for Python Packages
|
5
5
|
Project-URL: Homepage, https://github.com/matthewdeanmartin/skip-trace
|
6
6
|
Project-URL: Issues, https://github.com/matthewdeanmartin/skip-trace/issues
|
7
7
|
Author-email: Matthew Dean Martin <matthewdeanmartin@gmail.com>
|
8
|
+
License-Expression: MIT
|
8
9
|
License-File: LICENSE
|
9
|
-
|
10
|
+
Keywords: PEP 541,PyPI maintainers,package owners,package provenance,software supply chain
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
10
13
|
Classifier: Operating System :: OS Independent
|
11
14
|
Classifier: Programming Language :: Python :: 3
|
12
15
|
Classifier: Programming Language :: Python :: 3.9
|
@@ -16,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
16
19
|
Classifier: Programming Language :: Python :: 3.13
|
17
20
|
Classifier: Topic :: Security
|
18
21
|
Classifier: Topic :: Software Development :: Quality Assurance
|
19
|
-
Requires-Python: >=3.
|
22
|
+
Requires-Python: >=3.13
|
20
23
|
Requires-Dist: beautifulsoup4>=4.12.0
|
21
24
|
Requires-Dist: email-validator>=2.0.0
|
22
25
|
Requires-Dist: en-core-web-sm
|
@@ -27,6 +30,7 @@ Requires-Dist: pygithub>=1.59.0
|
|
27
30
|
Requires-Dist: python-dotenv
|
28
31
|
Requires-Dist: python-dotenv>=1.0.0
|
29
32
|
Requires-Dist: python-whois>=0.8.0
|
33
|
+
Requires-Dist: pyyaml>=6.0
|
30
34
|
Requires-Dist: rich-argparse
|
31
35
|
Requires-Dist: rich>=13.0.0
|
32
36
|
Requires-Dist: sigstore>=1.0.0
|
@@ -0,0 +1,39 @@
|
|
1
|
+
skip_trace/__about__.py,sha256=FsjvZ9_bL7XRX3JSfSw-8MGl8izBdAyC2zBiG2sCT-Q,660
|
2
|
+
skip_trace/__init__.py,sha256=t4sAc1NJDDj90Z1o1FwYnPMqpJgV1pDt4hlPuTlpykE,106
|
3
|
+
skip_trace/__main__.py,sha256=auCXP2BqRl6sPSrYr-_c5jA8fFKcOKTBTL2J9gMeFl0,144
|
4
|
+
skip_trace/cli.py,sha256=kHgr_jXkWWo6rthXU18c4qE5ur0Upc1wywkfzeTg9VA,5492
|
5
|
+
skip_trace/config.py,sha256=BHM8TuJ_jWDhr1uz9hAAwA3eJwu_m-pYmAvnx_TcCcw,4735
|
6
|
+
skip_trace/exceptions.py,sha256=MnMlTjPYrvtB_1j-CAHwmlggjfNCDiRiThjXyuX70Js,581
|
7
|
+
skip_trace/m.py,sha256=pmASLEmxc_V5snLxW90SXdmCQMphuCdcsZ6C399LLLo,10536
|
8
|
+
skip_trace/main.py,sha256=pmASLEmxc_V5snLxW90SXdmCQMphuCdcsZ6C399LLLo,10536
|
9
|
+
skip_trace/py.typed.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
|
+
skip_trace/schemas.py,sha256=jyK4HfJLNJTFfdXnSOKbRX_KQH1kxsLlhpeJ3izFEhA,3874
|
11
|
+
skip_trace/analysis/__init__.py,sha256=7bOZj8CbG7Ezl9w_Z9gZCuO456psxecJCmPLxljFiuo,135
|
12
|
+
skip_trace/analysis/content_scanner.py,sha256=B22moAVvPrl_IgdILYHVggIuUBYrGuvlqXL8xLIuYJg,6414
|
13
|
+
skip_trace/analysis/evidence.py,sha256=OSUS2SAlQCn6V6BJpzCKk_jxU_3Fzqv0EIH5AyRHln4,11661
|
14
|
+
skip_trace/analysis/ner.py,sha256=Ckcbyeza7fkDV-oGWTfakowLeWcybTzUpWjJ5bMlIwA,1607
|
15
|
+
skip_trace/analysis/scoring.py,sha256=Cfs54CjHjMwrC3y_Ab5CzmGyouf_wqepvGfNrxhfBAM,12312
|
16
|
+
skip_trace/analysis/source_scanner.py,sha256=CF3q5hXjSLMQHpQIzjSYlEMnTIJCMnWy24sK6RZN2w8,15272
|
17
|
+
skip_trace/collectors/__init__.py,sha256=R3ZEXSqLvecVghzxQ3c-pbTulgVddPVUSEwqFb3hLbU,193
|
18
|
+
skip_trace/collectors/github.py,sha256=CIwapS1UO6qLnoVyTHe7vLi159d6qRqCk9YRRk7jb7g,8575
|
19
|
+
skip_trace/collectors/github_files.py,sha256=APCavmVJ4ux3pUdSm2Ak2Fmdd6VplISqxqiFI_qj7so,13866
|
20
|
+
skip_trace/collectors/package_files.py,sha256=3rCtDMROF25N8anHy1UWLG1tPgSsNhR_zBYeKZ-MuoE,12936
|
21
|
+
skip_trace/collectors/pypi.py,sha256=nZVl7sDrnUBTKLsinU1TWbMm_CES6oGVUtQUKS21ues,6200
|
22
|
+
skip_trace/collectors/pypi_attestations.py,sha256=gc9_tPgEgyEr29nB0v2qSYGKUmEWsvi-qyukAVaz85Y,5807
|
23
|
+
skip_trace/collectors/sigstore.py,sha256=WWzRtx28pSQD-emqu-m6yAKiudOM6F0o49hSRWrwEao,6267
|
24
|
+
skip_trace/collectors/urls.py,sha256=XQ-2u48qTxQk175xFUBB4k6XA0t95rr34FBfmUBgV-E,3327
|
25
|
+
skip_trace/collectors/whois.py,sha256=tQYI30IbRMlHEwn3FRSdKYX_c2TJLyMUyhLdIxpXU4o,6953
|
26
|
+
skip_trace/reporting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
|
+
skip_trace/reporting/json_reporter.py,sha256=VInt34k3Zo41y7SKkOnjxRj_gsB932GaAZsBj93Fvfc,610
|
28
|
+
skip_trace/reporting/md_reporter.py,sha256=ZAZW9xm1VxKjgfgei_sFFFEfu5csMTU1ry9Qg75k3Dc,6819
|
29
|
+
skip_trace/utils/__init__.py,sha256=Wm-u-aQCpDEGL5wiRHWQ1ZwNQvA2iSLRpDNeb46_2P8,126
|
30
|
+
skip_trace/utils/cache.py,sha256=K6k0MXuf3fDr1ecjThV3qhZFHYhgCi0K69i27SoJmAY,2415
|
31
|
+
skip_trace/utils/cli_suggestions.py,sha256=pDNqfLhcYWEqvFM4jiOsUGXlqvTZxpWHR_O1hoCvzyM,2886
|
32
|
+
skip_trace/utils/http_client.py,sha256=kZwloPE-kXguOL9ZoQ_joT7OB8-AAin17AnqVHX7PPw,1939
|
33
|
+
skip_trace/utils/safe_targz.py,sha256=ETOJc5VA9A5KDhlaV9N15tLbTFABA0zSQob9eXnKQPc,5233
|
34
|
+
skip_trace/utils/validation.py,sha256=cgPcmkVEoHZ9vkvntycckxpQM5UbrVpUvUCb0S2FZrs,1427
|
35
|
+
skip_trace-0.1.1.dist-info/METADATA,sha256=KiJqLaPCUgxXlVHKgflAiN3t-toCcPt_MzaOXNsvNEA,8571
|
36
|
+
skip_trace-0.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
37
|
+
skip_trace-0.1.1.dist-info/entry_points.txt,sha256=zR7je0FG4CxaLIfaONVMi9LgmKfWtbYkrTVLclrTwhg,51
|
38
|
+
skip_trace-0.1.1.dist-info/licenses/LICENSE,sha256=CDE_-1UnY5KRaDCIuCdNg7j7lkGCJbtZWTbhB10QeLk,1071
|
39
|
+
skip_trace-0.1.1.dist-info/RECORD,,
|
@@ -1,33 +0,0 @@
|
|
1
|
-
skip_trace/__about__.py,sha256=aouD5xOQKs7wYRs0yiZysx-VWoCOqWX915NaDSofMR4,468
|
2
|
-
skip_trace/__init__.py,sha256=UkTfkLRuPO5XBc9_6IYHDXqGB_t8AfCZSzAdMS8AuyE,129
|
3
|
-
skip_trace/__main__.py,sha256=auCXP2BqRl6sPSrYr-_c5jA8fFKcOKTBTL2J9gMeFl0,144
|
4
|
-
skip_trace/cli.py,sha256=ylcR_PMRcaCDf2pmrEGbna-q_3DJVlbB0ard1R86yaM,5483
|
5
|
-
skip_trace/config.py,sha256=BHM8TuJ_jWDhr1uz9hAAwA3eJwu_m-pYmAvnx_TcCcw,4735
|
6
|
-
skip_trace/exceptions.py,sha256=MnMlTjPYrvtB_1j-CAHwmlggjfNCDiRiThjXyuX70Js,581
|
7
|
-
skip_trace/main.py,sha256=zcO1KaHB3nWq5oq4vOTraxuSSID9Ey78qYCjPbB0b9E,9907
|
8
|
-
skip_trace/py.typed.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
skip_trace/schemas.py,sha256=otxLkn56HtVGlycgOlzI6cTv_Iu_0ICfYYClb2WtPD0,3103
|
10
|
-
skip_trace/analysis/__init__.py,sha256=7bOZj8CbG7Ezl9w_Z9gZCuO456psxecJCmPLxljFiuo,135
|
11
|
-
skip_trace/analysis/evidence.py,sha256=z8-4AcoxTRTMzr4NhilijfVifjWmybTlBsvGR47evHc,11661
|
12
|
-
skip_trace/analysis/ner.py,sha256=Ckcbyeza7fkDV-oGWTfakowLeWcybTzUpWjJ5bMlIwA,1607
|
13
|
-
skip_trace/analysis/scoring.py,sha256=K_pyUVwkGUasYOdveNtvrBrTjZ03VbovjMbM0mbA7_s,10328
|
14
|
-
skip_trace/analysis/source_scanner.py,sha256=nBE--gCaWfrXxsc-OdU9uhi4deYuF6AodW4w9b64sB8,15277
|
15
|
-
skip_trace/collectors/__init__.py,sha256=7wRLLntBWFs-lik7Rr-oPv426zweFyCSKbwit1gXUdU,141
|
16
|
-
skip_trace/collectors/github.py,sha256=CIwapS1UO6qLnoVyTHe7vLi159d6qRqCk9YRRk7jb7g,8575
|
17
|
-
skip_trace/collectors/package_files.py,sha256=WT1I-WN6MclGGb02SaAE3kUTM5TImDdb9qXvVB_uIPc,6026
|
18
|
-
skip_trace/collectors/pypi.py,sha256=OeqKIsg-s7oKxqTfcquqYVjyecmjNSupXVFcqBmKMFU,6205
|
19
|
-
skip_trace/collectors/whois.py,sha256=tQYI30IbRMlHEwn3FRSdKYX_c2TJLyMUyhLdIxpXU4o,6953
|
20
|
-
skip_trace/reporting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
-
skip_trace/reporting/json_reporter.py,sha256=VInt34k3Zo41y7SKkOnjxRj_gsB932GaAZsBj93Fvfc,610
|
22
|
-
skip_trace/reporting/md_reporter.py,sha256=V0tR6srTVe4_PVB2J0TrC3B_tB_ZuDTAZ2xLrpMMaRo,4081
|
23
|
-
skip_trace/utils/__init__.py,sha256=Wm-u-aQCpDEGL5wiRHWQ1ZwNQvA2iSLRpDNeb46_2P8,126
|
24
|
-
skip_trace/utils/cache.py,sha256=K6k0MXuf3fDr1ecjThV3qhZFHYhgCi0K69i27SoJmAY,2415
|
25
|
-
skip_trace/utils/cli_suggestions.py,sha256=pDNqfLhcYWEqvFM4jiOsUGXlqvTZxpWHR_O1hoCvzyM,2886
|
26
|
-
skip_trace/utils/http_client.py,sha256=3n0c4QBMCXHnIZ6Jn30HZWtFaWYvrq0SNr5Mp2ll_1E,1350
|
27
|
-
skip_trace/utils/safe_targz.py,sha256=ETOJc5VA9A5KDhlaV9N15tLbTFABA0zSQob9eXnKQPc,5233
|
28
|
-
skip_trace/utils/validation.py,sha256=cgPcmkVEoHZ9vkvntycckxpQM5UbrVpUvUCb0S2FZrs,1427
|
29
|
-
skip_trace-0.1.0.dist-info/METADATA,sha256=hij-sg6Pgci3LycgEJpLTZI17RULvlzr22E5cbB53uY,8380
|
30
|
-
skip_trace-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
31
|
-
skip_trace-0.1.0.dist-info/entry_points.txt,sha256=zR7je0FG4CxaLIfaONVMi9LgmKfWtbYkrTVLclrTwhg,51
|
32
|
-
skip_trace-0.1.0.dist-info/licenses/LICENSE,sha256=CDE_-1UnY5KRaDCIuCdNg7j7lkGCJbtZWTbhB10QeLk,1071
|
33
|
-
skip_trace-0.1.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|