-
Notifications
You must be signed in to change notification settings - Fork 50
Expand file tree
/
Copy pathutils.py
More file actions
100 lines (71 loc) · 2.82 KB
/
utils.py
File metadata and controls
100 lines (71 loc) · 2.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
"""Utility functions for Mocket."""
from __future__ import annotations
import binascii
import contextlib
from typing import Any, Callable, Protocol, TypeVar, overload
import decorator
from typing_extensions import ParamSpec
from mocket.compat import decode_from_bytes, encode_to_bytes
_P = ParamSpec("_P")
_R = TypeVar("_R")
class MocketizeDecorator(Protocol):
"""Protocol for a flexible decorator that can be used in multiple ways.
This is a generic decorator signature, currently applicable to get_mocketize.
Decorators implementing this protocol can be used as:
1. A function that transforms func (the parameter) into func1 (the returned object).
2. A function that takes keyword arguments and returns a decorator.
"""
@overload
def __call__(self, func: Callable[_P, _R], /) -> Callable[_P, _R]: ...
@overload
def __call__(
self, **kwargs: Any
) -> Callable[[Callable[_P, _R]], Callable[_P, _R]]: ...
def hexdump(binary_string: bytes) -> str:
"""Convert binary data to space-separated hex string.
Args:
binary_string: Binary data to convert
Returns:
Space-separated hexadecimal representation
Example:
>>> hexdump(b"bar foobar foo") == decode_from_bytes(encode_to_bytes("62 61 72 20 66 6F 6F 62 61 72 20 66 6F 6F"))
True
"""
bs = decode_from_bytes(binascii.hexlify(binary_string).upper())
return " ".join(a + b for a, b in zip(bs[::2], bs[1::2]))
def hexload(string: str) -> bytes:
"""Convert space-separated hex string to binary data.
Args:
string: Space-separated hexadecimal string
Returns:
Binary data
Raises:
ValueError: If the hex string is invalid
Example:
>>> hexload("62 61 72 20 66 6F 6F 62 61 72 20 66 6F 6F") == encode_to_bytes("bar foobar foo")
True
"""
string_no_spaces = "".join(string.split())
try:
return encode_to_bytes(binascii.unhexlify(string_no_spaces))
except binascii.Error as e:
raise ValueError from e
def get_mocketize(wrapper_: Callable) -> MocketizeDecorator:
"""Get a mocketize decorator from a wrapper function.
Decorators can be used as:
1. A function that transforms func (the parameter) into func1 (the returned object).
2. A function that takes keyword arguments and returns 1.
Args:
wrapper_: The wrapper function to convert to a decorator
Returns:
A MocketizeDecorator instance that can be used as a flexible decorator
"""
# trying to support different versions of `decorator`
with contextlib.suppress(TypeError):
return decorator.decorator(wrapper_, kwsyntax=True) # type: ignore[return-value, call-arg, unused-ignore]
return decorator.decorator(wrapper_) # type: ignore[return-value]
__all__ = (
"get_mocketize",
"hexdump",
"hexload",
)