Skip to content

Commit

Permalink
Merge pull request #170 from kmike/ruff
Browse files Browse the repository at this point in the history
Ruff
  • Loading branch information
fizyk authored Oct 10, 2023
2 parents 217a90e + 3302529 commit 8ed0d52
Show file tree
Hide file tree
Showing 13 changed files with 94 additions and 59 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/linters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ jobs:
uses: fizyk/actions-reuse/.github/workflows/[email protected]
with:
mypy: true
pydocstyle: false
ruff: true
black: true
4 changes: 2 additions & 2 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ towncrier = "==23.6.0"
pytest = "==7.4.2"
pytest-cov = "==4.1.0"
coverage = "==7.3.2"
black = {version = "==23.9.1", markers="python_version >= '3.8'"}
pycodestyle = "==2.11.0"
black = "==23.9.1"
mypy = "==1.5.1"
tbump = "==6.11.0"
ruff = "==0.0.292"
3 changes: 3 additions & 0 deletions newsfragments/170.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Reformatted code with ruff and black.

Ruff skips docopt and _download_ranges module for the time being.
6 changes: 3 additions & 3 deletions port_for/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
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",
Expand Down
45 changes: 24 additions & 21 deletions port_for/api.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
# -*- 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)


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()

Expand All @@ -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)


Expand All @@ -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:
Expand All @@ -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.
"""
Expand All @@ -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)
Expand Down Expand Up @@ -130,7 +132,7 @@ def _refuses_connection(port: int, host: str) -> bool:


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)]


Expand All @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions port_for/cmd.py
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -26,6 +25,7 @@

import sys
from typing import Optional

import port_for
from port_for.docopt import docopt

Expand Down
10 changes: 4 additions & 6 deletions port_for/ephemeral.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
6 changes: 5 additions & 1 deletion port_for/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# -*- coding: utf-8 -*-
"""Port-for exceptions."""


class PortForException(Exception):
"""Main port-for exception class."""

pass
13 changes: 9 additions & 4 deletions port_for/store.py
Original file line number Diff line number Diff line change
@@ -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)

Expand Down Expand Up @@ -61,11 +64,13 @@ def bind_port(
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)
Expand Down
10 changes: 4 additions & 6 deletions port_for/utils.py
Original file line number Diff line number Diff line change
@@ -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)))
Expand All @@ -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))
Expand Down
13 changes: 13 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,19 @@ 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:
Expand Down
3 changes: 0 additions & 3 deletions setup.cfg

This file was deleted.

Loading

0 comments on commit 8ed0d52

Please sign in to comment.