Utilities for Extension Authors

outgoing.lookup_netrc(host: str, username: Optional[str] = None, path: Optional[Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]] = None) Tuple[str, str][source]

Look up the entry for host in the netrc file at path (default: ~/.netrc) and return a pair of the username & password. If username is specified and it does not equal the username in the file, a NetrcLookupError is raised.

Raises
  • NetrcLookupError – if no entry for host or the default entry is present in the netrc file; or if username differs from the username in the netrc file

  • netrc.NetrcParseError – if the netrc module encounters an error

outgoing.resolve_password(password: Union[str, Mapping[str, Any]], host: Optional[str] = None, username: Optional[str] = None, configpath: Optional[Union[str, pathlib.Path]] = None) str[source]

Resolve a configuration password value. If password is a string, it is returned unchanged. Otherwise, it must be a mapping with exactly one element; the key is used as the name of the password scheme, and the value is passed to the corresponding function for retrieving the password.

When resolving a password field in an outgoing configuration structure, the configpath and any host/service or username values from the configuration (or host/service/username constants specific to the sending method) should be passed into this function so that they can be made available to any password scheme functions that need them.

Raises

InvalidPasswordError – if password is invalid or cannot be resolved

outgoing.resolve_path(path: Union[str, bytes, os.PathLike[str], os.PathLike[bytes]], basepath: Optional[Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]] = None) pathlib.Path[source]

Convert a path to a pathlib.Path instance and resolve it using the same rules for as paths in outgoing configuration files: expand tildes by calling Path.expanduser(), prepend the parent directory of basepath (usually the value of configpath) to the path if given, and then resolve the resulting path to make it absolute.

Parameters
  • path (path) – the path to resolve

  • basepath (path) – an optional path to resolve path relative to

Return type

pathlib.Path

class outgoing.OpenClosable[source]

Bases: abc.ABC, pydantic.main.BaseModel

An abstract base class for creating reentrant context managers. A concrete subclass must define open() and close() methods; OpenClosable will then define __enter__ and __exit__ methods that keep track of the depth of nested with statements, calling open() and close() only when entering & exiting the outermost with.

abstract close() None[source]
abstract open() None[source]

Pydantic Types & Models

The senders built into outgoing make heavy use of pydantic for validating & processing configuration, and some of the custom types & models used are also of general interest to anyone writing an outgoing extension that also uses pydantic.

class outgoing.Path[source]

Converts its input to pathlib.Path instances, including expanding tildes. If there is a field named configpath declared before the Path field and its value is non-None, then the value of the Path field will be resolved relative to the parent directory of the configpath field; otherwise, it will be resolved relative to the current directory.

class outgoing.FilePath[source]

Like Path, but the path must exist and be a file

class outgoing.DirectoryPath[source]

Like Path, but the path must exist and be a directory

class outgoing.Password[source]

A subclass of pydantic.SecretStr that accepts outgoing password specifiers as input and automatically resolves them using resolve_password(). Host, username, and configpath values are passed to resolve_password() as follows:

  • If Password is subclassed and given a host class variable naming a field, and if the subclass is then used in a model where a field with that name is declared before the Password subclass field, then when the model is instantiated, the value of the named field will be passed as the host argument to resolve_password(). (If the named field is not present on the model that uses the subclass, the Password field will fail validation.)

  • Alternatively, Password can be subclassed with host set to a class callable (a classmethod or staticmethod), and when that subclass is used in a model being instantiated, the callable will be passed a dict of all validated fields declared before the password field; the return value from the callable will then be passed as the host argument to resolve_password(). (If the callable raises an exception, the Password field will fail validation.)

  • If Password is used in a model without being subclassed, or if host is not defined in a subclass, then None will be passed as the host argument to resolve_password().

  • The username argument to resolve_password() can likewise be defined by subclassing Password and defining username appropriately.

  • If there is a field named configpath declared before the Password field, then the value of configpath is passed to resolve_password().

For example, if writing a pydantic model for a sender configuration where the host-analogue value is passed in a field named "service" and for which the username is always "__token__", you would subclass Password like this:

class MyPassword(outgoing.Password):
    host = "service"

    @staticmethod
    def username(values: Dict[str, Any]) -> str:
        return "__token__"

and then use it in your model like so:

class MySender(pydantic.BaseModel):
    configpath: Optional[outgoing.Path]
    service: str
    password: MyPassword  # Must come after `configpath` and `service`!
    # ... other fields ...

Then, when MySender is instantiated, the input to the password field would be automatically resolved by doing (effectively):

my_sender.password = pydantic.SecretStr(
    resolve_password(
        my_sender.password,
        host=my_sender.service,
        username="__token__",
        configpath=my_sender.configpath,
    )
)

Note

As this is a subclass of pydantic.SecretStr, the value of a Password field is retrieved by calling its get_secret_value() method.

class outgoing.StandardPassword[source]

A subclass of Password in which host is set to "host" and username is set to "username"

class outgoing.NetrcConfig[source]

A pydantic model usable as a base class for any senders that wish to support both password fields and netrc files. The model accepts the fields configpath, netrc (a boolean or a file path; defaults to False), host (required), username (optional), and password (optional). When the model is instantiated, if password is None but netrc is true or a filepath, the entry for host is looked up in ~/.netrc or the given file, and the username and password fields are set to the values found.

The model will raise a validation error if any of the following are true:

  • password is set but netrc is true

  • password is set but username is not set

  • username is set but password is not set and netrc is false

  • netrc is true or a filepath, username is non-None, and the username in the netrc file differs from username

  • netrc is true or a filepath and no entry can be found in the netrc file

configpath: Optional[outgoing.config.Path]
host: str
netrc: Union[pydantic.types.StrictBool, outgoing.config.FilePath]
password: Optional[outgoing.config.StandardPassword]
username: Optional[str]