summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/automerge.yml1
-rw-r--r--.github/workflows/build.yml2
-rw-r--r--.github/workflows/linters.yml10
-rw-r--r--.github/workflows/pr-check.yml12
-rw-r--r--.github/workflows/pypi.yml2
-rw-r--r--.github/workflows/tests-macos.yml17
-rw-r--r--.github/workflows/tests.yml13
-rw-r--r--.gitignore5
-rw-r--r--CHANGES.rst21
-rw-r--r--Pipfile12
-rw-r--r--Pipfile.lock388
-rw-r--r--port_for/__init__.py8
-rw-r--r--port_for/api.py45
-rw-r--r--port_for/cmd.py4
-rw-r--r--port_for/ephemeral.py10
-rw-r--r--port_for/exceptions.py6
-rw-r--r--port_for/store.py13
-rw-r--r--port_for/utils.py10
-rw-r--r--pyproject.toml50
-rw-r--r--setup.cfg3
-rw-r--r--tests/test_cases.py33
21 files changed, 161 insertions, 504 deletions
diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml
index aa0e102..0fde336 100644
--- a/.github/workflows/automerge.yml
+++ b/.github/workflows/automerge.yml
@@ -8,7 +8,6 @@ on:
# List all required workflow names here.
- 'Run linters'
- 'Run tests'
- - 'Run tests on macos'
- 'Test build package'
- 'Run test commands'
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ebaa45f..da5c867 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -8,4 +8,4 @@ on:
jobs:
build:
- uses: fizyk/actions-reuse/.github/workflows/pypi.yml@v2.1.2
+ uses: fizyk/actions-reuse/.github/workflows/pypi.yml@v2.4.0
diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml
index dec9e2e..4fc4404 100644
--- a/.github/workflows/linters.yml
+++ b/.github/workflows/linters.yml
@@ -3,16 +3,12 @@ name: Run linters
on:
push:
branches: [ master ]
- paths:
- - '**.py'
- - .github/workflows/linters.yml
- - requirements-lint.txt
pull_request:
branches: [ master ]
jobs:
lint:
- uses: fizyk/actions-reuse/.github/workflows/linters-python.yml@v2.1.2
+ uses: fizyk/actions-reuse/.github/workflows/linters-python.yml@v2.4.0
with:
- pipenv: true
mypy: true
- pydocstyle: false \ No newline at end of file
+ ruff: true
+ black: true \ No newline at end of file
diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml
index 758fd46..22525ea 100644
--- a/.github/workflows/pr-check.yml
+++ b/.github/workflows/pr-check.yml
@@ -9,19 +9,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@v3
- - uses: fizyk/actions-reuse/.github/actions/pipenv@v2.1.2
+ uses: actions/checkout@v4
+ - uses: fizyk/actions-reuse/.github/actions/pipenv@v2.4.0
with:
- python-version: "3.11"
- pipenv-install-options: "--skip-lock"
+ python-version: "3.12"
command: tbump --dry-run --only-patch $(pipenv run tbump current-version)"-x"
towncrier:
runs-on: ubuntu-latest
if: ${{ github.actor != 'dependabot[bot]' }}
steps:
- - uses: fizyk/actions-reuse/.github/actions/pipenv@v2.1.2
+ - uses: fizyk/actions-reuse/.github/actions/pipenv@v2.4.0
with:
- python-version: "3.11"
- pipenv-install-options: "--skip-lock"
+ python-version: "3.12"
command: towncrier check --compare-with origin/master
fetch-depth: 0
diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml
index f90d2ce..b86f43a 100644
--- a/.github/workflows/pypi.yml
+++ b/.github/workflows/pypi.yml
@@ -5,7 +5,7 @@ on:
- v*
jobs:
build:
- uses: fizyk/actions-reuse/.github/workflows/pypi.yml@v2.1.2
+ uses: fizyk/actions-reuse/.github/workflows/pypi.yml@v2.4.0
with:
publish: true
secrets:
diff --git a/.github/workflows/tests-macos.yml b/.github/workflows/tests-macos.yml
deleted file mode 100644
index 4732209..0000000
--- a/.github/workflows/tests-macos.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: Run tests on macos
-
-on:
- push:
- branches: [ master ]
- pull_request:
- branches: [ master ]
-
-
-jobs:
- tests:
- uses: fizyk/actions-reuse/.github/workflows/tests-pytests.yml@v2.1.2
- with:
- python-versions: '["3.7", "3.8", "3.9", "3.10", "3.11", "pypy-3.8"]'
- os: macos-latest
- pipenv: true
- pipenv-install-options: --skip-lock
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index adbb036..d3f05ef 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -8,8 +8,13 @@ on:
jobs:
tests:
- uses: fizyk/actions-reuse/.github/workflows/tests-pytests.yml@v2.1.2
+ uses: fizyk/actions-reuse/.github/workflows/tests-pytests.yml@v2.4.0
with:
- python-versions: '["3.7", "3.8", "3.9", "3.10", "3.11", "pypy-3.8"]'
- pipenv: true
- pipenv-install-options: --skip-lock
+ python-versions: '["3.8", "3.9", "3.10", "3.11", "3.12", "pypy-3.8"]'
+ tests-macos:
+ needs:
+ - tests
+ uses: fizyk/actions-reuse/.github/workflows/tests-pytests.yml@v2.4.0
+ with:
+ python-versions: '["3.8", "3.9", "3.10", "3.11", "3.12", "pypy-3.8"]'
+ os: macos-latest
diff --git a/.gitignore b/.gitignore
index f46f8ba..55f37e0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,4 +10,7 @@ htmlcov
.ipynb_checkpoints/
MANIFEST
coverage
-venv/ \ No newline at end of file
+venv/
+
+# Managed by github-actions (cache + artifact) per python version - see pipeline artifacts
+Pipfile.lock
diff --git a/CHANGES.rst b/CHANGES.rst
index 3f8c3f2..e857fca 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -3,6 +3,27 @@ CHANGELOG
.. towncrier release notes start
+0.7.2 (2023-10-10)
+==================
+
+Breaking changes
+----------------
+
+- Drop support for python 3.7 (`#155 <https://github.com/kmike/port-for/issues/155>`__)
+
+
+Features
+--------
+
+- Support Python 3.12 (`#169 <https://github.com/kmike/port-for/issues/169>`__)
+
+
+Miscellaneus
+------------
+
+- `#152 <https://github.com/kmike/port-for/issues/152>`__, `#166 <https://github.com/kmike/port-for/issues/166>`__, `#170 <https://github.com/kmike/port-for/issues/170>`__
+
+
0.7.1 (2023-07-14)
==================
diff --git a/Pipfile b/Pipfile
index a9e2661..2ba7864 100644
--- a/Pipfile
+++ b/Pipfile
@@ -7,10 +7,10 @@ name = "pypi"
[dev-packages]
towncrier = "==23.6.0"
-pytest = "==7.4.0"
+pytest = "==7.4.2"
pytest-cov = "==4.1.0"
-coverage = "==7.2.7"
-black = "==23.7.0"
-pycodestyle = "==2.10.0"
-mypy = "==1.4.1"
-tbump = "==6.10.0"
+coverage = "==7.3.2"
+black = "==23.9.1"
+mypy = "==1.5.1"
+tbump = "==6.11.0"
+ruff = "==0.0.292"
diff --git a/Pipfile.lock b/Pipfile.lock
deleted file mode 100644
index 9776937..0000000
--- a/Pipfile.lock
+++ /dev/null
@@ -1,388 +0,0 @@
-{
- "_meta": {
- "hash": {
- "sha256": "643de800a20bbcc68b7b1d0fe879c91aab21620df5e3b74e70b7c54811746f7d"
- },
- "pipfile-spec": 6,
- "requires": {},
- "sources": [
- {
- "name": "pypi",
- "url": "https://pypi.org/simple",
- "verify_ssl": true
- }
- ]
- },
- "default": {},
- "develop": {
- "black": {
- "hashes": [
- "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3",
- "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb",
- "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087",
- "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320",
- "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6",
- "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3",
- "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc",
- "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f",
- "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587",
- "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91",
- "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a",
- "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad",
- "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926",
- "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9",
- "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be",
- "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd",
- "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96",
- "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491",
- "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2",
- "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a",
- "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f",
- "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"
- ],
- "index": "pypi",
- "version": "==23.7.0"
- },
- "cli-ui": {
- "hashes": [
- "sha256:2f67e50cf474e76ad160c3e660bbad98bf8b8dfb8d847765f3a261b7e13c05fa",
- "sha256:6a1ebdbbcd83a0fa06b2f63f4434082a3ba8664aebedd91f1ff86b9e4289d53e"
- ],
- "markers": "python_version >= '3.7' and python_version < '4.0'",
- "version": "==0.17.2"
- },
- "click": {
- "hashes": [
- "sha256:2739815aaa5d2c986a88f1e9230c55e17f0caad3d958a5e13ad0797c166db9e3",
- "sha256:b97d0c74955da062a7d4ef92fadb583806a585b2ea81958a81bd72726cbb8e37"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==8.1.4"
- },
- "click-default-group": {
- "hashes": [
- "sha256:d9560e8e8dfa44b3562fbc9425042a0fd6d21956fcc2db0077f63f34253ab904"
- ],
- "version": "==1.2.2"
- },
- "colorama": {
- "hashes": [
- "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44",
- "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"
- ],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'",
- "version": "==0.4.6"
- },
- "contextlib2": {
- "hashes": [
- "sha256:3fbdb64466afd23abaf6c977627b75b6139a5a3e8ce38405c5b413aed7a0471f",
- "sha256:ab1e2bfe1d01d968e1b7e8d9023bc51ef3509bba217bb730cee3827e1ee82869"
- ],
- "markers": "python_version >= '3.6'",
- "version": "==21.6.0"
- },
- "coverage": {
- "hashes": [
- "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f",
- "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2",
- "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a",
- "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a",
- "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01",
- "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6",
- "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7",
- "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f",
- "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02",
- "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c",
- "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063",
- "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a",
- "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5",
- "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959",
- "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97",
- "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6",
- "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f",
- "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9",
- "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5",
- "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f",
- "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562",
- "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe",
- "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9",
- "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f",
- "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb",
- "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb",
- "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1",
- "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb",
- "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250",
- "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e",
- "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511",
- "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5",
- "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59",
- "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2",
- "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d",
- "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3",
- "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4",
- "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de",
- "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9",
- "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833",
- "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0",
- "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9",
- "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d",
- "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050",
- "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d",
- "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6",
- "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353",
- "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb",
- "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e",
- "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8",
- "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495",
- "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2",
- "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd",
- "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27",
- "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1",
- "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818",
- "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4",
- "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e",
- "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850",
- "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"
- ],
- "index": "pypi",
- "version": "==7.2.7"
- },
- "docopt": {
- "hashes": [
- "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"
- ],
- "version": "==0.6.2"
- },
- "incremental": {
- "hashes": [
- "sha256:912feeb5e0f7e0188e6f42241d2f450002e11bbc0937c65865045854c24c0bd0",
- "sha256:b864a1f30885ee72c5ac2835a761b8fe8aa9c28b9395cacf27286602688d3e51"
- ],
- "version": "==22.10.0"
- },
- "iniconfig": {
- "hashes": [
- "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3",
- "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==2.0.0"
- },
- "jinja2": {
- "hashes": [
- "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852",
- "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==3.1.2"
- },
- "markupsafe": {
- "hashes": [
- "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e",
- "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e",
- "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431",
- "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686",
- "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559",
- "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc",
- "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c",
- "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0",
- "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4",
- "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9",
- "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575",
- "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba",
- "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d",
- "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3",
- "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00",
- "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155",
- "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac",
- "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52",
- "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f",
- "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8",
- "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b",
- "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24",
- "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea",
- "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198",
- "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0",
- "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee",
- "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be",
- "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2",
- "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707",
- "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6",
- "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58",
- "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779",
- "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636",
- "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c",
- "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad",
- "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee",
- "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc",
- "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2",
- "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48",
- "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7",
- "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e",
- "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b",
- "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa",
- "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5",
- "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e",
- "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb",
- "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9",
- "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57",
- "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc",
- "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==2.1.3"
- },
- "mypy": {
- "hashes": [
- "sha256:01fd2e9f85622d981fd9063bfaef1aed6e336eaacca00892cd2d82801ab7c042",
- "sha256:0dde1d180cd84f0624c5dcaaa89c89775550a675aff96b5848de78fb11adabcd",
- "sha256:141dedfdbfe8a04142881ff30ce6e6653c9685b354876b12e4fe6c78598b45e2",
- "sha256:16f0db5b641ba159eff72cff08edc3875f2b62b2fa2bc24f68c1e7a4e8232d01",
- "sha256:190b6bab0302cec4e9e6767d3eb66085aef2a1cc98fe04936d8a42ed2ba77bb7",
- "sha256:2460a58faeea905aeb1b9b36f5065f2dc9a9c6e4c992a6499a2360c6c74ceca3",
- "sha256:34a9239d5b3502c17f07fd7c0b2ae6b7dd7d7f6af35fbb5072c6208e76295816",
- "sha256:43b592511672017f5b1a483527fd2684347fdffc041c9ef53428c8dc530f79a3",
- "sha256:43d24f6437925ce50139a310a64b2ab048cb2d3694c84c71c3f2a1626d8101dc",
- "sha256:45d32cec14e7b97af848bddd97d85ea4f0db4d5a149ed9676caa4eb2f7402bb4",
- "sha256:470c969bb3f9a9efcedbadcd19a74ffb34a25f8e6b0e02dae7c0e71f8372f97b",
- "sha256:566e72b0cd6598503e48ea610e0052d1b8168e60a46e0bfd34b3acf2d57f96a8",
- "sha256:5703097c4936bbb9e9bce41478c8d08edd2865e177dc4c52be759f81ee4dd26c",
- "sha256:7549fbf655e5825d787bbc9ecf6028731973f78088fbca3a1f4145c39ef09462",
- "sha256:8207b7105829eca6f3d774f64a904190bb2231de91b8b186d21ffd98005f14a7",
- "sha256:8c4d8e89aa7de683e2056a581ce63c46a0c41e31bd2b6d34144e2c80f5ea53dc",
- "sha256:98324ec3ecf12296e6422939e54763faedbfcc502ea4a4c38502082711867258",
- "sha256:9bbcd9ab8ea1f2e1c8031c21445b511442cc45c89951e49bbf852cbb70755b1b",
- "sha256:9d40652cc4fe33871ad3338581dca3297ff5f2213d0df345bcfbde5162abf0c9",
- "sha256:a2746d69a8196698146a3dbe29104f9eb6a2a4d8a27878d92169a6c0b74435b6",
- "sha256:ae704dcfaa180ff7c4cfbad23e74321a2b774f92ca77fd94ce1049175a21c97f",
- "sha256:bfdca17c36ae01a21274a3c387a63aa1aafe72bff976522886869ef131b937f1",
- "sha256:c482e1246726616088532b5e964e39765b6d1520791348e6c9dc3af25b233828",
- "sha256:ca637024ca67ab24a7fd6f65d280572c3794665eaf5edcc7e90a866544076878",
- "sha256:e02d700ec8d9b1859790c0475df4e4092c7bf3272a4fd2c9f33d87fac4427b8f",
- "sha256:e5952d2d18b79f7dc25e62e014fe5a23eb1a3d2bc66318df8988a01b1a037c5b"
- ],
- "index": "pypi",
- "version": "==1.4.1"
- },
- "mypy-extensions": {
- "hashes": [
- "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d",
- "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"
- ],
- "markers": "python_version >= '3.5'",
- "version": "==1.0.0"
- },
- "packaging": {
- "hashes": [
- "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61",
- "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==23.1"
- },
- "pathspec": {
- "hashes": [
- "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687",
- "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==0.11.1"
- },
- "platformdirs": {
- "hashes": [
- "sha256:cec7b889196b9144d088e4c57d9ceef7374f6c39694ad1577a0aab50d27ea28c",
- "sha256:f87ca4fcff7d2b0f81c6a748a77973d7af0f4d526f98f308477c3c436c74d528"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==3.8.1"
- },
- "pluggy": {
- "hashes": [
- "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849",
- "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==1.2.0"
- },
- "pycodestyle": {
- "hashes": [
- "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053",
- "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"
- ],
- "index": "pypi",
- "version": "==2.10.0"
- },
- "pytest": {
- "hashes": [
- "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32",
- "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"
- ],
- "index": "pypi",
- "version": "==7.4.0"
- },
- "pytest-cov": {
- "hashes": [
- "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6",
- "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"
- ],
- "index": "pypi",
- "version": "==4.1.0"
- },
- "schema": {
- "hashes": [
- "sha256:f06717112c61895cabc4707752b88716e8420a8819d71404501e114f91043197",
- "sha256:f3ffdeeada09ec34bf40d7d79996d9f7175db93b7a5065de0faa7f41083c1e6c"
- ],
- "version": "==0.7.5"
- },
- "tabulate": {
- "hashes": [
- "sha256:0ba055423dbaa164b9e456abe7920c5e8ed33fcc16f6d1b2f2d152c8e1e8b4fc",
- "sha256:436f1c768b424654fce8597290d2764def1eea6a77cfa5c33be00b1bc0f4f63d",
- "sha256:6c57f3f3dd7ac2782770155f3adb2db0b1a269637e42f27599925e64b114f519"
- ],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
- "version": "==0.8.10"
- },
- "tbump": {
- "hashes": [
- "sha256:170a4395d167daee357cb96af5e874119c470feaba9f605e73f3426e768c2542",
- "sha256:9ebf5d69bc92ca8be1afb13a80f51e374526cb9988f4c3b167036a9e8a10a684"
- ],
- "index": "pypi",
- "version": "==6.10.0"
- },
- "tomlkit": {
- "hashes": [
- "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171",
- "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==0.11.8"
- },
- "towncrier": {
- "hashes": [
- "sha256:da552f29192b3c2b04d630133f194c98e9f14f0558669d427708e203fea4d0a5",
- "sha256:fc29bd5ab4727c8dacfbe636f7fb5dc53b99805b62da1c96b214836159ff70c1"
- ],
- "index": "pypi",
- "version": "==23.6.0"
- },
- "typing-extensions": {
- "hashes": [
- "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36",
- "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"
- ],
- "markers": "python_version >= '3.7'",
- "version": "==4.7.1"
- },
- "unidecode": {
- "hashes": [
- "sha256:547d7c479e4f377b430dd91ac1275d593308dce0fc464fb2ab7d41f82ec653be",
- "sha256:fed09cf0be8cf415b391642c2a5addfc72194407caee4f98719e40ec2a72b830"
- ],
- "markers": "python_version >= '3.5'",
- "version": "==1.3.6"
- }
- }
-}
diff --git a/port_for/__init__.py b/port_for/__init__.py
index 15c664d..289c396 100644
--- a/port_for/__init__.py
+++ b/port_for/__init__.py
@@ -1,19 +1,19 @@
# -*- coding: utf-8 -*-
"""port_for package."""
-__version__ = "0.7.1"
+__version__ = "0.7.2"
from ._ranges import UNASSIGNED_RANGES
from .api import (
available_good_ports,
available_ports,
- is_available,
+ get_port,
good_port_ranges,
+ is_available,
port_is_used,
select_random,
- get_port,
)
-from .store import PortStore
from .exceptions import PortForException
+from .store import PortStore
__all__ = (
"UNASSIGNED_RANGES",
diff --git a/port_for/api.py b/port_for/api.py
index 4ecf9f8..c4e15e6 100644
--- a/port_for/api.py
+++ b/port_for/api.py
@@ -1,15 +1,16 @@
-# -*- coding: utf-8 -*-
+"""main port-for functionality."""
import contextlib
-import socket
import errno
import random
+import socket
from itertools import chain
-from typing import Optional, Set, List, Tuple, Iterable, TypeVar, Type, Union
+from typing import Iterable, List, Optional, Set, Tuple, Type, TypeVar, Union
+
from port_for import ephemeral, utils
+
from ._ranges import UNASSIGNED_RANGES
from .exceptions import PortForException
-
SYSTEM_PORT_RANGE = (0, 1024)
@@ -17,9 +18,7 @@ def select_random(
ports: Optional[Set[int]] = None,
exclude_ports: Optional[Iterable[int]] = None,
) -> int:
- """
- Returns random unused port number.
- """
+ """Return random unused port number."""
if ports is None:
ports = available_good_ports()
@@ -35,9 +34,7 @@ def select_random(
def is_available(port: int) -> bool:
- """
- Returns if port is good to choose.
- """
+ """Return if port is good to choose."""
return port in available_ports() and not port_is_used(port)
@@ -46,9 +43,12 @@ def available_ports(
high: int = 65535,
exclude_ranges: Optional[List[Tuple[int, int]]] = None,
) -> Set[int]:
- """
- Returns a set of possible ports (excluding system,
- ephemeral and well-known ports).
+ """Return a set of possible ports.
+
+ .. note::
+
+ Excluding system, ephemeral and well-known ports.
+
Pass ``high`` and/or ``low`` to limit the port range.
"""
if exclude_ranges is None:
@@ -74,8 +74,8 @@ def available_ports(
def good_port_ranges(
ports: Optional[Set[int]] = None, min_range_len: int = 20, border: int = 3
) -> List[Tuple[int, int]]:
- """
- Returns a list of 'good' port ranges.
+ """Return a list of 'good' port ranges.
+
Such ranges are large and don't contain ephemeral or well-known ports.
Ranges borders are also excluded.
"""
@@ -94,14 +94,16 @@ def good_port_ranges(
def available_good_ports(min_range_len: int = 20, border: int = 3) -> Set[int]:
+ """List available good ports."""
return utils.ranges_to_set(
good_port_ranges(min_range_len=min_range_len, border=border)
)
def port_is_used(port: int, host: str = "127.0.0.1") -> bool:
- """
- Returns if port is used. Port is considered used if the current process
+ """Return if port is used.
+
+ Port is considered used if the current process
can't bind to it or the port doesn't refuse connections.
"""
unused = _can_bind(port, host) and _refuses_connection(port, host)
@@ -130,7 +132,7 @@ T = TypeVar("T")
def filter_by_type(lst: Iterable, type_of: Type[T]) -> List[T]:
- """Returns a list of elements with given type."""
+ """Return a list of elements with given type."""
return [e for e in lst if isinstance(e, type_of)]
@@ -152,9 +154,10 @@ def get_port(
ports: Optional[PortType],
exclude_ports: Optional[Iterable[int]] = None,
) -> Optional[int]:
- """
- Retuns a random available port. If there's only one port passed
- (e.g. 5000 or '5000') function does not check if port is available.
+ """Retun a random available port.
+
+ If there's only one port passed (e.g. 5000 or '5000') function
+ does not check if port is available.
If there's -1 passed as an argument, function returns None.
:param ports:
diff --git a/port_for/cmd.py b/port_for/cmd.py
index be28902..ba9add7 100644
--- a/port_for/cmd.py
+++ b/port_for/cmd.py
@@ -1,6 +1,5 @@
#!/usr/bin/env python
-"""
-cmd.py is a command-line utility that helps with local TCP ports management.
+"""cmd.py is a command-line utility that helps with local TCP ports management.
It finds 'good' unused TCP localhost port and remembers the association.
@@ -26,6 +25,7 @@ Options:
import sys
from typing import Optional
+
import port_for
from port_for.docopt import docopt
diff --git a/port_for/ephemeral.py b/port_for/ephemeral.py
index a3c03ec..41a4685 100644
--- a/port_for/ephemeral.py
+++ b/port_for/ephemeral.py
@@ -1,21 +1,19 @@
# -*- coding: utf-8 -*-
-"""
-This module provide utilities to find ephemeral port ranges for the current OS.
+"""Module provide utilities to find ephemeral port ranges for the current OS.
+
See http://www.ncftp.com/ncftpd/doc/misc/ephemeral_ports.html for more info
about ephemeral port ranges.
Currently only Linux and BSD (including OS X) are supported.
"""
import subprocess
-from typing import List, Tuple, Dict
+from typing import Dict, List, Tuple
DEFAULT_EPHEMERAL_PORT_RANGE = (32768, 65535)
def port_ranges() -> List[Tuple[int, int]]:
- """
- Returns a list of ephemeral port ranges for current machine.
- """
+ """Return a list of ephemeral port ranges for current machine."""
try:
return _linux_ranges()
except (OSError, IOError): # not linux, try BSD
diff --git a/port_for/exceptions.py b/port_for/exceptions.py
index 256a255..dc03591 100644
--- a/port_for/exceptions.py
+++ b/port_for/exceptions.py
@@ -1,3 +1,7 @@
-# -*- coding: utf-8 -*-
+"""Port-for exceptions."""
+
+
class PortForException(Exception):
+ """Main port-for exception class."""
+
pass
diff --git a/port_for/store.py b/port_for/store.py
index a07b737..685753c 100644
--- a/port_for/store.py
+++ b/port_for/store.py
@@ -1,22 +1,25 @@
-# -*- coding: utf-8 -*-
+"""PortStore implementation."""
import os
-from configparser import ConfigParser, DEFAULTSECT
-from typing import Optional, List, Tuple, Union
+from configparser import DEFAULTSECT, ConfigParser
+from typing import List, Optional, Tuple, Union
from .api import select_random
from .exceptions import PortForException
-
DEFAULT_CONFIG_PATH = "/etc/port-for.conf"
class PortStore(object):
+ """PortStore binds, reads and stores bound ports in config."""
+
def __init__(self, config_filename: str = DEFAULT_CONFIG_PATH):
+ """Initialize PortStore."""
self._config = config_filename
def bind_port(
self, app: str, port: Optional[Union[int, str]] = None
) -> int:
+ """Binds port to app in the config."""
if "=" in app or ":" in app:
raise Exception('invalid app name: "%s"' % app)
@@ -61,11 +64,13 @@ class PortStore(object):
return int(requested_port)
def unbind_port(self, app: str) -> None:
+ """Remove port assignement to application."""
parser = self._get_parser()
parser.remove_option(DEFAULTSECT, app)
self._save(parser)
def bound_ports(self) -> List[Tuple[str, int]]:
+ """List all bound ports."""
return [
(app, int(port))
for app, port in self._get_parser().items(DEFAULTSECT)
diff --git a/port_for/utils.py b/port_for/utils.py
index 361d5c0..997f63a 100644
--- a/port_for/utils.py
+++ b/port_for/utils.py
@@ -1,11 +1,10 @@
-# -*- coding: utf-8 -*-
+"""Port for utils."""
import itertools
-from typing import Iterable, Iterator, Tuple, Set
+from typing import Iterable, Iterator, Set, Tuple
def ranges_to_set(lst: Iterable[Tuple[int, int]]) -> Set[int]:
- """
- Convert a list of ranges to a set of numbers::
+ """Convert a list of ranges to a set of numbers.
>>> ranges = [(1,3), (5,6)]
>>> sorted(list(ranges_to_set(ranges)))
@@ -16,8 +15,7 @@ def ranges_to_set(lst: Iterable[Tuple[int, int]]) -> Set[int]:
def to_ranges(lst: Iterable[int]) -> Iterator[Tuple[int, int]]:
- """
- Convert a list of numbers to a list of ranges::
+ """Convert a list of numbers to a list of ranges.
>>> numbers = [1,2,3,5,6]
>>> list(to_ranges(numbers))
diff --git a/pyproject.toml b/pyproject.toml
index 608e240..a4c5862 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "port-for"
-version = "0.7.1"
+version = "0.7.2"
description = "Utility that helps with local TCP ports management. It can find an unused TCP localhost port and remember the association."
readme = "README.rst"
keywords = ["port", "posix"]
@@ -18,22 +18,22 @@ classifiers = [
"License :: OSI Approved :: MIT License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
"Operating System :: POSIX",
"Topic :: System :: Installation/Setup",
"Topic :: System :: Systems Administration",
"Topic :: Internet :: WWW/HTTP :: Site Management",
]
-requires-python = ">= 3.7"
+requires-python = ">= 3.8"
[project.urls]
"Source" = "https://github.com/kmike/port-for/"
"Bug Tracker" = "https://github.com/kmike/port-for/issues"
-"Changelog" = "https://github.com/kmike/port-for/blob/v0.7.1/CHANGES.rst"
+"Changelog" = "https://github.com/kmike/port-for/blob/v0.7.2/CHANGES.rst"
[project.scripts]
port-for = "port_for.cmd:main"
@@ -58,36 +58,58 @@ filterwarnings = "error"
directory = "newsfragments"
single_file=true
filename="CHANGES.rst"
-issue_format="`#{issue} <https://github.com/kmike/port-for/issues/{issue}>`_"
+issue_format="`#{issue} <https://github.com/kmike/port-for/issues/{issue}>`__"
-[tool.towncrier.fragment.feature]
-name = "Features"
+[[tool.towncrier.type]]
+directory = "break"
+name = "Breaking changes"
showcontent = true
-[tool.towncrier.fragment.bugfix]
-name = "Bugfixes"
+[[tool.towncrier.type]]
+directory = "depr"
+name = "Deprecations"
showcontent = true
-[tool.towncrier.fragment.break]
-name = "Breaking changes"
+[[tool.towncrier.type]]
+directory = "feature"
+name = "Features"
showcontent = true
-[tool.towncrier.fragment.misc]
-name = "Miscellaneus"
+[[tool.towncrier.type]]
+directory = "bugfix"
+name = "Bugfixes"
showcontent = true
+[[tool.towncrier.type]]
+directory = "misc"
+name = "Miscellaneus"
+showcontent = false
+
[tool.black]
line-length = 80
target-version = ['py38']
include = '.*\.pyi?$'
+[tool.ruff]
+line-length = 80
+select = [
+ "E", # pycodestyle
+ "F", # pyflakes
+ "I", # isort
+ "D", # pydocstyle
+]
+exclude = [
+ "port_for/docopt.py",
+ "port_for/_download_ranges.py"
+]
+
[tool.tbump]
# Uncomment this if your project is hosted on GitHub:
# github_url = "https://github.com/<user or organization>/<project>/"
[tool.tbump.version]
-current = "0.7.1"
+current = "0.7.2"
# Example of a semver regexp.
# Make sure this matches current_version before
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 2627357..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,3 +0,0 @@
-[pycodestyle]
-max-line-length = 80
-exclude = docs/*,build/*,venv/*
diff --git a/tests/test_cases.py b/tests/test_cases.py
index 02772a8..8f5f3f1 100644
--- a/tests/test_cases.py
+++ b/tests/test_cases.py
@@ -1,10 +1,10 @@
-# -*- coding: utf-8 -*-
-import unittest
+"""Test cases."""
+import os
+import socket
import tempfile
+import unittest
+from typing import List, Set, Tuple, Union
from unittest import mock
-import socket
-import os
-from typing import Union, List, Set, Tuple
import pytest
@@ -14,11 +14,13 @@ from port_for.utils import ranges_to_set
def test_common_ports() -> None:
+ """Check common ports (not available)."""
assert not port_for.is_available(80)
assert not port_for.is_available(11211)
def test_good_port_ranges() -> None:
+ """Select good ranges of ports aout of provided."""
ranges = [
(10, 15), # too short
(100, 200), # good
@@ -33,16 +35,18 @@ def test_good_port_ranges() -> None:
def test_something_works() -> None:
+ """Test default behaviour of good_port_ranges and available_good_ports."""
assert len(port_for.good_port_ranges()) > 10
assert len(port_for.available_good_ports()) > 1000
def test_binding() -> None:
- # low ports are not available
+ """Low ports are not available."""
assert port_for.port_is_used(10)
def test_binding_high() -> None:
+ """Test ports that are not used."""
s = socket.socket()
s.bind(("", 0))
port = s.getsockname()[1]
@@ -115,13 +119,17 @@ def test_port_mix() -> None:
class SelectPortTest(unittest.TestCase):
+ """Port selecting tests."""
+
@mock.patch("port_for.api.port_is_used")
def test_all_used(self, port_is_used: mock.MagicMock) -> None:
+ """Check behaviour if there are no ports to use."""
port_is_used.return_value = True
self.assertRaises(port_for.PortForException, port_for.select_random)
@mock.patch("port_for.api.port_is_used")
def test_random_port(self, port_is_used: mock.MagicMock) -> None:
+ """Test random ports."""
ports = set([1, 2, 3])
used = {1: True, 2: False, 3: True}
port_is_used.side_effect = lambda port: used[port]
@@ -131,14 +139,19 @@ class SelectPortTest(unittest.TestCase):
class StoreTest(unittest.TestCase):
+ """Port Store test suite."""
+
def setUp(self) -> None:
+ """Set up tests."""
fd, self.fname = tempfile.mkstemp()
self.store = port_for.PortStore(self.fname)
def tearDown(self) -> None:
+ """Tear down tests."""
os.remove(self.fname)
def test_store(self) -> None:
+ """Test port store."""
assert self.store.bound_ports() == []
port = self.store.bind_port("foo")
@@ -156,14 +169,14 @@ class StoreTest(unittest.TestCase):
self.assertEqual(self.store.bound_ports(), [("foo", port)])
def test_rebind(self) -> None:
- # try to rebind an used port for an another app
+ """Try to rebind an used port for an another app."""
port = self.store.bind_port("foo")
self.assertRaises(
port_for.PortForException, self.store.bind_port, "baz", port
)
def test_change_port(self) -> None:
- # changing app ports is not supported.
+ """Changing app ports is not supported."""
port = self.store.bind_port("foo")
another_port = port_for.select_random()
assert port != another_port
@@ -172,13 +185,13 @@ class StoreTest(unittest.TestCase):
)
def test_bind_unavailable(self) -> None:
- # it is possible to explicitly bind currently unavailable port
+ """It is possible to explicitly bind currently unavailable port."""
port = self.store.bind_port("foo", 80)
self.assertEqual(port, 80)
self.assertEqual(self.store.bound_ports(), [("foo", 80)])
def test_bind_non_auto(self) -> None:
- # it is possible to pass a port
+ """It is possible to pass a port."""
port = port_for.select_random()
res_port = self.store.bind_port("foo", port)
self.assertEqual(res_port, port)