API Reference#

Token#

class pypitoken.Token(prefix, macaroon)#

Create a Token (as PyPI itself would do), load an existing Token, create additional restrictions on a Token and dump a Token string from a Token.

This class is an higher level abstraction over the Macaroons from pymacaroons, with specific knowledge of their implementation within PyPI.

prefix#

PyPI tokens are usually prefixed with pypi, but this is arbitrary

Type:

str

domain#

PyPI tokens are attached to a specific domain, usually pypi.org or test.pypi.org

Type:

str

identifier#

This part is how PyPI will find a token in its database and associate it to a specific user. Even when additional restrictions are added to a token, the identifier will still be readable in the token. While this is not exactly a secret part of the token, it’s best to keep it reasonably private.

Type:

str

_macaroon#

This is part of the private API and may be subject to change at any time. This gives you access to the underlying Macaroon, if you need to do low-level operations, or just want to poke around.

Type:

pymacarrons.Macaroon

classmethod load(raw)#

Deserialize a Token from a raw string. Warning: does NOT check for the Token validity, you need to call check for that.

Parameters:

raw (str) – The token string (including the prefix)

Returns:

Loaded token

Return type:

Token

Raises:

pypitoken.LoaderError – Any error in loading the token will be raised as a LoaderError. The original exception (if any) will be attached as the exception cause (raise from).

classmethod create(domain, identifier, key, prefix='pypi', version=2)#

Create a token. Initially, it has no restruction, but they can be added with restrict. In order to create the token, you will need to provide a key. This key is the secret part of the token. When checking a macaroon validity, you will need to provide the same key.

Parameters:
  • domain (str) – PyPI tokens are attached to a specific domain, usually pypi.org or test.pypi.org.

  • identifier (str) – Identifies the Token (and its associated user) in the PyPI database.

  • key (str | bytes) – Secret key used to validate the token. Having the key of a token would allow removing existing restrictions.

  • prefix (str) – PyPI tokens are usually prefixed with pypi which is the default value for this parameter.

  • version (int) – Version of the pymacaroons specification to use. There’s probably no reason we would want to change this.

Returns:

The newly minted token

Return type:

Token

restrict(not_before=None, not_after=None, project_names=None, project_ids=None, user_id=None, legacy_project_names=None, legacy_not_before=None, legacy_not_after=None, legacy_noop=None)#

Modifies the token in-place to add restrictions to it. This can be called by PyPI as well as by anyone, adding restrictions to new or existing tokens.

Multiple restrictions of different types can be added in one call to restrict(). Alternatively, multiple restrictions of the same type can be added via multiple calls to restrict().

Note: a token allows the owner to delegate their rights to the bearer. Consequently, a token adding restrictions linked to a project that the owner cannot use will not make its bearer able to upload releases to the project. As stated in the name, restrictions can reduce the scope of a token, and cannot broaden it. It’s possible to create a token that can do nothing, for example by adding two incompatible restrictions.

Parameters:
  • not_before (Union[int, datetime, None]) – Restrict the token to uploading releases only after the given timestamp or tz-aware datetime. Must be used with not_after. By default, None (no restriction)

  • not_after (Union[int, datetime, None]) – Restrict the token to uploading releases only before the given timestamp or tz-aware datetime. Must be used with not_before. By default, None (no restriction)

  • project_names (Optional[Iterable[str]]) – Restrict the token to uploading releases only for projects with these names, by default None (no restriction)

  • project_ids (Optional[Iterable[str]]) – Restrict the token to uploading releases only for projects with these ids, by default None (no restriction)

  • user_ids – Restrict the token to uploading user attempting to upload Restrict the token to being used only by user with this id, by default None (no restriction)

  • legacy_not_before (Union[int, datetime, None]) – Uses the legacy restriction format (results in longer token size). Restrict the token to uploading releases only after the given timestamp or tz-aware datetime. Must be used with not_after. By default, None (no restriction)

  • legacy_not_after (Union[int, datetime, None]) – Uses the legacy restriction format (results in longer token size). Restrict the token to uploading releases only before the given timestamp or tz-aware datetime. Must be used with not_before. By default, None (no restriction)

  • legacy_project_names (Optional[Iterable[str]]) – Uses the legacy restriction format (results in longer token size). Restrict the token to uploading releases only for projects with these ed name of the project the bearer is attempting to upload toed names, by default None (no restriction)

  • legacy_noop (Optional[bool]) – Uses the legacy restriction format (results in longer token size). user attempting to upload This restriction being there or not doesn’t change the validity of the token.

Raises:

exceptions.Invalidrestrictions.Restriction – If the provided parameters cannot describe a valid description

Returns:

The modified Token, to ease chaining calls.

Return type:

Token

dump()#

Generates a string representing the token. This could be used for API authentication against PyPI.

Returns:

The token

Return type:

str

check(key, project_name=None, project_id=None, user_id=None, now=None)#

Raises pypitoken.ValidationError if the token is invalid.

Parameters besides key are all optional and will be used to provide the current context this token is used for, allowing to accept or reject the caveat restrictions. If a parameter is not passed, but a caveat using it is encountered, the caveat will not be met, the token will be found invalid, and this method will raise with an appropriate exception. There is an exception for now: if not passed, it defaults to the current timestamp.

Parameters:
  • key (str) – Key of the macaroon, stored in PyPI database

  • project_name (Optional[str]) – Normalized name of the project the bearer is attempting to upload to

  • project_id (Optional[str]) – ID of the project the bearer is attempting to upload to

  • user_id (Optional[str]) – ID of the user attempting to upload

  • now (Union[int, datetime, None]) – Timestamp of the moment the upload takes place, or tz-aware datetime. Defaults to the current timestamp.

Raises:

pypitoken.ValidationError – Any error in validating the token will be raised as a ValidationError. The original exception (if any) will be attached as the exception cause (raise     from).

Return type:

None

property restrictions: list[pypitoken.restrictions.Restriction]#

Return a list of restrictions associated to this Token. This can be used to get a better insight on what this Token contains.

Return type:

List[restrictions.Restriction]

Raises:

pypitoken.LoaderError – When the existing restrictions cannot be parsed

Restriction classes#

You may come accross those classes, but while introspection is ok, you should not have to call the methods directly. Use Token.restrict and Token.restrictions instead.

class pypitoken.restrictions.Restriction#

Base Restriction class.

Expose lower-level methods for restriction/caveat introspection.

check(context)#

Receive the context of a check

Parameters:

context (Context) – Describes how the bearer is attempting to use the token.

Raises:
  • ValidationError – Restriction was checked and appeared unmet.

  • MissingContextError – (a subclass of ValidationError): Restriction is unmet because the context is lacking required values. This is more probably a code issue from the Token.check call than an issue with the token itself, though it also means that the token should be rejected.

Return type:

None

dump()#

Transform a restriction into a JSON-compatible dict object

Return type:

dict | list

dump_json()#

Transform a restriction into a JSON-encoded string

Return type:

str

classmethod load(caveat)#

Create a Restriction from a raw caveat restriction JSON object.

Raises:

pypitokens.LoaderError – If the format cannot be understood

Return type:

Restriction

classmethod load_json(caveat)#

Create a Restriction from a raw caveat restriction JSON string.

Raises:

pypitokens.LoaderError – If the format cannot be understood

Return type:

Restriction

class pypitoken.DateRestriction(not_before, not_after)#

Bases: Restriction

Restrict a Token to a single time interval.

not_before#

Token is not to be used before this Unix timestamp.

not_after#

Token is not to be used after this Unix timestamp.

class pypitoken.ProjectNamesRestriction(project_names)#

Bases: Restriction

Restrict a Token to uploading releases for project with specific names.

project_names#

Normalized project names this token may upload to.

class pypitoken.ProjectIDsRestriction(project_ids)#

Bases: Restriction

Restrict a Token to uploading releases for project with specific IDs.

project_ids#

Project IDs this token may upload to.

class pypitoken.UserIDRestriction(user_id)#

Bases: Restriction

Restrict a Token to being used by the user with the corresponding ID.

user_id#

ID of the user that may use this token.

class pypitoken.LegacyNoopRestriction#

Bases: Restriction

Says it restricts the Token, but doesn’t actually restrict it.

class pypitoken.LegacyProjectNamesRestriction(project_names)#

Bases: Restriction

Restrict a Token to uploading releases for a specific set of packages.

projects#

Normalized project names this token may upload to.

class pypitoken.LegacyDateRestriction(not_before, not_after)#

Bases: Restriction

Restrict a Token to a single time interval.

not_before#

Token is not to be used before this Unix timestamp.

not_after#

Token is not to be used after this Unix timestamp.

Exceptions#

class pypitoken.PyPITokenException#

Bases: Exception

The base exception for all exceptions raised from this library. Any code raising a different exception would be considered a bug.

class pypitoken.LoaderError#

Bases: PyPITokenException

Exception encountered while calling Token.load, due to unexpected format.

Exception should be associated with a message in English that can be shown to the bearer to explain the error.

class pypitoken.ValidationError#

Bases: PyPITokenException

Exception encountered while calling Token.check, the token should be considered invalid.

Exception should be associated with a message in English that can be shown to the bearer to explain the error.

class pypitoken.MissingContextError#

Bases: ValidationError

Exception encountered while calling Token.check, the token should be considered invalid.

The restriction couldn’t be checked because the context is missing required values

class pypitoken.InvalidRestriction#

Bases: PyPITokenException, ValueError

Exception encountered while calling Token.restrict, due to unexpected parameters.