Metadata-Version: 2.5
Name: derivepassphrase-sshagentsocketprovider
Version: 1.0
Summary: An interface for SSH agent socket providers, which expose an abstract communication channel for an SSH agent to derivepassphrase.
Project-URL: Documentation, https://the13thletter.info/derivepassphrase/
Project-URL: Issues, https://the13thletter.info/derivepassphrase/latest/wishlist/
Project-URL: Source, https://git.schokokeks.org/derivepassphrase.git
Author-email: Marco Ricci <software@the13thletter.info>
License-Expression: Zlib
License-File: LICENSE.txt
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3.15
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: typing-extensions
Description-Content-Type: text/markdown

# derivepassphrase-sshagentsocketprovider

[![PyPI - Version](https://img.shields.io/pypi/v/derivepassphrase-sshagentsocketprovider.svg)](https://pypi.org/project/derivepassphrase-sshagentsocketprovider)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/derivepassphrase-sshagentsocketprovider.svg)](https://pypi.org/project/derivepassphrase-sshagentsocketprovider)

An interface for SSH agent socket providers, which expose an abstract communication channel for an SSH agent to [`derivepassphrase`][DERIVEPASSPHRASE].

This package contains only the interface definition and the types involved.

[DERIVEPASSPHRASE]: https://the13thletter.info/derivepassphrase/

-----

## Installation

`derivepassphrase-sshagentsocketprovider` is a pure Python package, and may be easily installed with any `pip`-compatible Python package manager such as `pip`, `pipx`, or `uv`.
(`pip` is distributed with Python 3 by default.)

`derivepassphrase-sshagentsocketprovider` requires Python 3.9 or higher, as well as the [typing-extensions package][TYPING_EXTENSIONS].

```console
pip install derivepassphrase-sshagentsocketprovider
```

[TYPING_EXTENSIONS]: https://pypi.org/project/typing-extensions/

## Registering an SSH agent socket provider

The `SSHAgentSocket` represents the abstract communication channel to an SSH agent.
Ensure that the abstract channel behaves like a socket with respect to the `sendall` and `recv` operations.
The abstract channel must also be a context manager, which closes itself upon leaving the context, causing further `sendall` and `recv` operations to raise an error.
(By convention, this is `OSError`, with `errno.EBADF`.)

The `SSHAgentSocketProvider` is a callable that returns an `SSHAgentSocket` when called without arguments.

To then actually register an SSH agent socket provider, build an `SSHAgentSocketProviderEntry` struct.
For example:

~~~ python
# The class is an SSHAgentSocket and has an empty constructor, so the
# constructor is a valid SSHAgentSocketProvider.
class SSHAgentOverStdinStdoutSocket:
    """Forwarding STDIN/STDOUT, as if connected to an SSH agent."""

    FLAGS_ARE_UNSUPPORTED = "flags argument is unsupported"
    """Common error message."""

    def __enter__(self) -> Self:
        """Return self."""
        return self

    def __exit__(self, *args: object) -> bool | None:
        """Close stdin/stdout."""
        sys.stdin.close()
        sys.stdout.close()
        return None

    def send(self, data: Buffer, flags: int = 0, /) -> None:
        """Send data to agent."""
        if flags:
            raise ValueError(self.FLAGS_ARE_UNSUPPORTED)
        sys.stdout.buffer.write(data)

    def recv(self, bufsize: int, flags: int = 0, /) -> bytes:
        """Receive data from agent."""
        if flags:
            raise ValueError(self.FLAGS_ARE_UNSUPPORTED)
        return sys.stdin.buffer.read(bufsize)


ENTRY_POINT = SSHAgentSocketProviderEntry(
    provider=SSHAgentOverStdinStdoutSocket,
    key="stdin_stdout",
    aliases=("stdin", "stdout"),
)
~~~

Then add an appropriate entry point definition in your `pyproject.toml`, using the entry point group name `derivepassphrase.ssh_agent_socket_providers`:

~~~ toml
[project.entry."derivepassphrase.ssh_agent_socket_providers"]
first_provider = "mymodule: ENTRY_POINT"
~~~

`derivepassphrase` will then pick up `stdin_stdout` as a new SSH agent socket provider, with aliases `stdin` and `stdout`.[^entry_point_name]

  [^entry_point_name]:
    Only the fields in the `SSHAgentSocketProviderEntry` matter, not what names are used to declare the entry point.
    By convention, however, you would choose `stdin_stdout` as the entry point name, not `first_provider`.

(See the tests and the test data for two further examples.)

## License

Like `derivepassphrase`, `derivepassphrase-sshagentsocketprovider` is distributed under the terms of the [zlib/libpng license](https://spdx.org/licenses/Zlib.html).
