Port70: Async Gopher Protocol Client Library
Port70 is an async-first, fully type-hinted Python client library for the Gopher protocol (RFC 1436 / RFC 4266).
Features
- Async First: Built on top of Python's standard
asyncionetworking loop. - RFC 1436 & RFC 4266 Support: Full support for standard Gopher item types, selectors, search queries, and URIs.
- Type Safe: Fully typed API passing strict static type checking (
mypy --strict). - GopherURI Representation: Rich URI class to parse, inspect, validate, manipulate, and resolve Gopher URIs and query targets.
- Zero Dependencies: Built entirely on Python's standard library.
- CLI Utility: Includes a
port70command-line interface out of the box.
Installation
port70 requires Python 3.12 or later and can be installed with your package manager of choice.
With pip:
pip install port70
With uv:
uv add port70
Quick Start
1. Make a Simple Request
Use Client with standard async context managers to query a Gopher server:
import asyncio
from port70 import Client, Port70Error
async def main():
async with Client() as client:
try:
# Query a Gopher menu or document
response = await client.request("gopher://gopher.floodgap.com/")
print(f"Target host: {response.uri.host}")
print(f"Item type: {response.item_type}")
print(f"Content length: {len(response.content)} bytes")
print("--- Response Text ---")
print(response.text)
except Port70Error as error:
print(f"Request failed: {error}")
if __name__ == "__main__":
asyncio.run(main())
2. Working with GopherURI
The GopherURI class parses both full URI strings (gopher://host/1/selector) and target format strings:
from port70 import GopherURI
# Parse from Gopher URI string
uri = GopherURI.from_string("gopher://gopher.floodgap.com/7/v2/vs?python")
print(uri.host) # 'gopher.floodgap.com'
print(uri.port) # 70
print(uri.item_type) # '7'
print(uri.selector) # '/v2/vs'
print(uri.query) # 'python'
print(uri.is_search) # True
# Create modified copies
custom_port_uri = uri.with_port(7070)
parent_uri = uri.parent
root_uri = uri.root
3. Search Queries and Response Inspection
You can issue search queries for item type 7 search engines or inspect item types on responses:
async with Client() as client:
# Send a search request with query terms
response = await client.request(
"gopher://gopher.floodgap.com/7/v2/vs",
query_terms="python",
)
assert response.is_text
# Access text response split into lines
for line in response.lines[:5]:
print(line)
Command Line Interface (CLI)
port70 includes a command-line client:
# Query a Gopher target (defaults to gopher://gopher.floodgap.com/)
uv run port70 gopher://gopher.floodgap.com/
# Perform a search request
uv run port70 -q python gopher://gopher.floodgap.com/7/v2/vs
# Query on a custom port
uv run port70 -p 7070 gopher://example.com/1/
# Output raw binary content to stdout
uv run port70 -r gopher://gopher.floodgap.com/0/gopher/readdata
# Display CLI help
uv run port70 --help
Licence
MIT
Release files for port70 1.0.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 | |
|---|---|---|---|
| port70-1.0.0.tar.gz | 9.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| port70-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 21.3 kB
Release files / port70-1.0.0.tar.gz
| Download URL | port70-1.0.0.tar.gz |
|---|---|
| Size | 9.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c5f58df5c7f1d6f42d95e4456e9878357b3d8827d7c7a377045ba529043cc050
|
|
BLAKE2b-256 checksum How to use checksums |
a0fccd64e080aee9887618105bb414cf56e71c0b745cc421f0e12c49a7fd0373
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","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 / port70-1.0.0-py3-none-any.whl
| Download URL | port70-1.0.0-py3-none-any.whl |
|---|---|
| Size | 11.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ac956e27d62502687442823371ade772895b7992918d03978ca8bed157b497f4
|
|
BLAKE2b-256 checksum How to use checksums |
e5614ef6a612b4f8cce8cb36a4e9a801077d94b2d017448626c3fd07f4ccddb6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","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}
|