portly 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.
@@ -0,0 +1,62 @@
1
+ name: Bug report
2
+ description: Report a problem with portly
3
+ labels: [bug]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for taking the time to report a bug! Please fill in as much
9
+ information as you can.
10
+ - type: textarea
11
+ id: what-happened
12
+ attributes:
13
+ label: What happened?
14
+ description: A clear and concise description of the bug.
15
+ validations:
16
+ required: true
17
+ - type: textarea
18
+ id: expected
19
+ attributes:
20
+ label: Expected behavior
21
+ description: What did you expect to happen?
22
+ - type: textarea
23
+ id: repro
24
+ attributes:
25
+ label: Steps to reproduce
26
+ description: Minimal code or commands that trigger the bug.
27
+ placeholder: |
28
+ ```python
29
+ import portly
30
+ portly.kill(8000)
31
+ ```
32
+ validations:
33
+ required: true
34
+ - type: input
35
+ id: version
36
+ attributes:
37
+ label: portly version
38
+ description: e.g. 0.1.0 (check `python -c "import portly; print(portly.__version__)"`)
39
+ validations:
40
+ required: true
41
+ - type: dropdown
42
+ id: platform
43
+ attributes:
44
+ label: Platform
45
+ options:
46
+ - Linux
47
+ - macOS
48
+ - Windows
49
+ - Other
50
+ validations:
51
+ required: true
52
+ - type: input
53
+ id: python
54
+ attributes:
55
+ label: Python version
56
+ description: e.g. 3.12, 3.14t (free-threaded)
57
+ - type: textarea
58
+ id: logs
59
+ attributes:
60
+ label: Relevant output / traceback
61
+ description: Paste any error messages or tracebacks.
62
+ render: shell
@@ -0,0 +1,8 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Security issues
4
+ url: https://github.com/PatrykBochenek/portly/security/policy
5
+ about: Please report security vulnerabilities privately — see SECURITY.md.
6
+ - name: Discussions
7
+ url: https://github.com/PatrykBochenek/portly/discussions
8
+ about: Ask questions, discuss ideas, and get help.
@@ -0,0 +1,30 @@
1
+ name: Feature request
2
+ description: Suggest a new feature or improvement for portly
3
+ labels: [enhancement]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for suggesting an idea! Please describe the problem you're
9
+ solving and the shape of the solution you have in mind.
10
+ - type: textarea
11
+ id: problem
12
+ attributes:
13
+ label: Problem
14
+ description: What problem would this feature solve?
15
+ validations:
16
+ required: true
17
+ - type: textarea
18
+ id: solution
19
+ attributes:
20
+ label: Proposed solution
21
+ description: How should the feature work? API sketches welcome.
22
+ placeholder: |
23
+ ```python
24
+ portly.wait_until_free(5432, interval=0.2)
25
+ ```
26
+ - type: textarea
27
+ id: alternatives
28
+ attributes:
29
+ label: Alternatives considered
30
+ description: Any workarounds or alternative designs you've thought of.
@@ -0,0 +1,20 @@
1
+ ## Summary
2
+
3
+ <!-- What does this PR do, and why? -->
4
+
5
+ ## Changes
6
+
7
+ <!-- Bullet list of the concrete changes. -->
8
+
9
+ ## Testing
10
+
11
+ <!-- How was this verified? e.g. "pytest tests/", "cargo test", "maturin build". -->
12
+
13
+ ## Checklist
14
+
15
+ - [ ] `cargo fmt --check` and `cargo clippy -- -D warnings` pass
16
+ - [ ] `ruff check` and `ruff format --check` pass
17
+ - [ ] `mypy python/portly tests` passes
18
+ - [ ] `pytest tests/` passes
19
+ - [ ] Stub changes (`.pyi`) are validated by `mypy.stubtest`
20
+ - [ ] CHANGELOG updated (if user-facing change)
@@ -0,0 +1,19 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+
8
+ - package-ecosystem: "cargo"
9
+ directory: "/"
10
+ schedule:
11
+ interval: "weekly"
12
+
13
+ - package-ecosystem: "pip"
14
+ directory: "/"
15
+ schedule:
16
+ interval: "weekly"
17
+ groups:
18
+ dev-dependencies:
19
+ patterns: ["maturin", "pytest", "pytest-cov", "ruff", "mypy"]
@@ -0,0 +1,110 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ lint:
14
+ name: Lint & typecheck
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
18
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
19
+ with:
20
+ python-version: "3.13"
21
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
22
+ with:
23
+ components: rustfmt, clippy
24
+ - name: Install Python tooling
25
+ run: pip install ruff mypy maturin pytest
26
+ - name: Ruff check
27
+ run: ruff check python/ tests/ examples/
28
+ - name: Ruff format
29
+ run: ruff format --check python/ tests/ examples/
30
+ - name: Mypy (strict)
31
+ run: mypy python/portly tests
32
+ - name: Stubtest (stubs vs runtime)
33
+ run: |
34
+ maturin build --out dist
35
+ pip install dist/*.whl
36
+ python -m mypy.stubtest portly._lib --allowlist tests/stubtest-allowlist.txt
37
+ - name: Cargo fmt
38
+ run: cargo fmt -- --check
39
+ - name: Cargo clippy
40
+ run: cargo clippy --all-targets -- -D warnings
41
+ - name: Cargo test
42
+ run: cargo test
43
+ - name: Zizmor (GitHub Actions security audit)
44
+ run: |
45
+ pip install zizmor
46
+ zizmor --min-severity high .github/workflows/
47
+
48
+ test:
49
+ name: Test (${{ matrix.os }} / ${{ matrix.python-version }})
50
+ runs-on: ${{ matrix.os }}
51
+ strategy:
52
+ fail-fast: false
53
+ matrix:
54
+ os: [ubuntu-latest, macos-latest, windows-latest]
55
+ python-version: ["3.10", "3.14"]
56
+ steps:
57
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
58
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
59
+ with:
60
+ python-version: ${{ matrix.python-version }}
61
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
62
+ - name: Install maturin
63
+ run: pip install maturin pytest
64
+ - name: Build extension
65
+ run: maturin build --out dist
66
+ - name: Install extension
67
+ shell: bash
68
+ run: pip install dist/*.whl
69
+ - name: Run tests
70
+ run: pytest tests/ -v
71
+
72
+ freethreaded:
73
+ name: Test (free-threaded 3.14t)
74
+ runs-on: ubuntu-latest
75
+ steps:
76
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
77
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
78
+ with:
79
+ python-version: "3.14t"
80
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
81
+ - name: Install maturin
82
+ run: pip install maturin pytest
83
+ - name: Build extension
84
+ run: maturin build --out dist
85
+ - name: Install extension
86
+ run: pip install dist/*.whl
87
+ - name: Run tests
88
+ run: pytest tests/ -v
89
+
90
+ wheel:
91
+ name: Wheel & sdist install test
92
+ runs-on: ubuntu-latest
93
+ steps:
94
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
95
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
96
+ with:
97
+ python-version: "3.13"
98
+ - uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
99
+ - name: Install maturin
100
+ run: pip install maturin pytest
101
+ - name: Build and test wheel
102
+ run: |
103
+ maturin build --release --locked --out dist
104
+ pip install dist/*.whl
105
+ python -m pytest tests/ -q
106
+ - name: Build and test sdist
107
+ run: |
108
+ maturin sdist --out dist
109
+ pip install dist/*.tar.gz
110
+ python -m pytest tests/ -q
@@ -0,0 +1,34 @@
1
+ name: Release Please
2
+
3
+ # release-please opens a "chore(main): release vX.Y.Z" PR whenever conventional
4
+ # commits land on main. Merging that PR bumps Cargo.toml/Cargo.lock and
5
+ # CHANGELOG.md, then release-please creates the vX.Y.Z tag + GitHub Release.
6
+ #
7
+ # Because the tag is created with GITHUB_TOKEN, the tag-push event does NOT
8
+ # trigger our release.yml (GitHub suppresses events caused by GITHUB_TOKEN).
9
+ # Instead we dispatch release.yml on the tag via workflow_dispatch, which is
10
+ # allowed for GITHUB_TOKEN.
11
+ on:
12
+ push:
13
+ branches: [main]
14
+
15
+ permissions:
16
+ contents: write
17
+ pull-requests: write
18
+ issues: write
19
+
20
+ jobs:
21
+ release-please:
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: googleapis/release-please-action@d1a8f221d7723166f48a584aebba00ef3f6febec # v4
25
+ id: release
26
+ with:
27
+ token: ${{ secrets.GITHUB_TOKEN }}
28
+ target-branch: main
29
+
30
+ - name: Trigger release build
31
+ if: ${{ steps.release.outputs.release_created == 'true' }}
32
+ run: gh workflow run release.yml --ref "${{ steps.release.outputs.tag_name }}"
33
+ env:
34
+ GH_TOKEN: ${{ github.token }}
@@ -0,0 +1,183 @@
1
+ name: Release
2
+
3
+ # Builds wheels + sdist for every supported platform and publishes them to
4
+ # PyPI using Trusted Publishing (OIDC). Triggered by `v*` tags.
5
+ on:
6
+ push:
7
+ tags:
8
+ - "v*"
9
+ workflow_dispatch:
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ linux:
16
+ runs-on: ${{ matrix.platform.runner }}
17
+ strategy:
18
+ matrix:
19
+ platform:
20
+ - runner: ubuntu-22.04
21
+ target: x86_64
22
+ - runner: ubuntu-22.04
23
+ target: aarch64
24
+ steps:
25
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
26
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
27
+ with:
28
+ python-version: "3.10"
29
+ - name: Build wheels
30
+ uses: PyO3/maturin-action@423a6347767a8b16e65c2a7a7042e4a921528da8 # v1
31
+ with:
32
+ target: ${{ matrix.platform.target }}
33
+ args: --release --out dist --find-interpreter --locked
34
+ sccache: false
35
+ manylinux: auto
36
+ - name: Upload wheels
37
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
38
+ with:
39
+ name: wheels-linux-${{ matrix.platform.target }}
40
+ path: dist
41
+
42
+ musllinux:
43
+ runs-on: ${{ matrix.platform.runner }}
44
+ strategy:
45
+ matrix:
46
+ platform:
47
+ - runner: ubuntu-22.04
48
+ target: x86_64
49
+ - runner: ubuntu-22.04
50
+ target: aarch64
51
+ steps:
52
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
53
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
54
+ with:
55
+ python-version: "3.10"
56
+ - name: Build wheels
57
+ uses: PyO3/maturin-action@423a6347767a8b16e65c2a7a7042e4a921528da8 # v1
58
+ with:
59
+ target: ${{ matrix.platform.target }}
60
+ args: --release --out dist --find-interpreter --locked
61
+ sccache: false
62
+ manylinux: musllinux_1_2
63
+ - name: Upload wheels
64
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
65
+ with:
66
+ name: wheels-musllinux-${{ matrix.platform.target }}
67
+ path: dist
68
+
69
+ windows:
70
+ runs-on: ${{ matrix.platform.runner }}
71
+ strategy:
72
+ matrix:
73
+ platform:
74
+ - runner: windows-latest
75
+ target: x64
76
+ python_arch: x64
77
+ - runner: windows-11-arm
78
+ target: aarch64
79
+ python_arch: arm64
80
+ steps:
81
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
82
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
83
+ with:
84
+ python-version: "3.13"
85
+ architecture: ${{ matrix.platform.python_arch }}
86
+ - name: Build wheels
87
+ uses: PyO3/maturin-action@423a6347767a8b16e65c2a7a7042e4a921528da8 # v1
88
+ with:
89
+ target: ${{ matrix.platform.target }}
90
+ args: --release --out dist --find-interpreter --locked
91
+ sccache: false
92
+ - name: Upload wheels
93
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
94
+ with:
95
+ name: wheels-windows-${{ matrix.platform.target }}
96
+ path: dist
97
+
98
+ macos:
99
+ runs-on: ${{ matrix.platform.runner }}
100
+ strategy:
101
+ matrix:
102
+ platform:
103
+ - runner: macos-15-intel
104
+ target: x86_64
105
+ - runner: macos-latest
106
+ target: aarch64
107
+ steps:
108
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
109
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
110
+ with:
111
+ python-version: "3.10"
112
+ - name: Build wheels
113
+ uses: PyO3/maturin-action@423a6347767a8b16e65c2a7a7042e4a921528da8 # v1
114
+ with:
115
+ target: ${{ matrix.platform.target }}
116
+ args: --release --out dist --find-interpreter --locked
117
+ sccache: false
118
+ - name: Upload wheels
119
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
120
+ with:
121
+ name: wheels-macos-${{ matrix.platform.target }}
122
+ path: dist
123
+
124
+ sdist:
125
+ runs-on: ubuntu-latest
126
+ steps:
127
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
128
+ - name: Build sdist
129
+ uses: PyO3/maturin-action@423a6347767a8b16e65c2a7a7042e4a921528da8 # v1
130
+ with:
131
+ command: sdist
132
+ args: --out dist
133
+ - name: Upload sdist
134
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
135
+ with:
136
+ name: wheels-sdist
137
+ path: dist
138
+
139
+ release:
140
+ name: Release
141
+ runs-on: ubuntu-latest
142
+ needs: [linux, musllinux, windows, macos, sdist]
143
+ permissions:
144
+ # For artifact attestation and trusted publishing.
145
+ id-token: write
146
+ # For creating the GitHub Release.
147
+ contents: write
148
+ # For generating PEP 740 attestations.
149
+ attestations: write
150
+ steps:
151
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
152
+ - name: Verify tag matches Cargo.toml version
153
+ if: startsWith(github.ref, 'refs/tags/')
154
+ run: |
155
+ version="$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)"
156
+ if [ "v${version}" != "${GITHUB_REF_NAME}" ]; then
157
+ echo "::error::Tag ${GITHUB_REF_NAME} does not match Cargo.toml version v${version}"
158
+ exit 1
159
+ fi
160
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
161
+ - name: Generate artifact attestation
162
+ uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4
163
+ with:
164
+ subject-path: 'wheels-*/*'
165
+ - name: Create or update GitHub Release
166
+ if: startsWith(github.ref, 'refs/tags/')
167
+ run: |
168
+ if gh release view "${GITHUB_REF_NAME}" >/dev/null 2>&1; then
169
+ # release-please already created the release (with changelog notes);
170
+ # attach the wheels to it.
171
+ gh release upload "${GITHUB_REF_NAME}" wheels-*/* --clobber
172
+ else
173
+ gh release create "${GITHUB_REF_NAME}" wheels-*/* --generate-notes
174
+ fi
175
+ env:
176
+ GH_TOKEN: ${{ github.token }}
177
+ - name: Install uv
178
+ uses: astral-sh/setup-uv@94527f2e458b27549849d47d273a16bec83a01e9 # v7
179
+ with:
180
+ enable-cache: false
181
+ - name: Publish to PyPI
182
+ if: startsWith(github.ref, 'refs/tags/')
183
+ run: uv publish --trusted-publishing always 'wheels-*/*'
@@ -0,0 +1,32 @@
1
+ # Rust
2
+ /target
3
+ **/*.rs.bk
4
+ # Cargo.lock is committed intentionally (reproducible wheel/sdist builds).
5
+
6
+ # Python
7
+ __pycache__/
8
+ *.py[cod]
9
+ *$py.class
10
+ *.so
11
+ .venv/
12
+ venv/
13
+ *.egg-info/
14
+ dist/
15
+ build/
16
+ .eggs/
17
+ .pytest_cache/
18
+ .mypy_cache/
19
+ .ruff_cache/
20
+
21
+ # IDE
22
+ .vscode/
23
+ .idea/
24
+ *.swp
25
+ *.swo
26
+
27
+ # OS
28
+ .DS_Store
29
+ Thumbs.db
30
+
31
+ # Maturin
32
+ wheelhouse/
@@ -0,0 +1,36 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v6.0.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-toml
9
+ - id: check-added-large-files
10
+ - id: check-merge-conflict
11
+
12
+ - repo: https://github.com/astral-sh/ruff-pre-commit
13
+ rev: v0.16.3
14
+ hooks:
15
+ - id: ruff
16
+ args: [--fix]
17
+ - id: ruff-format
18
+
19
+ - repo: local
20
+ hooks:
21
+ - id: mypy
22
+ name: mypy (strict)
23
+ entry: mypy python/portly tests
24
+ language: system
25
+ pass_filenames: false
26
+ types: [python]
27
+ - id: cargo-fmt
28
+ name: cargo fmt
29
+ entry: cargo fmt -- --check
30
+ language: system
31
+ pass_filenames: false
32
+ - id: cargo-clippy
33
+ name: cargo clippy
34
+ entry: cargo clippy --all-targets -- -D warnings
35
+ language: system
36
+ pass_filenames: false
@@ -0,0 +1 @@
1
+ {".":"0.1.0"}
@@ -0,0 +1,43 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## 0.1.0 (2026-08-16)
9
+
10
+
11
+ ### Features
12
+
13
+ * rename python package and add typed stubs ([cfbcd68](https://github.com/PatrykBochenek/portly/commit/cfbcd68b18a2b7751837ed2d226caafb68cb2cda))
14
+
15
+
16
+ ### Bug Fixes
17
+
18
+ * clippy flatten lint and Windows wheel install glob ([66c90dc](https://github.com/PatrykBochenek/portly/commit/66c90dce62e7259d935026cc26d4f9f1c1eb36a6))
19
+ * clippy manual-flatten on the Linux socket table loops ([061c010](https://github.com/PatrykBochenek/portly/commit/061c010ca90f53c6d3efc8e21c8a40709ab3678f))
20
+ * compile on Linux and Windows ([e300527](https://github.com/PatrykBochenek/portly/commit/e300527d5172146b0561a4bd47c127ee28c37d92))
21
+
22
+ ## [Unreleased]
23
+
24
+ ## [0.1.0] - 2026-08-16
25
+
26
+ ### Added
27
+
28
+ - Initial release of **portly**: a cross-platform, Rust-powered library
29
+ for checking, finding, scanning, waiting on, and freeing TCP/UDP ports.
30
+ - API: `is_available`, `find_free`, `wait_until_free`, `get_info`, `kill`,
31
+ `scan`, `__version__`.
32
+ - Native (subprocess-free) process lookup on all platforms:
33
+ - Linux: `/proc/net/{tcp,tcp6,udp,udp6}` + `/proc/<pid>/fd` via `procfs`.
34
+ - macOS: `libproc` (`proc_pidinfo`).
35
+ - Windows: `GetExtended{Tcp,Udp}Table` + ToolHelp32 via `windows-sys`
36
+ (no dependency on the deprecated `wmic`).
37
+ - Type stubs (`_lib.pyi`) validated by `mypy.stubtest`; `py.typed` marker.
38
+ - CI: lint/typecheck gates, cross-platform test matrix (incl. free-threaded
39
+ 3.14t), wheel + sdist install tests, and a release workflow using PyPI
40
+ Trusted Publishing with PEP 740 attestations.
41
+
42
+ [Unreleased]: https://github.com/PatrykBochenek/portly/compare/v0.1.0...HEAD
43
+ [0.1.0]: https://github.com/PatrykBochenek/portly/releases/tag/v0.1.0