Skip to main content

pypatree

CI PyPI Python License

Pretty-print a project's module tree with syntax-highlighted signatures.

uvx pypatree@latest
uvx pypatree@latest --flat

Run from a Python project or a repository containing Python subprojects. Pypatree reads local source with Griffe. The project and its dependencies do not need to be installed, and its code is not executed. Pass a dotted package or module name, such as uvx pypatree@latest mypkg.parsers, to inspect one subtree. Unknown and excluded scopes raise an error.

Use uv run pypatree --flat for fully qualified names, one module or callable per line. Flat output has no terminal wrapping and works with rg and other line-oriented tools. Both formats support --color auto|always|never; auto colors terminal output and emits plain text when piped. Add --docstrings none to omit module prose.

Source inspection shows declared functions, classes, and dataclass constructors. Defaults remain source expressions; decorators and metaclasses can change the runtime API. Classes without a local or synthesized constructor appear as name(...). Parsing requires a Python version that supports the project's syntax; select it with uvx --python 3.14 pypatree@latest when needed. A parse failure produces a diagnostic on stderr, preserves available output, and exits nonzero.

Discovery supports conventional package, src, namespace-only, and single-module layouts. From a repository root, it searches for subprojects with pyproject.toml, setup.py, or setup.cfg, stopping at each project boundary and skipping hidden, build, test, and output directories. Within each project, discovery prefers regular packages, then namespaces, then module files. Duplicate package names require running from the intended subproject.

Use uv run pypatree --runtime for APIs created dynamically. Install pypatree and the inspected project into the same environment (uv add --dev pypatree and uv pip install -e .). Runtime discovery uses editable-install metadata and imports trusted project code, including parent package initializers. Imports can have side effects or require optional dependencies. Import failures retain available output and exit nonzero; unavailable signatures appear as name(...) with a warning. --verbose adds discovery details and tracebacks.

Output lists public functions and classes defined in each module. Class methods, constants, and imported re-exports are outside this view.

pypatree  pypatree - Pretty-print a project's module tree.
├── __main__
│   ├── main() -> int
│   └── run(cfg: Config) -> bool
├── config  Configuration types for pypatree.
│   ├── Config(
│   │       scope: Optional[str] = ...,
│   │       exclude: Optional[str] = ...,
│   │       docstrings: DocstringMode = ...,
│   │       show_defaults: bool = ...,
│   │       flat: bool = ...,
│   │       color: Literal['auto', 'always', 'never'] = ...,
│   │       verbose: bool = ...,
│   │       runtime: bool = ...,
│   │   )
│   └── DocstringMode(...)
├── discovery
│   └── get_packages(
│           exclude: Optional[str] = ...,
│           scope: Optional[str] = ...,
│           *,
│           on_error: ErrorHandler = ...,
│       ) -> dict[str, list[str]]
├── display
│   ├── print_tree(pkg_name: str, tree: Tree, cfg: Config) -> None
│   └── render_tree(tree: Tree, prefix: str = ...) -> list[str]
├── introspection
│   ├── format_inspected_signature(
│   │       sig: inspect.Signature,
│   │       *,
│   │       name: str,
│   │       show_defaults: bool,
│   │       max_width: Optional[int],
│   │   ) -> str
│   ├── format_signature(
│   │       obj: Union[Callable, type],
│   │       show_defaults: bool,
│   │       *,
│   │       max_width: Optional[int] = ...,
│   │       name: Optional[str] = ...,
│   │   ) -> str
│   ├── get_module_docstring(modname: str, short: bool = ...) -> Optional[str]
│   ├── get_module_items(
│   │       modname: str,
│   │       exclude: Optional[str],
│   │       show_defaults: bool,
│   │       *,
│   │       max_width: Optional[int] = ...,
│   │       on_error: ErrorHandler = ...,
│   │   ) -> list[str]
│   ├── import_module(modname: str) -> ModuleType
│   └── safe_import(
│           modname: str,
│           *,
│           on_error: ErrorHandler = ...,
│       ) -> Optional[ModuleType]
├── source
│   ├── source_packages(root: Path) -> dict[str, Path]
│   └── source_trees(
│           *,
│           root: Path,
│           scope: Optional[str],
│           exclude: Optional[str],
│           show_defaults: bool,
│           max_width: Optional[int],
│           on_error: ErrorHandler,
│       ) -> dict[str, Tree]
└── tree
    ├── Tree(
    │       items: list[str] = ...,
    │       children: dict[str, Tree] = ...,
    │       docstring: Optional[str] = ...,
    │       failed: bool = ...,
    │   )
    ├── build_tree(
    │       submods: list[str],
    │       pkg_name: str,
    │       exclude: Optional[str],
    │       show_defaults: bool,
    │       *,
    │       max_width: Optional[int] = ...,
    │       on_error: ErrorHandler = ...,
    │   ) -> Tree
    └── get_subtree(tree: Tree, path: list[str]) -> Optional[Tree]

Flat output for the introspection module:

pypatree.introspection
pypatree.introspection.format_inspected_signature(sig: inspect.Signature, *, name: str, show_defaults: bool, max_width: Optional[int]) -> str
pypatree.introspection.format_signature(obj: Union[Callable, type], show_defaults: bool, *, max_width: Optional[int] = ..., name: Optional[str] = ...) -> str
pypatree.introspection.get_module_docstring(modname: str, short: bool = ...) -> Optional[str]
pypatree.introspection.get_module_items(modname: str, exclude: Optional[str], show_defaults: bool, *, max_width: Optional[int] = ..., on_error: ErrorHandler = ...) -> list[str]
pypatree.introspection.import_module(modname: str) -> ModuleType
pypatree.introspection.safe_import(modname: str, *, on_error: ErrorHandler = ...) -> Optional[ModuleType]

Run pypatree --help for options:

usage: pypatree [-h] [OPTIONS] [MODULE]

Display module tree with public functions/classes.

╭─ positional arguments ─────────────────────────────────────────────────────╮
│ [MODULE]                Module path to scope to (e.g., 'mypkg.submodule'). │
│                         (default: None)                                    │
╰────────────────────────────────────────────────────────────────────────────╯
╭─ options ──────────────────────────────────────────────────────────────────╮
│ -h, --help              show this help message and exit                    │
│ --exclude {None}|STR    Regex to exclude module segments and item names    │
│                         (default: tests). Use '' for none. (default:       │
│                         '^tests?$|^test_')                                 │
│ --docstrings {none,short,full}                                             │
│                         Show module docstrings: none, short (first line),  │
│                         or full. (default: short)                          │
│ --show-defaults, --no-show-defaults                                        │
│                         Show default values in signatures. Otherwise, =    │
│                         ... marks optional parameters. (default: False)    │
│ --flat, --no-flat       Print fully qualified names, one item per line,    │
│                         without tree guides or wrapping. (default: False)  │
│ --color {auto,always,never}                                                │
│                         Color policy for either output format. Auto        │
│                         detects the terminal. (default: auto)              │
│ --verbose, --no-verbose                                                    │
│                         Enable debug logging to stderr. (default: False)   │
│ --runtime, --no-runtime                                                    │
│                         Import editable-installed code in this             │
│                         environment. Default: read local source. (default: │
│                         False)                                             │
╰────────────────────────────────────────────────────────────────────────────╯

Example on httpx: Source: commit b5addb64f0161ff6bfe94c124ef76f6a1fba5254, Python 3.9.25.

httpx
├── main() -> None
├── __version__
├── _api
│   ├── delete(
│   │       url: URL | str,
│   │       *,
│   │       params: QueryParamTypes | None = ...,
│   │       headers: HeaderTypes | None = ...,
│   │       cookies: CookieTypes | None = ...,
│   │       auth: AuthTypes | None = ...,
│   │       proxy: ProxyTypes | None = ...,
│   │       follow_redirects: bool = ...,
│   │       timeout: TimeoutTypes = ...,
│   │       verify: ssl.SSLContext | str | bool = ...,
│   │       trust_env: bool = ...,
│   │   ) -> Response
│   ├── get(
│   │       url: URL | str,
│   │       *,
│   │       params: QueryParamTypes | None = ...,
│   │       headers: HeaderTypes | None = ...,
│   │       cookies: CookieTypes | None = ...,
│   │       auth: AuthTypes | None = ...,
│   │       proxy: ProxyTypes | None = ...,
│   │       follow_redirects: bool = ...,
│   │       verify: ssl.SSLContext | str | bool = ...,
│   │       timeout: TimeoutTypes = ...,
│   │       trust_env: bool = ...,
│   │   ) -> Response
│   ├── head(
│   │       url: URL | str,
│   │       *,
│   │       params: QueryParamTypes | None = ...,
│   │       headers: HeaderTypes | None = ...,
│   │       cookies: CookieTypes | None = ...,
│   │       auth: AuthTypes | None = ...,
│   │       proxy: ProxyTypes | None = ...,
│   │       follow_redirects: bool = ...,
│   │       verify: ssl.SSLContext | str | bool = ...,
│   │       timeout: TimeoutTypes = ...,
│   │       trust_env: bool = ...,
│   │   ) -> Response
│   ├── options(
│   │       url: URL | str,
│   │       *,
│   │       params: QueryParamTypes | None = ...,
│   │       headers: HeaderTypes | None = ...,
│   │       cookies: CookieTypes | None = ...,
│   │       auth: AuthTypes | None = ...,
│   │       proxy: ProxyTypes | None = ...,
│   │       follow_redirects: bool = ...,
│   │       verify: ssl.SSLContext | str | bool = ...,
│   │       timeout: TimeoutTypes = ...,
│   │       trust_env: bool = ...,
│   │   ) -> Response
│   ├── patch(
│   │       url: URL | str,
│   │       *,
│   │       content: RequestContent | None = ...,
│   │       data: RequestData | None = ...,
│   │       files: RequestFiles | None = ...,
│   │       json: typing.Any | None = ...,
│   │       params: QueryParamTypes | None = ...,
│   │       headers: HeaderTypes | None = ...,
│   │       cookies: CookieTypes | None = ...,
│   │       auth: AuthTypes | None = ...,
│   │       proxy: ProxyTypes | None = ...,
│   │       follow_redirects: bool = ...,
│   │       verify: ssl.SSLContext | str | bool = ...,
│   │       timeout: TimeoutTypes = ...,
│   │       trust_env: bool = ...,
│   │   ) -> Response
│   ├── post(
│   │       url: URL | str,
│   │       *,
│   │       content: RequestContent | None = ...,
│   │       data: RequestData | None = ...,
│   │       files: RequestFiles | None = ...,
│   │       json: typing.Any | None = ...,
│   │       params: QueryParamTypes | None = ...,
│   │       headers: HeaderTypes | None = ...,
│   │       cookies: CookieTypes | None = ...,
│   │       auth: AuthTypes | None = ...,
│   │       proxy: ProxyTypes | None = ...,
│   │       follow_redirects: bool = ...,
│   │       verify: ssl.SSLContext | str | bool = ...,
│   │       timeout: TimeoutTypes = ...,
│   │       trust_env: bool = ...,
│   │   ) -> Response
│   ├── put(
│   │       url: URL | str,
│   │       *,
│   │       content: RequestContent | None = ...,
│   │       data: RequestData | None = ...,
│   │       files: RequestFiles | None = ...,
│   │       json: typing.Any | None = ...,
│   │       params: QueryParamTypes | None = ...,
│   │       headers: HeaderTypes | None = ...,
│   │       cookies: CookieTypes | None = ...,
│   │       auth: AuthTypes | None = ...,
│   │       proxy: ProxyTypes | None = ...,
│   │       follow_redirects: bool = ...,
│   │       verify: ssl.SSLContext | str | bool = ...,
│   │       timeout: TimeoutTypes = ...,
│   │       trust_env: bool = ...,
│   │   ) -> Response
│   ├── request(
│   │       method: str,
│   │       url: URL | str,
│   │       *,
│   │       params: QueryParamTypes | None = ...,
│   │       content: RequestContent | None = ...,
│   │       data: RequestData | None = ...,
│   │       files: RequestFiles | None = ...,
│   │       json: typing.Any | None = ...,
│   │       headers: HeaderTypes | None = ...,
│   │       cookies: CookieTypes | None = ...,
│   │       auth: AuthTypes | None = ...,
│   │       proxy: ProxyTypes | None = ...,
│   │       timeout: TimeoutTypes = ...,
│   │       follow_redirects: bool = ...,
│   │       verify: ssl.SSLContext | str | bool = ...,
│   │       trust_env: bool = ...,
│   │   ) -> Response
│   └── stream(
│           method: str,
│           url: URL | str,
│           *,
│           params: QueryParamTypes | None = ...,
│           content: RequestContent | None = ...,
│           data: RequestData | None = ...,
│           files: RequestFiles | None = ...,
│           json: typing.Any | None = ...,
│           headers: HeaderTypes | None = ...,
│           cookies: CookieTypes | None = ...,
│           auth: AuthTypes | None = ...,
│           proxy: ProxyTypes | None = ...,
│           timeout: TimeoutTypes = ...,
│           follow_redirects: bool = ...,
│           verify: ssl.SSLContext | str | bool = ...,
│           trust_env: bool = ...,
│       ) -> typing.Iterator[Response]
├── _auth
│   ├── Auth(...)
│   ├── BasicAuth(username: str | bytes, password: str | bytes)
│   ├── DigestAuth(username: str | bytes, password: str | bytes)
│   ├── FunctionAuth(func: typing.Callable[[Request], Request])
│   └── NetRCAuth(file: str | None = ...)
├── _client
│   ├── AsyncClient(
│   │       *,
│   │       auth: AuthTypes | None = ...,
│   │       params: QueryParamTypes | None = ...,
│   │       headers: HeaderTypes | None = ...,
│   │       cookies: CookieTypes | None = ...,
│   │       verify: ssl.SSLContext | str | bool = ...,
│   │       cert: CertTypes | None = ...,
│   │       http1: bool = ...,
│   │       http2: bool = ...,
│   │       proxy: ProxyTypes | None = ...,
│   │       mounts: None | typing.Mapping[str, AsyncBaseTransport | None] = ...,
│   │       timeout: TimeoutTypes = ...,
│   │       follow_redirects: bool = ...,
│   │       limits: Limits = ...,
│   │       max_redirects: int = ...,
│   │       event_hooks: None | typing.Mapping[str, list[EventHook]] = ...,
│   │       base_url: URL | str = ...,
│   │       transport: AsyncBaseTransport | None = ...,
│   │       trust_env: bool = ...,
│   │       default_encoding: str | typing.Callable[[bytes], str] = ...,
│   │   )
│   ├── BaseClient(
│   │       *,
│   │       auth: AuthTypes | None = ...,
│   │       params: QueryParamTypes | None = ...,
│   │       headers: HeaderTypes | None = ...,
│   │       cookies: CookieTypes | None = ...,
│   │       timeout: TimeoutTypes = ...,
│   │       follow_redirects: bool = ...,
│   │       max_redirects: int = ...,
│   │       event_hooks: None | typing.Mapping[str, list[EventHook]] = ...,
│   │       base_url: URL | str = ...,
│   │       trust_env: bool = ...,
│   │       default_encoding: str | typing.Callable[[bytes], str] = ...,
│   │   )
│   ├── BoundAsyncStream(
│   │       stream: AsyncByteStream,
│   │       response: Response,
│   │       start: float,
│   │   )
│   ├── BoundSyncStream(
│   │       stream: SyncByteStream,
│   │       response: Response,
│   │       start: float,
│   │   )
│   ├── Client(
│   │       *,
│   │       auth: AuthTypes | None = ...,
│   │       params: QueryParamTypes | None = ...,
│   │       headers: HeaderTypes | None = ...,
│   │       cookies: CookieTypes | None = ...,
│   │       verify: ssl.SSLContext | str | bool = ...,
│   │       cert: CertTypes | None = ...,
│   │       trust_env: bool = ...,
│   │       http1: bool = ...,
│   │       http2: bool = ...,
│   │       proxy: ProxyTypes | None = ...,
│   │       mounts: None | typing.Mapping[str, BaseTransport | None] = ...,
│   │       timeout: TimeoutTypes = ...,
│   │       follow_redirects: bool = ...,
│   │       limits: Limits = ...,
│   │       max_redirects: int = ...,
│   │       event_hooks: None | typing.Mapping[str, list[EventHook]] = ...,
│   │       base_url: URL | str = ...,
│   │       transport: BaseTransport | None = ...,
│   │       default_encoding: str | typing.Callable[[bytes], str] = ...,
│   │   )
│   ├── ClientState(...)
│   └── UseClientDefault(...)
├── _config
│   ├── Limits(
│   │       *,
│   │       max_connections: int | None = ...,
│   │       max_keepalive_connections: int | None = ...,
│   │       keepalive_expiry: float | None = ...,
│   │   )
│   ├── Proxy(
│   │       url: URL | str,
│   │       *,
│   │       ssl_context: ssl.SSLContext | None = ...,
│   │       auth: tuple[str, str] | None = ...,
│   │       headers: HeaderTypes | None = ...,
│   │   )
│   ├── Timeout(
│   │       timeout: TimeoutTypes | UnsetType = ...,
│   │       *,
│   │       connect: None | float | UnsetType = ...,
│   │       read: None | float | UnsetType = ...,
│   │       write: None | float | UnsetType = ...,
│   │       pool: None | float | UnsetType = ...,
│   │   )
│   ├── UnsetType(...)
│   └── create_ssl_context(
│           verify: ssl.SSLContext | str | bool = ...,
│           cert: CertTypes | None = ...,
│           trust_env: bool = ...,
│       ) -> ssl.SSLContext
├── _content
│   ├── AsyncIteratorByteStream(stream: AsyncIterable[bytes])
│   ├── ByteStream(stream: bytes)
│   ├── IteratorByteStream(stream: Iterable[bytes])
│   ├── UnattachedStream(...)
│   ├── encode_content(
│   │       content: str | bytes | Iterable[bytes] | AsyncIterable[bytes],
│   │   ) -> tuple[dict[str, str], SyncByteStream | AsyncByteStream]
│   ├── encode_html(html: str) -> tuple[dict[str, str], ByteStream]
│   ├── encode_json(json: Any) -> tuple[dict[str, str], ByteStream]
│   ├── encode_multipart_data(
│   │       data: RequestData,
│   │       files: RequestFiles,
│   │       boundary: bytes | None,
│   │   ) -> tuple[dict[str, str], MultipartStream]
│   ├── encode_request(
│   │       content: RequestContent | None = ...,
│   │       data: RequestData | None = ...,
│   │       files: RequestFiles | None = ...,
│   │       json: Any | None = ...,
│   │       boundary: bytes | None = ...,
│   │   ) -> tuple[dict[str, str], SyncByteStream | AsyncByteStream]
│   ├── encode_response(
│   │       content: ResponseContent | None = ...,
│   │       text: str | None = ...,
│   │       html: str | None = ...,
│   │       json: Any | None = ...,
│   │   ) -> tuple[dict[str, str], SyncByteStream | AsyncByteStream]
│   ├── encode_text(text: str) -> tuple[dict[str, str], ByteStream]
│   └── encode_urlencoded_data(
│           data: RequestData,
│       ) -> tuple[dict[str, str], ByteStream]
├── _decoders  Handlers for Content-Encoding.
│   ├── BrotliDecoder()
│   ├── ByteChunker(chunk_size: int | None = ...)
│   ├── ContentDecoder(...)
│   ├── DeflateDecoder()
│   ├── GZipDecoder()
│   ├── IdentityDecoder(...)
│   ├── LineDecoder()
│   ├── MultiDecoder(children: typing.Sequence[ContentDecoder])
│   ├── TextChunker(chunk_size: int | None = ...)
│   ├── TextDecoder(encoding: str = ...)
│   └── ZStandardDecoder()
├── _exceptions  Our exception hierarchy:
│   ├── CloseError(...)
│   ├── ConnectError(...)
│   ├── ConnectTimeout(...)
│   ├── CookieConflict(message: str)
│   ├── DecodingError(...)
│   ├── HTTPError(message: str)
│   ├── HTTPStatusError(message: str, *, request: Request, response: Response)
│   ├── InvalidURL(message: str)
│   ├── LocalProtocolError(...)
│   ├── NetworkError(...)
│   ├── PoolTimeout(...)
│   ├── ProtocolError(...)
│   ├── ProxyError(...)
│   ├── ReadError(...)
│   ├── ReadTimeout(...)
│   ├── RemoteProtocolError(...)
│   ├── RequestError(message: str, *, request: Request | None = ...)
│   ├── RequestNotRead()
│   ├── ResponseNotRead()
│   ├── StreamClosed()
│   ├── StreamConsumed()
│   ├── StreamError(message: str)
│   ├── TimeoutException(...)
│   ├── TooManyRedirects(...)
│   ├── TransportError(...)
│   ├── UnsupportedProtocol(...)
│   ├── WriteError(...)
│   ├── WriteTimeout(...)
│   └── request_context(request: Request | None = ...) -> typing.Iterator[None]
├── _main
│   ├── download_response(response: Response, download: typing.BinaryIO) -> None
│   ├── format_certificate(cert: _PeerCertRetDictType) -> str
│   ├── format_request_headers(
│   │       request: httpcore.Request,
│   │       http2: bool = ...,
│   │   ) -> str
│   ├── format_response_headers(
│   │       http_version: bytes,
│   │       status: int,
│   │       reason_phrase: bytes | None,
│   │       headers: list[tuple[bytes, bytes]],
│   │   ) -> str
│   ├── get_lexer_for_response(response: Response) -> str
│   ├── handle_help(
│   │       ctx: click.Context,
│   │       param: click.Option | click.Parameter,
│   │       value: typing.Any,
│   │   ) -> None
│   ├── main(
│   │       url: str,
│   │       method: str,
│   │       params: list[tuple[str, str]],
│   │       content: str,
│   │       data: list[tuple[str, str]],
│   │       files: list[tuple[str, click.File]],
│   │       json: str,
│   │       headers: list[tuple[str, str]],
│   │       cookies: list[tuple[str, str]],
│   │       auth: tuple[str, str] | None,
│   │       proxy: str,
│   │       timeout: float,
│   │       follow_redirects: bool,
│   │       verify: bool,
│   │       http2: bool,
│   │       download: typing.BinaryIO | None,
│   │       verbose: bool,
│   │   ) -> None
│   ├── print_help() -> None
│   ├── print_request_headers(
│   │       request: httpcore.Request,
│   │       http2: bool = ...,
│   │   ) -> None
│   ├── print_response(response: Response) -> None
│   ├── print_response_headers(
│   │       http_version: bytes,
│   │       status: int,
│   │       reason_phrase: bytes | None,
│   │       headers: list[tuple[bytes, bytes]],
│   │   ) -> None
│   ├── trace(
│   │       name: str,
│   │       info: typing.Mapping[str, typing.Any],
│   │       verbose: bool = ...,
│   │   ) -> None
│   ├── validate_auth(
│   │       ctx: click.Context,
│   │       param: click.Option | click.Parameter,
│   │       value: typing.Any,
│   │   ) -> typing.Any
│   └── validate_json(
│           ctx: click.Context,
│           param: click.Option | click.Parameter,
│           value: typing.Any,
│       ) -> typing.Any
├── _models
│   ├── Cookies(cookies: CookieTypes | None = ...)
│   ├── Headers(headers: HeaderTypes | None = ..., encoding: str | None = ...)
│   ├── Request(
│   │       method: str,
│   │       url: URL | str,
│   │       *,
│   │       params: QueryParamTypes | None = ...,
│   │       headers: HeaderTypes | None = ...,
│   │       cookies: CookieTypes | None = ...,
│   │       content: RequestContent | None = ...,
│   │       data: RequestData | None = ...,
│   │       files: RequestFiles | None = ...,
│   │       json: typing.Any | None = ...,
│   │       stream: SyncByteStream | AsyncByteStream | None = ...,
│   │       extensions: RequestExtensions | None = ...,
│   │   )
│   └── Response(
│           status_code: int,
│           *,
│           headers: HeaderTypes | None = ...,
│           content: ResponseContent | None = ...,
│           text: str | None = ...,
│           html: str | None = ...,
│           json: typing.Any = ...,
│           stream: SyncByteStream | AsyncByteStream | None = ...,
│           request: Request | None = ...,
│           extensions: ResponseExtensions | None = ...,
│           history: list[Response] | None = ...,
│           default_encoding: str | typing.Callable[[bytes], str] = ...,
│       )
├── _multipart
│   ├── DataField(name: str, value: str | bytes | int | float | None)
│   ├── FileField(name: str, value: FileTypes)
│   ├── MultipartStream(
│   │       data: RequestData,
│   │       files: RequestFiles,
│   │       boundary: bytes | None = ...,
│   │   )
│   └── get_multipart_boundary_from_content_type(
│           content_type: bytes | None,
│       ) -> bytes | None
├── _status_codes
│   └── codes(value: int, phrase: str = ...)
├── _transports
│   ├── asgi
│   │   ├── ASGIResponseStream(body: list[bytes])
│   │   ├── ASGITransport(
│   │   │       app: _ASGIApp,
│   │   │       raise_app_exceptions: bool = ...,
│   │   │       root_path: str = ...,
│   │   │       client: tuple[str, int] = ...,
│   │   │   )
│   │   ├── create_event() -> Event
│   │   └── is_running_trio() -> bool
│   ├── base
│   │   ├── AsyncBaseTransport(...)
│   │   └── BaseTransport(...)
│   ├── default  Custom transports, with nicely configured defaults.
│   │   ├── AsyncHTTPTransport(
│   │   │       verify: ssl.SSLContext | str | bool = ...,
│   │   │       cert: CertTypes | None = ...,
│   │   │       trust_env: bool = ...,
│   │   │       http1: bool = ...,
│   │   │       http2: bool = ...,
│   │   │       limits: Limits = ...,
│   │   │       proxy: ProxyTypes | None = ...,
│   │   │       uds: str | None = ...,
│   │   │       local_address: str | None = ...,
│   │   │       retries: int = ...,
│   │   │       socket_options: typing.Iterable[SOCKET_OPTION] | None = ...,
│   │   │   )
│   │   ├── AsyncResponseStream(httpcore_stream: typing.AsyncIterable[bytes])
│   │   ├── HTTPTransport(
│   │   │       verify: ssl.SSLContext | str | bool = ...,
│   │   │       cert: CertTypes | None = ...,
│   │   │       trust_env: bool = ...,
│   │   │       http1: bool = ...,
│   │   │       http2: bool = ...,
│   │   │       limits: Limits = ...,
│   │   │       proxy: ProxyTypes | None = ...,
│   │   │       uds: str | None = ...,
│   │   │       local_address: str | None = ...,
│   │   │       retries: int = ...,
│   │   │       socket_options: typing.Iterable[SOCKET_OPTION] | None = ...,
│   │   │   )
│   │   ├── ResponseStream(httpcore_stream: typing.Iterable[bytes])
│   │   └── map_httpcore_exceptions() -> typing.Iterator[None]
│   ├── mock
│   │   └── MockTransport(handler: SyncHandler | AsyncHandler)
│   └── wsgi
│       ├── WSGIByteStream(result: typing.Iterable[bytes])
│       └── WSGITransport(
│               app: WSGIApplication,
│               raise_app_exceptions: bool = ...,
│               script_name: str = ...,
│               remote_addr: str = ...,
│               wsgi_errors: typing.TextIO | None = ...,
│           )
├── _types  Type definitions for type checking purposes.
│   ├── AsyncByteStream(...)
│   └── SyncByteStream(...)
├── _urlparse  An implementation of `urlparse` that provides URL validation and
│   normalization
│   ├── PERCENT(string: str) -> str
│   ├── ParseResult(...)
│   ├── encode_host(host: str) -> str
│   ├── normalize_path(path: str) -> str
│   ├── normalize_port(port: str | int | None, scheme: str) -> int | None
│   ├── percent_encoded(string: str, safe: str) -> str
│   ├── quote(string: str, safe: str) -> str
│   ├── urlparse(url: str = ..., **kwargs: str | None) -> ParseResult
│   └── validate_path(path: str, has_scheme: bool, has_authority: bool) -> None
├── _urls
│   ├── QueryParams(*args: QueryParamTypes | None, **kwargs: typing.Any)
│   └── URL(url: URL | str = ..., **kwargs: typing.Any)
└── _utils
    ├── URLPattern(pattern: str)
    ├── get_environment_proxies() -> dict[str, str | None]
    ├── is_ipv4_hostname(hostname: str) -> bool
    ├── is_ipv6_hostname(hostname: str) -> bool
    ├── peek_filelike_length(stream: typing.Any) -> int | None
    ├── primitive_value_to_str(value: PrimitiveData) -> str
    ├── to_bytes(value: str | bytes, encoding: str = ...) -> bytes
    ├── to_bytes_or_str(
    │       value: str,
    │       match_type_of: typing.AnyStr,
    │   ) -> typing.AnyStr
    ├── to_str(value: str | bytes, encoding: str = ...) -> str
    └── unquote(value: str) -> str

Python API: build_tree() performs runtime inspection and returns a Tree dataclass with items, children, docstring, and failed fields. In 0.5, this replaces the dictionary containing the reserved __items__ key. Read tree.items and tree.children[name] when updating callers from 0.4.

Development commands live in justfile. Run uv run just for local checks and README generation. Refresh the pinned showcase dependencies with uv run python scripts/regen_readme.py --update-constraints.

Metadata

Release files for pypatree 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pypatree 0.6.0
File Size Uploaded Provenance Actions
pypatree-0.6.0.tar.gz 98.0 kB Without provenance Details for pypatree-0.6.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pypatree 0.6.0
File Interpreter ABI Platform Actions
pypatree-0.6.0-py3-none-any.whl Python 3 none any Details for pypatree-0.6.0-py3-none-any.whl

Total release size: 118.4 kB

Release files / pypatree-0.6.0.tar.gz

Download URL pypatree-0.6.0.tar.gz
Size 98.0 kB
Tags Source
SHA-256 checksum
How to use checksums
72e90e8f02242d9967ecaceca5c53c4056c923e47852346a2441ba0018a299cf
BLAKE2b-256 checksum
How to use checksums
f4a0cd23cdfb4636707c1b7f654acf1ae100522f5172f26cbab538b59dea149d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / pypatree-0.6.0-py3-none-any.whl

Download URL pypatree-0.6.0-py3-none-any.whl
Size 20.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8669691b0e6ac17ec1d83dabcaba80ea678a4aac5e6aa18fee47a62c403beeda
BLAKE2b-256 checksum
How to use checksums
3e725e0c9e7c4fd2ef63c22c9d5c978312fff3f7ad0038eb407239fa77dc2c66
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for pypatree 0.6.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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page