opskit 0.1.0__tar.gz → 0.1.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.
- {opskit-0.1.0 → opskit-0.1.1}/.github/workflows/ci.yml +11 -8
- {opskit-0.1.0 → opskit-0.1.1}/.github/workflows/codeql.yml +2 -2
- {opskit-0.1.0 → opskit-0.1.1}/.github/workflows/release.yml +2 -2
- {opskit-0.1.0 → opskit-0.1.1}/.github/workflows/scorecard.yml +1 -1
- {opskit-0.1.0 → opskit-0.1.1}/.github/workflows/snyk.yml +4 -4
- opskit-0.1.1/.release-please-manifest.json +3 -0
- {opskit-0.1.0 → opskit-0.1.1}/CHANGELOG.md +7 -0
- {opskit-0.1.0 → opskit-0.1.1}/CLAUDE.md +7 -0
- {opskit-0.1.0 → opskit-0.1.1}/PKG-INFO +4 -4
- {opskit-0.1.0 → opskit-0.1.1}/README.md +2 -2
- {opskit-0.1.0 → opskit-0.1.1}/pyproject.toml +1 -1
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/__init__.py +1 -1
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_net_tcp.py +15 -4
- {opskit-0.1.0 → opskit-0.1.1}/uv.lock +1 -1
- opskit-0.1.0/.release-please-manifest.json +0 -3
- {opskit-0.1.0 → opskit-0.1.1}/.claude/skills/speckit-analyze/SKILL.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.claude/skills/speckit-checklist/SKILL.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.claude/skills/speckit-clarify/SKILL.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.claude/skills/speckit-constitution/SKILL.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.claude/skills/speckit-converge/SKILL.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.claude/skills/speckit-implement/SKILL.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.claude/skills/speckit-plan/SKILL.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.claude/skills/speckit-specify/SKILL.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.claude/skills/speckit-tasks/SKILL.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.claude/skills/speckit-taskstoissues/SKILL.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.coderabbit.yaml +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.github/dependabot.yml +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.gitignore +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.pre-commit-config.yaml +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/feature.json +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/init-options.json +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/integration.json +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/integrations/claude.manifest.json +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/integrations/speckit.manifest.json +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/memory/constitution.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/scripts/bash/check-prerequisites.sh +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/scripts/bash/common.sh +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/scripts/bash/create-new-feature.sh +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/scripts/bash/setup-plan.sh +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/scripts/bash/setup-tasks.sh +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/templates/checklist-template.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/templates/constitution-template.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/templates/plan-template.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/templates/spec-template.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/templates/tasks-template.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/workflows/speckit/workflow.yml +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/.specify/workflows/workflow-registry.json +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/LICENSE +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/SECURITY.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/docs/PLAN.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/noxfile.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/release-please-config.json +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/sonar-project.properties +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/001-dns-diagnostics/checklists/requirements.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/001-dns-diagnostics/contracts/cli.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/001-dns-diagnostics/contracts/json-envelope.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/001-dns-diagnostics/contracts/python-api.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/001-dns-diagnostics/data-model.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/001-dns-diagnostics/plan.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/001-dns-diagnostics/quickstart.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/001-dns-diagnostics/research.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/001-dns-diagnostics/spec.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/001-dns-diagnostics/tasks.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/002-tls-verification/checklists/requirements.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/002-tls-verification/contracts/cli.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/002-tls-verification/contracts/python-api.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/002-tls-verification/data-model.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/002-tls-verification/plan.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/002-tls-verification/quickstart.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/002-tls-verification/research.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/002-tls-verification/spec.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/specs/002-tls-verification/tasks.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/__main__.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/cli.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/core/__init__.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/core/cliutils.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/core/errors.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/core/exit_codes.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/core/output.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/core/result.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/dns/README.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/dns/__init__.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/dns/api.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/dns/cli.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/dns/errors.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/dns/models.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/dns/output.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/dns/resolver.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/net/__init__.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/net/errors.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/net/tcp.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/py.typed +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/tls/README.md +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/tls/__init__.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/tls/api.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/tls/cli.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/tls/errors.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/tls/handshake.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/tls/inspect.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/tls/models.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/src/opskit/tls/output.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/conftest.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/contract/test_json_envelope.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/integration/__init__.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/integration/conftest.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/integration/test_tls_loopback.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/integration/test_tls_network.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_batch.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_cli_lookup.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_dns_compare.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_dns_lookup.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_dns_lookup_all.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_dns_reverse.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_output.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_resolver.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_smoke.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_tls_api.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_tls_cli.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_tls_inspect.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_tls_match.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_tls_output.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_tls_target.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_trace.py +0 -0
- {opskit-0.1.0 → opskit-0.1.1}/tests/unit/test_watch.py +0 -0
|
@@ -20,11 +20,11 @@ jobs:
|
|
|
20
20
|
name: Lint & type-check
|
|
21
21
|
runs-on: ubuntu-latest
|
|
22
22
|
steps:
|
|
23
|
-
- uses: step-security/harden-runner@
|
|
23
|
+
- uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2
|
|
24
24
|
with:
|
|
25
25
|
egress-policy: audit
|
|
26
26
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
27
|
-
- uses: astral-sh/setup-uv@
|
|
27
|
+
- uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1
|
|
28
28
|
with:
|
|
29
29
|
enable-cache: true
|
|
30
30
|
- run: uv sync --extra dev
|
|
@@ -45,9 +45,12 @@ jobs:
|
|
|
45
45
|
steps:
|
|
46
46
|
- id: set
|
|
47
47
|
shell: bash
|
|
48
|
+
# PRs test all three OSes on the min+max Python (catches OS-specific bugs pre-merge —
|
|
49
|
+
# socket/TLS/filesystem behavior differs on Windows/macOS and is invisible on ubuntu).
|
|
50
|
+
# main additionally sweeps every Python version.
|
|
48
51
|
run: |
|
|
49
52
|
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
|
50
|
-
echo 'matrix={"os":["ubuntu-latest"],"python":["3.9","3.13"]}' >> "$GITHUB_OUTPUT"
|
|
53
|
+
echo 'matrix={"os":["ubuntu-latest","macos-latest","windows-latest"],"python":["3.9","3.13"]}' >> "$GITHUB_OUTPUT"
|
|
51
54
|
else
|
|
52
55
|
echo 'matrix={"os":["ubuntu-latest","macos-latest","windows-latest"],"python":["3.9","3.10","3.11","3.12","3.13"]}' >> "$GITHUB_OUTPUT"
|
|
53
56
|
fi
|
|
@@ -60,11 +63,11 @@ jobs:
|
|
|
60
63
|
matrix: ${{ fromJSON(needs.matrix-setup.outputs.matrix) }}
|
|
61
64
|
runs-on: ${{ matrix.os }}
|
|
62
65
|
steps:
|
|
63
|
-
- uses: step-security/harden-runner@
|
|
66
|
+
- uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2
|
|
64
67
|
with:
|
|
65
68
|
egress-policy: audit
|
|
66
69
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
67
|
-
- uses: astral-sh/setup-uv@
|
|
70
|
+
- uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1
|
|
68
71
|
with:
|
|
69
72
|
enable-cache: true
|
|
70
73
|
python-version: ${{ matrix.python }}
|
|
@@ -76,11 +79,11 @@ jobs:
|
|
|
76
79
|
name: Dependency audit
|
|
77
80
|
runs-on: ubuntu-latest
|
|
78
81
|
steps:
|
|
79
|
-
- uses: step-security/harden-runner@
|
|
82
|
+
- uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2
|
|
80
83
|
with:
|
|
81
84
|
egress-policy: audit
|
|
82
85
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
83
|
-
- uses: astral-sh/setup-uv@
|
|
86
|
+
- uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1
|
|
84
87
|
with:
|
|
85
88
|
enable-cache: true
|
|
86
89
|
- run: uv sync --extra dev
|
|
@@ -97,7 +100,7 @@ jobs:
|
|
|
97
100
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
98
101
|
with:
|
|
99
102
|
fetch-depth: 0
|
|
100
|
-
- uses: astral-sh/setup-uv@
|
|
103
|
+
- uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1
|
|
101
104
|
with:
|
|
102
105
|
enable-cache: true
|
|
103
106
|
- run: uv sync --extra dev
|
|
@@ -19,8 +19,8 @@ jobs:
|
|
|
19
19
|
security-events: write
|
|
20
20
|
steps:
|
|
21
21
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
22
|
-
- uses: github/codeql-action/init@
|
|
22
|
+
- uses: github/codeql-action/init@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4
|
|
23
23
|
with:
|
|
24
24
|
languages: python
|
|
25
25
|
queries: security-extended
|
|
26
|
-
- uses: github/codeql-action/analyze@
|
|
26
|
+
- uses: github/codeql-action/analyze@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4
|
|
@@ -43,11 +43,11 @@ jobs:
|
|
|
43
43
|
permissions:
|
|
44
44
|
id-token: write # OIDC for PyPI Trusted Publishing
|
|
45
45
|
steps:
|
|
46
|
-
- uses: step-security/harden-runner@
|
|
46
|
+
- uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2
|
|
47
47
|
with:
|
|
48
48
|
egress-policy: audit
|
|
49
49
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
50
|
-
- uses: astral-sh/setup-uv@
|
|
50
|
+
- uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1
|
|
51
51
|
- run: uv sync --extra dev
|
|
52
52
|
- name: Final security re-scan (zero-day gate)
|
|
53
53
|
run: uv run pip-audit
|
|
@@ -30,6 +30,6 @@ jobs:
|
|
|
30
30
|
results_file: results.sarif
|
|
31
31
|
results_format: sarif
|
|
32
32
|
publish_results: true
|
|
33
|
-
- uses: github/codeql-action/upload-sarif@
|
|
33
|
+
- uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4
|
|
34
34
|
with:
|
|
35
35
|
sarif_file: results.sarif
|
|
@@ -25,14 +25,14 @@ jobs:
|
|
|
25
25
|
env:
|
|
26
26
|
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
|
27
27
|
steps:
|
|
28
|
-
- uses: step-security/harden-runner@
|
|
28
|
+
- uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2
|
|
29
29
|
with:
|
|
30
30
|
egress-policy: audit
|
|
31
31
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
32
32
|
- name: Notice when unconfigured
|
|
33
33
|
if: ${{ env.SNYK_TOKEN == '' }}
|
|
34
34
|
run: echo "SNYK_TOKEN is not set — skipping Snyk. Add the repo secret to enable."
|
|
35
|
-
- uses: astral-sh/setup-uv@
|
|
35
|
+
- uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1
|
|
36
36
|
if: ${{ env.SNYK_TOKEN != '' }}
|
|
37
37
|
- name: Install Snyk CLI
|
|
38
38
|
if: ${{ env.SNYK_TOKEN != '' }}
|
|
@@ -55,13 +55,13 @@ jobs:
|
|
|
55
55
|
run: snyk code test --severity-threshold=high --sarif-file-output=snyk-code.sarif
|
|
56
56
|
- name: Upload Open Source SARIF
|
|
57
57
|
if: ${{ env.SNYK_TOKEN != '' && hashFiles('snyk-oss.sarif') != '' }}
|
|
58
|
-
uses: github/codeql-action/upload-sarif@
|
|
58
|
+
uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4
|
|
59
59
|
with:
|
|
60
60
|
sarif_file: snyk-oss.sarif
|
|
61
61
|
category: snyk-oss
|
|
62
62
|
- name: Upload Snyk Code SARIF
|
|
63
63
|
if: ${{ env.SNYK_TOKEN != '' && hashFiles('snyk-code.sarif') != '' }}
|
|
64
|
-
uses: github/codeql-action/upload-sarif@
|
|
64
|
+
uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4
|
|
65
65
|
with:
|
|
66
66
|
sarif_file: snyk-code.sarif
|
|
67
67
|
category: snyk-code
|
|
@@ -5,6 +5,13 @@ All notable changes to opskit are documented in this file. The format is based o
|
|
|
5
5
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html). Releases and this changelog are
|
|
6
6
|
generated automatically by release-please from Conventional Commits.
|
|
7
7
|
|
|
8
|
+
## [0.1.1](https://github.com/Prabhakar-cg/opskit/compare/opskit-v0.1.0...opskit-v0.1.1) (2026-07-08)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **ci:** cross-platform closed-port test; fix README badges ([#23](https://github.com/Prabhakar-cg/opskit/issues/23)) ([6736872](https://github.com/Prabhakar-cg/opskit/commit/673687205e0f6c205023951e998a76a6ac98c73c))
|
|
14
|
+
|
|
8
15
|
## 0.1.0 (2026-07-07)
|
|
9
16
|
|
|
10
17
|
|
|
@@ -91,6 +91,13 @@ Apply these from the start of every new category (`net`/`tls`/`ad`); each one co
|
|
|
91
91
|
- **Test gotcha (CodeQL):** don't assert `"<host.tld>" in output` — CodeQL's
|
|
92
92
|
`py/incomplete-url-substring-sanitization` flags it as a URL-host check. Assert on record
|
|
93
93
|
values / IPs / non-hostname substrings instead.
|
|
94
|
+
- **A green PR is not a green `main`.** CI runs all three OSes on PRs but only the min+max Python;
|
|
95
|
+
`main` sweeps every Python version. **Socket / TLS / filesystem / path / subprocess behavior
|
|
96
|
+
differs across OSes** (e.g. a closed loopback port *refuses* on Linux but *times out* on Windows;
|
|
97
|
+
trust stores, IPv6, and path separators differ) — write those tests to tolerate platform variance
|
|
98
|
+
(assert the typed error *class family*, not one exact subclass) and lean on the loopback/mock
|
|
99
|
+
layers. If a `main`-only matrix leg fails after merge, reproduce by widening the PR matrix, not by
|
|
100
|
+
guessing. The `net`/`tls` refused-vs-timeout classification is the canonical example.
|
|
94
101
|
|
|
95
102
|
## Testing
|
|
96
103
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opskit
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: Cross-platform diagnostics for engineers — one toolkit, every OS.
|
|
5
5
|
Project-URL: Homepage, https://github.com/Prabhakar-cg/opskit
|
|
6
6
|
Project-URL: Repository, https://github.com/Prabhakar-cg/opskit
|
|
@@ -25,7 +25,7 @@ Classifier: Topic :: System :: Networking
|
|
|
25
25
|
Classifier: Topic :: Utilities
|
|
26
26
|
Classifier: Typing :: Typed
|
|
27
27
|
Requires-Python: >=3.9.2
|
|
28
|
-
Requires-Dist: cryptography<
|
|
28
|
+
Requires-Dist: cryptography<50,>=48.0.1
|
|
29
29
|
Requires-Dist: dnspython<3,>=2.6
|
|
30
30
|
Requires-Dist: platformdirs<5,>=4
|
|
31
31
|
Requires-Dist: pyopenssl<27,>=24
|
|
@@ -55,7 +55,7 @@ Cross-platform diagnostics for engineers — one toolkit, every OS.
|
|
|
55
55
|
[](https://www.bestpractices.dev/projects/13462)
|
|
56
56
|
[](https://sonarcloud.io/summary/new_code?id=Prabhakar-cg_opskit)
|
|
57
57
|
[](https://snyk.io/test/github/Prabhakar-cg/opskit)
|
|
58
|
-
](https://coderabbit.ai)
|
|
59
59
|
[](LICENSE)
|
|
60
60
|
[](pyproject.toml)
|
|
61
61
|
|
|
@@ -64,7 +64,7 @@ troubleshooting commands that behave **identically on Windows, macOS, and Linux*
|
|
|
64
64
|
juggling `nslookup` vs `dig` vs PowerShell cmdlets. It's a **CLI *and* an importable Python
|
|
65
65
|
library**, is pure-Python (nothing to shell out to), and never phones home.
|
|
66
66
|
|
|
67
|
-
> ⚠️ **Early development.**
|
|
67
|
+
> ⚠️ **Early development.** Ships **DNS** and **TLS** diagnostics today; network / AD categories follow.
|
|
68
68
|
|
|
69
69
|
---
|
|
70
70
|
|
|
@@ -8,7 +8,7 @@ Cross-platform diagnostics for engineers — one toolkit, every OS.
|
|
|
8
8
|
[](https://www.bestpractices.dev/projects/13462)
|
|
9
9
|
[](https://sonarcloud.io/summary/new_code?id=Prabhakar-cg_opskit)
|
|
10
10
|
[](https://snyk.io/test/github/Prabhakar-cg/opskit)
|
|
11
|
-
](https://coderabbit.ai)
|
|
12
12
|
[](LICENSE)
|
|
13
13
|
[](pyproject.toml)
|
|
14
14
|
|
|
@@ -17,7 +17,7 @@ troubleshooting commands that behave **identically on Windows, macOS, and Linux*
|
|
|
17
17
|
juggling `nslookup` vs `dig` vs PowerShell cmdlets. It's a **CLI *and* an importable Python
|
|
18
18
|
library**, is pure-Python (nothing to shell out to), and never phones home.
|
|
19
19
|
|
|
20
|
-
> ⚠️ **Early development.**
|
|
20
|
+
> ⚠️ **Early development.** Ships **DNS** and **TLS** diagnostics today; network / AD categories follow.
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -36,7 +36,7 @@ dependencies = [
|
|
|
36
36
|
"tomli>=2 ; python_version < '3.11'",
|
|
37
37
|
# TLS category: handshake/chain retrieval + certificate parsing (PyCA-maintained).
|
|
38
38
|
"pyopenssl>=24,<27",
|
|
39
|
-
"cryptography>=48.0.1,<
|
|
39
|
+
"cryptography>=48.0.1,<50", # 48.0.1 fixes GHSA-537c-gmf6-5ccf
|
|
40
40
|
]
|
|
41
41
|
|
|
42
42
|
[project.urls]
|
|
@@ -47,11 +47,22 @@ def test_connect_success_reports_address_and_timing():
|
|
|
47
47
|
server.close()
|
|
48
48
|
|
|
49
49
|
|
|
50
|
+
def _closed_port() -> int:
|
|
51
|
+
"""A loopback port that is closed (bound then released, never listened)."""
|
|
52
|
+
probe = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
53
|
+
probe.bind(("127.0.0.1", 0))
|
|
54
|
+
port = int(probe.getsockname()[1])
|
|
55
|
+
probe.close()
|
|
56
|
+
return port
|
|
57
|
+
|
|
58
|
+
|
|
50
59
|
def test_connect_refused_on_closed_port():
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
# A closed loopback port refuses on Linux/macOS. Windows refuses a never-listened port
|
|
61
|
+
# (this pattern) but may *time out* on a port that was listen()ed then closed — so accept
|
|
62
|
+
# either "cannot connect" NetError. The precise refused mapping is asserted deterministically
|
|
63
|
+
# in test_refusal_wins_over_timeout_for_dual_stack.
|
|
64
|
+
with pytest.raises((ConnectRefused, ConnectTimeout)) as excinfo:
|
|
65
|
+
connect("127.0.0.1", _closed_port(), timeout=1.0, retries=0)
|
|
55
66
|
assert excinfo.value.hint
|
|
56
67
|
|
|
57
68
|
|
|
@@ -1257,7 +1257,7 @@ dev = [
|
|
|
1257
1257
|
|
|
1258
1258
|
[package.metadata]
|
|
1259
1259
|
requires-dist = [
|
|
1260
|
-
{ name = "cryptography", specifier = ">=48.0.1,<
|
|
1260
|
+
{ name = "cryptography", specifier = ">=48.0.1,<50" },
|
|
1261
1261
|
{ name = "dnslib", marker = "extra == 'dev'", specifier = ">=0.9" },
|
|
1262
1262
|
{ name = "dnspython", specifier = ">=2.6,<3" },
|
|
1263
1263
|
{ name = "hypothesis", marker = "extra == 'dev'", specifier = ">=6" },
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|