Skip to content

Commit

Permalink
Type annotations for nacl.utils (#697)
Browse files Browse the repository at this point in the history
* Type annotations for `nacl.utils`

This applies the changes proposed in #692 to `nacl.utils` on top of the
changes in more recent PRs.

I've annotated `nacl.bindings.randombytes_buf_deterministic` to appease
mypy. It's needed because I configured mypy to require that typed code
always calls typed functions, in #694.

Per #692 (comment) and
https://stackoverflow.com/a/44644576/5252017 , I've made sure that the
`_from_parts` accepts a generic `cls` argument and returns an instance
of that `cls`. I don't think we actually intend for people to subclass
`EncryptedMessage`, but maybe they do. Besides, it's nice to have
annotations that are as accurate as possible.

* Use `_EncryptedMessage` in place of `C`

* Run black to appease linter
  • Loading branch information
DMRobertson committed Nov 11, 2021
1 parent c2ddf9f commit 54a5ee2
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 11 deletions.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ ignore_missing_imports = true
module = [
"nacl.encoding",
"nacl.exceptions",
"nacl.utils",
]
disallow_any_unimported = true
disallow_any_expr = true
Expand Down
2 changes: 1 addition & 1 deletion src/nacl/bindings/randombytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def randombytes(size):
return ffi.buffer(buf, size)[:]


def randombytes_buf_deterministic(size, seed):
def randombytes_buf_deterministic(size: int, seed: bytes) -> bytes:
"""
Returns ``size`` number of deterministically generated pseudorandom bytes
from a seed
Expand Down
29 changes: 19 additions & 10 deletions src/nacl/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,57 +14,66 @@


import os
from typing import SupportsBytes
from typing import SupportsBytes, Type, TypeVar

import nacl.bindings
from nacl import encoding

_EncryptedMessage = TypeVar("_EncryptedMessage", bound="EncryptedMessage")


class EncryptedMessage(bytes):
"""
A bytes subclass that holds a messaged that has been encrypted by a
:class:`SecretBox`.
"""

_nonce = object
_ciphertext = object
_nonce: bytes
_ciphertext: bytes

@classmethod
def _from_parts(cls, nonce, ciphertext, combined):
def _from_parts(
cls: Type[_EncryptedMessage],
nonce: bytes,
ciphertext: bytes,
combined: bytes,
) -> _EncryptedMessage:
obj = cls(combined)
obj._nonce = nonce
obj._ciphertext = ciphertext
return obj

@property
def nonce(self):
def nonce(self) -> bytes:
"""
The nonce used during the encryption of the :class:`EncryptedMessage`.
"""
return self._nonce

@property
def ciphertext(self):
def ciphertext(self) -> bytes:
"""
The ciphertext contained within the :class:`EncryptedMessage`.
"""
return self._ciphertext


class StringFixer:
def __str__(self: SupportsBytes):
def __str__(self: SupportsBytes) -> str:
return str(self.__bytes__())


def bytes_as_string(bytes_in):
def bytes_as_string(bytes_in: bytes) -> str:
return bytes_in.decode("ascii")


def random(size=32):
def random(size: int = 32) -> bytes:
return os.urandom(size)


def randombytes_deterministic(size, seed, encoder=encoding.RawEncoder):
def randombytes_deterministic(
size: int, seed: bytes, encoder: encoding.Encoder = encoding.RawEncoder
) -> bytes:
"""
Returns ``size`` number of deterministically generated pseudorandom bytes
from a seed
Expand Down

0 comments on commit 54a5ee2

Please sign in to comment.