Port79: Async Finger Protocol Client Library
Port79 is an async-first, fully type-hinted Python client library for the Finger User Information Protocol (RFC 1288).
Features
- Async First: Built on top of Python's standard
asyncionetworking loop. - RFC 1288 Support: Full support for standard system queries, user queries, verbose (
/W) requests, and remote host forwarding. - Type Safe: Fully typed API passing strict static type checking (
mypy --strict). - FingerURI Representation: Rich URI class to parse, inspect, validate, and manipulate Finger URIs and query targets.
- Zero Dependencies: Built entirely on Python's standard library.
- CLI Utility: Includes a
port79command-line interface out of the box.
Installation
port79 requires Python 3.12 or later and can be installed with your package manager of choice.
With pip:
pip install port79
With uv:
uv add port79
Quick Start
1. Make a Simple Request
Use Client with standard async context managers to query a Finger server:
import asyncio
from port79 import Client, Port79Error
async def main():
async with Client() as client:
try:
# Query a user at a target host
response = await client.request("davep@plan.cat")
print(f"Target host: {response.target_host}")
print(f"Query kind: {response.query_kind.name}")
print(f"Latency: {response.latency:.3f}s")
print("--- Response Text ---")
print(response.text)
except Port79Error as e:
print(f"Request failed: {e}")
if __name__ == "__main__":
asyncio.run(main())
2. Working with FingerURI
The FingerURI class parses both URI strings (finger://host/user) and target format strings (user@host, /W user@host, @host):
from port79 import FingerURI
# Parse from email-style target or full URI
uri = FingerURI.from_string("/W davep@plan.cat")
print(uri.host) # 'plan.cat'
print(uri.username) # 'davep'
print(uri.is_verbose) # True
print(uri.raw_query) # '/W davep\r\n'
# Create modified copies
custom_port_uri = uri.with_port(7979)
system_uri = uri.with_username(None)
resolved_uri = uri.resolve("alice")
3. Verbose and System Queries
You can issue verbose queries or system-wide logged-in user listings:
async with Client() as client:
# System query (requests logged-in user list)
system_response = await client.request("plan.cat")
assert system_response.is_system_query
# Verbose user query
verbose_response = await client.request("finger://plan.cat/davep?W")
assert verbose_response.is_verbose
Command Line Interface (CLI)
port79 includes a command-line client:
# Query a user
uv run port79 davep@plan.cat
# Request verbose output
uv run port79 -w davep@plan.cat
# Query system user list on a custom port
uv run port79 -p 7979 plan.cat
# Display CLI help
uv run port79 --help
Licence
MIT
Metadata
Release files for port79 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| port79-1.1.0.tar.gz | 10.7 kB | Without provenance | Details for port79-1.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| port79-1.1.0-py3-none-any.whl | Python 3 | none | any | Details for port79-1.1.0-py3-none-any.whl |
Total release size: 24.1 kB
Release files / port79-1.1.0.tar.gz
| Download URL | port79-1.1.0.tar.gz |
|---|---|
| Size | 10.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
19580cec81dbbdae05668d6cd5f98b22ecc38f2cfa596e457b942ad5eee362cf
|
|
BLAKE2b-256 checksum How to use checksums |
710086159a02077c71a1cfb1a95ba88fbb83c51301bad003cfabdf4ec96dc45f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / port79-1.1.0-py3-none-any.whl
| Download URL | port79-1.1.0-py3-none-any.whl |
|---|---|
| Size | 13.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c07fc61f3035c1ee1b0c35fd22696fcdfea412cd1ec468189b2a2fccbb02d901
|
|
BLAKE2b-256 checksum How to use checksums |
45672b60273f14dc6867e779b880a59520a451e9992fb4cf010c289ae2f64c8e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for port79 1.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.