Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import re
from typing import List
from .net_port import is_port ← from net.port ^1.0.0 · built alongside by fune
NUMBER = re.compile(r"[0-9]+")
def _trim_blank(s: str) -> str:
"""Spaces and tabs only: a newline inside a port list is a mistake, not padding."""
return s.strip(" \t")
def _is_number(s: str) -> bool:
"""Whole ASCII digits with no leading zero: "80", not "080", "+80" or "٨٠"."""
return NUMBER.fullmatch(s) is not None and (len(s) == 1 or s[0] != "0")
def _port(token: str) -> int:
# More than five digits cannot be a port.
value = 0 if len(token) > 5 else int(token)
if not is_port(value):
raise ValueError('port "%s" is out of range 1-65535' % token)
return value
def parse_port_list(text: str) -> List[int]:
"""Parse a port list such as "22,80,8000-8010" into port numbers: each port
once, in the order first given. Ranges are inclusive.
"""
if not isinstance(text, str):
raise TypeError("text must be a string")
if _trim_blank(text) == "":
raise ValueError("port list is empty")
out: List[int] = []
seen = set()
def add(p: int) -> None:
if p not in seen:
seen.add(p)
out.append(p)
for raw in text.split(","):
item = _trim_blank(raw)
if item == "":
raise ValueError("empty item in port list")
if "-" in item:
ends = item.split("-")
if len(ends) != 2 or not _is_number(ends[0]) or not _is_number(ends[1]):
raise ValueError('invalid port range "%s"' % item)
low = _port(ends[0])
high = _port(ends[1])
if low > high:
raise ValueError('port range "%s" runs backwards' % item)
for p in range(low, high + 1):
add(p)
else:
if not _is_number(item):
raise ValueError('invalid port "%s"' % item)
add(_port(item))
return out