diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c61a802 Binary files /dev/null and b/.gitignore differ diff --git a/notification-service/__pycache__/main.cpython-312.pyc b/notification-service/__pycache__/main.cpython-312.pyc deleted file mode 100644 index 0f09a23..0000000 Binary files a/notification-service/__pycache__/main.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/81d243bd2c585b0f4821__mypyc.cp312-win_amd64.pyd b/notification-service/venv/Lib/site-packages/81d243bd2c585b0f4821__mypyc.cp312-win_amd64.pyd deleted file mode 100644 index 3ae76c8..0000000 Binary files a/notification-service/venv/Lib/site-packages/81d243bd2c585b0f4821__mypyc.cp312-win_amd64.pyd and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/__pycache__/typing_extensions.cpython-312.pyc b/notification-service/venv/Lib/site-packages/__pycache__/typing_extensions.cpython-312.pyc deleted file mode 100644 index af817d6..0000000 Binary files a/notification-service/venv/Lib/site-packages/__pycache__/typing_extensions.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/_cffi_backend.cp312-win_amd64.pyd b/notification-service/venv/Lib/site-packages/_cffi_backend.cp312-win_amd64.pyd deleted file mode 100644 index c83b3bd..0000000 Binary files a/notification-service/venv/Lib/site-packages/_cffi_backend.cp312-win_amd64.pyd and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/INSTALLER b/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/METADATA b/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/METADATA deleted file mode 100644 index 9bf7a9e..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/METADATA +++ /dev/null @@ -1,145 +0,0 @@ -Metadata-Version: 2.4 -Name: annotated-doc -Version: 0.0.4 -Summary: Document parameters, class attributes, return types, and variables inline, with Annotated. -Author-Email: =?utf-8?q?Sebasti=C3=A1n_Ram=C3=ADrez?= -License-Expression: MIT -License-File: LICENSE -Classifier: Intended Audience :: Information Technology -Classifier: Intended Audience :: System Administrators -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python -Classifier: Topic :: Internet -Classifier: Topic :: Software Development :: Libraries :: Application Frameworks -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Software Development :: Libraries -Classifier: Topic :: Software Development -Classifier: Typing :: Typed -Classifier: Development Status :: 4 - Beta -Classifier: Intended Audience :: Developers -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.8 -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 -Project-URL: Homepage, https://github.com/fastapi/annotated-doc -Project-URL: Documentation, https://github.com/fastapi/annotated-doc -Project-URL: Repository, https://github.com/fastapi/annotated-doc -Project-URL: Issues, https://github.com/fastapi/annotated-doc/issues -Project-URL: Changelog, https://github.com/fastapi/annotated-doc/release-notes.md -Requires-Python: >=3.8 -Description-Content-Type: text/markdown - -# Annotated Doc - -Document parameters, class attributes, return types, and variables inline, with `Annotated`. - - - Test - - - Coverage - - - Package version - - - Supported Python versions - - -## Installation - -```bash -pip install annotated-doc -``` - -Or with `uv`: - -```Python -uv add annotated-doc -``` - -## Usage - -Import `Doc` and pass a single literal string with the documentation for the specific parameter, class attribute, return type, or variable. - -For example, to document a parameter `name` in a function `hi` you could do: - -```Python -from typing import Annotated - -from annotated_doc import Doc - -def hi(name: Annotated[str, Doc("Who to say hi to")]) -> None: - print(f"Hi, {name}!") -``` - -You can also use it to document class attributes: - -```Python -from typing import Annotated - -from annotated_doc import Doc - -class User: - name: Annotated[str, Doc("The user's name")] - age: Annotated[int, Doc("The user's age")] -``` - -The same way, you could document return types and variables, or anything that could have a type annotation with `Annotated`. - -## Who Uses This - -`annotated-doc` was made for: - -* [FastAPI](https://fastapi.tiangolo.com/) -* [Typer](https://typer.tiangolo.com/) -* [SQLModel](https://sqlmodel.tiangolo.com/) -* [Asyncer](https://asyncer.tiangolo.com/) - -`annotated-doc` is supported by [griffe-typingdoc](https://github.com/mkdocstrings/griffe-typingdoc), which powers reference documentation like the one in the [FastAPI Reference](https://fastapi.tiangolo.com/reference/). - -## Reasons not to use `annotated-doc` - -You are already comfortable with one of the existing docstring formats, like: - -* Sphinx -* numpydoc -* Google -* Keras - -Your team is already comfortable using them. - -You prefer having the documentation about parameters all together in a docstring, separated from the code defining them. - -You care about a specific set of users, using one specific editor, and that editor already has support for the specific docstring format you use. - -## Reasons to use `annotated-doc` - -* No micro-syntax to learn for newcomers, it’s **just Python** syntax. -* **Editing** would be already fully supported by default by any editor (current or future) supporting Python syntax, including syntax errors, syntax highlighting, etc. -* **Rendering** would be relatively straightforward to implement by static tools (tools that don't need runtime execution), as the information can be extracted from the AST they normally already create. -* **Deduplication of information**: the name of a parameter would be defined in a single place, not duplicated inside of a docstring. -* **Elimination** of the possibility of having **inconsistencies** when removing a parameter or class variable and **forgetting to remove** its documentation. -* **Minimization** of the probability of adding a new parameter or class variable and **forgetting to add its documentation**. -* **Elimination** of the possibility of having **inconsistencies** between the **name** of a parameter in the **signature** and the name in the docstring when it is renamed. -* **Access** to the documentation string for each symbol at **runtime**, including existing (older) Python versions. -* A more formalized way to document other symbols, like type aliases, that could use Annotated. -* **Support** for apps using FastAPI, Typer and others. -* **AI Accessibility**: AI tools will have an easier way understanding each parameter as the distance from documentation to parameter is much closer. - -## History - -I ([@tiangolo](https://github.com/tiangolo)) originally wanted for this to be part of the Python standard library (in [PEP 727](https://peps.python.org/pep-0727/)), but the proposal was withdrawn as there was a fair amount of negative feedback and opposition. - -The conclusion was that this was better done as an external effort, in a third-party library. - -So, here it is, with a simpler approach, as a third-party library, in a way that can be used by others, starting with FastAPI and friends. - -## License - -This project is licensed under the terms of the MIT license. diff --git a/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/RECORD b/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/RECORD deleted file mode 100644 index 06bbc8d..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/RECORD +++ /dev/null @@ -1,11 +0,0 @@ -annotated_doc-0.0.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -annotated_doc-0.0.4.dist-info/METADATA,sha256=Irm5KJua33dY2qKKAjJ-OhKaVBVIfwFGej_dSe3Z1TU,6566 -annotated_doc-0.0.4.dist-info/RECORD,, -annotated_doc-0.0.4.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90 -annotated_doc-0.0.4.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34 -annotated_doc-0.0.4.dist-info/licenses/LICENSE,sha256=__Fwd5pqy_ZavbQFwIfxzuF4ZpHkqWpANFF-SlBKDN8,1086 -annotated_doc/__init__.py,sha256=VuyxxUe80kfEyWnOrCx_Bk8hybo3aKo6RYBlkBBYW8k,52 -annotated_doc/__pycache__/__init__.cpython-312.pyc,, -annotated_doc/__pycache__/main.cpython-312.pyc,, -annotated_doc/main.py,sha256=5Zfvxv80SwwLqpRW73AZyZyiM4bWma9QWRbp_cgD20s,1075 -annotated_doc/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/WHEEL b/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/WHEEL deleted file mode 100644 index 045c8ac..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: pdm-backend (2.4.5) -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/entry_points.txt b/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/entry_points.txt deleted file mode 100644 index c3ad472..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/entry_points.txt +++ /dev/null @@ -1,4 +0,0 @@ -[console_scripts] - -[gui_scripts] - diff --git a/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/licenses/LICENSE b/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/licenses/LICENSE deleted file mode 100644 index 7a25446..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_doc-0.0.4.dist-info/licenses/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2025 Sebastián Ramírez - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/notification-service/venv/Lib/site-packages/annotated_doc/__init__.py b/notification-service/venv/Lib/site-packages/annotated_doc/__init__.py deleted file mode 100644 index a0152a7..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_doc/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .main import Doc as Doc - -__version__ = "0.0.4" diff --git a/notification-service/venv/Lib/site-packages/annotated_doc/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/annotated_doc/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 8e93d45..0000000 Binary files a/notification-service/venv/Lib/site-packages/annotated_doc/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/annotated_doc/__pycache__/main.cpython-312.pyc b/notification-service/venv/Lib/site-packages/annotated_doc/__pycache__/main.cpython-312.pyc deleted file mode 100644 index 938d2ed..0000000 Binary files a/notification-service/venv/Lib/site-packages/annotated_doc/__pycache__/main.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/annotated_doc/main.py b/notification-service/venv/Lib/site-packages/annotated_doc/main.py deleted file mode 100644 index 7063c59..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_doc/main.py +++ /dev/null @@ -1,36 +0,0 @@ -class Doc: - """Define the documentation of a type annotation using `Annotated`, to be - used in class attributes, function and method parameters, return values, - and variables. - - The value should be a positional-only string literal to allow static tools - like editors and documentation generators to use it. - - This complements docstrings. - - The string value passed is available in the attribute `documentation`. - - Example: - - ```Python - from typing import Annotated - from annotated_doc import Doc - - def hi(name: Annotated[str, Doc("Who to say hi to")]) -> None: - print(f"Hi, {name}!") - ``` - """ - - def __init__(self, documentation: str, /) -> None: - self.documentation = documentation - - def __repr__(self) -> str: - return f"Doc({self.documentation!r})" - - def __hash__(self) -> int: - return hash(self.documentation) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, Doc): - return NotImplemented - return self.documentation == other.documentation diff --git a/notification-service/venv/Lib/site-packages/annotated_doc/py.typed b/notification-service/venv/Lib/site-packages/annotated_doc/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/INSTALLER b/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/METADATA b/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/METADATA deleted file mode 100644 index 3ac05cf..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/METADATA +++ /dev/null @@ -1,295 +0,0 @@ -Metadata-Version: 2.3 -Name: annotated-types -Version: 0.7.0 -Summary: Reusable constraint types to use with typing.Annotated -Project-URL: Homepage, https://github.com/annotated-types/annotated-types -Project-URL: Source, https://github.com/annotated-types/annotated-types -Project-URL: Changelog, https://github.com/annotated-types/annotated-types/releases -Author-email: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com>, Samuel Colvin , Zac Hatfield-Dodds -License-File: LICENSE -Classifier: Development Status :: 4 - Beta -Classifier: Environment :: Console -Classifier: Environment :: MacOS X -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: Information Technology -Classifier: License :: OSI Approved :: MIT License -Classifier: Operating System :: POSIX :: Linux -Classifier: Operating System :: Unix -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.8 -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: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Typing :: Typed -Requires-Python: >=3.8 -Requires-Dist: typing-extensions>=4.0.0; python_version < '3.9' -Description-Content-Type: text/markdown - -# annotated-types - -[![CI](https://github.com/annotated-types/annotated-types/workflows/CI/badge.svg?event=push)](https://github.com/annotated-types/annotated-types/actions?query=event%3Apush+branch%3Amain+workflow%3ACI) -[![pypi](https://img.shields.io/pypi/v/annotated-types.svg)](https://pypi.python.org/pypi/annotated-types) -[![versions](https://img.shields.io/pypi/pyversions/annotated-types.svg)](https://github.com/annotated-types/annotated-types) -[![license](https://img.shields.io/github/license/annotated-types/annotated-types.svg)](https://github.com/annotated-types/annotated-types/blob/main/LICENSE) - -[PEP-593](https://peps.python.org/pep-0593/) added `typing.Annotated` as a way of -adding context-specific metadata to existing types, and specifies that -`Annotated[T, x]` _should_ be treated as `T` by any tool or library without special -logic for `x`. - -This package provides metadata objects which can be used to represent common -constraints such as upper and lower bounds on scalar values and collection sizes, -a `Predicate` marker for runtime checks, and -descriptions of how we intend these metadata to be interpreted. In some cases, -we also note alternative representations which do not require this package. - -## Install - -```bash -pip install annotated-types -``` - -## Examples - -```python -from typing import Annotated -from annotated_types import Gt, Len, Predicate - -class MyClass: - age: Annotated[int, Gt(18)] # Valid: 19, 20, ... - # Invalid: 17, 18, "19", 19.0, ... - factors: list[Annotated[int, Predicate(is_prime)]] # Valid: 2, 3, 5, 7, 11, ... - # Invalid: 4, 8, -2, 5.0, "prime", ... - - my_list: Annotated[list[int], Len(0, 10)] # Valid: [], [10, 20, 30, 40, 50] - # Invalid: (1, 2), ["abc"], [0] * 20 -``` - -## Documentation - -_While `annotated-types` avoids runtime checks for performance, users should not -construct invalid combinations such as `MultipleOf("non-numeric")` or `Annotated[int, Len(3)]`. -Downstream implementors may choose to raise an error, emit a warning, silently ignore -a metadata item, etc., if the metadata objects described below are used with an -incompatible type - or for any other reason!_ - -### Gt, Ge, Lt, Le - -Express inclusive and/or exclusive bounds on orderable values - which may be numbers, -dates, times, strings, sets, etc. Note that the boundary value need not be of the -same type that was annotated, so long as they can be compared: `Annotated[int, Gt(1.5)]` -is fine, for example, and implies that the value is an integer x such that `x > 1.5`. - -We suggest that implementors may also interpret `functools.partial(operator.le, 1.5)` -as being equivalent to `Gt(1.5)`, for users who wish to avoid a runtime dependency on -the `annotated-types` package. - -To be explicit, these types have the following meanings: - -* `Gt(x)` - value must be "Greater Than" `x` - equivalent to exclusive minimum -* `Ge(x)` - value must be "Greater than or Equal" to `x` - equivalent to inclusive minimum -* `Lt(x)` - value must be "Less Than" `x` - equivalent to exclusive maximum -* `Le(x)` - value must be "Less than or Equal" to `x` - equivalent to inclusive maximum - -### Interval - -`Interval(gt, ge, lt, le)` allows you to specify an upper and lower bound with a single -metadata object. `None` attributes should be ignored, and non-`None` attributes -treated as per the single bounds above. - -### MultipleOf - -`MultipleOf(multiple_of=x)` might be interpreted in two ways: - -1. Python semantics, implying `value % multiple_of == 0`, or -2. [JSONschema semantics](https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.6.2.1), - where `int(value / multiple_of) == value / multiple_of`. - -We encourage users to be aware of these two common interpretations and their -distinct behaviours, especially since very large or non-integer numbers make -it easy to cause silent data corruption due to floating-point imprecision. - -We encourage libraries to carefully document which interpretation they implement. - -### MinLen, MaxLen, Len - -`Len()` implies that `min_length <= len(value) <= max_length` - lower and upper bounds are inclusive. - -As well as `Len()` which can optionally include upper and lower bounds, we also -provide `MinLen(x)` and `MaxLen(y)` which are equivalent to `Len(min_length=x)` -and `Len(max_length=y)` respectively. - -`Len`, `MinLen`, and `MaxLen` may be used with any type which supports `len(value)`. - -Examples of usage: - -* `Annotated[list, MaxLen(10)]` (or `Annotated[list, Len(max_length=10))`) - list must have a length of 10 or less -* `Annotated[str, MaxLen(10)]` - string must have a length of 10 or less -* `Annotated[list, MinLen(3))` (or `Annotated[list, Len(min_length=3))`) - list must have a length of 3 or more -* `Annotated[list, Len(4, 6)]` - list must have a length of 4, 5, or 6 -* `Annotated[list, Len(8, 8)]` - list must have a length of exactly 8 - -#### Changed in v0.4.0 - -* `min_inclusive` has been renamed to `min_length`, no change in meaning -* `max_exclusive` has been renamed to `max_length`, upper bound is now **inclusive** instead of **exclusive** -* The recommendation that slices are interpreted as `Len` has been removed due to ambiguity and different semantic - meaning of the upper bound in slices vs. `Len` - -See [issue #23](https://github.com/annotated-types/annotated-types/issues/23) for discussion. - -### Timezone - -`Timezone` can be used with a `datetime` or a `time` to express which timezones -are allowed. `Annotated[datetime, Timezone(None)]` must be a naive datetime. -`Timezone[...]` ([literal ellipsis](https://docs.python.org/3/library/constants.html#Ellipsis)) -expresses that any timezone-aware datetime is allowed. You may also pass a specific -timezone string or [`tzinfo`](https://docs.python.org/3/library/datetime.html#tzinfo-objects) -object such as `Timezone(timezone.utc)` or `Timezone("Africa/Abidjan")` to express that you only -allow a specific timezone, though we note that this is often a symptom of fragile design. - -#### Changed in v0.x.x - -* `Timezone` accepts [`tzinfo`](https://docs.python.org/3/library/datetime.html#tzinfo-objects) objects instead of - `timezone`, extending compatibility to [`zoneinfo`](https://docs.python.org/3/library/zoneinfo.html) and third party libraries. - -### Unit - -`Unit(unit: str)` expresses that the annotated numeric value is the magnitude of -a quantity with the specified unit. For example, `Annotated[float, Unit("m/s")]` -would be a float representing a velocity in meters per second. - -Please note that `annotated_types` itself makes no attempt to parse or validate -the unit string in any way. That is left entirely to downstream libraries, -such as [`pint`](https://pint.readthedocs.io) or -[`astropy.units`](https://docs.astropy.org/en/stable/units/). - -An example of how a library might use this metadata: - -```python -from annotated_types import Unit -from typing import Annotated, TypeVar, Callable, Any, get_origin, get_args - -# given a type annotated with a unit: -Meters = Annotated[float, Unit("m")] - - -# you can cast the annotation to a specific unit type with any -# callable that accepts a string and returns the desired type -T = TypeVar("T") -def cast_unit(tp: Any, unit_cls: Callable[[str], T]) -> T | None: - if get_origin(tp) is Annotated: - for arg in get_args(tp): - if isinstance(arg, Unit): - return unit_cls(arg.unit) - return None - - -# using `pint` -import pint -pint_unit = cast_unit(Meters, pint.Unit) - - -# using `astropy.units` -import astropy.units as u -astropy_unit = cast_unit(Meters, u.Unit) -``` - -### Predicate - -`Predicate(func: Callable)` expresses that `func(value)` is truthy for valid values. -Users should prefer the statically inspectable metadata above, but if you need -the full power and flexibility of arbitrary runtime predicates... here it is. - -For some common constraints, we provide generic types: - -* `IsLower = Annotated[T, Predicate(str.islower)]` -* `IsUpper = Annotated[T, Predicate(str.isupper)]` -* `IsDigit = Annotated[T, Predicate(str.isdigit)]` -* `IsFinite = Annotated[T, Predicate(math.isfinite)]` -* `IsNotFinite = Annotated[T, Predicate(Not(math.isfinite))]` -* `IsNan = Annotated[T, Predicate(math.isnan)]` -* `IsNotNan = Annotated[T, Predicate(Not(math.isnan))]` -* `IsInfinite = Annotated[T, Predicate(math.isinf)]` -* `IsNotInfinite = Annotated[T, Predicate(Not(math.isinf))]` - -so that you can write e.g. `x: IsFinite[float] = 2.0` instead of the longer -(but exactly equivalent) `x: Annotated[float, Predicate(math.isfinite)] = 2.0`. - -Some libraries might have special logic to handle known or understandable predicates, -for example by checking for `str.isdigit` and using its presence to both call custom -logic to enforce digit-only strings, and customise some generated external schema. -Users are therefore encouraged to avoid indirection like `lambda s: s.lower()`, in -favor of introspectable methods such as `str.lower` or `re.compile("pattern").search`. - -To enable basic negation of commonly used predicates like `math.isnan` without introducing introspection that makes it impossible for implementers to introspect the predicate we provide a `Not` wrapper that simply negates the predicate in an introspectable manner. Several of the predicates listed above are created in this manner. - -We do not specify what behaviour should be expected for predicates that raise -an exception. For example `Annotated[int, Predicate(str.isdigit)]` might silently -skip invalid constraints, or statically raise an error; or it might try calling it -and then propagate or discard the resulting -`TypeError: descriptor 'isdigit' for 'str' objects doesn't apply to a 'int' object` -exception. We encourage libraries to document the behaviour they choose. - -### Doc - -`doc()` can be used to add documentation information in `Annotated`, for function and method parameters, variables, class attributes, return types, and any place where `Annotated` can be used. - -It expects a value that can be statically analyzed, as the main use case is for static analysis, editors, documentation generators, and similar tools. - -It returns a `DocInfo` class with a single attribute `documentation` containing the value passed to `doc()`. - -This is the early adopter's alternative form of the [`typing-doc` proposal](https://github.com/tiangolo/fastapi/blob/typing-doc/typing_doc.md). - -### Integrating downstream types with `GroupedMetadata` - -Implementers may choose to provide a convenience wrapper that groups multiple pieces of metadata. -This can help reduce verbosity and cognitive overhead for users. -For example, an implementer like Pydantic might provide a `Field` or `Meta` type that accepts keyword arguments and transforms these into low-level metadata: - -```python -from dataclasses import dataclass -from typing import Iterator -from annotated_types import GroupedMetadata, Ge - -@dataclass -class Field(GroupedMetadata): - ge: int | None = None - description: str | None = None - - def __iter__(self) -> Iterator[object]: - # Iterating over a GroupedMetadata object should yield annotated-types - # constraint metadata objects which describe it as fully as possible, - # and may include other unknown objects too. - if self.ge is not None: - yield Ge(self.ge) - if self.description is not None: - yield Description(self.description) -``` - -Libraries consuming annotated-types constraints should check for `GroupedMetadata` and unpack it by iterating over the object and treating the results as if they had been "unpacked" in the `Annotated` type. The same logic should be applied to the [PEP 646 `Unpack` type](https://peps.python.org/pep-0646/), so that `Annotated[T, Field(...)]`, `Annotated[T, Unpack[Field(...)]]` and `Annotated[T, *Field(...)]` are all treated consistently. - -Libraries consuming annotated-types should also ignore any metadata they do not recongize that came from unpacking a `GroupedMetadata`, just like they ignore unrecognized metadata in `Annotated` itself. - -Our own `annotated_types.Interval` class is a `GroupedMetadata` which unpacks itself into `Gt`, `Lt`, etc., so this is not an abstract concern. Similarly, `annotated_types.Len` is a `GroupedMetadata` which unpacks itself into `MinLen` (optionally) and `MaxLen`. - -### Consuming metadata - -We intend to not be prescriptive as to _how_ the metadata and constraints are used, but as an example of how one might parse constraints from types annotations see our [implementation in `test_main.py`](https://github.com/annotated-types/annotated-types/blob/f59cf6d1b5255a0fe359b93896759a180bec30ae/tests/test_main.py#L94-L103). - -It is up to the implementer to determine how this metadata is used. -You could use the metadata for runtime type checking, for generating schemas or to generate example data, amongst other use cases. - -## Design & History - -This package was designed at the PyCon 2022 sprints by the maintainers of Pydantic -and Hypothesis, with the goal of making it as easy as possible for end-users to -provide more informative annotations for use by runtime libraries. - -It is deliberately minimal, and following PEP-593 allows considerable downstream -discretion in what (if anything!) they choose to support. Nonetheless, we expect -that staying simple and covering _only_ the most common use-cases will give users -and maintainers the best experience we can. If you'd like more constraints for your -types - follow our lead, by defining them and documenting them downstream! diff --git a/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/RECORD b/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/RECORD deleted file mode 100644 index 7045729..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/RECORD +++ /dev/null @@ -1,10 +0,0 @@ -annotated_types-0.7.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -annotated_types-0.7.0.dist-info/METADATA,sha256=7ltqxksJJ0wCYFGBNIQCWTlWQGeAH0hRFdnK3CB895E,15046 -annotated_types-0.7.0.dist-info/RECORD,, -annotated_types-0.7.0.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87 -annotated_types-0.7.0.dist-info/licenses/LICENSE,sha256=_hBJiEsaDZNCkB6I4H8ykl0ksxIdmXK2poBfuYJLCV0,1083 -annotated_types/__init__.py,sha256=RynLsRKUEGI0KimXydlD1fZEfEzWwDo0Uon3zOKhG1Q,13819 -annotated_types/__pycache__/__init__.cpython-312.pyc,, -annotated_types/__pycache__/test_cases.cpython-312.pyc,, -annotated_types/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -annotated_types/test_cases.py,sha256=zHFX6EpcMbGJ8FzBYDbO56bPwx_DYIVSKbZM-4B3_lg,6421 diff --git a/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/WHEEL b/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/WHEEL deleted file mode 100644 index 516596c..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: hatchling 1.24.2 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE b/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE deleted file mode 100644 index d99323a..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2022 the contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/notification-service/venv/Lib/site-packages/annotated_types/__init__.py b/notification-service/venv/Lib/site-packages/annotated_types/__init__.py deleted file mode 100644 index 74e0dee..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_types/__init__.py +++ /dev/null @@ -1,432 +0,0 @@ -import math -import sys -import types -from dataclasses import dataclass -from datetime import tzinfo -from typing import TYPE_CHECKING, Any, Callable, Iterator, Optional, SupportsFloat, SupportsIndex, TypeVar, Union - -if sys.version_info < (3, 8): - from typing_extensions import Protocol, runtime_checkable -else: - from typing import Protocol, runtime_checkable - -if sys.version_info < (3, 9): - from typing_extensions import Annotated, Literal -else: - from typing import Annotated, Literal - -if sys.version_info < (3, 10): - EllipsisType = type(Ellipsis) - KW_ONLY = {} - SLOTS = {} -else: - from types import EllipsisType - - KW_ONLY = {"kw_only": True} - SLOTS = {"slots": True} - - -__all__ = ( - 'BaseMetadata', - 'GroupedMetadata', - 'Gt', - 'Ge', - 'Lt', - 'Le', - 'Interval', - 'MultipleOf', - 'MinLen', - 'MaxLen', - 'Len', - 'Timezone', - 'Predicate', - 'LowerCase', - 'UpperCase', - 'IsDigits', - 'IsFinite', - 'IsNotFinite', - 'IsNan', - 'IsNotNan', - 'IsInfinite', - 'IsNotInfinite', - 'doc', - 'DocInfo', - '__version__', -) - -__version__ = '0.7.0' - - -T = TypeVar('T') - - -# arguments that start with __ are considered -# positional only -# see https://peps.python.org/pep-0484/#positional-only-arguments - - -class SupportsGt(Protocol): - def __gt__(self: T, __other: T) -> bool: - ... - - -class SupportsGe(Protocol): - def __ge__(self: T, __other: T) -> bool: - ... - - -class SupportsLt(Protocol): - def __lt__(self: T, __other: T) -> bool: - ... - - -class SupportsLe(Protocol): - def __le__(self: T, __other: T) -> bool: - ... - - -class SupportsMod(Protocol): - def __mod__(self: T, __other: T) -> T: - ... - - -class SupportsDiv(Protocol): - def __div__(self: T, __other: T) -> T: - ... - - -class BaseMetadata: - """Base class for all metadata. - - This exists mainly so that implementers - can do `isinstance(..., BaseMetadata)` while traversing field annotations. - """ - - __slots__ = () - - -@dataclass(frozen=True, **SLOTS) -class Gt(BaseMetadata): - """Gt(gt=x) implies that the value must be greater than x. - - It can be used with any type that supports the ``>`` operator, - including numbers, dates and times, strings, sets, and so on. - """ - - gt: SupportsGt - - -@dataclass(frozen=True, **SLOTS) -class Ge(BaseMetadata): - """Ge(ge=x) implies that the value must be greater than or equal to x. - - It can be used with any type that supports the ``>=`` operator, - including numbers, dates and times, strings, sets, and so on. - """ - - ge: SupportsGe - - -@dataclass(frozen=True, **SLOTS) -class Lt(BaseMetadata): - """Lt(lt=x) implies that the value must be less than x. - - It can be used with any type that supports the ``<`` operator, - including numbers, dates and times, strings, sets, and so on. - """ - - lt: SupportsLt - - -@dataclass(frozen=True, **SLOTS) -class Le(BaseMetadata): - """Le(le=x) implies that the value must be less than or equal to x. - - It can be used with any type that supports the ``<=`` operator, - including numbers, dates and times, strings, sets, and so on. - """ - - le: SupportsLe - - -@runtime_checkable -class GroupedMetadata(Protocol): - """A grouping of multiple objects, like typing.Unpack. - - `GroupedMetadata` on its own is not metadata and has no meaning. - All of the constraints and metadata should be fully expressable - in terms of the `BaseMetadata`'s returned by `GroupedMetadata.__iter__()`. - - Concrete implementations should override `GroupedMetadata.__iter__()` - to add their own metadata. - For example: - - >>> @dataclass - >>> class Field(GroupedMetadata): - >>> gt: float | None = None - >>> description: str | None = None - ... - >>> def __iter__(self) -> Iterable[object]: - >>> if self.gt is not None: - >>> yield Gt(self.gt) - >>> if self.description is not None: - >>> yield Description(self.gt) - - Also see the implementation of `Interval` below for an example. - - Parsers should recognize this and unpack it so that it can be used - both with and without unpacking: - - - `Annotated[int, Field(...)]` (parser must unpack Field) - - `Annotated[int, *Field(...)]` (PEP-646) - """ # noqa: trailing-whitespace - - @property - def __is_annotated_types_grouped_metadata__(self) -> Literal[True]: - return True - - def __iter__(self) -> Iterator[object]: - ... - - if not TYPE_CHECKING: - __slots__ = () # allow subclasses to use slots - - def __init_subclass__(cls, *args: Any, **kwargs: Any) -> None: - # Basic ABC like functionality without the complexity of an ABC - super().__init_subclass__(*args, **kwargs) - if cls.__iter__ is GroupedMetadata.__iter__: - raise TypeError("Can't subclass GroupedMetadata without implementing __iter__") - - def __iter__(self) -> Iterator[object]: # noqa: F811 - raise NotImplementedError # more helpful than "None has no attribute..." type errors - - -@dataclass(frozen=True, **KW_ONLY, **SLOTS) -class Interval(GroupedMetadata): - """Interval can express inclusive or exclusive bounds with a single object. - - It accepts keyword arguments ``gt``, ``ge``, ``lt``, and/or ``le``, which - are interpreted the same way as the single-bound constraints. - """ - - gt: Union[SupportsGt, None] = None - ge: Union[SupportsGe, None] = None - lt: Union[SupportsLt, None] = None - le: Union[SupportsLe, None] = None - - def __iter__(self) -> Iterator[BaseMetadata]: - """Unpack an Interval into zero or more single-bounds.""" - if self.gt is not None: - yield Gt(self.gt) - if self.ge is not None: - yield Ge(self.ge) - if self.lt is not None: - yield Lt(self.lt) - if self.le is not None: - yield Le(self.le) - - -@dataclass(frozen=True, **SLOTS) -class MultipleOf(BaseMetadata): - """MultipleOf(multiple_of=x) might be interpreted in two ways: - - 1. Python semantics, implying ``value % multiple_of == 0``, or - 2. JSONschema semantics, where ``int(value / multiple_of) == value / multiple_of`` - - We encourage users to be aware of these two common interpretations, - and libraries to carefully document which they implement. - """ - - multiple_of: Union[SupportsDiv, SupportsMod] - - -@dataclass(frozen=True, **SLOTS) -class MinLen(BaseMetadata): - """ - MinLen() implies minimum inclusive length, - e.g. ``len(value) >= min_length``. - """ - - min_length: Annotated[int, Ge(0)] - - -@dataclass(frozen=True, **SLOTS) -class MaxLen(BaseMetadata): - """ - MaxLen() implies maximum inclusive length, - e.g. ``len(value) <= max_length``. - """ - - max_length: Annotated[int, Ge(0)] - - -@dataclass(frozen=True, **SLOTS) -class Len(GroupedMetadata): - """ - Len() implies that ``min_length <= len(value) <= max_length``. - - Upper bound may be omitted or ``None`` to indicate no upper length bound. - """ - - min_length: Annotated[int, Ge(0)] = 0 - max_length: Optional[Annotated[int, Ge(0)]] = None - - def __iter__(self) -> Iterator[BaseMetadata]: - """Unpack a Len into zone or more single-bounds.""" - if self.min_length > 0: - yield MinLen(self.min_length) - if self.max_length is not None: - yield MaxLen(self.max_length) - - -@dataclass(frozen=True, **SLOTS) -class Timezone(BaseMetadata): - """Timezone(tz=...) requires a datetime to be aware (or ``tz=None``, naive). - - ``Annotated[datetime, Timezone(None)]`` must be a naive datetime. - ``Timezone[...]`` (the ellipsis literal) expresses that the datetime must be - tz-aware but any timezone is allowed. - - You may also pass a specific timezone string or tzinfo object such as - ``Timezone(timezone.utc)`` or ``Timezone("Africa/Abidjan")`` to express that - you only allow a specific timezone, though we note that this is often - a symptom of poor design. - """ - - tz: Union[str, tzinfo, EllipsisType, None] - - -@dataclass(frozen=True, **SLOTS) -class Unit(BaseMetadata): - """Indicates that the value is a physical quantity with the specified unit. - - It is intended for usage with numeric types, where the value represents the - magnitude of the quantity. For example, ``distance: Annotated[float, Unit('m')]`` - or ``speed: Annotated[float, Unit('m/s')]``. - - Interpretation of the unit string is left to the discretion of the consumer. - It is suggested to follow conventions established by python libraries that work - with physical quantities, such as - - - ``pint`` : - - ``astropy.units``: - - For indicating a quantity with a certain dimensionality but without a specific unit - it is recommended to use square brackets, e.g. `Annotated[float, Unit('[time]')]`. - Note, however, ``annotated_types`` itself makes no use of the unit string. - """ - - unit: str - - -@dataclass(frozen=True, **SLOTS) -class Predicate(BaseMetadata): - """``Predicate(func: Callable)`` implies `func(value)` is truthy for valid values. - - Users should prefer statically inspectable metadata, but if you need the full - power and flexibility of arbitrary runtime predicates... here it is. - - We provide a few predefined predicates for common string constraints: - ``IsLower = Predicate(str.islower)``, ``IsUpper = Predicate(str.isupper)``, and - ``IsDigits = Predicate(str.isdigit)``. Users are encouraged to use methods which - can be given special handling, and avoid indirection like ``lambda s: s.lower()``. - - Some libraries might have special logic to handle certain predicates, e.g. by - checking for `str.isdigit` and using its presence to both call custom logic to - enforce digit-only strings, and customise some generated external schema. - - We do not specify what behaviour should be expected for predicates that raise - an exception. For example `Annotated[int, Predicate(str.isdigit)]` might silently - skip invalid constraints, or statically raise an error; or it might try calling it - and then propagate or discard the resulting exception. - """ - - func: Callable[[Any], bool] - - def __repr__(self) -> str: - if getattr(self.func, "__name__", "") == "": - return f"{self.__class__.__name__}({self.func!r})" - if isinstance(self.func, (types.MethodType, types.BuiltinMethodType)) and ( - namespace := getattr(self.func.__self__, "__name__", None) - ): - return f"{self.__class__.__name__}({namespace}.{self.func.__name__})" - if isinstance(self.func, type(str.isascii)): # method descriptor - return f"{self.__class__.__name__}({self.func.__qualname__})" - return f"{self.__class__.__name__}({self.func.__name__})" - - -@dataclass -class Not: - func: Callable[[Any], bool] - - def __call__(self, __v: Any) -> bool: - return not self.func(__v) - - -_StrType = TypeVar("_StrType", bound=str) - -LowerCase = Annotated[_StrType, Predicate(str.islower)] -""" -Return True if the string is a lowercase string, False otherwise. - -A string is lowercase if all cased characters in the string are lowercase and there is at least one cased character in the string. -""" # noqa: E501 -UpperCase = Annotated[_StrType, Predicate(str.isupper)] -""" -Return True if the string is an uppercase string, False otherwise. - -A string is uppercase if all cased characters in the string are uppercase and there is at least one cased character in the string. -""" # noqa: E501 -IsDigit = Annotated[_StrType, Predicate(str.isdigit)] -IsDigits = IsDigit # type: ignore # plural for backwards compatibility, see #63 -""" -Return True if the string is a digit string, False otherwise. - -A string is a digit string if all characters in the string are digits and there is at least one character in the string. -""" # noqa: E501 -IsAscii = Annotated[_StrType, Predicate(str.isascii)] -""" -Return True if all characters in the string are ASCII, False otherwise. - -ASCII characters have code points in the range U+0000-U+007F. Empty string is ASCII too. -""" - -_NumericType = TypeVar('_NumericType', bound=Union[SupportsFloat, SupportsIndex]) -IsFinite = Annotated[_NumericType, Predicate(math.isfinite)] -"""Return True if x is neither an infinity nor a NaN, and False otherwise.""" -IsNotFinite = Annotated[_NumericType, Predicate(Not(math.isfinite))] -"""Return True if x is one of infinity or NaN, and False otherwise""" -IsNan = Annotated[_NumericType, Predicate(math.isnan)] -"""Return True if x is a NaN (not a number), and False otherwise.""" -IsNotNan = Annotated[_NumericType, Predicate(Not(math.isnan))] -"""Return True if x is anything but NaN (not a number), and False otherwise.""" -IsInfinite = Annotated[_NumericType, Predicate(math.isinf)] -"""Return True if x is a positive or negative infinity, and False otherwise.""" -IsNotInfinite = Annotated[_NumericType, Predicate(Not(math.isinf))] -"""Return True if x is neither a positive or negative infinity, and False otherwise.""" - -try: - from typing_extensions import DocInfo, doc # type: ignore [attr-defined] -except ImportError: - - @dataclass(frozen=True, **SLOTS) - class DocInfo: # type: ignore [no-redef] - """ " - The return value of doc(), mainly to be used by tools that want to extract the - Annotated documentation at runtime. - """ - - documentation: str - """The documentation string passed to doc().""" - - def doc( - documentation: str, - ) -> DocInfo: - """ - Add documentation to a type annotation inside of Annotated. - - For example: - - >>> def hi(name: Annotated[int, doc("The name of the user")]) -> None: ... - """ - return DocInfo(documentation) diff --git a/notification-service/venv/Lib/site-packages/annotated_types/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/annotated_types/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index ade7416..0000000 Binary files a/notification-service/venv/Lib/site-packages/annotated_types/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/annotated_types/__pycache__/test_cases.cpython-312.pyc b/notification-service/venv/Lib/site-packages/annotated_types/__pycache__/test_cases.cpython-312.pyc deleted file mode 100644 index b8853aa..0000000 Binary files a/notification-service/venv/Lib/site-packages/annotated_types/__pycache__/test_cases.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/annotated_types/py.typed b/notification-service/venv/Lib/site-packages/annotated_types/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/annotated_types/test_cases.py b/notification-service/venv/Lib/site-packages/annotated_types/test_cases.py deleted file mode 100644 index d9164d6..0000000 --- a/notification-service/venv/Lib/site-packages/annotated_types/test_cases.py +++ /dev/null @@ -1,151 +0,0 @@ -import math -import sys -from datetime import date, datetime, timedelta, timezone -from decimal import Decimal -from typing import Any, Dict, Iterable, Iterator, List, NamedTuple, Set, Tuple - -if sys.version_info < (3, 9): - from typing_extensions import Annotated -else: - from typing import Annotated - -import annotated_types as at - - -class Case(NamedTuple): - """ - A test case for `annotated_types`. - """ - - annotation: Any - valid_cases: Iterable[Any] - invalid_cases: Iterable[Any] - - -def cases() -> Iterable[Case]: - # Gt, Ge, Lt, Le - yield Case(Annotated[int, at.Gt(4)], (5, 6, 1000), (4, 0, -1)) - yield Case(Annotated[float, at.Gt(0.5)], (0.6, 0.7, 0.8, 0.9), (0.5, 0.0, -0.1)) - yield Case( - Annotated[datetime, at.Gt(datetime(2000, 1, 1))], - [datetime(2000, 1, 2), datetime(2000, 1, 3)], - [datetime(2000, 1, 1), datetime(1999, 12, 31)], - ) - yield Case( - Annotated[datetime, at.Gt(date(2000, 1, 1))], - [date(2000, 1, 2), date(2000, 1, 3)], - [date(2000, 1, 1), date(1999, 12, 31)], - ) - yield Case( - Annotated[datetime, at.Gt(Decimal('1.123'))], - [Decimal('1.1231'), Decimal('123')], - [Decimal('1.123'), Decimal('0')], - ) - - yield Case(Annotated[int, at.Ge(4)], (4, 5, 6, 1000, 4), (0, -1)) - yield Case(Annotated[float, at.Ge(0.5)], (0.5, 0.6, 0.7, 0.8, 0.9), (0.4, 0.0, -0.1)) - yield Case( - Annotated[datetime, at.Ge(datetime(2000, 1, 1))], - [datetime(2000, 1, 2), datetime(2000, 1, 3)], - [datetime(1998, 1, 1), datetime(1999, 12, 31)], - ) - - yield Case(Annotated[int, at.Lt(4)], (0, -1), (4, 5, 6, 1000, 4)) - yield Case(Annotated[float, at.Lt(0.5)], (0.4, 0.0, -0.1), (0.5, 0.6, 0.7, 0.8, 0.9)) - yield Case( - Annotated[datetime, at.Lt(datetime(2000, 1, 1))], - [datetime(1999, 12, 31), datetime(1999, 12, 31)], - [datetime(2000, 1, 2), datetime(2000, 1, 3)], - ) - - yield Case(Annotated[int, at.Le(4)], (4, 0, -1), (5, 6, 1000)) - yield Case(Annotated[float, at.Le(0.5)], (0.5, 0.0, -0.1), (0.6, 0.7, 0.8, 0.9)) - yield Case( - Annotated[datetime, at.Le(datetime(2000, 1, 1))], - [datetime(2000, 1, 1), datetime(1999, 12, 31)], - [datetime(2000, 1, 2), datetime(2000, 1, 3)], - ) - - # Interval - yield Case(Annotated[int, at.Interval(gt=4)], (5, 6, 1000), (4, 0, -1)) - yield Case(Annotated[int, at.Interval(gt=4, lt=10)], (5, 6), (4, 10, 1000, 0, -1)) - yield Case(Annotated[float, at.Interval(ge=0.5, le=1)], (0.5, 0.9, 1), (0.49, 1.1)) - yield Case( - Annotated[datetime, at.Interval(gt=datetime(2000, 1, 1), le=datetime(2000, 1, 3))], - [datetime(2000, 1, 2), datetime(2000, 1, 3)], - [datetime(2000, 1, 1), datetime(2000, 1, 4)], - ) - - yield Case(Annotated[int, at.MultipleOf(multiple_of=3)], (0, 3, 9), (1, 2, 4)) - yield Case(Annotated[float, at.MultipleOf(multiple_of=0.5)], (0, 0.5, 1, 1.5), (0.4, 1.1)) - - # lengths - - yield Case(Annotated[str, at.MinLen(3)], ('123', '1234', 'x' * 10), ('', '1', '12')) - yield Case(Annotated[str, at.Len(3)], ('123', '1234', 'x' * 10), ('', '1', '12')) - yield Case(Annotated[List[int], at.MinLen(3)], ([1, 2, 3], [1, 2, 3, 4], [1] * 10), ([], [1], [1, 2])) - yield Case(Annotated[List[int], at.Len(3)], ([1, 2, 3], [1, 2, 3, 4], [1] * 10), ([], [1], [1, 2])) - - yield Case(Annotated[str, at.MaxLen(4)], ('', '1234'), ('12345', 'x' * 10)) - yield Case(Annotated[str, at.Len(0, 4)], ('', '1234'), ('12345', 'x' * 10)) - yield Case(Annotated[List[str], at.MaxLen(4)], ([], ['a', 'bcdef'], ['a', 'b', 'c']), (['a'] * 5, ['b'] * 10)) - yield Case(Annotated[List[str], at.Len(0, 4)], ([], ['a', 'bcdef'], ['a', 'b', 'c']), (['a'] * 5, ['b'] * 10)) - - yield Case(Annotated[str, at.Len(3, 5)], ('123', '12345'), ('', '1', '12', '123456', 'x' * 10)) - yield Case(Annotated[str, at.Len(3, 3)], ('123',), ('12', '1234')) - - yield Case(Annotated[Dict[int, int], at.Len(2, 3)], [{1: 1, 2: 2}], [{}, {1: 1}, {1: 1, 2: 2, 3: 3, 4: 4}]) - yield Case(Annotated[Set[int], at.Len(2, 3)], ({1, 2}, {1, 2, 3}), (set(), {1}, {1, 2, 3, 4})) - yield Case(Annotated[Tuple[int, ...], at.Len(2, 3)], ((1, 2), (1, 2, 3)), ((), (1,), (1, 2, 3, 4))) - - # Timezone - - yield Case( - Annotated[datetime, at.Timezone(None)], [datetime(2000, 1, 1)], [datetime(2000, 1, 1, tzinfo=timezone.utc)] - ) - yield Case( - Annotated[datetime, at.Timezone(...)], [datetime(2000, 1, 1, tzinfo=timezone.utc)], [datetime(2000, 1, 1)] - ) - yield Case( - Annotated[datetime, at.Timezone(timezone.utc)], - [datetime(2000, 1, 1, tzinfo=timezone.utc)], - [datetime(2000, 1, 1), datetime(2000, 1, 1, tzinfo=timezone(timedelta(hours=6)))], - ) - yield Case( - Annotated[datetime, at.Timezone('Europe/London')], - [datetime(2000, 1, 1, tzinfo=timezone(timedelta(0), name='Europe/London'))], - [datetime(2000, 1, 1), datetime(2000, 1, 1, tzinfo=timezone(timedelta(hours=6)))], - ) - - # Quantity - - yield Case(Annotated[float, at.Unit(unit='m')], (5, 4.2), ('5m', '4.2m')) - - # predicate types - - yield Case(at.LowerCase[str], ['abc', 'foobar'], ['', 'A', 'Boom']) - yield Case(at.UpperCase[str], ['ABC', 'DEFO'], ['', 'a', 'abc', 'AbC']) - yield Case(at.IsDigit[str], ['123'], ['', 'ab', 'a1b2']) - yield Case(at.IsAscii[str], ['123', 'foo bar'], ['£100', '😊', 'whatever 👀']) - - yield Case(Annotated[int, at.Predicate(lambda x: x % 2 == 0)], [0, 2, 4], [1, 3, 5]) - - yield Case(at.IsFinite[float], [1.23], [math.nan, math.inf, -math.inf]) - yield Case(at.IsNotFinite[float], [math.nan, math.inf], [1.23]) - yield Case(at.IsNan[float], [math.nan], [1.23, math.inf]) - yield Case(at.IsNotNan[float], [1.23, math.inf], [math.nan]) - yield Case(at.IsInfinite[float], [math.inf], [math.nan, 1.23]) - yield Case(at.IsNotInfinite[float], [math.nan, 1.23], [math.inf]) - - # check stacked predicates - yield Case(at.IsInfinite[Annotated[float, at.Predicate(lambda x: x > 0)]], [math.inf], [-math.inf, 1.23, math.nan]) - - # doc - yield Case(Annotated[int, at.doc("A number")], [1, 2], []) - - # custom GroupedMetadata - class MyCustomGroupedMetadata(at.GroupedMetadata): - def __iter__(self) -> Iterator[at.Predicate]: - yield at.Predicate(lambda x: float(x).is_integer()) - - yield Case(Annotated[float, MyCustomGroupedMetadata()], [0, 2.0], [0.01, 1.5]) diff --git a/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/INSTALLER b/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/METADATA b/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/METADATA deleted file mode 100644 index 2de1cd5..0000000 --- a/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/METADATA +++ /dev/null @@ -1,105 +0,0 @@ -Metadata-Version: 2.4 -Name: anyio -Version: 4.13.0 -Summary: High-level concurrency and networking framework on top of asyncio or Trio -Author-email: Alex Grönholm -License-Expression: MIT -Project-URL: Documentation, https://anyio.readthedocs.io/en/latest/ -Project-URL: Changelog, https://anyio.readthedocs.io/en/stable/versionhistory.html -Project-URL: Source code, https://github.com/agronholm/anyio -Project-URL: Issue tracker, https://github.com/agronholm/anyio/issues -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: Framework :: AnyIO -Classifier: Typing :: Typed -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -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 -Requires-Python: >=3.10 -Description-Content-Type: text/x-rst -License-File: LICENSE -Requires-Dist: exceptiongroup>=1.0.2; python_version < "3.11" -Requires-Dist: idna>=2.8 -Requires-Dist: typing_extensions>=4.5; python_version < "3.13" -Provides-Extra: trio -Requires-Dist: trio>=0.32.0; extra == "trio" -Dynamic: license-file - -.. image:: https://github.com/agronholm/anyio/actions/workflows/test.yml/badge.svg - :target: https://github.com/agronholm/anyio/actions/workflows/test.yml - :alt: Build Status -.. image:: https://coveralls.io/repos/github/agronholm/anyio/badge.svg?branch=master - :target: https://coveralls.io/github/agronholm/anyio?branch=master - :alt: Code Coverage -.. image:: https://readthedocs.org/projects/anyio/badge/?version=latest - :target: https://anyio.readthedocs.io/en/latest/?badge=latest - :alt: Documentation -.. image:: https://badges.gitter.im/gitterHQ/gitter.svg - :target: https://gitter.im/python-trio/AnyIO - :alt: Gitter chat -.. image:: https://tidelift.com/badges/package/pypi/anyio - :target: https://tidelift.com/subscription/pkg/pypi-anyio - :alt: Tidelift - -AnyIO is an asynchronous networking and concurrency library that works on top of either asyncio_ or -Trio_. It implements Trio-like `structured concurrency`_ (SC) on top of asyncio and works in harmony -with the native SC of Trio itself. - -Applications and libraries written against AnyIO's API will run unmodified on either asyncio_ or -Trio_. AnyIO can also be adopted into a library or application incrementally – bit by bit, no full -refactoring necessary. It will blend in with the native libraries of your chosen backend. - -To find out why you might want to use AnyIO's APIs instead of asyncio's, you can read about it -`here `_. - -Documentation -------------- - -View full documentation at: https://anyio.readthedocs.io/ - -Features --------- - -AnyIO offers the following functionality: - -* Task groups (nurseries_ in trio terminology) -* High-level networking (TCP, UDP and UNIX sockets) - - * `Happy eyeballs`_ algorithm for TCP connections (more robust than that of asyncio on Python - 3.8) - * async/await style UDP sockets (unlike asyncio where you still have to use Transports and - Protocols) - -* A versatile API for byte streams and object streams -* Inter-task synchronization and communication (locks, conditions, events, semaphores, object - streams) -* Worker threads -* Subprocesses -* Subinterpreter support for code parallelization (on Python 3.13 and later) -* Asynchronous file I/O (using worker threads) -* Signal handling -* Asynchronous version of the functools_ module - -AnyIO also comes with its own pytest_ plugin which also supports asynchronous fixtures. -It even works with the popular Hypothesis_ library. - -.. _asyncio: https://docs.python.org/3/library/asyncio.html -.. _Trio: https://github.com/python-trio/trio -.. _structured concurrency: https://en.wikipedia.org/wiki/Structured_concurrency -.. _nurseries: https://trio.readthedocs.io/en/stable/reference-core.html#nurseries-and-spawning -.. _Happy eyeballs: https://en.wikipedia.org/wiki/Happy_Eyeballs -.. _pytest: https://docs.pytest.org/en/latest/ -.. _functools: https://docs.python.org/3/library/functools.html -.. _Hypothesis: https://hypothesis.works/ - -Security contact information ----------------------------- - -To report a security vulnerability, please use the `Tidelift security contact`_. -Tidelift will coordinate the fix and disclosure. - -.. _Tidelift security contact: https://tidelift.com/security diff --git a/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/RECORD b/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/RECORD deleted file mode 100644 index c0e5e01..0000000 --- a/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/RECORD +++ /dev/null @@ -1,92 +0,0 @@ -anyio-4.13.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -anyio-4.13.0.dist-info/METADATA,sha256=F0EYfiPlmTRwmJN2JktNxJg1GNnl0wHhzOWmz7pFvjM,4513 -anyio-4.13.0.dist-info/RECORD,, -anyio-4.13.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91 -anyio-4.13.0.dist-info/entry_points.txt,sha256=_d6Yu6uiaZmNe0CydowirE9Cmg7zUL2g08tQpoS3Qvc,39 -anyio-4.13.0.dist-info/licenses/LICENSE,sha256=U2GsncWPLvX9LpsJxoKXwX8ElQkJu8gCO9uC6s8iwrA,1081 -anyio-4.13.0.dist-info/top_level.txt,sha256=QglSMiWX8_5dpoVAEIHdEYzvqFMdSYWmCj6tYw2ITkQ,6 -anyio/__init__.py,sha256=7iDVqMUprUuKNY91FuoKqayAhR-OY136YDPI6P78HHk,6170 -anyio/__pycache__/__init__.cpython-312.pyc,, -anyio/__pycache__/from_thread.cpython-312.pyc,, -anyio/__pycache__/functools.cpython-312.pyc,, -anyio/__pycache__/lowlevel.cpython-312.pyc,, -anyio/__pycache__/pytest_plugin.cpython-312.pyc,, -anyio/__pycache__/to_interpreter.cpython-312.pyc,, -anyio/__pycache__/to_process.cpython-312.pyc,, -anyio/__pycache__/to_thread.cpython-312.pyc,, -anyio/_backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -anyio/_backends/__pycache__/__init__.cpython-312.pyc,, -anyio/_backends/__pycache__/_asyncio.cpython-312.pyc,, -anyio/_backends/__pycache__/_trio.cpython-312.pyc,, -anyio/_backends/_asyncio.py,sha256=kuqlg2sBUsFdgY80xSDAw60Gx_4WNCl9iSL5XlY6lCU,99476 -anyio/_backends/_trio.py,sha256=l9U-TsKRxzmTQxSMvOhn0bNeFn_iRx3Ho30jvR5Bdu0,41366 -anyio/_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -anyio/_core/__pycache__/__init__.cpython-312.pyc,, -anyio/_core/__pycache__/_asyncio_selector_thread.cpython-312.pyc,, -anyio/_core/__pycache__/_contextmanagers.cpython-312.pyc,, -anyio/_core/__pycache__/_eventloop.cpython-312.pyc,, -anyio/_core/__pycache__/_exceptions.cpython-312.pyc,, -anyio/_core/__pycache__/_fileio.cpython-312.pyc,, -anyio/_core/__pycache__/_resources.cpython-312.pyc,, -anyio/_core/__pycache__/_signals.cpython-312.pyc,, -anyio/_core/__pycache__/_sockets.cpython-312.pyc,, -anyio/_core/__pycache__/_streams.cpython-312.pyc,, -anyio/_core/__pycache__/_subprocesses.cpython-312.pyc,, -anyio/_core/__pycache__/_synchronization.cpython-312.pyc,, -anyio/_core/__pycache__/_tasks.cpython-312.pyc,, -anyio/_core/__pycache__/_tempfile.cpython-312.pyc,, -anyio/_core/__pycache__/_testing.cpython-312.pyc,, -anyio/_core/__pycache__/_typedattr.cpython-312.pyc,, -anyio/_core/_asyncio_selector_thread.py,sha256=2PdxFM3cs02Kp6BSppbvmRT7q7asreTW5FgBxEsflBo,5626 -anyio/_core/_contextmanagers.py,sha256=YInBCabiEeS-UaP_Jdxa1CaFC71ETPW8HZTHIM8Rsc8,7215 -anyio/_core/_eventloop.py,sha256=c2EdcBX-xnKwxPcC4Pjn3_qG9I-x4IWFO2R9RqCGjM4,6448 -anyio/_core/_exceptions.py,sha256=Y3aq-Wxd7Q2HqwSg7nZPvRsHEuGazv_qeet6gqEBdPk,4407 -anyio/_core/_fileio.py,sha256=CKi1gFNiW2G4knWeBE7He7-rptQwgYjDUWfG8DSlvLs,25665 -anyio/_core/_resources.py,sha256=NbmU5O5UX3xEyACnkmYX28Fmwdl-f-ny0tHym26e0w0,435 -anyio/_core/_signals.py,sha256=mjTBB2hTKNPRlU0IhnijeQedpWOGERDiMjSlJQsFrug,1016 -anyio/_core/_sockets.py,sha256=RBXHcUqZt5gg_-OOfgHVv8uq2FSKk1uVUzTdpjBoI1o,34977 -anyio/_core/_streams.py,sha256=FczFwIgDpnkK0bODWJXMpsUJYdvAD04kaUaGzJU8DK0,1806 -anyio/_core/_subprocesses.py,sha256=tkmkPKEkEaiMD8C9WRZBlmgjOYRDRbZdte6e-unay2E,7916 -anyio/_core/_synchronization.py,sha256=9G3fvRsPNrrWJ_Z6gD_80wXq8I8qgAyhwM8PvHQnT2c,21061 -anyio/_core/_tasks.py,sha256=pVB7K6AAulzUM8YgXAeqNZG44nSyZ1bYJjH8GznC00I,5435 -anyio/_core/_tempfile.py,sha256=jE2w59FRF3yRo4vjkjfZF2YcqsBZvc66VWRwrJGDYGk,19624 -anyio/_core/_testing.py,sha256=u7MPqGXwpTxqI7hclSdNA30z2GH1Nw258uwKvy_RfBg,2340 -anyio/_core/_typedattr.py,sha256=P4ozZikn3-DbpoYcvyghS_FOYAgbmUxeoU8-L_07pZM,2508 -anyio/abc/__init__.py,sha256=6mWhcl_pGXhrgZVHP_TCfMvIXIOp9mroEFM90fYCU_U,2869 -anyio/abc/__pycache__/__init__.cpython-312.pyc,, -anyio/abc/__pycache__/_eventloop.cpython-312.pyc,, -anyio/abc/__pycache__/_resources.cpython-312.pyc,, -anyio/abc/__pycache__/_sockets.cpython-312.pyc,, -anyio/abc/__pycache__/_streams.cpython-312.pyc,, -anyio/abc/__pycache__/_subprocesses.cpython-312.pyc,, -anyio/abc/__pycache__/_tasks.cpython-312.pyc,, -anyio/abc/__pycache__/_testing.cpython-312.pyc,, -anyio/abc/_eventloop.py,sha256=39lYnmtvoHaZw22sWBKOTA_zv7bamOnr8O49PqgDXdw,10629 -anyio/abc/_resources.py,sha256=DrYvkNN1hH6Uvv5_5uKySvDsnknGVDe8FCKfko0VtN8,783 -anyio/abc/_sockets.py,sha256=OmVDrfemVvF9c5K1tpBgQyV6fn5v0XyCExLAqBOGz9o,13124 -anyio/abc/_streams.py,sha256=HYvna1iZbWcwLROTO6IhLX79RTRLPShZMWe0sG1q54I,7481 -anyio/abc/_subprocesses.py,sha256=cumAPJTktOQtw63IqG0lDpyZqu_l1EElvQHMiwJgL08,2067 -anyio/abc/_tasks.py,sha256=KC7wrciE48AINOI-AhPutnFhe1ewfP7QnamFlDzqesQ,3721 -anyio/abc/_testing.py,sha256=tBJUzkSfOXJw23fe8qSJ03kJlShOYjjaEyFB6k6MYT8,1821 -anyio/from_thread.py,sha256=L-0w1HxJ6BSb-KuVi57k5Tkc3yzQrx3QK5tAxMPcY-0,19141 -anyio/functools.py,sha256=5AWM1iYTKkTzptvUhQDdLSh5GvbBW-vcs-SAUfIfA9A,12076 -anyio/lowlevel.py,sha256=AyKLVK3LaWSoK39LkCKxE4_GDMLKZBNqTrLUgk63y80,5158 -anyio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -anyio/pytest_plugin.py,sha256=t6h4KJstqIxfxwTZ1YO8vpUVuB99nfCLltn0NHfatHo,12775 -anyio/streams/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -anyio/streams/__pycache__/__init__.cpython-312.pyc,, -anyio/streams/__pycache__/buffered.cpython-312.pyc,, -anyio/streams/__pycache__/file.cpython-312.pyc,, -anyio/streams/__pycache__/memory.cpython-312.pyc,, -anyio/streams/__pycache__/stapled.cpython-312.pyc,, -anyio/streams/__pycache__/text.cpython-312.pyc,, -anyio/streams/__pycache__/tls.cpython-312.pyc,, -anyio/streams/buffered.py,sha256=2R3PeJhe4EXrdYqz44Y6-Eg9R6DrmlsYrP36Ir43-po,6263 -anyio/streams/file.py,sha256=msnrotVKGMQomUu_Rj2qz9MvIdUp6d3JGr7MOEO8kV4,4428 -anyio/streams/memory.py,sha256=F0zwzvFJKAhX_LRZGoKzzqDC2oMM-f-yyTBrEYEGOaU,10740 -anyio/streams/stapled.py,sha256=T8Xqwf8K6EgURPxbt1N4i7A8BAk-gScv-GRhjLXIf_o,4390 -anyio/streams/text.py,sha256=BcVAGJw1VRvtIqnv-o0Rb0pwH7p8vwlvl21xHq522ag,5765 -anyio/streams/tls.py,sha256=DQVkXUvsTEYKkBO8dlVU7j_5H8QOtLy4sGi1Wrjqevo,15303 -anyio/to_interpreter.py,sha256=_mLngrMy97TMR6VbW4Y6YzDUk9ZuPcQMPlkuyRh3C9k,7100 -anyio/to_process.py,sha256=J7gAA_YOuoHqnpDAf5fm1Qu6kOmTzdFbiDNvnV755vk,9798 -anyio/to_thread.py,sha256=f6h_k2d743GBv9FhAnhM_YpTvWgIrzBy9cOE0eJ1UJw,2693 diff --git a/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/WHEEL b/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/WHEEL deleted file mode 100644 index 14a883f..0000000 --- a/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (82.0.1) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/entry_points.txt b/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/entry_points.txt deleted file mode 100644 index 44dd9bd..0000000 --- a/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/entry_points.txt +++ /dev/null @@ -1,2 +0,0 @@ -[pytest11] -anyio = anyio.pytest_plugin diff --git a/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/licenses/LICENSE b/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/licenses/LICENSE deleted file mode 100644 index 104eebf..0000000 --- a/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/licenses/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2018 Alex Grönholm - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/top_level.txt b/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/top_level.txt deleted file mode 100644 index c77c069..0000000 --- a/notification-service/venv/Lib/site-packages/anyio-4.13.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -anyio diff --git a/notification-service/venv/Lib/site-packages/anyio/__init__.py b/notification-service/venv/Lib/site-packages/anyio/__init__.py deleted file mode 100644 index d23c5a5..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/__init__.py +++ /dev/null @@ -1,111 +0,0 @@ -from __future__ import annotations - -from ._core._contextmanagers import AsyncContextManagerMixin as AsyncContextManagerMixin -from ._core._contextmanagers import ContextManagerMixin as ContextManagerMixin -from ._core._eventloop import current_time as current_time -from ._core._eventloop import get_all_backends as get_all_backends -from ._core._eventloop import get_available_backends as get_available_backends -from ._core._eventloop import get_cancelled_exc_class as get_cancelled_exc_class -from ._core._eventloop import run as run -from ._core._eventloop import sleep as sleep -from ._core._eventloop import sleep_forever as sleep_forever -from ._core._eventloop import sleep_until as sleep_until -from ._core._exceptions import BrokenResourceError as BrokenResourceError -from ._core._exceptions import BrokenWorkerInterpreter as BrokenWorkerInterpreter -from ._core._exceptions import BrokenWorkerProcess as BrokenWorkerProcess -from ._core._exceptions import BusyResourceError as BusyResourceError -from ._core._exceptions import ClosedResourceError as ClosedResourceError -from ._core._exceptions import ConnectionFailed as ConnectionFailed -from ._core._exceptions import DelimiterNotFound as DelimiterNotFound -from ._core._exceptions import EndOfStream as EndOfStream -from ._core._exceptions import IncompleteRead as IncompleteRead -from ._core._exceptions import NoEventLoopError as NoEventLoopError -from ._core._exceptions import RunFinishedError as RunFinishedError -from ._core._exceptions import TypedAttributeLookupError as TypedAttributeLookupError -from ._core._exceptions import WouldBlock as WouldBlock -from ._core._fileio import AsyncFile as AsyncFile -from ._core._fileio import Path as Path -from ._core._fileio import open_file as open_file -from ._core._fileio import wrap_file as wrap_file -from ._core._resources import aclose_forcefully as aclose_forcefully -from ._core._signals import open_signal_receiver as open_signal_receiver -from ._core._sockets import TCPConnectable as TCPConnectable -from ._core._sockets import UNIXConnectable as UNIXConnectable -from ._core._sockets import as_connectable as as_connectable -from ._core._sockets import connect_tcp as connect_tcp -from ._core._sockets import connect_unix as connect_unix -from ._core._sockets import create_connected_udp_socket as create_connected_udp_socket -from ._core._sockets import ( - create_connected_unix_datagram_socket as create_connected_unix_datagram_socket, -) -from ._core._sockets import create_tcp_listener as create_tcp_listener -from ._core._sockets import create_udp_socket as create_udp_socket -from ._core._sockets import create_unix_datagram_socket as create_unix_datagram_socket -from ._core._sockets import create_unix_listener as create_unix_listener -from ._core._sockets import getaddrinfo as getaddrinfo -from ._core._sockets import getnameinfo as getnameinfo -from ._core._sockets import notify_closing as notify_closing -from ._core._sockets import wait_readable as wait_readable -from ._core._sockets import wait_socket_readable as wait_socket_readable -from ._core._sockets import wait_socket_writable as wait_socket_writable -from ._core._sockets import wait_writable as wait_writable -from ._core._streams import create_memory_object_stream as create_memory_object_stream -from ._core._subprocesses import open_process as open_process -from ._core._subprocesses import run_process as run_process -from ._core._synchronization import CapacityLimiter as CapacityLimiter -from ._core._synchronization import ( - CapacityLimiterStatistics as CapacityLimiterStatistics, -) -from ._core._synchronization import Condition as Condition -from ._core._synchronization import ConditionStatistics as ConditionStatistics -from ._core._synchronization import Event as Event -from ._core._synchronization import EventStatistics as EventStatistics -from ._core._synchronization import Lock as Lock -from ._core._synchronization import LockStatistics as LockStatistics -from ._core._synchronization import ResourceGuard as ResourceGuard -from ._core._synchronization import Semaphore as Semaphore -from ._core._synchronization import SemaphoreStatistics as SemaphoreStatistics -from ._core._tasks import TASK_STATUS_IGNORED as TASK_STATUS_IGNORED -from ._core._tasks import CancelScope as CancelScope -from ._core._tasks import create_task_group as create_task_group -from ._core._tasks import current_effective_deadline as current_effective_deadline -from ._core._tasks import fail_after as fail_after -from ._core._tasks import move_on_after as move_on_after -from ._core._tempfile import NamedTemporaryFile as NamedTemporaryFile -from ._core._tempfile import SpooledTemporaryFile as SpooledTemporaryFile -from ._core._tempfile import TemporaryDirectory as TemporaryDirectory -from ._core._tempfile import TemporaryFile as TemporaryFile -from ._core._tempfile import gettempdir as gettempdir -from ._core._tempfile import gettempdirb as gettempdirb -from ._core._tempfile import mkdtemp as mkdtemp -from ._core._tempfile import mkstemp as mkstemp -from ._core._testing import TaskInfo as TaskInfo -from ._core._testing import get_current_task as get_current_task -from ._core._testing import get_running_tasks as get_running_tasks -from ._core._testing import wait_all_tasks_blocked as wait_all_tasks_blocked -from ._core._typedattr import TypedAttributeProvider as TypedAttributeProvider -from ._core._typedattr import TypedAttributeSet as TypedAttributeSet -from ._core._typedattr import typed_attribute as typed_attribute - -# Re-export imports so they look like they live directly in this package -for __value in list(locals().values()): - if getattr(__value, "__module__", "").startswith("anyio."): - __value.__module__ = __name__ - - -del __value - - -def __getattr__(attr: str) -> type[BrokenWorkerInterpreter]: - """Support deprecated aliases.""" - if attr == "BrokenWorkerIntepreter": - import warnings - - warnings.warn( - "The 'BrokenWorkerIntepreter' alias is deprecated, use 'BrokenWorkerInterpreter' instead.", - DeprecationWarning, - stacklevel=2, - ) - return BrokenWorkerInterpreter - - raise AttributeError(f"module {__name__!r} has no attribute {attr!r}") diff --git a/notification-service/venv/Lib/site-packages/anyio/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 72cb021..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/__pycache__/from_thread.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/__pycache__/from_thread.cpython-312.pyc deleted file mode 100644 index 0e64496..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/__pycache__/from_thread.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/__pycache__/functools.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/__pycache__/functools.cpython-312.pyc deleted file mode 100644 index 10fba0b..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/__pycache__/functools.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/__pycache__/lowlevel.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/__pycache__/lowlevel.cpython-312.pyc deleted file mode 100644 index 0ce0791..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/__pycache__/lowlevel.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/__pycache__/pytest_plugin.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/__pycache__/pytest_plugin.cpython-312.pyc deleted file mode 100644 index 8976f50..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/__pycache__/pytest_plugin.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/__pycache__/to_interpreter.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/__pycache__/to_interpreter.cpython-312.pyc deleted file mode 100644 index 9e35e9d..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/__pycache__/to_interpreter.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/__pycache__/to_process.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/__pycache__/to_process.cpython-312.pyc deleted file mode 100644 index c769409..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/__pycache__/to_process.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/__pycache__/to_thread.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/__pycache__/to_thread.cpython-312.pyc deleted file mode 100644 index d7c5623..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/__pycache__/to_thread.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_backends/__init__.py b/notification-service/venv/Lib/site-packages/anyio/_backends/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/anyio/_backends/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_backends/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 358fc34..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_backends/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_backends/__pycache__/_asyncio.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_backends/__pycache__/_asyncio.cpython-312.pyc deleted file mode 100644 index ec337e2..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_backends/__pycache__/_asyncio.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_backends/__pycache__/_trio.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_backends/__pycache__/_trio.cpython-312.pyc deleted file mode 100644 index 48c2d0d..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_backends/__pycache__/_trio.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_backends/_asyncio.py b/notification-service/venv/Lib/site-packages/anyio/_backends/_asyncio.py deleted file mode 100644 index 9f1ddc2..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_backends/_asyncio.py +++ /dev/null @@ -1,2996 +0,0 @@ -from __future__ import annotations - -import array -import asyncio -import concurrent.futures -import contextvars -import math -import os -import socket -import sys -import threading -import weakref -from asyncio import ( - AbstractEventLoop, - CancelledError, - all_tasks, - create_task, - current_task, - get_running_loop, - sleep, -) -from asyncio.base_events import _run_until_complete_cb # type: ignore[attr-defined] -from collections import OrderedDict, deque -from collections.abc import ( - AsyncGenerator, - AsyncIterator, - Awaitable, - Callable, - Collection, - Coroutine, - Iterable, - Sequence, -) -from concurrent.futures import Future -from contextlib import AbstractContextManager, suppress -from contextvars import Context, copy_context -from dataclasses import dataclass, field -from functools import partial, wraps -from inspect import ( - CORO_RUNNING, - CORO_SUSPENDED, - getcoroutinestate, - iscoroutine, -) -from io import IOBase -from os import PathLike -from queue import Queue -from signal import Signals -from socket import AddressFamily, SocketKind -from threading import Thread -from types import CodeType, TracebackType -from typing import ( - IO, - TYPE_CHECKING, - Any, - ParamSpec, - TypeVar, - cast, -) -from weakref import WeakKeyDictionary - -from .. import ( - CapacityLimiterStatistics, - EventStatistics, - LockStatistics, - TaskInfo, - abc, -) -from .._core._eventloop import ( - claim_worker_thread, - set_current_async_library, - threadlocals, -) -from .._core._exceptions import ( - BrokenResourceError, - BusyResourceError, - ClosedResourceError, - EndOfStream, - RunFinishedError, - WouldBlock, -) -from .._core._sockets import convert_ipv6_sockaddr -from .._core._streams import create_memory_object_stream -from .._core._synchronization import ( - CapacityLimiter as BaseCapacityLimiter, -) -from .._core._synchronization import Event as BaseEvent -from .._core._synchronization import Lock as BaseLock -from .._core._synchronization import ( - ResourceGuard, - SemaphoreStatistics, -) -from .._core._synchronization import Semaphore as BaseSemaphore -from .._core._tasks import CancelScope as BaseCancelScope -from ..abc import ( - AsyncBackend, - IPSockAddrType, - SocketListener, - UDPPacketType, - UNIXDatagramPacketType, -) -from ..abc._eventloop import StrOrBytesPath -from ..lowlevel import RunVar -from ..streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream - -if TYPE_CHECKING: - from _typeshed import FileDescriptorLike -else: - FileDescriptorLike = object - -if sys.version_info >= (3, 11): - from asyncio import Runner - from typing import TypeVarTuple, Unpack -else: - import contextvars - import enum - import signal - from asyncio import coroutines, events, exceptions, tasks - - from exceptiongroup import BaseExceptionGroup - from typing_extensions import TypeVarTuple, Unpack - - class _State(enum.Enum): - CREATED = "created" - INITIALIZED = "initialized" - CLOSED = "closed" - - class Runner: - # Copied from CPython 3.11 - def __init__( - self, - *, - debug: bool | None = None, - loop_factory: Callable[[], AbstractEventLoop] | None = None, - ): - self._state = _State.CREATED - self._debug = debug - self._loop_factory = loop_factory - self._loop: AbstractEventLoop | None = None - self._context = None - self._interrupt_count = 0 - self._set_event_loop = False - - def __enter__(self) -> Runner: - self._lazy_init() - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self.close() - - def close(self) -> None: - """Shutdown and close event loop.""" - loop = self._loop - if self._state is not _State.INITIALIZED or loop is None: - return - try: - _cancel_all_tasks(loop) - loop.run_until_complete(loop.shutdown_asyncgens()) - if hasattr(loop, "shutdown_default_executor"): - loop.run_until_complete(loop.shutdown_default_executor()) - else: - loop.run_until_complete(_shutdown_default_executor(loop)) - finally: - if self._set_event_loop: - events.set_event_loop(None) - loop.close() - self._loop = None - self._state = _State.CLOSED - - def get_loop(self) -> AbstractEventLoop: - """Return embedded event loop.""" - self._lazy_init() - return self._loop - - def run(self, coro: Coroutine[T_Retval], *, context=None) -> T_Retval: - """Run a coroutine inside the embedded event loop.""" - if not coroutines.iscoroutine(coro): - raise ValueError(f"a coroutine was expected, got {coro!r}") - - if events._get_running_loop() is not None: - # fail fast with short traceback - raise RuntimeError( - "Runner.run() cannot be called from a running event loop" - ) - - self._lazy_init() - - if context is None: - context = self._context - task = context.run(self._loop.create_task, coro) - - if ( - threading.current_thread() is threading.main_thread() - and signal.getsignal(signal.SIGINT) is signal.default_int_handler - ): - sigint_handler = partial(self._on_sigint, main_task=task) - try: - signal.signal(signal.SIGINT, sigint_handler) - except ValueError: - # `signal.signal` may throw if `threading.main_thread` does - # not support signals (e.g. embedded interpreter with signals - # not registered - see gh-91880) - sigint_handler = None - else: - sigint_handler = None - - self._interrupt_count = 0 - try: - return self._loop.run_until_complete(task) - except exceptions.CancelledError: - if self._interrupt_count > 0: - uncancel = getattr(task, "uncancel", None) - if uncancel is not None and uncancel() == 0: - raise KeyboardInterrupt # noqa: B904 - raise # CancelledError - finally: - if ( - sigint_handler is not None - and signal.getsignal(signal.SIGINT) is sigint_handler - ): - signal.signal(signal.SIGINT, signal.default_int_handler) - - def _lazy_init(self) -> None: - if self._state is _State.CLOSED: - raise RuntimeError("Runner is closed") - if self._state is _State.INITIALIZED: - return - if self._loop_factory is None: - self._loop = events.new_event_loop() - if not self._set_event_loop: - # Call set_event_loop only once to avoid calling - # attach_loop multiple times on child watchers - events.set_event_loop(self._loop) - self._set_event_loop = True - else: - self._loop = self._loop_factory() - if self._debug is not None: - self._loop.set_debug(self._debug) - self._context = contextvars.copy_context() - self._state = _State.INITIALIZED - - def _on_sigint(self, signum, frame, main_task: asyncio.Task) -> None: - self._interrupt_count += 1 - if self._interrupt_count == 1 and not main_task.done(): - main_task.cancel() - # wakeup loop if it is blocked by select() with long timeout - self._loop.call_soon_threadsafe(lambda: None) - return - raise KeyboardInterrupt() - - def _cancel_all_tasks(loop: AbstractEventLoop) -> None: - to_cancel = tasks.all_tasks(loop) - if not to_cancel: - return - - for task in to_cancel: - task.cancel() - - loop.run_until_complete(tasks.gather(*to_cancel, return_exceptions=True)) - - for task in to_cancel: - if task.cancelled(): - continue - if task.exception() is not None: - loop.call_exception_handler( - { - "message": "unhandled exception during asyncio.run() shutdown", - "exception": task.exception(), - "task": task, - } - ) - - async def _shutdown_default_executor(loop: AbstractEventLoop) -> None: - """Schedule the shutdown of the default executor.""" - - def _do_shutdown(future: asyncio.futures.Future) -> None: - try: - loop._default_executor.shutdown(wait=True) # type: ignore[attr-defined] - loop.call_soon_threadsafe(future.set_result, None) - except Exception as ex: - loop.call_soon_threadsafe(future.set_exception, ex) - - loop._executor_shutdown_called = True - if loop._default_executor is None: - return - future = loop.create_future() - thread = threading.Thread(target=_do_shutdown, args=(future,)) - thread.start() - try: - await future - finally: - thread.join() - - -T_Retval = TypeVar("T_Retval") -T_contra = TypeVar("T_contra", contravariant=True) -PosArgsT = TypeVarTuple("PosArgsT") -P = ParamSpec("P") - -_root_task: RunVar[asyncio.Task | None] = RunVar("_root_task") - - -def find_root_task() -> asyncio.Task: - root_task = _root_task.get(None) - if root_task is not None and not root_task.done(): - return root_task - - # Look for a task that has been started via run_until_complete() - for task in all_tasks(): - if task._callbacks and not task.done(): - callbacks = [cb for cb, context in task._callbacks] - for cb in callbacks: - if ( - cb is _run_until_complete_cb - or getattr(cb, "__module__", None) == "uvloop.loop" - ): - _root_task.set(task) - return task - - # Look up the topmost task in the AnyIO task tree, if possible - task = cast(asyncio.Task, current_task()) - state = _task_states.get(task) - if state: - cancel_scope = state.cancel_scope - while cancel_scope and cancel_scope._parent_scope is not None: - cancel_scope = cancel_scope._parent_scope - - if cancel_scope is not None: - return cast(asyncio.Task, cancel_scope._host_task) - - return task - - -def get_callable_name(func: Callable) -> str: - module = getattr(func, "__module__", None) - qualname = getattr(func, "__qualname__", None) - return ".".join([x for x in (module, qualname) if x]) - - -# -# Event loop -# - -_run_vars: WeakKeyDictionary[asyncio.AbstractEventLoop, Any] = WeakKeyDictionary() - - -def _task_started(task: asyncio.Task) -> bool: - """Return ``True`` if the task has been started and has not finished.""" - # The task coro should never be None here, as we never add finished tasks to the - # task list - coro = task.get_coro() - assert coro is not None - try: - return getcoroutinestate(coro) in (CORO_RUNNING, CORO_SUSPENDED) - except AttributeError: - # task coro is async_genenerator_asend https://bugs.python.org/issue37771 - raise Exception(f"Cannot determine if task {task} has started or not") from None - - -# -# Timeouts and cancellation -# - - -def is_anyio_cancellation(exc: CancelledError) -> bool: - # Sometimes third party frameworks catch a CancelledError and raise a new one, so as - # a workaround we have to look at the previous ones in __context__ too for a - # matching cancel message - while True: - if ( - exc.args - and isinstance(exc.args[0], str) - and exc.args[0].startswith("Cancelled via cancel scope ") - ): - return True - - if isinstance(exc.__context__, CancelledError): - exc = exc.__context__ - continue - - return False - - -class CancelScope(BaseCancelScope): - def __new__( - cls, *, deadline: float = math.inf, shield: bool = False - ) -> CancelScope: - return object.__new__(cls) - - def __init__(self, deadline: float = math.inf, shield: bool = False): - self._deadline = deadline - self._shield = shield - self._parent_scope: CancelScope | None = None - self._child_scopes: set[CancelScope] = set() - self._cancel_called = False - self._cancel_reason: str | None = None - self._cancelled_caught = False - self._active = False - self._timeout_handle: asyncio.TimerHandle | None = None - self._cancel_handle: asyncio.Handle | None = None - self._tasks: set[asyncio.Task] = set() - self._host_task: asyncio.Task | None = None - if sys.version_info >= (3, 11): - self._pending_uncancellations: int | None = 0 - else: - self._pending_uncancellations = None - - def __enter__(self) -> CancelScope: - if self._active: - raise RuntimeError( - "Each CancelScope may only be used for a single 'with' block" - ) - - self._host_task = host_task = cast(asyncio.Task, current_task()) - self._tasks.add(host_task) - try: - task_state = _task_states[host_task] - except KeyError: - task_state = TaskState(None, self) - _task_states[host_task] = task_state - else: - self._parent_scope = task_state.cancel_scope - task_state.cancel_scope = self - if self._parent_scope is not None: - # If using an eager task factory, the parent scope may not even contain - # the host task - self._parent_scope._child_scopes.add(self) - self._parent_scope._tasks.discard(host_task) - - self._timeout() - self._active = True - - # Start cancelling the host task if the scope was cancelled before entering - if self._cancel_called: - self._deliver_cancellation(self) - - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool: - del exc_tb - - if not self._active: - raise RuntimeError("This cancel scope is not active") - if current_task() is not self._host_task: - raise RuntimeError( - "Attempted to exit cancel scope in a different task than it was " - "entered in" - ) - - assert self._host_task is not None - host_task_state = _task_states.get(self._host_task) - if host_task_state is None or host_task_state.cancel_scope is not self: - raise RuntimeError( - "Attempted to exit a cancel scope that isn't the current tasks's " - "current cancel scope" - ) - - try: - self._active = False - if self._timeout_handle: - self._timeout_handle.cancel() - self._timeout_handle = None - - self._tasks.remove(self._host_task) - if self._parent_scope is not None: - self._parent_scope._child_scopes.remove(self) - self._parent_scope._tasks.add(self._host_task) - - host_task_state.cancel_scope = self._parent_scope - - # Restart the cancellation effort in the closest visible, cancelled parent - # scope if necessary - self._restart_cancellation_in_parent() - - # We only swallow the exception iff it was an AnyIO CancelledError, either - # directly as exc_val or inside an exception group and there are no cancelled - # parent cancel scopes visible to us here - if self._cancel_called and not self._parent_cancellation_is_visible_to_us: - # For each level-cancel() call made on the host task, call uncancel() - while self._pending_uncancellations: - self._host_task.uncancel() - self._pending_uncancellations -= 1 - - # Update cancelled_caught and check for exceptions we must not swallow - if isinstance(exc_val, BaseExceptionGroup): - cancelleds_caught, remaining = exc_val.split( - lambda exc: ( - isinstance(exc, CancelledError) - and is_anyio_cancellation(exc) - ) - ) - - if cancelleds_caught is None: - return False - - self._cancelled_caught = True - - if remaining is None: - return True - - context = remaining.__context__ - try: - # Preserve __cause__ and __suppress_context__ by avoiding `raise - # ... from ...` - raise remaining - finally: - # Preserve __context__ - remaining.__context__ = context - del context - else: - if isinstance(exc_val, CancelledError) and is_anyio_cancellation( - exc_val - ): - self._cancelled_caught = True - return True - else: - return False - else: - if self._pending_uncancellations: - assert self._parent_scope is not None - assert self._parent_scope._pending_uncancellations is not None - self._parent_scope._pending_uncancellations += ( - self._pending_uncancellations - ) - self._pending_uncancellations = 0 - - return False - finally: - self._host_task = None - del exc_val - - @property - def _effectively_cancelled(self) -> bool: - cancel_scope: CancelScope | None = self - while cancel_scope is not None: - if cancel_scope._cancel_called: - return True - - if cancel_scope.shield: - return False - - cancel_scope = cancel_scope._parent_scope - - return False - - @property - def _parent_cancellation_is_visible_to_us(self) -> bool: - return ( - self._parent_scope is not None - and not self.shield - and self._parent_scope._effectively_cancelled - ) - - def _timeout(self) -> None: - if self._deadline != math.inf: - loop = get_running_loop() - if loop.time() >= self._deadline: - self.cancel("deadline exceeded") - else: - self._timeout_handle = loop.call_at(self._deadline, self._timeout) - - def _deliver_cancellation(self, origin: CancelScope) -> bool: - """ - Deliver cancellation to directly contained tasks and nested cancel scopes. - - Schedule another run at the end if we still have tasks eligible for - cancellation. - - :param origin: the cancel scope that originated the cancellation - :return: ``True`` if the delivery needs to be retried on the next cycle - - """ - should_retry = False - current = current_task() - for task in self._tasks: - should_retry = True - if task._must_cancel: # type: ignore[attr-defined] - continue - - # The task is eligible for cancellation if it has started - if task is not current and (task is self._host_task or _task_started(task)): - waiter = task._fut_waiter # type: ignore[attr-defined] - if not isinstance(waiter, asyncio.Future) or not waiter.done(): - task.cancel(origin._cancel_reason) - if ( - task is origin._host_task - and origin._pending_uncancellations is not None - ): - origin._pending_uncancellations += 1 - - # Deliver cancellation to child scopes that aren't shielded or running their own - # cancellation callbacks - for scope in self._child_scopes: - if not scope._shield and not scope.cancel_called: - should_retry = scope._deliver_cancellation(origin) or should_retry - - # Schedule another callback if there are still tasks left - if origin is self: - if should_retry: - self._cancel_handle = get_running_loop().call_soon( - self._deliver_cancellation, origin - ) - else: - self._cancel_handle = None - - return should_retry - - def _restart_cancellation_in_parent(self) -> None: - """ - Restart the cancellation effort in the closest directly cancelled parent scope. - - """ - scope = self._parent_scope - while scope is not None: - if scope._cancel_called: - if scope._cancel_handle is None: - scope._deliver_cancellation(scope) - - break - - # No point in looking beyond any shielded scope - if scope._shield: - break - - scope = scope._parent_scope - - def cancel(self, reason: str | None = None) -> None: - if not self._cancel_called: - if self._timeout_handle: - self._timeout_handle.cancel() - self._timeout_handle = None - - self._cancel_called = True - self._cancel_reason = f"Cancelled via cancel scope {id(self):x}" - if task := current_task(): - self._cancel_reason += f" by {task}" - - if reason: - self._cancel_reason += f"; reason: {reason}" - - if self._host_task is not None: - self._deliver_cancellation(self) - - @property - def deadline(self) -> float: - return self._deadline - - @deadline.setter - def deadline(self, value: float) -> None: - self._deadline = float(value) - if self._timeout_handle is not None: - self._timeout_handle.cancel() - self._timeout_handle = None - - if self._active and not self._cancel_called: - self._timeout() - - @property - def cancel_called(self) -> bool: - return self._cancel_called - - @property - def cancelled_caught(self) -> bool: - return self._cancelled_caught - - @property - def shield(self) -> bool: - return self._shield - - @shield.setter - def shield(self, value: bool) -> None: - if self._shield != value: - self._shield = value - if not value: - self._restart_cancellation_in_parent() - - -# -# Task states -# - - -class TaskState: - """ - Encapsulates auxiliary task information that cannot be added to the Task instance - itself because there are no guarantees about its implementation. - """ - - __slots__ = "parent_id", "cancel_scope", "__weakref__" - - def __init__(self, parent_id: int | None, cancel_scope: CancelScope | None): - self.parent_id = parent_id - self.cancel_scope = cancel_scope - - -_task_states: WeakKeyDictionary[asyncio.Task, TaskState] = WeakKeyDictionary() - - -# -# Task groups -# - - -class _AsyncioTaskStatus(abc.TaskStatus): - def __init__(self, future: asyncio.Future, parent_id: int): - self._future = future - self._parent_id = parent_id - - def started(self, value: T_contra | None = None) -> None: - try: - self._future.set_result(value) - except asyncio.InvalidStateError: - if not self._future.cancelled(): - raise RuntimeError( - "called 'started' twice on the same task status" - ) from None - - task = cast(asyncio.Task, current_task()) - _task_states[task].parent_id = self._parent_id - - -if sys.version_info >= (3, 12): - _eager_task_factory_code: CodeType | None = asyncio.eager_task_factory.__code__ -else: - _eager_task_factory_code = None - - -class TaskGroup(abc.TaskGroup): - def __init__(self) -> None: - self.cancel_scope: CancelScope = CancelScope() - self._active = False - self._exceptions: list[BaseException] = [] - self._tasks: set[asyncio.Task] = set() - self._on_completed_fut: asyncio.Future[None] | None = None - - async def __aenter__(self) -> TaskGroup: - self.cancel_scope.__enter__() - self._active = True - return self - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool: - try: - if exc_val is not None: - self.cancel_scope.cancel() - if not isinstance(exc_val, CancelledError): - self._exceptions.append(exc_val) - - loop = get_running_loop() - try: - if self._tasks: - with CancelScope() as wait_scope: - while self._tasks: - self._on_completed_fut = loop.create_future() - - try: - await self._on_completed_fut - except CancelledError as exc: - # Shield the scope against further cancellation attempts, - # as they're not productive (#695) - wait_scope.shield = True - self.cancel_scope.cancel() - - # Set exc_val from the cancellation exception if it was - # previously unset. However, we should not replace a native - # cancellation exception with one raise by a cancel scope. - if exc_val is None or ( - isinstance(exc_val, CancelledError) - and not is_anyio_cancellation(exc) - ): - exc_val = exc - - self._on_completed_fut = None - else: - # If there are no child tasks to wait on, run at least one checkpoint - # anyway - await AsyncIOBackend.cancel_shielded_checkpoint() - - self._active = False - if self._exceptions: - # The exception that got us here should already have been - # added to self._exceptions so it's ok to break exception - # chaining and avoid adding a "During handling of above..." - # for each nesting level. - raise BaseExceptionGroup( - "unhandled errors in a TaskGroup", self._exceptions - ) from None - elif exc_val: - raise exc_val - except BaseException as exc: - if self.cancel_scope.__exit__(type(exc), exc, exc.__traceback__): - return True - - raise - - return self.cancel_scope.__exit__(exc_type, exc_val, exc_tb) - finally: - del exc_val, exc_tb, self._exceptions - - def _spawn( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], - args: tuple[Unpack[PosArgsT]], - name: object, - task_status_future: asyncio.Future | None = None, - ) -> asyncio.Task: - def task_done(_task: asyncio.Task) -> None: - if sys.version_info >= (3, 14) and self.cancel_scope._host_task is not None: - asyncio.future_discard_from_awaited_by( - _task, self.cancel_scope._host_task - ) - - task_state = _task_states[_task] - assert task_state.cancel_scope is not None - assert _task in task_state.cancel_scope._tasks - task_state.cancel_scope._tasks.remove(_task) - self._tasks.remove(task) - del _task_states[_task] - - if self._on_completed_fut is not None and not self._tasks: - try: - self._on_completed_fut.set_result(None) - except asyncio.InvalidStateError: - pass - - try: - exc = _task.exception() - except CancelledError as e: - while isinstance(e.__context__, CancelledError): - e = e.__context__ - - exc = e - - if exc is not None: - # The future can only be in the cancelled state if the host task was - # cancelled, so return immediately instead of adding one more - # CancelledError to the exceptions list - if task_status_future is not None and task_status_future.cancelled(): - return - - if task_status_future is None or task_status_future.done(): - if not isinstance(exc, CancelledError): - self._exceptions.append(exc) - - if not self.cancel_scope._effectively_cancelled: - self.cancel_scope.cancel() - else: - task_status_future.set_exception(exc) - elif task_status_future is not None and not task_status_future.done(): - task_status_future.set_exception( - RuntimeError("Child exited without calling task_status.started()") - ) - - if not self._active: - raise RuntimeError( - "This task group is not active; no new tasks can be started." - ) - - kwargs = {} - if task_status_future: - parent_id = id(current_task()) - kwargs["task_status"] = _AsyncioTaskStatus( - task_status_future, id(self.cancel_scope._host_task) - ) - else: - parent_id = id(self.cancel_scope._host_task) - - coro = func(*args, **kwargs) - if not iscoroutine(coro): - prefix = f"{func.__module__}." if hasattr(func, "__module__") else "" - raise TypeError( - f"Expected {prefix}{func.__qualname__}() to return a coroutine, but " - f"the return value ({coro!r}) is not a coroutine object" - ) - - name = get_callable_name(func) if name is None else str(name) - loop = asyncio.get_running_loop() - if ( - (factory := loop.get_task_factory()) - and getattr(factory, "__code__", None) is _eager_task_factory_code - and (closure := getattr(factory, "__closure__", None)) - ): - custom_task_constructor = closure[0].cell_contents - task = custom_task_constructor(coro, loop=loop, name=name) - else: - task = create_task(coro, name=name) - - # Make the spawned task inherit the task group's cancel scope - _task_states[task] = TaskState( - parent_id=parent_id, cancel_scope=self.cancel_scope - ) - self.cancel_scope._tasks.add(task) - self._tasks.add(task) - if sys.version_info >= (3, 14) and self.cancel_scope._host_task is not None: - asyncio.future_add_to_awaited_by(task, self.cancel_scope._host_task) - - task.add_done_callback(task_done) - return task - - def start_soon( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], - *args: Unpack[PosArgsT], - name: object = None, - ) -> None: - self._spawn(func, args, name) - - async def start( - self, func: Callable[..., Awaitable[Any]], *args: object, name: object = None - ) -> Any: - future: asyncio.Future = asyncio.Future() - task = self._spawn(func, args, name, future) - - # If the task raises an exception after sending a start value without a switch - # point between, the task group is cancelled and this method never proceeds to - # process the completed future. That's why we have to have a shielded cancel - # scope here. - try: - return await future - except CancelledError: - # Cancel the task and wait for it to exit before returning - task.cancel() - with CancelScope(shield=True), suppress(CancelledError): - await task - - raise - - -# -# Threads -# - -_Retval_Queue_Type = tuple[T_Retval | None, BaseException | None] - - -class WorkerThread(Thread): - MAX_IDLE_TIME = 10 # seconds - - def __init__( - self, - root_task: asyncio.Task, - workers: set[WorkerThread], - idle_workers: deque[WorkerThread], - ): - super().__init__(name="AnyIO worker thread") - self.root_task = root_task - self.workers = workers - self.idle_workers = idle_workers - self.loop = root_task._loop - self.queue: Queue[ - tuple[Context, Callable, tuple, asyncio.Future, CancelScope] | None - ] = Queue(2) - self.idle_since = AsyncIOBackend.current_time() - self.stopping = False - - def _report_result( - self, future: asyncio.Future, result: Any, exc: BaseException | None - ) -> None: - self.idle_since = AsyncIOBackend.current_time() - if not self.stopping: - self.idle_workers.append(self) - - if not future.cancelled(): - if exc is not None: - if isinstance(exc, StopIteration): - new_exc = RuntimeError("coroutine raised StopIteration") - new_exc.__cause__ = exc - exc = new_exc - - future.set_exception(exc) - else: - future.set_result(result) - - def run(self) -> None: - with claim_worker_thread(AsyncIOBackend, self.loop): - while True: - item = self.queue.get() - if item is None: - # Shutdown command received - return - - context, func, args, future, cancel_scope = item - if not future.cancelled(): - result = None - exception: BaseException | None = None - threadlocals.current_cancel_scope = cancel_scope - try: - result = context.run(func, *args) - except BaseException as exc: - exception = exc - finally: - del threadlocals.current_cancel_scope - - if not self.loop.is_closed(): - self.loop.call_soon_threadsafe( - self._report_result, future, result, exception - ) - - del result, exception - - self.queue.task_done() - del item, context, func, args, future, cancel_scope - - def stop(self, f: asyncio.Task | None = None) -> None: - self.stopping = True - self.queue.put_nowait(None) - self.workers.discard(self) - try: - self.idle_workers.remove(self) - except ValueError: - pass - - -_threadpool_idle_workers: RunVar[deque[WorkerThread]] = RunVar( - "_threadpool_idle_workers" -) -_threadpool_workers: RunVar[set[WorkerThread]] = RunVar("_threadpool_workers") - - -# -# Subprocesses -# - - -@dataclass(eq=False) -class StreamReaderWrapper(abc.ByteReceiveStream): - _stream: asyncio.StreamReader - - async def receive(self, max_bytes: int = 65536) -> bytes: - data = await self._stream.read(max_bytes) - if data: - return data - else: - raise EndOfStream - - async def aclose(self) -> None: - self._stream.set_exception(ClosedResourceError()) - await AsyncIOBackend.checkpoint() - - -@dataclass(eq=False) -class StreamWriterWrapper(abc.ByteSendStream): - _stream: asyncio.StreamWriter - _closed: bool = field(init=False, default=False) - - async def send(self, item: bytes) -> None: - await AsyncIOBackend.checkpoint_if_cancelled() - stream_paused = self._stream._protocol._paused # type: ignore[attr-defined] - try: - self._stream.write(item) - await self._stream.drain() - except (ConnectionResetError, BrokenPipeError, RuntimeError) as exc: - # If closed by us and/or the peer: - # * on stdlib, drain() raises ConnectionResetError or BrokenPipeError - # * on uvloop and Winloop, write() eventually starts raising RuntimeError - if self._closed: - raise ClosedResourceError from exc - elif self._stream.is_closing(): - raise BrokenResourceError from exc - - raise - - if not stream_paused: - await AsyncIOBackend.cancel_shielded_checkpoint() - - async def aclose(self) -> None: - self._closed = True - self._stream.close() - await AsyncIOBackend.checkpoint() - - -@dataclass(eq=False) -class Process(abc.Process): - _process: asyncio.subprocess.Process - _stdin: StreamWriterWrapper | None - _stdout: StreamReaderWrapper | None - _stderr: StreamReaderWrapper | None - - async def aclose(self) -> None: - with CancelScope(shield=True) as scope: - if self._stdin: - await self._stdin.aclose() - if self._stdout: - await self._stdout.aclose() - if self._stderr: - await self._stderr.aclose() - - scope.shield = False - try: - await self.wait() - except BaseException: - scope.shield = True - self.kill() - await self.wait() - raise - - async def wait(self) -> int: - return await self._process.wait() - - def terminate(self) -> None: - self._process.terminate() - - def kill(self) -> None: - self._process.kill() - - def send_signal(self, signal: int) -> None: - self._process.send_signal(signal) - - @property - def pid(self) -> int: - return self._process.pid - - @property - def returncode(self) -> int | None: - return self._process.returncode - - @property - def stdin(self) -> abc.ByteSendStream | None: - return self._stdin - - @property - def stdout(self) -> abc.ByteReceiveStream | None: - return self._stdout - - @property - def stderr(self) -> abc.ByteReceiveStream | None: - return self._stderr - - -def _forcibly_shutdown_process_pool_on_exit( - workers: set[Process], _task: object -) -> None: - """ - Forcibly shuts down worker processes belonging to this event loop.""" - child_watcher: asyncio.AbstractChildWatcher | None = None # type: ignore[name-defined] - if sys.version_info < (3, 12): - try: - child_watcher = asyncio.get_event_loop_policy().get_child_watcher() - except NotImplementedError: - pass - - # Close as much as possible (w/o async/await) to avoid warnings - for process in workers.copy(): - if process.returncode is not None: - continue - - process._stdin._stream._transport.close() # type: ignore[union-attr] - process._stdout._stream._transport.close() # type: ignore[union-attr] - process._stderr._stream._transport.close() # type: ignore[union-attr] - process.kill() - if child_watcher: - child_watcher.remove_child_handler(process.pid) - - -async def _shutdown_process_pool_on_exit(workers: set[abc.Process]) -> None: - """ - Shuts down worker processes belonging to this event loop. - - NOTE: this only works when the event loop was started using asyncio.run() or - anyio.run(). - - """ - process: abc.Process - try: - await sleep(math.inf) - except asyncio.CancelledError: - workers = workers.copy() - for process in workers: - if process.returncode is None: - process.kill() - - for process in workers: - await process.aclose() - - -# -# Sockets and networking -# - - -class StreamProtocol(asyncio.Protocol): - read_queue: deque[bytes] - read_event: asyncio.Event - write_event: asyncio.Event - exception: Exception | None = None - is_at_eof: bool = False - - def connection_made(self, transport: asyncio.BaseTransport) -> None: - self.read_queue = deque() - self.read_event = asyncio.Event() - self.write_event = asyncio.Event() - self.write_event.set() - cast(asyncio.Transport, transport).set_write_buffer_limits(0) - - def connection_lost(self, exc: Exception | None) -> None: - if exc: - self.exception = exc - - self.read_event.set() - self.write_event.set() - - def data_received(self, data: bytes) -> None: - # ProactorEventloop sometimes sends bytearray instead of bytes - self.read_queue.append(bytes(data)) - self.read_event.set() - - def eof_received(self) -> bool | None: - self.is_at_eof = True - self.read_event.set() - return True - - def pause_writing(self) -> None: - self.write_event = asyncio.Event() - - def resume_writing(self) -> None: - self.write_event.set() - - -class DatagramProtocol(asyncio.DatagramProtocol): - read_queue: deque[tuple[bytes, IPSockAddrType]] - read_event: asyncio.Event - write_event: asyncio.Event - exception: Exception | None = None - - def connection_made(self, transport: asyncio.BaseTransport) -> None: - self.read_queue = deque(maxlen=100) # arbitrary value - self.read_event = asyncio.Event() - self.write_event = asyncio.Event() - self.write_event.set() - - def connection_lost(self, exc: Exception | None) -> None: - self.read_event.set() - self.write_event.set() - - def datagram_received(self, data: bytes, addr: IPSockAddrType) -> None: - addr = convert_ipv6_sockaddr(addr) - self.read_queue.append((data, addr)) - self.read_event.set() - - def error_received(self, exc: Exception) -> None: - self.exception = exc - - def pause_writing(self) -> None: - self.write_event.clear() - - def resume_writing(self) -> None: - self.write_event.set() - - -class SocketStream(abc.SocketStream): - def __init__(self, transport: asyncio.Transport, protocol: StreamProtocol): - self._transport = transport - self._protocol = protocol - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - self._closed = False - - @property - def _raw_socket(self) -> socket.socket: - return self._transport.get_extra_info("socket") - - async def receive(self, max_bytes: int = 65536) -> bytes: - with self._receive_guard: - if ( - not self._protocol.read_event.is_set() - and not self._transport.is_closing() - and not self._protocol.is_at_eof - ): - self._transport.resume_reading() - await self._protocol.read_event.wait() - self._transport.pause_reading() - else: - await AsyncIOBackend.checkpoint() - - try: - chunk = self._protocol.read_queue.popleft() - except IndexError: - if self._closed: - raise ClosedResourceError from None - elif self._protocol.exception: - raise BrokenResourceError from self._protocol.exception - else: - raise EndOfStream from None - - if len(chunk) > max_bytes: - # Split the oversized chunk - chunk, leftover = chunk[:max_bytes], chunk[max_bytes:] - self._protocol.read_queue.appendleft(leftover) - - # If the read queue is empty, clear the flag so that the next call will - # block until data is available - if not self._protocol.read_queue: - self._protocol.read_event.clear() - - return chunk - - async def send(self, item: bytes) -> None: - with self._send_guard: - await AsyncIOBackend.checkpoint() - - if self._closed: - raise ClosedResourceError - elif self._protocol.exception is not None: - raise BrokenResourceError from self._protocol.exception - - try: - self._transport.write(item) - except RuntimeError as exc: - if self._transport.is_closing(): - raise BrokenResourceError from exc - else: - raise - - await self._protocol.write_event.wait() - - async def send_eof(self) -> None: - try: - self._transport.write_eof() - except OSError: - pass - - async def aclose(self) -> None: - self._closed = True - if not self._transport.is_closing(): - try: - self._transport.write_eof() - except OSError: - pass - - self._transport.close() - await sleep(0) - self._transport.abort() - - -class _RawSocketMixin: - _receive_future: asyncio.Future | None = None - _send_future: asyncio.Future | None = None - _closing = False - - def __init__(self, raw_socket: socket.socket): - self.__raw_socket = raw_socket - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - - @property - def _raw_socket(self) -> socket.socket: - return self.__raw_socket - - def _wait_until_readable(self, loop: asyncio.AbstractEventLoop) -> asyncio.Future: - def callback(f: object) -> None: - del self._receive_future - loop.remove_reader(self.__raw_socket) - - f = self._receive_future = asyncio.Future() - loop.add_reader(self.__raw_socket, f.set_result, None) - f.add_done_callback(callback) - return f - - def _wait_until_writable(self, loop: asyncio.AbstractEventLoop) -> asyncio.Future: - def callback(f: object) -> None: - del self._send_future - loop.remove_writer(self.__raw_socket) - - f = self._send_future = asyncio.Future() - loop.add_writer(self.__raw_socket, f.set_result, None) - f.add_done_callback(callback) - return f - - async def aclose(self) -> None: - if not self._closing: - self._closing = True - if self.__raw_socket.fileno() != -1: - self.__raw_socket.close() - - if self._receive_future: - self._receive_future.set_result(None) - if self._send_future: - self._send_future.set_result(None) - - -class UNIXSocketStream(_RawSocketMixin, abc.UNIXSocketStream): - async def send_eof(self) -> None: - with self._send_guard: - self._raw_socket.shutdown(socket.SHUT_WR) - - async def receive(self, max_bytes: int = 65536) -> bytes: - loop = get_running_loop() - await AsyncIOBackend.checkpoint() - with self._receive_guard: - while True: - try: - data = self._raw_socket.recv(max_bytes) - except BlockingIOError: - await self._wait_until_readable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - else: - if not data: - raise EndOfStream - - return data - - async def send(self, item: bytes) -> None: - loop = get_running_loop() - await AsyncIOBackend.checkpoint() - with self._send_guard: - view = memoryview(item) - while view: - try: - bytes_sent = self._raw_socket.send(view) - except BlockingIOError: - await self._wait_until_writable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - else: - view = view[bytes_sent:] - - async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]: - if not isinstance(msglen, int) or msglen < 0: - raise ValueError("msglen must be a non-negative integer") - if not isinstance(maxfds, int) or maxfds < 1: - raise ValueError("maxfds must be a positive integer") - - loop = get_running_loop() - fds = array.array("i") - await AsyncIOBackend.checkpoint() - with self._receive_guard: - while True: - try: - message, ancdata, flags, addr = self._raw_socket.recvmsg( - msglen, socket.CMSG_LEN(maxfds * fds.itemsize) - ) - except BlockingIOError: - await self._wait_until_readable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - else: - if not message and not ancdata: - raise EndOfStream - - break - - for cmsg_level, cmsg_type, cmsg_data in ancdata: - if cmsg_level != socket.SOL_SOCKET or cmsg_type != socket.SCM_RIGHTS: - raise RuntimeError( - f"Received unexpected ancillary data; message = {message!r}, " - f"cmsg_level = {cmsg_level}, cmsg_type = {cmsg_type}" - ) - - fds.frombytes(cmsg_data[: len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) - - return message, list(fds) - - async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None: - if not message: - raise ValueError("message must not be empty") - if not fds: - raise ValueError("fds must not be empty") - - loop = get_running_loop() - filenos: list[int] = [] - for fd in fds: - if isinstance(fd, int): - filenos.append(fd) - elif isinstance(fd, IOBase): - filenos.append(fd.fileno()) - - fdarray = array.array("i", filenos) - await AsyncIOBackend.checkpoint() - with self._send_guard: - while True: - try: - # The ignore can be removed after mypy picks up - # https://github.com/python/typeshed/pull/5545 - self._raw_socket.sendmsg( - [message], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, fdarray)] - ) - break - except BlockingIOError: - await self._wait_until_writable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - - -class TCPSocketListener(abc.SocketListener): - _accept_scope: CancelScope | None = None - _closed = False - - def __init__(self, raw_socket: socket.socket): - self.__raw_socket = raw_socket - self._loop = cast(asyncio.BaseEventLoop, get_running_loop()) - self._accept_guard = ResourceGuard("accepting connections from") - - @property - def _raw_socket(self) -> socket.socket: - return self.__raw_socket - - async def accept(self) -> abc.SocketStream: - if self._closed: - raise ClosedResourceError - - with self._accept_guard: - await AsyncIOBackend.checkpoint() - with CancelScope() as self._accept_scope: - try: - client_sock, _addr = await self._loop.sock_accept(self._raw_socket) - except asyncio.CancelledError: - # Workaround for https://bugs.python.org/issue41317 - try: - self._loop.remove_reader(self._raw_socket) - except (ValueError, NotImplementedError): - pass - - if self._closed: - raise ClosedResourceError from None - - raise - finally: - self._accept_scope = None - - client_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - transport, protocol = await self._loop.connect_accepted_socket( - StreamProtocol, client_sock - ) - return SocketStream(transport, protocol) - - async def aclose(self) -> None: - if self._closed: - return - - self._closed = True - if self._accept_scope: - # Workaround for https://bugs.python.org/issue41317 - try: - self._loop.remove_reader(self._raw_socket) - except (ValueError, NotImplementedError): - pass - - self._accept_scope.cancel() - await sleep(0) - - self._raw_socket.close() - - -class UNIXSocketListener(abc.SocketListener): - def __init__(self, raw_socket: socket.socket): - self.__raw_socket = raw_socket - self._loop = get_running_loop() - self._accept_guard = ResourceGuard("accepting connections from") - self._closed = False - - async def accept(self) -> abc.SocketStream: - await AsyncIOBackend.checkpoint() - with self._accept_guard: - while True: - try: - client_sock, _ = self.__raw_socket.accept() - client_sock.setblocking(False) - return UNIXSocketStream(client_sock) - except BlockingIOError: - f: asyncio.Future = asyncio.Future() - self._loop.add_reader(self.__raw_socket, f.set_result, None) - f.add_done_callback( - lambda _: self._loop.remove_reader(self.__raw_socket) - ) - await f - except OSError as exc: - if self._closed: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - - async def aclose(self) -> None: - self._closed = True - self.__raw_socket.close() - - @property - def _raw_socket(self) -> socket.socket: - return self.__raw_socket - - -class UDPSocket(abc.UDPSocket): - def __init__( - self, transport: asyncio.DatagramTransport, protocol: DatagramProtocol - ): - self._transport = transport - self._protocol = protocol - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - self._closed = False - - @property - def _raw_socket(self) -> socket.socket: - return self._transport.get_extra_info("socket") - - async def aclose(self) -> None: - self._closed = True - if not self._transport.is_closing(): - self._transport.close() - - async def receive(self) -> tuple[bytes, IPSockAddrType]: - with self._receive_guard: - await AsyncIOBackend.checkpoint() - - # If the buffer is empty, ask for more data - if not self._protocol.read_queue and not self._transport.is_closing(): - self._protocol.read_event.clear() - await self._protocol.read_event.wait() - - try: - return self._protocol.read_queue.popleft() - except IndexError: - if self._closed: - raise ClosedResourceError from None - else: - raise BrokenResourceError from None - - async def send(self, item: UDPPacketType) -> None: - with self._send_guard: - await AsyncIOBackend.checkpoint() - await self._protocol.write_event.wait() - if self._closed: - raise ClosedResourceError - elif self._transport.is_closing(): - raise BrokenResourceError - else: - self._transport.sendto(*item) - - -class ConnectedUDPSocket(abc.ConnectedUDPSocket): - def __init__( - self, transport: asyncio.DatagramTransport, protocol: DatagramProtocol - ): - self._transport = transport - self._protocol = protocol - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - self._closed = False - - @property - def _raw_socket(self) -> socket.socket: - return self._transport.get_extra_info("socket") - - async def aclose(self) -> None: - self._closed = True - if not self._transport.is_closing(): - self._transport.close() - - async def receive(self) -> bytes: - with self._receive_guard: - await AsyncIOBackend.checkpoint() - - # If the buffer is empty, ask for more data - if not self._protocol.read_queue and not self._transport.is_closing(): - self._protocol.read_event.clear() - await self._protocol.read_event.wait() - - try: - packet = self._protocol.read_queue.popleft() - except IndexError: - if self._closed: - raise ClosedResourceError from None - else: - raise BrokenResourceError from None - - return packet[0] - - async def send(self, item: bytes) -> None: - with self._send_guard: - await AsyncIOBackend.checkpoint() - await self._protocol.write_event.wait() - if self._closed: - raise ClosedResourceError - elif self._transport.is_closing(): - raise BrokenResourceError - else: - self._transport.sendto(item) - - -class UNIXDatagramSocket(_RawSocketMixin, abc.UNIXDatagramSocket): - async def receive(self) -> UNIXDatagramPacketType: - loop = get_running_loop() - await AsyncIOBackend.checkpoint() - with self._receive_guard: - while True: - try: - data = self._raw_socket.recvfrom(65536) - except BlockingIOError: - await self._wait_until_readable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - else: - return data - - async def send(self, item: UNIXDatagramPacketType) -> None: - loop = get_running_loop() - await AsyncIOBackend.checkpoint() - with self._send_guard: - while True: - try: - self._raw_socket.sendto(*item) - except BlockingIOError: - await self._wait_until_writable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - else: - return - - -class ConnectedUNIXDatagramSocket(_RawSocketMixin, abc.ConnectedUNIXDatagramSocket): - async def receive(self) -> bytes: - loop = get_running_loop() - await AsyncIOBackend.checkpoint() - with self._receive_guard: - while True: - try: - data = self._raw_socket.recv(65536) - except BlockingIOError: - await self._wait_until_readable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - else: - return data - - async def send(self, item: bytes) -> None: - loop = get_running_loop() - await AsyncIOBackend.checkpoint() - with self._send_guard: - while True: - try: - self._raw_socket.send(item) - except BlockingIOError: - await self._wait_until_writable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - else: - return - - -_read_events: RunVar[dict[int, asyncio.Future[bool]]] = RunVar("read_events") -_write_events: RunVar[dict[int, asyncio.Future[bool]]] = RunVar("write_events") - - -# -# Synchronization -# - - -class Event(BaseEvent): - def __new__(cls) -> Event: - return object.__new__(cls) - - def __init__(self) -> None: - self._event = asyncio.Event() - - def set(self) -> None: - self._event.set() - - def is_set(self) -> bool: - return self._event.is_set() - - async def wait(self) -> None: - if self.is_set(): - await AsyncIOBackend.checkpoint() - else: - await self._event.wait() - - def statistics(self) -> EventStatistics: - return EventStatistics(len(self._event._waiters)) - - -class Lock(BaseLock): - def __new__(cls, *, fast_acquire: bool = False) -> Lock: - return object.__new__(cls) - - def __init__(self, *, fast_acquire: bool = False) -> None: - self._fast_acquire = fast_acquire - self._owner_task: asyncio.Task | None = None - self._waiters: deque[tuple[asyncio.Task, asyncio.Future]] = deque() - - async def acquire(self) -> None: - task = cast(asyncio.Task, current_task()) - if self._owner_task is None and not self._waiters: - await AsyncIOBackend.checkpoint_if_cancelled() - self._owner_task = task - - # Unless on the "fast path", yield control of the event loop so that other - # tasks can run too - if not self._fast_acquire: - try: - await AsyncIOBackend.cancel_shielded_checkpoint() - except CancelledError: - self.release() - raise - - return - - if self._owner_task == task: - raise RuntimeError("Attempted to acquire an already held Lock") - - fut: asyncio.Future[None] = asyncio.Future() - item = task, fut - self._waiters.append(item) - try: - await fut - except CancelledError: - self._waiters.remove(item) - if self._owner_task is task: - self.release() - - raise - - self._waiters.remove(item) - - def acquire_nowait(self) -> None: - task = cast(asyncio.Task, current_task()) - if self._owner_task is None and not self._waiters: - self._owner_task = task - return - - if self._owner_task is task: - raise RuntimeError("Attempted to acquire an already held Lock") - - raise WouldBlock - - def locked(self) -> bool: - return self._owner_task is not None - - def release(self) -> None: - if self._owner_task != current_task(): - raise RuntimeError("The current task is not holding this lock") - - for task, fut in self._waiters: - if not fut.cancelled(): - self._owner_task = task - fut.set_result(None) - return - - self._owner_task = None - - def statistics(self) -> LockStatistics: - task_info = AsyncIOTaskInfo(self._owner_task) if self._owner_task else None - return LockStatistics(self.locked(), task_info, len(self._waiters)) - - -class Semaphore(BaseSemaphore): - def __new__( - cls, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> Semaphore: - return object.__new__(cls) - - def __init__( - self, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ): - super().__init__(initial_value, max_value=max_value) - self._value = initial_value - self._max_value = max_value - self._fast_acquire = fast_acquire - self._waiters: deque[asyncio.Future[None]] = deque() - - async def acquire(self) -> None: - if self._value > 0 and not self._waiters: - await AsyncIOBackend.checkpoint_if_cancelled() - self._value -= 1 - - # Unless on the "fast path", yield control of the event loop so that other - # tasks can run too - if not self._fast_acquire: - try: - await AsyncIOBackend.cancel_shielded_checkpoint() - except CancelledError: - self.release() - raise - - return - - fut: asyncio.Future[None] = asyncio.Future() - self._waiters.append(fut) - try: - await fut - except CancelledError: - try: - self._waiters.remove(fut) - except ValueError: - self.release() - - raise - - def acquire_nowait(self) -> None: - if self._value == 0: - raise WouldBlock - - self._value -= 1 - - def release(self) -> None: - if self._max_value is not None and self._value == self._max_value: - raise ValueError("semaphore released too many times") - - for fut in self._waiters: - if not fut.cancelled(): - fut.set_result(None) - self._waiters.remove(fut) - return - - self._value += 1 - - @property - def value(self) -> int: - return self._value - - @property - def max_value(self) -> int | None: - return self._max_value - - def statistics(self) -> SemaphoreStatistics: - return SemaphoreStatistics(len(self._waiters)) - - -class CapacityLimiter(BaseCapacityLimiter): - _total_tokens: float = 0 - - def __new__(cls, total_tokens: float) -> CapacityLimiter: - return object.__new__(cls) - - def __init__(self, total_tokens: float): - self._borrowers: set[Any] = set() - self._wait_queue: OrderedDict[Any, asyncio.Event] = OrderedDict() - self.total_tokens = total_tokens - - async def __aenter__(self) -> None: - await self.acquire() - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self.release() - - @property - def total_tokens(self) -> float: - return self._total_tokens - - @total_tokens.setter - def total_tokens(self, value: float) -> None: - if not isinstance(value, int) and not math.isinf(value): - raise TypeError("total_tokens must be an int or math.inf") - - if value < 0: - raise ValueError("total_tokens must be >= 0") - - waiters_to_notify = max(value - self._total_tokens, 0) - self._total_tokens = value - - # Notify waiting tasks that they have acquired the limiter - while self._wait_queue and waiters_to_notify: - event = self._wait_queue.popitem(last=False)[1] - event.set() - waiters_to_notify -= 1 - - @property - def borrowed_tokens(self) -> int: - return len(self._borrowers) - - @property - def available_tokens(self) -> float: - return self._total_tokens - len(self._borrowers) - - def _notify_next_waiter(self) -> None: - """Notify the next task in line if this limiter has free capacity now.""" - if self._wait_queue and len(self._borrowers) < self._total_tokens: - event = self._wait_queue.popitem(last=False)[1] - event.set() - - def acquire_nowait(self) -> None: - self.acquire_on_behalf_of_nowait(current_task()) - - def acquire_on_behalf_of_nowait(self, borrower: object) -> None: - if borrower in self._borrowers: - raise RuntimeError( - "this borrower is already holding one of this CapacityLimiter's tokens" - ) - - if self._wait_queue or len(self._borrowers) >= self._total_tokens: - raise WouldBlock - - self._borrowers.add(borrower) - - async def acquire(self) -> None: - return await self.acquire_on_behalf_of(current_task()) - - async def acquire_on_behalf_of(self, borrower: object) -> None: - await AsyncIOBackend.checkpoint_if_cancelled() - try: - self.acquire_on_behalf_of_nowait(borrower) - except WouldBlock: - event = asyncio.Event() - self._wait_queue[borrower] = event - try: - await event.wait() - except BaseException: - self._wait_queue.pop(borrower, None) - if event.is_set(): - self._notify_next_waiter() - - raise - - self._borrowers.add(borrower) - else: - try: - await AsyncIOBackend.cancel_shielded_checkpoint() - except BaseException: - self.release() - raise - - def release(self) -> None: - self.release_on_behalf_of(current_task()) - - def release_on_behalf_of(self, borrower: object) -> None: - try: - self._borrowers.remove(borrower) - except KeyError: - raise RuntimeError( - "this borrower isn't holding any of this CapacityLimiter's tokens" - ) from None - - self._notify_next_waiter() - - def statistics(self) -> CapacityLimiterStatistics: - return CapacityLimiterStatistics( - self.borrowed_tokens, - self.total_tokens, - tuple(self._borrowers), - len(self._wait_queue), - ) - - -_default_thread_limiter: RunVar[CapacityLimiter] = RunVar("_default_thread_limiter") - - -# -# Operating system signals -# - - -class _SignalReceiver: - def __init__(self, signals: tuple[Signals, ...]): - self._signals = signals - self._loop = get_running_loop() - self._signal_queue: deque[Signals] = deque() - self._future: asyncio.Future = asyncio.Future() - self._handled_signals: set[Signals] = set() - - def _deliver(self, signum: Signals) -> None: - self._signal_queue.append(signum) - if not self._future.done(): - self._future.set_result(None) - - def __enter__(self) -> _SignalReceiver: - for sig in set(self._signals): - self._loop.add_signal_handler(sig, self._deliver, sig) - self._handled_signals.add(sig) - - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - for sig in self._handled_signals: - self._loop.remove_signal_handler(sig) - - def __aiter__(self) -> _SignalReceiver: - return self - - async def __anext__(self) -> Signals: - await AsyncIOBackend.checkpoint() - if not self._signal_queue: - self._future = asyncio.Future() - await self._future - - return self._signal_queue.popleft() - - -# -# Testing and debugging -# - - -class AsyncIOTaskInfo(TaskInfo): - def __init__(self, task: asyncio.Task): - task_state = _task_states.get(task) - if task_state is None: - parent_id = None - else: - parent_id = task_state.parent_id - - coro = task.get_coro() - assert coro is not None, "created TaskInfo from a completed Task" - super().__init__(id(task), parent_id, task.get_name(), coro) - self._task = weakref.ref(task) - - def has_pending_cancellation(self) -> bool: - if not (task := self._task()): - # If the task isn't around anymore, it won't have a pending cancellation - return False - - if task._must_cancel: # type: ignore[attr-defined] - return True - elif ( - isinstance(task._fut_waiter, asyncio.Future) # type: ignore[attr-defined] - and task._fut_waiter.cancelled() # type: ignore[attr-defined] - ): - return True - - if task_state := _task_states.get(task): - if cancel_scope := task_state.cancel_scope: - return cancel_scope._effectively_cancelled - - return False - - -class TestRunner(abc.TestRunner): - _send_stream: MemoryObjectSendStream[tuple[Awaitable[Any], asyncio.Future[Any]]] - - def __init__( - self, - *, - debug: bool | None = None, - use_uvloop: bool = False, - loop_factory: Callable[[], AbstractEventLoop] | None = None, - ) -> None: - if use_uvloop and loop_factory is None: - if sys.platform != "win32": - import uvloop - - loop_factory = uvloop.new_event_loop - else: - import winloop - - loop_factory = winloop.new_event_loop - - self._runner = Runner(debug=debug, loop_factory=loop_factory) - self._exceptions: list[BaseException] = [] - self._runner_task: asyncio.Task | None = None - - def __enter__(self) -> TestRunner: - self._runner.__enter__() - self.get_loop().set_exception_handler(self._exception_handler) - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self._runner.__exit__(exc_type, exc_val, exc_tb) - - def get_loop(self) -> AbstractEventLoop: - return self._runner.get_loop() - - def _exception_handler( - self, loop: asyncio.AbstractEventLoop, context: dict[str, Any] - ) -> None: - if isinstance(context.get("exception"), Exception): - self._exceptions.append(context["exception"]) - else: - loop.default_exception_handler(context) - - def _raise_async_exceptions(self) -> None: - # Re-raise any exceptions raised in asynchronous callbacks - if self._exceptions: - exceptions, self._exceptions = self._exceptions, [] - if len(exceptions) == 1: - raise exceptions[0] - elif exceptions: - raise BaseExceptionGroup( - "Multiple exceptions occurred in asynchronous callbacks", exceptions - ) - - async def _run_tests_and_fixtures( - self, - receive_stream: MemoryObjectReceiveStream[ - tuple[Awaitable[T_Retval], asyncio.Future[T_Retval]] - ], - ) -> None: - from _pytest.outcomes import OutcomeException - - with receive_stream, self._send_stream: - async for coro, future in receive_stream: - try: - retval = await coro - except CancelledError as exc: - if not future.cancelled(): - future.cancel(*exc.args) - - raise - except BaseException as exc: - if not future.cancelled(): - future.set_exception(exc) - - if not isinstance(exc, (Exception, OutcomeException)): - raise - else: - if not future.cancelled(): - future.set_result(retval) - - async def _call_in_runner_task( - self, - func: Callable[P, Awaitable[T_Retval]], - /, - *args: P.args, - **kwargs: P.kwargs, - ) -> T_Retval: - if not self._runner_task: - self._send_stream, receive_stream = create_memory_object_stream[ - tuple[Awaitable[Any], asyncio.Future] - ](1) - self._runner_task = self.get_loop().create_task( - self._run_tests_and_fixtures(receive_stream) - ) - - coro = func(*args, **kwargs) - future: asyncio.Future[T_Retval] = self.get_loop().create_future() - self._send_stream.send_nowait((coro, future)) - return await future - - def run_asyncgen_fixture( - self, - fixture_func: Callable[..., AsyncGenerator[T_Retval, Any]], - kwargs: dict[str, Any], - ) -> Iterable[T_Retval]: - asyncgen = fixture_func(**kwargs) - fixturevalue: T_Retval = self.get_loop().run_until_complete( - self._call_in_runner_task(asyncgen.asend, None) - ) - self._raise_async_exceptions() - - yield fixturevalue - - try: - self.get_loop().run_until_complete( - self._call_in_runner_task(asyncgen.asend, None) - ) - except StopAsyncIteration: - self._raise_async_exceptions() - else: - self.get_loop().run_until_complete(asyncgen.aclose()) - raise RuntimeError("Async generator fixture did not stop") - - def run_fixture( - self, - fixture_func: Callable[..., Coroutine[Any, Any, T_Retval]], - kwargs: dict[str, Any], - ) -> T_Retval: - retval = self.get_loop().run_until_complete( - self._call_in_runner_task(fixture_func, **kwargs) - ) - self._raise_async_exceptions() - return retval - - def run_test( - self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any] - ) -> None: - try: - self.get_loop().run_until_complete( - self._call_in_runner_task(test_func, **kwargs) - ) - except Exception as exc: - self._exceptions.append(exc) - - self._raise_async_exceptions() - - -class AsyncIOBackend(AsyncBackend): - @classmethod - def run( - cls, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - args: tuple[Unpack[PosArgsT]], - kwargs: dict[str, Any], - options: dict[str, Any], - ) -> T_Retval: - @wraps(func) - async def wrapper() -> T_Retval: - task = cast(asyncio.Task, current_task()) - task.set_name(get_callable_name(func)) - _task_states[task] = TaskState(None, None) - - try: - return await func(*args) - finally: - del _task_states[task] - - debug = options.get("debug", None) - loop_factory = options.get("loop_factory", None) - if loop_factory is None and options.get("use_uvloop", False): - if sys.platform != "win32": - import uvloop - - loop_factory = uvloop.new_event_loop - else: - import winloop - - loop_factory = winloop.new_event_loop - - with Runner(debug=debug, loop_factory=loop_factory) as runner: - return runner.run(wrapper()) - - @classmethod - def current_token(cls) -> object: - return get_running_loop() - - @classmethod - def current_time(cls) -> float: - return get_running_loop().time() - - @classmethod - def cancelled_exception_class(cls) -> type[BaseException]: - return CancelledError - - @classmethod - async def checkpoint(cls) -> None: - await sleep(0) - - @classmethod - async def checkpoint_if_cancelled(cls) -> None: - task = current_task() - if task is None: - return - - try: - cancel_scope = _task_states[task].cancel_scope - except KeyError: - return - - while cancel_scope: - if cancel_scope.cancel_called: - await sleep(0) - elif cancel_scope.shield: - break - else: - cancel_scope = cancel_scope._parent_scope - - @classmethod - async def cancel_shielded_checkpoint(cls) -> None: - with CancelScope(shield=True): - await sleep(0) - - @classmethod - async def sleep(cls, delay: float) -> None: - await sleep(delay) - - @classmethod - def create_cancel_scope( - cls, *, deadline: float = math.inf, shield: bool = False - ) -> CancelScope: - return CancelScope(deadline=deadline, shield=shield) - - @classmethod - def current_effective_deadline(cls) -> float: - if (task := current_task()) is None: - return math.inf - - try: - cancel_scope = _task_states[task].cancel_scope - except KeyError: - return math.inf - - deadline = math.inf - while cancel_scope: - deadline = min(deadline, cancel_scope.deadline) - if cancel_scope._cancel_called: - deadline = -math.inf - break - elif cancel_scope.shield: - break - else: - cancel_scope = cancel_scope._parent_scope - - return deadline - - @classmethod - def create_task_group(cls) -> abc.TaskGroup: - return TaskGroup() - - @classmethod - def create_event(cls) -> abc.Event: - return Event() - - @classmethod - def create_lock(cls, *, fast_acquire: bool) -> abc.Lock: - return Lock(fast_acquire=fast_acquire) - - @classmethod - def create_semaphore( - cls, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> abc.Semaphore: - return Semaphore(initial_value, max_value=max_value, fast_acquire=fast_acquire) - - @classmethod - def create_capacity_limiter(cls, total_tokens: float) -> abc.CapacityLimiter: - return CapacityLimiter(total_tokens) - - @classmethod - async def run_sync_in_worker_thread( # type: ignore[return] - cls, - func: Callable[[Unpack[PosArgsT]], T_Retval], - args: tuple[Unpack[PosArgsT]], - abandon_on_cancel: bool = False, - limiter: abc.CapacityLimiter | None = None, - ) -> T_Retval: - await cls.checkpoint() - - # If this is the first run in this event loop thread, set up the necessary - # variables - try: - idle_workers = _threadpool_idle_workers.get() - workers = _threadpool_workers.get() - except LookupError: - idle_workers = deque() - workers = set() - _threadpool_idle_workers.set(idle_workers) - _threadpool_workers.set(workers) - - async with limiter or cls.current_default_thread_limiter(): - with CancelScope(shield=not abandon_on_cancel) as scope: - future = asyncio.Future[T_Retval]() - root_task = find_root_task() - if not idle_workers: - worker = WorkerThread(root_task, workers, idle_workers) - worker.start() - workers.add(worker) - root_task.add_done_callback( - worker.stop, context=contextvars.Context() - ) - else: - worker = idle_workers.pop() - - # Prune any other workers that have been idle for MAX_IDLE_TIME - # seconds or longer - now = cls.current_time() - while idle_workers: - if ( - now - idle_workers[0].idle_since - < WorkerThread.MAX_IDLE_TIME - ): - break - - expired_worker = idle_workers.popleft() - expired_worker.root_task.remove_done_callback( - expired_worker.stop - ) - expired_worker.stop() - - context = copy_context() - context.run(set_current_async_library, None) - if abandon_on_cancel or scope._parent_scope is None: - worker_scope = scope - else: - worker_scope = scope._parent_scope - - worker.queue.put_nowait((context, func, args, future, worker_scope)) - return await future - - @classmethod - def check_cancelled(cls) -> None: - scope: CancelScope | None = threadlocals.current_cancel_scope - while scope is not None: - if scope.cancel_called: - raise CancelledError(f"Cancelled by cancel scope {id(scope):x}") - - if scope.shield: - return - - scope = scope._parent_scope - - @classmethod - def run_async_from_thread( - cls, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - args: tuple[Unpack[PosArgsT]], - token: object, - ) -> T_Retval: - async def task_wrapper() -> T_Retval: - __tracebackhide__ = True - if scope is not None: - task = cast(asyncio.Task, current_task()) - _task_states[task] = TaskState(None, scope) - scope._tasks.add(task) - try: - return await func(*args) - except CancelledError as exc: - raise concurrent.futures.CancelledError(str(exc)) from None - finally: - if scope is not None: - scope._tasks.discard(task) - - loop = cast( - "AbstractEventLoop", token or threadlocals.current_token.native_token - ) - if loop.is_closed(): - raise RunFinishedError - - context = copy_context() - context.run(set_current_async_library, "asyncio") - scope = getattr(threadlocals, "current_cancel_scope", None) - f: concurrent.futures.Future[T_Retval] = context.run( - asyncio.run_coroutine_threadsafe, task_wrapper(), loop=loop - ) - return f.result() - - @classmethod - def run_sync_from_thread( - cls, - func: Callable[[Unpack[PosArgsT]], T_Retval], - args: tuple[Unpack[PosArgsT]], - token: object, - ) -> T_Retval: - @wraps(func) - def wrapper() -> None: - try: - set_current_async_library("asyncio") - f.set_result(func(*args)) - except BaseException as exc: - f.set_exception(exc) - if not isinstance(exc, Exception): - raise - - loop = cast( - "AbstractEventLoop", token or threadlocals.current_token.native_token - ) - if loop.is_closed(): - raise RunFinishedError - - f: concurrent.futures.Future[T_Retval] = Future() - loop.call_soon_threadsafe(wrapper) - return f.result() - - @classmethod - async def open_process( - cls, - command: StrOrBytesPath | Sequence[StrOrBytesPath], - *, - stdin: int | IO[Any] | None, - stdout: int | IO[Any] | None, - stderr: int | IO[Any] | None, - **kwargs: Any, - ) -> Process: - await cls.checkpoint() - if isinstance(command, PathLike): - command = os.fspath(command) - - if isinstance(command, (str, bytes)): - process = await asyncio.create_subprocess_shell( - command, - stdin=stdin, - stdout=stdout, - stderr=stderr, - **kwargs, - ) - else: - process = await asyncio.create_subprocess_exec( - *command, - stdin=stdin, - stdout=stdout, - stderr=stderr, - **kwargs, - ) - - stdin_stream = StreamWriterWrapper(process.stdin) if process.stdin else None - stdout_stream = StreamReaderWrapper(process.stdout) if process.stdout else None - stderr_stream = StreamReaderWrapper(process.stderr) if process.stderr else None - return Process(process, stdin_stream, stdout_stream, stderr_stream) - - @classmethod - def setup_process_pool_exit_at_shutdown(cls, workers: set[abc.Process]) -> None: - create_task( - _shutdown_process_pool_on_exit(workers), - name="AnyIO process pool shutdown task", - ) - find_root_task().add_done_callback( - partial(_forcibly_shutdown_process_pool_on_exit, workers) # type:ignore[arg-type] - ) - - @classmethod - async def connect_tcp( - cls, host: str, port: int, local_address: IPSockAddrType | None = None - ) -> abc.SocketStream: - transport, protocol = cast( - tuple[asyncio.Transport, StreamProtocol], - await get_running_loop().create_connection( - StreamProtocol, host, port, local_addr=local_address - ), - ) - transport.pause_reading() - return SocketStream(transport, protocol) - - @classmethod - async def connect_unix(cls, path: str | bytes) -> abc.UNIXSocketStream: - await cls.checkpoint() - loop = get_running_loop() - raw_socket = socket.socket(socket.AF_UNIX) - raw_socket.setblocking(False) - while True: - try: - raw_socket.connect(path) - except BlockingIOError: - f: asyncio.Future = asyncio.Future() - loop.add_writer(raw_socket, f.set_result, None) - f.add_done_callback(lambda _: loop.remove_writer(raw_socket)) - await f - except BaseException: - raw_socket.close() - raise - else: - return UNIXSocketStream(raw_socket) - - @classmethod - def create_tcp_listener(cls, sock: socket.socket) -> SocketListener: - return TCPSocketListener(sock) - - @classmethod - def create_unix_listener(cls, sock: socket.socket) -> SocketListener: - return UNIXSocketListener(sock) - - @classmethod - async def create_udp_socket( - cls, - family: AddressFamily, - local_address: IPSockAddrType | None, - remote_address: IPSockAddrType | None, - reuse_port: bool, - ) -> UDPSocket | ConnectedUDPSocket: - transport, protocol = await get_running_loop().create_datagram_endpoint( - DatagramProtocol, - local_addr=local_address, - remote_addr=remote_address, - family=family, - reuse_port=reuse_port, - ) - if protocol.exception: - transport.close() - raise protocol.exception - - if not remote_address: - return UDPSocket(transport, protocol) - else: - return ConnectedUDPSocket(transport, protocol) - - @classmethod - async def create_unix_datagram_socket( # type: ignore[override] - cls, raw_socket: socket.socket, remote_path: str | bytes | None - ) -> abc.UNIXDatagramSocket | abc.ConnectedUNIXDatagramSocket: - await cls.checkpoint() - loop = get_running_loop() - - if remote_path: - while True: - try: - raw_socket.connect(remote_path) - except BlockingIOError: - f: asyncio.Future = asyncio.Future() - loop.add_writer(raw_socket, f.set_result, None) - f.add_done_callback(lambda _: loop.remove_writer(raw_socket)) - await f - except BaseException: - raw_socket.close() - raise - else: - return ConnectedUNIXDatagramSocket(raw_socket) - else: - return UNIXDatagramSocket(raw_socket) - - @classmethod - async def getaddrinfo( - cls, - host: bytes | str | None, - port: str | int | None, - *, - family: int | AddressFamily = 0, - type: int | SocketKind = 0, - proto: int = 0, - flags: int = 0, - ) -> Sequence[ - tuple[ - AddressFamily, - SocketKind, - int, - str, - tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes], - ] - ]: - return await get_running_loop().getaddrinfo( - host, port, family=family, type=type, proto=proto, flags=flags - ) - - @classmethod - async def getnameinfo( - cls, sockaddr: IPSockAddrType, flags: int = 0 - ) -> tuple[str, str]: - return await get_running_loop().getnameinfo(sockaddr, flags) - - @classmethod - async def wait_readable(cls, obj: FileDescriptorLike) -> None: - try: - read_events = _read_events.get() - except LookupError: - read_events = {} - _read_events.set(read_events) - - fd = obj if isinstance(obj, int) else obj.fileno() - if read_events.get(fd): - raise BusyResourceError("reading from") - - loop = get_running_loop() - fut: asyncio.Future[bool] = loop.create_future() - - def cb() -> None: - try: - del read_events[fd] - except KeyError: - pass - else: - remove_reader(fd) - - try: - fut.set_result(True) - except asyncio.InvalidStateError: - pass - - try: - loop.add_reader(fd, cb) - except NotImplementedError: - from anyio._core._asyncio_selector_thread import get_selector - - selector = get_selector() - selector.add_reader(fd, cb) - remove_reader = selector.remove_reader - else: - remove_reader = loop.remove_reader - - read_events[fd] = fut - try: - success = await fut - finally: - try: - del read_events[fd] - except KeyError: - pass - else: - remove_reader(fd) - - if not success: - raise ClosedResourceError - - @classmethod - async def wait_writable(cls, obj: FileDescriptorLike) -> None: - try: - write_events = _write_events.get() - except LookupError: - write_events = {} - _write_events.set(write_events) - - fd = obj if isinstance(obj, int) else obj.fileno() - if write_events.get(fd): - raise BusyResourceError("writing to") - - loop = get_running_loop() - fut: asyncio.Future[bool] = loop.create_future() - - def cb() -> None: - try: - del write_events[fd] - except KeyError: - pass - else: - remove_writer(fd) - - try: - fut.set_result(True) - except asyncio.InvalidStateError: - pass - - try: - loop.add_writer(fd, cb) - except NotImplementedError: - from anyio._core._asyncio_selector_thread import get_selector - - selector = get_selector() - selector.add_writer(fd, cb) - remove_writer = selector.remove_writer - else: - remove_writer = loop.remove_writer - - write_events[fd] = fut - try: - success = await fut - finally: - try: - del write_events[fd] - except KeyError: - pass - else: - remove_writer(fd) - - if not success: - raise ClosedResourceError - - @classmethod - def notify_closing(cls, obj: FileDescriptorLike) -> None: - fd = obj if isinstance(obj, int) else obj.fileno() - loop = get_running_loop() - - try: - write_events = _write_events.get() - except LookupError: - pass - else: - try: - fut = write_events.pop(fd) - except KeyError: - pass - else: - try: - fut.set_result(False) - except asyncio.InvalidStateError: - pass - - try: - loop.remove_writer(fd) - except NotImplementedError: - from anyio._core._asyncio_selector_thread import get_selector - - get_selector().remove_writer(fd) - - try: - read_events = _read_events.get() - except LookupError: - pass - else: - try: - fut = read_events.pop(fd) - except KeyError: - pass - else: - try: - fut.set_result(False) - except asyncio.InvalidStateError: - pass - - try: - loop.remove_reader(fd) - except NotImplementedError: - from anyio._core._asyncio_selector_thread import get_selector - - get_selector().remove_reader(fd) - - @classmethod - async def wrap_listener_socket(cls, sock: socket.socket) -> SocketListener: - return TCPSocketListener(sock) - - @classmethod - async def wrap_stream_socket(cls, sock: socket.socket) -> SocketStream: - transport, protocol = await get_running_loop().create_connection( - StreamProtocol, sock=sock - ) - return SocketStream(transport, protocol) - - @classmethod - async def wrap_unix_stream_socket(cls, sock: socket.socket) -> UNIXSocketStream: - return UNIXSocketStream(sock) - - @classmethod - async def wrap_udp_socket(cls, sock: socket.socket) -> UDPSocket: - transport, protocol = await get_running_loop().create_datagram_endpoint( - DatagramProtocol, sock=sock - ) - return UDPSocket(transport, protocol) - - @classmethod - async def wrap_connected_udp_socket(cls, sock: socket.socket) -> ConnectedUDPSocket: - transport, protocol = await get_running_loop().create_datagram_endpoint( - DatagramProtocol, sock=sock - ) - return ConnectedUDPSocket(transport, protocol) - - @classmethod - async def wrap_unix_datagram_socket(cls, sock: socket.socket) -> UNIXDatagramSocket: - return UNIXDatagramSocket(sock) - - @classmethod - async def wrap_connected_unix_datagram_socket( - cls, sock: socket.socket - ) -> ConnectedUNIXDatagramSocket: - return ConnectedUNIXDatagramSocket(sock) - - @classmethod - def current_default_thread_limiter(cls) -> CapacityLimiter: - try: - return _default_thread_limiter.get() - except LookupError: - limiter = CapacityLimiter(40) - _default_thread_limiter.set(limiter) - return limiter - - @classmethod - def open_signal_receiver( - cls, *signals: Signals - ) -> AbstractContextManager[AsyncIterator[Signals]]: - return _SignalReceiver(signals) - - @classmethod - def get_current_task(cls) -> TaskInfo: - return AsyncIOTaskInfo(current_task()) # type: ignore[arg-type] - - @classmethod - def get_running_tasks(cls) -> Sequence[TaskInfo]: - return [AsyncIOTaskInfo(task) for task in all_tasks() if not task.done()] - - @classmethod - async def wait_all_tasks_blocked(cls) -> None: - await cls.checkpoint() - this_task = current_task() - while True: - for task in all_tasks(): - if task is this_task: - continue - - waiter = task._fut_waiter # type: ignore[attr-defined] - if waiter is None or waiter.done(): - await sleep(0.1) - break - else: - return - - @classmethod - def create_test_runner(cls, options: dict[str, Any]) -> TestRunner: - return TestRunner(**options) - - -backend_class = AsyncIOBackend diff --git a/notification-service/venv/Lib/site-packages/anyio/_backends/_trio.py b/notification-service/venv/Lib/site-packages/anyio/_backends/_trio.py deleted file mode 100644 index b85a10a..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_backends/_trio.py +++ /dev/null @@ -1,1343 +0,0 @@ -from __future__ import annotations - -import array -import math -import os -import socket -import sys -import types -import weakref -from collections.abc import ( - AsyncGenerator, - AsyncIterator, - Awaitable, - Callable, - Collection, - Coroutine, - Iterable, - Sequence, -) -from contextlib import AbstractContextManager -from dataclasses import dataclass -from io import IOBase -from os import PathLike -from signal import Signals -from socket import AddressFamily, SocketKind -from types import TracebackType -from typing import ( - IO, - TYPE_CHECKING, - Any, - Generic, - NoReturn, - ParamSpec, - TypeVar, - cast, - overload, -) - -import trio.from_thread -import trio.lowlevel -from outcome import Error, Outcome, Value -from trio.lowlevel import ( - current_root_task, - current_task, - notify_closing, - wait_readable, - wait_writable, -) -from trio.socket import SocketType as TrioSocketType -from trio.to_thread import run_sync - -from .. import ( - CapacityLimiterStatistics, - EventStatistics, - LockStatistics, - RunFinishedError, - TaskInfo, - WouldBlock, - abc, -) -from .._core._eventloop import claim_worker_thread -from .._core._exceptions import ( - BrokenResourceError, - BusyResourceError, - ClosedResourceError, - EndOfStream, -) -from .._core._sockets import convert_ipv6_sockaddr -from .._core._streams import create_memory_object_stream -from .._core._synchronization import ( - CapacityLimiter as BaseCapacityLimiter, -) -from .._core._synchronization import Event as BaseEvent -from .._core._synchronization import Lock as BaseLock -from .._core._synchronization import ( - ResourceGuard, - SemaphoreStatistics, -) -from .._core._synchronization import Semaphore as BaseSemaphore -from .._core._tasks import CancelScope as BaseCancelScope -from ..abc import IPSockAddrType, UDPPacketType, UNIXDatagramPacketType -from ..abc._eventloop import AsyncBackend, StrOrBytesPath -from ..streams.memory import MemoryObjectSendStream - -if TYPE_CHECKING: - from _typeshed import FileDescriptorLike - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from exceptiongroup import BaseExceptionGroup - from typing_extensions import TypeVarTuple, Unpack - -T = TypeVar("T") -T_Retval = TypeVar("T_Retval") -T_SockAddr = TypeVar("T_SockAddr", str, IPSockAddrType) -PosArgsT = TypeVarTuple("PosArgsT") -P = ParamSpec("P") - - -# -# Event loop -# - -RunVar = trio.lowlevel.RunVar - - -# -# Timeouts and cancellation -# - - -class CancelScope(BaseCancelScope): - def __new__( - cls, original: trio.CancelScope | None = None, **kwargs: object - ) -> CancelScope: - return object.__new__(cls) - - def __init__(self, original: trio.CancelScope | None = None, **kwargs: Any) -> None: - self.__original = original or trio.CancelScope(**kwargs) - - def __enter__(self) -> CancelScope: - self.__original.__enter__() - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool: - return self.__original.__exit__(exc_type, exc_val, exc_tb) - - def cancel(self, reason: str | None = None) -> None: - self.__original.cancel(reason) - - @property - def deadline(self) -> float: - return self.__original.deadline - - @deadline.setter - def deadline(self, value: float) -> None: - self.__original.deadline = value - - @property - def cancel_called(self) -> bool: - return self.__original.cancel_called - - @property - def cancelled_caught(self) -> bool: - return self.__original.cancelled_caught - - @property - def shield(self) -> bool: - return self.__original.shield - - @shield.setter - def shield(self, value: bool) -> None: - self.__original.shield = value - - -# -# Task groups -# - - -class TaskGroup(abc.TaskGroup): - def __init__(self) -> None: - self._active = False - self._nursery_manager = trio.open_nursery(strict_exception_groups=True) - self.cancel_scope = None # type: ignore[assignment] - - async def __aenter__(self) -> TaskGroup: - self._active = True - self._nursery = await self._nursery_manager.__aenter__() - self.cancel_scope = CancelScope(self._nursery.cancel_scope) - return self - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool: - try: - # trio.Nursery.__exit__ returns bool; .open_nursery has wrong type - return await self._nursery_manager.__aexit__(exc_type, exc_val, exc_tb) # type: ignore[return-value] - except BaseExceptionGroup as exc: - if not exc.split(trio.Cancelled)[1]: - raise trio.Cancelled._create() from exc - - raise - finally: - del exc_val, exc_tb - self._active = False - - def start_soon( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], - *args: Unpack[PosArgsT], - name: object = None, - ) -> None: - if not self._active: - raise RuntimeError( - "This task group is not active; no new tasks can be started." - ) - - self._nursery.start_soon(func, *args, name=name) - - async def start( - self, func: Callable[..., Awaitable[Any]], *args: object, name: object = None - ) -> Any: - if not self._active: - raise RuntimeError( - "This task group is not active; no new tasks can be started." - ) - - return await self._nursery.start(func, *args, name=name) - - -# -# Subprocesses -# - - -@dataclass(eq=False) -class ReceiveStreamWrapper(abc.ByteReceiveStream): - _stream: trio.abc.ReceiveStream - - async def receive(self, max_bytes: int | None = None) -> bytes: - try: - data = await self._stream.receive_some(max_bytes) - except trio.ClosedResourceError as exc: - raise ClosedResourceError from exc.__cause__ - except trio.BrokenResourceError as exc: - raise BrokenResourceError from exc.__cause__ - - if data: - return bytes(data) - else: - raise EndOfStream - - async def aclose(self) -> None: - await self._stream.aclose() - - -@dataclass(eq=False) -class SendStreamWrapper(abc.ByteSendStream): - _stream: trio.abc.SendStream - - async def send(self, item: bytes) -> None: - try: - await self._stream.send_all(item) - except trio.ClosedResourceError as exc: - raise ClosedResourceError from exc.__cause__ - except trio.BrokenResourceError as exc: - raise BrokenResourceError from exc.__cause__ - - async def aclose(self) -> None: - await self._stream.aclose() - - -@dataclass(eq=False) -class Process(abc.Process): - _process: trio.Process - _stdin: abc.ByteSendStream | None - _stdout: abc.ByteReceiveStream | None - _stderr: abc.ByteReceiveStream | None - - async def aclose(self) -> None: - with CancelScope(shield=True): - if self._stdin: - await self._stdin.aclose() - if self._stdout: - await self._stdout.aclose() - if self._stderr: - await self._stderr.aclose() - - try: - await self.wait() - except BaseException: - self.kill() - with CancelScope(shield=True): - await self.wait() - raise - - async def wait(self) -> int: - return await self._process.wait() - - def terminate(self) -> None: - self._process.terminate() - - def kill(self) -> None: - self._process.kill() - - def send_signal(self, signal: Signals) -> None: - self._process.send_signal(signal) - - @property - def pid(self) -> int: - return self._process.pid - - @property - def returncode(self) -> int | None: - return self._process.returncode - - @property - def stdin(self) -> abc.ByteSendStream | None: - return self._stdin - - @property - def stdout(self) -> abc.ByteReceiveStream | None: - return self._stdout - - @property - def stderr(self) -> abc.ByteReceiveStream | None: - return self._stderr - - -class _ProcessPoolShutdownInstrument(trio.abc.Instrument): - def after_run(self) -> None: - super().after_run() - - -current_default_worker_process_limiter: trio.lowlevel.RunVar = RunVar( - "current_default_worker_process_limiter" -) - - -async def _shutdown_process_pool(workers: set[abc.Process]) -> None: - try: - await trio.sleep(math.inf) - except trio.Cancelled: - for process in workers: - if process.returncode is None: - process.kill() - - with CancelScope(shield=True): - for process in workers: - await process.aclose() - - -# -# Sockets and networking -# - - -class _TrioSocketMixin(Generic[T_SockAddr]): - def __init__(self, trio_socket: TrioSocketType) -> None: - self._trio_socket = trio_socket - self._closed = False - - def _check_closed(self) -> None: - if self._closed: - raise ClosedResourceError - if self._trio_socket.fileno() < 0: - raise BrokenResourceError - - @property - def _raw_socket(self) -> socket.socket: - return self._trio_socket._sock # type: ignore[attr-defined] - - async def aclose(self) -> None: - if self._trio_socket.fileno() >= 0: - self._closed = True - self._trio_socket.close() - - def _convert_socket_error(self, exc: BaseException) -> NoReturn: - if isinstance(exc, trio.ClosedResourceError): - raise ClosedResourceError from exc - elif self._trio_socket.fileno() < 0 and self._closed: - raise ClosedResourceError from None - elif isinstance(exc, OSError): - raise BrokenResourceError from exc - else: - raise exc - - -class SocketStream(_TrioSocketMixin, abc.SocketStream): - def __init__(self, trio_socket: TrioSocketType) -> None: - super().__init__(trio_socket) - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - - async def receive(self, max_bytes: int = 65536) -> bytes: - with self._receive_guard: - try: - data = await self._trio_socket.recv(max_bytes) - except BaseException as exc: - self._convert_socket_error(exc) - - if data: - return data - else: - raise EndOfStream - - async def send(self, item: bytes) -> None: - with self._send_guard: - view = memoryview(item) - while view: - try: - bytes_sent = await self._trio_socket.send(view) - except BaseException as exc: - self._convert_socket_error(exc) - - view = view[bytes_sent:] - - async def send_eof(self) -> None: - self._trio_socket.shutdown(socket.SHUT_WR) - - -class UNIXSocketStream(SocketStream, abc.UNIXSocketStream): - async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]: - if not isinstance(msglen, int) or msglen < 0: - raise ValueError("msglen must be a non-negative integer") - if not isinstance(maxfds, int) or maxfds < 1: - raise ValueError("maxfds must be a positive integer") - - fds = array.array("i") - await trio.lowlevel.checkpoint() - with self._receive_guard: - while True: - try: - message, ancdata, flags, addr = await self._trio_socket.recvmsg( - msglen, socket.CMSG_LEN(maxfds * fds.itemsize) - ) - except BaseException as exc: - self._convert_socket_error(exc) - else: - if not message and not ancdata: - raise EndOfStream - - break - - for cmsg_level, cmsg_type, cmsg_data in ancdata: - if cmsg_level != socket.SOL_SOCKET or cmsg_type != socket.SCM_RIGHTS: - raise RuntimeError( - f"Received unexpected ancillary data; message = {message!r}, " - f"cmsg_level = {cmsg_level}, cmsg_type = {cmsg_type}" - ) - - fds.frombytes(cmsg_data[: len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) - - return message, list(fds) - - async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None: - if not message: - raise ValueError("message must not be empty") - if not fds: - raise ValueError("fds must not be empty") - - filenos: list[int] = [] - for fd in fds: - if isinstance(fd, int): - filenos.append(fd) - elif isinstance(fd, IOBase): - filenos.append(fd.fileno()) - - fdarray = array.array("i", filenos) - await trio.lowlevel.checkpoint() - with self._send_guard: - while True: - try: - await self._trio_socket.sendmsg( - [message], - [ - ( - socket.SOL_SOCKET, - socket.SCM_RIGHTS, - fdarray, - ) - ], - ) - break - except BaseException as exc: - self._convert_socket_error(exc) - - -class TCPSocketListener(_TrioSocketMixin, abc.SocketListener): - def __init__(self, raw_socket: socket.socket): - super().__init__(trio.socket.from_stdlib_socket(raw_socket)) - self._accept_guard = ResourceGuard("accepting connections from") - - async def accept(self) -> SocketStream: - with self._accept_guard: - try: - trio_socket, _addr = await self._trio_socket.accept() - except BaseException as exc: - self._convert_socket_error(exc) - - trio_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - return SocketStream(trio_socket) - - -class UNIXSocketListener(_TrioSocketMixin, abc.SocketListener): - def __init__(self, raw_socket: socket.socket): - super().__init__(trio.socket.from_stdlib_socket(raw_socket)) - self._accept_guard = ResourceGuard("accepting connections from") - - async def accept(self) -> UNIXSocketStream: - with self._accept_guard: - try: - trio_socket, _addr = await self._trio_socket.accept() - except BaseException as exc: - self._convert_socket_error(exc) - - return UNIXSocketStream(trio_socket) - - -class UDPSocket(_TrioSocketMixin[IPSockAddrType], abc.UDPSocket): - def __init__(self, trio_socket: TrioSocketType) -> None: - super().__init__(trio_socket) - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - - async def receive(self) -> tuple[bytes, IPSockAddrType]: - with self._receive_guard: - try: - data, addr = await self._trio_socket.recvfrom(65536) - return data, convert_ipv6_sockaddr(addr) - except BaseException as exc: - self._convert_socket_error(exc) - - async def send(self, item: UDPPacketType) -> None: - with self._send_guard: - try: - await self._trio_socket.sendto(*item) - except BaseException as exc: - self._convert_socket_error(exc) - - -class ConnectedUDPSocket(_TrioSocketMixin[IPSockAddrType], abc.ConnectedUDPSocket): - def __init__(self, trio_socket: TrioSocketType) -> None: - super().__init__(trio_socket) - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - - async def receive(self) -> bytes: - with self._receive_guard: - try: - return await self._trio_socket.recv(65536) - except BaseException as exc: - self._convert_socket_error(exc) - - async def send(self, item: bytes) -> None: - with self._send_guard: - try: - await self._trio_socket.send(item) - except BaseException as exc: - self._convert_socket_error(exc) - - -class UNIXDatagramSocket(_TrioSocketMixin[str], abc.UNIXDatagramSocket): - def __init__(self, trio_socket: TrioSocketType) -> None: - super().__init__(trio_socket) - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - - async def receive(self) -> UNIXDatagramPacketType: - with self._receive_guard: - try: - data, addr = await self._trio_socket.recvfrom(65536) - return data, addr - except BaseException as exc: - self._convert_socket_error(exc) - - async def send(self, item: UNIXDatagramPacketType) -> None: - with self._send_guard: - try: - await self._trio_socket.sendto(*item) - except BaseException as exc: - self._convert_socket_error(exc) - - -class ConnectedUNIXDatagramSocket( - _TrioSocketMixin[str], abc.ConnectedUNIXDatagramSocket -): - def __init__(self, trio_socket: TrioSocketType) -> None: - super().__init__(trio_socket) - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - - async def receive(self) -> bytes: - with self._receive_guard: - try: - return await self._trio_socket.recv(65536) - except BaseException as exc: - self._convert_socket_error(exc) - - async def send(self, item: bytes) -> None: - with self._send_guard: - try: - await self._trio_socket.send(item) - except BaseException as exc: - self._convert_socket_error(exc) - - -# -# Synchronization -# - - -class Event(BaseEvent): - def __new__(cls) -> Event: - return object.__new__(cls) - - def __init__(self) -> None: - self.__original = trio.Event() - - def is_set(self) -> bool: - return self.__original.is_set() - - async def wait(self) -> None: - return await self.__original.wait() - - def statistics(self) -> EventStatistics: - orig_statistics = self.__original.statistics() - return EventStatistics(tasks_waiting=orig_statistics.tasks_waiting) - - def set(self) -> None: - self.__original.set() - - -class Lock(BaseLock): - def __new__(cls, *, fast_acquire: bool = False) -> Lock: - return object.__new__(cls) - - def __init__(self, *, fast_acquire: bool = False) -> None: - self._fast_acquire = fast_acquire - self.__original = trio.Lock() - - @staticmethod - def _convert_runtime_error_msg(exc: RuntimeError) -> None: - if exc.args == ("attempt to re-acquire an already held Lock",): - exc.args = ("Attempted to acquire an already held Lock",) - - async def acquire(self) -> None: - if not self._fast_acquire: - try: - await self.__original.acquire() - except RuntimeError as exc: - self._convert_runtime_error_msg(exc) - raise - - return - - # This is the "fast path" where we don't let other tasks run - await trio.lowlevel.checkpoint_if_cancelled() - try: - self.__original.acquire_nowait() - except trio.WouldBlock: - await self.__original._lot.park() - except RuntimeError as exc: - self._convert_runtime_error_msg(exc) - raise - - def acquire_nowait(self) -> None: - try: - self.__original.acquire_nowait() - except trio.WouldBlock: - raise WouldBlock from None - except RuntimeError as exc: - self._convert_runtime_error_msg(exc) - raise - - def locked(self) -> bool: - return self.__original.locked() - - def release(self) -> None: - self.__original.release() - - def statistics(self) -> LockStatistics: - orig_statistics = self.__original.statistics() - owner = TrioTaskInfo(orig_statistics.owner) if orig_statistics.owner else None - return LockStatistics( - orig_statistics.locked, owner, orig_statistics.tasks_waiting - ) - - -class Semaphore(BaseSemaphore): - def __new__( - cls, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> Semaphore: - return object.__new__(cls) - - def __init__( - self, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> None: - super().__init__(initial_value, max_value=max_value, fast_acquire=fast_acquire) - self.__original = trio.Semaphore(initial_value, max_value=max_value) - - async def acquire(self) -> None: - if not self._fast_acquire: - await self.__original.acquire() - return - - # This is the "fast path" where we don't let other tasks run - await trio.lowlevel.checkpoint_if_cancelled() - try: - self.__original.acquire_nowait() - except trio.WouldBlock: - await self.__original._lot.park() - - def acquire_nowait(self) -> None: - try: - self.__original.acquire_nowait() - except trio.WouldBlock: - raise WouldBlock from None - - @property - def max_value(self) -> int | None: - return self.__original.max_value - - @property - def value(self) -> int: - return self.__original.value - - def release(self) -> None: - self.__original.release() - - def statistics(self) -> SemaphoreStatistics: - orig_statistics = self.__original.statistics() - return SemaphoreStatistics(orig_statistics.tasks_waiting) - - -class CapacityLimiter(BaseCapacityLimiter): - def __new__( - cls, - total_tokens: float | None = None, - *, - original: trio.CapacityLimiter | None = None, - ) -> CapacityLimiter: - return object.__new__(cls) - - def __init__( - self, - total_tokens: float | None = None, - *, - original: trio.CapacityLimiter | None = None, - ) -> None: - if original is not None: - self.__original = original - else: - assert total_tokens is not None - self.__original = trio.CapacityLimiter(total_tokens) - - async def __aenter__(self) -> None: - return await self.__original.__aenter__() - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - await self.__original.__aexit__(exc_type, exc_val, exc_tb) - - @property - def total_tokens(self) -> float: - return self.__original.total_tokens - - @total_tokens.setter - def total_tokens(self, value: float) -> None: - self.__original.total_tokens = value - - @property - def borrowed_tokens(self) -> int: - return self.__original.borrowed_tokens - - @property - def available_tokens(self) -> float: - return self.__original.available_tokens - - def acquire_nowait(self) -> None: - self.__original.acquire_nowait() - - def acquire_on_behalf_of_nowait(self, borrower: object) -> None: - self.__original.acquire_on_behalf_of_nowait(borrower) - - async def acquire(self) -> None: - await self.__original.acquire() - - async def acquire_on_behalf_of(self, borrower: object) -> None: - await self.__original.acquire_on_behalf_of(borrower) - - def release(self) -> None: - return self.__original.release() - - def release_on_behalf_of(self, borrower: object) -> None: - return self.__original.release_on_behalf_of(borrower) - - def statistics(self) -> CapacityLimiterStatistics: - orig = self.__original.statistics() - return CapacityLimiterStatistics( - borrowed_tokens=orig.borrowed_tokens, - total_tokens=orig.total_tokens, - borrowers=tuple(orig.borrowers), - tasks_waiting=orig.tasks_waiting, - ) - - -_capacity_limiter_wrapper: trio.lowlevel.RunVar = RunVar("_capacity_limiter_wrapper") - - -# -# Signal handling -# - - -class _SignalReceiver: - _iterator: AsyncIterator[int] - - def __init__(self, signals: tuple[Signals, ...]): - self._signals = signals - - def __enter__(self) -> _SignalReceiver: - self._cm = trio.open_signal_receiver(*self._signals) - self._iterator = self._cm.__enter__() - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool | None: - return self._cm.__exit__(exc_type, exc_val, exc_tb) - - def __aiter__(self) -> _SignalReceiver: - return self - - async def __anext__(self) -> Signals: - signum = await self._iterator.__anext__() - return Signals(signum) - - -# -# Testing and debugging -# - - -class TestRunner(abc.TestRunner): - def __init__(self, **options: Any) -> None: - from queue import Queue - - self._call_queue: Queue[Callable[[], object]] = Queue() - self._send_stream: MemoryObjectSendStream | None = None - self._options = options - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: types.TracebackType | None, - ) -> None: - if self._send_stream: - self._send_stream.close() - while self._send_stream is not None: - self._call_queue.get()() - - async def _run_tests_and_fixtures(self) -> None: - self._send_stream, receive_stream = create_memory_object_stream(1) - with receive_stream: - async for coro, outcome_holder in receive_stream: - try: - retval = await coro - except BaseException as exc: - outcome_holder.append(Error(exc)) - else: - outcome_holder.append(Value(retval)) - - def _main_task_finished(self, outcome: object) -> None: - self._send_stream = None - - def _call_in_runner_task( - self, - func: Callable[P, Awaitable[T_Retval]], - /, - *args: P.args, - **kwargs: P.kwargs, - ) -> T_Retval: - if self._send_stream is None: - trio.lowlevel.start_guest_run( - self._run_tests_and_fixtures, - run_sync_soon_threadsafe=self._call_queue.put, - done_callback=self._main_task_finished, - **self._options, - ) - while self._send_stream is None: - self._call_queue.get()() - - outcome_holder: list[Outcome] = [] - self._send_stream.send_nowait((func(*args, **kwargs), outcome_holder)) - while not outcome_holder: - self._call_queue.get()() - - return outcome_holder[0].unwrap() - - def run_asyncgen_fixture( - self, - fixture_func: Callable[..., AsyncGenerator[T_Retval, Any]], - kwargs: dict[str, Any], - ) -> Iterable[T_Retval]: - asyncgen = fixture_func(**kwargs) - fixturevalue: T_Retval = self._call_in_runner_task(asyncgen.asend, None) - - yield fixturevalue - - try: - self._call_in_runner_task(asyncgen.asend, None) - except StopAsyncIteration: - pass - else: - self._call_in_runner_task(asyncgen.aclose) - raise RuntimeError("Async generator fixture did not stop") - - def run_fixture( - self, - fixture_func: Callable[..., Coroutine[Any, Any, T_Retval]], - kwargs: dict[str, Any], - ) -> T_Retval: - return self._call_in_runner_task(fixture_func, **kwargs) - - def run_test( - self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any] - ) -> None: - self._call_in_runner_task(test_func, **kwargs) - - -class TrioTaskInfo(TaskInfo): - def __init__(self, task: trio.lowlevel.Task): - parent_id = None - if task.parent_nursery and task.parent_nursery.parent_task: - parent_id = id(task.parent_nursery.parent_task) - - super().__init__(id(task), parent_id, task.name, task.coro) - self._task = weakref.proxy(task) - - def has_pending_cancellation(self) -> bool: - try: - return self._task._cancel_status.effectively_cancelled - except ReferenceError: - # If the task is no longer around, it surely doesn't have a cancellation - # pending - return False - - -class TrioBackend(AsyncBackend): - @classmethod - def run( - cls, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - args: tuple[Unpack[PosArgsT]], - kwargs: dict[str, Any], - options: dict[str, Any], - ) -> T_Retval: - return trio.run(func, *args) - - @classmethod - def current_token(cls) -> object: - return trio.lowlevel.current_trio_token() - - @classmethod - def current_time(cls) -> float: - return trio.current_time() - - @classmethod - def cancelled_exception_class(cls) -> type[BaseException]: - return trio.Cancelled - - @classmethod - async def checkpoint(cls) -> None: - await trio.lowlevel.checkpoint() - - @classmethod - async def checkpoint_if_cancelled(cls) -> None: - await trio.lowlevel.checkpoint_if_cancelled() - - @classmethod - async def cancel_shielded_checkpoint(cls) -> None: - await trio.lowlevel.cancel_shielded_checkpoint() - - @classmethod - async def sleep(cls, delay: float) -> None: - await trio.sleep(delay) - - @classmethod - def create_cancel_scope( - cls, *, deadline: float = math.inf, shield: bool = False - ) -> abc.CancelScope: - return CancelScope(deadline=deadline, shield=shield) - - @classmethod - def current_effective_deadline(cls) -> float: - return trio.current_effective_deadline() - - @classmethod - def create_task_group(cls) -> abc.TaskGroup: - return TaskGroup() - - @classmethod - def create_event(cls) -> abc.Event: - return Event() - - @classmethod - def create_lock(cls, *, fast_acquire: bool) -> Lock: - return Lock(fast_acquire=fast_acquire) - - @classmethod - def create_semaphore( - cls, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> abc.Semaphore: - return Semaphore(initial_value, max_value=max_value, fast_acquire=fast_acquire) - - @classmethod - def create_capacity_limiter(cls, total_tokens: float) -> CapacityLimiter: - return CapacityLimiter(total_tokens) - - @classmethod - async def run_sync_in_worker_thread( - cls, - func: Callable[[Unpack[PosArgsT]], T_Retval], - args: tuple[Unpack[PosArgsT]], - abandon_on_cancel: bool = False, - limiter: abc.CapacityLimiter | None = None, - ) -> T_Retval: - def wrapper() -> T_Retval: - with claim_worker_thread(TrioBackend, token): - return func(*args) - - token = TrioBackend.current_token() - return await run_sync( - wrapper, - abandon_on_cancel=abandon_on_cancel, - limiter=cast(trio.CapacityLimiter, limiter), - ) - - @classmethod - def check_cancelled(cls) -> None: - trio.from_thread.check_cancelled() - - @classmethod - def run_async_from_thread( - cls, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - args: tuple[Unpack[PosArgsT]], - token: object, - ) -> T_Retval: - trio_token = cast("trio.lowlevel.TrioToken | None", token) - try: - return trio.from_thread.run(func, *args, trio_token=trio_token) - except trio.RunFinishedError: - raise RunFinishedError from None - - @classmethod - def run_sync_from_thread( - cls, - func: Callable[[Unpack[PosArgsT]], T_Retval], - args: tuple[Unpack[PosArgsT]], - token: object, - ) -> T_Retval: - trio_token = cast("trio.lowlevel.TrioToken | None", token) - try: - return trio.from_thread.run_sync(func, *args, trio_token=trio_token) - except trio.RunFinishedError: - raise RunFinishedError from None - - @classmethod - async def open_process( - cls, - command: StrOrBytesPath | Sequence[StrOrBytesPath], - *, - stdin: int | IO[Any] | None, - stdout: int | IO[Any] | None, - stderr: int | IO[Any] | None, - **kwargs: Any, - ) -> Process: - def convert_item(item: StrOrBytesPath) -> str: - str_or_bytes = os.fspath(item) - if isinstance(str_or_bytes, str): - return str_or_bytes - else: - return os.fsdecode(str_or_bytes) - - if isinstance(command, (str, bytes, PathLike)): - process = await trio.lowlevel.open_process( - convert_item(command), - stdin=stdin, - stdout=stdout, - stderr=stderr, - shell=True, - **kwargs, - ) - else: - process = await trio.lowlevel.open_process( - [convert_item(item) for item in command], - stdin=stdin, - stdout=stdout, - stderr=stderr, - shell=False, - **kwargs, - ) - - stdin_stream = SendStreamWrapper(process.stdin) if process.stdin else None - stdout_stream = ReceiveStreamWrapper(process.stdout) if process.stdout else None - stderr_stream = ReceiveStreamWrapper(process.stderr) if process.stderr else None - return Process(process, stdin_stream, stdout_stream, stderr_stream) - - @classmethod - def setup_process_pool_exit_at_shutdown(cls, workers: set[abc.Process]) -> None: - trio.lowlevel.spawn_system_task(_shutdown_process_pool, workers) - - @classmethod - async def connect_tcp( - cls, host: str, port: int, local_address: IPSockAddrType | None = None - ) -> SocketStream: - family = socket.AF_INET6 if ":" in host else socket.AF_INET - trio_socket = trio.socket.socket(family) - trio_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - if local_address: - await trio_socket.bind(local_address) - - try: - await trio_socket.connect((host, port)) - except BaseException: - trio_socket.close() - raise - - return SocketStream(trio_socket) - - @classmethod - async def connect_unix(cls, path: str | bytes) -> abc.UNIXSocketStream: - trio_socket = trio.socket.socket(socket.AF_UNIX) - try: - await trio_socket.connect(path) - except BaseException: - trio_socket.close() - raise - - return UNIXSocketStream(trio_socket) - - @classmethod - def create_tcp_listener(cls, sock: socket.socket) -> abc.SocketListener: - return TCPSocketListener(sock) - - @classmethod - def create_unix_listener(cls, sock: socket.socket) -> abc.SocketListener: - return UNIXSocketListener(sock) - - @classmethod - async def create_udp_socket( - cls, - family: socket.AddressFamily, - local_address: IPSockAddrType | None, - remote_address: IPSockAddrType | None, - reuse_port: bool, - ) -> UDPSocket | ConnectedUDPSocket: - trio_socket = trio.socket.socket(family=family, type=socket.SOCK_DGRAM) - - if reuse_port: - trio_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) - - if local_address: - await trio_socket.bind(local_address) - - if remote_address: - await trio_socket.connect(remote_address) - return ConnectedUDPSocket(trio_socket) - else: - return UDPSocket(trio_socket) - - @classmethod - @overload - async def create_unix_datagram_socket( - cls, raw_socket: socket.socket, remote_path: None - ) -> abc.UNIXDatagramSocket: ... - - @classmethod - @overload - async def create_unix_datagram_socket( - cls, raw_socket: socket.socket, remote_path: str | bytes - ) -> abc.ConnectedUNIXDatagramSocket: ... - - @classmethod - async def create_unix_datagram_socket( - cls, raw_socket: socket.socket, remote_path: str | bytes | None - ) -> abc.UNIXDatagramSocket | abc.ConnectedUNIXDatagramSocket: - trio_socket = trio.socket.from_stdlib_socket(raw_socket) - - if remote_path: - await trio_socket.connect(remote_path) - return ConnectedUNIXDatagramSocket(trio_socket) - else: - return UNIXDatagramSocket(trio_socket) - - @classmethod - async def getaddrinfo( - cls, - host: bytes | str | None, - port: str | int | None, - *, - family: int | AddressFamily = 0, - type: int | SocketKind = 0, - proto: int = 0, - flags: int = 0, - ) -> Sequence[ - tuple[ - AddressFamily, - SocketKind, - int, - str, - tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes], - ] - ]: - return await trio.socket.getaddrinfo(host, port, family, type, proto, flags) - - @classmethod - async def getnameinfo( - cls, sockaddr: IPSockAddrType, flags: int = 0 - ) -> tuple[str, str]: - return await trio.socket.getnameinfo(sockaddr, flags) - - @classmethod - async def wait_readable(cls, obj: FileDescriptorLike) -> None: - try: - await wait_readable(obj) - except trio.ClosedResourceError as exc: - raise ClosedResourceError().with_traceback(exc.__traceback__) from None - except trio.BusyResourceError: - raise BusyResourceError("reading from") from None - - @classmethod - async def wait_writable(cls, obj: FileDescriptorLike) -> None: - try: - await wait_writable(obj) - except trio.ClosedResourceError as exc: - raise ClosedResourceError().with_traceback(exc.__traceback__) from None - except trio.BusyResourceError: - raise BusyResourceError("writing to") from None - - @classmethod - def notify_closing(cls, obj: FileDescriptorLike) -> None: - notify_closing(obj) - - @classmethod - async def wrap_listener_socket(cls, sock: socket.socket) -> abc.SocketListener: - return TCPSocketListener(sock) - - @classmethod - async def wrap_stream_socket(cls, sock: socket.socket) -> SocketStream: - trio_sock = trio.socket.from_stdlib_socket(sock) - return SocketStream(trio_sock) - - @classmethod - async def wrap_unix_stream_socket(cls, sock: socket.socket) -> UNIXSocketStream: - trio_sock = trio.socket.from_stdlib_socket(sock) - return UNIXSocketStream(trio_sock) - - @classmethod - async def wrap_udp_socket(cls, sock: socket.socket) -> UDPSocket: - trio_sock = trio.socket.from_stdlib_socket(sock) - return UDPSocket(trio_sock) - - @classmethod - async def wrap_connected_udp_socket(cls, sock: socket.socket) -> ConnectedUDPSocket: - trio_sock = trio.socket.from_stdlib_socket(sock) - return ConnectedUDPSocket(trio_sock) - - @classmethod - async def wrap_unix_datagram_socket(cls, sock: socket.socket) -> UNIXDatagramSocket: - trio_sock = trio.socket.from_stdlib_socket(sock) - return UNIXDatagramSocket(trio_sock) - - @classmethod - async def wrap_connected_unix_datagram_socket( - cls, sock: socket.socket - ) -> ConnectedUNIXDatagramSocket: - trio_sock = trio.socket.from_stdlib_socket(sock) - return ConnectedUNIXDatagramSocket(trio_sock) - - @classmethod - def current_default_thread_limiter(cls) -> CapacityLimiter: - try: - return _capacity_limiter_wrapper.get() - except LookupError: - limiter = CapacityLimiter( - original=trio.to_thread.current_default_thread_limiter() - ) - _capacity_limiter_wrapper.set(limiter) - return limiter - - @classmethod - def open_signal_receiver( - cls, *signals: Signals - ) -> AbstractContextManager[AsyncIterator[Signals]]: - return _SignalReceiver(signals) - - @classmethod - def get_current_task(cls) -> TaskInfo: - task = current_task() - return TrioTaskInfo(task) - - @classmethod - def get_running_tasks(cls) -> Sequence[TaskInfo]: - root_task = current_root_task() - assert root_task - task_infos = [TrioTaskInfo(root_task)] - nurseries = root_task.child_nurseries - while nurseries: - new_nurseries: list[trio.Nursery] = [] - for nursery in nurseries: - for task in nursery.child_tasks: - task_infos.append(TrioTaskInfo(task)) - new_nurseries.extend(task.child_nurseries) - - nurseries = new_nurseries - - return task_infos - - @classmethod - async def wait_all_tasks_blocked(cls) -> None: - from trio.testing import wait_all_tasks_blocked - - await wait_all_tasks_blocked() - - @classmethod - def create_test_runner(cls, options: dict[str, Any]) -> TestRunner: - return TestRunner(**options) - - -backend_class = TrioBackend diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__init__.py b/notification-service/venv/Lib/site-packages/anyio/_core/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 6f3d06e..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_asyncio_selector_thread.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_asyncio_selector_thread.cpython-312.pyc deleted file mode 100644 index 1af3915..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_asyncio_selector_thread.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_contextmanagers.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_contextmanagers.cpython-312.pyc deleted file mode 100644 index cbbff49..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_contextmanagers.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_eventloop.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_eventloop.cpython-312.pyc deleted file mode 100644 index 06c25cd..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_eventloop.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_exceptions.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_exceptions.cpython-312.pyc deleted file mode 100644 index 4a9caee..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_exceptions.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_fileio.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_fileio.cpython-312.pyc deleted file mode 100644 index 4fac112..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_fileio.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_resources.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_resources.cpython-312.pyc deleted file mode 100644 index a309592..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_resources.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_signals.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_signals.cpython-312.pyc deleted file mode 100644 index 3183c0c..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_signals.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_sockets.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_sockets.cpython-312.pyc deleted file mode 100644 index c6279d1..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_sockets.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_streams.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_streams.cpython-312.pyc deleted file mode 100644 index 6f163c4..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_streams.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_subprocesses.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_subprocesses.cpython-312.pyc deleted file mode 100644 index 3f583fc..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_subprocesses.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_synchronization.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_synchronization.cpython-312.pyc deleted file mode 100644 index 4f0dd1a..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_synchronization.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_tasks.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_tasks.cpython-312.pyc deleted file mode 100644 index 6a3a2a5..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_tasks.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_tempfile.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_tempfile.cpython-312.pyc deleted file mode 100644 index 1f10847..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_tempfile.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_testing.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_testing.cpython-312.pyc deleted file mode 100644 index cc1d87a..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_testing.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_typedattr.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_typedattr.cpython-312.pyc deleted file mode 100644 index fda735a..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/_core/__pycache__/_typedattr.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_asyncio_selector_thread.py b/notification-service/venv/Lib/site-packages/anyio/_core/_asyncio_selector_thread.py deleted file mode 100644 index 9f35bae..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_asyncio_selector_thread.py +++ /dev/null @@ -1,167 +0,0 @@ -from __future__ import annotations - -import asyncio -import socket -import threading -from collections.abc import Callable -from selectors import EVENT_READ, EVENT_WRITE, DefaultSelector -from typing import TYPE_CHECKING, Any - -if TYPE_CHECKING: - from _typeshed import FileDescriptorLike - -_selector_lock = threading.Lock() -_selector: Selector | None = None - - -class Selector: - def __init__(self) -> None: - self._thread = threading.Thread(target=self.run, name="AnyIO socket selector") - self._selector = DefaultSelector() - self._send, self._receive = socket.socketpair() - self._send.setblocking(False) - self._receive.setblocking(False) - # This somewhat reduces the amount of memory wasted queueing up data - # for wakeups. With these settings, maximum number of 1-byte sends - # before getting BlockingIOError: - # Linux 4.8: 6 - # macOS (darwin 15.5): 1 - # Windows 10: 525347 - # Windows you're weird. (And on Windows setting SNDBUF to 0 makes send - # blocking, even on non-blocking sockets, so don't do that.) - self._receive.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1) - self._send.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1) - # On Windows this is a TCP socket so this might matter. On other - # platforms this fails b/c AF_UNIX sockets aren't actually TCP. - try: - self._send.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - except OSError: - pass - - self._selector.register(self._receive, EVENT_READ) - self._closed = False - - def start(self) -> None: - self._thread.start() - threading._register_atexit(self._stop) # type: ignore[attr-defined] - - def _stop(self) -> None: - global _selector - self._closed = True - self._notify_self() - self._send.close() - self._thread.join() - self._selector.unregister(self._receive) - self._receive.close() - self._selector.close() - _selector = None - assert not self._selector.get_map(), ( - "selector still has registered file descriptors after shutdown" - ) - - def _notify_self(self) -> None: - try: - self._send.send(b"\x00") - except BlockingIOError: - pass - - def add_reader(self, fd: FileDescriptorLike, callback: Callable[[], Any]) -> None: - loop = asyncio.get_running_loop() - try: - key = self._selector.get_key(fd) - except KeyError: - self._selector.register(fd, EVENT_READ, {EVENT_READ: (loop, callback)}) - else: - if EVENT_READ in key.data: - raise ValueError( - "this file descriptor is already registered for reading" - ) - - key.data[EVENT_READ] = loop, callback - self._selector.modify(fd, key.events | EVENT_READ, key.data) - - self._notify_self() - - def add_writer(self, fd: FileDescriptorLike, callback: Callable[[], Any]) -> None: - loop = asyncio.get_running_loop() - try: - key = self._selector.get_key(fd) - except KeyError: - self._selector.register(fd, EVENT_WRITE, {EVENT_WRITE: (loop, callback)}) - else: - if EVENT_WRITE in key.data: - raise ValueError( - "this file descriptor is already registered for writing" - ) - - key.data[EVENT_WRITE] = loop, callback - self._selector.modify(fd, key.events | EVENT_WRITE, key.data) - - self._notify_self() - - def remove_reader(self, fd: FileDescriptorLike) -> bool: - try: - key = self._selector.get_key(fd) - except KeyError: - return False - - if new_events := key.events ^ EVENT_READ: - del key.data[EVENT_READ] - self._selector.modify(fd, new_events, key.data) - else: - self._selector.unregister(fd) - - return True - - def remove_writer(self, fd: FileDescriptorLike) -> bool: - try: - key = self._selector.get_key(fd) - except KeyError: - return False - - if new_events := key.events ^ EVENT_WRITE: - del key.data[EVENT_WRITE] - self._selector.modify(fd, new_events, key.data) - else: - self._selector.unregister(fd) - - return True - - def run(self) -> None: - while not self._closed: - for key, events in self._selector.select(): - if key.fileobj is self._receive: - try: - while self._receive.recv(4096): - pass - except BlockingIOError: - pass - - continue - - if events & EVENT_READ: - loop, callback = key.data[EVENT_READ] - self.remove_reader(key.fd) - try: - loop.call_soon_threadsafe(callback) - except RuntimeError: - pass # the loop was already closed - - if events & EVENT_WRITE: - loop, callback = key.data[EVENT_WRITE] - self.remove_writer(key.fd) - try: - loop.call_soon_threadsafe(callback) - except RuntimeError: - pass # the loop was already closed - - -def get_selector() -> Selector: - global _selector - - with _selector_lock: - if _selector is None: - _selector = Selector() - _selector.start() - - return _selector diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_contextmanagers.py b/notification-service/venv/Lib/site-packages/anyio/_core/_contextmanagers.py deleted file mode 100644 index 302f32b..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_contextmanagers.py +++ /dev/null @@ -1,200 +0,0 @@ -from __future__ import annotations - -from abc import abstractmethod -from contextlib import AbstractAsyncContextManager, AbstractContextManager -from inspect import isasyncgen, iscoroutine, isgenerator -from types import TracebackType -from typing import Protocol, TypeVar, cast, final - -_T_co = TypeVar("_T_co", covariant=True) -_ExitT_co = TypeVar("_ExitT_co", covariant=True, bound="bool | None") - - -class _SupportsCtxMgr(Protocol[_T_co, _ExitT_co]): - def __contextmanager__(self) -> AbstractContextManager[_T_co, _ExitT_co]: ... - - -class _SupportsAsyncCtxMgr(Protocol[_T_co, _ExitT_co]): - def __asynccontextmanager__( - self, - ) -> AbstractAsyncContextManager[_T_co, _ExitT_co]: ... - - -class ContextManagerMixin: - """ - Mixin class providing context manager functionality via a generator-based - implementation. - - This class allows you to implement a context manager via :meth:`__contextmanager__` - which should return a generator. The mechanics are meant to mirror those of - :func:`@contextmanager `. - - .. note:: Classes using this mix-in are not reentrant as context managers, meaning - that once you enter it, you can't re-enter before first exiting it. - - .. seealso:: :doc:`contextmanagers` - """ - - __cm: AbstractContextManager[object, bool | None] | None = None - - @final - def __enter__(self: _SupportsCtxMgr[_T_co, bool | None]) -> _T_co: - # Needed for mypy to assume self still has the __cm member - assert isinstance(self, ContextManagerMixin) - if self.__cm is not None: - raise RuntimeError( - f"this {self.__class__.__qualname__} has already been entered" - ) - - cm = self.__contextmanager__() - if not isinstance(cm, AbstractContextManager): - if isgenerator(cm): - raise TypeError( - "__contextmanager__() returned a generator object instead of " - "a context manager. Did you forget to add the @contextmanager " - "decorator?" - ) - - raise TypeError( - f"__contextmanager__() did not return a context manager object, " - f"but {cm.__class__!r}" - ) - - if cm is self: - raise TypeError( - f"{self.__class__.__qualname__}.__contextmanager__() returned " - f"self. Did you forget to add the @contextmanager decorator and a " - f"'yield' statement?" - ) - - value = cm.__enter__() - self.__cm = cm - return value - - @final - def __exit__( - self: _SupportsCtxMgr[object, _ExitT_co], - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> _ExitT_co: - # Needed for mypy to assume self still has the __cm member - assert isinstance(self, ContextManagerMixin) - if self.__cm is None: - raise RuntimeError( - f"this {self.__class__.__qualname__} has not been entered yet" - ) - - # Prevent circular references - cm = self.__cm - del self.__cm - - return cast(_ExitT_co, cm.__exit__(exc_type, exc_val, exc_tb)) - - @abstractmethod - def __contextmanager__(self) -> AbstractContextManager[object, bool | None]: - """ - Implement your context manager logic here. - - This method **must** be decorated with - :func:`@contextmanager `. - - .. note:: Remember that the ``yield`` will raise any exception raised in the - enclosed context block, so use a ``finally:`` block to clean up resources! - - :return: a context manager object - """ - - -class AsyncContextManagerMixin: - """ - Mixin class providing async context manager functionality via a generator-based - implementation. - - This class allows you to implement a context manager via - :meth:`__asynccontextmanager__`. The mechanics are meant to mirror those of - :func:`@asynccontextmanager `. - - .. note:: Classes using this mix-in are not reentrant as context managers, meaning - that once you enter it, you can't re-enter before first exiting it. - - .. seealso:: :doc:`contextmanagers` - """ - - __cm: AbstractAsyncContextManager[object, bool | None] | None = None - - @final - async def __aenter__(self: _SupportsAsyncCtxMgr[_T_co, bool | None]) -> _T_co: - # Needed for mypy to assume self still has the __cm member - assert isinstance(self, AsyncContextManagerMixin) - if self.__cm is not None: - raise RuntimeError( - f"this {self.__class__.__qualname__} has already been entered" - ) - - cm = self.__asynccontextmanager__() - if not isinstance(cm, AbstractAsyncContextManager): - if isasyncgen(cm): - raise TypeError( - "__asynccontextmanager__() returned an async generator instead of " - "an async context manager. Did you forget to add the " - "@asynccontextmanager decorator?" - ) - elif iscoroutine(cm): - cm.close() - raise TypeError( - "__asynccontextmanager__() returned a coroutine object instead of " - "an async context manager. Did you forget to add the " - "@asynccontextmanager decorator and a 'yield' statement?" - ) - - raise TypeError( - f"__asynccontextmanager__() did not return an async context manager, " - f"but {cm.__class__!r}" - ) - - if cm is self: - raise TypeError( - f"{self.__class__.__qualname__}.__asynccontextmanager__() returned " - f"self. Did you forget to add the @asynccontextmanager decorator and a " - f"'yield' statement?" - ) - - value = await cm.__aenter__() - self.__cm = cm - return value - - @final - async def __aexit__( - self: _SupportsAsyncCtxMgr[object, _ExitT_co], - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> _ExitT_co: - assert isinstance(self, AsyncContextManagerMixin) - if self.__cm is None: - raise RuntimeError( - f"this {self.__class__.__qualname__} has not been entered yet" - ) - - # Prevent circular references - cm = self.__cm - del self.__cm - - return cast(_ExitT_co, await cm.__aexit__(exc_type, exc_val, exc_tb)) - - @abstractmethod - def __asynccontextmanager__( - self, - ) -> AbstractAsyncContextManager[object, bool | None]: - """ - Implement your async context manager logic here. - - This method **must** be decorated with - :func:`@asynccontextmanager `. - - .. note:: Remember that the ``yield`` will raise any exception raised in the - enclosed context block, so use a ``finally:`` block to clean up resources! - - :return: an async context manager object - """ diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_eventloop.py b/notification-service/venv/Lib/site-packages/anyio/_core/_eventloop.py deleted file mode 100644 index 59a69cc..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_eventloop.py +++ /dev/null @@ -1,234 +0,0 @@ -from __future__ import annotations - -import math -import sys -import threading -from collections.abc import Awaitable, Callable, Generator -from contextlib import contextmanager -from contextvars import Token -from importlib import import_module -from typing import TYPE_CHECKING, Any, TypeVar - -from ._exceptions import NoEventLoopError - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -sniffio: Any -try: - import sniffio -except ModuleNotFoundError: - sniffio = None - -if TYPE_CHECKING: - from ..abc import AsyncBackend - -# This must be updated when new backends are introduced -BACKENDS = "asyncio", "trio" - -T_Retval = TypeVar("T_Retval") -PosArgsT = TypeVarTuple("PosArgsT") - -threadlocals = threading.local() -loaded_backends: dict[str, type[AsyncBackend]] = {} - - -def run( - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - *args: Unpack[PosArgsT], - backend: str = "asyncio", - backend_options: dict[str, Any] | None = None, -) -> T_Retval: - """ - Run the given coroutine function in an asynchronous event loop. - - The current thread must not be already running an event loop. - - :param func: a coroutine function - :param args: positional arguments to ``func`` - :param backend: name of the asynchronous event loop implementation – currently - either ``asyncio`` or ``trio`` - :param backend_options: keyword arguments to call the backend ``run()`` - implementation with (documented :ref:`here `) - :return: the return value of the coroutine function - :raises RuntimeError: if an asynchronous event loop is already running in this - thread - :raises LookupError: if the named backend is not found - - """ - if asynclib_name := current_async_library(): - raise RuntimeError(f"Already running {asynclib_name} in this thread") - - try: - async_backend = get_async_backend(backend) - except ImportError as exc: - raise LookupError(f"No such backend: {backend}") from exc - - token = None - if asynclib_name is None: - # Since we're in control of the event loop, we can cache the name of the async - # library - token = set_current_async_library(backend) - - try: - backend_options = backend_options or {} - return async_backend.run(func, args, {}, backend_options) - finally: - reset_current_async_library(token) - - -async def sleep(delay: float) -> None: - """ - Pause the current task for the specified duration. - - :param delay: the duration, in seconds - - """ - return await get_async_backend().sleep(delay) - - -async def sleep_forever() -> None: - """ - Pause the current task until it's cancelled. - - This is a shortcut for ``sleep(math.inf)``. - - .. versionadded:: 3.1 - - """ - await sleep(math.inf) - - -async def sleep_until(deadline: float) -> None: - """ - Pause the current task until the given time. - - :param deadline: the absolute time to wake up at (according to the internal - monotonic clock of the event loop) - - .. versionadded:: 3.1 - - """ - now = current_time() - await sleep(max(deadline - now, 0)) - - -def current_time() -> float: - """ - Return the current value of the event loop's internal clock. - - :return: the clock value (seconds) - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - """ - return get_async_backend().current_time() - - -def get_all_backends() -> tuple[str, ...]: - """Return a tuple of the names of all built-in backends.""" - return BACKENDS - - -def get_available_backends() -> tuple[str, ...]: - """ - Test for the availability of built-in backends. - - :return a tuple of the built-in backend names that were successfully imported - - .. versionadded:: 4.12 - - """ - available_backends: list[str] = [] - for backend_name in get_all_backends(): - try: - get_async_backend(backend_name) - except ImportError: - continue - - available_backends.append(backend_name) - - return tuple(available_backends) - - -def get_cancelled_exc_class() -> type[BaseException]: - """ - Return the current async library's cancellation exception class. - - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - """ - return get_async_backend().cancelled_exception_class() - - -# -# Private API -# - - -@contextmanager -def claim_worker_thread( - backend_class: type[AsyncBackend], token: object -) -> Generator[Any, None, None]: - from ..lowlevel import EventLoopToken - - threadlocals.current_token = EventLoopToken(backend_class, token) - try: - yield - finally: - del threadlocals.current_token - - -def get_async_backend(asynclib_name: str | None = None) -> type[AsyncBackend]: - if asynclib_name is None: - asynclib_name = current_async_library() - if not asynclib_name: - raise NoEventLoopError( - f"Not currently running on any asynchronous event loop. " - f"Available async backends: {', '.join(get_all_backends())}" - ) - - # We use our own dict instead of sys.modules to get the already imported back-end - # class because the appropriate modules in sys.modules could potentially be only - # partially initialized - try: - return loaded_backends[asynclib_name] - except KeyError: - module = import_module(f"anyio._backends._{asynclib_name}") - loaded_backends[asynclib_name] = module.backend_class - return module.backend_class - - -def current_async_library() -> str | None: - if sniffio is None: - # If sniffio is not installed, we assume we're either running asyncio or nothing - import asyncio - - try: - asyncio.get_running_loop() - return "asyncio" - except RuntimeError: - pass - else: - try: - return sniffio.current_async_library() - except sniffio.AsyncLibraryNotFoundError: - pass - - return None - - -def set_current_async_library(asynclib_name: str | None) -> Token | None: - # no-op if sniffio is not installed - if sniffio is None: - return None - - return sniffio.current_async_library_cvar.set(asynclib_name) - - -def reset_current_async_library(token: Token | None) -> None: - if token is not None: - sniffio.current_async_library_cvar.reset(token) diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_exceptions.py b/notification-service/venv/Lib/site-packages/anyio/_core/_exceptions.py deleted file mode 100644 index 3776bed..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_exceptions.py +++ /dev/null @@ -1,156 +0,0 @@ -from __future__ import annotations - -import sys -from collections.abc import Generator -from textwrap import dedent -from typing import Any - -if sys.version_info < (3, 11): - from exceptiongroup import BaseExceptionGroup - - -class BrokenResourceError(Exception): - """ - Raised when trying to use a resource that has been rendered unusable due to external - causes (e.g. a send stream whose peer has disconnected). - """ - - -class BrokenWorkerProcess(Exception): - """ - Raised by :meth:`~anyio.to_process.run_sync` if the worker process terminates abruptly or - otherwise misbehaves. - """ - - -class BrokenWorkerInterpreter(Exception): - """ - Raised by :meth:`~anyio.to_interpreter.run_sync` if an unexpected exception is - raised in the subinterpreter. - """ - - def __init__(self, excinfo: Any): - # This was adapted from concurrent.futures.interpreter.ExecutionFailed - msg = excinfo.formatted - if not msg: - if excinfo.type and excinfo.msg: - msg = f"{excinfo.type.__name__}: {excinfo.msg}" - else: - msg = excinfo.type.__name__ or excinfo.msg - - super().__init__(msg) - self.excinfo = excinfo - - def __str__(self) -> str: - try: - formatted = self.excinfo.errdisplay - except Exception: - return super().__str__() - else: - return dedent( - f""" - {super().__str__()} - - Uncaught in the interpreter: - - {formatted} - """.strip() - ) - - -class BusyResourceError(Exception): - """ - Raised when two tasks are trying to read from or write to the same resource - concurrently. - """ - - def __init__(self, action: str): - super().__init__(f"Another task is already {action} this resource") - - -class ClosedResourceError(Exception): - """Raised when trying to use a resource that has been closed.""" - - -class ConnectionFailed(OSError): - """ - Raised when a connection attempt fails. - - .. note:: This class inherits from :exc:`OSError` for backwards compatibility. - """ - - -def iterate_exceptions( - exception: BaseException, -) -> Generator[BaseException, None, None]: - if isinstance(exception, BaseExceptionGroup): - for exc in exception.exceptions: - yield from iterate_exceptions(exc) - else: - yield exception - - -class DelimiterNotFound(Exception): - """ - Raised during - :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_until` if the - maximum number of bytes has been read without the delimiter being found. - """ - - def __init__(self, max_bytes: int) -> None: - super().__init__( - f"The delimiter was not found among the first {max_bytes} bytes" - ) - - -class EndOfStream(Exception): - """ - Raised when trying to read from a stream that has been closed from the other end. - """ - - -class IncompleteRead(Exception): - """ - Raised during - :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_exactly` or - :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_until` if the - connection is closed before the requested amount of bytes has been read. - """ - - def __init__(self) -> None: - super().__init__( - "The stream was closed before the read operation could be completed" - ) - - -class TypedAttributeLookupError(LookupError): - """ - Raised by :meth:`~anyio.TypedAttributeProvider.extra` when the given typed attribute - is not found and no default value has been given. - """ - - -class WouldBlock(Exception): - """Raised by ``X_nowait`` functions if ``X()`` would block.""" - - -class NoEventLoopError(RuntimeError): - """ - Raised by several functions that require an event loop to be running in the current - thread when there is no running event loop. - - This is also raised by :func:`.from_thread.run` and :func:`.from_thread.run_sync` - if not calling from an AnyIO worker thread, and no ``token`` was passed. - """ - - -class RunFinishedError(RuntimeError): - """ - Raised by :func:`.from_thread.run` and :func:`.from_thread.run_sync` if the event - loop associated with the explicitly passed token has already finished. - """ - - def __init__(self) -> None: - super().__init__( - "The event loop associated with the given token has already finished" - ) diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_fileio.py b/notification-service/venv/Lib/site-packages/anyio/_core/_fileio.py deleted file mode 100644 index 3bb8c84..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_fileio.py +++ /dev/null @@ -1,799 +0,0 @@ -from __future__ import annotations - -import os -import pathlib -import sys -from collections.abc import ( - AsyncIterator, - Callable, - Iterable, - Iterator, - Sequence, -) -from dataclasses import dataclass -from functools import partial -from os import PathLike -from typing import ( - IO, - TYPE_CHECKING, - Any, - AnyStr, - ClassVar, - Final, - Generic, - overload, -) - -from .. import to_thread -from ..abc import AsyncResource - -if TYPE_CHECKING: - from types import ModuleType - - from _typeshed import OpenBinaryMode, OpenTextMode, ReadableBuffer, WriteableBuffer -else: - ReadableBuffer = OpenBinaryMode = OpenTextMode = WriteableBuffer = object - - -class AsyncFile(AsyncResource, Generic[AnyStr]): - """ - An asynchronous file object. - - This class wraps a standard file object and provides async friendly versions of the - following blocking methods (where available on the original file object): - - * read - * read1 - * readline - * readlines - * readinto - * readinto1 - * write - * writelines - * truncate - * seek - * tell - * flush - - All other methods are directly passed through. - - This class supports the asynchronous context manager protocol which closes the - underlying file at the end of the context block. - - This class also supports asynchronous iteration:: - - async with await open_file(...) as f: - async for line in f: - print(line) - """ - - def __init__(self, fp: IO[AnyStr]) -> None: - self._fp: Any = fp - - def __getattr__(self, name: str) -> object: - return getattr(self._fp, name) - - @property - def wrapped(self) -> IO[AnyStr]: - """The wrapped file object.""" - return self._fp - - async def __aiter__(self) -> AsyncIterator[AnyStr]: - while True: - line = await self.readline() - if line: - yield line - else: - break - - async def aclose(self) -> None: - return await to_thread.run_sync(self._fp.close) - - async def read(self, size: int = -1) -> AnyStr: - return await to_thread.run_sync(self._fp.read, size) - - async def read1(self: AsyncFile[bytes], size: int = -1) -> bytes: - return await to_thread.run_sync(self._fp.read1, size) - - async def readline(self) -> AnyStr: - return await to_thread.run_sync(self._fp.readline) - - async def readlines(self) -> list[AnyStr]: - return await to_thread.run_sync(self._fp.readlines) - - async def readinto(self: AsyncFile[bytes], b: WriteableBuffer) -> int: - return await to_thread.run_sync(self._fp.readinto, b) - - async def readinto1(self: AsyncFile[bytes], b: WriteableBuffer) -> int: - return await to_thread.run_sync(self._fp.readinto1, b) - - @overload - async def write(self: AsyncFile[bytes], b: ReadableBuffer) -> int: ... - - @overload - async def write(self: AsyncFile[str], b: str) -> int: ... - - async def write(self, b: ReadableBuffer | str) -> int: - return await to_thread.run_sync(self._fp.write, b) - - @overload - async def writelines( - self: AsyncFile[bytes], lines: Iterable[ReadableBuffer] - ) -> None: ... - - @overload - async def writelines(self: AsyncFile[str], lines: Iterable[str]) -> None: ... - - async def writelines(self, lines: Iterable[ReadableBuffer] | Iterable[str]) -> None: - return await to_thread.run_sync(self._fp.writelines, lines) - - async def truncate(self, size: int | None = None) -> int: - return await to_thread.run_sync(self._fp.truncate, size) - - async def seek(self, offset: int, whence: int | None = os.SEEK_SET) -> int: - return await to_thread.run_sync(self._fp.seek, offset, whence) - - async def tell(self) -> int: - return await to_thread.run_sync(self._fp.tell) - - async def flush(self) -> None: - return await to_thread.run_sync(self._fp.flush) - - -@overload -async def open_file( - file: str | PathLike[str] | int, - mode: OpenBinaryMode, - buffering: int = ..., - encoding: str | None = ..., - errors: str | None = ..., - newline: str | None = ..., - closefd: bool = ..., - opener: Callable[[str, int], int] | None = ..., -) -> AsyncFile[bytes]: ... - - -@overload -async def open_file( - file: str | PathLike[str] | int, - mode: OpenTextMode = ..., - buffering: int = ..., - encoding: str | None = ..., - errors: str | None = ..., - newline: str | None = ..., - closefd: bool = ..., - opener: Callable[[str, int], int] | None = ..., -) -> AsyncFile[str]: ... - - -async def open_file( - file: str | PathLike[str] | int, - mode: str = "r", - buffering: int = -1, - encoding: str | None = None, - errors: str | None = None, - newline: str | None = None, - closefd: bool = True, - opener: Callable[[str, int], int] | None = None, -) -> AsyncFile[Any]: - """ - Open a file asynchronously. - - The arguments are exactly the same as for the builtin :func:`open`. - - :return: an asynchronous file object - - """ - fp = await to_thread.run_sync( - open, file, mode, buffering, encoding, errors, newline, closefd, opener - ) - return AsyncFile(fp) - - -def wrap_file(file: IO[AnyStr]) -> AsyncFile[AnyStr]: - """ - Wrap an existing file as an asynchronous file. - - :param file: an existing file-like object - :return: an asynchronous file object - - """ - return AsyncFile(file) - - -@dataclass(eq=False) -class _PathIterator(AsyncIterator["Path"]): - iterator: Iterator[PathLike[str]] - - async def __anext__(self) -> Path: - nextval = await to_thread.run_sync( - next, self.iterator, None, abandon_on_cancel=True - ) - if nextval is None: - raise StopAsyncIteration from None - - return Path(nextval) - - -class Path: - """ - An asynchronous version of :class:`pathlib.Path`. - - This class cannot be substituted for :class:`pathlib.Path` or - :class:`pathlib.PurePath`, but it is compatible with the :class:`os.PathLike` - interface. - - It implements the Python 3.10 version of :class:`pathlib.Path` interface, except for - the deprecated :meth:`~pathlib.Path.link_to` method. - - Some methods may be unavailable or have limited functionality, based on the Python - version: - - * :meth:`~pathlib.Path.copy` (available on Python 3.14 or later) - * :meth:`~pathlib.Path.copy_into` (available on Python 3.14 or later) - * :meth:`~pathlib.Path.from_uri` (available on Python 3.13 or later) - * :meth:`~pathlib.PurePath.full_match` (available on Python 3.13 or later) - * :attr:`~pathlib.Path.info` (available on Python 3.14 or later) - * :meth:`~pathlib.Path.is_junction` (available on Python 3.12 or later) - * :meth:`~pathlib.PurePath.match` (the ``case_sensitive`` parameter is only - available on Python 3.13 or later) - * :meth:`~pathlib.Path.move` (available on Python 3.14 or later) - * :meth:`~pathlib.Path.move_into` (available on Python 3.14 or later) - * :meth:`~pathlib.PurePath.relative_to` (the ``walk_up`` parameter is only available - on Python 3.12 or later) - * :meth:`~pathlib.Path.walk` (available on Python 3.12 or later) - - Any methods that do disk I/O need to be awaited on. These methods are: - - * :meth:`~pathlib.Path.absolute` - * :meth:`~pathlib.Path.chmod` - * :meth:`~pathlib.Path.cwd` - * :meth:`~pathlib.Path.exists` - * :meth:`~pathlib.Path.expanduser` - * :meth:`~pathlib.Path.group` - * :meth:`~pathlib.Path.hardlink_to` - * :meth:`~pathlib.Path.home` - * :meth:`~pathlib.Path.is_block_device` - * :meth:`~pathlib.Path.is_char_device` - * :meth:`~pathlib.Path.is_dir` - * :meth:`~pathlib.Path.is_fifo` - * :meth:`~pathlib.Path.is_file` - * :meth:`~pathlib.Path.is_junction` - * :meth:`~pathlib.Path.is_mount` - * :meth:`~pathlib.Path.is_socket` - * :meth:`~pathlib.Path.is_symlink` - * :meth:`~pathlib.Path.lchmod` - * :meth:`~pathlib.Path.lstat` - * :meth:`~pathlib.Path.mkdir` - * :meth:`~pathlib.Path.open` - * :meth:`~pathlib.Path.owner` - * :meth:`~pathlib.Path.read_bytes` - * :meth:`~pathlib.Path.read_text` - * :meth:`~pathlib.Path.readlink` - * :meth:`~pathlib.Path.rename` - * :meth:`~pathlib.Path.replace` - * :meth:`~pathlib.Path.resolve` - * :meth:`~pathlib.Path.rmdir` - * :meth:`~pathlib.Path.samefile` - * :meth:`~pathlib.Path.stat` - * :meth:`~pathlib.Path.symlink_to` - * :meth:`~pathlib.Path.touch` - * :meth:`~pathlib.Path.unlink` - * :meth:`~pathlib.Path.walk` - * :meth:`~pathlib.Path.write_bytes` - * :meth:`~pathlib.Path.write_text` - - Additionally, the following methods return an async iterator yielding - :class:`~.Path` objects: - - * :meth:`~pathlib.Path.glob` - * :meth:`~pathlib.Path.iterdir` - * :meth:`~pathlib.Path.rglob` - """ - - __slots__ = "_path", "__weakref__" - - __weakref__: Any - - def __init__(self, *args: str | PathLike[str]) -> None: - self._path: Final[pathlib.Path] = pathlib.Path(*args) - - def __fspath__(self) -> str: - return self._path.__fspath__() - - if sys.version_info >= (3, 15): - - def __vfspath__(self) -> str: - return self._path.__vfspath__() - - def __str__(self) -> str: - return self._path.__str__() - - def __repr__(self) -> str: - return f"{self.__class__.__name__}({self.as_posix()!r})" - - def __bytes__(self) -> bytes: - return self._path.__bytes__() - - def __hash__(self) -> int: - return self._path.__hash__() - - def __eq__(self, other: object) -> bool: - target = other._path if isinstance(other, Path) else other - return self._path.__eq__(target) - - def __lt__(self, other: pathlib.PurePath | Path) -> bool: - target = other._path if isinstance(other, Path) else other - return self._path.__lt__(target) - - def __le__(self, other: pathlib.PurePath | Path) -> bool: - target = other._path if isinstance(other, Path) else other - return self._path.__le__(target) - - def __gt__(self, other: pathlib.PurePath | Path) -> bool: - target = other._path if isinstance(other, Path) else other - return self._path.__gt__(target) - - def __ge__(self, other: pathlib.PurePath | Path) -> bool: - target = other._path if isinstance(other, Path) else other - return self._path.__ge__(target) - - def __truediv__(self, other: str | PathLike[str]) -> Path: - return Path(self._path / other) - - def __rtruediv__(self, other: str | PathLike[str]) -> Path: - return Path(other) / self - - @property - def parts(self) -> tuple[str, ...]: - return self._path.parts - - @property - def drive(self) -> str: - return self._path.drive - - @property - def root(self) -> str: - return self._path.root - - @property - def anchor(self) -> str: - return self._path.anchor - - @property - def parents(self) -> Sequence[Path]: - return tuple(Path(p) for p in self._path.parents) - - @property - def parent(self) -> Path: - return Path(self._path.parent) - - @property - def name(self) -> str: - return self._path.name - - @property - def suffix(self) -> str: - return self._path.suffix - - @property - def suffixes(self) -> list[str]: - return self._path.suffixes - - @property - def stem(self) -> str: - return self._path.stem - - async def absolute(self) -> Path: - path = await to_thread.run_sync(self._path.absolute) - return Path(path) - - def as_posix(self) -> str: - return self._path.as_posix() - - def as_uri(self) -> str: - return self._path.as_uri() - - if sys.version_info >= (3, 13): - parser: ClassVar[ModuleType] = pathlib.Path.parser - - @classmethod - def from_uri(cls, uri: str) -> Path: - return Path(pathlib.Path.from_uri(uri)) - - def full_match( - self, path_pattern: str, *, case_sensitive: bool | None = None - ) -> bool: - return self._path.full_match(path_pattern, case_sensitive=case_sensitive) - - def match( - self, path_pattern: str, *, case_sensitive: bool | None = None - ) -> bool: - return self._path.match(path_pattern, case_sensitive=case_sensitive) - else: - - def match(self, path_pattern: str) -> bool: - return self._path.match(path_pattern) - - if sys.version_info >= (3, 14): - - @property - def info(self) -> Any: # TODO: add return type annotation when Typeshed gets it - return self._path.info - - async def copy( - self, - target: str | os.PathLike[str], - *, - follow_symlinks: bool = True, - preserve_metadata: bool = False, - ) -> Path: - func = partial( - self._path.copy, - follow_symlinks=follow_symlinks, - preserve_metadata=preserve_metadata, - ) - return Path(await to_thread.run_sync(func, pathlib.Path(target))) - - async def copy_into( - self, - target_dir: str | os.PathLike[str], - *, - follow_symlinks: bool = True, - preserve_metadata: bool = False, - ) -> Path: - func = partial( - self._path.copy_into, - follow_symlinks=follow_symlinks, - preserve_metadata=preserve_metadata, - ) - return Path(await to_thread.run_sync(func, pathlib.Path(target_dir))) - - async def move(self, target: str | os.PathLike[str]) -> Path: - # Upstream does not handle anyio.Path properly as a PathLike - target = pathlib.Path(target) - return Path(await to_thread.run_sync(self._path.move, target)) - - async def move_into( - self, - target_dir: str | os.PathLike[str], - ) -> Path: - return Path(await to_thread.run_sync(self._path.move_into, target_dir)) - - def is_relative_to(self, other: str | PathLike[str]) -> bool: - try: - self.relative_to(other) - return True - except ValueError: - return False - - async def chmod(self, mode: int, *, follow_symlinks: bool = True) -> None: - func = partial(os.chmod, follow_symlinks=follow_symlinks) - return await to_thread.run_sync(func, self._path, mode) - - @classmethod - async def cwd(cls) -> Path: - path = await to_thread.run_sync(pathlib.Path.cwd) - return cls(path) - - async def exists(self) -> bool: - return await to_thread.run_sync(self._path.exists, abandon_on_cancel=True) - - async def expanduser(self) -> Path: - return Path( - await to_thread.run_sync(self._path.expanduser, abandon_on_cancel=True) - ) - - if sys.version_info < (3, 12): - # Python 3.11 and earlier - def glob(self, pattern: str) -> AsyncIterator[Path]: - gen = self._path.glob(pattern) - return _PathIterator(gen) - elif (3, 12) <= sys.version_info < (3, 13): - # changed in Python 3.12: - # - The case_sensitive parameter was added. - def glob( - self, - pattern: str, - *, - case_sensitive: bool | None = None, - ) -> AsyncIterator[Path]: - gen = self._path.glob(pattern, case_sensitive=case_sensitive) - return _PathIterator(gen) - elif sys.version_info >= (3, 13): - # Changed in Python 3.13: - # - The recurse_symlinks parameter was added. - # - The pattern parameter accepts a path-like object. - def glob( # type: ignore[misc] # mypy doesn't allow for differing signatures in a conditional block - self, - pattern: str | PathLike[str], - *, - case_sensitive: bool | None = None, - recurse_symlinks: bool = False, - ) -> AsyncIterator[Path]: - gen = self._path.glob( - pattern, # type: ignore[arg-type] - case_sensitive=case_sensitive, - recurse_symlinks=recurse_symlinks, - ) - return _PathIterator(gen) - - async def group(self) -> str: - return await to_thread.run_sync(self._path.group, abandon_on_cancel=True) - - async def hardlink_to( - self, target: str | bytes | PathLike[str] | PathLike[bytes] - ) -> None: - if isinstance(target, Path): - target = target._path - - await to_thread.run_sync(os.link, target, self) - - @classmethod - async def home(cls) -> Path: - home_path = await to_thread.run_sync(pathlib.Path.home) - return cls(home_path) - - def is_absolute(self) -> bool: - return self._path.is_absolute() - - async def is_block_device(self) -> bool: - return await to_thread.run_sync( - self._path.is_block_device, abandon_on_cancel=True - ) - - async def is_char_device(self) -> bool: - return await to_thread.run_sync( - self._path.is_char_device, abandon_on_cancel=True - ) - - async def is_dir(self) -> bool: - return await to_thread.run_sync(self._path.is_dir, abandon_on_cancel=True) - - async def is_fifo(self) -> bool: - return await to_thread.run_sync(self._path.is_fifo, abandon_on_cancel=True) - - async def is_file(self) -> bool: - return await to_thread.run_sync(self._path.is_file, abandon_on_cancel=True) - - if sys.version_info >= (3, 12): - - async def is_junction(self) -> bool: - return await to_thread.run_sync(self._path.is_junction) - - async def is_mount(self) -> bool: - return await to_thread.run_sync( - os.path.ismount, self._path, abandon_on_cancel=True - ) - - if sys.version_info < (3, 15): - - def is_reserved(self) -> bool: - return self._path.is_reserved() - - async def is_socket(self) -> bool: - return await to_thread.run_sync(self._path.is_socket, abandon_on_cancel=True) - - async def is_symlink(self) -> bool: - return await to_thread.run_sync(self._path.is_symlink, abandon_on_cancel=True) - - async def iterdir(self) -> AsyncIterator[Path]: - gen = ( - self._path.iterdir() - if sys.version_info < (3, 13) - else await to_thread.run_sync(self._path.iterdir, abandon_on_cancel=True) - ) - async for path in _PathIterator(gen): - yield path - - def joinpath(self, *args: str | PathLike[str]) -> Path: - return Path(self._path.joinpath(*args)) - - async def lchmod(self, mode: int) -> None: - await to_thread.run_sync(self._path.lchmod, mode) - - async def lstat(self) -> os.stat_result: - return await to_thread.run_sync(self._path.lstat, abandon_on_cancel=True) - - async def mkdir( - self, mode: int = 0o777, parents: bool = False, exist_ok: bool = False - ) -> None: - await to_thread.run_sync(self._path.mkdir, mode, parents, exist_ok) - - @overload - async def open( - self, - mode: OpenBinaryMode, - buffering: int = ..., - encoding: str | None = ..., - errors: str | None = ..., - newline: str | None = ..., - ) -> AsyncFile[bytes]: ... - - @overload - async def open( - self, - mode: OpenTextMode = ..., - buffering: int = ..., - encoding: str | None = ..., - errors: str | None = ..., - newline: str | None = ..., - ) -> AsyncFile[str]: ... - - async def open( - self, - mode: str = "r", - buffering: int = -1, - encoding: str | None = None, - errors: str | None = None, - newline: str | None = None, - ) -> AsyncFile[Any]: - fp = await to_thread.run_sync( - self._path.open, mode, buffering, encoding, errors, newline - ) - return AsyncFile(fp) - - async def owner(self) -> str: - return await to_thread.run_sync(self._path.owner, abandon_on_cancel=True) - - async def read_bytes(self) -> bytes: - return await to_thread.run_sync(self._path.read_bytes) - - async def read_text( - self, encoding: str | None = None, errors: str | None = None - ) -> str: - return await to_thread.run_sync(self._path.read_text, encoding, errors) - - if sys.version_info >= (3, 12): - - def relative_to( - self, *other: str | PathLike[str], walk_up: bool = False - ) -> Path: - # relative_to() should work with any PathLike but it doesn't - others = [pathlib.Path(other) for other in other] - return Path(self._path.relative_to(*others, walk_up=walk_up)) - - else: - - def relative_to(self, *other: str | PathLike[str]) -> Path: - return Path(self._path.relative_to(*other)) - - async def readlink(self) -> Path: - target = await to_thread.run_sync(os.readlink, self._path) - return Path(target) - - async def rename(self, target: str | pathlib.PurePath | Path) -> Path: - if isinstance(target, Path): - target = target._path - - await to_thread.run_sync(self._path.rename, target) - return Path(target) - - async def replace(self, target: str | pathlib.PurePath | Path) -> Path: - if isinstance(target, Path): - target = target._path - - await to_thread.run_sync(self._path.replace, target) - return Path(target) - - async def resolve(self, strict: bool = False) -> Path: - func = partial(self._path.resolve, strict=strict) - return Path(await to_thread.run_sync(func, abandon_on_cancel=True)) - - if sys.version_info < (3, 12): - # Pre Python 3.12 - def rglob(self, pattern: str) -> AsyncIterator[Path]: - gen = self._path.rglob(pattern) - return _PathIterator(gen) - elif (3, 12) <= sys.version_info < (3, 13): - # Changed in Python 3.12: - # - The case_sensitive parameter was added. - def rglob( - self, pattern: str, *, case_sensitive: bool | None = None - ) -> AsyncIterator[Path]: - gen = self._path.rglob(pattern, case_sensitive=case_sensitive) - return _PathIterator(gen) - elif sys.version_info >= (3, 13): - # Changed in Python 3.13: - # - The recurse_symlinks parameter was added. - # - The pattern parameter accepts a path-like object. - def rglob( # type: ignore[misc] # mypy doesn't allow for differing signatures in a conditional block - self, - pattern: str | PathLike[str], - *, - case_sensitive: bool | None = None, - recurse_symlinks: bool = False, - ) -> AsyncIterator[Path]: - gen = self._path.rglob( - pattern, # type: ignore[arg-type] - case_sensitive=case_sensitive, - recurse_symlinks=recurse_symlinks, - ) - return _PathIterator(gen) - - async def rmdir(self) -> None: - await to_thread.run_sync(self._path.rmdir) - - async def samefile(self, other_path: str | PathLike[str]) -> bool: - if isinstance(other_path, Path): - other_path = other_path._path - - return await to_thread.run_sync( - self._path.samefile, other_path, abandon_on_cancel=True - ) - - async def stat(self, *, follow_symlinks: bool = True) -> os.stat_result: - func = partial(os.stat, follow_symlinks=follow_symlinks) - return await to_thread.run_sync(func, self._path, abandon_on_cancel=True) - - async def symlink_to( - self, - target: str | bytes | PathLike[str] | PathLike[bytes], - target_is_directory: bool = False, - ) -> None: - if isinstance(target, Path): - target = target._path - - await to_thread.run_sync(self._path.symlink_to, target, target_is_directory) - - async def touch(self, mode: int = 0o666, exist_ok: bool = True) -> None: - await to_thread.run_sync(self._path.touch, mode, exist_ok) - - async def unlink(self, missing_ok: bool = False) -> None: - try: - await to_thread.run_sync(self._path.unlink) - except FileNotFoundError: - if not missing_ok: - raise - - if sys.version_info >= (3, 12): - - async def walk( - self, - top_down: bool = True, - on_error: Callable[[OSError], object] | None = None, - follow_symlinks: bool = False, - ) -> AsyncIterator[tuple[Path, list[str], list[str]]]: - def get_next_value() -> tuple[pathlib.Path, list[str], list[str]] | None: - try: - return next(gen) - except StopIteration: - return None - - gen = self._path.walk(top_down, on_error, follow_symlinks) - while True: - value = await to_thread.run_sync(get_next_value) - if value is None: - return - - root, dirs, paths = value - yield Path(root), dirs, paths - - def with_name(self, name: str) -> Path: - return Path(self._path.with_name(name)) - - def with_stem(self, stem: str) -> Path: - return Path(self._path.with_name(stem + self._path.suffix)) - - def with_suffix(self, suffix: str) -> Path: - return Path(self._path.with_suffix(suffix)) - - def with_segments(self, *pathsegments: str | PathLike[str]) -> Path: - return Path(*pathsegments) - - async def write_bytes(self, data: bytes) -> int: - return await to_thread.run_sync(self._path.write_bytes, data) - - async def write_text( - self, - data: str, - encoding: str | None = None, - errors: str | None = None, - newline: str | None = None, - ) -> int: - return await to_thread.run_sync( - self._path.write_text, data, encoding, errors, newline - ) - - -PathLike.register(Path) diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_resources.py b/notification-service/venv/Lib/site-packages/anyio/_core/_resources.py deleted file mode 100644 index b9a5344..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_resources.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from ..abc import AsyncResource -from ._tasks import CancelScope - - -async def aclose_forcefully(resource: AsyncResource) -> None: - """ - Close an asynchronous resource in a cancelled scope. - - Doing this closes the resource without waiting on anything. - - :param resource: the resource to close - - """ - with CancelScope() as scope: - scope.cancel() - await resource.aclose() diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_signals.py b/notification-service/venv/Lib/site-packages/anyio/_core/_signals.py deleted file mode 100644 index e24c79e..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_signals.py +++ /dev/null @@ -1,29 +0,0 @@ -from __future__ import annotations - -from collections.abc import AsyncIterator -from contextlib import AbstractContextManager -from signal import Signals - -from ._eventloop import get_async_backend - - -def open_signal_receiver( - *signals: Signals, -) -> AbstractContextManager[AsyncIterator[Signals]]: - """ - Start receiving operating system signals. - - :param signals: signals to receive (e.g. ``signal.SIGINT``) - :return: an asynchronous context manager for an asynchronous iterator which yields - signal numbers - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - .. warning:: Windows does not support signals natively so it is best to avoid - relying on this in cross-platform applications. - - .. warning:: On asyncio, this permanently replaces any previous signal handler for - the given signals, as set via :meth:`~asyncio.loop.add_signal_handler`. - - """ - return get_async_backend().open_signal_receiver(*signals) diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_sockets.py b/notification-service/venv/Lib/site-packages/anyio/_core/_sockets.py deleted file mode 100644 index 6c99b3a..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_sockets.py +++ /dev/null @@ -1,1003 +0,0 @@ -from __future__ import annotations - -import errno -import os -import socket -import ssl -import stat -import sys -from collections.abc import Awaitable -from dataclasses import dataclass -from ipaddress import IPv4Address, IPv6Address, ip_address -from os import PathLike, chmod -from socket import AddressFamily, SocketKind -from typing import TYPE_CHECKING, Any, Literal, cast, overload - -from .. import ConnectionFailed, to_thread -from ..abc import ( - ByteStreamConnectable, - ConnectedUDPSocket, - ConnectedUNIXDatagramSocket, - IPAddressType, - IPSockAddrType, - SocketListener, - SocketStream, - UDPSocket, - UNIXDatagramSocket, - UNIXSocketStream, -) -from ..streams.stapled import MultiListener -from ..streams.tls import TLSConnectable, TLSStream -from ._eventloop import get_async_backend -from ._resources import aclose_forcefully -from ._synchronization import Event -from ._tasks import create_task_group, move_on_after - -if TYPE_CHECKING: - from _typeshed import FileDescriptorLike -else: - FileDescriptorLike = object - -if sys.version_info < (3, 11): - from exceptiongroup import ExceptionGroup - -if sys.version_info >= (3, 12): - from typing import override -else: - from typing_extensions import override - -if sys.version_info < (3, 13): - from typing_extensions import deprecated -else: - from warnings import deprecated - -IPPROTO_IPV6 = getattr(socket, "IPPROTO_IPV6", 41) # https://bugs.python.org/issue29515 - -AnyIPAddressFamily = Literal[ - AddressFamily.AF_UNSPEC, AddressFamily.AF_INET, AddressFamily.AF_INET6 -] -IPAddressFamily = Literal[AddressFamily.AF_INET, AddressFamily.AF_INET6] - - -# tls_hostname given -@overload -async def connect_tcp( - remote_host: IPAddressType, - remote_port: int, - *, - local_host: IPAddressType | None = ..., - ssl_context: ssl.SSLContext | None = ..., - tls_standard_compatible: bool = ..., - tls_hostname: str, - happy_eyeballs_delay: float = ..., -) -> TLSStream: ... - - -# ssl_context given -@overload -async def connect_tcp( - remote_host: IPAddressType, - remote_port: int, - *, - local_host: IPAddressType | None = ..., - ssl_context: ssl.SSLContext, - tls_standard_compatible: bool = ..., - tls_hostname: str | None = ..., - happy_eyeballs_delay: float = ..., -) -> TLSStream: ... - - -# tls=True -@overload -async def connect_tcp( - remote_host: IPAddressType, - remote_port: int, - *, - local_host: IPAddressType | None = ..., - tls: Literal[True], - ssl_context: ssl.SSLContext | None = ..., - tls_standard_compatible: bool = ..., - tls_hostname: str | None = ..., - happy_eyeballs_delay: float = ..., -) -> TLSStream: ... - - -# tls=False -@overload -async def connect_tcp( - remote_host: IPAddressType, - remote_port: int, - *, - local_host: IPAddressType | None = ..., - tls: Literal[False], - ssl_context: ssl.SSLContext | None = ..., - tls_standard_compatible: bool = ..., - tls_hostname: str | None = ..., - happy_eyeballs_delay: float = ..., -) -> SocketStream: ... - - -# No TLS arguments -@overload -async def connect_tcp( - remote_host: IPAddressType, - remote_port: int, - *, - local_host: IPAddressType | None = ..., - happy_eyeballs_delay: float = ..., -) -> SocketStream: ... - - -async def connect_tcp( - remote_host: IPAddressType, - remote_port: int, - *, - local_host: IPAddressType | None = None, - tls: bool = False, - ssl_context: ssl.SSLContext | None = None, - tls_standard_compatible: bool = True, - tls_hostname: str | None = None, - happy_eyeballs_delay: float = 0.25, -) -> SocketStream | TLSStream: - """ - Connect to a host using the TCP protocol. - - This function implements the stateless version of the Happy Eyeballs algorithm (RFC - 6555). If ``remote_host`` is a host name that resolves to multiple IP addresses, - each one is tried until one connection attempt succeeds. If the first attempt does - not connected within 250 milliseconds, a second attempt is started using the next - address in the list, and so on. On IPv6 enabled systems, an IPv6 address (if - available) is tried first. - - When the connection has been established, a TLS handshake will be done if either - ``ssl_context`` or ``tls_hostname`` is not ``None``, or if ``tls`` is ``True``. - - :param remote_host: the IP address or host name to connect to - :param remote_port: port on the target host to connect to - :param local_host: the interface address or name to bind the socket to before - connecting - :param tls: ``True`` to do a TLS handshake with the connected stream and return a - :class:`~anyio.streams.tls.TLSStream` instead - :param ssl_context: the SSL context object to use (if omitted, a default context is - created) - :param tls_standard_compatible: If ``True``, performs the TLS shutdown handshake - before closing the stream and requires that the server does this as well. - Otherwise, :exc:`~ssl.SSLEOFError` may be raised during reads from the stream. - Some protocols, such as HTTP, require this option to be ``False``. - See :meth:`~ssl.SSLContext.wrap_socket` for details. - :param tls_hostname: host name to check the server certificate against (defaults to - the value of ``remote_host``) - :param happy_eyeballs_delay: delay (in seconds) before starting the next connection - attempt - :return: a socket stream object if no TLS handshake was done, otherwise a TLS stream - :raises ConnectionFailed: if the connection fails - - """ - # Placed here due to https://github.com/python/mypy/issues/7057 - connected_stream: SocketStream | None = None - - async def try_connect(remote_host: str, event: Event) -> None: - nonlocal connected_stream - try: - stream = await asynclib.connect_tcp(remote_host, remote_port, local_address) - except OSError as exc: - oserrors.append(exc) - return - else: - if connected_stream is None: - connected_stream = stream - tg.cancel_scope.cancel() - else: - await stream.aclose() - finally: - event.set() - - asynclib = get_async_backend() - local_address: IPSockAddrType | None = None - family = socket.AF_UNSPEC - if local_host: - gai_res = await getaddrinfo(str(local_host), None) - family, *_, local_address = gai_res[0] - - target_host = str(remote_host) - try: - addr_obj = ip_address(remote_host) - except ValueError: - addr_obj = None - - if addr_obj is not None: - if isinstance(addr_obj, IPv6Address): - target_addrs = [(socket.AF_INET6, addr_obj.compressed)] - else: - target_addrs = [(socket.AF_INET, addr_obj.compressed)] - else: - # getaddrinfo() will raise an exception if name resolution fails - gai_res = await getaddrinfo( - target_host, remote_port, family=family, type=socket.SOCK_STREAM - ) - - # Organize the list so that the first address is an IPv6 address (if available) - # and the second one is an IPv4 addresses. The rest can be in whatever order. - v6_found = v4_found = False - target_addrs = [] - for af, *_, sa in gai_res: - if af == socket.AF_INET6 and not v6_found: - v6_found = True - target_addrs.insert(0, (af, sa[0])) - elif af == socket.AF_INET and not v4_found and v6_found: - v4_found = True - target_addrs.insert(1, (af, sa[0])) - else: - target_addrs.append((af, sa[0])) - - oserrors: list[OSError] = [] - try: - async with create_task_group() as tg: - for _af, addr in target_addrs: - event = Event() - tg.start_soon(try_connect, addr, event) - with move_on_after(happy_eyeballs_delay): - await event.wait() - - if connected_stream is None: - cause = ( - oserrors[0] - if len(oserrors) == 1 - else ExceptionGroup("multiple connection attempts failed", oserrors) - ) - raise OSError("All connection attempts failed") from cause - finally: - oserrors.clear() - - if tls or tls_hostname or ssl_context: - try: - return await TLSStream.wrap( - connected_stream, - server_side=False, - hostname=tls_hostname or str(remote_host), - ssl_context=ssl_context, - standard_compatible=tls_standard_compatible, - ) - except BaseException: - await aclose_forcefully(connected_stream) - raise - - return connected_stream - - -async def connect_unix(path: str | bytes | PathLike[Any]) -> UNIXSocketStream: - """ - Connect to the given UNIX socket. - - Not available on Windows. - - :param path: path to the socket - :return: a socket stream object - :raises ConnectionFailed: if the connection fails - - """ - path = os.fspath(path) - return await get_async_backend().connect_unix(path) - - -async def create_tcp_listener( - *, - local_host: IPAddressType | None = None, - local_port: int = 0, - family: AnyIPAddressFamily = socket.AddressFamily.AF_UNSPEC, - backlog: int = 65536, - reuse_port: bool = False, -) -> MultiListener[SocketStream]: - """ - Create a TCP socket listener. - - :param local_port: port number to listen on - :param local_host: IP address of the interface to listen on. If omitted, listen on - all IPv4 and IPv6 interfaces. To listen on all interfaces on a specific address - family, use ``0.0.0.0`` for IPv4 or ``::`` for IPv6. - :param family: address family (used if ``local_host`` was omitted) - :param backlog: maximum number of queued incoming connections (up to a maximum of - 2**16, or 65536) - :param reuse_port: ``True`` to allow multiple sockets to bind to the same - address/port (not supported on Windows) - :return: a multi-listener object containing one or more socket listeners - :raises OSError: if there's an error creating a socket, or binding to one or more - interfaces failed - - """ - asynclib = get_async_backend() - backlog = min(backlog, 65536) - local_host = str(local_host) if local_host is not None else None - - def setup_raw_socket( - fam: AddressFamily, - bind_addr: tuple[str, int] | tuple[str, int, int, int], - *, - v6only: bool = True, - ) -> socket.socket: - sock = socket.socket(fam) - try: - sock.setblocking(False) - - if fam == AddressFamily.AF_INET6: - sock.setsockopt(IPPROTO_IPV6, socket.IPV6_V6ONLY, v6only) - - # For Windows, enable exclusive address use. For others, enable address - # reuse. - if sys.platform == "win32": - sock.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1) - else: - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - - if reuse_port: - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) - - # Workaround for #554 - if fam == socket.AF_INET6 and "%" in bind_addr[0]: - addr, scope_id = bind_addr[0].split("%", 1) - bind_addr = (addr, bind_addr[1], 0, int(scope_id)) - - sock.bind(bind_addr) - sock.listen(backlog) - except BaseException: - sock.close() - raise - - return sock - - # We passing type=0 on non-Windows platforms as a workaround for a uvloop bug - # where we don't get the correct scope ID for IPv6 link-local addresses when passing - # type=socket.SOCK_STREAM to getaddrinfo(): - # https://github.com/MagicStack/uvloop/issues/539 - gai_res = await getaddrinfo( - local_host, - local_port, - family=family, - type=socket.SOCK_STREAM if sys.platform == "win32" else 0, - flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG, - ) - - # The set comprehension is here to work around a glibc bug: - # https://sourceware.org/bugzilla/show_bug.cgi?id=14969 - sockaddrs = sorted({res for res in gai_res if res[1] == SocketKind.SOCK_STREAM}) - - # Special case for dual-stack binding on the "any" interface - if ( - local_host is None - and family == AddressFamily.AF_UNSPEC - and socket.has_dualstack_ipv6() - and any(fam == AddressFamily.AF_INET6 for fam, *_ in gai_res) - ): - raw_socket = setup_raw_socket( - AddressFamily.AF_INET6, ("::", local_port), v6only=False - ) - listener = asynclib.create_tcp_listener(raw_socket) - return MultiListener([listener]) - - errors: list[OSError] = [] - try: - for _ in range(len(sockaddrs)): - listeners: list[SocketListener] = [] - bound_ephemeral_port = local_port - try: - for fam, *_, sockaddr in sockaddrs: - sockaddr = sockaddr[0], bound_ephemeral_port, *sockaddr[2:] - raw_socket = setup_raw_socket(fam, sockaddr) - - # Store the assigned port if an ephemeral port was requested, so - # we'll bind to the same port on all interfaces - if local_port == 0 and len(gai_res) > 1: - bound_ephemeral_port = raw_socket.getsockname()[1] - - listeners.append(asynclib.create_tcp_listener(raw_socket)) - except BaseException as exc: - for listener in listeners: - await listener.aclose() - - # If an ephemeral port was requested but binding the assigned port - # failed for another interface, rotate the address list and try again - if ( - isinstance(exc, OSError) - and exc.errno == errno.EADDRINUSE - and local_port == 0 - and bound_ephemeral_port - ): - errors.append(exc) - sockaddrs.append(sockaddrs.pop(0)) - continue - - raise - - return MultiListener(listeners) - - raise OSError( - f"Could not create {len(sockaddrs)} listeners with a consistent port" - ) from ExceptionGroup("Several bind attempts failed", errors) - finally: - del errors # Prevent reference cycles - - -async def create_unix_listener( - path: str | bytes | PathLike[Any], - *, - mode: int | None = None, - backlog: int = 65536, -) -> SocketListener: - """ - Create a UNIX socket listener. - - Not available on Windows. - - :param path: path of the socket - :param mode: permissions to set on the socket - :param backlog: maximum number of queued incoming connections (up to a maximum of - 2**16, or 65536) - :return: a listener object - - .. versionchanged:: 3.0 - If a socket already exists on the file system in the given path, it will be - removed first. - - """ - backlog = min(backlog, 65536) - raw_socket = await setup_unix_local_socket(path, mode, socket.SOCK_STREAM) - try: - raw_socket.listen(backlog) - return get_async_backend().create_unix_listener(raw_socket) - except BaseException: - raw_socket.close() - raise - - -async def create_udp_socket( - family: AnyIPAddressFamily = AddressFamily.AF_UNSPEC, - *, - local_host: IPAddressType | None = None, - local_port: int = 0, - reuse_port: bool = False, -) -> UDPSocket: - """ - Create a UDP socket. - - If ``port`` has been given, the socket will be bound to this port on the local - machine, making this socket suitable for providing UDP based services. - - :param family: address family (``AF_INET`` or ``AF_INET6``) – automatically - determined from ``local_host`` if omitted - :param local_host: IP address or host name of the local interface to bind to - :param local_port: local port to bind to - :param reuse_port: ``True`` to allow multiple sockets to bind to the same - address/port (not supported on Windows) - :return: a UDP socket - - """ - if family is AddressFamily.AF_UNSPEC and not local_host: - raise ValueError('Either "family" or "local_host" must be given') - - if local_host: - gai_res = await getaddrinfo( - str(local_host), - local_port, - family=family, - type=socket.SOCK_DGRAM, - flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG, - ) - family = cast(AnyIPAddressFamily, gai_res[0][0]) - local_address = gai_res[0][-1] - elif family is AddressFamily.AF_INET6: - local_address = ("::", 0) - else: - local_address = ("0.0.0.0", 0) - - sock = await get_async_backend().create_udp_socket( - family, local_address, None, reuse_port - ) - return cast(UDPSocket, sock) - - -async def create_connected_udp_socket( - remote_host: IPAddressType, - remote_port: int, - *, - family: AnyIPAddressFamily = AddressFamily.AF_UNSPEC, - local_host: IPAddressType | None = None, - local_port: int = 0, - reuse_port: bool = False, -) -> ConnectedUDPSocket: - """ - Create a connected UDP socket. - - Connected UDP sockets can only communicate with the specified remote host/port, an - any packets sent from other sources are dropped. - - :param remote_host: remote host to set as the default target - :param remote_port: port on the remote host to set as the default target - :param family: address family (``AF_INET`` or ``AF_INET6``) – automatically - determined from ``local_host`` or ``remote_host`` if omitted - :param local_host: IP address or host name of the local interface to bind to - :param local_port: local port to bind to - :param reuse_port: ``True`` to allow multiple sockets to bind to the same - address/port (not supported on Windows) - :return: a connected UDP socket - - """ - local_address = None - if local_host: - gai_res = await getaddrinfo( - str(local_host), - local_port, - family=family, - type=socket.SOCK_DGRAM, - flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG, - ) - family = cast(AnyIPAddressFamily, gai_res[0][0]) - local_address = gai_res[0][-1] - - gai_res = await getaddrinfo( - str(remote_host), remote_port, family=family, type=socket.SOCK_DGRAM - ) - family = cast(AnyIPAddressFamily, gai_res[0][0]) - remote_address = gai_res[0][-1] - - sock = await get_async_backend().create_udp_socket( - family, local_address, remote_address, reuse_port - ) - return cast(ConnectedUDPSocket, sock) - - -async def create_unix_datagram_socket( - *, - local_path: None | str | bytes | PathLike[Any] = None, - local_mode: int | None = None, -) -> UNIXDatagramSocket: - """ - Create a UNIX datagram socket. - - Not available on Windows. - - If ``local_path`` has been given, the socket will be bound to this path, making this - socket suitable for receiving datagrams from other processes. Other processes can - send datagrams to this socket only if ``local_path`` is set. - - If a socket already exists on the file system in the ``local_path``, it will be - removed first. - - :param local_path: the path on which to bind to - :param local_mode: permissions to set on the local socket - :return: a UNIX datagram socket - - """ - raw_socket = await setup_unix_local_socket( - local_path, local_mode, socket.SOCK_DGRAM - ) - return await get_async_backend().create_unix_datagram_socket(raw_socket, None) - - -async def create_connected_unix_datagram_socket( - remote_path: str | bytes | PathLike[Any], - *, - local_path: None | str | bytes | PathLike[Any] = None, - local_mode: int | None = None, -) -> ConnectedUNIXDatagramSocket: - """ - Create a connected UNIX datagram socket. - - Connected datagram sockets can only communicate with the specified remote path. - - If ``local_path`` has been given, the socket will be bound to this path, making - this socket suitable for receiving datagrams from other processes. Other processes - can send datagrams to this socket only if ``local_path`` is set. - - If a socket already exists on the file system in the ``local_path``, it will be - removed first. - - :param remote_path: the path to set as the default target - :param local_path: the path on which to bind to - :param local_mode: permissions to set on the local socket - :return: a connected UNIX datagram socket - - """ - remote_path = os.fspath(remote_path) - raw_socket = await setup_unix_local_socket( - local_path, local_mode, socket.SOCK_DGRAM - ) - return await get_async_backend().create_unix_datagram_socket( - raw_socket, remote_path - ) - - -async def getaddrinfo( - host: bytes | str | None, - port: str | int | None, - *, - family: int | AddressFamily = 0, - type: int | SocketKind = 0, - proto: int = 0, - flags: int = 0, -) -> list[tuple[AddressFamily, SocketKind, int, str, tuple[str, int]]]: - """ - Look up a numeric IP address given a host name. - - Internationalized domain names are translated according to the (non-transitional) - IDNA 2008 standard. - - .. note:: 4-tuple IPv6 socket addresses are automatically converted to 2-tuples of - (host, port), unlike what :func:`socket.getaddrinfo` does. - - :param host: host name - :param port: port number - :param family: socket family (`'AF_INET``, ...) - :param type: socket type (``SOCK_STREAM``, ...) - :param proto: protocol number - :param flags: flags to pass to upstream ``getaddrinfo()`` - :return: list of tuples containing (family, type, proto, canonname, sockaddr) - - .. seealso:: :func:`socket.getaddrinfo` - - """ - # Handle unicode hostnames - if isinstance(host, str): - try: - encoded_host: bytes | None = host.encode("ascii") - except UnicodeEncodeError: - import idna - - encoded_host = idna.encode(host, uts46=True) - else: - encoded_host = host - - gai_res = await get_async_backend().getaddrinfo( - encoded_host, port, family=family, type=type, proto=proto, flags=flags - ) - return [ - (family, type, proto, canonname, convert_ipv6_sockaddr(sockaddr)) - for family, type, proto, canonname, sockaddr in gai_res - # filter out IPv6 results when IPv6 is disabled - if not isinstance(sockaddr[0], int) - ] - - -def getnameinfo(sockaddr: IPSockAddrType, flags: int = 0) -> Awaitable[tuple[str, str]]: - """ - Look up the host name of an IP address. - - :param sockaddr: socket address (e.g. (ipaddress, port) for IPv4) - :param flags: flags to pass to upstream ``getnameinfo()`` - :return: a tuple of (host name, service name) - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - .. seealso:: :func:`socket.getnameinfo` - - """ - return get_async_backend().getnameinfo(sockaddr, flags) - - -@deprecated("This function is deprecated; use `wait_readable` instead") -def wait_socket_readable(sock: socket.socket) -> Awaitable[None]: - """ - .. deprecated:: 4.7.0 - Use :func:`wait_readable` instead. - - Wait until the given socket has data to be read. - - .. warning:: Only use this on raw sockets that have not been wrapped by any higher - level constructs like socket streams! - - :param sock: a socket object - :raises ~anyio.ClosedResourceError: if the socket was closed while waiting for the - socket to become readable - :raises ~anyio.BusyResourceError: if another task is already waiting for the socket - to become readable - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - """ - return get_async_backend().wait_readable(sock.fileno()) - - -@deprecated("This function is deprecated; use `wait_writable` instead") -def wait_socket_writable(sock: socket.socket) -> Awaitable[None]: - """ - .. deprecated:: 4.7.0 - Use :func:`wait_writable` instead. - - Wait until the given socket can be written to. - - This does **NOT** work on Windows when using the asyncio backend with a proactor - event loop (default on py3.8+). - - .. warning:: Only use this on raw sockets that have not been wrapped by any higher - level constructs like socket streams! - - :param sock: a socket object - :raises ~anyio.ClosedResourceError: if the socket was closed while waiting for the - socket to become writable - :raises ~anyio.BusyResourceError: if another task is already waiting for the socket - to become writable - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - """ - return get_async_backend().wait_writable(sock.fileno()) - - -def wait_readable(obj: FileDescriptorLike) -> Awaitable[None]: - """ - Wait until the given object has data to be read. - - On Unix systems, ``obj`` must either be an integer file descriptor, or else an - object with a ``.fileno()`` method which returns an integer file descriptor. Any - kind of file descriptor can be passed, though the exact semantics will depend on - your kernel. For example, this probably won't do anything useful for on-disk files. - - On Windows systems, ``obj`` must either be an integer ``SOCKET`` handle, or else an - object with a ``.fileno()`` method which returns an integer ``SOCKET`` handle. File - descriptors aren't supported, and neither are handles that refer to anything besides - a ``SOCKET``. - - On backends where this functionality is not natively provided (asyncio - ``ProactorEventLoop`` on Windows), it is provided using a separate selector thread - which is set to shut down when the interpreter shuts down. - - .. warning:: Don't use this on raw sockets that have been wrapped by any higher - level constructs like socket streams! - - :param obj: an object with a ``.fileno()`` method or an integer handle - :raises ~anyio.ClosedResourceError: if the object was closed while waiting for the - object to become readable - :raises ~anyio.BusyResourceError: if another task is already waiting for the object - to become readable - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - """ - return get_async_backend().wait_readable(obj) - - -def wait_writable(obj: FileDescriptorLike) -> Awaitable[None]: - """ - Wait until the given object can be written to. - - :param obj: an object with a ``.fileno()`` method or an integer handle - :raises ~anyio.ClosedResourceError: if the object was closed while waiting for the - object to become writable - :raises ~anyio.BusyResourceError: if another task is already waiting for the object - to become writable - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - .. seealso:: See the documentation of :func:`wait_readable` for the definition of - ``obj`` and notes on backend compatibility. - - .. warning:: Don't use this on raw sockets that have been wrapped by any higher - level constructs like socket streams! - - """ - return get_async_backend().wait_writable(obj) - - -def notify_closing(obj: FileDescriptorLike) -> None: - """ - Call this before closing a file descriptor (on Unix) or socket (on - Windows). This will cause any `wait_readable` or `wait_writable` - calls on the given object to immediately wake up and raise - `~anyio.ClosedResourceError`. - - This doesn't actually close the object – you still have to do that - yourself afterwards. Also, you want to be careful to make sure no - new tasks start waiting on the object in between when you call this - and when it's actually closed. So to close something properly, you - usually want to do these steps in order: - - 1. Explicitly mark the object as closed, so that any new attempts - to use it will abort before they start. - 2. Call `notify_closing` to wake up any already-existing users. - 3. Actually close the object. - - It's also possible to do them in a different order if that's more - convenient, *but only if* you make sure not to have any checkpoints in - between the steps. This way they all happen in a single atomic - step, so other tasks won't be able to tell what order they happened - in anyway. - - :param obj: an object with a ``.fileno()`` method or an integer handle - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - """ - get_async_backend().notify_closing(obj) - - -# -# Private API -# - - -def convert_ipv6_sockaddr( - sockaddr: tuple[str, int, int, int] | tuple[str, int], -) -> tuple[str, int]: - """ - Convert a 4-tuple IPv6 socket address to a 2-tuple (address, port) format. - - If the scope ID is nonzero, it is added to the address, separated with ``%``. - Otherwise the flow id and scope id are simply cut off from the tuple. - Any other kinds of socket addresses are returned as-is. - - :param sockaddr: the result of :meth:`~socket.socket.getsockname` - :return: the converted socket address - - """ - # This is more complicated than it should be because of MyPy - if isinstance(sockaddr, tuple) and len(sockaddr) == 4: - host, port, flowinfo, scope_id = sockaddr - if scope_id: - # PyPy (as of v7.3.11) leaves the interface name in the result, so - # we discard it and only get the scope ID from the end - # (https://foss.heptapod.net/pypy/pypy/-/issues/3938) - host = host.split("%")[0] - - # Add scope_id to the address - return f"{host}%{scope_id}", port - else: - return host, port - else: - return sockaddr - - -async def setup_unix_local_socket( - path: None | str | bytes | PathLike[Any], - mode: int | None, - socktype: int, -) -> socket.socket: - """ - Create a UNIX local socket object, deleting the socket at the given path if it - exists. - - Not available on Windows. - - :param path: path of the socket - :param mode: permissions to set on the socket - :param socktype: socket.SOCK_STREAM or socket.SOCK_DGRAM - - """ - path_str: str | None - if path is not None: - path_str = os.fsdecode(path) - - # Linux abstract namespace sockets aren't backed by a concrete file so skip stat call - if not path_str.startswith("\0"): - # Copied from pathlib... - try: - stat_result = os.stat(path) - except OSError as e: - if e.errno not in ( - errno.ENOENT, - errno.ENOTDIR, - errno.EBADF, - errno.ELOOP, - ): - raise - else: - if stat.S_ISSOCK(stat_result.st_mode): - os.unlink(path) - else: - path_str = None - - raw_socket = socket.socket(socket.AF_UNIX, socktype) - raw_socket.setblocking(False) - - if path_str is not None: - try: - await to_thread.run_sync(raw_socket.bind, path_str, abandon_on_cancel=True) - if mode is not None: - await to_thread.run_sync(chmod, path_str, mode, abandon_on_cancel=True) - except BaseException: - raw_socket.close() - raise - - return raw_socket - - -@dataclass -class TCPConnectable(ByteStreamConnectable): - """ - Connects to a TCP server at the given host and port. - - :param host: host name or IP address of the server - :param port: TCP port number of the server - """ - - host: str | IPv4Address | IPv6Address - port: int - - def __post_init__(self) -> None: - if self.port < 1 or self.port > 65535: - raise ValueError("TCP port number out of range") - - @override - async def connect(self) -> SocketStream: - try: - return await connect_tcp(self.host, self.port) - except OSError as exc: - raise ConnectionFailed( - f"error connecting to {self.host}:{self.port}: {exc}" - ) from exc - - -@dataclass -class UNIXConnectable(ByteStreamConnectable): - """ - Connects to a UNIX domain socket at the given path. - - :param path: the file system path of the socket - """ - - path: str | bytes | PathLike[str] | PathLike[bytes] - - @override - async def connect(self) -> UNIXSocketStream: - try: - return await connect_unix(self.path) - except OSError as exc: - raise ConnectionFailed(f"error connecting to {self.path!r}: {exc}") from exc - - -def as_connectable( - remote: ByteStreamConnectable - | tuple[str | IPv4Address | IPv6Address, int] - | str - | bytes - | PathLike[str], - /, - *, - tls: bool = False, - ssl_context: ssl.SSLContext | None = None, - tls_hostname: str | None = None, - tls_standard_compatible: bool = True, -) -> ByteStreamConnectable: - """ - Return a byte stream connectable from the given object. - - If a bytestream connectable is given, it is returned unchanged. - If a tuple of (host, port) is given, a TCP connectable is returned. - If a string or bytes path is given, a UNIX connectable is returned. - - If ``tls=True``, the connectable will be wrapped in a - :class:`~.streams.tls.TLSConnectable`. - - :param remote: a connectable, a tuple of (host, port) or a path to a UNIX socket - :param tls: if ``True``, wrap the plaintext connectable in a - :class:`~.streams.tls.TLSConnectable`, using the provided TLS settings) - :param ssl_context: if ``tls=True``, the SSLContext object to use (if not provided, - a secure default will be created) - :param tls_hostname: if ``tls=True``, host name of the server to use for checking - the server certificate (defaults to the host portion of the address for TCP - connectables) - :param tls_standard_compatible: if ``False`` and ``tls=True``, makes the TLS stream - skip the closing handshake when closing the connection, so it won't raise an - exception if the server does the same - - """ - connectable: TCPConnectable | UNIXConnectable | TLSConnectable - if isinstance(remote, ByteStreamConnectable): - return remote - elif isinstance(remote, tuple) and len(remote) == 2: - connectable = TCPConnectable(*remote) - elif isinstance(remote, (str, bytes, PathLike)): - connectable = UNIXConnectable(remote) - else: - raise TypeError(f"cannot convert {remote!r} to a connectable") - - if tls: - if not tls_hostname and isinstance(connectable, TCPConnectable): - tls_hostname = str(connectable.host) - - connectable = TLSConnectable( - connectable, - ssl_context=ssl_context, - hostname=tls_hostname, - standard_compatible=tls_standard_compatible, - ) - - return connectable diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_streams.py b/notification-service/venv/Lib/site-packages/anyio/_core/_streams.py deleted file mode 100644 index 2b9c7df..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_streams.py +++ /dev/null @@ -1,52 +0,0 @@ -from __future__ import annotations - -import math -from typing import TypeVar -from warnings import warn - -from ..streams.memory import ( - MemoryObjectReceiveStream, - MemoryObjectSendStream, - _MemoryObjectStreamState, -) - -T_Item = TypeVar("T_Item") - - -class create_memory_object_stream( - tuple[MemoryObjectSendStream[T_Item], MemoryObjectReceiveStream[T_Item]], -): - """ - Create a memory object stream. - - The stream's item type can be annotated like - :func:`create_memory_object_stream[T_Item]`. - - :param max_buffer_size: number of items held in the buffer until ``send()`` starts - blocking - :param item_type: old way of marking the streams with the right generic type for - static typing (does nothing on AnyIO 4) - - .. deprecated:: 4.0 - Use ``create_memory_object_stream[YourItemType](...)`` instead. - :return: a tuple of (send stream, receive stream) - - """ - - def __new__( # type: ignore[misc] - cls, max_buffer_size: float = 0, item_type: object = None - ) -> tuple[MemoryObjectSendStream[T_Item], MemoryObjectReceiveStream[T_Item]]: - if max_buffer_size != math.inf and not isinstance(max_buffer_size, int): - raise ValueError("max_buffer_size must be either an integer or math.inf") - if max_buffer_size < 0: - raise ValueError("max_buffer_size cannot be negative") - if item_type is not None: - warn( - "The item_type argument has been deprecated in AnyIO 4.0. " - "Use create_memory_object_stream[YourItemType](...) instead.", - DeprecationWarning, - stacklevel=2, - ) - - state = _MemoryObjectStreamState[T_Item](max_buffer_size) - return (MemoryObjectSendStream(state), MemoryObjectReceiveStream(state)) diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_subprocesses.py b/notification-service/venv/Lib/site-packages/anyio/_core/_subprocesses.py deleted file mode 100644 index 9796f8b..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_subprocesses.py +++ /dev/null @@ -1,196 +0,0 @@ -from __future__ import annotations - -from collections.abc import AsyncIterable, Iterable, Mapping, Sequence -from io import BytesIO -from os import PathLike -from subprocess import PIPE, CalledProcessError, CompletedProcess -from typing import IO, Any, TypeAlias, cast - -from ..abc import Process -from ._eventloop import get_async_backend -from ._tasks import create_task_group - -StrOrBytesPath: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes] - - -async def run_process( - command: StrOrBytesPath | Sequence[StrOrBytesPath], - *, - input: bytes | None = None, - stdin: int | IO[Any] | None = None, - stdout: int | IO[Any] | None = PIPE, - stderr: int | IO[Any] | None = PIPE, - check: bool = True, - cwd: StrOrBytesPath | None = None, - env: Mapping[str, str] | None = None, - startupinfo: Any = None, - creationflags: int = 0, - start_new_session: bool = False, - pass_fds: Sequence[int] = (), - user: str | int | None = None, - group: str | int | None = None, - extra_groups: Iterable[str | int] | None = None, - umask: int = -1, -) -> CompletedProcess[bytes]: - """ - Run an external command in a subprocess and wait until it completes. - - .. seealso:: :func:`subprocess.run` - - :param command: either a string to pass to the shell, or an iterable of strings - containing the executable name or path and its arguments - :param input: bytes passed to the standard input of the subprocess - :param stdin: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, - a file-like object, or `None`; ``input`` overrides this - :param stdout: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, - a file-like object, or `None` - :param stderr: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, - :data:`subprocess.STDOUT`, a file-like object, or `None` - :param check: if ``True``, raise :exc:`~subprocess.CalledProcessError` if the - process terminates with a return code other than 0 - :param cwd: If not ``None``, change the working directory to this before running the - command - :param env: if not ``None``, this mapping replaces the inherited environment - variables from the parent process - :param startupinfo: an instance of :class:`subprocess.STARTUPINFO` that can be used - to specify process startup parameters (Windows only) - :param creationflags: flags that can be used to control the creation of the - subprocess (see :class:`subprocess.Popen` for the specifics) - :param start_new_session: if ``true`` the setsid() system call will be made in the - child process prior to the execution of the subprocess. (POSIX only) - :param pass_fds: sequence of file descriptors to keep open between the parent and - child processes. (POSIX only) - :param user: effective user to run the process as (Python >= 3.9, POSIX only) - :param group: effective group to run the process as (Python >= 3.9, POSIX only) - :param extra_groups: supplementary groups to set in the subprocess (Python >= 3.9, - POSIX only) - :param umask: if not negative, this umask is applied in the child process before - running the given command (Python >= 3.9, POSIX only) - :return: an object representing the completed process - :raises ~subprocess.CalledProcessError: if ``check`` is ``True`` and the process - exits with a nonzero return code - - """ - - async def drain_stream(stream: AsyncIterable[bytes], index: int) -> None: - buffer = BytesIO() - async for chunk in stream: - buffer.write(chunk) - - stream_contents[index] = buffer.getvalue() - - if stdin is not None and input is not None: - raise ValueError("only one of stdin and input is allowed") - - async with await open_process( - command, - stdin=PIPE if input else stdin, - stdout=stdout, - stderr=stderr, - cwd=cwd, - env=env, - startupinfo=startupinfo, - creationflags=creationflags, - start_new_session=start_new_session, - pass_fds=pass_fds, - user=user, - group=group, - extra_groups=extra_groups, - umask=umask, - ) as process: - stream_contents: list[bytes | None] = [None, None] - async with create_task_group() as tg: - if process.stdout: - tg.start_soon(drain_stream, process.stdout, 0) - - if process.stderr: - tg.start_soon(drain_stream, process.stderr, 1) - - if process.stdin and input: - await process.stdin.send(input) - await process.stdin.aclose() - - await process.wait() - - output, errors = stream_contents - if check and process.returncode != 0: - raise CalledProcessError(cast(int, process.returncode), command, output, errors) - - return CompletedProcess(command, cast(int, process.returncode), output, errors) - - -async def open_process( - command: StrOrBytesPath | Sequence[StrOrBytesPath], - *, - stdin: int | IO[Any] | None = PIPE, - stdout: int | IO[Any] | None = PIPE, - stderr: int | IO[Any] | None = PIPE, - cwd: StrOrBytesPath | None = None, - env: Mapping[str, str] | None = None, - startupinfo: Any = None, - creationflags: int = 0, - start_new_session: bool = False, - pass_fds: Sequence[int] = (), - user: str | int | None = None, - group: str | int | None = None, - extra_groups: Iterable[str | int] | None = None, - umask: int = -1, -) -> Process: - """ - Start an external command in a subprocess. - - .. seealso:: :class:`subprocess.Popen` - - :param command: either a string to pass to the shell, or an iterable of strings - containing the executable name or path and its arguments - :param stdin: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, a - file-like object, or ``None`` - :param stdout: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, - a file-like object, or ``None`` - :param stderr: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, - :data:`subprocess.STDOUT`, a file-like object, or ``None`` - :param cwd: If not ``None``, the working directory is changed before executing - :param env: If env is not ``None``, it must be a mapping that defines the - environment variables for the new process - :param creationflags: flags that can be used to control the creation of the - subprocess (see :class:`subprocess.Popen` for the specifics) - :param startupinfo: an instance of :class:`subprocess.STARTUPINFO` that can be used - to specify process startup parameters (Windows only) - :param start_new_session: if ``true`` the setsid() system call will be made in the - child process prior to the execution of the subprocess. (POSIX only) - :param pass_fds: sequence of file descriptors to keep open between the parent and - child processes. (POSIX only) - :param user: effective user to run the process as (POSIX only) - :param group: effective group to run the process as (POSIX only) - :param extra_groups: supplementary groups to set in the subprocess (POSIX only) - :param umask: if not negative, this umask is applied in the child process before - running the given command (POSIX only) - :return: an asynchronous process object - - """ - kwargs: dict[str, Any] = {} - if user is not None: - kwargs["user"] = user - - if group is not None: - kwargs["group"] = group - - if extra_groups is not None: - kwargs["extra_groups"] = group - - if umask >= 0: - kwargs["umask"] = umask - - return await get_async_backend().open_process( - command, - stdin=stdin, - stdout=stdout, - stderr=stderr, - cwd=cwd, - env=env, - startupinfo=startupinfo, - creationflags=creationflags, - start_new_session=start_new_session, - pass_fds=pass_fds, - **kwargs, - ) diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_synchronization.py b/notification-service/venv/Lib/site-packages/anyio/_core/_synchronization.py deleted file mode 100644 index 9c6f9a0..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_synchronization.py +++ /dev/null @@ -1,757 +0,0 @@ -from __future__ import annotations - -import math -from collections import deque -from collections.abc import Callable -from dataclasses import dataclass -from types import TracebackType -from typing import TypeVar - -from ..lowlevel import checkpoint_if_cancelled -from ._eventloop import get_async_backend -from ._exceptions import BusyResourceError, NoEventLoopError -from ._tasks import CancelScope -from ._testing import TaskInfo, get_current_task - -T = TypeVar("T") - - -@dataclass(frozen=True) -class EventStatistics: - """ - :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Event.wait` - """ - - tasks_waiting: int - - -@dataclass(frozen=True) -class CapacityLimiterStatistics: - """ - :ivar int borrowed_tokens: number of tokens currently borrowed by tasks - :ivar float total_tokens: total number of available tokens - :ivar tuple borrowers: tasks or other objects currently holding tokens borrowed from - this limiter - :ivar int tasks_waiting: number of tasks waiting on - :meth:`~.CapacityLimiter.acquire` or - :meth:`~.CapacityLimiter.acquire_on_behalf_of` - """ - - borrowed_tokens: int - total_tokens: float - borrowers: tuple[object, ...] - tasks_waiting: int - - -@dataclass(frozen=True) -class LockStatistics: - """ - :ivar bool locked: flag indicating if this lock is locked or not - :ivar ~anyio.TaskInfo owner: task currently holding the lock (or ``None`` if the - lock is not held by any task) - :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Lock.acquire` - """ - - locked: bool - owner: TaskInfo | None - tasks_waiting: int - - -@dataclass(frozen=True) -class ConditionStatistics: - """ - :ivar int tasks_waiting: number of tasks blocked on :meth:`~.Condition.wait` - :ivar ~anyio.LockStatistics lock_statistics: statistics of the underlying - :class:`~.Lock` - """ - - tasks_waiting: int - lock_statistics: LockStatistics - - -@dataclass(frozen=True) -class SemaphoreStatistics: - """ - :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Semaphore.acquire` - - """ - - tasks_waiting: int - - -class Event: - def __new__(cls) -> Event: - try: - return get_async_backend().create_event() - except NoEventLoopError: - return EventAdapter() - - def set(self) -> None: - """Set the flag, notifying all listeners.""" - raise NotImplementedError - - def is_set(self) -> bool: - """Return ``True`` if the flag is set, ``False`` if not.""" - raise NotImplementedError - - async def wait(self) -> None: - """ - Wait until the flag has been set. - - If the flag has already been set when this method is called, it returns - immediately. - - """ - raise NotImplementedError - - def statistics(self) -> EventStatistics: - """Return statistics about the current state of this event.""" - raise NotImplementedError - - -class EventAdapter(Event): - _internal_event: Event | None = None - _is_set: bool = False - - def __new__(cls) -> EventAdapter: - return object.__new__(cls) - - @property - def _event(self) -> Event: - if self._internal_event is None: - self._internal_event = get_async_backend().create_event() - if self._is_set: - self._internal_event.set() - - return self._internal_event - - def set(self) -> None: - if self._internal_event is None: - self._is_set = True - else: - self._event.set() - - def is_set(self) -> bool: - if self._internal_event is None: - return self._is_set - - return self._internal_event.is_set() - - async def wait(self) -> None: - await self._event.wait() - - def statistics(self) -> EventStatistics: - if self._internal_event is None: - return EventStatistics(tasks_waiting=0) - - return self._internal_event.statistics() - - -class Lock: - def __new__(cls, *, fast_acquire: bool = False) -> Lock: - try: - return get_async_backend().create_lock(fast_acquire=fast_acquire) - except NoEventLoopError: - return LockAdapter(fast_acquire=fast_acquire) - - async def __aenter__(self) -> None: - await self.acquire() - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self.release() - - async def acquire(self) -> None: - """Acquire the lock.""" - raise NotImplementedError - - def acquire_nowait(self) -> None: - """ - Acquire the lock, without blocking. - - :raises ~anyio.WouldBlock: if the operation would block - - """ - raise NotImplementedError - - def release(self) -> None: - """Release the lock.""" - raise NotImplementedError - - def locked(self) -> bool: - """Return True if the lock is currently held.""" - raise NotImplementedError - - def statistics(self) -> LockStatistics: - """ - Return statistics about the current state of this lock. - - .. versionadded:: 3.0 - """ - raise NotImplementedError - - -class LockAdapter(Lock): - _internal_lock: Lock | None = None - - def __new__(cls, *, fast_acquire: bool = False) -> LockAdapter: - return object.__new__(cls) - - def __init__(self, *, fast_acquire: bool = False): - self._fast_acquire = fast_acquire - - @property - def _lock(self) -> Lock: - if self._internal_lock is None: - self._internal_lock = get_async_backend().create_lock( - fast_acquire=self._fast_acquire - ) - - return self._internal_lock - - async def __aenter__(self) -> None: - await self._lock.acquire() - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - if self._internal_lock is not None: - self._internal_lock.release() - - async def acquire(self) -> None: - """Acquire the lock.""" - await self._lock.acquire() - - def acquire_nowait(self) -> None: - """ - Acquire the lock, without blocking. - - :raises ~anyio.WouldBlock: if the operation would block - - """ - self._lock.acquire_nowait() - - def release(self) -> None: - """Release the lock.""" - self._lock.release() - - def locked(self) -> bool: - """Return True if the lock is currently held.""" - return self._lock.locked() - - def statistics(self) -> LockStatistics: - """ - Return statistics about the current state of this lock. - - .. versionadded:: 3.0 - - """ - if self._internal_lock is None: - return LockStatistics(False, None, 0) - - return self._internal_lock.statistics() - - -class Condition: - _owner_task: TaskInfo | None = None - - def __init__(self, lock: Lock | None = None): - self._lock = lock or Lock() - self._waiters: deque[Event] = deque() - - async def __aenter__(self) -> None: - await self.acquire() - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self.release() - - def _check_acquired(self) -> None: - if self._owner_task != get_current_task(): - raise RuntimeError("The current task is not holding the underlying lock") - - async def acquire(self) -> None: - """Acquire the underlying lock.""" - await self._lock.acquire() - self._owner_task = get_current_task() - - def acquire_nowait(self) -> None: - """ - Acquire the underlying lock, without blocking. - - :raises ~anyio.WouldBlock: if the operation would block - - """ - self._lock.acquire_nowait() - self._owner_task = get_current_task() - - def release(self) -> None: - """Release the underlying lock.""" - self._lock.release() - - def locked(self) -> bool: - """Return True if the lock is set.""" - return self._lock.locked() - - def notify(self, n: int = 1) -> None: - """Notify exactly n listeners.""" - self._check_acquired() - for _ in range(n): - try: - event = self._waiters.popleft() - except IndexError: - break - - event.set() - - def notify_all(self) -> None: - """Notify all the listeners.""" - self._check_acquired() - for event in self._waiters: - event.set() - - self._waiters.clear() - - async def wait(self) -> None: - """Wait for a notification.""" - await checkpoint_if_cancelled() - self._check_acquired() - event = Event() - self._waiters.append(event) - self.release() - try: - await event.wait() - except BaseException: - if not event.is_set(): - self._waiters.remove(event) - elif self._waiters: - # This task was notified by could not act on it, so pass - # it on to the next task - self._waiters.popleft().set() - - raise - finally: - with CancelScope(shield=True): - await self.acquire() - - async def wait_for(self, predicate: Callable[[], T]) -> T: - """ - Wait until a predicate becomes true. - - :param predicate: a callable that returns a truthy value when the condition is - met - :return: the result of the predicate - - .. versionadded:: 4.11.0 - - """ - while not (result := predicate()): - await self.wait() - - return result - - def statistics(self) -> ConditionStatistics: - """ - Return statistics about the current state of this condition. - - .. versionadded:: 3.0 - """ - return ConditionStatistics(len(self._waiters), self._lock.statistics()) - - -class Semaphore: - def __new__( - cls, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> Semaphore: - try: - return get_async_backend().create_semaphore( - initial_value, max_value=max_value, fast_acquire=fast_acquire - ) - except NoEventLoopError: - return SemaphoreAdapter(initial_value, max_value=max_value) - - def __init__( - self, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ): - if not isinstance(initial_value, int): - raise TypeError("initial_value must be an integer") - if initial_value < 0: - raise ValueError("initial_value must be >= 0") - if max_value is not None: - if not isinstance(max_value, int): - raise TypeError("max_value must be an integer or None") - if max_value < initial_value: - raise ValueError( - "max_value must be equal to or higher than initial_value" - ) - - self._fast_acquire = fast_acquire - - async def __aenter__(self) -> Semaphore: - await self.acquire() - return self - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self.release() - - async def acquire(self) -> None: - """Decrement the semaphore value, blocking if necessary.""" - raise NotImplementedError - - def acquire_nowait(self) -> None: - """ - Acquire the underlying lock, without blocking. - - :raises ~anyio.WouldBlock: if the operation would block - - """ - raise NotImplementedError - - def release(self) -> None: - """Increment the semaphore value.""" - raise NotImplementedError - - @property - def value(self) -> int: - """The current value of the semaphore.""" - raise NotImplementedError - - @property - def max_value(self) -> int | None: - """The maximum value of the semaphore.""" - raise NotImplementedError - - def statistics(self) -> SemaphoreStatistics: - """ - Return statistics about the current state of this semaphore. - - .. versionadded:: 3.0 - """ - raise NotImplementedError - - -class SemaphoreAdapter(Semaphore): - _internal_semaphore: Semaphore | None = None - - def __new__( - cls, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> SemaphoreAdapter: - return object.__new__(cls) - - def __init__( - self, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> None: - super().__init__(initial_value, max_value=max_value, fast_acquire=fast_acquire) - self._initial_value = initial_value - self._max_value = max_value - - @property - def _semaphore(self) -> Semaphore: - if self._internal_semaphore is None: - self._internal_semaphore = get_async_backend().create_semaphore( - self._initial_value, max_value=self._max_value - ) - - return self._internal_semaphore - - async def acquire(self) -> None: - await self._semaphore.acquire() - - def acquire_nowait(self) -> None: - self._semaphore.acquire_nowait() - - def release(self) -> None: - self._semaphore.release() - - @property - def value(self) -> int: - if self._internal_semaphore is None: - return self._initial_value - - return self._semaphore.value - - @property - def max_value(self) -> int | None: - return self._max_value - - def statistics(self) -> SemaphoreStatistics: - if self._internal_semaphore is None: - return SemaphoreStatistics(tasks_waiting=0) - - return self._semaphore.statistics() - - -class CapacityLimiter: - def __new__(cls, total_tokens: float) -> CapacityLimiter: - try: - return get_async_backend().create_capacity_limiter(total_tokens) - except NoEventLoopError: - return CapacityLimiterAdapter(total_tokens) - - async def __aenter__(self) -> None: - raise NotImplementedError - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - raise NotImplementedError - - @property - def total_tokens(self) -> float: - """ - The total number of tokens available for borrowing. - - This is a read-write property. If the total number of tokens is increased, the - proportionate number of tasks waiting on this limiter will be granted their - tokens. - - .. versionchanged:: 3.0 - The property is now writable. - .. versionchanged:: 4.12 - The value can now be set to 0. - - """ - raise NotImplementedError - - @total_tokens.setter - def total_tokens(self, value: float) -> None: - raise NotImplementedError - - @property - def borrowed_tokens(self) -> int: - """The number of tokens that have currently been borrowed.""" - raise NotImplementedError - - @property - def available_tokens(self) -> float: - """The number of tokens currently available to be borrowed""" - raise NotImplementedError - - def acquire_nowait(self) -> None: - """ - Acquire a token for the current task without waiting for one to become - available. - - :raises ~anyio.WouldBlock: if there are no tokens available for borrowing - - """ - raise NotImplementedError - - def acquire_on_behalf_of_nowait(self, borrower: object) -> None: - """ - Acquire a token without waiting for one to become available. - - :param borrower: the entity borrowing a token - :raises ~anyio.WouldBlock: if there are no tokens available for borrowing - - """ - raise NotImplementedError - - async def acquire(self) -> None: - """ - Acquire a token for the current task, waiting if necessary for one to become - available. - - """ - raise NotImplementedError - - async def acquire_on_behalf_of(self, borrower: object) -> None: - """ - Acquire a token, waiting if necessary for one to become available. - - :param borrower: the entity borrowing a token - - """ - raise NotImplementedError - - def release(self) -> None: - """ - Release the token held by the current task. - - :raises RuntimeError: if the current task has not borrowed a token from this - limiter. - - """ - raise NotImplementedError - - def release_on_behalf_of(self, borrower: object) -> None: - """ - Release the token held by the given borrower. - - :raises RuntimeError: if the borrower has not borrowed a token from this - limiter. - - """ - raise NotImplementedError - - def statistics(self) -> CapacityLimiterStatistics: - """ - Return statistics about the current state of this limiter. - - .. versionadded:: 3.0 - - """ - raise NotImplementedError - - -class CapacityLimiterAdapter(CapacityLimiter): - _internal_limiter: CapacityLimiter | None = None - - def __new__(cls, total_tokens: float) -> CapacityLimiterAdapter: - return object.__new__(cls) - - def __init__(self, total_tokens: float) -> None: - self.total_tokens = total_tokens - - @property - def _limiter(self) -> CapacityLimiter: - if self._internal_limiter is None: - self._internal_limiter = get_async_backend().create_capacity_limiter( - self._total_tokens - ) - - return self._internal_limiter - - async def __aenter__(self) -> None: - await self._limiter.__aenter__() - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - return await self._limiter.__aexit__(exc_type, exc_val, exc_tb) - - @property - def total_tokens(self) -> float: - if self._internal_limiter is None: - return self._total_tokens - - return self._internal_limiter.total_tokens - - @total_tokens.setter - def total_tokens(self, value: float) -> None: - if not isinstance(value, int) and value is not math.inf: - raise TypeError("total_tokens must be an int or math.inf") - elif value < 1: - raise ValueError("total_tokens must be >= 1") - - if self._internal_limiter is None: - self._total_tokens = value - return - - self._limiter.total_tokens = value - - @property - def borrowed_tokens(self) -> int: - if self._internal_limiter is None: - return 0 - - return self._internal_limiter.borrowed_tokens - - @property - def available_tokens(self) -> float: - if self._internal_limiter is None: - return self._total_tokens - - return self._internal_limiter.available_tokens - - def acquire_nowait(self) -> None: - self._limiter.acquire_nowait() - - def acquire_on_behalf_of_nowait(self, borrower: object) -> None: - self._limiter.acquire_on_behalf_of_nowait(borrower) - - async def acquire(self) -> None: - await self._limiter.acquire() - - async def acquire_on_behalf_of(self, borrower: object) -> None: - await self._limiter.acquire_on_behalf_of(borrower) - - def release(self) -> None: - self._limiter.release() - - def release_on_behalf_of(self, borrower: object) -> None: - self._limiter.release_on_behalf_of(borrower) - - def statistics(self) -> CapacityLimiterStatistics: - if self._internal_limiter is None: - return CapacityLimiterStatistics( - borrowed_tokens=0, - total_tokens=self.total_tokens, - borrowers=(), - tasks_waiting=0, - ) - - return self._internal_limiter.statistics() - - -class ResourceGuard: - """ - A context manager for ensuring that a resource is only used by a single task at a - time. - - Entering this context manager while the previous has not exited it yet will trigger - :exc:`BusyResourceError`. - - :param action: the action to guard against (visible in the :exc:`BusyResourceError` - when triggered, e.g. "Another task is already {action} this resource") - - .. versionadded:: 4.1 - """ - - __slots__ = "action", "_guarded" - - def __init__(self, action: str = "using"): - self.action: str = action - self._guarded = False - - def __enter__(self) -> None: - if self._guarded: - raise BusyResourceError(self.action) - - self._guarded = True - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self._guarded = False diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_tasks.py b/notification-service/venv/Lib/site-packages/anyio/_core/_tasks.py deleted file mode 100644 index 0688bfe..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_tasks.py +++ /dev/null @@ -1,173 +0,0 @@ -from __future__ import annotations - -import math -from collections.abc import Generator -from contextlib import contextmanager -from types import TracebackType - -from ..abc._tasks import TaskGroup, TaskStatus -from ._eventloop import get_async_backend - - -class _IgnoredTaskStatus(TaskStatus[object]): - def started(self, value: object = None) -> None: - pass - - -TASK_STATUS_IGNORED = _IgnoredTaskStatus() - - -class CancelScope: - """ - Wraps a unit of work that can be made separately cancellable. - - :param deadline: The time (clock value) when this scope is cancelled automatically - :param shield: ``True`` to shield the cancel scope from external cancellation - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - """ - - def __new__( - cls, *, deadline: float = math.inf, shield: bool = False - ) -> CancelScope: - return get_async_backend().create_cancel_scope(shield=shield, deadline=deadline) - - def cancel(self, reason: str | None = None) -> None: - """ - Cancel this scope immediately. - - :param reason: a message describing the reason for the cancellation - - """ - raise NotImplementedError - - @property - def deadline(self) -> float: - """ - The time (clock value) when this scope is cancelled automatically. - - Will be ``float('inf')`` if no timeout has been set. - - """ - raise NotImplementedError - - @deadline.setter - def deadline(self, value: float) -> None: - raise NotImplementedError - - @property - def cancel_called(self) -> bool: - """``True`` if :meth:`cancel` has been called.""" - raise NotImplementedError - - @property - def cancelled_caught(self) -> bool: - """ - ``True`` if this scope suppressed a cancellation exception it itself raised. - - This is typically used to check if any work was interrupted, or to see if the - scope was cancelled due to its deadline being reached. The value will, however, - only be ``True`` if the cancellation was triggered by the scope itself (and not - an outer scope). - - """ - raise NotImplementedError - - @property - def shield(self) -> bool: - """ - ``True`` if this scope is shielded from external cancellation. - - While a scope is shielded, it will not receive cancellations from outside. - - """ - raise NotImplementedError - - @shield.setter - def shield(self, value: bool) -> None: - raise NotImplementedError - - def __enter__(self) -> CancelScope: - raise NotImplementedError - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool: - raise NotImplementedError - - -@contextmanager -def fail_after( - delay: float | None, shield: bool = False -) -> Generator[CancelScope, None, None]: - """ - Create a context manager which raises a :class:`TimeoutError` if does not finish in - time. - - :param delay: maximum allowed time (in seconds) before raising the exception, or - ``None`` to disable the timeout - :param shield: ``True`` to shield the cancel scope from external cancellation - :return: a context manager that yields a cancel scope - :rtype: :class:`~typing.ContextManager`\\[:class:`~anyio.CancelScope`\\] - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - """ - current_time = get_async_backend().current_time - deadline = (current_time() + delay) if delay is not None else math.inf - with get_async_backend().create_cancel_scope( - deadline=deadline, shield=shield - ) as cancel_scope: - yield cancel_scope - - if cancel_scope.cancelled_caught and current_time() >= cancel_scope.deadline: - raise TimeoutError - - -def move_on_after(delay: float | None, shield: bool = False) -> CancelScope: - """ - Create a cancel scope with a deadline that expires after the given delay. - - :param delay: maximum allowed time (in seconds) before exiting the context block, or - ``None`` to disable the timeout - :param shield: ``True`` to shield the cancel scope from external cancellation - :return: a cancel scope - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - """ - deadline = ( - (get_async_backend().current_time() + delay) if delay is not None else math.inf - ) - return get_async_backend().create_cancel_scope(deadline=deadline, shield=shield) - - -def current_effective_deadline() -> float: - """ - Return the nearest deadline among all the cancel scopes effective for the current - task. - - :return: a clock value from the event loop's internal clock (or ``float('inf')`` if - there is no deadline in effect, or ``float('-inf')`` if the current scope has - been cancelled) - :rtype: float - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - """ - return get_async_backend().current_effective_deadline() - - -def create_task_group() -> TaskGroup: - """ - Create a task group. - - :return: a task group - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - """ - return get_async_backend().create_task_group() diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_tempfile.py b/notification-service/venv/Lib/site-packages/anyio/_core/_tempfile.py deleted file mode 100644 index 75a09f7..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_tempfile.py +++ /dev/null @@ -1,613 +0,0 @@ -from __future__ import annotations - -import os -import sys -import tempfile -from collections.abc import Iterable -from io import BytesIO, TextIOWrapper -from types import TracebackType -from typing import ( - TYPE_CHECKING, - Any, - AnyStr, - Generic, - overload, -) - -from .. import to_thread -from .._core._fileio import AsyncFile -from ..lowlevel import checkpoint_if_cancelled - -if TYPE_CHECKING: - from _typeshed import OpenBinaryMode, OpenTextMode, ReadableBuffer, WriteableBuffer - - -class TemporaryFile(Generic[AnyStr]): - """ - An asynchronous temporary file that is automatically created and cleaned up. - - This class provides an asynchronous context manager interface to a temporary file. - The file is created using Python's standard `tempfile.TemporaryFile` function in a - background thread, and is wrapped as an asynchronous file using `AsyncFile`. - - :param mode: The mode in which the file is opened. Defaults to "w+b". - :param buffering: The buffering policy (-1 means the default buffering). - :param encoding: The encoding used to decode or encode the file. Only applicable in - text mode. - :param newline: Controls how universal newlines mode works (only applicable in text - mode). - :param suffix: The suffix for the temporary file name. - :param prefix: The prefix for the temporary file name. - :param dir: The directory in which the temporary file is created. - :param errors: The error handling scheme used for encoding/decoding errors. - """ - - _async_file: AsyncFile[AnyStr] - - @overload - def __init__( - self: TemporaryFile[bytes], - mode: OpenBinaryMode = ..., - buffering: int = ..., - encoding: str | None = ..., - newline: str | None = ..., - suffix: str | None = ..., - prefix: str | None = ..., - dir: str | None = ..., - *, - errors: str | None = ..., - ): ... - @overload - def __init__( - self: TemporaryFile[str], - mode: OpenTextMode, - buffering: int = ..., - encoding: str | None = ..., - newline: str | None = ..., - suffix: str | None = ..., - prefix: str | None = ..., - dir: str | None = ..., - *, - errors: str | None = ..., - ): ... - - def __init__( - self, - mode: OpenTextMode | OpenBinaryMode = "w+b", - buffering: int = -1, - encoding: str | None = None, - newline: str | None = None, - suffix: str | None = None, - prefix: str | None = None, - dir: str | None = None, - *, - errors: str | None = None, - ) -> None: - self.mode = mode - self.buffering = buffering - self.encoding = encoding - self.newline = newline - self.suffix: str | None = suffix - self.prefix: str | None = prefix - self.dir: str | None = dir - self.errors = errors - - async def __aenter__(self) -> AsyncFile[AnyStr]: - fp = await to_thread.run_sync( - lambda: tempfile.TemporaryFile( - self.mode, - self.buffering, - self.encoding, - self.newline, - self.suffix, - self.prefix, - self.dir, - errors=self.errors, - ) - ) - self._async_file = AsyncFile(fp) - return self._async_file - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_value: BaseException | None, - traceback: TracebackType | None, - ) -> None: - await self._async_file.aclose() - - -class NamedTemporaryFile(Generic[AnyStr]): - """ - An asynchronous named temporary file that is automatically created and cleaned up. - - This class provides an asynchronous context manager for a temporary file with a - visible name in the file system. It uses Python's standard - :func:`~tempfile.NamedTemporaryFile` function and wraps the file object with - :class:`AsyncFile` for asynchronous operations. - - :param mode: The mode in which the file is opened. Defaults to "w+b". - :param buffering: The buffering policy (-1 means the default buffering). - :param encoding: The encoding used to decode or encode the file. Only applicable in - text mode. - :param newline: Controls how universal newlines mode works (only applicable in text - mode). - :param suffix: The suffix for the temporary file name. - :param prefix: The prefix for the temporary file name. - :param dir: The directory in which the temporary file is created. - :param delete: Whether to delete the file when it is closed. - :param errors: The error handling scheme used for encoding/decoding errors. - :param delete_on_close: (Python 3.12+) Whether to delete the file on close. - """ - - _async_file: AsyncFile[AnyStr] - - @overload - def __init__( - self: NamedTemporaryFile[bytes], - mode: OpenBinaryMode = ..., - buffering: int = ..., - encoding: str | None = ..., - newline: str | None = ..., - suffix: str | None = ..., - prefix: str | None = ..., - dir: str | None = ..., - delete: bool = ..., - *, - errors: str | None = ..., - delete_on_close: bool = ..., - ): ... - @overload - def __init__( - self: NamedTemporaryFile[str], - mode: OpenTextMode, - buffering: int = ..., - encoding: str | None = ..., - newline: str | None = ..., - suffix: str | None = ..., - prefix: str | None = ..., - dir: str | None = ..., - delete: bool = ..., - *, - errors: str | None = ..., - delete_on_close: bool = ..., - ): ... - - def __init__( - self, - mode: OpenBinaryMode | OpenTextMode = "w+b", - buffering: int = -1, - encoding: str | None = None, - newline: str | None = None, - suffix: str | None = None, - prefix: str | None = None, - dir: str | None = None, - delete: bool = True, - *, - errors: str | None = None, - delete_on_close: bool = True, - ) -> None: - self._params: dict[str, Any] = { - "mode": mode, - "buffering": buffering, - "encoding": encoding, - "newline": newline, - "suffix": suffix, - "prefix": prefix, - "dir": dir, - "delete": delete, - "errors": errors, - } - if sys.version_info >= (3, 12): - self._params["delete_on_close"] = delete_on_close - - async def __aenter__(self) -> AsyncFile[AnyStr]: - fp = await to_thread.run_sync( - lambda: tempfile.NamedTemporaryFile(**self._params) - ) - self._async_file = AsyncFile(fp) - return self._async_file - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_value: BaseException | None, - traceback: TracebackType | None, - ) -> None: - await self._async_file.aclose() - - -class SpooledTemporaryFile(AsyncFile[AnyStr]): - """ - An asynchronous spooled temporary file that starts in memory and is spooled to disk. - - This class provides an asynchronous interface to a spooled temporary file, much like - Python's standard :class:`~tempfile.SpooledTemporaryFile`. It supports asynchronous - write operations and provides a method to force a rollover to disk. - - :param max_size: Maximum size in bytes before the file is rolled over to disk. - :param mode: The mode in which the file is opened. Defaults to "w+b". - :param buffering: The buffering policy (-1 means the default buffering). - :param encoding: The encoding used to decode or encode the file (text mode only). - :param newline: Controls how universal newlines mode works (text mode only). - :param suffix: The suffix for the temporary file name. - :param prefix: The prefix for the temporary file name. - :param dir: The directory in which the temporary file is created. - :param errors: The error handling scheme used for encoding/decoding errors. - """ - - _rolled: bool = False - - @overload - def __init__( - self: SpooledTemporaryFile[bytes], - max_size: int = ..., - mode: OpenBinaryMode = ..., - buffering: int = ..., - encoding: str | None = ..., - newline: str | None = ..., - suffix: str | None = ..., - prefix: str | None = ..., - dir: str | None = ..., - *, - errors: str | None = ..., - ): ... - @overload - def __init__( - self: SpooledTemporaryFile[str], - max_size: int = ..., - mode: OpenTextMode = ..., - buffering: int = ..., - encoding: str | None = ..., - newline: str | None = ..., - suffix: str | None = ..., - prefix: str | None = ..., - dir: str | None = ..., - *, - errors: str | None = ..., - ): ... - - def __init__( - self, - max_size: int = 0, - mode: OpenBinaryMode | OpenTextMode = "w+b", - buffering: int = -1, - encoding: str | None = None, - newline: str | None = None, - suffix: str | None = None, - prefix: str | None = None, - dir: str | None = None, - *, - errors: str | None = None, - ) -> None: - self._tempfile_params: dict[str, Any] = { - "mode": mode, - "buffering": buffering, - "encoding": encoding, - "newline": newline, - "suffix": suffix, - "prefix": prefix, - "dir": dir, - "errors": errors, - } - self._max_size = max_size - if "b" in mode: - super().__init__(BytesIO()) # type: ignore[arg-type] - else: - super().__init__( - TextIOWrapper( # type: ignore[arg-type] - BytesIO(), - encoding=encoding, - errors=errors, - newline=newline, - write_through=True, - ) - ) - - async def aclose(self) -> None: - if not self._rolled: - self._fp.close() - return - - await super().aclose() - - async def _check(self) -> None: - if self._rolled or self._fp.tell() <= self._max_size: - return - - await self.rollover() - - async def rollover(self) -> None: - if self._rolled: - return - - self._rolled = True - buffer = self._fp - buffer.seek(0) - self._fp = await to_thread.run_sync( - lambda: tempfile.TemporaryFile(**self._tempfile_params) - ) - await self.write(buffer.read()) - buffer.close() - - @property - def closed(self) -> bool: - return self._fp.closed - - async def read(self, size: int = -1) -> AnyStr: - if not self._rolled: - await checkpoint_if_cancelled() - return self._fp.read(size) - - return await super().read(size) # type: ignore[return-value] - - async def read1(self: SpooledTemporaryFile[bytes], size: int = -1) -> bytes: - if not self._rolled: - await checkpoint_if_cancelled() - return self._fp.read1(size) - - return await super().read1(size) - - async def readline(self) -> AnyStr: - if not self._rolled: - await checkpoint_if_cancelled() - return self._fp.readline() - - return await super().readline() # type: ignore[return-value] - - async def readlines(self) -> list[AnyStr]: - if not self._rolled: - await checkpoint_if_cancelled() - return self._fp.readlines() - - return await super().readlines() # type: ignore[return-value] - - async def readinto(self: SpooledTemporaryFile[bytes], b: WriteableBuffer) -> int: - if not self._rolled: - await checkpoint_if_cancelled() - self._fp.readinto(b) - - return await super().readinto(b) - - async def readinto1(self: SpooledTemporaryFile[bytes], b: WriteableBuffer) -> int: - if not self._rolled: - await checkpoint_if_cancelled() - self._fp.readinto(b) - - return await super().readinto1(b) - - async def seek(self, offset: int, whence: int | None = os.SEEK_SET) -> int: - if not self._rolled: - await checkpoint_if_cancelled() - return self._fp.seek(offset, whence) - - return await super().seek(offset, whence) - - async def tell(self) -> int: - if not self._rolled: - await checkpoint_if_cancelled() - return self._fp.tell() - - return await super().tell() - - async def truncate(self, size: int | None = None) -> int: - if not self._rolled: - await checkpoint_if_cancelled() - return self._fp.truncate(size) - - return await super().truncate(size) - - @overload - async def write(self: SpooledTemporaryFile[bytes], b: ReadableBuffer) -> int: ... - @overload - async def write(self: SpooledTemporaryFile[str], b: str) -> int: ... - - async def write(self, b: ReadableBuffer | str) -> int: - """ - Asynchronously write data to the spooled temporary file. - - If the file has not yet been rolled over, the data is written synchronously, - and a rollover is triggered if the size exceeds the maximum size. - - :param s: The data to write. - :return: The number of bytes written. - :raises RuntimeError: If the underlying file is not initialized. - - """ - if not self._rolled: - await checkpoint_if_cancelled() - result = self._fp.write(b) - await self._check() - return result - - return await super().write(b) # type: ignore[misc] - - @overload - async def writelines( - self: SpooledTemporaryFile[bytes], lines: Iterable[ReadableBuffer] - ) -> None: ... - @overload - async def writelines( - self: SpooledTemporaryFile[str], lines: Iterable[str] - ) -> None: ... - - async def writelines(self, lines: Iterable[str] | Iterable[ReadableBuffer]) -> None: - """ - Asynchronously write a list of lines to the spooled temporary file. - - If the file has not yet been rolled over, the lines are written synchronously, - and a rollover is triggered if the size exceeds the maximum size. - - :param lines: An iterable of lines to write. - :raises RuntimeError: If the underlying file is not initialized. - - """ - if not self._rolled: - await checkpoint_if_cancelled() - result = self._fp.writelines(lines) - await self._check() - return result - - return await super().writelines(lines) # type: ignore[misc] - - -class TemporaryDirectory(Generic[AnyStr]): - """ - An asynchronous temporary directory that is created and cleaned up automatically. - - This class provides an asynchronous context manager for creating a temporary - directory. It wraps Python's standard :class:`~tempfile.TemporaryDirectory` to - perform directory creation and cleanup operations in a background thread. - - :param suffix: Suffix to be added to the temporary directory name. - :param prefix: Prefix to be added to the temporary directory name. - :param dir: The parent directory where the temporary directory is created. - :param ignore_cleanup_errors: Whether to ignore errors during cleanup - :param delete: Whether to delete the directory upon closing (Python 3.12+). - """ - - def __init__( - self, - suffix: AnyStr | None = None, - prefix: AnyStr | None = None, - dir: AnyStr | None = None, - *, - ignore_cleanup_errors: bool = False, - delete: bool = True, - ) -> None: - self.suffix: AnyStr | None = suffix - self.prefix: AnyStr | None = prefix - self.dir: AnyStr | None = dir - self.ignore_cleanup_errors = ignore_cleanup_errors - self.delete = delete - - self._tempdir: tempfile.TemporaryDirectory | None = None - - async def __aenter__(self) -> str: - params: dict[str, Any] = { - "suffix": self.suffix, - "prefix": self.prefix, - "dir": self.dir, - "ignore_cleanup_errors": self.ignore_cleanup_errors, - } - if sys.version_info >= (3, 12): - params["delete"] = self.delete - - self._tempdir = await to_thread.run_sync( - lambda: tempfile.TemporaryDirectory(**params) - ) - return await to_thread.run_sync(self._tempdir.__enter__) - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_value: BaseException | None, - traceback: TracebackType | None, - ) -> None: - if self._tempdir is not None: - await to_thread.run_sync( - self._tempdir.__exit__, exc_type, exc_value, traceback - ) - - async def cleanup(self) -> None: - if self._tempdir is not None: - await to_thread.run_sync(self._tempdir.cleanup) - - -@overload -async def mkstemp( - suffix: str | None = None, - prefix: str | None = None, - dir: str | None = None, - text: bool = False, -) -> tuple[int, str]: ... - - -@overload -async def mkstemp( - suffix: bytes | None = None, - prefix: bytes | None = None, - dir: bytes | None = None, - text: bool = False, -) -> tuple[int, bytes]: ... - - -async def mkstemp( - suffix: AnyStr | None = None, - prefix: AnyStr | None = None, - dir: AnyStr | None = None, - text: bool = False, -) -> tuple[int, str | bytes]: - """ - Asynchronously create a temporary file and return an OS-level handle and the file - name. - - This function wraps `tempfile.mkstemp` and executes it in a background thread. - - :param suffix: Suffix to be added to the file name. - :param prefix: Prefix to be added to the file name. - :param dir: Directory in which the temporary file is created. - :param text: Whether the file is opened in text mode. - :return: A tuple containing the file descriptor and the file name. - - """ - return await to_thread.run_sync(tempfile.mkstemp, suffix, prefix, dir, text) - - -@overload -async def mkdtemp( - suffix: str | None = None, - prefix: str | None = None, - dir: str | None = None, -) -> str: ... - - -@overload -async def mkdtemp( - suffix: bytes | None = None, - prefix: bytes | None = None, - dir: bytes | None = None, -) -> bytes: ... - - -async def mkdtemp( - suffix: AnyStr | None = None, - prefix: AnyStr | None = None, - dir: AnyStr | None = None, -) -> str | bytes: - """ - Asynchronously create a temporary directory and return its path. - - This function wraps `tempfile.mkdtemp` and executes it in a background thread. - - :param suffix: Suffix to be added to the directory name. - :param prefix: Prefix to be added to the directory name. - :param dir: Parent directory where the temporary directory is created. - :return: The path of the created temporary directory. - - """ - return await to_thread.run_sync(tempfile.mkdtemp, suffix, prefix, dir) - - -async def gettempdir() -> str: - """ - Asynchronously return the name of the directory used for temporary files. - - This function wraps `tempfile.gettempdir` and executes it in a background thread. - - :return: The path of the temporary directory as a string. - - """ - return await to_thread.run_sync(tempfile.gettempdir) - - -async def gettempdirb() -> bytes: - """ - Asynchronously return the name of the directory used for temporary files in bytes. - - This function wraps `tempfile.gettempdirb` and executes it in a background thread. - - :return: The path of the temporary directory as bytes. - - """ - return await to_thread.run_sync(tempfile.gettempdirb) diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_testing.py b/notification-service/venv/Lib/site-packages/anyio/_core/_testing.py deleted file mode 100644 index 369e65c..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_testing.py +++ /dev/null @@ -1,82 +0,0 @@ -from __future__ import annotations - -from collections.abc import Awaitable, Generator -from typing import Any, cast - -from ._eventloop import get_async_backend - - -class TaskInfo: - """ - Represents an asynchronous task. - - :ivar int id: the unique identifier of the task - :ivar parent_id: the identifier of the parent task, if any - :vartype parent_id: Optional[int] - :ivar str name: the description of the task (if any) - :ivar ~collections.abc.Coroutine coro: the coroutine object of the task - """ - - __slots__ = "_name", "id", "parent_id", "name", "coro" - - def __init__( - self, - id: int, - parent_id: int | None, - name: str | None, - coro: Generator[Any, Any, Any] | Awaitable[Any], - ): - func = get_current_task - self._name = f"{func.__module__}.{func.__qualname__}" - self.id: int = id - self.parent_id: int | None = parent_id - self.name: str | None = name - self.coro: Generator[Any, Any, Any] | Awaitable[Any] = coro - - def __eq__(self, other: object) -> bool: - if isinstance(other, TaskInfo): - return self.id == other.id - - return NotImplemented - - def __hash__(self) -> int: - return hash(self.id) - - def __repr__(self) -> str: - return f"{self.__class__.__name__}(id={self.id!r}, name={self.name!r})" - - def has_pending_cancellation(self) -> bool: - """ - Return ``True`` if the task has a cancellation pending, ``False`` otherwise. - - """ - return False - - -def get_current_task() -> TaskInfo: - """ - Return the current task. - - :return: a representation of the current task - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - """ - return get_async_backend().get_current_task() - - -def get_running_tasks() -> list[TaskInfo]: - """ - Return a list of running tasks in the current event loop. - - :return: a list of task info objects - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - """ - return cast("list[TaskInfo]", get_async_backend().get_running_tasks()) - - -async def wait_all_tasks_blocked() -> None: - """Wait until all other tasks are waiting for something.""" - await get_async_backend().wait_all_tasks_blocked() diff --git a/notification-service/venv/Lib/site-packages/anyio/_core/_typedattr.py b/notification-service/venv/Lib/site-packages/anyio/_core/_typedattr.py deleted file mode 100644 index f358a44..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/_core/_typedattr.py +++ /dev/null @@ -1,81 +0,0 @@ -from __future__ import annotations - -from collections.abc import Callable, Mapping -from typing import Any, TypeVar, final, overload - -from ._exceptions import TypedAttributeLookupError - -T_Attr = TypeVar("T_Attr") -T_Default = TypeVar("T_Default") -undefined = object() - - -def typed_attribute() -> Any: - """Return a unique object, used to mark typed attributes.""" - return object() - - -class TypedAttributeSet: - """ - Superclass for typed attribute collections. - - Checks that every public attribute of every subclass has a type annotation. - """ - - def __init_subclass__(cls) -> None: - annotations: dict[str, Any] = getattr(cls, "__annotations__", {}) - for attrname in dir(cls): - if not attrname.startswith("_") and attrname not in annotations: - raise TypeError( - f"Attribute {attrname!r} is missing its type annotation" - ) - - super().__init_subclass__() - - -class TypedAttributeProvider: - """Base class for classes that wish to provide typed extra attributes.""" - - @property - def extra_attributes(self) -> Mapping[T_Attr, Callable[[], T_Attr]]: - """ - A mapping of the extra attributes to callables that return the corresponding - values. - - If the provider wraps another provider, the attributes from that wrapper should - also be included in the returned mapping (but the wrapper may override the - callables from the wrapped instance). - - """ - return {} - - @overload - def extra(self, attribute: T_Attr) -> T_Attr: ... - - @overload - def extra(self, attribute: T_Attr, default: T_Default) -> T_Attr | T_Default: ... - - @final - def extra(self, attribute: Any, default: object = undefined) -> object: - """ - extra(attribute, default=undefined) - - Return the value of the given typed extra attribute. - - :param attribute: the attribute (member of a :class:`~TypedAttributeSet`) to - look for - :param default: the value that should be returned if no value is found for the - attribute - :raises ~anyio.TypedAttributeLookupError: if the search failed and no default - value was given - - """ - try: - getter = self.extra_attributes[attribute] - except KeyError: - if default is undefined: - raise TypedAttributeLookupError("Attribute not found") from None - else: - return default - - return getter() diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/__init__.py b/notification-service/venv/Lib/site-packages/anyio/abc/__init__.py deleted file mode 100644 index d560ce3..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/abc/__init__.py +++ /dev/null @@ -1,58 +0,0 @@ -from __future__ import annotations - -from ._eventloop import AsyncBackend as AsyncBackend -from ._resources import AsyncResource as AsyncResource -from ._sockets import ConnectedUDPSocket as ConnectedUDPSocket -from ._sockets import ConnectedUNIXDatagramSocket as ConnectedUNIXDatagramSocket -from ._sockets import IPAddressType as IPAddressType -from ._sockets import IPSockAddrType as IPSockAddrType -from ._sockets import SocketAttribute as SocketAttribute -from ._sockets import SocketListener as SocketListener -from ._sockets import SocketStream as SocketStream -from ._sockets import UDPPacketType as UDPPacketType -from ._sockets import UDPSocket as UDPSocket -from ._sockets import UNIXDatagramPacketType as UNIXDatagramPacketType -from ._sockets import UNIXDatagramSocket as UNIXDatagramSocket -from ._sockets import UNIXSocketStream as UNIXSocketStream -from ._streams import AnyByteReceiveStream as AnyByteReceiveStream -from ._streams import AnyByteSendStream as AnyByteSendStream -from ._streams import AnyByteStream as AnyByteStream -from ._streams import AnyByteStreamConnectable as AnyByteStreamConnectable -from ._streams import AnyUnreliableByteReceiveStream as AnyUnreliableByteReceiveStream -from ._streams import AnyUnreliableByteSendStream as AnyUnreliableByteSendStream -from ._streams import AnyUnreliableByteStream as AnyUnreliableByteStream -from ._streams import ByteReceiveStream as ByteReceiveStream -from ._streams import ByteSendStream as ByteSendStream -from ._streams import ByteStream as ByteStream -from ._streams import ByteStreamConnectable as ByteStreamConnectable -from ._streams import Listener as Listener -from ._streams import ObjectReceiveStream as ObjectReceiveStream -from ._streams import ObjectSendStream as ObjectSendStream -from ._streams import ObjectStream as ObjectStream -from ._streams import ObjectStreamConnectable as ObjectStreamConnectable -from ._streams import UnreliableObjectReceiveStream as UnreliableObjectReceiveStream -from ._streams import UnreliableObjectSendStream as UnreliableObjectSendStream -from ._streams import UnreliableObjectStream as UnreliableObjectStream -from ._subprocesses import Process as Process -from ._tasks import TaskGroup as TaskGroup -from ._tasks import TaskStatus as TaskStatus -from ._testing import TestRunner as TestRunner - -# Re-exported here, for backwards compatibility -# isort: off -from .._core._synchronization import ( - CapacityLimiter as CapacityLimiter, - Condition as Condition, - Event as Event, - Lock as Lock, - Semaphore as Semaphore, -) -from .._core._tasks import CancelScope as CancelScope -from ..from_thread import BlockingPortal as BlockingPortal - -# Re-export imports so they look like they live directly in this package -for __value in list(locals().values()): - if getattr(__value, "__module__", "").startswith("anyio.abc."): - __value.__module__ = __name__ - -del __value diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 2060d18..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_eventloop.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_eventloop.cpython-312.pyc deleted file mode 100644 index 39e9c19..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_eventloop.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_resources.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_resources.cpython-312.pyc deleted file mode 100644 index 5ef4531..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_resources.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_sockets.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_sockets.cpython-312.pyc deleted file mode 100644 index ab269da..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_sockets.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_streams.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_streams.cpython-312.pyc deleted file mode 100644 index 240cd0a..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_streams.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_subprocesses.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_subprocesses.cpython-312.pyc deleted file mode 100644 index 67e4697..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_subprocesses.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_tasks.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_tasks.cpython-312.pyc deleted file mode 100644 index 0903528..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_tasks.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_testing.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_testing.cpython-312.pyc deleted file mode 100644 index a870a97..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/abc/__pycache__/_testing.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/_eventloop.py b/notification-service/venv/Lib/site-packages/anyio/abc/_eventloop.py deleted file mode 100644 index ae06288..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/abc/_eventloop.py +++ /dev/null @@ -1,409 +0,0 @@ -from __future__ import annotations - -import math -import sys -from abc import ABCMeta, abstractmethod -from collections.abc import AsyncIterator, Awaitable, Callable, Sequence -from contextlib import AbstractContextManager -from os import PathLike -from signal import Signals -from socket import AddressFamily, SocketKind, socket -from typing import ( - IO, - TYPE_CHECKING, - Any, - TypeAlias, - TypeVar, - overload, -) - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -if TYPE_CHECKING: - from _typeshed import FileDescriptorLike - - from .._core._synchronization import CapacityLimiter, Event, Lock, Semaphore - from .._core._tasks import CancelScope - from .._core._testing import TaskInfo - from ._sockets import ( - ConnectedUDPSocket, - ConnectedUNIXDatagramSocket, - IPSockAddrType, - SocketListener, - SocketStream, - UDPSocket, - UNIXDatagramSocket, - UNIXSocketStream, - ) - from ._subprocesses import Process - from ._tasks import TaskGroup - from ._testing import TestRunner - -T_Retval = TypeVar("T_Retval") -PosArgsT = TypeVarTuple("PosArgsT") -StrOrBytesPath: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes] - - -class AsyncBackend(metaclass=ABCMeta): - @classmethod - @abstractmethod - def run( - cls, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - args: tuple[Unpack[PosArgsT]], - kwargs: dict[str, Any], - options: dict[str, Any], - ) -> T_Retval: - """ - Run the given coroutine function in an asynchronous event loop. - - The current thread must not be already running an event loop. - - :param func: a coroutine function - :param args: positional arguments to ``func`` - :param kwargs: positional arguments to ``func`` - :param options: keyword arguments to call the backend ``run()`` implementation - with - :return: the return value of the coroutine function - """ - - @classmethod - @abstractmethod - def current_token(cls) -> object: - """ - Return an object that allows other threads to run code inside the event loop. - - :return: a token object, specific to the event loop running in the current - thread - """ - - @classmethod - @abstractmethod - def current_time(cls) -> float: - """ - Return the current value of the event loop's internal clock. - - :return: the clock value (seconds) - """ - - @classmethod - @abstractmethod - def cancelled_exception_class(cls) -> type[BaseException]: - """Return the exception class that is raised in a task if it's cancelled.""" - - @classmethod - @abstractmethod - async def checkpoint(cls) -> None: - """ - Check if the task has been cancelled, and allow rescheduling of other tasks. - - This is effectively the same as running :meth:`checkpoint_if_cancelled` and then - :meth:`cancel_shielded_checkpoint`. - """ - - @classmethod - async def checkpoint_if_cancelled(cls) -> None: - """ - Check if the current task group has been cancelled. - - This will check if the task has been cancelled, but will not allow other tasks - to be scheduled if not. - - """ - if cls.current_effective_deadline() == -math.inf: - await cls.checkpoint() - - @classmethod - async def cancel_shielded_checkpoint(cls) -> None: - """ - Allow the rescheduling of other tasks. - - This will give other tasks the opportunity to run, but without checking if the - current task group has been cancelled, unlike with :meth:`checkpoint`. - - """ - with cls.create_cancel_scope(shield=True): - await cls.sleep(0) - - @classmethod - @abstractmethod - async def sleep(cls, delay: float) -> None: - """ - Pause the current task for the specified duration. - - :param delay: the duration, in seconds - """ - - @classmethod - @abstractmethod - def create_cancel_scope( - cls, *, deadline: float = math.inf, shield: bool = False - ) -> CancelScope: - pass - - @classmethod - @abstractmethod - def current_effective_deadline(cls) -> float: - """ - Return the nearest deadline among all the cancel scopes effective for the - current task. - - :return: - - a clock value from the event loop's internal clock - - ``inf`` if there is no deadline in effect - - ``-inf`` if the current scope has been cancelled - :rtype: float - """ - - @classmethod - @abstractmethod - def create_task_group(cls) -> TaskGroup: - pass - - @classmethod - @abstractmethod - def create_event(cls) -> Event: - pass - - @classmethod - @abstractmethod - def create_lock(cls, *, fast_acquire: bool) -> Lock: - pass - - @classmethod - @abstractmethod - def create_semaphore( - cls, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> Semaphore: - pass - - @classmethod - @abstractmethod - def create_capacity_limiter(cls, total_tokens: float) -> CapacityLimiter: - pass - - @classmethod - @abstractmethod - async def run_sync_in_worker_thread( - cls, - func: Callable[[Unpack[PosArgsT]], T_Retval], - args: tuple[Unpack[PosArgsT]], - abandon_on_cancel: bool = False, - limiter: CapacityLimiter | None = None, - ) -> T_Retval: - pass - - @classmethod - @abstractmethod - def check_cancelled(cls) -> None: - pass - - @classmethod - @abstractmethod - def run_async_from_thread( - cls, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - args: tuple[Unpack[PosArgsT]], - token: object, - ) -> T_Retval: - pass - - @classmethod - @abstractmethod - def run_sync_from_thread( - cls, - func: Callable[[Unpack[PosArgsT]], T_Retval], - args: tuple[Unpack[PosArgsT]], - token: object, - ) -> T_Retval: - pass - - @classmethod - @abstractmethod - async def open_process( - cls, - command: StrOrBytesPath | Sequence[StrOrBytesPath], - *, - stdin: int | IO[Any] | None, - stdout: int | IO[Any] | None, - stderr: int | IO[Any] | None, - **kwargs: Any, - ) -> Process: - pass - - @classmethod - @abstractmethod - def setup_process_pool_exit_at_shutdown(cls, workers: set[Process]) -> None: - pass - - @classmethod - @abstractmethod - async def connect_tcp( - cls, host: str, port: int, local_address: IPSockAddrType | None = None - ) -> SocketStream: - pass - - @classmethod - @abstractmethod - async def connect_unix(cls, path: str | bytes) -> UNIXSocketStream: - pass - - @classmethod - @abstractmethod - def create_tcp_listener(cls, sock: socket) -> SocketListener: - pass - - @classmethod - @abstractmethod - def create_unix_listener(cls, sock: socket) -> SocketListener: - pass - - @classmethod - @abstractmethod - async def create_udp_socket( - cls, - family: AddressFamily, - local_address: IPSockAddrType | None, - remote_address: IPSockAddrType | None, - reuse_port: bool, - ) -> UDPSocket | ConnectedUDPSocket: - pass - - @classmethod - @overload - async def create_unix_datagram_socket( - cls, raw_socket: socket, remote_path: None - ) -> UNIXDatagramSocket: ... - - @classmethod - @overload - async def create_unix_datagram_socket( - cls, raw_socket: socket, remote_path: str | bytes - ) -> ConnectedUNIXDatagramSocket: ... - - @classmethod - @abstractmethod - async def create_unix_datagram_socket( - cls, raw_socket: socket, remote_path: str | bytes | None - ) -> UNIXDatagramSocket | ConnectedUNIXDatagramSocket: - pass - - @classmethod - @abstractmethod - async def getaddrinfo( - cls, - host: bytes | str | None, - port: str | int | None, - *, - family: int | AddressFamily = 0, - type: int | SocketKind = 0, - proto: int = 0, - flags: int = 0, - ) -> Sequence[ - tuple[ - AddressFamily, - SocketKind, - int, - str, - tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes], - ] - ]: - pass - - @classmethod - @abstractmethod - async def getnameinfo( - cls, sockaddr: IPSockAddrType, flags: int = 0 - ) -> tuple[str, str]: - pass - - @classmethod - @abstractmethod - async def wait_readable(cls, obj: FileDescriptorLike) -> None: - pass - - @classmethod - @abstractmethod - async def wait_writable(cls, obj: FileDescriptorLike) -> None: - pass - - @classmethod - @abstractmethod - def notify_closing(cls, obj: FileDescriptorLike) -> None: - pass - - @classmethod - @abstractmethod - async def wrap_listener_socket(cls, sock: socket) -> SocketListener: - pass - - @classmethod - @abstractmethod - async def wrap_stream_socket(cls, sock: socket) -> SocketStream: - pass - - @classmethod - @abstractmethod - async def wrap_unix_stream_socket(cls, sock: socket) -> UNIXSocketStream: - pass - - @classmethod - @abstractmethod - async def wrap_udp_socket(cls, sock: socket) -> UDPSocket: - pass - - @classmethod - @abstractmethod - async def wrap_connected_udp_socket(cls, sock: socket) -> ConnectedUDPSocket: - pass - - @classmethod - @abstractmethod - async def wrap_unix_datagram_socket(cls, sock: socket) -> UNIXDatagramSocket: - pass - - @classmethod - @abstractmethod - async def wrap_connected_unix_datagram_socket( - cls, sock: socket - ) -> ConnectedUNIXDatagramSocket: - pass - - @classmethod - @abstractmethod - def current_default_thread_limiter(cls) -> CapacityLimiter: - pass - - @classmethod - @abstractmethod - def open_signal_receiver( - cls, *signals: Signals - ) -> AbstractContextManager[AsyncIterator[Signals]]: - pass - - @classmethod - @abstractmethod - def get_current_task(cls) -> TaskInfo: - pass - - @classmethod - @abstractmethod - def get_running_tasks(cls) -> Sequence[TaskInfo]: - pass - - @classmethod - @abstractmethod - async def wait_all_tasks_blocked(cls) -> None: - pass - - @classmethod - @abstractmethod - def create_test_runner(cls, options: dict[str, Any]) -> TestRunner: - pass diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/_resources.py b/notification-service/venv/Lib/site-packages/anyio/abc/_resources.py deleted file mode 100644 index 10df115..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/abc/_resources.py +++ /dev/null @@ -1,33 +0,0 @@ -from __future__ import annotations - -from abc import ABCMeta, abstractmethod -from types import TracebackType -from typing import TypeVar - -T = TypeVar("T") - - -class AsyncResource(metaclass=ABCMeta): - """ - Abstract base class for all closeable asynchronous resources. - - Works as an asynchronous context manager which returns the instance itself on enter, - and calls :meth:`aclose` on exit. - """ - - __slots__ = () - - async def __aenter__(self: T) -> T: - return self - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - await self.aclose() - - @abstractmethod - async def aclose(self) -> None: - """Close the resource.""" diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/_sockets.py b/notification-service/venv/Lib/site-packages/anyio/abc/_sockets.py deleted file mode 100644 index feb26bd..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/abc/_sockets.py +++ /dev/null @@ -1,399 +0,0 @@ -from __future__ import annotations - -import errno -import socket -from abc import abstractmethod -from collections.abc import Callable, Collection, Mapping -from contextlib import AsyncExitStack -from io import IOBase -from ipaddress import IPv4Address, IPv6Address -from socket import AddressFamily -from typing import Any, TypeAlias, TypeVar - -from .._core._eventloop import get_async_backend -from .._core._typedattr import ( - TypedAttributeProvider, - TypedAttributeSet, - typed_attribute, -) -from ._streams import ByteStream, Listener, UnreliableObjectStream -from ._tasks import TaskGroup - -IPAddressType: TypeAlias = str | IPv4Address | IPv6Address -IPSockAddrType: TypeAlias = tuple[str, int] -SockAddrType: TypeAlias = IPSockAddrType | str -UDPPacketType: TypeAlias = tuple[bytes, IPSockAddrType] -UNIXDatagramPacketType: TypeAlias = tuple[bytes, str] -T_Retval = TypeVar("T_Retval") - - -def _validate_socket( - sock_or_fd: socket.socket | int, - sock_type: socket.SocketKind, - addr_family: socket.AddressFamily = socket.AF_UNSPEC, - *, - require_connected: bool = False, - require_bound: bool = False, -) -> socket.socket: - if isinstance(sock_or_fd, int): - try: - sock = socket.socket(fileno=sock_or_fd) - except OSError as exc: - if exc.errno == errno.ENOTSOCK: - raise ValueError( - "the file descriptor does not refer to a socket" - ) from exc - elif require_connected: - raise ValueError("the socket must be connected") from exc - elif require_bound: - raise ValueError("the socket must be bound to a local address") from exc - else: - raise - elif isinstance(sock_or_fd, socket.socket): - sock = sock_or_fd - else: - raise TypeError( - f"expected an int or socket, got {type(sock_or_fd).__qualname__} instead" - ) - - try: - if require_connected: - try: - sock.getpeername() - except OSError as exc: - raise ValueError("the socket must be connected") from exc - - if require_bound: - try: - if sock.family in (socket.AF_INET, socket.AF_INET6): - bound_addr = sock.getsockname()[1] - else: - bound_addr = sock.getsockname() - except OSError: - bound_addr = None - - if not bound_addr: - raise ValueError("the socket must be bound to a local address") - - if addr_family != socket.AF_UNSPEC and sock.family != addr_family: - raise ValueError( - f"address family mismatch: expected {addr_family.name}, got " - f"{sock.family.name}" - ) - - if sock.type != sock_type: - raise ValueError( - f"socket type mismatch: expected {sock_type.name}, got {sock.type.name}" - ) - except BaseException: - # Avoid ResourceWarning from the locally constructed socket object - if isinstance(sock_or_fd, int): - sock.detach() - - raise - - sock.setblocking(False) - return sock - - -class SocketAttribute(TypedAttributeSet): - """ - .. attribute:: family - :type: socket.AddressFamily - - the address family of the underlying socket - - .. attribute:: local_address - :type: tuple[str, int] | str - - the local address the underlying socket is connected to - - .. attribute:: local_port - :type: int - - for IP based sockets, the local port the underlying socket is bound to - - .. attribute:: raw_socket - :type: socket.socket - - the underlying stdlib socket object - - .. attribute:: remote_address - :type: tuple[str, int] | str - - the remote address the underlying socket is connected to - - .. attribute:: remote_port - :type: int - - for IP based sockets, the remote port the underlying socket is connected to - """ - - family: AddressFamily = typed_attribute() - local_address: SockAddrType = typed_attribute() - local_port: int = typed_attribute() - raw_socket: socket.socket = typed_attribute() - remote_address: SockAddrType = typed_attribute() - remote_port: int = typed_attribute() - - -class _SocketProvider(TypedAttributeProvider): - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - from .._core._sockets import convert_ipv6_sockaddr as convert - - attributes: dict[Any, Callable[[], Any]] = { - SocketAttribute.family: lambda: self._raw_socket.family, - SocketAttribute.local_address: lambda: convert( - self._raw_socket.getsockname() - ), - SocketAttribute.raw_socket: lambda: self._raw_socket, - } - try: - peername: tuple[str, int] | None = convert(self._raw_socket.getpeername()) - except OSError: - peername = None - - # Provide the remote address for connected sockets - if peername is not None: - attributes[SocketAttribute.remote_address] = lambda: peername - - # Provide local and remote ports for IP based sockets - if self._raw_socket.family in (AddressFamily.AF_INET, AddressFamily.AF_INET6): - attributes[SocketAttribute.local_port] = lambda: ( - self._raw_socket.getsockname()[1] - ) - if peername is not None: - remote_port = peername[1] - attributes[SocketAttribute.remote_port] = lambda: remote_port - - return attributes - - @property - @abstractmethod - def _raw_socket(self) -> socket.socket: - pass - - -class SocketStream(ByteStream, _SocketProvider): - """ - Transports bytes over a socket. - - Supports all relevant extra attributes from :class:`~SocketAttribute`. - """ - - @classmethod - async def from_socket(cls, sock_or_fd: socket.socket | int) -> SocketStream: - """ - Wrap an existing socket object or file descriptor as a socket stream. - - The newly created socket wrapper takes ownership of the socket being passed in. - The existing socket must already be connected. - - :param sock_or_fd: a socket object or file descriptor - :return: a socket stream - - """ - sock = _validate_socket(sock_or_fd, socket.SOCK_STREAM, require_connected=True) - return await get_async_backend().wrap_stream_socket(sock) - - -class UNIXSocketStream(SocketStream): - @classmethod - async def from_socket(cls, sock_or_fd: socket.socket | int) -> UNIXSocketStream: - """ - Wrap an existing socket object or file descriptor as a UNIX socket stream. - - The newly created socket wrapper takes ownership of the socket being passed in. - The existing socket must already be connected. - - :param sock_or_fd: a socket object or file descriptor - :return: a UNIX socket stream - - """ - sock = _validate_socket( - sock_or_fd, socket.SOCK_STREAM, socket.AF_UNIX, require_connected=True - ) - return await get_async_backend().wrap_unix_stream_socket(sock) - - @abstractmethod - async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None: - """ - Send file descriptors along with a message to the peer. - - :param message: a non-empty bytestring - :param fds: a collection of files (either numeric file descriptors or open file - or socket objects) - """ - - @abstractmethod - async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]: - """ - Receive file descriptors along with a message from the peer. - - :param msglen: length of the message to expect from the peer - :param maxfds: maximum number of file descriptors to expect from the peer - :return: a tuple of (message, file descriptors) - """ - - -class SocketListener(Listener[SocketStream], _SocketProvider): - """ - Listens to incoming socket connections. - - Supports all relevant extra attributes from :class:`~SocketAttribute`. - """ - - @classmethod - async def from_socket( - cls, - sock_or_fd: socket.socket | int, - ) -> SocketListener: - """ - Wrap an existing socket object or file descriptor as a socket listener. - - The newly created listener takes ownership of the socket being passed in. - - :param sock_or_fd: a socket object or file descriptor - :return: a socket listener - - """ - sock = _validate_socket(sock_or_fd, socket.SOCK_STREAM, require_bound=True) - return await get_async_backend().wrap_listener_socket(sock) - - @abstractmethod - async def accept(self) -> SocketStream: - """Accept an incoming connection.""" - - async def serve( - self, - handler: Callable[[SocketStream], Any], - task_group: TaskGroup | None = None, - ) -> None: - from .. import create_task_group - - async with AsyncExitStack() as stack: - if task_group is None: - task_group = await stack.enter_async_context(create_task_group()) - - while True: - stream = await self.accept() - task_group.start_soon(handler, stream) - - -class UDPSocket(UnreliableObjectStream[UDPPacketType], _SocketProvider): - """ - Represents an unconnected UDP socket. - - Supports all relevant extra attributes from :class:`~SocketAttribute`. - """ - - @classmethod - async def from_socket(cls, sock_or_fd: socket.socket | int) -> UDPSocket: - """ - Wrap an existing socket object or file descriptor as a UDP socket. - - The newly created socket wrapper takes ownership of the socket being passed in. - The existing socket must be bound to a local address. - - :param sock_or_fd: a socket object or file descriptor - :return: a UDP socket - - """ - sock = _validate_socket(sock_or_fd, socket.SOCK_DGRAM, require_bound=True) - return await get_async_backend().wrap_udp_socket(sock) - - async def sendto(self, data: bytes, host: str, port: int) -> None: - """ - Alias for :meth:`~.UnreliableObjectSendStream.send` ((data, (host, port))). - - """ - return await self.send((data, (host, port))) - - -class ConnectedUDPSocket(UnreliableObjectStream[bytes], _SocketProvider): - """ - Represents an connected UDP socket. - - Supports all relevant extra attributes from :class:`~SocketAttribute`. - """ - - @classmethod - async def from_socket(cls, sock_or_fd: socket.socket | int) -> ConnectedUDPSocket: - """ - Wrap an existing socket object or file descriptor as a connected UDP socket. - - The newly created socket wrapper takes ownership of the socket being passed in. - The existing socket must already be connected. - - :param sock_or_fd: a socket object or file descriptor - :return: a connected UDP socket - - """ - sock = _validate_socket( - sock_or_fd, - socket.SOCK_DGRAM, - require_connected=True, - ) - return await get_async_backend().wrap_connected_udp_socket(sock) - - -class UNIXDatagramSocket( - UnreliableObjectStream[UNIXDatagramPacketType], _SocketProvider -): - """ - Represents an unconnected Unix datagram socket. - - Supports all relevant extra attributes from :class:`~SocketAttribute`. - """ - - @classmethod - async def from_socket( - cls, - sock_or_fd: socket.socket | int, - ) -> UNIXDatagramSocket: - """ - Wrap an existing socket object or file descriptor as a UNIX datagram - socket. - - The newly created socket wrapper takes ownership of the socket being passed in. - - :param sock_or_fd: a socket object or file descriptor - :return: a UNIX datagram socket - - """ - sock = _validate_socket(sock_or_fd, socket.SOCK_DGRAM, socket.AF_UNIX) - return await get_async_backend().wrap_unix_datagram_socket(sock) - - async def sendto(self, data: bytes, path: str) -> None: - """Alias for :meth:`~.UnreliableObjectSendStream.send` ((data, path)).""" - return await self.send((data, path)) - - -class ConnectedUNIXDatagramSocket(UnreliableObjectStream[bytes], _SocketProvider): - """ - Represents a connected Unix datagram socket. - - Supports all relevant extra attributes from :class:`~SocketAttribute`. - """ - - @classmethod - async def from_socket( - cls, - sock_or_fd: socket.socket | int, - ) -> ConnectedUNIXDatagramSocket: - """ - Wrap an existing socket object or file descriptor as a connected UNIX datagram - socket. - - The newly created socket wrapper takes ownership of the socket being passed in. - The existing socket must already be connected. - - :param sock_or_fd: a socket object or file descriptor - :return: a connected UNIX datagram socket - - """ - sock = _validate_socket( - sock_or_fd, socket.SOCK_DGRAM, socket.AF_UNIX, require_connected=True - ) - return await get_async_backend().wrap_connected_unix_datagram_socket(sock) diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/_streams.py b/notification-service/venv/Lib/site-packages/anyio/abc/_streams.py deleted file mode 100644 index 186e3f5..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/abc/_streams.py +++ /dev/null @@ -1,233 +0,0 @@ -from __future__ import annotations - -from abc import ABCMeta, abstractmethod -from collections.abc import Callable -from typing import Any, Generic, TypeAlias, TypeVar - -from .._core._exceptions import EndOfStream -from .._core._typedattr import TypedAttributeProvider -from ._resources import AsyncResource -from ._tasks import TaskGroup - -T_Item = TypeVar("T_Item") -T_co = TypeVar("T_co", covariant=True) -T_contra = TypeVar("T_contra", contravariant=True) - - -class UnreliableObjectReceiveStream( - Generic[T_co], AsyncResource, TypedAttributeProvider -): - """ - An interface for receiving objects. - - This interface makes no guarantees that the received messages arrive in the order in - which they were sent, or that no messages are missed. - - Asynchronously iterating over objects of this type will yield objects matching the - given type parameter. - """ - - def __aiter__(self) -> UnreliableObjectReceiveStream[T_co]: - return self - - async def __anext__(self) -> T_co: - try: - return await self.receive() - except EndOfStream: - raise StopAsyncIteration from None - - @abstractmethod - async def receive(self) -> T_co: - """ - Receive the next item. - - :raises ~anyio.ClosedResourceError: if the receive stream has been explicitly - closed - :raises ~anyio.EndOfStream: if this stream has been closed from the other end - :raises ~anyio.BrokenResourceError: if this stream has been rendered unusable - due to external causes - """ - - -class UnreliableObjectSendStream( - Generic[T_contra], AsyncResource, TypedAttributeProvider -): - """ - An interface for sending objects. - - This interface makes no guarantees that the messages sent will reach the - recipient(s) in the same order in which they were sent, or at all. - """ - - @abstractmethod - async def send(self, item: T_contra) -> None: - """ - Send an item to the peer(s). - - :param item: the item to send - :raises ~anyio.ClosedResourceError: if the send stream has been explicitly - closed - :raises ~anyio.BrokenResourceError: if this stream has been rendered unusable - due to external causes - """ - - -class UnreliableObjectStream( - UnreliableObjectReceiveStream[T_Item], UnreliableObjectSendStream[T_Item] -): - """ - A bidirectional message stream which does not guarantee the order or reliability of - message delivery. - """ - - -class ObjectReceiveStream(UnreliableObjectReceiveStream[T_co]): - """ - A receive message stream which guarantees that messages are received in the same - order in which they were sent, and that no messages are missed. - """ - - -class ObjectSendStream(UnreliableObjectSendStream[T_contra]): - """ - A send message stream which guarantees that messages are delivered in the same order - in which they were sent, without missing any messages in the middle. - """ - - -class ObjectStream( - ObjectReceiveStream[T_Item], - ObjectSendStream[T_Item], - UnreliableObjectStream[T_Item], -): - """ - A bidirectional message stream which guarantees the order and reliability of message - delivery. - """ - - @abstractmethod - async def send_eof(self) -> None: - """ - Send an end-of-file indication to the peer. - - You should not try to send any further data to this stream after calling this - method. This method is idempotent (does nothing on successive calls). - """ - - -class ByteReceiveStream(AsyncResource, TypedAttributeProvider): - """ - An interface for receiving bytes from a single peer. - - Iterating this byte stream will yield a byte string of arbitrary length, but no more - than 65536 bytes. - """ - - def __aiter__(self) -> ByteReceiveStream: - return self - - async def __anext__(self) -> bytes: - try: - return await self.receive() - except EndOfStream: - raise StopAsyncIteration from None - - @abstractmethod - async def receive(self, max_bytes: int = 65536) -> bytes: - """ - Receive at most ``max_bytes`` bytes from the peer. - - .. note:: Implementers of this interface should not return an empty - :class:`bytes` object, and users should ignore them. - - :param max_bytes: maximum number of bytes to receive - :return: the received bytes - :raises ~anyio.EndOfStream: if this stream has been closed from the other end - """ - - -class ByteSendStream(AsyncResource, TypedAttributeProvider): - """An interface for sending bytes to a single peer.""" - - @abstractmethod - async def send(self, item: bytes) -> None: - """ - Send the given bytes to the peer. - - :param item: the bytes to send - """ - - -class ByteStream(ByteReceiveStream, ByteSendStream): - """A bidirectional byte stream.""" - - @abstractmethod - async def send_eof(self) -> None: - """ - Send an end-of-file indication to the peer. - - You should not try to send any further data to this stream after calling this - method. This method is idempotent (does nothing on successive calls). - """ - - -#: Type alias for all unreliable bytes-oriented receive streams. -AnyUnreliableByteReceiveStream: TypeAlias = ( - UnreliableObjectReceiveStream[bytes] | ByteReceiveStream -) -#: Type alias for all unreliable bytes-oriented send streams. -AnyUnreliableByteSendStream: TypeAlias = ( - UnreliableObjectSendStream[bytes] | ByteSendStream -) -#: Type alias for all unreliable bytes-oriented streams. -AnyUnreliableByteStream: TypeAlias = UnreliableObjectStream[bytes] | ByteStream -#: Type alias for all bytes-oriented receive streams. -AnyByteReceiveStream: TypeAlias = ObjectReceiveStream[bytes] | ByteReceiveStream -#: Type alias for all bytes-oriented send streams. -AnyByteSendStream: TypeAlias = ObjectSendStream[bytes] | ByteSendStream -#: Type alias for all bytes-oriented streams. -AnyByteStream: TypeAlias = ObjectStream[bytes] | ByteStream - - -class Listener(Generic[T_co], AsyncResource, TypedAttributeProvider): - """An interface for objects that let you accept incoming connections.""" - - @abstractmethod - async def serve( - self, handler: Callable[[T_co], Any], task_group: TaskGroup | None = None - ) -> None: - """ - Accept incoming connections as they come in and start tasks to handle them. - - :param handler: a callable that will be used to handle each accepted connection - :param task_group: the task group that will be used to start tasks for handling - each accepted connection (if omitted, an ad-hoc task group will be created) - """ - - -class ObjectStreamConnectable(Generic[T_co], metaclass=ABCMeta): - @abstractmethod - async def connect(self) -> ObjectStream[T_co]: - """ - Connect to the remote endpoint. - - :return: an object stream connected to the remote end - :raises ConnectionFailed: if the connection fails - """ - - -class ByteStreamConnectable(metaclass=ABCMeta): - @abstractmethod - async def connect(self) -> ByteStream: - """ - Connect to the remote endpoint. - - :return: a bytestream connected to the remote end - :raises ConnectionFailed: if the connection fails - """ - - -#: Type alias for all connectables returning bytestreams or bytes-oriented object streams -AnyByteStreamConnectable: TypeAlias = ( - ObjectStreamConnectable[bytes] | ByteStreamConnectable -) diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/_subprocesses.py b/notification-service/venv/Lib/site-packages/anyio/abc/_subprocesses.py deleted file mode 100644 index ce0564c..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/abc/_subprocesses.py +++ /dev/null @@ -1,79 +0,0 @@ -from __future__ import annotations - -from abc import abstractmethod -from signal import Signals - -from ._resources import AsyncResource -from ._streams import ByteReceiveStream, ByteSendStream - - -class Process(AsyncResource): - """An asynchronous version of :class:`subprocess.Popen`.""" - - @abstractmethod - async def wait(self) -> int: - """ - Wait until the process exits. - - :return: the exit code of the process - """ - - @abstractmethod - def terminate(self) -> None: - """ - Terminates the process, gracefully if possible. - - On Windows, this calls ``TerminateProcess()``. - On POSIX systems, this sends ``SIGTERM`` to the process. - - .. seealso:: :meth:`subprocess.Popen.terminate` - """ - - @abstractmethod - def kill(self) -> None: - """ - Kills the process. - - On Windows, this calls ``TerminateProcess()``. - On POSIX systems, this sends ``SIGKILL`` to the process. - - .. seealso:: :meth:`subprocess.Popen.kill` - """ - - @abstractmethod - def send_signal(self, signal: Signals) -> None: - """ - Send a signal to the subprocess. - - .. seealso:: :meth:`subprocess.Popen.send_signal` - - :param signal: the signal number (e.g. :data:`signal.SIGHUP`) - """ - - @property - @abstractmethod - def pid(self) -> int: - """The process ID of the process.""" - - @property - @abstractmethod - def returncode(self) -> int | None: - """ - The return code of the process. If the process has not yet terminated, this will - be ``None``. - """ - - @property - @abstractmethod - def stdin(self) -> ByteSendStream | None: - """The stream for the standard input of the process.""" - - @property - @abstractmethod - def stdout(self) -> ByteReceiveStream | None: - """The stream for the standard output of the process.""" - - @property - @abstractmethod - def stderr(self) -> ByteReceiveStream | None: - """The stream for the standard error output of the process.""" diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/_tasks.py b/notification-service/venv/Lib/site-packages/anyio/abc/_tasks.py deleted file mode 100644 index 516b3ec..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/abc/_tasks.py +++ /dev/null @@ -1,117 +0,0 @@ -from __future__ import annotations - -import sys -from abc import ABCMeta, abstractmethod -from collections.abc import Awaitable, Callable -from types import TracebackType -from typing import TYPE_CHECKING, Any, Protocol, overload - -if sys.version_info >= (3, 13): - from typing import TypeVar -else: - from typing_extensions import TypeVar - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -if TYPE_CHECKING: - from .._core._tasks import CancelScope - -T_Retval = TypeVar("T_Retval") -T_contra = TypeVar("T_contra", contravariant=True, default=None) -PosArgsT = TypeVarTuple("PosArgsT") - - -class TaskStatus(Protocol[T_contra]): - @overload - def started(self: TaskStatus[None]) -> None: ... - - @overload - def started(self, value: T_contra) -> None: ... - - def started(self, value: T_contra | None = None) -> None: - """ - Signal that the task has started. - - :param value: object passed back to the starter of the task - """ - - -class TaskGroup(metaclass=ABCMeta): - """ - Groups several asynchronous tasks together. - - :ivar cancel_scope: the cancel scope inherited by all child tasks - :vartype cancel_scope: CancelScope - - .. note:: On asyncio, support for eager task factories is considered to be - **experimental**. In particular, they don't follow the usual semantics of new - tasks being scheduled on the next iteration of the event loop, and may thus - cause unexpected behavior in code that wasn't written with such semantics in - mind. - """ - - cancel_scope: CancelScope - - @abstractmethod - def start_soon( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], - *args: Unpack[PosArgsT], - name: object = None, - ) -> None: - """ - Start a new task in this task group. - - :param func: a coroutine function - :param args: positional arguments to call the function with - :param name: name of the task, for the purposes of introspection and debugging - - .. versionadded:: 3.0 - """ - - @abstractmethod - async def start( - self, - func: Callable[..., Awaitable[Any]], - *args: object, - name: object = None, - ) -> Any: - """ - Start a new task and wait until it signals for readiness. - - The target callable must accept a keyword argument ``task_status`` (of type - :class:`TaskStatus`). Awaiting on this method will return whatever was passed to - ``task_status.started()`` (``None`` by default). - - .. note:: The :class:`TaskStatus` class is generic, and the type argument should - indicate the type of the value that will be passed to - ``task_status.started()``. - - :param func: a coroutine function that accepts the ``task_status`` keyword - argument - :param args: positional arguments to call the function with - :param name: an optional name for the task, for introspection and debugging - :return: the value passed to ``task_status.started()`` - :raises RuntimeError: if the task finishes without calling - ``task_status.started()`` - - .. seealso:: :ref:`start_initialize` - - .. versionadded:: 3.0 - """ - - @abstractmethod - async def __aenter__(self) -> TaskGroup: - """Enter the task group context and allow starting new tasks.""" - - @abstractmethod - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool: - """Exit the task group context waiting for all tasks to finish.""" diff --git a/notification-service/venv/Lib/site-packages/anyio/abc/_testing.py b/notification-service/venv/Lib/site-packages/anyio/abc/_testing.py deleted file mode 100644 index 7c50ed7..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/abc/_testing.py +++ /dev/null @@ -1,65 +0,0 @@ -from __future__ import annotations - -import types -from abc import ABCMeta, abstractmethod -from collections.abc import AsyncGenerator, Callable, Coroutine, Iterable -from typing import Any, TypeVar - -_T = TypeVar("_T") - - -class TestRunner(metaclass=ABCMeta): - """ - Encapsulates a running event loop. Every call made through this object will use the - same event loop. - """ - - def __enter__(self) -> TestRunner: - return self - - @abstractmethod - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: types.TracebackType | None, - ) -> bool | None: ... - - @abstractmethod - def run_asyncgen_fixture( - self, - fixture_func: Callable[..., AsyncGenerator[_T, Any]], - kwargs: dict[str, Any], - ) -> Iterable[_T]: - """ - Run an async generator fixture. - - :param fixture_func: the fixture function - :param kwargs: keyword arguments to call the fixture function with - :return: an iterator yielding the value yielded from the async generator - """ - - @abstractmethod - def run_fixture( - self, - fixture_func: Callable[..., Coroutine[Any, Any, _T]], - kwargs: dict[str, Any], - ) -> _T: - """ - Run an async fixture. - - :param fixture_func: the fixture function - :param kwargs: keyword arguments to call the fixture function with - :return: the return value of the fixture function - """ - - @abstractmethod - def run_test( - self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any] - ) -> None: - """ - Run an async test function. - - :param test_func: the test function - :param kwargs: keyword arguments to call the test function with - """ diff --git a/notification-service/venv/Lib/site-packages/anyio/from_thread.py b/notification-service/venv/Lib/site-packages/anyio/from_thread.py deleted file mode 100644 index 837de5e..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/from_thread.py +++ /dev/null @@ -1,578 +0,0 @@ -from __future__ import annotations - -__all__ = ( - "BlockingPortal", - "BlockingPortalProvider", - "check_cancelled", - "run", - "run_sync", - "start_blocking_portal", -) - -import sys -from collections.abc import Awaitable, Callable, Generator -from concurrent.futures import Future -from contextlib import ( - AbstractAsyncContextManager, - AbstractContextManager, - contextmanager, -) -from dataclasses import dataclass, field -from functools import partial -from inspect import isawaitable -from threading import Lock, Thread, current_thread, get_ident -from types import TracebackType -from typing import ( - Any, - Generic, - TypeVar, - cast, - overload, -) - -from ._core._eventloop import ( - get_cancelled_exc_class, - threadlocals, -) -from ._core._eventloop import run as run_eventloop -from ._core._exceptions import NoEventLoopError -from ._core._synchronization import Event -from ._core._tasks import CancelScope, create_task_group -from .abc._tasks import TaskStatus -from .lowlevel import EventLoopToken, current_token - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -T_Retval = TypeVar("T_Retval") -T_co = TypeVar("T_co", covariant=True) -PosArgsT = TypeVarTuple("PosArgsT") - - -def _token_or_error(token: EventLoopToken | None) -> EventLoopToken: - if token is not None: - return token - - try: - return threadlocals.current_token - except AttributeError: - raise NoEventLoopError( - "Not running inside an AnyIO worker thread, and no event loop token was " - "provided" - ) from None - - -def run( - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - *args: Unpack[PosArgsT], - token: EventLoopToken | None = None, -) -> T_Retval: - """ - Call a coroutine function from a worker thread. - - :param func: a coroutine function - :param args: positional arguments for the callable - :param token: an event loop token to use to get back to the event loop thread - (required if calling this function from outside an AnyIO worker thread) - :return: the return value of the coroutine function - :raises MissingTokenError: if no token was provided and called from outside an - AnyIO worker thread - :raises RunFinishedError: if the event loop tied to ``token`` is no longer running - - .. versionchanged:: 4.11.0 - Added the ``token`` parameter. - - """ - explicit_token = token is not None - token = _token_or_error(token) - return token.backend_class.run_async_from_thread( - func, args, token=token.native_token if explicit_token else None - ) - - -def run_sync( - func: Callable[[Unpack[PosArgsT]], T_Retval], - *args: Unpack[PosArgsT], - token: EventLoopToken | None = None, -) -> T_Retval: - """ - Call a function in the event loop thread from a worker thread. - - :param func: a callable - :param args: positional arguments for the callable - :param token: an event loop token to use to get back to the event loop thread - (required if calling this function from outside an AnyIO worker thread) - :return: the return value of the callable - :raises MissingTokenError: if no token was provided and called from outside an - AnyIO worker thread - :raises RunFinishedError: if the event loop tied to ``token`` is no longer running - - .. versionchanged:: 4.11.0 - Added the ``token`` parameter. - - """ - explicit_token = token is not None - token = _token_or_error(token) - return token.backend_class.run_sync_from_thread( - func, args, token=token.native_token if explicit_token else None - ) - - -class _BlockingAsyncContextManager(Generic[T_co], AbstractContextManager): - _enter_future: Future[T_co] - _exit_future: Future[bool | None] - _exit_event: Event - _exit_exc_info: tuple[ - type[BaseException] | None, BaseException | None, TracebackType | None - ] = (None, None, None) - - def __init__( - self, async_cm: AbstractAsyncContextManager[T_co], portal: BlockingPortal - ): - self._async_cm = async_cm - self._portal = portal - - async def run_async_cm(self) -> bool | None: - try: - self._exit_event = Event() - value = await self._async_cm.__aenter__() - except BaseException as exc: - self._enter_future.set_exception(exc) - raise - else: - self._enter_future.set_result(value) - - try: - # Wait for the sync context manager to exit. - # This next statement can raise `get_cancelled_exc_class()` if - # something went wrong in a task group in this async context - # manager. - await self._exit_event.wait() - finally: - # In case of cancellation, it could be that we end up here before - # `_BlockingAsyncContextManager.__exit__` is called, and an - # `_exit_exc_info` has been set. - result = await self._async_cm.__aexit__(*self._exit_exc_info) - - return result - - def __enter__(self) -> T_co: - self._enter_future = Future() - self._exit_future = self._portal.start_task_soon(self.run_async_cm) - return self._enter_future.result() - - def __exit__( - self, - __exc_type: type[BaseException] | None, - __exc_value: BaseException | None, - __traceback: TracebackType | None, - ) -> bool | None: - self._exit_exc_info = __exc_type, __exc_value, __traceback - self._portal.call(self._exit_event.set) - return self._exit_future.result() - - -class _BlockingPortalTaskStatus(TaskStatus): - def __init__(self, future: Future): - self._future = future - - def started(self, value: object = None) -> None: - self._future.set_result(value) - - -class BlockingPortal: - """ - An object that lets external threads run code in an asynchronous event loop. - - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - """ - - def __init__(self) -> None: - self._token = current_token() - self._event_loop_thread_id: int | None = get_ident() - self._stop_event = Event() - self._task_group = create_task_group() - - async def __aenter__(self) -> BlockingPortal: - await self._task_group.__aenter__() - return self - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool: - await self.stop() - return await self._task_group.__aexit__(exc_type, exc_val, exc_tb) - - def _check_running(self) -> None: - if self._event_loop_thread_id is None: - raise RuntimeError("This portal is not running") - if self._event_loop_thread_id == get_ident(): - raise RuntimeError( - "This method cannot be called from the event loop thread" - ) - - async def sleep_until_stopped(self) -> None: - """Sleep until :meth:`stop` is called.""" - await self._stop_event.wait() - - async def stop(self, cancel_remaining: bool = False) -> None: - """ - Signal the portal to shut down. - - This marks the portal as no longer accepting new calls and exits from - :meth:`sleep_until_stopped`. - - :param cancel_remaining: ``True`` to cancel all the remaining tasks, ``False`` - to let them finish before returning - - """ - self._event_loop_thread_id = None - self._stop_event.set() - if cancel_remaining: - self._task_group.cancel_scope.cancel("the blocking portal is shutting down") - - async def _call_func( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], - args: tuple[Unpack[PosArgsT]], - kwargs: dict[str, Any], - future: Future[T_Retval], - ) -> None: - def callback(f: Future[T_Retval]) -> None: - if f.cancelled(): - if self._event_loop_thread_id == get_ident(): - scope.cancel("the future was cancelled") - elif self._event_loop_thread_id is not None: - self.call(scope.cancel, "the future was cancelled") - - try: - retval_or_awaitable = func(*args, **kwargs) - if isawaitable(retval_or_awaitable): - with CancelScope() as scope: - future.add_done_callback(callback) - retval = await retval_or_awaitable - else: - retval = retval_or_awaitable - except get_cancelled_exc_class(): - future.cancel() - future.set_running_or_notify_cancel() - except BaseException as exc: - if not future.cancelled(): - future.set_exception(exc) - - # Let base exceptions fall through - if not isinstance(exc, Exception): - raise - else: - if not future.cancelled(): - future.set_result(retval) - finally: - scope = None # type: ignore[assignment] - - def _spawn_task_from_thread( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], - args: tuple[Unpack[PosArgsT]], - kwargs: dict[str, Any], - name: object, - future: Future[T_Retval], - ) -> None: - """ - Spawn a new task using the given callable. - - :param func: a callable - :param args: positional arguments to be passed to the callable - :param kwargs: keyword arguments to be passed to the callable - :param name: name of the task (will be coerced to a string if not ``None``) - :param future: a future that will resolve to the return value of the callable, - or the exception raised during its execution - - """ - run_sync( - partial(self._task_group.start_soon, name=name), - self._call_func, - func, - args, - kwargs, - future, - token=self._token, - ) - - @overload - def call( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - *args: Unpack[PosArgsT], - ) -> T_Retval: ... - - @overload - def call( - self, func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT] - ) -> T_Retval: ... - - def call( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], - *args: Unpack[PosArgsT], - ) -> T_Retval: - """ - Call the given function in the event loop thread. - - If the callable returns a coroutine object, it is awaited on. - - :param func: any callable - :raises RuntimeError: if the portal is not running or if this method is called - from within the event loop thread - - """ - return cast(T_Retval, self.start_task_soon(func, *args).result()) - - @overload - def start_task_soon( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - *args: Unpack[PosArgsT], - name: object = None, - ) -> Future[T_Retval]: ... - - @overload - def start_task_soon( - self, - func: Callable[[Unpack[PosArgsT]], T_Retval], - *args: Unpack[PosArgsT], - name: object = None, - ) -> Future[T_Retval]: ... - - def start_task_soon( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], - *args: Unpack[PosArgsT], - name: object = None, - ) -> Future[T_Retval]: - """ - Start a task in the portal's task group. - - The task will be run inside a cancel scope which can be cancelled by cancelling - the returned future. - - :param func: the target function - :param args: positional arguments passed to ``func`` - :param name: name of the task (will be coerced to a string if not ``None``) - :return: a future that resolves with the return value of the callable if the - task completes successfully, or with the exception raised in the task - :raises RuntimeError: if the portal is not running or if this method is called - from within the event loop thread - :rtype: concurrent.futures.Future[T_Retval] - - .. versionadded:: 3.0 - - """ - self._check_running() - f: Future[T_Retval] = Future() - self._spawn_task_from_thread(func, args, {}, name, f) - return f - - def start_task( - self, - func: Callable[..., Awaitable[T_Retval]], - *args: object, - name: object = None, - ) -> tuple[Future[T_Retval], Any]: - """ - Start a task in the portal's task group and wait until it signals for readiness. - - This method works the same way as :meth:`.abc.TaskGroup.start`. - - :param func: the target function - :param args: positional arguments passed to ``func`` - :param name: name of the task (will be coerced to a string if not ``None``) - :return: a tuple of (future, task_status_value) where the ``task_status_value`` - is the value passed to ``task_status.started()`` from within the target - function - :rtype: tuple[concurrent.futures.Future[T_Retval], Any] - - .. versionadded:: 3.0 - - """ - - def task_done(future: Future[T_Retval]) -> None: - if not task_status_future.done(): - if future.cancelled(): - task_status_future.cancel() - elif future.exception(): - task_status_future.set_exception(future.exception()) - else: - exc = RuntimeError( - "Task exited without calling task_status.started()" - ) - task_status_future.set_exception(exc) - - self._check_running() - task_status_future: Future = Future() - task_status = _BlockingPortalTaskStatus(task_status_future) - f: Future = Future() - f.add_done_callback(task_done) - self._spawn_task_from_thread(func, args, {"task_status": task_status}, name, f) - return f, task_status_future.result() - - def wrap_async_context_manager( - self, cm: AbstractAsyncContextManager[T_co] - ) -> AbstractContextManager[T_co]: - """ - Wrap an async context manager as a synchronous context manager via this portal. - - Spawns a task that will call both ``__aenter__()`` and ``__aexit__()``, stopping - in the middle until the synchronous context manager exits. - - :param cm: an asynchronous context manager - :return: a synchronous context manager - - .. versionadded:: 2.1 - - """ - return _BlockingAsyncContextManager(cm, self) - - -@dataclass -class BlockingPortalProvider: - """ - A manager for a blocking portal. Used as a context manager. The first thread to - enter this context manager causes a blocking portal to be started with the specific - parameters, and the last thread to exit causes the portal to be shut down. Thus, - there will be exactly one blocking portal running in this context as long as at - least one thread has entered this context manager. - - The parameters are the same as for :func:`~anyio.run`. - - :param backend: name of the backend - :param backend_options: backend options - - .. versionadded:: 4.4 - """ - - backend: str = "asyncio" - backend_options: dict[str, Any] | None = None - _lock: Lock = field(init=False, default_factory=Lock) - _leases: int = field(init=False, default=0) - _portal: BlockingPortal = field(init=False) - _portal_cm: AbstractContextManager[BlockingPortal] | None = field( - init=False, default=None - ) - - def __enter__(self) -> BlockingPortal: - with self._lock: - if self._portal_cm is None: - self._portal_cm = start_blocking_portal( - self.backend, self.backend_options - ) - self._portal = self._portal_cm.__enter__() - - self._leases += 1 - return self._portal - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - portal_cm: AbstractContextManager[BlockingPortal] | None = None - with self._lock: - assert self._portal_cm - assert self._leases > 0 - self._leases -= 1 - if not self._leases: - portal_cm = self._portal_cm - self._portal_cm = None - del self._portal - - if portal_cm: - portal_cm.__exit__(None, None, None) - - -@contextmanager -def start_blocking_portal( - backend: str = "asyncio", - backend_options: dict[str, Any] | None = None, - *, - name: str | None = None, -) -> Generator[BlockingPortal, Any, None]: - """ - Start a new event loop in a new thread and run a blocking portal in its main task. - - The parameters are the same as for :func:`~anyio.run`. - - :param backend: name of the backend - :param backend_options: backend options - :param name: name of the thread - :return: a context manager that yields a blocking portal - - .. versionchanged:: 3.0 - Usage as a context manager is now required. - - """ - - async def run_portal() -> None: - async with BlockingPortal() as portal_: - if name is None: - current_thread().name = f"{backend}-portal-{id(portal_):x}" - - future.set_result(portal_) - await portal_.sleep_until_stopped() - - def run_blocking_portal() -> None: - if future.set_running_or_notify_cancel(): - try: - run_eventloop( - run_portal, backend=backend, backend_options=backend_options - ) - except BaseException as exc: - if not future.done(): - future.set_exception(exc) - - future: Future[BlockingPortal] = Future() - thread = Thread(target=run_blocking_portal, daemon=True, name=name) - thread.start() - try: - cancel_remaining_tasks = False - portal = future.result() - try: - yield portal - except BaseException: - cancel_remaining_tasks = True - raise - finally: - try: - portal.call(portal.stop, cancel_remaining_tasks) - except RuntimeError: - pass - finally: - thread.join() - - -def check_cancelled() -> None: - """ - Check if the cancel scope of the host task's running the current worker thread has - been cancelled. - - If the host task's current cancel scope has indeed been cancelled, the - backend-specific cancellation exception will be raised. - - :raises RuntimeError: if the current thread was not spawned by - :func:`.to_thread.run_sync` - - """ - try: - token: EventLoopToken = threadlocals.current_token - except AttributeError: - raise NoEventLoopError( - "This function can only be called inside an AnyIO worker thread" - ) from None - - token.backend_class.check_cancelled() diff --git a/notification-service/venv/Lib/site-packages/anyio/functools.py b/notification-service/venv/Lib/site-packages/anyio/functools.py deleted file mode 100644 index f1d6c7c..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/functools.py +++ /dev/null @@ -1,409 +0,0 @@ -from __future__ import annotations - -__all__ = ( - "AsyncCacheInfo", - "AsyncCacheParameters", - "AsyncLRUCacheWrapper", - "cache", - "lru_cache", - "reduce", -) - -import functools -import sys -from collections import OrderedDict -from collections.abc import ( - AsyncIterable, - Awaitable, - Callable, - Coroutine, - Hashable, - Iterable, -) -from functools import update_wrapper -from inspect import iscoroutinefunction -from typing import ( - Any, - Generic, - NamedTuple, - TypedDict, - TypeVar, - cast, - final, - overload, -) -from weakref import WeakKeyDictionary - -from ._core._eventloop import current_time -from ._core._synchronization import Lock -from .lowlevel import RunVar, checkpoint - -if sys.version_info >= (3, 11): - from typing import ParamSpec -else: - from typing_extensions import ParamSpec - -T = TypeVar("T") -S = TypeVar("S") -P = ParamSpec("P") -lru_cache_items: RunVar[ - WeakKeyDictionary[ - AsyncLRUCacheWrapper[Any, Any], - OrderedDict[ - Hashable, - tuple[_InitialMissingType, Lock, float | None] - | tuple[Any, None, float | None], - ], - ] -] = RunVar("lru_cache_items") - - -class _InitialMissingType: - pass - - -initial_missing: _InitialMissingType = _InitialMissingType() - - -class AsyncCacheInfo(NamedTuple): - hits: int - misses: int - maxsize: int | None - currsize: int - ttl: int | None - - -class AsyncCacheParameters(TypedDict): - maxsize: int | None - typed: bool - always_checkpoint: bool - ttl: int | None - - -class _LRUMethodWrapper(Generic[T]): - def __init__(self, wrapper: AsyncLRUCacheWrapper[..., T], instance: object): - self.__wrapper = wrapper - self.__instance = instance - - def cache_info(self) -> AsyncCacheInfo: - return self.__wrapper.cache_info() - - def cache_parameters(self) -> AsyncCacheParameters: - return self.__wrapper.cache_parameters() - - def cache_clear(self) -> None: - self.__wrapper.cache_clear() - - async def __call__(self, *args: Any, **kwargs: Any) -> T: - if self.__instance is None: - return await self.__wrapper(*args, **kwargs) - - return await self.__wrapper(self.__instance, *args, **kwargs) - - -@final -class AsyncLRUCacheWrapper(Generic[P, T]): - def __init__( - self, - func: Callable[P, Awaitable[T]], - maxsize: int | None, - typed: bool, - always_checkpoint: bool, - ttl: int | None, - ): - self.__wrapped__ = func - self._hits: int = 0 - self._misses: int = 0 - self._maxsize = max(maxsize, 0) if maxsize is not None else None - self._currsize: int = 0 - self._typed = typed - self._always_checkpoint = always_checkpoint - self._ttl = ttl - update_wrapper(self, func) - - def cache_info(self) -> AsyncCacheInfo: - return AsyncCacheInfo( - self._hits, self._misses, self._maxsize, self._currsize, self._ttl - ) - - def cache_parameters(self) -> AsyncCacheParameters: - return { - "maxsize": self._maxsize, - "typed": self._typed, - "always_checkpoint": self._always_checkpoint, - "ttl": self._ttl, - } - - def cache_clear(self) -> None: - if cache := lru_cache_items.get(None): - cache.pop(self, None) - self._hits = self._misses = self._currsize = 0 - - async def __call__(self, *args: P.args, **kwargs: P.kwargs) -> T: - # Easy case first: if maxsize == 0, no caching is done - if self._maxsize == 0: - value = await self.__wrapped__(*args, **kwargs) - self._misses += 1 - return value - - # The key is constructed as a flat tuple to avoid memory overhead - key: tuple[Any, ...] = args - if kwargs: - # initial_missing is used as a separator - key += (initial_missing,) + sum(kwargs.items(), ()) - - if self._typed: - key += tuple(type(arg) for arg in args) - if kwargs: - key += (initial_missing,) + tuple(type(val) for val in kwargs.values()) - - try: - cache = lru_cache_items.get() - except LookupError: - cache = WeakKeyDictionary() - lru_cache_items.set(cache) - - try: - cache_entry = cache[self] - except KeyError: - cache_entry = cache[self] = OrderedDict() - - cached_value: T | _InitialMissingType - try: - cached_value, lock, expires_at = cache_entry[key] - except KeyError: - # We're the first task to call this function - cached_value, lock, expires_at = ( - initial_missing, - Lock(fast_acquire=not self._always_checkpoint), - None, - ) - cache_entry[key] = cached_value, lock, expires_at - - if lock is None: - if expires_at is not None and current_time() >= expires_at: - self._currsize -= 1 - cached_value, lock, expires_at = ( - initial_missing, - Lock(fast_acquire=not self._always_checkpoint), - None, - ) - cache_entry[key] = cached_value, lock, expires_at - else: - # The value was already cached - self._hits += 1 - cache_entry.move_to_end(key) - if self._always_checkpoint: - await checkpoint() - - return cast(T, cached_value) - - async with lock: - # Check if another task filled the cache while we acquired the lock - if (cached_value := cache_entry[key][0]) is initial_missing: - self._misses += 1 - if self._maxsize is not None and self._currsize >= self._maxsize: - cache_entry.popitem(last=False) - else: - self._currsize += 1 - - value = await self.__wrapped__(*args, **kwargs) - expires_at = ( - current_time() + self._ttl if self._ttl is not None else None - ) - cache_entry[key] = value, None, expires_at - else: - # Another task filled the cache while we were waiting for the lock - self._hits += 1 - cache_entry.move_to_end(key) - value = cast(T, cached_value) - - return value - - def __get__( - self, instance: object, owner: type | None = None - ) -> _LRUMethodWrapper[T]: - wrapper = _LRUMethodWrapper(self, instance) - update_wrapper(wrapper, self.__wrapped__) - return wrapper - - -class _LRUCacheWrapper(Generic[T]): - def __init__( - self, maxsize: int | None, typed: bool, always_checkpoint: bool, ttl: int | None - ): - self._maxsize = maxsize - self._typed = typed - self._always_checkpoint = always_checkpoint - self._ttl = ttl - - @overload - def __call__( # type: ignore[overload-overlap] - self, func: Callable[P, Coroutine[Any, Any, T]], / - ) -> AsyncLRUCacheWrapper[P, T]: ... - - @overload - def __call__( - self, func: Callable[..., T], / - ) -> functools._lru_cache_wrapper[T]: ... - - def __call__( - self, f: Callable[P, Coroutine[Any, Any, T]] | Callable[..., T], / - ) -> AsyncLRUCacheWrapper[P, T] | functools._lru_cache_wrapper[T]: - if iscoroutinefunction(f): - return AsyncLRUCacheWrapper( - f, self._maxsize, self._typed, self._always_checkpoint, self._ttl - ) - - return functools.lru_cache(maxsize=self._maxsize, typed=self._typed)(f) # type: ignore[arg-type] - - -@overload -def cache( # type: ignore[overload-overlap] - func: Callable[P, Coroutine[Any, Any, T]], / -) -> AsyncLRUCacheWrapper[P, T]: ... - - -@overload -def cache(func: Callable[..., T], /) -> functools._lru_cache_wrapper[T]: ... - - -def cache( - func: Callable[..., T] | Callable[P, Coroutine[Any, Any, T]], / -) -> AsyncLRUCacheWrapper[P, T] | functools._lru_cache_wrapper[T]: - """ - A convenient shortcut for :func:`lru_cache` with ``maxsize=None``. - - This is the asynchronous equivalent to :func:`functools.cache`. - - """ - return lru_cache(maxsize=None)(func) - - -@overload -def lru_cache( - *, - maxsize: int | None = ..., - typed: bool = ..., - always_checkpoint: bool = ..., - ttl: int | None = ..., -) -> _LRUCacheWrapper[Any]: ... - - -@overload -def lru_cache( # type: ignore[overload-overlap] - func: Callable[P, Coroutine[Any, Any, T]], / -) -> AsyncLRUCacheWrapper[P, T]: ... - - -@overload -def lru_cache(func: Callable[..., T], /) -> functools._lru_cache_wrapper[T]: ... - - -def lru_cache( - func: Callable[P, Coroutine[Any, Any, T]] | Callable[..., T] | None = None, - /, - *, - maxsize: int | None = 128, - typed: bool = False, - always_checkpoint: bool = False, - ttl: int | None = None, -) -> ( - AsyncLRUCacheWrapper[P, T] | functools._lru_cache_wrapper[T] | _LRUCacheWrapper[Any] -): - """ - An asynchronous version of :func:`functools.lru_cache`. - - If a synchronous function is passed, the standard library - :func:`functools.lru_cache` is applied instead. - - :param always_checkpoint: if ``True``, every call to the cached function will be - guaranteed to yield control to the event loop at least once - :param ttl: time in seconds after which to invalidate cache entries - - .. note:: Caches and locks are managed on a per-event loop basis. - - """ - if func is None: - return _LRUCacheWrapper[Any](maxsize, typed, always_checkpoint, ttl) - - if not callable(func): - raise TypeError("the first argument must be callable") - - return _LRUCacheWrapper[T](maxsize, typed, always_checkpoint, ttl)(func) - - -@overload -async def reduce( - function: Callable[[T, S], Awaitable[T]], - iterable: Iterable[S] | AsyncIterable[S], - /, - initial: T, -) -> T: ... - - -@overload -async def reduce( - function: Callable[[T, T], Awaitable[T]], - iterable: Iterable[T] | AsyncIterable[T], - /, -) -> T: ... - - -async def reduce( # type: ignore[misc] - function: Callable[[T, T], Awaitable[T]] | Callable[[T, S], Awaitable[T]], - iterable: Iterable[T] | Iterable[S] | AsyncIterable[T] | AsyncIterable[S], - /, - initial: T | _InitialMissingType = initial_missing, -) -> T: - """ - Asynchronous version of :func:`functools.reduce`. - - :param function: a coroutine function that takes two arguments: the accumulated - value and the next element from the iterable - :param iterable: an iterable or async iterable - :param initial: the initial value (if missing, the first element of the iterable is - used as the initial value) - - """ - element: Any - function_called = False - if isinstance(iterable, AsyncIterable): - async_it = iterable.__aiter__() - if initial is initial_missing: - try: - value = cast(T, await async_it.__anext__()) - except StopAsyncIteration: - raise TypeError( - "reduce() of empty sequence with no initial value" - ) from None - else: - value = cast(T, initial) - - async for element in async_it: - value = await function(value, element) - function_called = True - elif isinstance(iterable, Iterable): - it = iter(iterable) - if initial is initial_missing: - try: - value = cast(T, next(it)) - except StopIteration: - raise TypeError( - "reduce() of empty sequence with no initial value" - ) from None - else: - value = cast(T, initial) - - for element in it: - value = await function(value, element) - function_called = True - else: - raise TypeError("reduce() argument 2 must be an iterable or async iterable") - - # Make sure there is at least one checkpoint, even if an empty iterable and an - # initial value were given - if not function_called: - await checkpoint() - - return value diff --git a/notification-service/venv/Lib/site-packages/anyio/lowlevel.py b/notification-service/venv/Lib/site-packages/anyio/lowlevel.py deleted file mode 100644 index ffbb75a..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/lowlevel.py +++ /dev/null @@ -1,196 +0,0 @@ -from __future__ import annotations - -__all__ = ( - "EventLoopToken", - "RunvarToken", - "RunVar", - "checkpoint", - "checkpoint_if_cancelled", - "cancel_shielded_checkpoint", - "current_token", -) - -import enum -from dataclasses import dataclass -from types import TracebackType -from typing import Any, Generic, Literal, TypeVar, final, overload -from weakref import WeakKeyDictionary - -from ._core._eventloop import get_async_backend -from .abc import AsyncBackend - -T = TypeVar("T") -D = TypeVar("D") - - -async def checkpoint() -> None: - """ - Check for cancellation and allow the scheduler to switch to another task. - - Equivalent to (but more efficient than):: - - await checkpoint_if_cancelled() - await cancel_shielded_checkpoint() - - .. versionadded:: 3.0 - - """ - await get_async_backend().checkpoint() - - -async def checkpoint_if_cancelled() -> None: - """ - Enter a checkpoint if the enclosing cancel scope has been cancelled. - - This does not allow the scheduler to switch to a different task. - - .. versionadded:: 3.0 - - """ - await get_async_backend().checkpoint_if_cancelled() - - -async def cancel_shielded_checkpoint() -> None: - """ - Allow the scheduler to switch to another task but without checking for cancellation. - - Equivalent to (but potentially more efficient than):: - - with CancelScope(shield=True): - await checkpoint() - - .. versionadded:: 3.0 - - """ - await get_async_backend().cancel_shielded_checkpoint() - - -@final -@dataclass(frozen=True, repr=False) -class EventLoopToken: - """ - An opaque object that holds a reference to an event loop. - - .. versionadded:: 4.11.0 - """ - - backend_class: type[AsyncBackend] - native_token: object - - -def current_token() -> EventLoopToken: - """ - Return a token object that can be used to call code in the current event loop from - another thread. - - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - .. versionadded:: 4.11.0 - - """ - backend_class = get_async_backend() - raw_token = backend_class.current_token() - return EventLoopToken(backend_class, raw_token) - - -_run_vars: WeakKeyDictionary[object, dict[RunVar[Any], Any]] = WeakKeyDictionary() - - -class _NoValueSet(enum.Enum): - NO_VALUE_SET = enum.auto() - - -class RunvarToken(Generic[T]): - __slots__ = "_var", "_value", "_redeemed" - - def __init__(self, var: RunVar[T], value: T | Literal[_NoValueSet.NO_VALUE_SET]): - self._var = var - self._value: T | Literal[_NoValueSet.NO_VALUE_SET] = value - self._redeemed = False - - def __enter__(self) -> RunvarToken[T]: - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self._var.reset(self) - - -class RunVar(Generic[T]): - """ - Like a :class:`~contextvars.ContextVar`, except scoped to the running event loop. - - Can be used as a context manager, Just like :class:`~contextvars.ContextVar`, that - will reset the variable to its previous value when the context block is exited. - """ - - __slots__ = "_name", "_default" - - NO_VALUE_SET: Literal[_NoValueSet.NO_VALUE_SET] = _NoValueSet.NO_VALUE_SET - - def __init__( - self, name: str, default: T | Literal[_NoValueSet.NO_VALUE_SET] = NO_VALUE_SET - ): - self._name = name - self._default = default - - @property - def _current_vars(self) -> dict[RunVar[T], T]: - native_token = current_token().native_token - try: - return _run_vars[native_token] - except KeyError: - run_vars = _run_vars[native_token] = {} - return run_vars - - @overload - def get(self, default: D) -> T | D: ... - - @overload - def get(self) -> T: ... - - def get( - self, default: D | Literal[_NoValueSet.NO_VALUE_SET] = NO_VALUE_SET - ) -> T | D: - try: - return self._current_vars[self] - except KeyError: - if default is not RunVar.NO_VALUE_SET: - return default - elif self._default is not RunVar.NO_VALUE_SET: - return self._default - - raise LookupError( - f'Run variable "{self._name}" has no value and no default set' - ) - - def set(self, value: T) -> RunvarToken[T]: - current_vars = self._current_vars - token = RunvarToken(self, current_vars.get(self, RunVar.NO_VALUE_SET)) - current_vars[self] = value - return token - - def reset(self, token: RunvarToken[T]) -> None: - if token._var is not self: - raise ValueError("This token does not belong to this RunVar") - - if token._redeemed: - raise ValueError("This token has already been used") - - if token._value is _NoValueSet.NO_VALUE_SET: - try: - del self._current_vars[self] - except KeyError: - pass - else: - self._current_vars[self] = token._value - - token._redeemed = True - - def __repr__(self) -> str: - return f"" diff --git a/notification-service/venv/Lib/site-packages/anyio/py.typed b/notification-service/venv/Lib/site-packages/anyio/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/anyio/pytest_plugin.py b/notification-service/venv/Lib/site-packages/anyio/pytest_plugin.py deleted file mode 100644 index a5183f0..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/pytest_plugin.py +++ /dev/null @@ -1,363 +0,0 @@ -from __future__ import annotations - -import dataclasses -import socket -import sys -from collections.abc import Callable, Generator, Iterator -from contextlib import ExitStack, contextmanager -from inspect import isasyncgenfunction, iscoroutinefunction, ismethod -from typing import Any, cast - -import pytest -from _pytest.fixtures import FuncFixtureInfo, SubRequest -from _pytest.outcomes import Exit -from _pytest.python import CallSpec2 -from _pytest.scope import Scope - -from . import get_available_backends -from ._core._eventloop import ( - current_async_library, - get_async_backend, - reset_current_async_library, - set_current_async_library, -) -from ._core._exceptions import iterate_exceptions -from .abc import TestRunner - -if sys.version_info < (3, 11): - from exceptiongroup import ExceptionGroup - -_current_runner: TestRunner | None = None -_runner_stack: ExitStack | None = None -_runner_leases = 0 - - -def extract_backend_and_options(backend: object) -> tuple[str, dict[str, Any]]: - if isinstance(backend, str): - return backend, {} - elif isinstance(backend, tuple) and len(backend) == 2: - if isinstance(backend[0], str) and isinstance(backend[1], dict): - return cast(tuple[str, dict[str, Any]], backend) - - raise TypeError("anyio_backend must be either a string or tuple of (string, dict)") - - -@contextmanager -def get_runner( - backend_name: str, backend_options: dict[str, Any] -) -> Iterator[TestRunner]: - global _current_runner, _runner_leases, _runner_stack - if _current_runner is None: - asynclib = get_async_backend(backend_name) - _runner_stack = ExitStack() - if current_async_library() is None: - # Since we're in control of the event loop, we can cache the name of the - # async library - token = set_current_async_library(backend_name) - _runner_stack.callback(reset_current_async_library, token) - - backend_options = backend_options or {} - _current_runner = _runner_stack.enter_context( - asynclib.create_test_runner(backend_options) - ) - - _runner_leases += 1 - try: - yield _current_runner - finally: - _runner_leases -= 1 - if not _runner_leases: - assert _runner_stack is not None - _runner_stack.close() - _runner_stack = _current_runner = None - - -def pytest_addoption(parser: pytest.Parser) -> None: - parser.addini( - "anyio_mode", - default="strict", - help='AnyIO plugin mode (either "strict" or "auto")', - ) - - -def pytest_configure(config: pytest.Config) -> None: - config.addinivalue_line( - "markers", - "anyio: mark the (coroutine function) test to be run asynchronously via anyio.", - ) - if ( - config.getini("anyio_mode") == "auto" - and config.pluginmanager.has_plugin("asyncio") - and config.getini("asyncio_mode") == "auto" - ): - config.issue_config_time_warning( - pytest.PytestConfigWarning( - "AnyIO auto mode has been enabled together with pytest-asyncio auto " - "mode. This may cause unexpected behavior." - ), - 1, - ) - - -@pytest.hookimpl(hookwrapper=True) -def pytest_fixture_setup(fixturedef: Any, request: Any) -> Generator[Any]: - def wrapper(anyio_backend: Any, request: SubRequest, **kwargs: Any) -> Any: - # Rebind any fixture methods to the request instance - if ( - request.instance - and ismethod(func) - and type(func.__self__) is type(request.instance) - ): - local_func = func.__func__.__get__(request.instance) - else: - local_func = func - - backend_name, backend_options = extract_backend_and_options(anyio_backend) - if has_backend_arg: - kwargs["anyio_backend"] = anyio_backend - - if has_request_arg: - kwargs["request"] = request - - with get_runner(backend_name, backend_options) as runner: - if isasyncgenfunction(local_func): - yield from runner.run_asyncgen_fixture(local_func, kwargs) - else: - yield runner.run_fixture(local_func, kwargs) - - # Only apply this to coroutine functions and async generator functions in requests - # that involve the anyio_backend fixture - func = fixturedef.func - if isasyncgenfunction(func) or iscoroutinefunction(func): - if "anyio_backend" in request.fixturenames: - fixturedef.func = wrapper - original_argname = fixturedef.argnames - - if not (has_backend_arg := "anyio_backend" in fixturedef.argnames): - fixturedef.argnames += ("anyio_backend",) - - if not (has_request_arg := "request" in fixturedef.argnames): - fixturedef.argnames += ("request",) - - try: - return (yield) - finally: - fixturedef.func = func - fixturedef.argnames = original_argname - - return (yield) - - -@pytest.hookimpl(tryfirst=True) -def pytest_pycollect_makeitem( - collector: pytest.Module | pytest.Class, name: str, obj: object -) -> None: - if collector.istestfunction(obj, name): - inner_func = obj.hypothesis.inner_test if hasattr(obj, "hypothesis") else obj - if iscoroutinefunction(inner_func): - anyio_auto_mode = collector.config.getini("anyio_mode") == "auto" - marker = collector.get_closest_marker("anyio") - own_markers = getattr(obj, "pytestmark", ()) - if ( - anyio_auto_mode - or marker - or any(marker.name == "anyio" for marker in own_markers) - ): - pytest.mark.usefixtures("anyio_backend")(obj) - - -def pytest_collection_finish(session: pytest.Session) -> None: - for i, item in reversed(list(enumerate(session.items))): - if ( - isinstance(item, pytest.Function) - and iscoroutinefunction(item.function) - and item.get_closest_marker("anyio") is not None - and "anyio_backend" not in item.fixturenames - ): - new_items = [] - try: - cs_fields = {f.name for f in dataclasses.fields(CallSpec2)} - except TypeError: - cs_fields = set() - - for param_index, backend in enumerate(get_available_backends()): - if "_arg2scope" in cs_fields: # pytest >= 8 - callspec = CallSpec2( - params={"anyio_backend": backend}, - indices={"anyio_backend": param_index}, - _arg2scope={"anyio_backend": Scope.Module}, - _idlist=[backend], - marks=[], - ) - else: # pytest 7.x - callspec = CallSpec2( # type: ignore[call-arg] - funcargs={}, - params={"anyio_backend": backend}, - indices={"anyio_backend": param_index}, - arg2scope={"anyio_backend": Scope.Module}, - idlist=[backend], - marks=[], - ) - - fi = item._fixtureinfo - new_names_closure = list(fi.names_closure) - if "anyio_backend" not in new_names_closure: - new_names_closure.append("anyio_backend") - - new_fixtureinfo = FuncFixtureInfo( - argnames=fi.argnames, - initialnames=fi.initialnames, - names_closure=new_names_closure, - name2fixturedefs=fi.name2fixturedefs, - ) - new_item = pytest.Function.from_parent( - item.parent, - name=f"{item.originalname}[{backend}]", - callspec=callspec, - callobj=item.obj, - fixtureinfo=new_fixtureinfo, - keywords=item.keywords, - originalname=item.originalname, - ) - new_items.append(new_item) - - session.items[i : i + 1] = new_items - - -@pytest.hookimpl(tryfirst=True) -def pytest_pyfunc_call(pyfuncitem: Any) -> bool | None: - def run_with_hypothesis(**kwargs: Any) -> None: - with get_runner(backend_name, backend_options) as runner: - runner.run_test(original_func, kwargs) - - backend = pyfuncitem.funcargs.get("anyio_backend") - if backend: - backend_name, backend_options = extract_backend_and_options(backend) - - if hasattr(pyfuncitem.obj, "hypothesis"): - # Wrap the inner test function unless it's already wrapped - original_func = pyfuncitem.obj.hypothesis.inner_test - if original_func.__qualname__ != run_with_hypothesis.__qualname__: - if iscoroutinefunction(original_func): - pyfuncitem.obj.hypothesis.inner_test = run_with_hypothesis - - return None - - if iscoroutinefunction(pyfuncitem.obj): - funcargs = pyfuncitem.funcargs - testargs = {arg: funcargs[arg] for arg in pyfuncitem._fixtureinfo.argnames} - with get_runner(backend_name, backend_options) as runner: - try: - runner.run_test(pyfuncitem.obj, testargs) - except ExceptionGroup as excgrp: - for exc in iterate_exceptions(excgrp): - if isinstance(exc, (Exit, KeyboardInterrupt, SystemExit)): - raise exc from excgrp - - raise - - return True - - return None - - -@pytest.fixture(scope="module", params=get_available_backends()) -def anyio_backend(request: Any) -> Any: - return request.param - - -@pytest.fixture -def anyio_backend_name(anyio_backend: Any) -> str: - if isinstance(anyio_backend, str): - return anyio_backend - else: - return anyio_backend[0] - - -@pytest.fixture -def anyio_backend_options(anyio_backend: Any) -> dict[str, Any]: - if isinstance(anyio_backend, str): - return {} - else: - return anyio_backend[1] - - -class FreePortFactory: - """ - Manages port generation based on specified socket kind, ensuring no duplicate - ports are generated. - - This class provides functionality for generating available free ports on the - system. It is initialized with a specific socket kind and can generate ports - for given address families while avoiding reuse of previously generated ports. - - Users should not instantiate this class directly, but use the - ``free_tcp_port_factory`` and ``free_udp_port_factory`` fixtures instead. For simple - uses cases, ``free_tcp_port`` and ``free_udp_port`` can be used instead. - """ - - def __init__(self, kind: socket.SocketKind) -> None: - self._kind = kind - self._generated = set[int]() - - @property - def kind(self) -> socket.SocketKind: - """ - The type of socket connection (e.g., :data:`~socket.SOCK_STREAM` or - :data:`~socket.SOCK_DGRAM`) used to bind for checking port availability - - """ - return self._kind - - def __call__(self, family: socket.AddressFamily | None = None) -> int: - """ - Return an unbound port for the given address family. - - :param family: if omitted, both IPv4 and IPv6 addresses will be tried - :return: a port number - - """ - if family is not None: - families = [family] - else: - families = [socket.AF_INET] - if socket.has_ipv6: - families.append(socket.AF_INET6) - - while True: - port = 0 - with ExitStack() as stack: - for family in families: - sock = stack.enter_context(socket.socket(family, self._kind)) - addr = "::1" if family == socket.AF_INET6 else "127.0.0.1" - try: - sock.bind((addr, port)) - except OSError: - break - - if not port: - port = sock.getsockname()[1] - else: - if port not in self._generated: - self._generated.add(port) - return port - - -@pytest.fixture(scope="session") -def free_tcp_port_factory() -> FreePortFactory: - return FreePortFactory(socket.SOCK_STREAM) - - -@pytest.fixture(scope="session") -def free_udp_port_factory() -> FreePortFactory: - return FreePortFactory(socket.SOCK_DGRAM) - - -@pytest.fixture -def free_tcp_port(free_tcp_port_factory: Callable[[], int]) -> int: - return free_tcp_port_factory() - - -@pytest.fixture -def free_udp_port(free_udp_port_factory: Callable[[], int]) -> int: - return free_udp_port_factory() diff --git a/notification-service/venv/Lib/site-packages/anyio/streams/__init__.py b/notification-service/venv/Lib/site-packages/anyio/streams/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index c563323..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/buffered.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/buffered.cpython-312.pyc deleted file mode 100644 index c7491f8..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/buffered.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/file.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/file.cpython-312.pyc deleted file mode 100644 index 134aa26..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/file.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/memory.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/memory.cpython-312.pyc deleted file mode 100644 index 4272538..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/memory.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/stapled.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/stapled.cpython-312.pyc deleted file mode 100644 index 6cc35a6..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/stapled.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/text.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/text.cpython-312.pyc deleted file mode 100644 index 4f8bc65..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/text.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/tls.cpython-312.pyc b/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/tls.cpython-312.pyc deleted file mode 100644 index eedfe5b..0000000 Binary files a/notification-service/venv/Lib/site-packages/anyio/streams/__pycache__/tls.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/anyio/streams/buffered.py b/notification-service/venv/Lib/site-packages/anyio/streams/buffered.py deleted file mode 100644 index 57c7cd7..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/streams/buffered.py +++ /dev/null @@ -1,188 +0,0 @@ -from __future__ import annotations - -__all__ = ( - "BufferedByteReceiveStream", - "BufferedByteStream", - "BufferedConnectable", -) - -import sys -from collections.abc import Callable, Iterable, Mapping -from dataclasses import dataclass, field -from typing import Any, SupportsIndex - -from .. import ClosedResourceError, DelimiterNotFound, EndOfStream, IncompleteRead -from ..abc import ( - AnyByteReceiveStream, - AnyByteStream, - AnyByteStreamConnectable, - ByteReceiveStream, - ByteStream, - ByteStreamConnectable, -) - -if sys.version_info >= (3, 12): - from typing import override -else: - from typing_extensions import override - - -@dataclass(eq=False) -class BufferedByteReceiveStream(ByteReceiveStream): - """ - Wraps any bytes-based receive stream and uses a buffer to provide sophisticated - receiving capabilities in the form of a byte stream. - """ - - receive_stream: AnyByteReceiveStream - _buffer: bytearray = field(init=False, default_factory=bytearray) - _closed: bool = field(init=False, default=False) - - async def aclose(self) -> None: - await self.receive_stream.aclose() - self._closed = True - - @property - def buffer(self) -> bytes: - """The bytes currently in the buffer.""" - return bytes(self._buffer) - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return self.receive_stream.extra_attributes - - def feed_data(self, data: Iterable[SupportsIndex], /) -> None: - """ - Append data directly into the buffer. - - Any data in the buffer will be consumed by receive operations before receiving - anything from the wrapped stream. - - :param data: the data to append to the buffer (can be bytes or anything else - that supports ``__index__()``) - - """ - self._buffer.extend(data) - - async def receive(self, max_bytes: int = 65536) -> bytes: - if self._closed: - raise ClosedResourceError - - if self._buffer: - chunk = bytes(self._buffer[:max_bytes]) - del self._buffer[:max_bytes] - return chunk - elif isinstance(self.receive_stream, ByteReceiveStream): - return await self.receive_stream.receive(max_bytes) - else: - # With a bytes-oriented object stream, we need to handle any surplus bytes - # we get from the receive() call - chunk = await self.receive_stream.receive() - if len(chunk) > max_bytes: - # Save the surplus bytes in the buffer - self._buffer.extend(chunk[max_bytes:]) - return chunk[:max_bytes] - else: - return chunk - - async def receive_exactly(self, nbytes: int) -> bytes: - """ - Read exactly the given amount of bytes from the stream. - - :param nbytes: the number of bytes to read - :return: the bytes read - :raises ~anyio.IncompleteRead: if the stream was closed before the requested - amount of bytes could be read from the stream - - """ - while True: - remaining = nbytes - len(self._buffer) - if remaining <= 0: - retval = self._buffer[:nbytes] - del self._buffer[:nbytes] - return bytes(retval) - - try: - if isinstance(self.receive_stream, ByteReceiveStream): - chunk = await self.receive_stream.receive(remaining) - else: - chunk = await self.receive_stream.receive() - except EndOfStream as exc: - raise IncompleteRead from exc - - self._buffer.extend(chunk) - - async def receive_until(self, delimiter: bytes, max_bytes: int) -> bytes: - """ - Read from the stream until the delimiter is found or max_bytes have been read. - - :param delimiter: the marker to look for in the stream - :param max_bytes: maximum number of bytes that will be read before raising - :exc:`~anyio.DelimiterNotFound` - :return: the bytes read (not including the delimiter) - :raises ~anyio.IncompleteRead: if the stream was closed before the delimiter - was found - :raises ~anyio.DelimiterNotFound: if the delimiter is not found within the - bytes read up to the maximum allowed - - """ - delimiter_size = len(delimiter) - offset = 0 - while True: - # Check if the delimiter can be found in the current buffer - index = self._buffer.find(delimiter, offset) - if index >= 0: - found = self._buffer[:index] - del self._buffer[: index + len(delimiter) :] - return bytes(found) - - # Check if the buffer is already at or over the limit - if len(self._buffer) >= max_bytes: - raise DelimiterNotFound(max_bytes) - - # Read more data into the buffer from the socket - try: - data = await self.receive_stream.receive() - except EndOfStream as exc: - raise IncompleteRead from exc - - # Move the offset forward and add the new data to the buffer - offset = max(len(self._buffer) - delimiter_size + 1, 0) - self._buffer.extend(data) - - -class BufferedByteStream(BufferedByteReceiveStream, ByteStream): - """ - A full-duplex variant of :class:`BufferedByteReceiveStream`. All writes are passed - through to the wrapped stream as-is. - """ - - def __init__(self, stream: AnyByteStream): - """ - :param stream: the stream to be wrapped - - """ - super().__init__(stream) - self._stream = stream - - @override - async def send_eof(self) -> None: - await self._stream.send_eof() - - @override - async def send(self, item: bytes) -> None: - await self._stream.send(item) - - -class BufferedConnectable(ByteStreamConnectable): - def __init__(self, connectable: AnyByteStreamConnectable): - """ - :param connectable: the connectable to wrap - - """ - self.connectable = connectable - - @override - async def connect(self) -> BufferedByteStream: - stream = await self.connectable.connect() - return BufferedByteStream(stream) diff --git a/notification-service/venv/Lib/site-packages/anyio/streams/file.py b/notification-service/venv/Lib/site-packages/anyio/streams/file.py deleted file mode 100644 index 79c3d50..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/streams/file.py +++ /dev/null @@ -1,154 +0,0 @@ -from __future__ import annotations - -__all__ = ( - "FileReadStream", - "FileStreamAttribute", - "FileWriteStream", -) - -from collections.abc import Callable, Mapping -from io import SEEK_SET, UnsupportedOperation -from os import PathLike -from pathlib import Path -from typing import IO, Any - -from .. import ( - BrokenResourceError, - ClosedResourceError, - EndOfStream, - TypedAttributeSet, - to_thread, - typed_attribute, -) -from ..abc import ByteReceiveStream, ByteSendStream - - -class FileStreamAttribute(TypedAttributeSet): - #: the open file descriptor - file: IO[bytes] = typed_attribute() - #: the path of the file on the file system, if available (file must be a real file) - path: Path = typed_attribute() - #: the file number, if available (file must be a real file or a TTY) - fileno: int = typed_attribute() - - -class _BaseFileStream: - def __init__(self, file: IO[bytes]): - self._file = file - - async def aclose(self) -> None: - await to_thread.run_sync(self._file.close) - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - attributes: dict[Any, Callable[[], Any]] = { - FileStreamAttribute.file: lambda: self._file, - } - - if hasattr(self._file, "name"): - attributes[FileStreamAttribute.path] = lambda: Path(self._file.name) - - try: - self._file.fileno() - except UnsupportedOperation: - pass - else: - attributes[FileStreamAttribute.fileno] = lambda: self._file.fileno() - - return attributes - - -class FileReadStream(_BaseFileStream, ByteReceiveStream): - """ - A byte stream that reads from a file in the file system. - - :param file: a file that has been opened for reading in binary mode - - .. versionadded:: 3.0 - """ - - @classmethod - async def from_path(cls, path: str | PathLike[str]) -> FileReadStream: - """ - Create a file read stream by opening the given file. - - :param path: path of the file to read from - - """ - file = await to_thread.run_sync(Path(path).open, "rb") - return cls(file) - - async def receive(self, max_bytes: int = 65536) -> bytes: - try: - data = await to_thread.run_sync(self._file.read, max_bytes) - except ValueError: - raise ClosedResourceError from None - except OSError as exc: - raise BrokenResourceError from exc - - if data: - return data - else: - raise EndOfStream - - async def seek(self, position: int, whence: int = SEEK_SET) -> int: - """ - Seek the file to the given position. - - .. seealso:: :meth:`io.IOBase.seek` - - .. note:: Not all file descriptors are seekable. - - :param position: position to seek the file to - :param whence: controls how ``position`` is interpreted - :return: the new absolute position - :raises OSError: if the file is not seekable - - """ - return await to_thread.run_sync(self._file.seek, position, whence) - - async def tell(self) -> int: - """ - Return the current stream position. - - .. note:: Not all file descriptors are seekable. - - :return: the current absolute position - :raises OSError: if the file is not seekable - - """ - return await to_thread.run_sync(self._file.tell) - - -class FileWriteStream(_BaseFileStream, ByteSendStream): - """ - A byte stream that writes to a file in the file system. - - :param file: a file that has been opened for writing in binary mode - - .. versionadded:: 3.0 - """ - - @classmethod - async def from_path( - cls, path: str | PathLike[str], append: bool = False - ) -> FileWriteStream: - """ - Create a file write stream by opening the given file for writing. - - :param path: path of the file to write to - :param append: if ``True``, open the file for appending; if ``False``, any - existing file at the given path will be truncated - - """ - mode = "ab" if append else "wb" - file = await to_thread.run_sync(Path(path).open, mode) - return cls(file) - - async def send(self, item: bytes) -> None: - try: - await to_thread.run_sync(self._file.write, item) - except ValueError: - raise ClosedResourceError from None - except OSError as exc: - raise BrokenResourceError from exc diff --git a/notification-service/venv/Lib/site-packages/anyio/streams/memory.py b/notification-service/venv/Lib/site-packages/anyio/streams/memory.py deleted file mode 100644 index a3fa0c3..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/streams/memory.py +++ /dev/null @@ -1,325 +0,0 @@ -from __future__ import annotations - -__all__ = ( - "MemoryObjectReceiveStream", - "MemoryObjectSendStream", - "MemoryObjectStreamStatistics", -) - -import warnings -from collections import OrderedDict, deque -from dataclasses import dataclass, field -from types import TracebackType -from typing import Generic, NamedTuple, TypeVar - -from .. import ( - BrokenResourceError, - ClosedResourceError, - EndOfStream, - WouldBlock, -) -from .._core._testing import TaskInfo, get_current_task -from ..abc import Event, ObjectReceiveStream, ObjectSendStream -from ..lowlevel import checkpoint - -T_Item = TypeVar("T_Item") -T_co = TypeVar("T_co", covariant=True) -T_contra = TypeVar("T_contra", contravariant=True) - - -class MemoryObjectStreamStatistics(NamedTuple): - current_buffer_used: int #: number of items stored in the buffer - #: maximum number of items that can be stored on this stream (or :data:`math.inf`) - max_buffer_size: float - open_send_streams: int #: number of unclosed clones of the send stream - open_receive_streams: int #: number of unclosed clones of the receive stream - #: number of tasks blocked on :meth:`MemoryObjectSendStream.send` - tasks_waiting_send: int - #: number of tasks blocked on :meth:`MemoryObjectReceiveStream.receive` - tasks_waiting_receive: int - - -@dataclass(eq=False) -class _MemoryObjectItemReceiver(Generic[T_Item]): - task_info: TaskInfo = field(init=False, default_factory=get_current_task) - item: T_Item = field(init=False) - - def __repr__(self) -> str: - # When item is not defined, we get following error with default __repr__: - # AttributeError: 'MemoryObjectItemReceiver' object has no attribute 'item' - item = getattr(self, "item", None) - return f"{self.__class__.__name__}(task_info={self.task_info}, item={item!r})" - - -@dataclass(eq=False) -class _MemoryObjectStreamState(Generic[T_Item]): - max_buffer_size: float = field() - buffer: deque[T_Item] = field(init=False, default_factory=deque) - open_send_channels: int = field(init=False, default=0) - open_receive_channels: int = field(init=False, default=0) - waiting_receivers: OrderedDict[Event, _MemoryObjectItemReceiver[T_Item]] = field( - init=False, default_factory=OrderedDict - ) - waiting_senders: OrderedDict[Event, T_Item] = field( - init=False, default_factory=OrderedDict - ) - - def statistics(self) -> MemoryObjectStreamStatistics: - return MemoryObjectStreamStatistics( - len(self.buffer), - self.max_buffer_size, - self.open_send_channels, - self.open_receive_channels, - len(self.waiting_senders), - len(self.waiting_receivers), - ) - - -@dataclass(eq=False) -class MemoryObjectReceiveStream(Generic[T_co], ObjectReceiveStream[T_co]): - _state: _MemoryObjectStreamState[T_co] - _closed: bool = field(init=False, default=False) - - def __post_init__(self) -> None: - self._state.open_receive_channels += 1 - - def receive_nowait(self) -> T_co: - """ - Receive the next item if it can be done without waiting. - - :return: the received item - :raises ~anyio.ClosedResourceError: if this send stream has been closed - :raises ~anyio.EndOfStream: if the buffer is empty and this stream has been - closed from the sending end - :raises ~anyio.WouldBlock: if there are no items in the buffer and no tasks - waiting to send - - """ - if self._closed: - raise ClosedResourceError - - if self._state.waiting_senders: - # Get the item from the next sender - send_event, item = self._state.waiting_senders.popitem(last=False) - self._state.buffer.append(item) - send_event.set() - - if self._state.buffer: - return self._state.buffer.popleft() - elif not self._state.open_send_channels: - raise EndOfStream - - raise WouldBlock - - async def receive(self) -> T_co: - await checkpoint() - try: - return self.receive_nowait() - except WouldBlock: - # Add ourselves in the queue - receive_event = Event() - receiver = _MemoryObjectItemReceiver[T_co]() - self._state.waiting_receivers[receive_event] = receiver - - try: - await receive_event.wait() - finally: - self._state.waiting_receivers.pop(receive_event, None) - - try: - return receiver.item - except AttributeError: - raise EndOfStream from None - - def clone(self) -> MemoryObjectReceiveStream[T_co]: - """ - Create a clone of this receive stream. - - Each clone can be closed separately. Only when all clones have been closed will - the receiving end of the memory stream be considered closed by the sending ends. - - :return: the cloned stream - - """ - if self._closed: - raise ClosedResourceError - - return MemoryObjectReceiveStream(_state=self._state) - - def close(self) -> None: - """ - Close the stream. - - This works the exact same way as :meth:`aclose`, but is provided as a special - case for the benefit of synchronous callbacks. - - """ - if not self._closed: - self._closed = True - self._state.open_receive_channels -= 1 - if self._state.open_receive_channels == 0: - send_events = list(self._state.waiting_senders.keys()) - for event in send_events: - event.set() - - async def aclose(self) -> None: - self.close() - - def statistics(self) -> MemoryObjectStreamStatistics: - """ - Return statistics about the current state of this stream. - - .. versionadded:: 3.0 - """ - return self._state.statistics() - - def __enter__(self) -> MemoryObjectReceiveStream[T_co]: - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self.close() - - def __del__(self) -> None: - if not self._closed: - warnings.warn( - f"Unclosed <{self.__class__.__name__} at {id(self):x}>", - ResourceWarning, - stacklevel=1, - source=self, - ) - - -@dataclass(eq=False) -class MemoryObjectSendStream(Generic[T_contra], ObjectSendStream[T_contra]): - _state: _MemoryObjectStreamState[T_contra] - _closed: bool = field(init=False, default=False) - - def __post_init__(self) -> None: - self._state.open_send_channels += 1 - - def send_nowait(self, item: T_contra) -> None: - """ - Send an item immediately if it can be done without waiting. - - :param item: the item to send - :raises ~anyio.ClosedResourceError: if this send stream has been closed - :raises ~anyio.BrokenResourceError: if the stream has been closed from the - receiving end - :raises ~anyio.WouldBlock: if the buffer is full and there are no tasks waiting - to receive - - """ - if self._closed: - raise ClosedResourceError - if not self._state.open_receive_channels: - raise BrokenResourceError - - while self._state.waiting_receivers: - receive_event, receiver = self._state.waiting_receivers.popitem(last=False) - if not receiver.task_info.has_pending_cancellation(): - receiver.item = item - receive_event.set() - return - - if len(self._state.buffer) < self._state.max_buffer_size: - self._state.buffer.append(item) - else: - raise WouldBlock - - async def send(self, item: T_contra) -> None: - """ - Send an item to the stream. - - If the buffer is full, this method blocks until there is again room in the - buffer or the item can be sent directly to a receiver. - - :param item: the item to send - :raises ~anyio.ClosedResourceError: if this send stream has been closed - :raises ~anyio.BrokenResourceError: if the stream has been closed from the - receiving end - - """ - await checkpoint() - try: - self.send_nowait(item) - except WouldBlock: - # Wait until there's someone on the receiving end - send_event = Event() - self._state.waiting_senders[send_event] = item - try: - await send_event.wait() - except BaseException: - self._state.waiting_senders.pop(send_event, None) - raise - - if send_event in self._state.waiting_senders: - del self._state.waiting_senders[send_event] - raise BrokenResourceError from None - - def clone(self) -> MemoryObjectSendStream[T_contra]: - """ - Create a clone of this send stream. - - Each clone can be closed separately. Only when all clones have been closed will - the sending end of the memory stream be considered closed by the receiving ends. - - :return: the cloned stream - - """ - if self._closed: - raise ClosedResourceError - - return MemoryObjectSendStream(_state=self._state) - - def close(self) -> None: - """ - Close the stream. - - This works the exact same way as :meth:`aclose`, but is provided as a special - case for the benefit of synchronous callbacks. - - """ - if not self._closed: - self._closed = True - self._state.open_send_channels -= 1 - if self._state.open_send_channels == 0: - receive_events = list(self._state.waiting_receivers.keys()) - self._state.waiting_receivers.clear() - for event in receive_events: - event.set() - - async def aclose(self) -> None: - self.close() - - def statistics(self) -> MemoryObjectStreamStatistics: - """ - Return statistics about the current state of this stream. - - .. versionadded:: 3.0 - """ - return self._state.statistics() - - def __enter__(self) -> MemoryObjectSendStream[T_contra]: - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self.close() - - def __del__(self) -> None: - if not self._closed: - warnings.warn( - f"Unclosed <{self.__class__.__name__} at {id(self):x}>", - ResourceWarning, - stacklevel=1, - source=self, - ) diff --git a/notification-service/venv/Lib/site-packages/anyio/streams/stapled.py b/notification-service/venv/Lib/site-packages/anyio/streams/stapled.py deleted file mode 100644 index 9248b68..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/streams/stapled.py +++ /dev/null @@ -1,147 +0,0 @@ -from __future__ import annotations - -__all__ = ( - "MultiListener", - "StapledByteStream", - "StapledObjectStream", -) - -from collections.abc import Callable, Mapping, Sequence -from dataclasses import dataclass -from typing import Any, Generic, TypeVar - -from ..abc import ( - ByteReceiveStream, - ByteSendStream, - ByteStream, - Listener, - ObjectReceiveStream, - ObjectSendStream, - ObjectStream, - TaskGroup, -) - -T_Item = TypeVar("T_Item") -T_Stream = TypeVar("T_Stream") - - -@dataclass(eq=False) -class StapledByteStream(ByteStream): - """ - Combines two byte streams into a single, bidirectional byte stream. - - Extra attributes will be provided from both streams, with the receive stream - providing the values in case of a conflict. - - :param ByteSendStream send_stream: the sending byte stream - :param ByteReceiveStream receive_stream: the receiving byte stream - """ - - send_stream: ByteSendStream - receive_stream: ByteReceiveStream - - async def receive(self, max_bytes: int = 65536) -> bytes: - return await self.receive_stream.receive(max_bytes) - - async def send(self, item: bytes) -> None: - await self.send_stream.send(item) - - async def send_eof(self) -> None: - await self.send_stream.aclose() - - async def aclose(self) -> None: - await self.send_stream.aclose() - await self.receive_stream.aclose() - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return { - **self.send_stream.extra_attributes, - **self.receive_stream.extra_attributes, - } - - -@dataclass(eq=False) -class StapledObjectStream(Generic[T_Item], ObjectStream[T_Item]): - """ - Combines two object streams into a single, bidirectional object stream. - - Extra attributes will be provided from both streams, with the receive stream - providing the values in case of a conflict. - - :param ObjectSendStream send_stream: the sending object stream - :param ObjectReceiveStream receive_stream: the receiving object stream - """ - - send_stream: ObjectSendStream[T_Item] - receive_stream: ObjectReceiveStream[T_Item] - - async def receive(self) -> T_Item: - return await self.receive_stream.receive() - - async def send(self, item: T_Item) -> None: - await self.send_stream.send(item) - - async def send_eof(self) -> None: - await self.send_stream.aclose() - - async def aclose(self) -> None: - await self.send_stream.aclose() - await self.receive_stream.aclose() - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return { - **self.send_stream.extra_attributes, - **self.receive_stream.extra_attributes, - } - - -@dataclass(eq=False) -class MultiListener(Generic[T_Stream], Listener[T_Stream]): - """ - Combines multiple listeners into one, serving connections from all of them at once. - - Any MultiListeners in the given collection of listeners will have their listeners - moved into this one. - - Extra attributes are provided from each listener, with each successive listener - overriding any conflicting attributes from the previous one. - - :param listeners: listeners to serve - :type listeners: Sequence[Listener[T_Stream]] - """ - - listeners: Sequence[Listener[T_Stream]] - - def __post_init__(self) -> None: - listeners: list[Listener[T_Stream]] = [] - for listener in self.listeners: - if isinstance(listener, MultiListener): - listeners.extend(listener.listeners) - del listener.listeners[:] # type: ignore[attr-defined] - else: - listeners.append(listener) - - self.listeners = listeners - - async def serve( - self, handler: Callable[[T_Stream], Any], task_group: TaskGroup | None = None - ) -> None: - from .. import create_task_group - - async with create_task_group() as tg: - for listener in self.listeners: - tg.start_soon(listener.serve, handler, task_group) - - async def aclose(self) -> None: - for listener in self.listeners: - await listener.aclose() - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - attributes: dict = {} - for listener in self.listeners: - attributes.update(listener.extra_attributes) - - return attributes diff --git a/notification-service/venv/Lib/site-packages/anyio/streams/text.py b/notification-service/venv/Lib/site-packages/anyio/streams/text.py deleted file mode 100644 index 296cd25..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/streams/text.py +++ /dev/null @@ -1,176 +0,0 @@ -from __future__ import annotations - -__all__ = ( - "TextConnectable", - "TextReceiveStream", - "TextSendStream", - "TextStream", -) - -import codecs -import sys -from collections.abc import Callable, Mapping -from dataclasses import InitVar, dataclass, field -from typing import Any - -from ..abc import ( - AnyByteReceiveStream, - AnyByteSendStream, - AnyByteStream, - AnyByteStreamConnectable, - ObjectReceiveStream, - ObjectSendStream, - ObjectStream, - ObjectStreamConnectable, -) - -if sys.version_info >= (3, 12): - from typing import override -else: - from typing_extensions import override - - -@dataclass(eq=False) -class TextReceiveStream(ObjectReceiveStream[str]): - """ - Stream wrapper that decodes bytes to strings using the given encoding. - - Decoding is done using :class:`~codecs.IncrementalDecoder` which returns any - completely received unicode characters as soon as they come in. - - :param transport_stream: any bytes-based receive stream - :param encoding: character encoding to use for decoding bytes to strings (defaults - to ``utf-8``) - :param errors: handling scheme for decoding errors (defaults to ``strict``; see the - `codecs module documentation`_ for a comprehensive list of options) - - .. _codecs module documentation: - https://docs.python.org/3/library/codecs.html#codec-objects - """ - - transport_stream: AnyByteReceiveStream - encoding: InitVar[str] = "utf-8" - errors: InitVar[str] = "strict" - _decoder: codecs.IncrementalDecoder = field(init=False) - - def __post_init__(self, encoding: str, errors: str) -> None: - decoder_class = codecs.getincrementaldecoder(encoding) - self._decoder = decoder_class(errors=errors) - - async def receive(self) -> str: - while True: - chunk = await self.transport_stream.receive() - decoded = self._decoder.decode(chunk) - if decoded: - return decoded - - async def aclose(self) -> None: - await self.transport_stream.aclose() - self._decoder.reset() - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return self.transport_stream.extra_attributes - - -@dataclass(eq=False) -class TextSendStream(ObjectSendStream[str]): - """ - Sends strings to the wrapped stream as bytes using the given encoding. - - :param AnyByteSendStream transport_stream: any bytes-based send stream - :param str encoding: character encoding to use for encoding strings to bytes - (defaults to ``utf-8``) - :param str errors: handling scheme for encoding errors (defaults to ``strict``; see - the `codecs module documentation`_ for a comprehensive list of options) - - .. _codecs module documentation: - https://docs.python.org/3/library/codecs.html#codec-objects - """ - - transport_stream: AnyByteSendStream - encoding: InitVar[str] = "utf-8" - errors: str = "strict" - _encoder: Callable[..., tuple[bytes, int]] = field(init=False) - - def __post_init__(self, encoding: str) -> None: - self._encoder = codecs.getencoder(encoding) - - async def send(self, item: str) -> None: - encoded = self._encoder(item, self.errors)[0] - await self.transport_stream.send(encoded) - - async def aclose(self) -> None: - await self.transport_stream.aclose() - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return self.transport_stream.extra_attributes - - -@dataclass(eq=False) -class TextStream(ObjectStream[str]): - """ - A bidirectional stream that decodes bytes to strings on receive and encodes strings - to bytes on send. - - Extra attributes will be provided from both streams, with the receive stream - providing the values in case of a conflict. - - :param AnyByteStream transport_stream: any bytes-based stream - :param str encoding: character encoding to use for encoding/decoding strings to/from - bytes (defaults to ``utf-8``) - :param str errors: handling scheme for encoding errors (defaults to ``strict``; see - the `codecs module documentation`_ for a comprehensive list of options) - - .. _codecs module documentation: - https://docs.python.org/3/library/codecs.html#codec-objects - """ - - transport_stream: AnyByteStream - encoding: InitVar[str] = "utf-8" - errors: InitVar[str] = "strict" - _receive_stream: TextReceiveStream = field(init=False) - _send_stream: TextSendStream = field(init=False) - - def __post_init__(self, encoding: str, errors: str) -> None: - self._receive_stream = TextReceiveStream( - self.transport_stream, encoding=encoding, errors=errors - ) - self._send_stream = TextSendStream( - self.transport_stream, encoding=encoding, errors=errors - ) - - async def receive(self) -> str: - return await self._receive_stream.receive() - - async def send(self, item: str) -> None: - await self._send_stream.send(item) - - async def send_eof(self) -> None: - await self.transport_stream.send_eof() - - async def aclose(self) -> None: - await self._send_stream.aclose() - await self._receive_stream.aclose() - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return { - **self._send_stream.extra_attributes, - **self._receive_stream.extra_attributes, - } - - -class TextConnectable(ObjectStreamConnectable[str]): - def __init__(self, connectable: AnyByteStreamConnectable): - """ - :param connectable: the bytestream endpoint to wrap - - """ - self.connectable = connectable - - @override - async def connect(self) -> TextStream: - stream = await self.connectable.connect() - return TextStream(stream) diff --git a/notification-service/venv/Lib/site-packages/anyio/streams/tls.py b/notification-service/venv/Lib/site-packages/anyio/streams/tls.py deleted file mode 100644 index e2a7ca5..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/streams/tls.py +++ /dev/null @@ -1,421 +0,0 @@ -from __future__ import annotations - -__all__ = ( - "TLSAttribute", - "TLSConnectable", - "TLSListener", - "TLSStream", -) - -import logging -import re -import ssl -import sys -from collections.abc import Callable, Mapping -from dataclasses import dataclass -from functools import wraps -from ssl import SSLContext -from typing import Any, TypeAlias, TypeVar - -from .. import ( - BrokenResourceError, - EndOfStream, - aclose_forcefully, - get_cancelled_exc_class, - to_thread, -) -from .._core._typedattr import TypedAttributeSet, typed_attribute -from ..abc import ( - AnyByteStream, - AnyByteStreamConnectable, - ByteStream, - ByteStreamConnectable, - Listener, - TaskGroup, -) - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -if sys.version_info >= (3, 12): - from typing import override -else: - from typing_extensions import override - -T_Retval = TypeVar("T_Retval") -PosArgsT = TypeVarTuple("PosArgsT") -_PCTRTT: TypeAlias = tuple[tuple[str, str], ...] -_PCTRTTT: TypeAlias = tuple[_PCTRTT, ...] - - -class TLSAttribute(TypedAttributeSet): - """Contains Transport Layer Security related attributes.""" - - #: the selected ALPN protocol - alpn_protocol: str | None = typed_attribute() - #: the channel binding for type ``tls-unique`` - channel_binding_tls_unique: bytes = typed_attribute() - #: the selected cipher - cipher: tuple[str, str, int] = typed_attribute() - #: the peer certificate in dictionary form (see :meth:`ssl.SSLSocket.getpeercert` - # for more information) - peer_certificate: None | (dict[str, str | _PCTRTTT | _PCTRTT]) = typed_attribute() - #: the peer certificate in binary form - peer_certificate_binary: bytes | None = typed_attribute() - #: ``True`` if this is the server side of the connection - server_side: bool = typed_attribute() - #: ciphers shared by the client during the TLS handshake (``None`` if this is the - #: client side) - shared_ciphers: list[tuple[str, str, int]] | None = typed_attribute() - #: the :class:`~ssl.SSLObject` used for encryption - ssl_object: ssl.SSLObject = typed_attribute() - #: ``True`` if this stream does (and expects) a closing TLS handshake when the - #: stream is being closed - standard_compatible: bool = typed_attribute() - #: the TLS protocol version (e.g. ``TLSv1.2``) - tls_version: str = typed_attribute() - - -@dataclass(eq=False) -class TLSStream(ByteStream): - """ - A stream wrapper that encrypts all sent data and decrypts received data. - - This class has no public initializer; use :meth:`wrap` instead. - All extra attributes from :class:`~TLSAttribute` are supported. - - :var AnyByteStream transport_stream: the wrapped stream - - """ - - transport_stream: AnyByteStream - standard_compatible: bool - _ssl_object: ssl.SSLObject - _read_bio: ssl.MemoryBIO - _write_bio: ssl.MemoryBIO - - @classmethod - async def wrap( - cls, - transport_stream: AnyByteStream, - *, - server_side: bool | None = None, - hostname: str | None = None, - ssl_context: ssl.SSLContext | None = None, - standard_compatible: bool = True, - ) -> TLSStream: - """ - Wrap an existing stream with Transport Layer Security. - - This performs a TLS handshake with the peer. - - :param transport_stream: a bytes-transporting stream to wrap - :param server_side: ``True`` if this is the server side of the connection, - ``False`` if this is the client side (if omitted, will be set to ``False`` - if ``hostname`` has been provided, ``False`` otherwise). Used only to create - a default context when an explicit context has not been provided. - :param hostname: host name of the peer (if host name checking is desired) - :param ssl_context: the SSLContext object to use (if not provided, a secure - default will be created) - :param standard_compatible: if ``False``, skip the closing handshake when - closing the connection, and don't raise an exception if the peer does the - same - :raises ~ssl.SSLError: if the TLS handshake fails - - """ - if server_side is None: - server_side = not hostname - - if not ssl_context: - purpose = ( - ssl.Purpose.CLIENT_AUTH if server_side else ssl.Purpose.SERVER_AUTH - ) - ssl_context = ssl.create_default_context(purpose) - - # Re-enable detection of unexpected EOFs if it was disabled by Python - if hasattr(ssl, "OP_IGNORE_UNEXPECTED_EOF"): - ssl_context.options &= ~ssl.OP_IGNORE_UNEXPECTED_EOF - - bio_in = ssl.MemoryBIO() - bio_out = ssl.MemoryBIO() - - # External SSLContext implementations may do blocking I/O in wrap_bio(), - # but the standard library implementation won't - if type(ssl_context) is ssl.SSLContext: - ssl_object = ssl_context.wrap_bio( - bio_in, bio_out, server_side=server_side, server_hostname=hostname - ) - else: - ssl_object = await to_thread.run_sync( - ssl_context.wrap_bio, - bio_in, - bio_out, - server_side, - hostname, - None, - ) - - wrapper = cls( - transport_stream=transport_stream, - standard_compatible=standard_compatible, - _ssl_object=ssl_object, - _read_bio=bio_in, - _write_bio=bio_out, - ) - await wrapper._call_sslobject_method(ssl_object.do_handshake) - return wrapper - - async def _call_sslobject_method( - self, func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT] - ) -> T_Retval: - while True: - try: - result = func(*args) - except ssl.SSLWantReadError: - try: - # Flush any pending writes first - if self._write_bio.pending: - await self.transport_stream.send(self._write_bio.read()) - - data = await self.transport_stream.receive() - except EndOfStream: - self._read_bio.write_eof() - except OSError as exc: - self._read_bio.write_eof() - self._write_bio.write_eof() - raise BrokenResourceError from exc - else: - self._read_bio.write(data) - except ssl.SSLWantWriteError: - await self.transport_stream.send(self._write_bio.read()) - except ssl.SSLSyscallError as exc: - self._read_bio.write_eof() - self._write_bio.write_eof() - raise BrokenResourceError from exc - except ssl.SSLError as exc: - self._read_bio.write_eof() - self._write_bio.write_eof() - if isinstance(exc, ssl.SSLEOFError) or ( - exc.strerror and "UNEXPECTED_EOF_WHILE_READING" in exc.strerror - ): - if self.standard_compatible: - raise BrokenResourceError from exc - else: - raise EndOfStream from None - - raise - else: - # Flush any pending writes first - if self._write_bio.pending: - await self.transport_stream.send(self._write_bio.read()) - - return result - - async def unwrap(self) -> tuple[AnyByteStream, bytes]: - """ - Does the TLS closing handshake. - - :return: a tuple of (wrapped byte stream, bytes left in the read buffer) - - """ - await self._call_sslobject_method(self._ssl_object.unwrap) - self._read_bio.write_eof() - self._write_bio.write_eof() - return self.transport_stream, self._read_bio.read() - - async def aclose(self) -> None: - if self.standard_compatible: - try: - await self.unwrap() - except BaseException: - await aclose_forcefully(self.transport_stream) - raise - - await self.transport_stream.aclose() - - async def receive(self, max_bytes: int = 65536) -> bytes: - data = await self._call_sslobject_method(self._ssl_object.read, max_bytes) - if not data: - raise EndOfStream - - return data - - async def send(self, item: bytes) -> None: - await self._call_sslobject_method(self._ssl_object.write, item) - - async def send_eof(self) -> None: - tls_version = self.extra(TLSAttribute.tls_version) - match = re.match(r"TLSv(\d+)(?:\.(\d+))?", tls_version) - if match: - major, minor = int(match.group(1)), int(match.group(2) or 0) - if (major, minor) < (1, 3): - raise NotImplementedError( - f"send_eof() requires at least TLSv1.3; current " - f"session uses {tls_version}" - ) - - raise NotImplementedError( - "send_eof() has not yet been implemented for TLS streams" - ) - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return { - **self.transport_stream.extra_attributes, - TLSAttribute.alpn_protocol: self._ssl_object.selected_alpn_protocol, - TLSAttribute.channel_binding_tls_unique: ( - self._ssl_object.get_channel_binding - ), - TLSAttribute.cipher: self._ssl_object.cipher, - TLSAttribute.peer_certificate: lambda: self._ssl_object.getpeercert(False), - TLSAttribute.peer_certificate_binary: lambda: self._ssl_object.getpeercert( - True - ), - TLSAttribute.server_side: lambda: self._ssl_object.server_side, - TLSAttribute.shared_ciphers: lambda: ( - self._ssl_object.shared_ciphers() - if self._ssl_object.server_side - else None - ), - TLSAttribute.standard_compatible: lambda: self.standard_compatible, - TLSAttribute.ssl_object: lambda: self._ssl_object, - TLSAttribute.tls_version: self._ssl_object.version, - } - - -@dataclass(eq=False) -class TLSListener(Listener[TLSStream]): - """ - A convenience listener that wraps another listener and auto-negotiates a TLS session - on every accepted connection. - - If the TLS handshake times out or raises an exception, - :meth:`handle_handshake_error` is called to do whatever post-mortem processing is - deemed necessary. - - Supports only the :attr:`~TLSAttribute.standard_compatible` extra attribute. - - :param Listener listener: the listener to wrap - :param ssl_context: the SSL context object - :param standard_compatible: a flag passed through to :meth:`TLSStream.wrap` - :param handshake_timeout: time limit for the TLS handshake - (passed to :func:`~anyio.fail_after`) - """ - - listener: Listener[Any] - ssl_context: ssl.SSLContext - standard_compatible: bool = True - handshake_timeout: float = 30 - - @staticmethod - async def handle_handshake_error(exc: BaseException, stream: AnyByteStream) -> None: - """ - Handle an exception raised during the TLS handshake. - - This method does 3 things: - - #. Forcefully closes the original stream - #. Logs the exception (unless it was a cancellation exception) using the - ``anyio.streams.tls`` logger - #. Reraises the exception if it was a base exception or a cancellation exception - - :param exc: the exception - :param stream: the original stream - - """ - await aclose_forcefully(stream) - - # Log all except cancellation exceptions - if not isinstance(exc, get_cancelled_exc_class()): - # CPython (as of 3.11.5) returns incorrect `sys.exc_info()` here when using - # any asyncio implementation, so we explicitly pass the exception to log - # (https://github.com/python/cpython/issues/108668). Trio does not have this - # issue because it works around the CPython bug. - logging.getLogger(__name__).exception( - "Error during TLS handshake", exc_info=exc - ) - - # Only reraise base exceptions and cancellation exceptions - if not isinstance(exc, Exception) or isinstance(exc, get_cancelled_exc_class()): - raise - - async def serve( - self, - handler: Callable[[TLSStream], Any], - task_group: TaskGroup | None = None, - ) -> None: - @wraps(handler) - async def handler_wrapper(stream: AnyByteStream) -> None: - from .. import fail_after - - try: - with fail_after(self.handshake_timeout): - wrapped_stream = await TLSStream.wrap( - stream, - ssl_context=self.ssl_context, - standard_compatible=self.standard_compatible, - ) - except BaseException as exc: - await self.handle_handshake_error(exc, stream) - else: - await handler(wrapped_stream) - - await self.listener.serve(handler_wrapper, task_group) - - async def aclose(self) -> None: - await self.listener.aclose() - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return { - TLSAttribute.standard_compatible: lambda: self.standard_compatible, - } - - -class TLSConnectable(ByteStreamConnectable): - """ - Wraps another connectable and does TLS negotiation after a successful connection. - - :param connectable: the connectable to wrap - :param hostname: host name of the server (if host name checking is desired) - :param ssl_context: the SSLContext object to use (if not provided, a secure default - will be created) - :param standard_compatible: if ``False``, skip the closing handshake when closing - the connection, and don't raise an exception if the server does the same - """ - - def __init__( - self, - connectable: AnyByteStreamConnectable, - *, - hostname: str | None = None, - ssl_context: ssl.SSLContext | None = None, - standard_compatible: bool = True, - ) -> None: - self.connectable = connectable - self.ssl_context: SSLContext = ssl_context or ssl.create_default_context( - ssl.Purpose.SERVER_AUTH - ) - if not isinstance(self.ssl_context, ssl.SSLContext): - raise TypeError( - "ssl_context must be an instance of ssl.SSLContext, not " - f"{type(self.ssl_context).__name__}" - ) - self.hostname = hostname - self.standard_compatible = standard_compatible - - @override - async def connect(self) -> TLSStream: - stream = await self.connectable.connect() - try: - return await TLSStream.wrap( - stream, - hostname=self.hostname, - ssl_context=self.ssl_context, - standard_compatible=self.standard_compatible, - ) - except BaseException: - await aclose_forcefully(stream) - raise diff --git a/notification-service/venv/Lib/site-packages/anyio/to_interpreter.py b/notification-service/venv/Lib/site-packages/anyio/to_interpreter.py deleted file mode 100644 index 694dbe7..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/to_interpreter.py +++ /dev/null @@ -1,246 +0,0 @@ -from __future__ import annotations - -__all__ = ( - "run_sync", - "current_default_interpreter_limiter", -) - -import atexit -import os -import sys -from collections import deque -from collections.abc import Callable -from typing import Any, Final, TypeVar - -from . import current_time, to_thread -from ._core._exceptions import BrokenWorkerInterpreter -from ._core._synchronization import CapacityLimiter -from .lowlevel import RunVar - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -if sys.version_info >= (3, 14): - from concurrent.interpreters import ExecutionFailed, create - - def _interp_call( - func: Callable[..., Any], args: tuple[Any, ...] - ) -> tuple[Any, bool]: - try: - retval = func(*args) - except BaseException as exc: - return exc, True - else: - return retval, False - - class _Worker: - last_used: float = 0 - - def __init__(self) -> None: - self._interpreter = create() - - def destroy(self) -> None: - self._interpreter.close() - - def call( - self, - func: Callable[..., T_Retval], - args: tuple[Any, ...], - ) -> T_Retval: - try: - res, is_exception = self._interpreter.call(_interp_call, func, args) - except ExecutionFailed as exc: - raise BrokenWorkerInterpreter(exc.excinfo) from exc - - if is_exception: - raise res - - return res -elif sys.version_info >= (3, 13): - import _interpqueues - import _interpreters - - UNBOUND: Final = 2 # I have no clue how this works, but it was used in the stdlib - FMT_UNPICKLED: Final = 0 - FMT_PICKLED: Final = 1 - QUEUE_PICKLE_ARGS: Final = (FMT_PICKLED, UNBOUND) - QUEUE_UNPICKLE_ARGS: Final = (FMT_UNPICKLED, UNBOUND) - - _run_func = compile( - """ -import _interpqueues -from _interpreters import NotShareableError -from pickle import loads, dumps, HIGHEST_PROTOCOL - -QUEUE_PICKLE_ARGS = (1, 2) -QUEUE_UNPICKLE_ARGS = (0, 2) - -item = _interpqueues.get(queue_id)[0] -try: - func, args = loads(item) - retval = func(*args) -except BaseException as exc: - is_exception = True - retval = exc -else: - is_exception = False - -try: - _interpqueues.put(queue_id, (retval, is_exception), *QUEUE_UNPICKLE_ARGS) -except NotShareableError: - retval = dumps(retval, HIGHEST_PROTOCOL) - _interpqueues.put(queue_id, (retval, is_exception), *QUEUE_PICKLE_ARGS) - """, - "", - "exec", - ) - - class _Worker: - last_used: float = 0 - - def __init__(self) -> None: - self._interpreter_id = _interpreters.create() - self._queue_id = _interpqueues.create(1, *QUEUE_UNPICKLE_ARGS) - _interpreters.set___main___attrs( - self._interpreter_id, {"queue_id": self._queue_id} - ) - - def destroy(self) -> None: - _interpqueues.destroy(self._queue_id) - _interpreters.destroy(self._interpreter_id) - - def call( - self, - func: Callable[..., T_Retval], - args: tuple[Any, ...], - ) -> T_Retval: - import pickle - - item = pickle.dumps((func, args), pickle.HIGHEST_PROTOCOL) - _interpqueues.put(self._queue_id, item, *QUEUE_PICKLE_ARGS) - exc_info = _interpreters.exec(self._interpreter_id, _run_func) - if exc_info: - raise BrokenWorkerInterpreter(exc_info) - - res = _interpqueues.get(self._queue_id) - (res, is_exception), fmt = res[:2] - if fmt == FMT_PICKLED: - res = pickle.loads(res) - - if is_exception: - raise res - - return res -else: - - class _Worker: - last_used: float = 0 - - def __init__(self) -> None: - raise RuntimeError("subinterpreters require at least Python 3.13") - - def call( - self, - func: Callable[..., T_Retval], - args: tuple[Any, ...], - ) -> T_Retval: - raise NotImplementedError - - def destroy(self) -> None: - pass - - -DEFAULT_CPU_COUNT: Final = 8 # this is just an arbitrarily selected value -MAX_WORKER_IDLE_TIME = ( - 30 # seconds a subinterpreter can be idle before becoming eligible for pruning -) - -T_Retval = TypeVar("T_Retval") -PosArgsT = TypeVarTuple("PosArgsT") - -_idle_workers = RunVar[deque[_Worker]]("_available_workers") -_default_interpreter_limiter = RunVar[CapacityLimiter]("_default_interpreter_limiter") - - -def _stop_workers(workers: deque[_Worker]) -> None: - for worker in workers: - worker.destroy() - - workers.clear() - - -async def run_sync( - func: Callable[[Unpack[PosArgsT]], T_Retval], - *args: Unpack[PosArgsT], - limiter: CapacityLimiter | None = None, -) -> T_Retval: - """ - Call the given function with the given arguments in a subinterpreter. - - .. warning:: On Python 3.13, the :mod:`concurrent.interpreters` module was not yet - available, so the code path for that Python version relies on an undocumented, - private API. As such, it is recommended to not rely on this function for anything - mission-critical on Python 3.13. - - :param func: a callable - :param args: the positional arguments for the callable - :param limiter: capacity limiter to use to limit the total number of subinterpreters - running (if omitted, the default limiter is used) - :return: the result of the call - :raises BrokenWorkerInterpreter: if there's an internal error in a subinterpreter - - """ - if limiter is None: - limiter = current_default_interpreter_limiter() - - try: - idle_workers = _idle_workers.get() - except LookupError: - idle_workers = deque() - _idle_workers.set(idle_workers) - atexit.register(_stop_workers, idle_workers) - - async with limiter: - try: - worker = idle_workers.pop() - except IndexError: - worker = _Worker() - - try: - return await to_thread.run_sync( - worker.call, - func, - args, - limiter=limiter, - ) - finally: - # Prune workers that have been idle for too long - now = current_time() - while idle_workers: - if now - idle_workers[0].last_used <= MAX_WORKER_IDLE_TIME: - break - - await to_thread.run_sync(idle_workers.popleft().destroy, limiter=limiter) - - worker.last_used = current_time() - idle_workers.append(worker) - - -def current_default_interpreter_limiter() -> CapacityLimiter: - """ - Return the capacity limiter used by default to limit the number of concurrently - running subinterpreters. - - Defaults to the number of CPU cores. - - :return: a capacity limiter object - - """ - try: - return _default_interpreter_limiter.get() - except LookupError: - limiter = CapacityLimiter(os.cpu_count() or DEFAULT_CPU_COUNT) - _default_interpreter_limiter.set(limiter) - return limiter diff --git a/notification-service/venv/Lib/site-packages/anyio/to_process.py b/notification-service/venv/Lib/site-packages/anyio/to_process.py deleted file mode 100644 index b289234..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/to_process.py +++ /dev/null @@ -1,266 +0,0 @@ -from __future__ import annotations - -__all__ = ( - "current_default_process_limiter", - "process_worker", - "run_sync", -) - -import os -import pickle -import subprocess -import sys -from collections import deque -from collections.abc import Callable -from importlib.util import module_from_spec, spec_from_file_location -from typing import TypeVar, cast - -from ._core._eventloop import current_time, get_async_backend, get_cancelled_exc_class -from ._core._exceptions import BrokenWorkerProcess -from ._core._subprocesses import open_process -from ._core._synchronization import CapacityLimiter -from ._core._tasks import CancelScope, fail_after -from .abc import ByteReceiveStream, ByteSendStream, Process -from .lowlevel import RunVar, checkpoint_if_cancelled -from .streams.buffered import BufferedByteReceiveStream - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -WORKER_MAX_IDLE_TIME = 300 # 5 minutes - -T_Retval = TypeVar("T_Retval") -PosArgsT = TypeVarTuple("PosArgsT") - -_process_pool_workers: RunVar[set[Process]] = RunVar("_process_pool_workers") -_process_pool_idle_workers: RunVar[deque[tuple[Process, float]]] = RunVar( - "_process_pool_idle_workers" -) -_default_process_limiter: RunVar[CapacityLimiter] = RunVar("_default_process_limiter") - - -async def run_sync( # type: ignore[return] - func: Callable[[Unpack[PosArgsT]], T_Retval], - *args: Unpack[PosArgsT], - cancellable: bool = False, - limiter: CapacityLimiter | None = None, -) -> T_Retval: - """ - Call the given function with the given arguments in a worker process. - - If the ``cancellable`` option is enabled and the task waiting for its completion is - cancelled, the worker process running it will be abruptly terminated using SIGKILL - (or ``terminateProcess()`` on Windows). - - :param func: a callable - :param args: positional arguments for the callable - :param cancellable: ``True`` to allow cancellation of the operation while it's - running - :param limiter: capacity limiter to use to limit the total amount of processes - running (if omitted, the default limiter is used) - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - :return: an awaitable that yields the return value of the function. - - """ - - async def send_raw_command(pickled_cmd: bytes) -> object: - try: - await stdin.send(pickled_cmd) - response = await buffered.receive_until(b"\n", 50) - status, length = response.split(b" ") - if status not in (b"RETURN", b"EXCEPTION"): - raise RuntimeError( - f"Worker process returned unexpected response: {response!r}" - ) - - pickled_response = await buffered.receive_exactly(int(length)) - except BaseException as exc: - workers.discard(process) - try: - process.kill() - with CancelScope(shield=True): - await process.aclose() - except ProcessLookupError: - pass - - if isinstance(exc, get_cancelled_exc_class()): - raise - else: - raise BrokenWorkerProcess from exc - - retval = pickle.loads(pickled_response) - if status == b"EXCEPTION": - assert isinstance(retval, BaseException) - raise retval - else: - return retval - - # First pickle the request before trying to reserve a worker process - await checkpoint_if_cancelled() - request = pickle.dumps(("run", func, args), protocol=pickle.HIGHEST_PROTOCOL) - - # If this is the first run in this event loop thread, set up the necessary variables - try: - workers = _process_pool_workers.get() - idle_workers = _process_pool_idle_workers.get() - except LookupError: - workers = set() - idle_workers = deque() - _process_pool_workers.set(workers) - _process_pool_idle_workers.set(idle_workers) - get_async_backend().setup_process_pool_exit_at_shutdown(workers) - - async with limiter or current_default_process_limiter(): - # Pop processes from the pool (starting from the most recently used) until we - # find one that hasn't exited yet - process: Process - while idle_workers: - process, idle_since = idle_workers.pop() - if process.returncode is None: - stdin = cast(ByteSendStream, process.stdin) - buffered = BufferedByteReceiveStream( - cast(ByteReceiveStream, process.stdout) - ) - - # Prune any other workers that have been idle for WORKER_MAX_IDLE_TIME - # seconds or longer - now = current_time() - killed_processes: list[Process] = [] - while idle_workers: - if now - idle_workers[0][1] < WORKER_MAX_IDLE_TIME: - break - - process_to_kill, idle_since = idle_workers.popleft() - process_to_kill.kill() - workers.remove(process_to_kill) - killed_processes.append(process_to_kill) - - with CancelScope(shield=True): - for killed_process in killed_processes: - await killed_process.aclose() - - break - - workers.remove(process) - else: - command = [sys.executable, "-u", "-m", __name__] - process = await open_process( - command, stdin=subprocess.PIPE, stdout=subprocess.PIPE - ) - try: - stdin = cast(ByteSendStream, process.stdin) - buffered = BufferedByteReceiveStream( - cast(ByteReceiveStream, process.stdout) - ) - with fail_after(20): - message = await buffered.receive(6) - - if message != b"READY\n": - raise BrokenWorkerProcess( - f"Worker process returned unexpected response: {message!r}" - ) - - main_module_path = getattr(sys.modules["__main__"], "__file__", None) - pickled = pickle.dumps( - ("init", sys.path, main_module_path), - protocol=pickle.HIGHEST_PROTOCOL, - ) - await send_raw_command(pickled) - except (BrokenWorkerProcess, get_cancelled_exc_class()): - raise - except BaseException as exc: - process.kill() - raise BrokenWorkerProcess( - "Error during worker process initialization" - ) from exc - - workers.add(process) - - with CancelScope(shield=not cancellable): - try: - return cast(T_Retval, await send_raw_command(request)) - finally: - if process in workers: - idle_workers.append((process, current_time())) - - -def current_default_process_limiter() -> CapacityLimiter: - """ - Return the capacity limiter that is used by default to limit the number of worker - processes. - - :return: a capacity limiter object - - """ - try: - return _default_process_limiter.get() - except LookupError: - limiter = CapacityLimiter(os.cpu_count() or 2) - _default_process_limiter.set(limiter) - return limiter - - -def process_worker() -> None: - # Redirect standard streams to os.devnull so that user code won't interfere with the - # parent-worker communication - stdin = sys.stdin - stdout = sys.stdout - sys.stdin = open(os.devnull) - sys.stdout = open(os.devnull, "w") - - stdout.buffer.write(b"READY\n") - while True: - retval = exception = None - try: - command, *args = pickle.load(stdin.buffer) - except EOFError: - return - except BaseException as exc: - exception = exc - else: - if command == "run": - func, args = args - try: - retval = func(*args) - except BaseException as exc: - exception = exc - elif command == "init": - main_module_path: str | None - sys.path, main_module_path = args - del sys.modules["__main__"] - if main_module_path and os.path.isfile(main_module_path): - # Load the parent's main module but as __mp_main__ instead of - # __main__ (like multiprocessing does) to avoid infinite recursion - try: - spec = spec_from_file_location("__mp_main__", main_module_path) - if spec and spec.loader: - main = module_from_spec(spec) - spec.loader.exec_module(main) - sys.modules["__main__"] = main - except BaseException as exc: - exception = exc - try: - if exception is not None: - status = b"EXCEPTION" - pickled = pickle.dumps(exception, pickle.HIGHEST_PROTOCOL) - else: - status = b"RETURN" - pickled = pickle.dumps(retval, pickle.HIGHEST_PROTOCOL) - except BaseException as exc: - exception = exc - status = b"EXCEPTION" - pickled = pickle.dumps(exc, pickle.HIGHEST_PROTOCOL) - - stdout.buffer.write(b"%s %d\n" % (status, len(pickled))) - stdout.buffer.write(pickled) - - # Respect SIGTERM - if isinstance(exception, SystemExit): - raise exception - - -if __name__ == "__main__": - process_worker() diff --git a/notification-service/venv/Lib/site-packages/anyio/to_thread.py b/notification-service/venv/Lib/site-packages/anyio/to_thread.py deleted file mode 100644 index 83c79d1..0000000 --- a/notification-service/venv/Lib/site-packages/anyio/to_thread.py +++ /dev/null @@ -1,78 +0,0 @@ -from __future__ import annotations - -__all__ = ( - "run_sync", - "current_default_thread_limiter", -) - -import sys -from collections.abc import Callable -from typing import TypeVar -from warnings import warn - -from ._core._eventloop import get_async_backend -from .abc import CapacityLimiter - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -T_Retval = TypeVar("T_Retval") -PosArgsT = TypeVarTuple("PosArgsT") - - -async def run_sync( - func: Callable[[Unpack[PosArgsT]], T_Retval], - *args: Unpack[PosArgsT], - abandon_on_cancel: bool = False, - cancellable: bool | None = None, - limiter: CapacityLimiter | None = None, -) -> T_Retval: - """ - Call the given function with the given arguments in a worker thread. - - If the ``abandon_on_cancel`` option is enabled and the task waiting for its - completion is cancelled, the thread will still run its course but its - return value (or any raised exception) will be ignored. - - :param func: a callable - :param args: positional arguments for the callable - :param abandon_on_cancel: ``True`` to abandon the thread (leaving it to run - unchecked on own) if the host task is cancelled, ``False`` to ignore - cancellations in the host task until the operation has completed in the worker - thread - :param cancellable: deprecated alias of ``abandon_on_cancel``; will override - ``abandon_on_cancel`` if both parameters are passed - :param limiter: capacity limiter to use to limit the total amount of threads running - (if omitted, the default limiter is used) - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - :return: an awaitable that yields the return value of the function. - - """ - if cancellable is not None: - abandon_on_cancel = cancellable - warn( - "The `cancellable=` keyword argument to `anyio.to_thread.run_sync` is " - "deprecated since AnyIO 4.1.0; use `abandon_on_cancel=` instead", - DeprecationWarning, - stacklevel=2, - ) - - return await get_async_backend().run_sync_in_worker_thread( - func, args, abandon_on_cancel=abandon_on_cancel, limiter=limiter - ) - - -def current_default_thread_limiter() -> CapacityLimiter: - """ - Return the capacity limiter that is used by default to limit the number of - concurrent threads. - - :return: a capacity limiter object - :raises NoEventLoopError: if no supported asynchronous event loop is running in the - current thread - - """ - return get_async_backend().current_default_thread_limiter() diff --git a/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/INSTALLER b/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/METADATA b/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/METADATA deleted file mode 100644 index 9ae7298..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/METADATA +++ /dev/null @@ -1,91 +0,0 @@ -Metadata-Version: 2.4 -Name: CacheControl -Version: 0.14.4 -Summary: httplib2 caching for requests -Keywords: requests,http,caching,web -Author: Eric Larson, Frost Ming, William Woodruff -Author-email: Eric Larson , Frost Ming , William Woodruff -License-Expression: Apache-2.0 -License-File: LICENSE.txt -Classifier: Development Status :: 4 - Beta -Classifier: Environment :: Web Environment -Classifier: Operating System :: OS Independent -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: Topic :: Internet :: WWW/HTTP -Requires-Dist: requests>=2.16.0 -Requires-Dist: msgpack>=0.5.2,<2.0.0 -Requires-Dist: cachecontrol[filecache,redis] ; extra == 'dev' -Requires-Dist: cherrypy ; extra == 'dev' -Requires-Dist: cheroot>=11.1.2 ; extra == 'dev' -Requires-Dist: codespell ; extra == 'dev' -Requires-Dist: furo ; extra == 'dev' -Requires-Dist: mypy ; extra == 'dev' -Requires-Dist: pytest ; extra == 'dev' -Requires-Dist: pytest-cov ; extra == 'dev' -Requires-Dist: ruff ; extra == 'dev' -Requires-Dist: sphinx ; extra == 'dev' -Requires-Dist: sphinx-copybutton ; extra == 'dev' -Requires-Dist: types-redis ; extra == 'dev' -Requires-Dist: types-requests ; extra == 'dev' -Requires-Dist: filelock>=3.8.0 ; extra == 'filecache' -Requires-Dist: redis>=2.10.5 ; extra == 'redis' -Requires-Python: >=3.10 -Project-URL: Homepage, https://pypi.org/project/CacheControl/ -Project-URL: Issues, https://github.com/psf/cachecontrol/issues -Project-URL: Source, https://github.com/psf/cachecontrol -Provides-Extra: dev -Provides-Extra: filecache -Provides-Extra: redis -Description-Content-Type: text/x-rst - -.. - SPDX-FileCopyrightText: SPDX-FileCopyrightText: 2015 Eric Larson - - SPDX-License-Identifier: Apache-2.0 - -============== - CacheControl -============== - -.. image:: https://img.shields.io/pypi/v/cachecontrol.svg - :target: https://pypi.python.org/pypi/cachecontrol - :alt: Latest Version - -.. image:: https://github.com/psf/cachecontrol/actions/workflows/tests.yml/badge.svg - :target: https://github.com/psf/cachecontrol/actions/workflows/tests.yml - -CacheControl is a port of the caching algorithms in httplib2_ for use with -requests_ session object. - -It was written because httplib2's better support for caching is often -mitigated by its lack of thread safety. The same is true of requests in -terms of caching. - - -Quickstart -========== - -.. code-block:: python - - import requests - - from cachecontrol import CacheControl - - - sess = requests.session() - cached_sess = CacheControl(sess) - - response = cached_sess.get('https://google.com') - -If the URL contains any caching based headers, it will cache the -result in a simple dictionary. - -For more info, check out the docs_ - -.. _docs: http://cachecontrol.readthedocs.org/en/latest/ -.. _httplib2: https://github.com/httplib2/httplib2 -.. _requests: http://docs.python-requests.org/ diff --git a/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/RECORD b/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/RECORD deleted file mode 100644 index 76357e6..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/RECORD +++ /dev/null @@ -1,32 +0,0 @@ -../../Scripts/doesitcache.exe,sha256=7vfgCyFkqL85nZGHti7KEOjwp9dbiDUA6z9s3wpp5Ug,108495 -cachecontrol-0.14.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -cachecontrol-0.14.4.dist-info/METADATA,sha256=o7eXpgH_41Bc5LDGNTY8zyaplZ8kkOkC-EGktZlrXMQ,3074 -cachecontrol-0.14.4.dist-info/RECORD,, -cachecontrol-0.14.4.dist-info/WHEEL,sha256=w4ZtLaDgMAZW2MMZZwtH8zENekoQYBCeullI-zsXJQk,78 -cachecontrol-0.14.4.dist-info/entry_points.txt,sha256=HjCekaRCv8kfNqP5WehMR29IWxIA5VrhoOeKrCykCLc,56 -cachecontrol-0.14.4.dist-info/licenses/LICENSE.txt,sha256=hu7uh74qQ_P_H1ZJb0UfaSQ5JvAl_tuwM2ZsMExMFhs,558 -cachecontrol/__init__.py,sha256=aMPfN_9huuMwdL8qh269agzp2ugriVc2okgB4PGHcS0,702 -cachecontrol/__pycache__/__init__.cpython-312.pyc,, -cachecontrol/__pycache__/_cmd.cpython-312.pyc,, -cachecontrol/__pycache__/adapter.cpython-312.pyc,, -cachecontrol/__pycache__/cache.cpython-312.pyc,, -cachecontrol/__pycache__/controller.cpython-312.pyc,, -cachecontrol/__pycache__/filewrapper.cpython-312.pyc,, -cachecontrol/__pycache__/heuristics.cpython-312.pyc,, -cachecontrol/__pycache__/serialize.cpython-312.pyc,, -cachecontrol/__pycache__/wrapper.cpython-312.pyc,, -cachecontrol/_cmd.py,sha256=4l2UbK9N85Vr_KTkF4LjvSlsr-TZnOXTfT2NODlIMtc,1672 -cachecontrol/adapter.py,sha256=VBORpVV3mQCLgGa5Mk531KtjoaYTZs4HBd222GfdL4o,6478 -cachecontrol/cache.py,sha256=OXwv7Fn2AwnKNiahJHnjtvaKLndvVLv_-zO-ltlV9qI,1953 -cachecontrol/caches/__init__.py,sha256=3-BaJBXjdt-4iFbv-799XjzRBsd6zF9wOEqOdDuAAro,279 -cachecontrol/caches/__pycache__/__init__.cpython-312.pyc,, -cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc,, -cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc,, -cachecontrol/caches/file_cache.py,sha256=0Df9CcKBaGjKF4dhkFGncLx-YHae0BOPd0jo67mG1rQ,4093 -cachecontrol/caches/redis_cache.py,sha256=94Qw4INGwjHcCDwMnOe0gbbcP2fttrlui-e1-Yutclw,1374 -cachecontrol/controller.py,sha256=qZF9BOy_aDElMAXPejH5ohixTgkxYkXWPoB0Ocer_Vk,19030 -cachecontrol/filewrapper.py,sha256=DhxC_rSk-beKdbsYhfvBUDovQHX9r3gHH_jP9-q_mKk,4354 -cachecontrol/heuristics.py,sha256=ccecGyeEycWDY_Kfnx41ebYl7eSdDCLM5X6Sx0f5fZE,4869 -cachecontrol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -cachecontrol/serialize.py,sha256=dP5k_UKYUAano6TKG9qlbKHbFMonz0AV_lYR3IFCGMg,5110 -cachecontrol/wrapper.py,sha256=KyaQ4Bq1RqsX-zA4pXH62nmcU511ECIGn5gCvmNIj20,1328 diff --git a/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/WHEEL b/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/WHEEL deleted file mode 100644 index fedee5b..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: uv 0.9.9 -Root-Is-Purelib: true -Tag: py3-none-any \ No newline at end of file diff --git a/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/entry_points.txt b/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/entry_points.txt deleted file mode 100644 index 7c31574..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[console_scripts] -doesitcache = cachecontrol._cmd:main - diff --git a/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/licenses/LICENSE.txt b/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/licenses/LICENSE.txt deleted file mode 100644 index d8b3b56..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol-0.14.4.dist-info/licenses/LICENSE.txt +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2012-2021 Eric Larson - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/__init__.py b/notification-service/venv/Lib/site-packages/cachecontrol/__init__.py deleted file mode 100644 index 4d3837a..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol/__init__.py +++ /dev/null @@ -1,31 +0,0 @@ -# SPDX-FileCopyrightText: 2015 Eric Larson -# -# SPDX-License-Identifier: Apache-2.0 - -"""CacheControl import Interface. - -Make it easy to import from cachecontrol without long namespaces. -""" - -import importlib.metadata - -from cachecontrol.adapter import CacheControlAdapter -from cachecontrol.controller import CacheController -from cachecontrol.wrapper import CacheControl - -__author__ = "Eric Larson" -__email__ = "eric@ionrock.org" -__version__ = importlib.metadata.version("cachecontrol") - -__all__ = [ - "__author__", - "__email__", - "__version__", - "CacheControlAdapter", - "CacheController", - "CacheControl", -] - -import logging - -logging.getLogger(__name__).addHandler(logging.NullHandler()) diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index a21a80b..0000000 Binary files a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/_cmd.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/_cmd.cpython-312.pyc deleted file mode 100644 index df24c6f..0000000 Binary files a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/_cmd.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/adapter.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/adapter.cpython-312.pyc deleted file mode 100644 index 3c57b3e..0000000 Binary files a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/adapter.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/cache.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/cache.cpython-312.pyc deleted file mode 100644 index b7f2632..0000000 Binary files a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/cache.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/controller.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/controller.cpython-312.pyc deleted file mode 100644 index 7d2b17d..0000000 Binary files a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/controller.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/filewrapper.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/filewrapper.cpython-312.pyc deleted file mode 100644 index 419e9ee..0000000 Binary files a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/filewrapper.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/heuristics.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/heuristics.cpython-312.pyc deleted file mode 100644 index 16671be..0000000 Binary files a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/heuristics.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/serialize.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/serialize.cpython-312.pyc deleted file mode 100644 index 79120b3..0000000 Binary files a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/serialize.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/wrapper.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/wrapper.cpython-312.pyc deleted file mode 100644 index 8804e66..0000000 Binary files a/notification-service/venv/Lib/site-packages/cachecontrol/__pycache__/wrapper.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/_cmd.py b/notification-service/venv/Lib/site-packages/cachecontrol/_cmd.py deleted file mode 100644 index 684a4a8..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol/_cmd.py +++ /dev/null @@ -1,70 +0,0 @@ -# SPDX-FileCopyrightText: 2015 Eric Larson -# -# SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations - -import logging -from argparse import ArgumentParser -from typing import TYPE_CHECKING - -import requests - -from cachecontrol.adapter import CacheControlAdapter -from cachecontrol.cache import DictCache -from cachecontrol.controller import logger - -if TYPE_CHECKING: - from argparse import Namespace - - from cachecontrol.controller import CacheController - - -def setup_logging() -> None: - logger.setLevel(logging.DEBUG) - handler = logging.StreamHandler() - logger.addHandler(handler) - - -def get_session() -> requests.Session: - adapter = CacheControlAdapter( - DictCache(), cache_etags=True, serializer=None, heuristic=None - ) - sess = requests.Session() - sess.mount("http://", adapter) - sess.mount("https://", adapter) - - sess.cache_controller = adapter.controller # type: ignore[attr-defined] - return sess - - -def get_args() -> Namespace: - parser = ArgumentParser() - parser.add_argument("url", help="The URL to try and cache") - return parser.parse_args() - - -def main() -> None: - args = get_args() - sess = get_session() - - # Make a request to get a response - resp = sess.get(args.url) - - # Turn on logging - setup_logging() - - # try setting the cache - cache_controller: CacheController = ( - sess.cache_controller # type: ignore[attr-defined] - ) - cache_controller.cache_response(resp.request, resp.raw) - - # Now try to get it - if cache_controller.cached_request(resp.request): - print("Cached!") - else: - print("Not cached :(") - - -if __name__ == "__main__": - main() diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/adapter.py b/notification-service/venv/Lib/site-packages/cachecontrol/adapter.py deleted file mode 100644 index 4f4c185..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol/adapter.py +++ /dev/null @@ -1,167 +0,0 @@ -# SPDX-FileCopyrightText: 2015 Eric Larson -# -# SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations - -import functools -import weakref -import zlib -from typing import TYPE_CHECKING, Any, Collection, Mapping - -from requests.adapters import HTTPAdapter - -from cachecontrol.cache import DictCache -from cachecontrol.controller import PERMANENT_REDIRECT_STATUSES, CacheController -from cachecontrol.filewrapper import CallbackFileWrapper - -if TYPE_CHECKING: - from requests import PreparedRequest, Response - from urllib3 import HTTPResponse - - from cachecontrol.cache import BaseCache - from cachecontrol.heuristics import BaseHeuristic - from cachecontrol.serialize import Serializer - - -class CacheControlAdapter(HTTPAdapter): - invalidating_methods = {"PUT", "PATCH", "DELETE"} - - def __init__( - self, - cache: BaseCache | None = None, - cache_etags: bool = True, - controller_class: type[CacheController] | None = None, - serializer: Serializer | None = None, - heuristic: BaseHeuristic | None = None, - cacheable_methods: Collection[str] | None = None, - *args: Any, - **kw: Any, - ) -> None: - super().__init__(*args, **kw) - self.cache = DictCache() if cache is None else cache - self.heuristic = heuristic - self.cacheable_methods = cacheable_methods or ("GET",) - - controller_factory = controller_class or CacheController - self.controller = controller_factory( - self.cache, cache_etags=cache_etags, serializer=serializer - ) - - def send( - self, - request: PreparedRequest, - stream: bool = False, - timeout: None | float | tuple[float, float] | tuple[float, None] = None, - verify: bool | str = True, - cert: (None | bytes | str | tuple[bytes | str, bytes | str]) = None, - proxies: Mapping[str, str] | None = None, - cacheable_methods: Collection[str] | None = None, - ) -> Response: - """ - Send a request. Use the request information to see if it - exists in the cache and cache the response if we need to and can. - """ - cacheable = cacheable_methods or self.cacheable_methods - if request.method in cacheable: - try: - cached_response = self.controller.cached_request(request) - except zlib.error: - cached_response = None - if cached_response: - return self.build_response(request, cached_response, from_cache=True) - - # check for etags and add headers if appropriate - request.headers.update(self.controller.conditional_headers(request)) - - resp = super().send(request, stream, timeout, verify, cert, proxies) - - return resp - - def build_response( # type: ignore[override] - self, - request: PreparedRequest, - response: HTTPResponse, - from_cache: bool = False, - cacheable_methods: Collection[str] | None = None, - ) -> Response: - """ - Build a response by making a request or using the cache. - - This will end up calling send and returning a potentially - cached response - """ - cacheable = cacheable_methods or self.cacheable_methods - if not from_cache and request.method in cacheable: - # Check for any heuristics that might update headers - # before trying to cache. - if self.heuristic: - response = self.heuristic.apply(response) - - # apply any expiration heuristics - if response.status == 304: - # We must have sent an ETag request. This could mean - # that we've been expired already or that we simply - # have an etag. In either case, we want to try and - # update the cache if that is the case. - cached_response = self.controller.update_cached_response( - request, response - ) - - if cached_response is not response: - from_cache = True - - # We are done with the server response, read a - # possible response body (compliant servers will - # not return one, but we cannot be 100% sure) and - # release the connection back to the pool. - response.read(decode_content=False) - response.release_conn() - - response = cached_response - - # We always cache the 301 responses - elif int(response.status) in PERMANENT_REDIRECT_STATUSES: - self.controller.cache_response(request, response) - else: - # Wrap the response file with a wrapper that will cache the - # response when the stream has been consumed. - response._fp = CallbackFileWrapper( # type: ignore[assignment] - response._fp, # type: ignore[arg-type] - functools.partial( - self.controller.cache_response, request, weakref.ref(response) - ), - ) - if response.chunked: - super_update_chunk_length = response.__class__._update_chunk_length - - def _update_chunk_length( - weak_self: weakref.ReferenceType[HTTPResponse], - ) -> None: - self = weak_self() - if self is None: - return - - super_update_chunk_length(self) - if self.chunk_left == 0: - self._fp._close() # type: ignore[union-attr] - - response._update_chunk_length = functools.partial( # type: ignore[method-assign] - _update_chunk_length, weakref.ref(response) - ) - - resp: Response = super().build_response(request, response) - - # See if we should invalidate the cache. - if request.method in self.invalidating_methods and resp.ok: - assert request.url is not None - cache_url = self.controller.cache_url(request.url) - self.cache.delete(cache_url) - - # Give the request a from_cache attr to let people use it - resp.from_cache = from_cache # type: ignore[attr-defined] - - return resp - - def close(self) -> None: - self.cache.close() - super().close() # type: ignore[no-untyped-call] diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/cache.py b/notification-service/venv/Lib/site-packages/cachecontrol/cache.py deleted file mode 100644 index 91598e9..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol/cache.py +++ /dev/null @@ -1,75 +0,0 @@ -# SPDX-FileCopyrightText: 2015 Eric Larson -# -# SPDX-License-Identifier: Apache-2.0 - -""" -The cache object API for implementing caches. The default is a thread -safe in-memory dictionary. -""" - -from __future__ import annotations - -from threading import Lock -from typing import IO, TYPE_CHECKING, MutableMapping - -if TYPE_CHECKING: - from datetime import datetime - - -class BaseCache: - def get(self, key: str) -> bytes | None: - raise NotImplementedError() - - def set( - self, key: str, value: bytes, expires: int | datetime | None = None - ) -> None: - raise NotImplementedError() - - def delete(self, key: str) -> None: - raise NotImplementedError() - - def close(self) -> None: - pass - - -class DictCache(BaseCache): - def __init__(self, init_dict: MutableMapping[str, bytes] | None = None) -> None: - self.lock = Lock() - self.data = init_dict or {} - - def get(self, key: str) -> bytes | None: - return self.data.get(key, None) - - def set( - self, key: str, value: bytes, expires: int | datetime | None = None - ) -> None: - with self.lock: - self.data.update({key: value}) - - def delete(self, key: str) -> None: - with self.lock: - if key in self.data: - self.data.pop(key) - - -class SeparateBodyBaseCache(BaseCache): - """ - In this variant, the body is not stored mixed in with the metadata, but is - passed in (as a bytes-like object) in a separate call to ``set_body()``. - - That is, the expected interaction pattern is:: - - cache.set(key, serialized_metadata) - cache.set_body(key) - - Similarly, the body should be loaded separately via ``get_body()``. - """ - - def set_body(self, key: str, body: bytes) -> None: - raise NotImplementedError() - - def get_body(self, key: str) -> IO[bytes] | None: - """ - Return the body as file-like object. - """ - raise NotImplementedError() diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/caches/__init__.py b/notification-service/venv/Lib/site-packages/cachecontrol/caches/__init__.py deleted file mode 100644 index 44a1af8..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol/caches/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: 2015 Eric Larson -# -# SPDX-License-Identifier: Apache-2.0 - -from cachecontrol.caches.file_cache import FileCache, SeparateBodyFileCache -from cachecontrol.caches.redis_cache import RedisCache - -__all__ = ["FileCache", "SeparateBodyFileCache", "RedisCache"] diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index bde038f..0000000 Binary files a/notification-service/venv/Lib/site-packages/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc deleted file mode 100644 index 0260d82..0000000 Binary files a/notification-service/venv/Lib/site-packages/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc deleted file mode 100644 index 64ba3b2..0000000 Binary files a/notification-service/venv/Lib/site-packages/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/caches/file_cache.py b/notification-service/venv/Lib/site-packages/cachecontrol/caches/file_cache.py deleted file mode 100644 index b0bf5bf..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol/caches/file_cache.py +++ /dev/null @@ -1,145 +0,0 @@ -# SPDX-FileCopyrightText: 2015 Eric Larson -# -# SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations - -import hashlib -import os -import tempfile -from textwrap import dedent -from typing import IO, TYPE_CHECKING -from pathlib import Path - -from cachecontrol.cache import BaseCache, SeparateBodyBaseCache -from cachecontrol.controller import CacheController - -if TYPE_CHECKING: - from datetime import datetime - - from filelock import BaseFileLock - - -class _FileCacheMixin: - """Shared implementation for both FileCache variants.""" - - def __init__( - self, - directory: str | Path, - forever: bool = False, - filemode: int = 0o0600, - dirmode: int = 0o0700, - lock_class: type[BaseFileLock] | None = None, - ) -> None: - try: - if lock_class is None: - from filelock import FileLock - - lock_class = FileLock - except ImportError: - notice = dedent( - """ - NOTE: In order to use the FileCache you must have - filelock installed. You can install it via pip: - pip install cachecontrol[filecache] - """ - ) - raise ImportError(notice) - - self.directory = directory - self.forever = forever - self.filemode = filemode - self.dirmode = dirmode - self.lock_class = lock_class - - @staticmethod - def encode(x: str) -> str: - return hashlib.sha224(x.encode()).hexdigest() - - def _fn(self, name: str) -> str: - # NOTE: This method should not change as some may depend on it. - # See: https://github.com/ionrock/cachecontrol/issues/63 - hashed = self.encode(name) - parts = list(hashed[:5]) + [hashed] - return os.path.join(self.directory, *parts) - - def get(self, key: str) -> bytes | None: - name = self._fn(key) - try: - with open(name, "rb") as fh: - return fh.read() - - except FileNotFoundError: - return None - - def set( - self, key: str, value: bytes, expires: int | datetime | None = None - ) -> None: - name = self._fn(key) - self._write(name, value) - - def _write(self, path: str, data: bytes) -> None: - """ - Safely write the data to the given path. - """ - # Make sure the directory exists - dirname = os.path.dirname(path) - os.makedirs(dirname, self.dirmode, exist_ok=True) - - with self.lock_class(path + ".lock"): - # Write our actual file - (fd, name) = tempfile.mkstemp(dir=dirname) - try: - os.write(fd, data) - finally: - os.close(fd) - os.chmod(name, self.filemode) - os.replace(name, path) - - def _delete(self, key: str, suffix: str) -> None: - name = self._fn(key) + suffix - if not self.forever: - try: - os.remove(name) - except FileNotFoundError: - pass - - -class FileCache(_FileCacheMixin, BaseCache): - """ - Traditional FileCache: body is stored in memory, so not suitable for large - downloads. - """ - - def delete(self, key: str) -> None: - self._delete(key, "") - - -class SeparateBodyFileCache(_FileCacheMixin, SeparateBodyBaseCache): - """ - Memory-efficient FileCache: body is stored in a separate file, reducing - peak memory usage. - """ - - def get_body(self, key: str) -> IO[bytes] | None: - name = self._fn(key) + ".body" - try: - return open(name, "rb") - except FileNotFoundError: - return None - - def set_body(self, key: str, body: bytes) -> None: - name = self._fn(key) + ".body" - self._write(name, body) - - def delete(self, key: str) -> None: - self._delete(key, "") - self._delete(key, ".body") - - -def url_to_file_path(url: str, filecache: FileCache) -> str: - """Return the file cache path based on the URL. - - This does not ensure the file exists! - """ - key = CacheController.cache_url(url) - return filecache._fn(key) diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/caches/redis_cache.py b/notification-service/venv/Lib/site-packages/cachecontrol/caches/redis_cache.py deleted file mode 100644 index f859e71..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol/caches/redis_cache.py +++ /dev/null @@ -1,48 +0,0 @@ -# SPDX-FileCopyrightText: 2015 Eric Larson -# -# SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations - - -from datetime import datetime, timezone -from typing import TYPE_CHECKING - -from cachecontrol.cache import BaseCache - -if TYPE_CHECKING: - from redis import Redis - - -class RedisCache(BaseCache): - def __init__(self, conn: Redis[bytes]) -> None: - self.conn = conn - - def get(self, key: str) -> bytes | None: - return self.conn.get(key) - - def set( - self, key: str, value: bytes, expires: int | datetime | None = None - ) -> None: - if not expires: - self.conn.set(key, value) - elif isinstance(expires, datetime): - now_utc = datetime.now(timezone.utc) - if expires.tzinfo is None: - now_utc = now_utc.replace(tzinfo=None) - delta = expires - now_utc - self.conn.setex(key, int(delta.total_seconds()), value) - else: - self.conn.setex(key, expires, value) - - def delete(self, key: str) -> None: - self.conn.delete(key) - - def clear(self) -> None: - """Helper for clearing all the keys in a database. Use with - caution!""" - for key in self.conn.keys(): - self.conn.delete(key) - - def close(self) -> None: - """Redis uses connection pooling, no need to close the connection.""" - pass diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/controller.py b/notification-service/venv/Lib/site-packages/cachecontrol/controller.py deleted file mode 100644 index c7dd8a1..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol/controller.py +++ /dev/null @@ -1,511 +0,0 @@ -# SPDX-FileCopyrightText: 2015 Eric Larson -# -# SPDX-License-Identifier: Apache-2.0 - -""" -The httplib2 algorithms ported for use with requests. -""" - -from __future__ import annotations - -import calendar -import logging -import re -import time -import weakref -from email.utils import parsedate_tz -from typing import TYPE_CHECKING, Collection, Mapping - -from requests.structures import CaseInsensitiveDict - -from cachecontrol.cache import DictCache, SeparateBodyBaseCache -from cachecontrol.serialize import Serializer - -if TYPE_CHECKING: - from typing import Literal - - from requests import PreparedRequest - from urllib3 import HTTPResponse - - from cachecontrol.cache import BaseCache - -logger = logging.getLogger(__name__) - -URI = re.compile(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?") - -PERMANENT_REDIRECT_STATUSES = (301, 308) - - -def parse_uri(uri: str) -> tuple[str, str, str, str, str]: - """Parses a URI using the regex given in Appendix B of RFC 3986. - - (scheme, authority, path, query, fragment) = parse_uri(uri) - """ - match = URI.match(uri) - assert match is not None - groups = match.groups() - return (groups[1], groups[3], groups[4], groups[6], groups[8]) - - -class CacheController: - """An interface to see if request should cached or not.""" - - def __init__( - self, - cache: BaseCache | None = None, - cache_etags: bool = True, - serializer: Serializer | None = None, - status_codes: Collection[int] | None = None, - ): - self.cache = DictCache() if cache is None else cache - self.cache_etags = cache_etags - self.serializer = serializer or Serializer() - self.cacheable_status_codes = status_codes or (200, 203, 300, 301, 308) - - @classmethod - def _urlnorm(cls, uri: str) -> str: - """Normalize the URL to create a safe key for the cache""" - (scheme, authority, path, query, fragment) = parse_uri(uri) - if not scheme or not authority: - raise Exception("Only absolute URIs are allowed. uri = %s" % uri) - - scheme = scheme.lower() - authority = authority.lower() - - if not path: - path = "/" - - # Could do syntax based normalization of the URI before - # computing the digest. See Section 6.2.2 of Std 66. - request_uri = query and "?".join([path, query]) or path - defrag_uri = scheme + "://" + authority + request_uri - - return defrag_uri - - @classmethod - def cache_url(cls, uri: str) -> str: - return cls._urlnorm(uri) - - def parse_cache_control(self, headers: Mapping[str, str]) -> dict[str, int | None]: - known_directives = { - # https://tools.ietf.org/html/rfc7234#section-5.2 - "max-age": (int, True), - "max-stale": (int, False), - "min-fresh": (int, True), - "no-cache": (None, False), - "no-store": (None, False), - "no-transform": (None, False), - "only-if-cached": (None, False), - "must-revalidate": (None, False), - "public": (None, False), - "private": (None, False), - "proxy-revalidate": (None, False), - "s-maxage": (int, True), - } - - cc_headers = headers.get("cache-control", headers.get("Cache-Control", "")) - - retval: dict[str, int | None] = {} - - for cc_directive in cc_headers.split(","): - if not cc_directive.strip(): - continue - - parts = cc_directive.split("=", 1) - directive = parts[0].strip() - - try: - typ, required = known_directives[directive] - except KeyError: - logger.debug("Ignoring unknown cache-control directive: %s", directive) - continue - - if not typ or not required: - retval[directive] = None - if typ: - try: - retval[directive] = typ(parts[1].strip()) - except IndexError: - if required: - logger.debug( - "Missing value for cache-control " "directive: %s", - directive, - ) - except ValueError: - logger.debug( - "Invalid value for cache-control directive " "%s, must be %s", - directive, - typ.__name__, - ) - - return retval - - def _load_from_cache(self, request: PreparedRequest) -> HTTPResponse | None: - """ - Load a cached response, or return None if it's not available. - """ - # We do not support caching of partial content: so if the request contains a - # Range header then we don't want to load anything from the cache. - if "Range" in request.headers: - return None - - cache_url = request.url - assert cache_url is not None - cache_data = self.cache.get(cache_url) - if cache_data is None: - logger.debug("No cache entry available") - return None - - if isinstance(self.cache, SeparateBodyBaseCache): - body_file = self.cache.get_body(cache_url) - else: - body_file = None - - result = self.serializer.loads(request, cache_data, body_file) - if result is None: - logger.warning("Cache entry deserialization failed, entry ignored") - return result - - def cached_request(self, request: PreparedRequest) -> HTTPResponse | Literal[False]: - """ - Return a cached response if it exists in the cache, otherwise - return False. - """ - assert request.url is not None - cache_url = self.cache_url(request.url) - logger.debug('Looking up "%s" in the cache', cache_url) - cc = self.parse_cache_control(request.headers) - - # Bail out if the request insists on fresh data - if "no-cache" in cc: - logger.debug('Request header has "no-cache", cache bypassed') - return False - - if "max-age" in cc and cc["max-age"] == 0: - logger.debug('Request header has "max_age" as 0, cache bypassed') - return False - - # Check whether we can load the response from the cache: - resp = self._load_from_cache(request) - if not resp: - return False - - # If we have a cached permanent redirect, return it immediately. We - # don't need to test our response for other headers b/c it is - # intrinsically "cacheable" as it is Permanent. - # - # See: - # https://tools.ietf.org/html/rfc7231#section-6.4.2 - # - # Client can try to refresh the value by repeating the request - # with cache busting headers as usual (ie no-cache). - if int(resp.status) in PERMANENT_REDIRECT_STATUSES: - msg = ( - "Returning cached permanent redirect response " - "(ignoring date and etag information)" - ) - logger.debug(msg) - return resp - - headers: CaseInsensitiveDict[str] = CaseInsensitiveDict(resp.headers) - if not headers or "date" not in headers: - if "etag" not in headers: - # Without date or etag, the cached response can never be used - # and should be deleted. - logger.debug("Purging cached response: no date or etag") - self.cache.delete(cache_url) - logger.debug("Ignoring cached response: no date") - return False - - now = time.time() - time_tuple = parsedate_tz(headers["date"]) - assert time_tuple is not None - date = calendar.timegm(time_tuple[:6]) - current_age = max(0, now - date) - logger.debug("Current age based on date: %i", current_age) - - # TODO: There is an assumption that the result will be a - # urllib3 response object. This may not be best since we - # could probably avoid instantiating or constructing the - # response until we know we need it. - resp_cc = self.parse_cache_control(headers) - - # determine freshness - freshness_lifetime = 0 - - # Check the max-age pragma in the cache control header - max_age = resp_cc.get("max-age") - if max_age is not None: - freshness_lifetime = max_age - logger.debug("Freshness lifetime from max-age: %i", freshness_lifetime) - - # If there isn't a max-age, check for an expires header - elif "expires" in headers: - expires = parsedate_tz(headers["expires"]) - if expires is not None: - expire_time = calendar.timegm(expires[:6]) - date - freshness_lifetime = max(0, expire_time) - logger.debug("Freshness lifetime from expires: %i", freshness_lifetime) - - # Determine if we are setting freshness limit in the - # request. Note, this overrides what was in the response. - max_age = cc.get("max-age") - if max_age is not None: - freshness_lifetime = max_age - logger.debug( - "Freshness lifetime from request max-age: %i", freshness_lifetime - ) - - min_fresh = cc.get("min-fresh") - if min_fresh is not None: - # adjust our current age by our min fresh - current_age += min_fresh - logger.debug("Adjusted current age from min-fresh: %i", current_age) - - # Return entry if it is fresh enough - if freshness_lifetime > current_age: - logger.debug('The response is "fresh", returning cached response') - logger.debug("%i > %i", freshness_lifetime, current_age) - return resp - - # we're not fresh. If we don't have an Etag, clear it out - if "etag" not in headers: - logger.debug('The cached response is "stale" with no etag, purging') - self.cache.delete(cache_url) - - # return the original handler - return False - - def conditional_headers(self, request: PreparedRequest) -> dict[str, str]: - resp = self._load_from_cache(request) - new_headers = {} - - if resp: - headers: CaseInsensitiveDict[str] = CaseInsensitiveDict(resp.headers) - - if "etag" in headers: - new_headers["If-None-Match"] = headers["ETag"] - - if "last-modified" in headers: - new_headers["If-Modified-Since"] = headers["Last-Modified"] - - return new_headers - - def _cache_set( - self, - cache_url: str, - request: PreparedRequest, - response: HTTPResponse, - body: bytes | None = None, - expires_time: int | None = None, - ) -> None: - """ - Store the data in the cache. - """ - if isinstance(self.cache, SeparateBodyBaseCache): - # We pass in the body separately; just put a placeholder empty - # string in the metadata. - self.cache.set( - cache_url, - self.serializer.dumps(request, response, b""), - expires=expires_time, - ) - # body is None can happen when, for example, we're only updating - # headers, as is the case in update_cached_response(). - if body is not None: - self.cache.set_body(cache_url, body) - else: - self.cache.set( - cache_url, - self.serializer.dumps(request, response, body), - expires=expires_time, - ) - - def cache_response( - self, - request: PreparedRequest, - response_or_ref: HTTPResponse | weakref.ReferenceType[HTTPResponse], - body: bytes | None = None, - status_codes: Collection[int] | None = None, - ) -> None: - """ - Algorithm for caching requests. - - This assumes a requests Response object. - """ - if isinstance(response_or_ref, weakref.ReferenceType): - response = response_or_ref() - if response is None: - # The weakref can be None only in case the user used streamed request - # and did not consume or close it, and holds no reference to requests.Response. - # In such case, we don't want to cache the response. - return - else: - response = response_or_ref - - # From httplib2: Don't cache 206's since we aren't going to - # handle byte range requests - cacheable_status_codes = status_codes or self.cacheable_status_codes - if response.status not in cacheable_status_codes: - logger.debug( - "Status code %s not in %s", response.status, cacheable_status_codes - ) - return - - response_headers: CaseInsensitiveDict[str] = CaseInsensitiveDict( - response.headers - ) - - if "date" in response_headers: - time_tuple = parsedate_tz(response_headers["date"]) - assert time_tuple is not None - date = calendar.timegm(time_tuple[:6]) - else: - date = 0 - - # If we've been given a body, our response has a Content-Length, that - # Content-Length is valid then we can check to see if the body we've - # been given matches the expected size, and if it doesn't we'll just - # skip trying to cache it. - if ( - body is not None - and "content-length" in response_headers - and response_headers["content-length"].isdigit() - and int(response_headers["content-length"]) != len(body) - ): - return - - cc_req = self.parse_cache_control(request.headers) - cc = self.parse_cache_control(response_headers) - - assert request.url is not None - cache_url = self.cache_url(request.url) - logger.debug('Updating cache with response from "%s"', cache_url) - - # Delete it from the cache if we happen to have it stored there - no_store = False - if "no-store" in cc: - no_store = True - logger.debug('Response header has "no-store"') - if "no-store" in cc_req: - no_store = True - logger.debug('Request header has "no-store"') - if no_store and self.cache.get(cache_url): - logger.debug('Purging existing cache entry to honor "no-store"') - self.cache.delete(cache_url) - if no_store: - return - - # https://tools.ietf.org/html/rfc7234#section-4.1: - # A Vary header field-value of "*" always fails to match. - # Storing such a response leads to a deserialization warning - # during cache lookup and is not allowed to ever be served, - # so storing it can be avoided. - if "*" in response_headers.get("vary", ""): - logger.debug('Response header has "Vary: *"') - return - - # If we've been given an etag, then keep the response - if self.cache_etags and "etag" in response_headers: - expires_time = 0 - if response_headers.get("expires"): - expires = parsedate_tz(response_headers["expires"]) - if expires is not None: - expires_time = calendar.timegm(expires[:6]) - date - - expires_time = max(expires_time, 14 * 86400) - - logger.debug(f"etag object cached for {expires_time} seconds") - logger.debug("Caching due to etag") - self._cache_set(cache_url, request, response, body, expires_time) - - # Add to the cache any permanent redirects. We do this before looking - # that the Date headers. - elif int(response.status) in PERMANENT_REDIRECT_STATUSES: - logger.debug("Caching permanent redirect") - self._cache_set(cache_url, request, response, b"") - - # Add to the cache if the response headers demand it. If there - # is no date header then we can't do anything about expiring - # the cache. - elif "date" in response_headers: - time_tuple = parsedate_tz(response_headers["date"]) - assert time_tuple is not None - date = calendar.timegm(time_tuple[:6]) - # cache when there is a max-age > 0 - max_age = cc.get("max-age") - if max_age is not None and max_age > 0: - logger.debug("Caching b/c date exists and max-age > 0") - expires_time = max_age - self._cache_set( - cache_url, - request, - response, - body, - expires_time, - ) - - # If the request can expire, it means we should cache it - # in the meantime. - elif "expires" in response_headers: - if response_headers["expires"]: - expires = parsedate_tz(response_headers["expires"]) - if expires is not None: - expires_time = calendar.timegm(expires[:6]) - date - else: - expires_time = None - - logger.debug( - "Caching b/c of expires header. expires in {} seconds".format( - expires_time - ) - ) - self._cache_set( - cache_url, - request, - response, - body, - expires_time, - ) - - def update_cached_response( - self, request: PreparedRequest, response: HTTPResponse - ) -> HTTPResponse: - """On a 304 we will get a new set of headers that we want to - update our cached value with, assuming we have one. - - This should only ever be called when we've sent an ETag and - gotten a 304 as the response. - """ - assert request.url is not None - cache_url = self.cache_url(request.url) - cached_response = self._load_from_cache(request) - - if not cached_response: - # we didn't have a cached response - return response - - # Lets update our headers with the headers from the new request: - # http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-4.1 - # - # The server isn't supposed to send headers that would make - # the cached body invalid. But... just in case, we'll be sure - # to strip out ones we know that might be problematic due to - # typical assumptions. - excluded_headers = ["content-length"] - - cached_response.headers.update( - { - k: v - for k, v in response.headers.items() - if k.lower() not in excluded_headers - } - ) - - # we want a 200 b/c we have content via the cache - cached_response.status = 200 - - # update our cache - self._cache_set(cache_url, request, cached_response) - - return cached_response diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/filewrapper.py b/notification-service/venv/Lib/site-packages/cachecontrol/filewrapper.py deleted file mode 100644 index 6569fb5..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol/filewrapper.py +++ /dev/null @@ -1,121 +0,0 @@ -# SPDX-FileCopyrightText: 2015 Eric Larson -# -# SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations - -import mmap -from tempfile import NamedTemporaryFile -from typing import TYPE_CHECKING, Any, Callable - -if TYPE_CHECKING: - from collections.abc import Buffer - from http.client import HTTPResponse - - -class CallbackFileWrapper: - """ - Small wrapper around a fp object which will tee everything read into a - buffer, and when that file is closed it will execute a callback with the - contents of that buffer. - - All attributes are proxied to the underlying file object. - - This class uses members with a double underscore (__) leading prefix so as - not to accidentally shadow an attribute. - - The data is stored in a temporary file until it is all available. As long - as the temporary files directory is disk-based (sometimes it's a - memory-backed-``tmpfs`` on Linux), data will be unloaded to disk if memory - pressure is high. For small files the disk usually won't be used at all, - it'll all be in the filesystem memory cache, so there should be no - performance impact. - """ - - def __init__( - self, fp: HTTPResponse, callback: Callable[[Buffer], None] | None - ) -> None: - self.__buf = NamedTemporaryFile("rb+", delete=True) - self.__fp = fp - self.__callback = callback - - def __getattr__(self, name: str) -> Any: - # The vagaries of garbage collection means that self.__fp is - # not always set. By using __getattribute__ and the private - # name[0] allows looking up the attribute value and raising an - # AttributeError when it doesn't exist. This stop things from - # infinitely recursing calls to getattr in the case where - # self.__fp hasn't been set. - # - # [0] https://docs.python.org/2/reference/expressions.html#atom-identifiers - fp = self.__getattribute__("_CallbackFileWrapper__fp") - return getattr(fp, name) - - def __is_fp_closed(self) -> bool: - try: - return self.__fp.fp is None - - except AttributeError: - pass - - try: - closed: bool = self.__fp.closed - return closed - - except AttributeError: - pass - - # We just don't cache it then. - # TODO: Add some logging here... - return False - - def _close(self) -> None: - result: Buffer - if self.__callback: - if self.__buf.tell() == 0: - # Empty file: - result = b"" - else: - # Return the data without actually loading it into memory, - # relying on Python's buffer API and mmap(). mmap() just gives - # a view directly into the filesystem's memory cache, so it - # doesn't result in duplicate memory use. - self.__buf.seek(0, 0) - result = memoryview( - mmap.mmap(self.__buf.fileno(), 0, access=mmap.ACCESS_READ) - ) - self.__callback(result) - - # We assign this to None here, because otherwise we can get into - # really tricky problems where the CPython interpreter dead locks - # because the callback is holding a reference to something which - # has a __del__ method. Setting this to None breaks the cycle - # and allows the garbage collector to do it's thing normally. - self.__callback = None - - # Closing the temporary file releases memory and frees disk space. - # Important when caching big files. - self.__buf.close() - - def read(self, amt: int | None = None) -> bytes: - data: bytes = self.__fp.read(amt) - if data: - # We may be dealing with b'', a sign that things are over: - # it's passed e.g. after we've already closed self.__buf. - self.__buf.write(data) - if self.__is_fp_closed(): - self._close() - - return data - - def _safe_read(self, amt: int) -> bytes: - data: bytes = self.__fp._safe_read(amt) # type: ignore[attr-defined] - if amt == 2 and data == b"\r\n": - # urllib executes this read to toss the CRLF at the end - # of the chunk. - return data - - self.__buf.write(data) - if self.__is_fp_closed(): - self._close() - - return data diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/heuristics.py b/notification-service/venv/Lib/site-packages/cachecontrol/heuristics.py deleted file mode 100644 index d95e78a..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol/heuristics.py +++ /dev/null @@ -1,157 +0,0 @@ -# SPDX-FileCopyrightText: 2015 Eric Larson -# -# SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations - -import calendar -import time -from datetime import datetime, timedelta, timezone -from email.utils import formatdate, parsedate, parsedate_tz -from typing import TYPE_CHECKING, Any, Mapping - -if TYPE_CHECKING: - from urllib3 import HTTPResponse - -TIME_FMT = "%a, %d %b %Y %H:%M:%S GMT" - - -def expire_after(delta: timedelta, date: datetime | None = None) -> datetime: - date = date or datetime.now(timezone.utc) - return date + delta - - -def datetime_to_header(dt: datetime) -> str: - return formatdate(calendar.timegm(dt.timetuple())) - - -class BaseHeuristic: - def warning(self, response: HTTPResponse) -> str | None: - """ - Return a valid 1xx warning header value describing the cache - adjustments. - - The response is provided too allow warnings like 113 - http://tools.ietf.org/html/rfc7234#section-5.5.4 where we need - to explicitly say response is over 24 hours old. - """ - return '110 - "Response is Stale"' - - def update_headers(self, response: HTTPResponse) -> dict[str, str]: - """Update the response headers with any new headers. - - NOTE: This SHOULD always include some Warning header to - signify that the response was cached by the client, not - by way of the provided headers. - """ - return {} - - def apply(self, response: HTTPResponse) -> HTTPResponse: - updated_headers = self.update_headers(response) - - if updated_headers: - response.headers.update(updated_headers) - warning_header_value = self.warning(response) - if warning_header_value is not None: - response.headers.update({"Warning": warning_header_value}) - - return response - - -class OneDayCache(BaseHeuristic): - """ - Cache the response by providing an expires 1 day in the - future. - """ - - def update_headers(self, response: HTTPResponse) -> dict[str, str]: - headers = {} - - if "expires" not in response.headers: - date = parsedate(response.headers["date"]) - expires = expire_after( - timedelta(days=1), - date=datetime(*date[:6], tzinfo=timezone.utc), # type: ignore[index,misc] - ) - headers["expires"] = datetime_to_header(expires) - headers["cache-control"] = "public" - return headers - - -class ExpiresAfter(BaseHeuristic): - """ - Cache **all** requests for a defined time period. - """ - - def __init__(self, **kw: Any) -> None: - self.delta = timedelta(**kw) - - def update_headers(self, response: HTTPResponse) -> dict[str, str]: - expires = expire_after(self.delta) - return {"expires": datetime_to_header(expires), "cache-control": "public"} - - def warning(self, response: HTTPResponse) -> str | None: - tmpl = "110 - Automatically cached for %s. Response might be stale" - return tmpl % self.delta - - -class LastModified(BaseHeuristic): - """ - If there is no Expires header already, fall back on Last-Modified - using the heuristic from - http://tools.ietf.org/html/rfc7234#section-4.2.2 - to calculate a reasonable value. - - Firefox also does something like this per - https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching_FAQ - http://lxr.mozilla.org/mozilla-release/source/netwerk/protocol/http/nsHttpResponseHead.cpp#397 - Unlike mozilla we limit this to 24-hr. - """ - - cacheable_by_default_statuses = { - 200, - 203, - 204, - 206, - 300, - 301, - 404, - 405, - 410, - 414, - 501, - } - - def update_headers(self, resp: HTTPResponse) -> dict[str, str]: - headers: Mapping[str, str] = resp.headers - - if "expires" in headers: - return {} - - if "cache-control" in headers and headers["cache-control"] != "public": - return {} - - if resp.status not in self.cacheable_by_default_statuses: - return {} - - if "date" not in headers or "last-modified" not in headers: - return {} - - time_tuple = parsedate_tz(headers["date"]) - assert time_tuple is not None - date = calendar.timegm(time_tuple[:6]) - last_modified = parsedate(headers["last-modified"]) - if last_modified is None: - return {} - - now = time.time() - current_age = max(0, now - date) - delta = date - calendar.timegm(last_modified) - freshness_lifetime = max(0, min(delta / 10, 24 * 3600)) - if freshness_lifetime <= current_age: - return {} - - expires = date + freshness_lifetime - return {"expires": time.strftime(TIME_FMT, time.gmtime(expires))} - - def warning(self, resp: HTTPResponse) -> str | None: - return None diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/py.typed b/notification-service/venv/Lib/site-packages/cachecontrol/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/serialize.py b/notification-service/venv/Lib/site-packages/cachecontrol/serialize.py deleted file mode 100644 index 83bce07..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol/serialize.py +++ /dev/null @@ -1,146 +0,0 @@ -# SPDX-FileCopyrightText: 2015 Eric Larson -# -# SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations - -import io -from typing import IO, TYPE_CHECKING, Any, Mapping, cast - -import msgpack -from requests.structures import CaseInsensitiveDict -from urllib3 import HTTPResponse - -if TYPE_CHECKING: - from requests import PreparedRequest - - -class Serializer: - serde_version = "4" - - def dumps( - self, - request: PreparedRequest, - response: HTTPResponse, - body: bytes | None = None, - ) -> bytes: - response_headers: CaseInsensitiveDict[str] = CaseInsensitiveDict( - response.headers - ) - - if body is None: - # When a body isn't passed in, we'll read the response. We - # also update the response with a new file handler to be - # sure it acts as though it was never read. - body = response.read(decode_content=False) - response._fp = io.BytesIO(body) # type: ignore[assignment] - response.length_remaining = len(body) - - data = { - "response": { - "body": body, # Empty bytestring if body is stored separately - "headers": {str(k): str(v) for k, v in response.headers.items()}, - "status": response.status, - "version": response.version, - "reason": str(response.reason), - "decode_content": response.decode_content, - } - } - - # Construct our vary headers - data["vary"] = {} - if "vary" in response_headers: - varied_headers = response_headers["vary"].split(",") - for header in varied_headers: - header = str(header).strip() - header_value = request.headers.get(header, None) - if header_value is not None: - header_value = str(header_value) - data["vary"][header] = header_value - - return b",".join([f"cc={self.serde_version}".encode(), self.serialize(data)]) - - def serialize(self, data: dict[str, Any]) -> bytes: - return cast(bytes, msgpack.dumps(data, use_bin_type=True)) - - def loads( - self, - request: PreparedRequest, - data: bytes, - body_file: IO[bytes] | None = None, - ) -> HTTPResponse | None: - # Short circuit if we've been given an empty set of data - if not data: - return None - - # Previous versions of this library supported other serialization - # formats, but these have all been removed. - if not data.startswith(f"cc={self.serde_version},".encode()): - return None - - data = data[5:] - return self._loads_v4(request, data, body_file) - - def prepare_response( - self, - request: PreparedRequest, - cached: Mapping[str, Any], - body_file: IO[bytes] | None = None, - ) -> HTTPResponse | None: - """Verify our vary headers match and construct a real urllib3 - HTTPResponse object. - """ - # Special case the '*' Vary value as it means we cannot actually - # determine if the cached response is suitable for this request. - # This case is also handled in the controller code when creating - # a cache entry, but is left here for backwards compatibility. - if "*" in cached.get("vary", {}): - return None - - # Ensure that the Vary headers for the cached response match our - # request - for header, value in cached.get("vary", {}).items(): - if request.headers.get(header, None) != value: - return None - - body_raw = cached["response"].pop("body") - - headers: CaseInsensitiveDict[str] = CaseInsensitiveDict( - data=cached["response"]["headers"] - ) - if headers.get("transfer-encoding", "") == "chunked": - headers.pop("transfer-encoding") - - cached["response"]["headers"] = headers - - try: - body: IO[bytes] - if body_file is None: - body = io.BytesIO(body_raw) - else: - body = body_file - except TypeError: - # This can happen if cachecontrol serialized to v1 format (pickle) - # using Python 2. A Python 2 str(byte string) will be unpickled as - # a Python 3 str (unicode string), which will cause the above to - # fail with: - # - # TypeError: 'str' does not support the buffer interface - body = io.BytesIO(body_raw.encode("utf8")) - - # Discard any `strict` parameter serialized by older version of cachecontrol. - cached["response"].pop("strict", None) - - return HTTPResponse(body=body, preload_content=False, **cached["response"]) - - def _loads_v4( - self, - request: PreparedRequest, - data: bytes, - body_file: IO[bytes] | None = None, - ) -> HTTPResponse | None: - try: - cached = msgpack.loads(data, raw=False) - except ValueError: - return None - - return self.prepare_response(request, cached, body_file) diff --git a/notification-service/venv/Lib/site-packages/cachecontrol/wrapper.py b/notification-service/venv/Lib/site-packages/cachecontrol/wrapper.py deleted file mode 100644 index 37ee07c..0000000 --- a/notification-service/venv/Lib/site-packages/cachecontrol/wrapper.py +++ /dev/null @@ -1,43 +0,0 @@ -# SPDX-FileCopyrightText: 2015 Eric Larson -# -# SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations - -from typing import TYPE_CHECKING, Collection - -from cachecontrol.adapter import CacheControlAdapter -from cachecontrol.cache import DictCache - -if TYPE_CHECKING: - import requests - - from cachecontrol.cache import BaseCache - from cachecontrol.controller import CacheController - from cachecontrol.heuristics import BaseHeuristic - from cachecontrol.serialize import Serializer - - -def CacheControl( - sess: requests.Session, - cache: BaseCache | None = None, - cache_etags: bool = True, - serializer: Serializer | None = None, - heuristic: BaseHeuristic | None = None, - controller_class: type[CacheController] | None = None, - adapter_class: type[CacheControlAdapter] | None = None, - cacheable_methods: Collection[str] | None = None, -) -> requests.Session: - cache = DictCache() if cache is None else cache - adapter_class = adapter_class or CacheControlAdapter - adapter = adapter_class( - cache, - cache_etags=cache_etags, - serializer=serializer, - heuristic=heuristic, - controller_class=controller_class, - cacheable_methods=cacheable_methods, - ) - sess.mount("http://", adapter) - sess.mount("https://", adapter) - - return sess diff --git a/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/INSTALLER b/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/METADATA b/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/METADATA deleted file mode 100644 index 7b7bb30..0000000 --- a/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/METADATA +++ /dev/null @@ -1,78 +0,0 @@ -Metadata-Version: 2.4 -Name: certifi -Version: 2026.5.20 -Summary: Python package for providing Mozilla's CA Bundle. -Home-page: https://github.com/certifi/python-certifi -Author: Kenneth Reitz -Author-email: me@kennethreitz.com -License: MPL-2.0 -Project-URL: Source, https://github.com/certifi/python-certifi -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0) -Classifier: Natural Language :: English -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -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 -Requires-Python: >=3.7 -License-File: LICENSE -Dynamic: author -Dynamic: author-email -Dynamic: classifier -Dynamic: description -Dynamic: home-page -Dynamic: license -Dynamic: license-file -Dynamic: project-url -Dynamic: requires-python -Dynamic: summary - -Certifi: Python SSL Certificates -================================ - -Certifi provides Mozilla's carefully curated collection of Root Certificates for -validating the trustworthiness of SSL certificates while verifying the identity -of TLS hosts. It has been extracted from the `Requests`_ project. - -Installation ------------- - -``certifi`` is available on PyPI. Simply install it with ``pip``:: - - $ pip install certifi - -Usage ------ - -To reference the installed certificate authority (CA) bundle, you can use the -built-in function:: - - >>> import certifi - - >>> certifi.where() - '/usr/local/lib/python3.7/site-packages/certifi/cacert.pem' - -Or from the command line:: - - $ python -m certifi - /usr/local/lib/python3.7/site-packages/certifi/cacert.pem - -Enjoy! - -.. _`Requests`: https://requests.readthedocs.io/en/master/ - -Addition/Removal of Certificates --------------------------------- - -Certifi does not support any addition/removal or other modification of the -CA trust store content. This project is intended to provide a reliable and -highly portable root of trust to python deployments. Look to upstream projects -for methods to use alternate trust. diff --git a/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/RECORD b/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/RECORD deleted file mode 100644 index 71a62dc..0000000 --- a/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/RECORD +++ /dev/null @@ -1,14 +0,0 @@ -certifi-2026.5.20.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -certifi-2026.5.20.dist-info/METADATA,sha256=HDiCa8lfd0TGlQFongDjoaLJOhWJiJN84y707Vwd8PY,2474 -certifi-2026.5.20.dist-info/RECORD,, -certifi-2026.5.20.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91 -certifi-2026.5.20.dist-info/licenses/LICENSE,sha256=6TcW2mucDVpKHfYP5pWzcPBpVgPSH2-D8FPkLPwQyvc,989 -certifi-2026.5.20.dist-info/top_level.txt,sha256=KMu4vUCfsjLrkPbSNdgdekS-pVJzBAJFO__nI8NF6-U,8 -certifi/__init__.py,sha256=-8ljc7w7fyi5Kyi06c1_L0lG_kD_J0FvbUTa8mEpdzQ,94 -certifi/__main__.py,sha256=xBBoj905TUWBLRGANOcf7oi6e-3dMP4cEoG9OyMs11g,243 -certifi/__pycache__/__init__.cpython-312.pyc,, -certifi/__pycache__/__main__.cpython-312.pyc,, -certifi/__pycache__/core.cpython-312.pyc,, -certifi/cacert.pem,sha256=fO9UDGrzvwo8fQBwvT_XquNPiqgFtAjRwnoByK6zBd8,236095 -certifi/core.py,sha256=XFXycndG5pf37ayeF8N32HUuDafsyhkVMbO4BAPWHa0,3394 -certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/WHEEL b/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/WHEEL deleted file mode 100644 index 14a883f..0000000 --- a/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (82.0.1) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/licenses/LICENSE b/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/licenses/LICENSE deleted file mode 100644 index 62b076c..0000000 --- a/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/licenses/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -This package contains a modified version of ca-bundle.crt: - -ca-bundle.crt -- Bundle of CA Root Certificates - -This is a bundle of X.509 certificates of public Certificate Authorities -(CA). These were automatically extracted from Mozilla's root certificates -file (certdata.txt). This file can be found in the mozilla source tree: -https://hg.mozilla.org/mozilla-central/file/tip/security/nss/lib/ckfw/builtins/certdata.txt -It contains the certificates in PEM format and therefore -can be directly used with curl / libcurl / php_curl, or with -an Apache+mod_ssl webserver for SSL client authentication. -Just configure this file as the SSLCACertificateFile.# - -***** BEGIN LICENSE BLOCK ***** -This Source Code Form is subject to the terms of the Mozilla Public License, -v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain -one at http://mozilla.org/MPL/2.0/. - -***** END LICENSE BLOCK ***** -@(#) $RCSfile: certdata.txt,v $ $Revision: 1.80 $ $Date: 2011/11/03 15:11:58 $ diff --git a/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/top_level.txt b/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/top_level.txt deleted file mode 100644 index 963eac5..0000000 --- a/notification-service/venv/Lib/site-packages/certifi-2026.5.20.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -certifi diff --git a/notification-service/venv/Lib/site-packages/certifi/__init__.py b/notification-service/venv/Lib/site-packages/certifi/__init__.py deleted file mode 100644 index 004dd55..0000000 --- a/notification-service/venv/Lib/site-packages/certifi/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .core import contents, where - -__all__ = ["contents", "where"] -__version__ = "2026.05.20" diff --git a/notification-service/venv/Lib/site-packages/certifi/__main__.py b/notification-service/venv/Lib/site-packages/certifi/__main__.py deleted file mode 100644 index 8945b5d..0000000 --- a/notification-service/venv/Lib/site-packages/certifi/__main__.py +++ /dev/null @@ -1,12 +0,0 @@ -import argparse - -from certifi import contents, where - -parser = argparse.ArgumentParser() -parser.add_argument("-c", "--contents", action="store_true") -args = parser.parse_args() - -if args.contents: - print(contents()) -else: - print(where()) diff --git a/notification-service/venv/Lib/site-packages/certifi/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/certifi/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index a08f464..0000000 Binary files a/notification-service/venv/Lib/site-packages/certifi/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/certifi/__pycache__/__main__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/certifi/__pycache__/__main__.cpython-312.pyc deleted file mode 100644 index d93b137..0000000 Binary files a/notification-service/venv/Lib/site-packages/certifi/__pycache__/__main__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/certifi/__pycache__/core.cpython-312.pyc b/notification-service/venv/Lib/site-packages/certifi/__pycache__/core.cpython-312.pyc deleted file mode 100644 index af07d02..0000000 Binary files a/notification-service/venv/Lib/site-packages/certifi/__pycache__/core.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/certifi/cacert.pem b/notification-service/venv/Lib/site-packages/certifi/cacert.pem deleted file mode 100644 index 6faad41..0000000 --- a/notification-service/venv/Lib/site-packages/certifi/cacert.pem +++ /dev/null @@ -1,3892 +0,0 @@ - -# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited -# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited -# Label: "COMODO ECC Certification Authority" -# Serial: 41578283867086692638256921589707938090 -# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23 -# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11 -# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7 ------BEGIN CERTIFICATE----- -MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL -MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE -BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT -IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw -MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy -ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N -T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR -FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J -cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW -BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm -fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv -GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= ------END CERTIFICATE----- - -# Issuer: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) -# Subject: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) -# Label: "NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny" -# Serial: 80544274841616 -# MD5 Fingerprint: c5:a1:b7:ff:73:dd:d6:d7:34:32:18:df:fc:3c:ad:88 -# SHA1 Fingerprint: 06:08:3f:59:3f:15:a1:04:a0:69:a4:6b:a9:03:d0:06:b7:97:09:91 -# SHA256 Fingerprint: 6c:61:da:c3:a2:de:f0:31:50:6b:e0:36:d2:a6:fe:40:19:94:fb:d1:3d:f9:c8:d4:66:59:92:74:c4:46:ec:98 ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG -EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 -MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl -cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR -dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB -pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM -b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm -aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz -IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT -lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz -AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 -VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG -ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 -BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG -AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M -U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh -bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C -+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC -bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F -uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 -XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= ------END CERTIFICATE----- - -# Issuer: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. -# Subject: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. -# Label: "Microsec e-Szigno Root CA 2009" -# Serial: 14014712776195784473 -# MD5 Fingerprint: f8:49:f4:03:bc:44:2d:83:be:48:69:7d:29:64:fc:b1 -# SHA1 Fingerprint: 89:df:74:fe:5c:f4:0f:4a:80:f9:e3:37:7d:54:da:91:e1:01:31:8e -# SHA256 Fingerprint: 3c:5f:81:fe:a5:fa:b8:2c:64:bf:a2:ea:ec:af:cd:e8:e0:77:fc:86:20:a7:ca:e5:37:16:3d:f3:6e:db:f3:78 ------BEGIN CERTIFICATE----- -MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD -VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 -ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G -CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y -OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx -FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp -Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o -dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP -kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc -cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U -fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 -N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC -xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 -+rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G -A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM -Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG -SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h -mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk -ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 -tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c -2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t -HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 -# Label: "GlobalSign Root CA - R3" -# Serial: 4835703278459759426209954 -# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28 -# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad -# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b ------BEGIN CERTIFICATE----- -MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 -MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 -RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT -gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm -KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd -QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ -XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw -DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o -LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU -RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp -jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK -6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX -mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs -Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH -WD9f ------END CERTIFICATE----- - -# Issuer: CN=Izenpe.com O=IZENPE S.A. -# Subject: CN=Izenpe.com O=IZENPE S.A. -# Label: "Izenpe.com" -# Serial: 917563065490389241595536686991402621 -# MD5 Fingerprint: a6:b0:cd:85:80:da:5c:50:34:a3:39:90:2f:55:67:73 -# SHA1 Fingerprint: 2f:78:3d:25:52:18:a7:4a:65:39:71:b5:2c:a2:9c:45:15:6f:e9:19 -# SHA256 Fingerprint: 25:30:cc:8e:98:32:15:02:ba:d9:6f:9b:1f:ba:1b:09:9e:2d:29:9e:0f:45:48:bb:91:4f:36:3b:c0:d4:53:1f ------BEGIN CERTIFICATE----- -MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 -MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 -ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD -VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j -b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq -scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO -xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H -LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX -uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD -yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ -JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q -rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN -BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L -hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB -QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ -HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu -Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg -QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB -BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx -MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA -A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb -laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 -awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo -JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw -LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT -VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk -LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb -UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ -QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ -naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls -QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== ------END CERTIFICATE----- - -# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. -# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. -# Label: "Go Daddy Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01 -# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b -# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT -EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp -ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz -NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH -EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE -AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD -E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH -/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy -DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh -GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR -tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA -AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE -FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX -WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu -9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr -gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo -2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO -LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI -4uJEvlz36hz1 ------END CERTIFICATE----- - -# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Label: "Starfield Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96 -# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e -# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5 ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs -ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw -MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 -b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj -aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp -Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg -nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 -HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N -Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN -dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 -HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G -CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU -sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 -4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg -8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K -pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 -mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 ------END CERTIFICATE----- - -# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. -# Label: "Starfield Services Root Certificate Authority - G2" -# Serial: 0 -# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2 -# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f -# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5 ------BEGIN CERTIFICATE----- -MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx -EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT -HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs -ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 -MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD -VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy -ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy -dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p -OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 -8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K -Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe -hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk -6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw -DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q -AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI -bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB -ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z -qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd -iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn -0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN -sSi6 ------END CERTIFICATE----- - -# Issuer: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority -# Subject: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority -# Label: "Certum Trusted Network CA" -# Serial: 279744 -# MD5 Fingerprint: d5:e9:81:40:c5:18:69:fc:46:2c:89:75:62:0f:aa:78 -# SHA1 Fingerprint: 07:e0:32:e0:20:b7:2c:3f:19:2f:06:28:a2:59:3a:19:a7:0f:06:9e -# SHA256 Fingerprint: 5c:58:46:8d:55:f5:8e:49:7e:74:39:82:d2:b5:00:10:b6:d1:65:37:4a:cf:83:a7:d4:a3:2d:b7:68:c4:40:8e ------BEGIN CERTIFICATE----- -MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM -MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D -ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU -cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 -WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg -Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw -IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH -UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM -TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU -BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM -kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x -AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV -HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y -sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL -I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 -J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY -VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI -03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= ------END CERTIFICATE----- - -# Issuer: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA -# Subject: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA -# Label: "TWCA Root Certification Authority" -# Serial: 1 -# MD5 Fingerprint: aa:08:8f:f6:f9:7b:b7:f2:b1:a7:1e:9b:ea:ea:bd:79 -# SHA1 Fingerprint: cf:9e:87:6d:d3:eb:fc:42:26:97:a3:b5:a3:7a:a0:76:a9:06:23:48 -# SHA256 Fingerprint: bf:d8:8f:e1:10:1c:41:ae:3e:80:1b:f8:be:56:35:0e:e9:ba:d1:a6:b9:bd:51:5e:dc:5c:6d:5b:87:11:ac:44 ------BEGIN CERTIFICATE----- -MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES -MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU -V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz -WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO -LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm -aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE -AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH -K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX -RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z -rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx -3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq -hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC -MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls -XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D -lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn -aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ -YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== ------END CERTIFICATE----- - -# Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 -# Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 -# Label: "Security Communication RootCA2" -# Serial: 0 -# MD5 Fingerprint: 6c:39:7d:a4:0e:55:59:b2:3f:d6:41:b1:12:50:de:43 -# SHA1 Fingerprint: 5f:3b:8c:f2:f8:10:b3:7d:78:b4:ce:ec:19:19:c3:73:34:b9:c7:74 -# SHA256 Fingerprint: 51:3b:2c:ec:b8:10:d4:cd:e5:dd:85:39:1a:df:c6:c2:dd:60:d8:7b:b7:36:d2:b5:21:48:4a:a4:7a:0e:be:f6 ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl -MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe -U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX -DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy -dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj -YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV -OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr -zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM -VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ -hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO -ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw -awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs -OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 -DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF -coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc -okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 -t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy -1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ -SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 ------END CERTIFICATE----- - -# Issuer: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 -# Subject: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 -# Label: "Actalis Authentication Root CA" -# Serial: 6271844772424770508 -# MD5 Fingerprint: 69:c1:0d:4f:07:a3:1b:c3:fe:56:3d:04:bc:11:f6:a6 -# SHA1 Fingerprint: f3:73:b3:87:06:5a:28:84:8a:f2:f3:4a:ce:19:2b:dd:c7:8e:9c:ac -# SHA256 Fingerprint: 55:92:60:84:ec:96:3a:64:b9:6e:2a:be:01:ce:0b:a8:6a:64:fb:fe:bc:c7:aa:b5:af:c1:55:b3:7f:d7:60:66 ------BEGIN CERTIFICATE----- -MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE -BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w -MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 -IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC -SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 -ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv -UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX -4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 -KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ -gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb -rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ -51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F -be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe -KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F -v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn -fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 -jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz -ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt -ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL -e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 -jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz -WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V -SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j -pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX -X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok -fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R -K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU -ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU -LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT -LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== ------END CERTIFICATE----- - -# Issuer: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 -# Subject: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 -# Label: "Buypass Class 2 Root CA" -# Serial: 2 -# MD5 Fingerprint: 46:a7:d2:fe:45:fb:64:5a:a8:59:90:9b:78:44:9b:29 -# SHA1 Fingerprint: 49:0a:75:74:de:87:0a:47:fe:58:ee:f6:c7:6b:eb:c6:0b:12:40:99 -# SHA256 Fingerprint: 9a:11:40:25:19:7c:5b:b9:5d:94:e6:3d:55:cd:43:79:08:47:b6:46:b2:3c:df:11:ad:a4:a0:0e:ff:15:fb:48 ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd -MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg -Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow -TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw -HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB -BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr -6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV -L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 -1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx -MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ -QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB -arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr -Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi -FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS -P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN -9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP -AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz -uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h -9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s -A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t -OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo -+fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 -KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 -DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us -H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ -I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 -5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h -3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz -Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= ------END CERTIFICATE----- - -# Issuer: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 -# Subject: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 -# Label: "Buypass Class 3 Root CA" -# Serial: 2 -# MD5 Fingerprint: 3d:3b:18:9e:2c:64:5a:e8:d5:88:ce:0e:f9:37:c2:ec -# SHA1 Fingerprint: da:fa:f7:fa:66:84:ec:06:8f:14:50:bd:c7:c2:81:a5:bc:a9:64:57 -# SHA256 Fingerprint: ed:f7:eb:bc:a2:7a:2a:38:4d:38:7b:7d:40:10:c6:66:e2:ed:b4:84:3e:4c:29:b4:ae:1d:5b:93:32:e6:b2:4d ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd -MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg -Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow -TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw -HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB -BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y -ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E -N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 -tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX -0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c -/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X -KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY -zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS -O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D -34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP -K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 -AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv -Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj -QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV -cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS -IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 -HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa -O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv -033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u -dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE -kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 -3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD -u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq -4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= ------END CERTIFICATE----- - -# Issuer: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center -# Subject: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center -# Label: "T-TeleSec GlobalRoot Class 3" -# Serial: 1 -# MD5 Fingerprint: ca:fb:40:a8:4e:39:92:8a:1d:fe:8e:2f:c4:27:ea:ef -# SHA1 Fingerprint: 55:a6:72:3e:cb:f2:ec:cd:c3:23:74:70:19:9d:2a:be:11:e3:81:d1 -# SHA256 Fingerprint: fd:73:da:d3:1c:64:4f:f1:b4:3b:ef:0c:cd:da:96:71:0b:9c:d9:87:5e:ca:7e:31:70:7a:f3:e9:6d:52:2b:bd ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx -KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd -BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl -YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 -OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy -aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 -ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN -8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ -RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 -hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 -ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM -EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj -QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 -A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy -WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ -1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 -6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT -91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml -e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p -TpPDpFQUWw== ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH -# Subject: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH -# Label: "D-TRUST Root Class 3 CA 2 2009" -# Serial: 623603 -# MD5 Fingerprint: cd:e0:25:69:8d:47:ac:9c:89:35:90:f7:fd:51:3d:2f -# SHA1 Fingerprint: 58:e8:ab:b0:36:15:33:fb:80:f7:9b:1b:6d:29:d3:ff:8d:5f:00:f0 -# SHA256 Fingerprint: 49:e7:a4:42:ac:f0:ea:62:87:05:00:54:b5:25:64:b6:50:e4:f4:9e:42:e3:48:d6:aa:38:e0:39:e9:57:b1:c1 ------BEGIN CERTIFICATE----- -MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF -MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD -bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha -ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM -HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 -UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 -tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R -ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM -lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp -/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G -A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G -A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj -dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy -MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl -cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js -L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL -BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni -acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 -o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K -zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 -PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y -Johw1+qRzT65ysCQblrGXnRl11z+o+I= ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH -# Subject: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH -# Label: "D-TRUST Root Class 3 CA 2 EV 2009" -# Serial: 623604 -# MD5 Fingerprint: aa:c6:43:2c:5e:2d:cd:c4:34:c0:50:4f:11:02:4f:b6 -# SHA1 Fingerprint: 96:c9:1b:0b:95:b4:10:98:42:fa:d0:d8:22:79:fe:60:fa:b9:16:83 -# SHA256 Fingerprint: ee:c5:49:6b:98:8c:e9:86:25:b9:34:09:2e:ec:29:08:be:d0:b0:f3:16:c2:d4:73:0c:84:ea:f1:f3:d3:48:81 ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF -MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD -bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw -NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV -BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn -ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 -3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z -qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR -p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 -HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw -ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea -HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw -Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh -c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E -RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt -dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku -Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp -3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 -nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF -CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na -xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX -KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 ------END CERTIFICATE----- - -# Issuer: CN=CA Disig Root R2 O=Disig a.s. -# Subject: CN=CA Disig Root R2 O=Disig a.s. -# Label: "CA Disig Root R2" -# Serial: 10572350602393338211 -# MD5 Fingerprint: 26:01:fb:d8:27:a7:17:9a:45:54:38:1a:43:01:3b:03 -# SHA1 Fingerprint: b5:61:eb:ea:a4:de:e4:25:4b:69:1a:98:a5:57:47:c2:34:c7:d9:71 -# SHA256 Fingerprint: e2:3d:4a:03:6d:7b:70:e9:f5:95:b1:42:20:79:d2:b9:1e:df:bb:1f:b6:51:a0:63:3e:aa:8a:9d:c5:f8:07:03 ------BEGIN CERTIFICATE----- -MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV -BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu -MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy -MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx -EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw -ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe -NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH -PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I -x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe -QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR -yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO -QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 -H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ -QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD -i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs -nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 -rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud -DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI -hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM -tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf -GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb -lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka -+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal -TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i -nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 -gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr -G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os -zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x -L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL ------END CERTIFICATE----- - -# Issuer: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV -# Subject: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV -# Label: "ACCVRAIZ1" -# Serial: 6828503384748696800 -# MD5 Fingerprint: d0:a0:5a:ee:05:b6:09:94:21:a1:7d:f1:b2:29:82:02 -# SHA1 Fingerprint: 93:05:7a:88:15:c6:4f:ce:88:2f:fa:91:16:52:28:78:bc:53:64:17 -# SHA256 Fingerprint: 9a:6e:c0:12:e1:a7:da:9d:be:34:19:4d:47:8a:d7:c0:db:18:22:fb:07:1d:f1:29:81:49:6e:d1:04:38:41:13 ------BEGIN CERTIFICATE----- -MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE -AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw -CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ -BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND -VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb -qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY -HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo -G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA -lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr -IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ -0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH -k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 -4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO -m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa -cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl -uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI -KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls -ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG -AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 -VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT -VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG -CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA -cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA -QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA -7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA -cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA -QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA -czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu -aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt -aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud -DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF -BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp -D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU -JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m -AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD -vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms -tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH -7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h -I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA -h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF -d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H -pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 ------END CERTIFICATE----- - -# Issuer: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA -# Subject: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA -# Label: "TWCA Global Root CA" -# Serial: 3262 -# MD5 Fingerprint: f9:03:7e:cf:e6:9e:3c:73:7a:2a:90:07:69:ff:2b:96 -# SHA1 Fingerprint: 9c:bb:48:53:f6:a4:f6:d3:52:a4:e8:32:52:55:60:13:f5:ad:af:65 -# SHA256 Fingerprint: 59:76:90:07:f7:68:5d:0f:cd:50:87:2f:9f:95:d5:75:5a:5b:2b:45:7d:81:f3:69:2b:61:0a:98:67:2f:0e:1b ------BEGIN CERTIFICATE----- -MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx -EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT -VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 -NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT -B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF -10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz -0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh -MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH -zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc -46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 -yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi -laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP -oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA -BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE -qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm -4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL -1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn -LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF -H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo -RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ -nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh -15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW -6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW -nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j -wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz -aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy -KwbQBM0= ------END CERTIFICATE----- - -# Issuer: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center -# Subject: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center -# Label: "T-TeleSec GlobalRoot Class 2" -# Serial: 1 -# MD5 Fingerprint: 2b:9b:9e:e4:7b:6c:1f:00:72:1a:cc:c1:77:79:df:6a -# SHA1 Fingerprint: 59:0d:2d:7d:88:4f:40:2e:61:7e:a5:62:32:17:65:cf:17:d8:94:e9 -# SHA256 Fingerprint: 91:e2:f5:78:8d:58:10:eb:a7:ba:58:73:7d:e1:54:8a:8e:ca:cd:01:45:98:bc:0b:14:3e:04:1b:17:05:25:52 ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx -KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd -BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl -YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 -OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy -aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 -ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd -AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC -FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi -1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq -jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ -wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj -QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ -WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy -NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC -uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw -IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 -g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN -9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP -BSeOE6Fuwg== ------END CERTIFICATE----- - -# Issuer: CN=Atos TrustedRoot 2011 O=Atos -# Subject: CN=Atos TrustedRoot 2011 O=Atos -# Label: "Atos TrustedRoot 2011" -# Serial: 6643877497813316402 -# MD5 Fingerprint: ae:b9:c4:32:4b:ac:7f:5d:66:cc:77:94:bb:2a:77:56 -# SHA1 Fingerprint: 2b:b1:f5:3e:55:0c:1d:c5:f1:d4:e6:b7:6a:46:4b:55:06:02:ac:21 -# SHA256 Fingerprint: f3:56:be:a2:44:b7:a9:1e:b3:5d:53:ca:9a:d7:86:4a:ce:01:8e:2d:35:d5:f8:f9:6d:df:68:a6:f4:1a:a4:74 ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE -AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG -EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM -FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC -REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp -Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM -VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ -SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ -4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L -cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi -eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV -HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG -A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 -DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j -vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP -DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc -maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D -lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv -KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed ------END CERTIFICATE----- - -# Issuer: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited -# Subject: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited -# Label: "QuoVadis Root CA 1 G3" -# Serial: 687049649626669250736271037606554624078720034195 -# MD5 Fingerprint: a4:bc:5b:3f:fe:37:9a:fa:64:f0:e2:fa:05:3d:0b:ab -# SHA1 Fingerprint: 1b:8e:ea:57:96:29:1a:c9:39:ea:b8:0a:81:1a:73:73:c0:93:79:67 -# SHA256 Fingerprint: 8a:86:6f:d1:b2:76:b5:7e:57:8e:92:1c:65:82:8a:2b:ed:58:e9:f2:f2:88:05:41:34:b7:f1:f4:bf:c9:cc:74 ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL -BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 -MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV -wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe -rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 -68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh -4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp -UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o -abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc -3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G -KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt -hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO -Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt -zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD -ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC -MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 -cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN -qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 -YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv -b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 -8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k -NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj -ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp -q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt -nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD ------END CERTIFICATE----- - -# Issuer: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited -# Subject: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited -# Label: "QuoVadis Root CA 2 G3" -# Serial: 390156079458959257446133169266079962026824725800 -# MD5 Fingerprint: af:0c:86:6e:bf:40:2d:7f:0b:3e:12:50:ba:12:3d:06 -# SHA1 Fingerprint: 09:3c:61:f3:8b:8b:dc:7d:55:df:75:38:02:05:00:e1:25:f5:c8:36 -# SHA256 Fingerprint: 8f:e4:fb:0a:f9:3a:4d:0d:67:db:0b:eb:b2:3e:37:c7:1b:f3:25:dc:bc:dd:24:0e:a0:4d:af:58:b4:7e:18:40 ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL -BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 -MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf -qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW -n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym -c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ -O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 -o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j -IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq -IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz -8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh -vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l -7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG -cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD -ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 -AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC -roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga -W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n -lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE -+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV -csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd -dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg -KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM -HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 -WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M ------END CERTIFICATE----- - -# Issuer: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited -# Subject: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited -# Label: "QuoVadis Root CA 3 G3" -# Serial: 268090761170461462463995952157327242137089239581 -# MD5 Fingerprint: df:7d:b9:ad:54:6f:68:a1:df:89:57:03:97:43:b0:d7 -# SHA1 Fingerprint: 48:12:bd:92:3c:a8:c4:39:06:e7:30:6d:27:96:e6:a4:cf:22:2e:7d -# SHA256 Fingerprint: 88:ef:81:de:20:2e:b0:18:45:2e:43:f8:64:72:5c:ea:5f:bd:1f:c2:d9:d2:05:73:07:09:c5:d8:b8:69:0f:46 ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL -BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc -BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 -MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM -aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR -/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu -FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR -U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c -ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR -FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k -A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw -eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl -sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp -VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q -A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ -ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD -ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px -KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI -FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv -oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg -u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP -0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf -3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl -8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ -DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN -PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ -ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Assured ID Root G2" -# Serial: 15385348160840213938643033620894905419 -# MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d -# SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f -# SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85 ------BEGIN CERTIFICATE----- -MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA -n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc -biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp -EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA -bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu -YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB -AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW -BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI -QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I -0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni -lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 -B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv -ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo -IhNzbM8m9Yop5w== ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Assured ID Root G3" -# Serial: 15459312981008553731928384953135426796 -# MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb -# SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89 -# SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2 ------BEGIN CERTIFICATE----- -MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw -CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu -ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg -RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV -UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu -Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq -hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf -Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q -RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ -BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD -AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY -JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv -6pZjamVFkpUBtA== ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Global Root G2" -# Serial: 4293743540046975378534879503202253541 -# MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44 -# SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4 -# SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f ------BEGIN CERTIFICATE----- -MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH -MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT -MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI -2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx -1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ -q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz -tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ -vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP -BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV -5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY -1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 -NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG -Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 -8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe -pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl -MrY= ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Global Root G3" -# Serial: 7089244469030293291760083333884364146 -# MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca -# SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e -# SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0 ------BEGIN CERTIFICATE----- -MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw -CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu -ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe -Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw -EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x -IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF -K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG -fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO -Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd -BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx -AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ -oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 -sycX ------END CERTIFICATE----- - -# Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com -# Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com -# Label: "DigiCert Trusted Root G4" -# Serial: 7451500558977370777930084869016614236 -# MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49 -# SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4 -# SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88 ------BEGIN CERTIFICATE----- -MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg -RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV -UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu -Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y -ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If -xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV -ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO -DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ -jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ -CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi -EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM -fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY -uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK -chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t -9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB -hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD -ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 -SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd -+SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc -fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa -sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N -cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N -0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie -4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI -r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 -/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm -gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ ------END CERTIFICATE----- - -# Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited -# Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited -# Label: "COMODO RSA Certification Authority" -# Serial: 101909084537582093308941363524873193117 -# MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18 -# SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4 -# SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34 ------BEGIN CERTIFICATE----- -MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB -hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G -A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV -BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 -MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT -EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR -Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR -6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X -pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC -9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV -/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf -Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z -+pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w -qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah -SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC -u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf -Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq -crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E -FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB -/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl -wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM -4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV -2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna -FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ -CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK -boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke -jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL -S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb -QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl -0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB -NVOFBkpdn627G190 ------END CERTIFICATE----- - -# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network -# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network -# Label: "USERTrust RSA Certification Authority" -# Serial: 2645093764781058787591871645665788717 -# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5 -# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e -# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2 ------BEGIN CERTIFICATE----- -MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB -iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl -cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV -BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw -MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV -BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU -aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy -dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B -3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY -tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ -Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 -VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT -79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 -c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT -Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l -c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee -UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE -Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd -BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G -A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF -Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO -VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 -ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs -8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR -iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze -Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ -XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ -qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB -VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB -L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG -jjxDah2nGN59PRbxYvnKkKj9 ------END CERTIFICATE----- - -# Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network -# Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network -# Label: "USERTrust ECC Certification Authority" -# Serial: 123013823720199481456569720443997572134 -# MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1 -# SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0 -# SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a ------BEGIN CERTIFICATE----- -MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL -MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl -eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT -JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx -MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT -Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg -VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm -aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo -I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng -o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G -A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB -zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW -RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 -# Label: "GlobalSign ECC Root CA - R5" -# Serial: 32785792099990507226680698011560947931244 -# MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08 -# SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa -# SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24 ------BEGIN CERTIFICATE----- -MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk -MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH -bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX -DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD -QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu -MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc -8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke -hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI -KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg -515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO -xwy8p2Fp8fc74SrL+SvzZpA3 ------END CERTIFICATE----- - -# Issuer: CN=IdenTrust Commercial Root CA 1 O=IdenTrust -# Subject: CN=IdenTrust Commercial Root CA 1 O=IdenTrust -# Label: "IdenTrust Commercial Root CA 1" -# Serial: 13298821034946342390520003877796839426 -# MD5 Fingerprint: b3:3e:77:73:75:ee:a0:d3:e3:7e:49:63:49:59:bb:c7 -# SHA1 Fingerprint: df:71:7e:aa:4a:d9:4e:c9:55:84:99:60:2d:48:de:5f:bc:f0:3a:25 -# SHA256 Fingerprint: 5d:56:49:9b:e4:d2:e0:8b:cf:ca:d0:8a:3e:38:72:3d:50:50:3b:de:70:69:48:e4:2f:55:60:30:19:e5:28:ae ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK -MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu -VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw -MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw -JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT -3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU -+ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp -S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 -bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi -T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL -vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK -Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK -dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT -c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv -l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N -iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD -ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH -6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt -LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 -nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 -+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK -W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT -AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq -l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG -4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ -mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A -7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H ------END CERTIFICATE----- - -# Issuer: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust -# Subject: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust -# Label: "IdenTrust Public Sector Root CA 1" -# Serial: 13298821034946342390521976156843933698 -# MD5 Fingerprint: 37:06:a5:b0:fc:89:9d:ba:f4:6b:8c:1a:64:cd:d5:ba -# SHA1 Fingerprint: ba:29:41:60:77:98:3f:f4:f3:ef:f2:31:05:3b:2e:ea:6d:4d:45:fd -# SHA256 Fingerprint: 30:d0:89:5a:9a:44:8a:26:20:91:63:55:22:d1:f5:20:10:b5:86:7a:ca:e1:2c:78:ef:95:8f:d4:f4:38:9f:2f ------BEGIN CERTIFICATE----- -MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN -MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu -VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN -MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 -MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 -ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy -RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS -bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF -/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R -3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw -EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy -9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V -GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ -2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV -WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD -W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN -AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj -t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV -DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 -TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G -lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW -mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df -WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 -+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ -tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA -GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv -8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c ------END CERTIFICATE----- - -# Issuer: CN=CFCA EV ROOT O=China Financial Certification Authority -# Subject: CN=CFCA EV ROOT O=China Financial Certification Authority -# Label: "CFCA EV ROOT" -# Serial: 407555286 -# MD5 Fingerprint: 74:e1:b6:ed:26:7a:7a:44:30:33:94:ab:7b:27:81:30 -# SHA1 Fingerprint: e2:b8:29:4b:55:84:ab:6b:58:c2:90:46:6c:ac:3f:b8:39:8f:84:83 -# SHA256 Fingerprint: 5c:c3:d7:8e:4e:1d:5e:45:54:7a:04:e6:87:3e:64:f9:0c:f9:53:6d:1c:cc:2e:f8:00:f3:55:c4:c5:fd:70:fd ------BEGIN CERTIFICATE----- -MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD -TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y -aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx -MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j -aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP -T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 -sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL -TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 -/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp -7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz -EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt -hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP -a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot -aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg -TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV -PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv -cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL -tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd -BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB -ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT -ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL -jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS -ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy -P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 -xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d -Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN -5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe -/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z -AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ -5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su ------END CERTIFICATE----- - -# Issuer: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed -# Subject: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed -# Label: "OISTE WISeKey Global Root GB CA" -# Serial: 157768595616588414422159278966750757568 -# MD5 Fingerprint: a4:eb:b9:61:28:2e:b7:2f:98:b0:35:26:90:99:51:1d -# SHA1 Fingerprint: 0f:f9:40:76:18:d3:d7:6a:4b:98:f0:a8:35:9e:0c:fd:27:ac:cc:ed -# SHA256 Fingerprint: 6b:9c:08:e8:6e:b0:f7:67:cf:ad:65:cd:98:b6:21:49:e5:49:4a:67:f5:84:5e:7b:d1:ed:01:9f:27:b8:6b:d6 ------BEGIN CERTIFICATE----- -MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt -MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg -Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i -YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x -CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG -b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh -bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 -HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx -WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX -1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk -u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P -99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r -M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB -BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh -cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 -gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO -ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf -aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic -Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= ------END CERTIFICATE----- - -# Issuer: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. -# Subject: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. -# Label: "SZAFIR ROOT CA2" -# Serial: 357043034767186914217277344587386743377558296292 -# MD5 Fingerprint: 11:64:c1:89:b0:24:b1:8c:b1:07:7e:89:9e:51:9e:99 -# SHA1 Fingerprint: e2:52:fa:95:3f:ed:db:24:60:bd:6e:28:f3:9c:cc:cf:5e:b3:3f:de -# SHA256 Fingerprint: a1:33:9d:33:28:1a:0b:56:e5:57:d3:d3:2b:1c:e7:f9:36:7e:b0:94:bd:5f:a7:2a:7e:50:04:c8:de:d7:ca:fe ------BEGIN CERTIFICATE----- -MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL -BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 -ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw -NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L -cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg -Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN -QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT -3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw -3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6 -3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5 -BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN -XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF -AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw -8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG -nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP -oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy -d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg -LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== ------END CERTIFICATE----- - -# Issuer: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority -# Subject: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority -# Label: "Certum Trusted Network CA 2" -# Serial: 44979900017204383099463764357512596969 -# MD5 Fingerprint: 6d:46:9e:d9:25:6d:08:23:5b:5e:74:7d:1e:27:db:f2 -# SHA1 Fingerprint: d3:dd:48:3e:2b:bf:4c:05:e8:af:10:f5:fa:76:26:cf:d3:dc:30:92 -# SHA256 Fingerprint: b6:76:f2:ed:da:e8:77:5c:d3:6c:b0:f6:3c:d1:d4:60:39:61:f4:9e:62:65:ba:01:3a:2f:03:07:b6:d0:b8:04 ------BEGIN CERTIFICATE----- -MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB -gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu -QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG -A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz -OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ -VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 -b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA -DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn -0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB -OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE -fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E -Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m -o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i -sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW -OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez -Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS -adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n -3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC -AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ -F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf -CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 -XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm -djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ -WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb -AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq -P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko -b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj -XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P -5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi -DrW5viSP ------END CERTIFICATE----- - -# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority -# Subject: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority -# Label: "Hellenic Academic and Research Institutions RootCA 2015" -# Serial: 0 -# MD5 Fingerprint: ca:ff:e2:db:03:d9:cb:4b:e9:0f:ad:84:fd:7b:18:ce -# SHA1 Fingerprint: 01:0c:06:95:a6:98:19:14:ff:bf:5f:c6:b0:b6:95:ea:29:e9:12:a6 -# SHA256 Fingerprint: a0:40:92:9a:02:ce:53:b4:ac:f4:f2:ff:c6:98:1c:e4:49:6f:75:5e:6d:45:fe:0b:2a:69:2b:cd:52:52:3f:36 ------BEGIN CERTIFICATE----- -MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix -DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k -IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT -N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v -dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG -A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh -ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx -QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 -dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA -4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 -AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 -4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C -ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV -9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD -gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 -Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq -NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko -LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc -Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV -HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd -ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I -XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI -M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot -9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V -Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea -j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh -X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ -l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf -bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 -pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK -e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 -vm9qp/UsQu0yrbYhnr68 ------END CERTIFICATE----- - -# Issuer: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority -# Subject: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority -# Label: "Hellenic Academic and Research Institutions ECC RootCA 2015" -# Serial: 0 -# MD5 Fingerprint: 81:e5:b4:17:eb:c2:f5:e1:4b:0d:41:7b:49:92:fe:ef -# SHA1 Fingerprint: 9f:f1:71:8d:92:d5:9a:f3:7d:74:97:b4:bc:6f:84:68:0b:ba:b6:66 -# SHA256 Fingerprint: 44:b5:45:aa:8a:25:e6:5a:73:ca:15:dc:27:fc:36:d2:4c:1c:b9:95:3a:06:65:39:b1:15:82:dc:48:7b:48:33 ------BEGIN CERTIFICATE----- -MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN -BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl -c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl -bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv -b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ -BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj -YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 -MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 -dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg -QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa -jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi -C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep -lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof -TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR ------END CERTIFICATE----- - -# Issuer: CN=ISRG Root X1 O=Internet Security Research Group -# Subject: CN=ISRG Root X1 O=Internet Security Research Group -# Label: "ISRG Root X1" -# Serial: 172886928669790476064670243504169061120 -# MD5 Fingerprint: 0c:d2:f9:e0:da:17:73:e9:ed:86:4d:a5:e3:70:e7:4e -# SHA1 Fingerprint: ca:bd:2a:79:a1:07:6a:31:f2:1d:25:36:35:cb:03:9d:43:29:a5:e8 -# SHA256 Fingerprint: 96:bc:ec:06:26:49:76:f3:74:60:77:9a:cf:28:c5:a7:cf:e8:a3:c0:aa:e1:1a:8f:fc:ee:05:c0:bd:df:08:c6 ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 -WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu -ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc -h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ -0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U -A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW -T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH -B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC -B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv -KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn -OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn -jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw -qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI -rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq -hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ -3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK -NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 -ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur -TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC -jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc -oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq -4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA -mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d -emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= ------END CERTIFICATE----- - -# Issuer: O=FNMT-RCM OU=AC RAIZ FNMT-RCM -# Subject: O=FNMT-RCM OU=AC RAIZ FNMT-RCM -# Label: "AC RAIZ FNMT-RCM" -# Serial: 485876308206448804701554682760554759 -# MD5 Fingerprint: e2:09:04:b4:d3:bd:d1:a0:14:fd:1a:d2:47:c4:57:1d -# SHA1 Fingerprint: ec:50:35:07:b2:15:c4:95:62:19:e2:a8:9a:5b:42:99:2c:4c:2c:20 -# SHA256 Fingerprint: eb:c5:57:0c:29:01:8c:4d:67:b1:aa:12:7b:af:12:f7:03:b4:61:1e:bc:17:b7:da:b5:57:38:94:17:9b:93:fa ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx -CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ -WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ -BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG -Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ -yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf -BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz -WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF -tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z -374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC -IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL -mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 -wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS -MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 -ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet -UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H -YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 -LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD -nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 -RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM -LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf -77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N -JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm -fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp -6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp -1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B -9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok -RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv -uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= ------END CERTIFICATE----- - -# Issuer: CN=Amazon Root CA 1 O=Amazon -# Subject: CN=Amazon Root CA 1 O=Amazon -# Label: "Amazon Root CA 1" -# Serial: 143266978916655856878034712317230054538369994 -# MD5 Fingerprint: 43:c6:bf:ae:ec:fe:ad:2f:18:c6:88:68:30:fc:c8:e6 -# SHA1 Fingerprint: 8d:a7:f9:65:ec:5e:fc:37:91:0f:1c:6e:59:fd:c1:cc:6a:6e:de:16 -# SHA256 Fingerprint: 8e:cd:e6:88:4f:3d:87:b1:12:5b:a3:1a:c3:fc:b1:3d:70:16:de:7f:57:cc:90:4f:e1:cb:97:c6:ae:98:19:6e ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- - -# Issuer: CN=Amazon Root CA 2 O=Amazon -# Subject: CN=Amazon Root CA 2 O=Amazon -# Label: "Amazon Root CA 2" -# Serial: 143266982885963551818349160658925006970653239 -# MD5 Fingerprint: c8:e5:8d:ce:a8:42:e2:7a:c0:2a:5c:7c:9e:26:bf:66 -# SHA1 Fingerprint: 5a:8c:ef:45:d7:a6:98:59:76:7a:8c:8b:44:96:b5:78:cf:47:4b:1a -# SHA256 Fingerprint: 1b:a5:b2:aa:8c:65:40:1a:82:96:01:18:f8:0b:ec:4f:62:30:4d:83:ce:c4:71:3a:19:c3:9c:01:1e:a4:6d:b4 ------BEGIN CERTIFICATE----- -MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK -gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ -W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg -1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K -8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r -2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me -z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR -8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj -mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz -7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 -+XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI -0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB -Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm -UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 -LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY -+gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS -k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl -7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm -btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl -urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ -fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 -n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE -76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H -9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT -4PsJYGw= ------END CERTIFICATE----- - -# Issuer: CN=Amazon Root CA 3 O=Amazon -# Subject: CN=Amazon Root CA 3 O=Amazon -# Label: "Amazon Root CA 3" -# Serial: 143266986699090766294700635381230934788665930 -# MD5 Fingerprint: a0:d4:ef:0b:f7:b5:d8:49:95:2a:ec:f5:c4:fc:81:87 -# SHA1 Fingerprint: 0d:44:dd:8c:3c:8c:1a:1a:58:75:64:81:e9:0f:2e:2a:ff:b3:d2:6e -# SHA256 Fingerprint: 18:ce:6c:fe:7b:f1:4e:60:b2:e3:47:b8:df:e8:68:cb:31:d0:2e:bb:3a:da:27:15:69:f5:03:43:b4:6d:b3:a4 ------BEGIN CERTIFICATE----- -MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 -MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g -Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG -A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg -Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl -ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j -QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr -ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr -BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM -YyRIHN8wfdVoOw== ------END CERTIFICATE----- - -# Issuer: CN=Amazon Root CA 4 O=Amazon -# Subject: CN=Amazon Root CA 4 O=Amazon -# Label: "Amazon Root CA 4" -# Serial: 143266989758080763974105200630763877849284878 -# MD5 Fingerprint: 89:bc:27:d5:eb:17:8d:06:6a:69:d5:fd:89:47:b4:cd -# SHA1 Fingerprint: f6:10:84:07:d6:f8:bb:67:98:0c:c2:e2:44:c2:eb:ae:1c:ef:63:be -# SHA256 Fingerprint: e3:5d:28:41:9e:d0:20:25:cf:a6:90:38:cd:62:39:62:45:8d:a5:c6:95:fb:de:a3:c2:2b:0b:fb:25:89:70:92 ------BEGIN CERTIFICATE----- -MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 -MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g -Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG -A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg -Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi -9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk -M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB -/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB -MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw -CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW -1KyLa2tJElMzrdfkviT8tQp21KW8EA== ------END CERTIFICATE----- - -# Issuer: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM -# Subject: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM -# Label: "TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1" -# Serial: 1 -# MD5 Fingerprint: dc:00:81:dc:69:2f:3e:2f:b0:3b:f6:3d:5a:91:8e:49 -# SHA1 Fingerprint: 31:43:64:9b:ec:ce:27:ec:ed:3a:3f:0b:8f:0d:e4:e8:91:dd:ee:ca -# SHA256 Fingerprint: 46:ed:c3:68:90:46:d5:3a:45:3f:b3:10:4a:b8:0d:ca:ec:65:8b:26:60:ea:16:29:dd:7e:86:79:90:64:87:16 ------BEGIN CERTIFICATE----- -MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx -GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp -bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w -KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0 -BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy -dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG -EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll -IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU -QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT -TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg -LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7 -a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr -LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr -N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X -YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/ -iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f -AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH -V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL -BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh -AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf -IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4 -lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c -8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf -lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= ------END CERTIFICATE----- - -# Issuer: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. -# Subject: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. -# Label: "GDCA TrustAUTH R5 ROOT" -# Serial: 9009899650740120186 -# MD5 Fingerprint: 63:cc:d9:3d:34:35:5c:6f:53:a3:e2:08:70:48:1f:b4 -# SHA1 Fingerprint: 0f:36:38:5b:81:1a:25:c3:9b:31:4e:83:ca:e9:34:66:70:cc:74:b4 -# SHA256 Fingerprint: bf:ff:8f:d0:44:33:48:7d:6a:8a:a6:0c:1a:29:76:7a:9f:c2:bb:b0:5e:42:0f:71:3a:13:b9:92:89:1d:38:93 ------BEGIN CERTIFICATE----- -MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE -BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ -IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 -MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV -BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w -HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF -AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj -Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj -TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u -KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj -qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm -MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12 -ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP -zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk -L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC -jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA -HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC -AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg -p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm -DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5 -COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry -L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf -JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg -IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io -2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV -09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ -XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq -T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe -MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== ------END CERTIFICATE----- - -# Issuer: CN=SSL.com Root Certification Authority RSA O=SSL Corporation -# Subject: CN=SSL.com Root Certification Authority RSA O=SSL Corporation -# Label: "SSL.com Root Certification Authority RSA" -# Serial: 8875640296558310041 -# MD5 Fingerprint: 86:69:12:c0:70:f1:ec:ac:ac:c2:d5:bc:a5:5b:a1:29 -# SHA1 Fingerprint: b7:ab:33:08:d1:ea:44:77:ba:14:80:12:5a:6f:bd:a9:36:49:0c:bb -# SHA256 Fingerprint: 85:66:6a:56:2e:e0:be:5c:e9:25:c1:d8:89:0a:6f:76:a8:7e:c1:6d:4d:7d:5f:29:ea:74:19:cf:20:12:3b:69 ------BEGIN CERTIFICATE----- -MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE -BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK -DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz -OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv -dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv -bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R -xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX -qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC -C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3 -6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh -/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF -YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E -JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc -US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8 -ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm -+Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi -M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV -HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G -A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV -cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc -Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs -PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/ -q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0 -cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr -a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I -H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y -K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu -nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf -oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY -Ic2wBlX7Jz9TkHCpBB5XJ7k= ------END CERTIFICATE----- - -# Issuer: CN=SSL.com Root Certification Authority ECC O=SSL Corporation -# Subject: CN=SSL.com Root Certification Authority ECC O=SSL Corporation -# Label: "SSL.com Root Certification Authority ECC" -# Serial: 8495723813297216424 -# MD5 Fingerprint: 2e:da:e4:39:7f:9c:8f:37:d1:70:9f:26:17:51:3a:8e -# SHA1 Fingerprint: c3:19:7c:39:24:e6:54:af:1b:c4:ab:20:95:7a:e2:c3:0e:13:02:6a -# SHA256 Fingerprint: 34:17:bb:06:cc:60:07:da:1b:96:1c:92:0b:8a:b4:ce:3f:ad:82:0e:4a:a3:0b:9a:cb:c4:a7:4e:bd:ce:bc:65 ------BEGIN CERTIFICATE----- -MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC -VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T -U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 -aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz -WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 -b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS -b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB -BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI -7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg -CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud -EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD -VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T -kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ -gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl ------END CERTIFICATE----- - -# Issuer: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation -# Subject: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation -# Label: "SSL.com EV Root Certification Authority RSA R2" -# Serial: 6248227494352943350 -# MD5 Fingerprint: e1:1e:31:58:1a:ae:54:53:02:f6:17:6a:11:7b:4d:95 -# SHA1 Fingerprint: 74:3a:f0:52:9b:d0:32:a0:f4:4a:83:cd:d4:ba:a9:7b:7c:2e:c4:9a -# SHA256 Fingerprint: 2e:7b:f1:6c:c2:24:85:a7:bb:e2:aa:86:96:75:07:61:b0:ae:39:be:3b:2f:e9:d0:cc:6d:4e:f7:34:91:42:5c ------BEGIN CERTIFICATE----- -MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV -BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE -CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy -dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy -MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G -A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD -DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq -M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf -OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa -4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9 -HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR -aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA -b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ -Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV -PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO -pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu -UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY -MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV -HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4 -9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW -s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5 -Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg -cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM -79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz -/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt -ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm -Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK -QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ -w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi -S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 -mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== ------END CERTIFICATE----- - -# Issuer: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation -# Subject: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation -# Label: "SSL.com EV Root Certification Authority ECC" -# Serial: 3182246526754555285 -# MD5 Fingerprint: 59:53:22:65:83:42:01:54:c0:ce:42:b9:5a:7c:f2:90 -# SHA1 Fingerprint: 4c:dd:51:a3:d1:f5:20:32:14:b0:c6:c5:32:23:03:91:c7:46:42:6d -# SHA256 Fingerprint: 22:a2:c1:f7:bd:ed:70:4c:c1:e7:01:b5:f4:08:c3:10:88:0f:e9:56:b5:de:2a:4a:44:f9:9c:87:3a:25:a7:c8 ------BEGIN CERTIFICATE----- -MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC -VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T -U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx -NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv -dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv -bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49 -AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA -VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku -WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP -MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX -5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ -ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg -h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 -# Label: "GlobalSign Root CA - R6" -# Serial: 1417766617973444989252670301619537 -# MD5 Fingerprint: 4f:dd:07:e4:d4:22:64:39:1e:0c:37:42:ea:d1:c6:ae -# SHA1 Fingerprint: 80:94:64:0e:b5:a7:a1:ca:11:9c:1f:dd:d5:9f:81:02:63:a7:fb:d1 -# SHA256 Fingerprint: 2c:ab:ea:fe:37:d0:6c:a2:2a:ba:73:91:c0:03:3d:25:98:29:52:c4:53:64:73:49:76:3a:3a:b5:ad:6c:cf:69 ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg -MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh -bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx -MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET -MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ -KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI -xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k -ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD -aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw -LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw -1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX -k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 -SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h -bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n -WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY -rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce -MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD -AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu -bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN -nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt -Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 -55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj -vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf -cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz -oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp -nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs -pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v -JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R -8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 -5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= ------END CERTIFICATE----- - -# Issuer: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed -# Subject: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed -# Label: "OISTE WISeKey Global Root GC CA" -# Serial: 44084345621038548146064804565436152554 -# MD5 Fingerprint: a9:d6:b9:2d:2f:93:64:f8:a5:69:ca:91:e9:68:07:23 -# SHA1 Fingerprint: e0:11:84:5e:34:de:be:88:81:b9:9c:f6:16:26:d1:96:1f:c3:b9:31 -# SHA256 Fingerprint: 85:60:f9:1c:36:24:da:ba:95:70:b5:fe:a0:db:e3:6f:f1:1a:83:23:be:94:86:85:4f:b3:f3:4a:55:71:19:8d ------BEGIN CERTIFICATE----- -MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw -CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 -bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg -Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ -BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu -ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS -b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni -eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W -p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T -rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV -57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg -Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 ------END CERTIFICATE----- - -# Issuer: CN=UCA Global G2 Root O=UniTrust -# Subject: CN=UCA Global G2 Root O=UniTrust -# Label: "UCA Global G2 Root" -# Serial: 124779693093741543919145257850076631279 -# MD5 Fingerprint: 80:fe:f0:c4:4a:f0:5c:62:32:9f:1c:ba:78:a9:50:f8 -# SHA1 Fingerprint: 28:f9:78:16:19:7a:ff:18:25:18:aa:44:fe:c1:a0:ce:5c:b6:4c:8a -# SHA256 Fingerprint: 9b:ea:11:c9:76:fe:01:47:64:c1:be:56:a6:f9:14:b5:a5:60:31:7a:bd:99:88:39:33:82:e5:16:1a:a0:49:3c ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9 -MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH -bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x -CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds -b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr -b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9 -kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm -VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R -VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc -C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj -tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY -D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv -j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl -NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6 -iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP -O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/ -BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV -ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj -L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 -1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl -1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU -b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV -PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj -y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb -EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg -DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI -+Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy -YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX -UB+K+wb1whnw0A== ------END CERTIFICATE----- - -# Issuer: CN=UCA Extended Validation Root O=UniTrust -# Subject: CN=UCA Extended Validation Root O=UniTrust -# Label: "UCA Extended Validation Root" -# Serial: 106100277556486529736699587978573607008 -# MD5 Fingerprint: a1:f3:5f:43:c6:34:9b:da:bf:8c:7e:05:53:ad:96:e2 -# SHA1 Fingerprint: a3:a1:b0:6f:24:61:23:4a:e3:36:a5:c2:37:fc:a6:ff:dd:f0:d7:3a -# SHA256 Fingerprint: d4:3a:f9:b3:54:73:75:5c:96:84:fc:06:d7:d8:cb:70:ee:5c:28:e7:73:fb:29:4e:b4:1e:e7:17:22:92:4d:24 ------BEGIN CERTIFICATE----- -MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH -MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF -eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx -MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV -BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog -D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS -sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop -O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk -sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi -c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj -VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz -KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/ -TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G -sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs -1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD -fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T -AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN -l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR -ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ -VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5 -c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp -4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s -t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj -2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO -vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C -xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx -cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM -fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax ------END CERTIFICATE----- - -# Issuer: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 -# Subject: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 -# Label: "Certigna Root CA" -# Serial: 269714418870597844693661054334862075617 -# MD5 Fingerprint: 0e:5c:30:62:27:eb:5b:bc:d7:ae:62:ba:e9:d5:df:77 -# SHA1 Fingerprint: 2d:0d:52:14:ff:9e:ad:99:24:01:74:20:47:6e:6c:85:27:27:f5:43 -# SHA256 Fingerprint: d4:8d:3d:23:ee:db:50:a4:59:e5:51:97:60:1c:27:77:4b:9d:7b:18:c9:4d:5a:05:95:11:a1:02:50:b9:31:68 ------BEGIN CERTIFICATE----- -MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw -WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw -MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x -MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD -VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX -BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw -ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO -ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M -CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu -I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm -TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh -C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf -ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz -IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT -Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k -JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5 -hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB -GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE -FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of -1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov -L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo -dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr -aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq -hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L -6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG -HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6 -0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB -lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi -o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1 -gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v -faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63 -Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh -jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw -3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= ------END CERTIFICATE----- - -# Issuer: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI -# Subject: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI -# Label: "emSign Root CA - G1" -# Serial: 235931866688319308814040 -# MD5 Fingerprint: 9c:42:84:57:dd:cb:0b:a7:2e:95:ad:b6:f3:da:bc:ac -# SHA1 Fingerprint: 8a:c7:ad:8f:73:ac:4e:c1:b5:75:4d:a5:40:f4:fc:cf:7c:b5:8e:8c -# SHA256 Fingerprint: 40:f6:af:03:46:a9:9a:a1:cd:1d:55:5a:4e:9c:ce:62:c7:f9:63:46:03:ee:40:66:15:83:3d:c8:c8:d0:03:67 ------BEGIN CERTIFICATE----- -MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD -VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU -ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH -MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO -MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv -Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz -f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO -8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq -d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM -tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt -Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB -o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD -AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x -PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM -wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d -GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH -6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby -RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx -iN66zB+Afko= ------END CERTIFICATE----- - -# Issuer: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI -# Subject: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI -# Label: "emSign ECC Root CA - G3" -# Serial: 287880440101571086945156 -# MD5 Fingerprint: ce:0b:72:d1:9f:88:8e:d0:50:03:e8:e3:b8:8b:67:40 -# SHA1 Fingerprint: 30:43:fa:4f:f2:57:dc:a0:c3:80:ee:2e:58:ea:78:b2:3f:e6:bb:c1 -# SHA256 Fingerprint: 86:a1:ec:ba:08:9c:4a:8d:3b:be:27:34:c6:12:ba:34:1d:81:3e:04:3c:f9:e8:a8:62:cd:5c:57:a3:6b:be:6b ------BEGIN CERTIFICATE----- -MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG -EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo -bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g -RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ -TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s -b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw -djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0 -WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS -fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB -zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq -hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB -CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD -+JbNR6iC8hZVdyR+EhCVBCyj ------END CERTIFICATE----- - -# Issuer: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI -# Subject: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI -# Label: "emSign Root CA - C1" -# Serial: 825510296613316004955058 -# MD5 Fingerprint: d8:e3:5d:01:21:fa:78:5a:b0:df:ba:d2:ee:2a:5f:68 -# SHA1 Fingerprint: e7:2e:f1:df:fc:b2:09:28:cf:5d:d4:d5:67:37:b1:51:cb:86:4f:01 -# SHA256 Fingerprint: 12:56:09:aa:30:1d:a0:a2:49:b9:7a:82:39:cb:6a:34:21:6f:44:dc:ac:9f:39:54:b1:42:92:f2:e8:c8:60:8f ------BEGIN CERTIFICATE----- -MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG -A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg -SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw -MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln -biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v -dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ -BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ -HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH -3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH -GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c -xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1 -aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq -TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL -BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87 -/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4 -kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG -YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT -+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo -WXzhriKi4gp6D/piq1JM4fHfyr6DDUI= ------END CERTIFICATE----- - -# Issuer: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI -# Subject: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI -# Label: "emSign ECC Root CA - C3" -# Serial: 582948710642506000014504 -# MD5 Fingerprint: 3e:53:b3:a3:81:ee:d7:10:f8:d3:b0:1d:17:92:f5:d5 -# SHA1 Fingerprint: b6:af:43:c2:9b:81:53:7d:f6:ef:6b:c3:1f:1f:60:15:0c:ee:48:66 -# SHA256 Fingerprint: bc:4d:80:9b:15:18:9d:78:db:3e:1d:8c:f4:f9:72:6a:79:5d:a1:64:3c:a5:f1:35:8e:1d:db:0e:dc:0d:7e:b3 ------BEGIN CERTIFICATE----- -MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG -EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx -IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw -MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln -biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND -IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci -MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti -sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O -BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB -Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c -3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J -0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== ------END CERTIFICATE----- - -# Issuer: CN=Hongkong Post Root CA 3 O=Hongkong Post -# Subject: CN=Hongkong Post Root CA 3 O=Hongkong Post -# Label: "Hongkong Post Root CA 3" -# Serial: 46170865288971385588281144162979347873371282084 -# MD5 Fingerprint: 11:fc:9f:bd:73:30:02:8a:fd:3f:f3:58:b9:cb:20:f0 -# SHA1 Fingerprint: 58:a2:d0:ec:20:52:81:5b:c1:f3:f8:64:02:24:4e:c2:8e:02:4b:02 -# SHA256 Fingerprint: 5a:2f:c0:3f:0c:83:b0:90:bb:fa:40:60:4b:09:88:44:6c:76:36:18:3d:f9:84:6e:17:10:1a:44:7f:b8:ef:d6 ------BEGIN CERTIFICATE----- -MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQEL -BQAwbzELMAkGA1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJ -SG9uZyBLb25nMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25n -a29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2MDMwMjI5NDZaFw00MjA2MDMwMjI5 -NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxEjAQBgNVBAcT -CUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMXSG9u -Z2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQCziNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFO -dem1p+/l6TWZ5Mwc50tfjTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mI -VoBc+L0sPOFMV4i707mV78vH9toxdCim5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV -9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOesL4jpNrcyCse2m5FHomY -2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj0mRiikKY -vLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+Tt -bNe/JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZb -x39ri1UbSsUgYT2uy1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+ -l2oBlKN8W4UdKjk60FSh0Tlxnf0h+bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YK -TE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsGxVd7GYYKecsAyVKvQv83j+Gj -Hno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwIDAQABo2MwYTAP -BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e -i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEw -DQYJKoZIhvcNAQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG -7BJ8dNVI0lkUmcDrudHr9EgwW62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCk -MpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWldy8joRTnU+kLBEUx3XZL7av9YROXr -gZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov+BS5gLNdTaqX4fnk -GMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDceqFS -3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJm -Ozj/2ZQw9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+ -l6mc1X5VTMbeRRAc6uk7nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6c -JfTzPV4e0hz5sy229zdcxsshTrD3mUcYhcErulWuBurQB7Lcq9CClnXO0lD+mefP -L5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB60PZ2Pierc+xYw5F9KBa -LJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEG -mpv0 ------END CERTIFICATE----- - -# Issuer: CN=Microsoft ECC Root Certificate Authority 2017 O=Microsoft Corporation -# Subject: CN=Microsoft ECC Root Certificate Authority 2017 O=Microsoft Corporation -# Label: "Microsoft ECC Root Certificate Authority 2017" -# Serial: 136839042543790627607696632466672567020 -# MD5 Fingerprint: dd:a1:03:e6:4a:93:10:d1:bf:f0:19:42:cb:fe:ed:67 -# SHA1 Fingerprint: 99:9a:64:c3:7f:f4:7d:9f:ab:95:f1:47:69:89:14:60:ee:c4:c3:c5 -# SHA256 Fingerprint: 35:8d:f3:9d:76:4a:f9:e1:b7:66:e9:c9:72:df:35:2e:e1:5c:fa:c2:27:af:6a:d1:d7:0e:8e:4a:6e:dc:ba:02 ------BEGIN CERTIFICATE----- -MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQsw -CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYD -VQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw -MTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4MjMxNjA0WjBlMQswCQYDVQQGEwJV -UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNy -b3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQBgcq -hkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZR -ogPZnZH6thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYb -hGBKia/teQ87zvH2RPUBeMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E -BTADAQH/MB0GA1UdDgQWBBTIy5lycFIM+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3 -FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlfXu5gKcs68tvWMoQZP3zV -L8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaReNtUjGUB -iudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= ------END CERTIFICATE----- - -# Issuer: CN=Microsoft RSA Root Certificate Authority 2017 O=Microsoft Corporation -# Subject: CN=Microsoft RSA Root Certificate Authority 2017 O=Microsoft Corporation -# Label: "Microsoft RSA Root Certificate Authority 2017" -# Serial: 40975477897264996090493496164228220339 -# MD5 Fingerprint: 10:ff:00:ff:cf:c9:f8:c7:7a:c0:ee:35:8e:c9:0f:47 -# SHA1 Fingerprint: 73:a5:e6:4a:3b:ff:83:16:ff:0e:dc:cc:61:8a:90:6e:4e:ae:4d:74 -# SHA256 Fingerprint: c7:41:f7:0f:4b:2a:8d:88:bf:2e:71:c1:41:22:ef:53:ef:10:eb:a0:cf:a5:e6:4c:fa:20:f4:18:85:30:73:e0 ------BEGIN CERTIFICATE----- -MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl -MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw -NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 -IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIwNzE4MjMwMDIzWjBlMQswCQYDVQQG -EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1N -aWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZ -Nt9GkMml7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0 -ZdDMbRnMlfl7rEqUrQ7eS0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1 -HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw71VdyvD/IybLeS2v4I2wDwAW9lcfNcztm -gGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+dkC0zVJhUXAoP8XFWvLJ -jEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49FyGcohJUc -aDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaG -YaRSMLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6 -W6IYZVcSn2i51BVrlMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4K -UGsTuqwPN1q3ErWQgR5WrlcihtnJ0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH -+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJClTUFLkqqNfs+avNJVgyeY+Q -W5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/ -BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC -NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZC -LgLNFgVZJ8og6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OC -gMNPOsduET/m4xaRhPtthH80dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6 -tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk+ONVFT24bcMKpBLBaYVu32TxU5nh -SnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex/2kskZGT4d9Mozd2 -TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDyAmH3 -pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGR -xpl/j8nWZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiApp -GWSZI1b7rCoucL5mxAyE7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9 -dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN -AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB -RA+GsCyRxj3qrg+E ------END CERTIFICATE----- - -# Issuer: CN=e-Szigno Root CA 2017 O=Microsec Ltd. -# Subject: CN=e-Szigno Root CA 2017 O=Microsec Ltd. -# Label: "e-Szigno Root CA 2017" -# Serial: 411379200276854331539784714 -# MD5 Fingerprint: de:1f:f6:9e:84:ae:a7:b4:21:ce:1e:58:7d:d1:84:98 -# SHA1 Fingerprint: 89:d4:83:03:4f:9e:9a:48:80:5f:72:37:d4:a9:a6:ef:cb:7c:1f:d1 -# SHA256 Fingerprint: be:b0:0b:30:83:9b:9b:c3:2c:32:e4:44:79:05:95:06:41:f2:64:21:b1:5e:d0:89:19:8b:51:8a:e2:ea:1b:99 ------BEGIN CERTIFICATE----- -MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNV -BAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRk -LjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJv -b3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZaFw00MjA4MjIxMjA3MDZaMHExCzAJ -BgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMg -THRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25v -IFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtv -xie+RJCxs1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+H -Wyx7xf58etqjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G -A1UdDgQWBBSHERUI0arBeAyxr87GyZDvvzAEwDAfBgNVHSMEGDAWgBSHERUI0arB -eAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEAtVfd14pVCzbhhkT61Nlo -jbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxOsvxyqltZ -+efcMQ== ------END CERTIFICATE----- - -# Issuer: O=CERTSIGN SA OU=certSIGN ROOT CA G2 -# Subject: O=CERTSIGN SA OU=certSIGN ROOT CA G2 -# Label: "certSIGN Root CA G2" -# Serial: 313609486401300475190 -# MD5 Fingerprint: 8c:f1:75:8a:c6:19:cf:94:b7:f7:65:20:87:c3:97:c7 -# SHA1 Fingerprint: 26:f9:93:b4:ed:3d:28:27:b0:b9:4b:a7:e9:15:1d:a3:8d:92:e5:32 -# SHA256 Fingerprint: 65:7c:fe:2f:a7:3f:aa:38:46:25:71:f3:32:a2:36:3a:46:fc:e7:02:09:51:71:07:02:cd:fb:b6:ee:da:33:05 ------BEGIN CERTIFICATE----- -MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV -BAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04g -Uk9PVCBDQSBHMjAeFw0xNzAyMDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJ -BgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJ -R04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDF -dRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05N0Iw -vlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZ -uIt4ImfkabBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhp -n+Sc8CnTXPnGFiWeI8MgwT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKs -cpc/I1mbySKEwQdPzH/iV8oScLumZfNpdWO9lfsbl83kqK/20U6o2YpxJM02PbyW -xPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91QqhngLjYl/rNUssuHLoPj1P -rCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732jcZZroiF -DsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fx -DTvf95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgy -LcsUDFDYg2WD7rlcz8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6C -eWRgKRM+o/1Pcmqr4tTluCRVLERLiohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSCIS1mxteg4BXrzkwJ -d8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOBywaK8SJJ6ejq -kX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC -b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQl -qiCA2ClV9+BB/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0 -OJD7uNGzcgbJceaBxXntC6Z58hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+c -NywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5BiKDUyUM/FHE5r7iOZULJK2v0ZXk -ltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklWatKcsWMy5WHgUyIO -pwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tUSxfj -03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZk -PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE -1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX -QRBdJ3NghVdJIgc= ------END CERTIFICATE----- - -# Issuer: CN=NAVER Global Root Certification Authority O=NAVER BUSINESS PLATFORM Corp. -# Subject: CN=NAVER Global Root Certification Authority O=NAVER BUSINESS PLATFORM Corp. -# Label: "NAVER Global Root Certification Authority" -# Serial: 9013692873798656336226253319739695165984492813 -# MD5 Fingerprint: c8:7e:41:f6:25:3b:f5:09:b3:17:e8:46:3d:bf:d0:9b -# SHA1 Fingerprint: 8f:6b:f2:a9:27:4a:da:14:a0:c4:f4:8e:61:27:f9:c0:1e:78:5d:d1 -# SHA256 Fingerprint: 88:f4:38:dc:f8:ff:d1:fa:8f:42:91:15:ff:e5:f8:2a:e1:e0:6e:0c:70:c3:75:fa:ad:71:7b:34:a4:9e:72:65 ------BEGIN CERTIFICATE----- -MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEM -BQAwaTELMAkGA1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRG -T1JNIENvcnAuMTIwMAYDVQQDDClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0 -aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4NDJaFw0zNzA4MTgyMzU5NTlaMGkx -CzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVTUyBQTEFURk9STSBD -b3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlvbiBB -dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVA -iQqrDZBbUGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH -38dq6SZeWYp34+hInDEW+j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lE -HoSTGEq0n+USZGnQJoViAbbJAh2+g1G7XNr4rRVqmfeSVPc0W+m/6imBEtRTkZaz -kVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2aacp+yPOiNgSnABIqKYP -szuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4Yb8Obtoq -vC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHf -nZ3zVHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaG -YQ5fG8Ir4ozVu53BA0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo -0es+nPxdGoMuK8u180SdOqcXYZaicdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3a -CJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejyYhbLgGvtPe31HzClrkvJE+2K -AQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNVHQ4EFgQU0p+I -36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB -Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoN -qo0hV4/GPnrK21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatj -cu3cvuzHV+YwIHHW1xDBE1UBjCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm -+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bxhYTeodoS76TiEJd6eN4MUZeoIUCL -hr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTgE34h5prCy8VCZLQe -lHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTHD8z7 -p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8 -piKCk5XQA76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLR -LBT/DShycpWbXgnbiUSYqqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX -5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oGI/hGoiLtk/bdmuYqh7GYVPEi92tF4+KO -dh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmgkpzNNIaRkPpkUZ3+/uul -9XXeifdy ------END CERTIFICATE----- - -# Issuer: CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS O=FNMT-RCM OU=Ceres -# Subject: CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS O=FNMT-RCM OU=Ceres -# Label: "AC RAIZ FNMT-RCM SERVIDORES SEGUROS" -# Serial: 131542671362353147877283741781055151509 -# MD5 Fingerprint: 19:36:9c:52:03:2f:d2:d1:bb:23:cc:dd:1e:12:55:bb -# SHA1 Fingerprint: 62:ff:d9:9e:c0:65:0d:03:ce:75:93:d2:ed:3f:2d:32:c9:e3:e5:4a -# SHA256 Fingerprint: 55:41:53:b1:3d:2c:f9:dd:b7:53:bf:be:1a:4e:0a:e0:8d:0a:a4:18:70:58:fe:60:a2:b8:62:b2:e4:b8:7b:cb ------BEGIN CERTIFICATE----- -MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw -CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw -FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S -Q00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4MTIyMDA5MzczM1oXDTQzMTIyMDA5 -MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQtUkNNMQ4wDAYDVQQL -DAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNBQyBS -QUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuB -BAAiA2IABPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LH -sbI6GA60XYyzZl2hNPk2LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oK -Um8BA06Oi6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD -VR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqGSM49BAMDA2kAMGYCMQCu -SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC -MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy -v+c= ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign Root R46 O=GlobalSign nv-sa -# Subject: CN=GlobalSign Root R46 O=GlobalSign nv-sa -# Label: "GlobalSign Root R46" -# Serial: 1552617688466950547958867513931858518042577 -# MD5 Fingerprint: c4:14:30:e4:fa:66:43:94:2a:6a:1b:24:5f:19:d0:ef -# SHA1 Fingerprint: 53:a2:b0:4b:ca:6b:d6:45:e6:39:8a:8e:c4:0d:d2:bf:77:c3:a2:90 -# SHA256 Fingerprint: 4f:a3:12:6d:8d:3a:11:d1:c4:85:5a:4f:80:7c:ba:d6:cf:91:9d:3a:5a:88:b0:3b:ea:2c:63:72:d9:3c:40:c9 ------BEGIN CERTIFICATE----- -MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA -MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD -VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy -MDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt -c2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ -OaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG -vGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud -316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo -0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE -y132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF -zXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE -+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN -I/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs -x2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa -ByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC -4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -HQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4 -7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg -JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti -2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk -pnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF -FRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt -rWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk -ZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5 -u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP -4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6 -N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3 -vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6 ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign Root E46 O=GlobalSign nv-sa -# Subject: CN=GlobalSign Root E46 O=GlobalSign nv-sa -# Label: "GlobalSign Root E46" -# Serial: 1552617690338932563915843282459653771421763 -# MD5 Fingerprint: b5:b8:66:ed:de:08:83:e3:c9:e2:01:34:06:ac:51:6f -# SHA1 Fingerprint: 39:b4:6c:d5:fe:80:06:eb:e2:2f:4a:bb:08:33:a0:af:db:b9:dd:84 -# SHA256 Fingerprint: cb:b9:c4:4d:84:b8:04:3e:10:50:ea:31:a6:9f:51:49:55:d7:bf:d2:e2:c6:b4:93:01:01:9a:d6:1d:9f:50:58 ------BEGIN CERTIFICATE----- -MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx -CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD -ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw -MDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex -HDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA -IgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkBjtjq -R+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGdd -yXqBPCCjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud -DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ -7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8 -+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A= ------END CERTIFICATE----- - -# Issuer: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz -# Subject: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz -# Label: "ANF Secure Server Root CA" -# Serial: 996390341000653745 -# MD5 Fingerprint: 26:a6:44:5a:d9:af:4e:2f:b2:1d:b6:65:b0:4e:e8:96 -# SHA1 Fingerprint: 5b:6e:68:d0:cc:15:b6:a0:5f:1e:c1:5f:ae:02:fc:6b:2f:5d:6f:74 -# SHA256 Fingerprint: fb:8f:ec:75:91:69:b9:10:6b:1e:51:16:44:c6:18:c5:13:04:37:3f:6c:06:43:08:8d:8b:ef:fd:1b:99:75:99 ------BEGIN CERTIFICATE----- -MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNV -BAUTCUc2MzI4NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlk -YWQgZGUgQ2VydGlmaWNhY2lvbjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNV -BAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3QgQ0EwHhcNMTkwOTA0MTAwMDM4WhcN -MzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEwMQswCQYDVQQGEwJF -UzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQwEgYD -VQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9v -dCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCj -cqQZAZ2cC4Ffc0m6p6zzBE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9q -yGFOtibBTI3/TO80sh9l2Ll49a2pcbnvT1gdpd50IJeh7WhM3pIXS7yr/2WanvtH -2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcvB2VSAKduyK9o7PQUlrZX -H1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXsezx76W0OL -zc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyR -p1RMVwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQz -W7i1o0TJrH93PB0j7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/ -SiOL9V8BY9KHcyi1Swr1+KuCLH5zJTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJn -LNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe8TZBAQIvfXOn3kLMTOmJDVb3 -n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVOHj1tyRRM4y5B -u8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj -o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAO -BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC -AgEATh65isagmD9uw2nAalxJUqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L -9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzxj6ptBZNscsdW699QIyjlRRA96Gej -rw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDtdD+4E5UGUcjohybK -pFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM5gf0 -vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjq -OknkJjCb5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ -/zo1PqVUSlJZS2Db7v54EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ9 -2zg/LFis6ELhDtjTO0wugumDLmsx2d1Hhk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI -+PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGyg77FGr8H6lnco4g175x2 -MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3r5+qPeoo -tt7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw= ------END CERTIFICATE----- - -# Issuer: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority -# Subject: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority -# Label: "Certum EC-384 CA" -# Serial: 160250656287871593594747141429395092468 -# MD5 Fingerprint: b6:65:b3:96:60:97:12:a1:ec:4e:e1:3d:a3:c6:c9:f1 -# SHA1 Fingerprint: f3:3e:78:3c:ac:df:f4:a2:cc:ac:67:55:69:56:d7:e5:16:3c:e1:ed -# SHA256 Fingerprint: 6b:32:80:85:62:53:18:aa:50:d1:73:c9:8d:8b:da:09:d5:7e:27:41:3d:11:4c:f7:87:a0:f5:d0:6c:03:0c:f6 ------BEGIN CERTIFICATE----- -MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw -CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw -JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT -EENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2MDcyNDU0WhcNNDMwMzI2MDcyNDU0 -WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBT -LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAX -BgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATE -KI6rGFtqvm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7Tm -Fy8as10CW4kjPMIRBSqniBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68Kj -QjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI0GZnQkdjrzife81r1HfS+8 -EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J -UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn -nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= ------END CERTIFICATE----- - -# Issuer: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority -# Subject: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority -# Label: "Certum Trusted Root CA" -# Serial: 40870380103424195783807378461123655149 -# MD5 Fingerprint: 51:e1:c2:e7:fe:4c:84:af:59:0e:2f:f4:54:6f:ea:29 -# SHA1 Fingerprint: c8:83:44:c0:18:ae:9f:cc:f1:87:b7:8f:22:d1:c5:d7:45:84:ba:e5 -# SHA256 Fingerprint: fe:76:96:57:38:55:77:3e:37:a9:5e:7a:d4:d9:cc:96:c3:01:57:c1:5d:31:76:5b:a9:b1:57:04:e1:ae:78:fd ------BEGIN CERTIFICATE----- -MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6 -MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEu -MScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNV -BAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwHhcNMTgwMzE2MTIxMDEzWhcNNDMw -MzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEg -U3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRo -b3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZ -n0EGze2jusDbCSzBfN8pfktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/q -p1x4EaTByIVcJdPTsuclzxFUl6s1wB52HO8AU5853BSlLCIls3Jy/I2z5T4IHhQq -NwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2fJmItdUDmj0VDT06qKhF -8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGtg/BKEiJ3 -HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGa -mqi4NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi -7VdNIuJGmj8PkTQkfVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSF -ytKAQd8FqKPVhJBPC/PgP5sZ0jeJP/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0P -qafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSYnjYJdmZm/Bo/6khUHL4wvYBQ -v3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHKHRzQ+8S1h9E6 -Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1 -vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQAD -ggIBAEii1QALLtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4 -WxmB82M+w85bj/UvXgF2Ez8sALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvo -zMrnadyHncI013nR03e4qllY/p0m+jiGPp2Kh2RX5Rc64vmNueMzeMGQ2Ljdt4NR -5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8CYyqOhNf6DR5UMEQ -GfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA4kZf -5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq -0Uc9NneoWWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7D -P78v3DSk+yshzWePS/Tj6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTM -qJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmTOPQD8rv7gmsHINFSH5pkAnuYZttcTVoP -0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZckbxJF0WddCajJFdr60qZf -E2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb ------END CERTIFICATE----- - -# Issuer: CN=TunTrust Root CA O=Agence Nationale de Certification Electronique -# Subject: CN=TunTrust Root CA O=Agence Nationale de Certification Electronique -# Label: "TunTrust Root CA" -# Serial: 108534058042236574382096126452369648152337120275 -# MD5 Fingerprint: 85:13:b9:90:5b:36:5c:b6:5e:b8:5a:f8:e0:31:57:b4 -# SHA1 Fingerprint: cf:e9:70:84:0f:e0:73:0f:9d:f6:0c:7f:2c:4b:ee:20:46:34:9c:bb -# SHA256 Fingerprint: 2e:44:10:2a:b5:8c:b8:54:19:45:1c:8e:19:d9:ac:f3:66:2c:af:bc:61:4b:6a:53:96:0a:30:f7:d0:e2:eb:41 ------BEGIN CERTIFICATE----- -MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQEL -BQAwYTELMAkGA1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUg -Q2VydGlmaWNhdGlvbiBFbGVjdHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJv -b3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQwNDI2MDg1NzU2WjBhMQswCQYDVQQG -EwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBDZXJ0aWZpY2F0aW9u -IEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIwDQYJ -KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZ -n56eY+hz2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd -2JQDoOw05TDENX37Jk0bbjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgF -VwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZ -GoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAdgjH8KcwAWJeRTIAAHDOF -li/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViWVSHbhlnU -r8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2 -eY8fTpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIb -MlEsPvLfe/ZdeikZjuXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISg -jwBUFfyRbVinljvrS5YnzWuioYasDXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB -7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwSVXAkPcvCFDVDXSdOvsC9qnyW -5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI04Y+oXNZtPdE -ITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0 -90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+z -xiD2BkewhpMl0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYu -QEkHDVneixCwSQXi/5E/S7fdAo74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4 -FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRYYdZ2vyJ/0Adqp2RT8JeNnYA/u8EH -22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJpadbGNjHh/PqAulxP -xOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65xxBzn -dFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5 -Xc0yGYuPjCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7b -nV2UqL1g52KAdoGDDIzMMEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQ -CvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9zZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZH -u/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3rAZ3r2OvEhJn7wAzMMujj -d9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= ------END CERTIFICATE----- - -# Issuer: CN=HARICA TLS RSA Root CA 2021 O=Hellenic Academic and Research Institutions CA -# Subject: CN=HARICA TLS RSA Root CA 2021 O=Hellenic Academic and Research Institutions CA -# Label: "HARICA TLS RSA Root CA 2021" -# Serial: 76817823531813593706434026085292783742 -# MD5 Fingerprint: 65:47:9b:58:86:dd:2c:f0:fc:a2:84:1f:1e:96:c4:91 -# SHA1 Fingerprint: 02:2d:05:82:fa:88:ce:14:0c:06:79:de:7f:14:10:e9:45:d7:a5:6d -# SHA256 Fingerprint: d9:5d:0e:8e:da:79:52:5b:f9:be:b1:1b:14:d2:10:0d:32:94:98:5f:0c:62:d9:fa:bd:9c:d9:99:ec:cb:7b:1d ------BEGIN CERTIFICATE----- -MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBs -MQswCQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl -c2VhcmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0Eg -Um9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUzOFoXDTQ1MDIxMzEwNTUzN1owbDEL -MAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl -YXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNBIFJv -b3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569l -mwVnlskNJLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE -4VGC/6zStGndLuwRo0Xua2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uv -a9of08WRiFukiZLRgeaMOVig1mlDqa2YUlhu2wr7a89o+uOkXjpFc5gH6l8Cct4M -pbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K5FrZx40d/JiZ+yykgmvw -Kh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEvdmn8kN3b -LW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcY -AuUR0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqB -AGMUuTNe3QvboEUHGjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYq -E613TBoYm5EPWNgGVMWX+Ko/IIqmhaZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHr -W2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQCPxrvrNQKlr9qEgYRtaQQJKQ -CoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE -AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAU -X15QvWiWkKQUEapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3 -f5Z2EMVGpdAgS1D0NTsY9FVqQRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxaja -H6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxDQpSbIPDRzbLrLFPCU3hKTwSUQZqP -JzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcRj88YxeMn/ibvBZ3P -zzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5vZSt -jBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0 -/L5H9MG0qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pT -BGIBnfHAT+7hOtSLIBD6Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79 -aPib8qXPMThcFarmlwDB31qlpzmq6YR/PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YW -xw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnnkf3/W9b3raYvAwtt41dU -63ZTGI0RmLo= ------END CERTIFICATE----- - -# Issuer: CN=HARICA TLS ECC Root CA 2021 O=Hellenic Academic and Research Institutions CA -# Subject: CN=HARICA TLS ECC Root CA 2021 O=Hellenic Academic and Research Institutions CA -# Label: "HARICA TLS ECC Root CA 2021" -# Serial: 137515985548005187474074462014555733966 -# MD5 Fingerprint: ae:f7:4c:e5:66:35:d1:b7:9b:8c:22:93:74:d3:4b:b0 -# SHA1 Fingerprint: bc:b0:c1:9d:e9:98:92:70:19:38:57:e9:8d:a7:b4:5d:6e:ee:01:48 -# SHA256 Fingerprint: 3f:99:cc:47:4a:cf:ce:4d:fe:d5:87:94:66:5e:47:8d:15:47:73:9f:2e:78:0f:1b:b4:ca:9b:13:30:97:d4:01 ------BEGIN CERTIFICATE----- -MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQsw -CQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2Vh -cmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9v -dCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoXDTQ1MDIxMzExMDEwOVowbDELMAkG -A1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj -aCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJvb3Qg -Q0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7 -KKrxcm1lAEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9Y -STHMmE5gEYd103KUkE+bECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUw -AwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQD -AgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAircJRQO9gcS3ujwLEXQNw -SaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/QwCZ61IygN -nxS2PFOiTAZpffpskcYqSUXm7LcT4Tps ------END CERTIFICATE----- - -# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 -# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 -# Label: "Autoridad de Certificacion Firmaprofesional CIF A62634068" -# Serial: 1977337328857672817 -# MD5 Fingerprint: 4e:6e:9b:54:4c:ca:b7:fa:48:e4:90:b1:15:4b:1c:a3 -# SHA1 Fingerprint: 0b:be:c2:27:22:49:cb:39:aa:db:35:5c:53:e3:8c:ae:78:ff:b6:fe -# SHA256 Fingerprint: 57:de:05:83:ef:d2:b2:6e:03:61:da:99:da:9d:f4:64:8d:ef:7e:e8:44:1c:3b:72:8a:fa:9b:cd:e0:f9:b2:6a ------BEGIN CERTIFICATE----- -MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UE -BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h -cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1 -MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg -Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 -thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM -cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG -L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i -NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h -X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b -m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy -Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja -EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T -KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF -6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh -OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1UdDgQWBBRlzeurNR4APn7VdMAc -tHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4wgZswgZgGBFUd -IAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j -b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABC -AG8AbgBhAG4AbwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAw -ADEANzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9m -iWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL4QjbEwj4KKE1soCzC1HA01aajTNF -Sa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDbLIpgD7dvlAceHabJ -hfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1ilI45P -Vf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZE -EAEeiGaPcjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV -1aUsIC+nmCjuRfzxuIgALI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2t -CsvMo2ebKHTEm9caPARYpoKdrcd7b/+Alun4jWq9GJAd/0kakFI3ky88Al2CdgtR -5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH9IBk9W6VULgRfhVwOEqw -f9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpfNIbnYrX9 -ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNK -GbqEZycPvEJdvSRUDewdcAZfpLz6IHxV ------END CERTIFICATE----- - -# Issuer: CN=vTrus ECC Root CA O=iTrusChina Co.,Ltd. -# Subject: CN=vTrus ECC Root CA O=iTrusChina Co.,Ltd. -# Label: "vTrus ECC Root CA" -# Serial: 630369271402956006249506845124680065938238527194 -# MD5 Fingerprint: de:4b:c1:f5:52:8c:9b:43:e1:3e:8f:55:54:17:8d:85 -# SHA1 Fingerprint: f6:9c:db:b0:fc:f6:02:13:b6:52:32:a6:a3:91:3f:16:70:da:c3:e1 -# SHA256 Fingerprint: 30:fb:ba:2c:32:23:8e:2a:98:54:7a:f9:79:31:e5:50:42:8b:9b:3f:1c:8e:eb:66:33:dc:fa:86:c5:b2:7d:d3 ------BEGIN CERTIFICATE----- -MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMw -RzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAY -BgNVBAMTEXZUcnVzIEVDQyBSb290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDcz -MTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28u -LEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYwEAYHKoZIzj0CAQYF -K4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+cToL0 -v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUd -e4BdS49nTPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYD -VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIw -V53dVvHH4+m4SVBrm2nDb+zDfSXkV5UTQJtS0zvzQBm8JsctBp61ezaf9SXUY2sA -AjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQLYgmRWAD5Tfs0aNoJrSEG -GJTO ------END CERTIFICATE----- - -# Issuer: CN=vTrus Root CA O=iTrusChina Co.,Ltd. -# Subject: CN=vTrus Root CA O=iTrusChina Co.,Ltd. -# Label: "vTrus Root CA" -# Serial: 387574501246983434957692974888460947164905180485 -# MD5 Fingerprint: b8:c9:37:df:fa:6b:31:84:64:c5:ea:11:6a:1b:75:fc -# SHA1 Fingerprint: 84:1a:69:fb:f5:cd:1a:25:34:13:3d:e3:f8:fc:b8:99:d0:c9:14:b7 -# SHA256 Fingerprint: 8a:71:de:65:59:33:6f:42:6c:26:e5:38:80:d0:0d:88:a1:8d:a4:c6:a9:1f:0d:cb:61:94:e2:06:c5:c9:63:87 ------BEGIN CERTIFICATE----- -MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQEL -BQAwQzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4x -FjAUBgNVBAMTDXZUcnVzIFJvb3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMx -MDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoGA1UEChMTaVRydXNDaGluYSBDby4s -THRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZotsSKYc -IrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykU -AyyNJJrIZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+ -GrPSbcKvdmaVayqwlHeFXgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z9 -8Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KAYPxMvDVTAWqXcoKv8R1w6Jz1717CbMdH -flqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70kLJrxLT5ZOrpGgrIDajt -J8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2AXPKBlim -0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZN -pGvu/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQ -UqqzApVg+QxMaPnu1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHW -OXSuTEGC2/KmSNGzm/MzqvOmwMVO9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMB -AAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYgscasGrz2iTAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAKbqSSaet -8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd -nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1j -bhd47F18iMjrjld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvM -Kar5CKXiNxTKsbhm7xqC5PD48acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIiv -TDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJnxDHO2zTlJQNgJXtxmOTAGytfdELS -S8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554WgicEFOwE30z9J4nfr -I8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4sEb9 -b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNB -UvupLnKWnyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1P -Ti07NEPhmg4NpGaXutIcSkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929ven -sBxXVsFy6K2ir40zSbofitzmdHxghm+Hl3s= ------END CERTIFICATE----- - -# Issuer: CN=ISRG Root X2 O=Internet Security Research Group -# Subject: CN=ISRG Root X2 O=Internet Security Research Group -# Label: "ISRG Root X2" -# Serial: 87493402998870891108772069816698636114 -# MD5 Fingerprint: d3:9e:c4:1e:23:3c:a6:df:cf:a3:7e:6d:e0:14:e6:e5 -# SHA1 Fingerprint: bd:b1:b9:3c:d5:97:8d:45:c6:26:14:55:f8:db:95:c7:5a:d1:53:af -# SHA256 Fingerprint: 69:72:9b:8e:15:a8:6e:fc:17:7a:57:af:b7:17:1d:fc:64:ad:d2:8c:2f:ca:8c:f1:50:7e:34:45:3c:cb:14:70 ------BEGIN CERTIFICATE----- -MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw -CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg -R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00 -MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT -ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw -EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW -+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9 -ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T -AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI -zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW -tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1 -/q4AaOeMSQ+2b1tbFfLn ------END CERTIFICATE----- - -# Issuer: CN=HiPKI Root CA - G1 O=Chunghwa Telecom Co., Ltd. -# Subject: CN=HiPKI Root CA - G1 O=Chunghwa Telecom Co., Ltd. -# Label: "HiPKI Root CA - G1" -# Serial: 60966262342023497858655262305426234976 -# MD5 Fingerprint: 69:45:df:16:65:4b:e8:68:9a:8f:76:5f:ff:80:9e:d3 -# SHA1 Fingerprint: 6a:92:e4:a8:ee:1b:ec:96:45:37:e3:29:57:49:cd:96:e3:e5:d2:60 -# SHA256 Fingerprint: f0:15:ce:3c:c2:39:bf:ef:06:4b:e9:f1:d2:c4:17:e1:a0:26:4a:0a:94:be:1f:0c:8d:12:18:64:eb:69:49:cc ------BEGIN CERTIFICATE----- -MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBP -MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 -ZC4xGzAZBgNVBAMMEkhpUEtJIFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRa -Fw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3 -YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kgUm9vdCBDQSAtIEcx -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0o9Qw -qNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twv -Vcg3Px+kwJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6 -lZgRZq2XNdZ1AYDgr/SEYYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnz -Qs7ZngyzsHeXZJzA9KMuH5UHsBffMNsAGJZMoYFL3QRtU6M9/Aes1MU3guvklQgZ -KILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfdhSi8MEyr48KxRURHH+CK -FgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj1jOXTyFj -HluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDr -y+K49a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ -/W3c1pzAtH2lsN0/Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgM -a/aOEmem8rJY5AIJEzypuxC00jBF8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6 -fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNV -HQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQDAgGGMA0GCSqG -SIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi -7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqc -SE5XCV0vrPSltJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6Fza -ZsT0pPBWGTMpWmWSBUdGSquEwx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9Tc -XzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07QJNBAsNB1CI69aO4I1258EHBGG3zg -iLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv5wiZqAxeJoBF1Pho -L5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+GpzjLrF -Ne85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wr -kkVbbiVghUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+ -vhV4nYWBSipX3tUZQ9rbyltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQU -YDksswBVLuT1sw5XxJFBAJw/6KXf6vb/yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ== ------END CERTIFICATE----- - -# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 -# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 -# Label: "GlobalSign ECC Root CA - R4" -# Serial: 159662223612894884239637590694 -# MD5 Fingerprint: 26:29:f8:6d:e1:88:bf:a2:65:7f:aa:c4:cd:0f:7f:fc -# SHA1 Fingerprint: 6b:a0:b0:98:e1:71:ef:5a:ad:fe:48:15:80:77:10:f4:bd:6f:0b:28 -# SHA256 Fingerprint: b0:85:d7:0b:96:4f:19:1a:73:e4:af:0d:54:ae:7a:0e:07:aa:fd:af:9b:71:dd:08:62:13:8a:b7:32:5a:24:a2 ------BEGIN CERTIFICATE----- -MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD -VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh -bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw -MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g -UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT -BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx -uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV -HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/ -+wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147 -bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm ------END CERTIFICATE----- - -# Issuer: CN=GTS Root R1 O=Google Trust Services LLC -# Subject: CN=GTS Root R1 O=Google Trust Services LLC -# Label: "GTS Root R1" -# Serial: 159662320309726417404178440727 -# MD5 Fingerprint: 05:fe:d0:bf:71:a8:a3:76:63:da:01:e0:d8:52:dc:40 -# SHA1 Fingerprint: e5:8c:1c:c4:91:3b:38:63:4b:e9:10:6e:e3:ad:8e:6b:9d:d9:81:4a -# SHA256 Fingerprint: d9:47:43:2a:bd:e7:b7:fa:90:fc:2e:6b:59:10:1b:12:80:e0:e1:c7:e4:e4:0f:a3:c6:88:7f:ff:57:a7:f4:cf ------BEGIN CERTIFICATE----- -MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw -CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU -MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw -MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp -Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA -A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo -27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w -Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw -TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl -qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH -szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8 -Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk -MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 -wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p -aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN -VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID -AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E -FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb -C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe -QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy -h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4 -7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J -ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef -MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/ -Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT -6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ -0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm -2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb -bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c ------END CERTIFICATE----- - -# Issuer: CN=GTS Root R3 O=Google Trust Services LLC -# Subject: CN=GTS Root R3 O=Google Trust Services LLC -# Label: "GTS Root R3" -# Serial: 159662495401136852707857743206 -# MD5 Fingerprint: 3e:e7:9d:58:02:94:46:51:94:e5:e0:22:4a:8b:e7:73 -# SHA1 Fingerprint: ed:e5:71:80:2b:c8:92:b9:5b:83:3c:d2:32:68:3f:09:cd:a0:1e:46 -# SHA256 Fingerprint: 34:d8:a7:3e:e2:08:d9:bc:db:0d:95:65:20:93:4b:4e:40:e6:94:82:59:6e:8b:6f:73:c8:42:6b:01:0a:6f:48 ------BEGIN CERTIFICATE----- -MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD -VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG -A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw -WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz -IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi -AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G -jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2 -4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7 -VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm -ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X ------END CERTIFICATE----- - -# Issuer: CN=GTS Root R4 O=Google Trust Services LLC -# Subject: CN=GTS Root R4 O=Google Trust Services LLC -# Label: "GTS Root R4" -# Serial: 159662532700760215368942768210 -# MD5 Fingerprint: 43:96:83:77:19:4d:76:b3:9d:65:52:e4:1d:22:a5:e8 -# SHA1 Fingerprint: 77:d3:03:67:b5:e0:0c:15:f6:0c:38:61:df:7c:e1:3b:92:46:4d:47 -# SHA256 Fingerprint: 34:9d:fa:40:58:c5:e2:63:12:3b:39:8a:e7:95:57:3c:4e:13:13:c8:3f:e6:8f:93:55:6c:d5:e8:03:1b:3c:7d ------BEGIN CERTIFICATE----- -MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD -VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG -A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw -WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz -IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi -AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi -QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR -HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D -9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8 -p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD ------END CERTIFICATE----- - -# Issuer: CN=Telia Root CA v2 O=Telia Finland Oyj -# Subject: CN=Telia Root CA v2 O=Telia Finland Oyj -# Label: "Telia Root CA v2" -# Serial: 7288924052977061235122729490515358 -# MD5 Fingerprint: 0e:8f:ac:aa:82:df:85:b1:f4:dc:10:1c:fc:99:d9:48 -# SHA1 Fingerprint: b9:99:cd:d1:73:50:8a:c4:47:05:08:9c:8c:88:fb:be:a0:2b:40:cd -# SHA256 Fingerprint: 24:2b:69:74:2f:cb:1e:5b:2a:bf:98:89:8b:94:57:21:87:54:4e:5b:4d:99:11:78:65:73:62:1f:6a:74:b8:2c ------BEGIN CERTIFICATE----- -MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQx -CzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UE -AwwQVGVsaWEgUm9vdCBDQSB2MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1 -NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZ -MBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZIhvcNAQEBBQADggIP -ADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ76zBq -AMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9 -vVYiQJ3q9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9 -lRdU2HhE8Qx3FZLgmEKnpNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTOD -n3WhUidhOPFZPY5Q4L15POdslv5e2QJltI5c0BE0312/UqeBAMN/mUWZFdUXyApT -7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW5olWK8jjfN7j/4nlNW4o -6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNrRBH0pUPC -TEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6 -WT0EBXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63R -DolUK5X6wK0dmBR4M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZI -pEYslOqodmJHixBTB0hXbOKSTbauBcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGj -YzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7Wxy+G2CQ5MB0GA1UdDgQWBBRy -rOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw -AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ -8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi -0f6X+J8wfBj5tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMM -A8iZGok1GTzTyVR8qPAs5m4HeW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBS -SRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+Cy748fdHif64W1lZYudogsYMVoe+K -TTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygCQMez2P2ccGrGKMOF -6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15h2Er -3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMt -Ty3EHD70sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pT -VmBds9hCG1xLEooc6+t9xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAW -ysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQraVplI/owd8k+BsHMYeB2F326CjYSlKA -rBPuUBQemMc= ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST BR Root CA 1 2020 O=D-Trust GmbH -# Subject: CN=D-TRUST BR Root CA 1 2020 O=D-Trust GmbH -# Label: "D-TRUST BR Root CA 1 2020" -# Serial: 165870826978392376648679885835942448534 -# MD5 Fingerprint: b5:aa:4b:d5:ed:f7:e3:55:2e:8f:72:0a:f3:75:b8:ed -# SHA1 Fingerprint: 1f:5b:98:f0:e3:b5:f7:74:3c:ed:e6:b0:36:7d:32:cd:f4:09:41:67 -# SHA256 Fingerprint: e5:9a:aa:81:60:09:c2:2b:ff:5b:25:ba:d3:7d:f3:06:f0:49:79:7c:1f:81:d8:5a:b0:89:e6:57:bd:8f:00:44 ------BEGIN CERTIFICATE----- -MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQsw -CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS -VVNUIEJSIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5 -NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG -A1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB -BAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7dPYS -zuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0 -QVK5buXuQqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/ -VbNafAkl1bK6CKBrqx9tMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g -PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2JyX3Jvb3Rf -Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l -dC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 -c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO -PQQDAwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFW -wKrY7RjEsK70PvomAjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHV -dWNbFJWcHwHP2NVypw87 ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST EV Root CA 1 2020 O=D-Trust GmbH -# Subject: CN=D-TRUST EV Root CA 1 2020 O=D-Trust GmbH -# Label: "D-TRUST EV Root CA 1 2020" -# Serial: 126288379621884218666039612629459926992 -# MD5 Fingerprint: 8c:2d:9d:70:9f:48:99:11:06:11:fb:e9:cb:30:c0:6e -# SHA1 Fingerprint: 61:db:8c:21:59:69:03:90:d8:7c:9c:12:86:54:cf:9d:3d:f4:dd:07 -# SHA256 Fingerprint: 08:17:0d:1a:a3:64:53:90:1a:2f:95:92:45:e3:47:db:0c:8d:37:ab:aa:bc:56:b8:1a:a1:00:dc:95:89:70:db ------BEGIN CERTIFICATE----- -MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQsw -CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS -VVNUIEVWIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5 -NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG -A1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB -BAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8ZRCC -/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rD -wpdhQntJraOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3 -OqQo5FD4pPfsazK2/umLMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g -PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2V2X3Jvb3Rf -Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l -dC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 -c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO -PQQDAwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CA -y/m0sRtW9XLS/BnRAjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJb -gfM0agPnIjhQW+0ZT0MW ------END CERTIFICATE----- - -# Issuer: CN=DigiCert TLS ECC P384 Root G5 O=DigiCert, Inc. -# Subject: CN=DigiCert TLS ECC P384 Root G5 O=DigiCert, Inc. -# Label: "DigiCert TLS ECC P384 Root G5" -# Serial: 13129116028163249804115411775095713523 -# MD5 Fingerprint: d3:71:04:6a:43:1c:db:a6:59:e1:a8:a3:aa:c5:71:ed -# SHA1 Fingerprint: 17:f3:de:5e:9f:0f:19:e9:8e:f6:1f:32:26:6e:20:c4:07:ae:30:ee -# SHA256 Fingerprint: 01:8e:13:f0:77:25:32:cf:80:9b:d1:b1:72:81:86:72:83:fc:48:c6:e1:3b:e9:c6:98:12:85:4a:49:0c:1b:05 ------BEGIN CERTIFICATE----- -MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp -Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2 -MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ -bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG -ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS -7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp -0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS -B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49 -BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ -LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4 -DXZDjC5Ty3zfDBeWUA== ------END CERTIFICATE----- - -# Issuer: CN=DigiCert TLS RSA4096 Root G5 O=DigiCert, Inc. -# Subject: CN=DigiCert TLS RSA4096 Root G5 O=DigiCert, Inc. -# Label: "DigiCert TLS RSA4096 Root G5" -# Serial: 11930366277458970227240571539258396554 -# MD5 Fingerprint: ac:fe:f7:34:96:a9:f2:b3:b4:12:4b:e4:27:41:6f:e1 -# SHA1 Fingerprint: a7:88:49:dc:5d:7c:75:8c:8c:de:39:98:56:b3:aa:d0:b2:a5:71:35 -# SHA256 Fingerprint: 37:1a:00:dc:05:33:b3:72:1a:7e:eb:40:e8:41:9e:70:79:9d:2b:0a:0f:2c:1d:80:69:31:65:f7:ce:c4:ad:75 ------BEGIN CERTIFICATE----- -MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBN -MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMT -HERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcN -NDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs -IEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS87IE+ -ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG0 -2C+JFvuUAT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgp -wgscONyfMXdcvyej/Cestyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZM -pG2T6T867jp8nVid9E6P/DsjyG244gXazOvswzH016cpVIDPRFtMbzCe88zdH5RD -nU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnVDdXifBBiqmvwPXbzP6Po -sMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9qTXeXAaDx -Zre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cd -Lvvyz6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvX -KyY//SovcfXWJL5/MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNe -XoVPzthwiHvOAbWWl9fNff2C+MIkwcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPL -tgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4EFgQUUTMc7TZArxfTJc1paPKv -TiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN -AQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw -GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7H -PNtQOa27PShNlnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLF -O4uJ+DQtpBflF+aZfTCIITfNMBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQ -REtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/u4cnYiWB39yhL/btp/96j1EuMPik -AdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9GOUrYU9DzLjtxpdRv -/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh47a+ -p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilw -MUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WF -qUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCK -ovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+ ------END CERTIFICATE----- - -# Issuer: CN=Certainly Root R1 O=Certainly -# Subject: CN=Certainly Root R1 O=Certainly -# Label: "Certainly Root R1" -# Serial: 188833316161142517227353805653483829216 -# MD5 Fingerprint: 07:70:d4:3e:82:87:a0:fa:33:36:13:f4:fa:33:e7:12 -# SHA1 Fingerprint: a0:50:ee:0f:28:71:f4:27:b2:12:6d:6f:50:96:25:ba:cc:86:42:af -# SHA256 Fingerprint: 77:b8:2c:d8:64:4c:43:05:f7:ac:c5:cb:15:6b:45:67:50:04:03:3d:51:c6:0c:62:02:a8:e0:c3:34:67:d3:a0 ------BEGIN CERTIFICATE----- -MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAw -PTELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2Vy -dGFpbmx5IFJvb3QgUjEwHhcNMjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9 -MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0 -YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANA2 -1B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O5MQT -vqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbed -aFySpvXl8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b0 -1C7jcvk2xusVtyWMOvwlDbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5 -r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGIXsXwClTNSaa/ApzSRKft43jvRl5tcdF5 -cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkNKPl6I7ENPT2a/Z2B7yyQ -wHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQAjeZjOVJ -6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA -2CnbrlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyH -Wyf5QBGenDPBt+U1VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMR -eiFPCyEQtkA6qyI6BJyLm4SGcprSp6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB -/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTgqj8ljZ9EXME66C6u -d0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAszHQNTVfSVcOQr -PbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d -8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi -1wrykXprOQ4vMMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrd -rRT90+7iIgXr0PK3aBLXWopBGsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9di -taY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+gjwN/KUD+nsa2UUeYNrEjvn8K8l7 -lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgHJBu6haEaBQmAupVj -yTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7fpYn -Kx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLy -yCwzk5Iwx06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5n -wXARPbv0+Em34yaXOp/SX3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6 -OV+KmalBWQewLK8= ------END CERTIFICATE----- - -# Issuer: CN=Certainly Root E1 O=Certainly -# Subject: CN=Certainly Root E1 O=Certainly -# Label: "Certainly Root E1" -# Serial: 8168531406727139161245376702891150584 -# MD5 Fingerprint: 0a:9e:ca:cd:3e:52:50:c6:36:f3:4b:a3:ed:a7:53:e9 -# SHA1 Fingerprint: f9:e1:6d:dc:01:89:cf:d5:82:45:63:3e:c5:37:7d:c2:eb:93:6f:2b -# SHA256 Fingerprint: b4:58:5f:22:e4:ac:75:6a:4e:86:12:a1:36:1c:5d:9d:03:1a:93:fd:84:fe:bb:77:8f:a3:06:8b:0f:c4:2d:c2 ------BEGIN CERTIFICATE----- -MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQsw -CQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlu -bHkgUm9vdCBFMTAeFw0yMTA0MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJ -BgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlubHkxGjAYBgNVBAMTEUNlcnRhaW5s -eSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4fxzf7flHh4axpMCK -+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9YBk2 -QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4 -hevIIgcwCgYIKoZIzj0EAwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozm -ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG -BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR ------END CERTIFICATE----- - -# Issuer: CN=Security Communication ECC RootCA1 O=SECOM Trust Systems CO.,LTD. -# Subject: CN=Security Communication ECC RootCA1 O=SECOM Trust Systems CO.,LTD. -# Label: "Security Communication ECC RootCA1" -# Serial: 15446673492073852651 -# MD5 Fingerprint: 7e:43:b0:92:68:ec:05:43:4c:98:ab:5d:35:2e:7e:86 -# SHA1 Fingerprint: b8:0e:26:a9:bf:d2:b2:3b:c0:ef:46:c9:ba:c7:bb:f6:1d:0d:41:41 -# SHA256 Fingerprint: e7:4f:bd:a5:5b:d5:64:c4:73:a3:6b:44:1a:a7:99:c8:a6:8e:07:74:40:e8:28:8b:9f:a1:e5:0e:4b:ba:ca:11 ------BEGIN CERTIFICATE----- -MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYT -AkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYD -VQQDEyJTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYx -NjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTELMAkGA1UEBhMCSlAxJTAjBgNVBAoT -HFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNVBAMTIlNlY3VyaXR5 -IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQAIgNi -AASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+Cnnfdl -dB9sELLo5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpK -ULGjQjBAMB0GA1UdDgQWBBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu -9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0O -be0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k= ------END CERTIFICATE----- - -# Issuer: CN=BJCA Global Root CA1 O=BEIJING CERTIFICATE AUTHORITY -# Subject: CN=BJCA Global Root CA1 O=BEIJING CERTIFICATE AUTHORITY -# Label: "BJCA Global Root CA1" -# Serial: 113562791157148395269083148143378328608 -# MD5 Fingerprint: 42:32:99:76:43:33:36:24:35:07:82:9b:28:f9:d0:90 -# SHA1 Fingerprint: d5:ec:8d:7b:4c:ba:79:f4:e7:e8:cb:9d:6b:ae:77:83:10:03:21:6a -# SHA256 Fingerprint: f3:89:6f:88:fe:7c:0a:88:27:66:a7:fa:6a:d2:74:9f:b5:7a:7f:3e:98:fb:76:9c:1f:a7:b0:9c:2c:44:d5:ae ------BEGIN CERTIFICATE----- -MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBU -MQswCQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRI -T1JJVFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAz -MTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJF -SUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2Jh -bCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFmCL3Z -xRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZ -spDyRhySsTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O5 -58dnJCNPYwpj9mZ9S1WnP3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgR -at7GGPZHOiJBhyL8xIkoVNiMpTAK+BcWyqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll -5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRjeulumijWML3mG90Vr4Tq -nMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNnMoH1V6XK -V0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/ -pj+bOT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZO -z2nxbkRs1CTqjSShGL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXn -jSXWgXSHRtQpdaJCbPdzied9v3pKH9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+ -WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMBAAGjQjBAMB0GA1UdDgQWBBTF -7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE -AwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4 -YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3Kli -awLwQ8hOnThJdMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u -+2D2/VnGKhs/I0qUJDAnyIm860Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88 -X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuhTaRjAv04l5U/BXCga99igUOLtFkN -SoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW4AB+dAb/OMRyHdOo -P2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmpGQrI -+pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRz -znfSxqxx4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9 -eVzYH6Eze9mCUAyTF6ps3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2 -YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4SSPfSKcOYKMryMguTjClPPGAyzQWWYezy -r/6zcCwupvI= ------END CERTIFICATE----- - -# Issuer: CN=BJCA Global Root CA2 O=BEIJING CERTIFICATE AUTHORITY -# Subject: CN=BJCA Global Root CA2 O=BEIJING CERTIFICATE AUTHORITY -# Label: "BJCA Global Root CA2" -# Serial: 58605626836079930195615843123109055211 -# MD5 Fingerprint: 5e:0a:f6:47:5f:a6:14:e8:11:01:95:3f:4d:01:eb:3c -# SHA1 Fingerprint: f4:27:86:eb:6e:b8:6d:88:31:67:02:fb:ba:66:a4:53:00:aa:7a:a6 -# SHA256 Fingerprint: 57:4d:f6:93:1e:27:80:39:66:7b:72:0a:fd:c1:60:0f:c2:7e:b6:6d:d3:09:29:79:fb:73:85:64:87:21:28:82 ------BEGIN CERTIFICATE----- -MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQsw -CQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJ -VFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgy -MVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJ -TkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2JhbCBS -b290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jlSR9B -IgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK+ -+kpRuDCK/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJK -sVF/BvDRgh9Obl+rg/xI1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA -94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8gUXOQwKhbYdDFUDn9hf7B -43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== ------END CERTIFICATE----- - -# Issuer: CN=Sectigo Public Server Authentication Root E46 O=Sectigo Limited -# Subject: CN=Sectigo Public Server Authentication Root E46 O=Sectigo Limited -# Label: "Sectigo Public Server Authentication Root E46" -# Serial: 88989738453351742415770396670917916916 -# MD5 Fingerprint: 28:23:f8:b2:98:5c:37:16:3b:3e:46:13:4e:b0:b3:01 -# SHA1 Fingerprint: ec:8a:39:6c:40:f0:2e:bc:42:75:d4:9f:ab:1c:1a:5b:67:be:d2:9a -# SHA256 Fingerprint: c9:0f:26:f0:fb:1b:40:18:b2:22:27:51:9b:5c:a2:b5:3e:2c:a5:b3:be:5c:f1:8e:fe:1b:ef:47:38:0c:53:83 ------BEGIN CERTIFICATE----- -MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw -CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T -ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN -MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG -A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT -ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA -IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC -WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+ -6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B -Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa -qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q -4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw== ------END CERTIFICATE----- - -# Issuer: CN=Sectigo Public Server Authentication Root R46 O=Sectigo Limited -# Subject: CN=Sectigo Public Server Authentication Root R46 O=Sectigo Limited -# Label: "Sectigo Public Server Authentication Root R46" -# Serial: 156256931880233212765902055439220583700 -# MD5 Fingerprint: 32:10:09:52:00:d5:7e:6c:43:df:15:c0:b1:16:93:e5 -# SHA1 Fingerprint: ad:98:f9:f3:e4:7d:75:3b:65:d4:82:b3:a4:52:17:bb:6e:f5:e4:38 -# SHA256 Fingerprint: 7b:b6:47:a6:2a:ee:ac:88:bf:25:7a:a5:22:d0:1f:fe:a3:95:e0:ab:45:c7:3f:93:f6:56:54:ec:38:f2:5a:06 ------BEGIN CERTIFICATE----- -MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf -MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD -Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw -HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY -MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp -YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa -ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz -SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf -iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X -ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3 -IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS -VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE -SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu -+Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt -8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L -HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt -zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P -AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c -mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ -YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52 -gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA -Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB -JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX -DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui -TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5 -dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65 -LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp -0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY -QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL ------END CERTIFICATE----- - -# Issuer: CN=SSL.com TLS RSA Root CA 2022 O=SSL Corporation -# Subject: CN=SSL.com TLS RSA Root CA 2022 O=SSL Corporation -# Label: "SSL.com TLS RSA Root CA 2022" -# Serial: 148535279242832292258835760425842727825 -# MD5 Fingerprint: d8:4e:c6:59:30:d8:fe:a0:d6:7a:5a:2c:2c:69:78:da -# SHA1 Fingerprint: ec:2c:83:40:72:af:26:95:10:ff:0e:f2:03:ee:31:70:f6:78:9d:ca -# SHA256 Fingerprint: 8f:af:7d:2e:2c:b4:70:9b:b8:e0:b3:36:66:bf:75:a5:dd:45:b5:de:48:0f:8e:a8:d4:bf:e6:be:bc:17:f2:ed ------BEGIN CERTIFICATE----- -MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO -MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD -DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX -DTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw -b3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCC -AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTP -L3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OY -t6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0ins -S657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3 -PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBO -L9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3 -R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77w -dr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS -+YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYS -d66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoG -AtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2f -gTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j -BBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0Z -NbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt -hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsM -QtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvf -R4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJ -DPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeW -P4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVy -lrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlq -bLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2w -AgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3q -r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji -Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU -98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= ------END CERTIFICATE----- - -# Issuer: CN=SSL.com TLS ECC Root CA 2022 O=SSL Corporation -# Subject: CN=SSL.com TLS ECC Root CA 2022 O=SSL Corporation -# Label: "SSL.com TLS ECC Root CA 2022" -# Serial: 26605119622390491762507526719404364228 -# MD5 Fingerprint: 99:d7:5c:f1:51:36:cc:e9:ce:d9:19:2e:77:71:56:c5 -# SHA1 Fingerprint: 9f:5f:d9:1a:54:6d:f5:0c:71:f0:ee:7a:bd:17:49:98:84:73:e2:39 -# SHA256 Fingerprint: c3:2f:fd:9f:46:f9:36:d1:6c:36:73:99:09:59:43:4b:9a:d6:0a:af:bb:9e:7c:f3:36:54:f1:44:cc:1b:a1:43 ------BEGIN CERTIFICATE----- -MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw -CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT -U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2 -MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh -dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG -ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm -acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN -SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME -GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW -uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp -15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN -b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g== ------END CERTIFICATE----- - -# Issuer: CN=Atos TrustedRoot Root CA ECC TLS 2021 O=Atos -# Subject: CN=Atos TrustedRoot Root CA ECC TLS 2021 O=Atos -# Label: "Atos TrustedRoot Root CA ECC TLS 2021" -# Serial: 81873346711060652204712539181482831616 -# MD5 Fingerprint: 16:9f:ad:f1:70:ad:79:d6:ed:29:b4:d1:c5:79:70:a8 -# SHA1 Fingerprint: 9e:bc:75:10:42:b3:02:f3:81:f4:f7:30:62:d4:8f:c3:a7:51:b2:dd -# SHA256 Fingerprint: b2:fa:e5:3e:14:cc:d7:ab:92:12:06:47:01:ae:27:9c:1d:89:88:fa:cb:77:5f:a8:a0:08:91:4e:66:39:88:a8 ------BEGIN CERTIFICATE----- -MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4w -LAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0w -CwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0 -MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBF -Q0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMHYwEAYHKoZI -zj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6KDP/X -tXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4 -AjJn8ZQSb+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2 -KCXWfeBmmnoJsmo7jjPXNtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMD -aAAwZQIwW5kp85wxtolrbNa9d+F851F+uDrNozZffPc8dz7kUK2o59JZDCaOMDtu -CCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGYa3cpetskz2VAv9LcjBHo -9H1/IISpQuQo ------END CERTIFICATE----- - -# Issuer: CN=Atos TrustedRoot Root CA RSA TLS 2021 O=Atos -# Subject: CN=Atos TrustedRoot Root CA RSA TLS 2021 O=Atos -# Label: "Atos TrustedRoot Root CA RSA TLS 2021" -# Serial: 111436099570196163832749341232207667876 -# MD5 Fingerprint: d4:d3:46:b8:9a:c0:9c:76:5d:9e:3a:c3:b9:99:31:d2 -# SHA1 Fingerprint: 18:52:3b:0d:06:37:e4:d6:3a:df:23:e4:98:fb:5b:16:fb:86:74:48 -# SHA256 Fingerprint: 81:a9:08:8e:a5:9f:b3:64:c5:48:a6:f8:55:59:09:9b:6f:04:05:ef:bf:18:e5:32:4e:c9:f4:57:ba:00:11:2f ------BEGIN CERTIFICATE----- -MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBM -MS4wLAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIx -MQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00 -MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBD -QSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMIICIjAN -BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BBl01Z -4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYv -Ye+W/CBGvevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZ -kmGbzSoXfduP9LVq6hdKZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDs -GY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt0xU6kGpn8bRrZtkh68rZYnxGEFzedUln -nkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVKPNe0OwANwI8f4UDErmwh -3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMYsluMWuPD -0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzy -geBYBr3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8 -ANSbhqRAvNncTFd+rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezB -c6eUWsuSZIKmAMFwoW4sKeFYV+xafJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lI -pw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU -dEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB -DAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS -4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPs -o0UvFJ/1TCplQ3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJ -qM7F78PRreBrAwA0JrRUITWXAdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuyw -xfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9GslA9hGCZcbUztVdF5kJHdWoOsAgM -rr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2VktafcxBPTy+av5EzH4 -AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9qTFsR -0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuY -o7Ey7Nmj1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5 -dDTedk+SKlOxJTnbPP/lPqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcE -oji2jbDwN/zIIX8/syQbPYtuzE2wFg2WHYMfRsCbvUOZ58SWLs5fyQ== ------END CERTIFICATE----- - -# Issuer: CN=TrustAsia Global Root CA G3 O=TrustAsia Technologies, Inc. -# Subject: CN=TrustAsia Global Root CA G3 O=TrustAsia Technologies, Inc. -# Label: "TrustAsia Global Root CA G3" -# Serial: 576386314500428537169965010905813481816650257167 -# MD5 Fingerprint: 30:42:1b:b7:bb:81:75:35:e4:16:4f:53:d2:94:de:04 -# SHA1 Fingerprint: 63:cf:b6:c1:27:2b:56:e4:88:8e:1c:23:9a:b6:2e:81:47:24:c3:c7 -# SHA256 Fingerprint: e0:d3:22:6a:eb:11:63:c2:e4:8f:f9:be:3b:50:b4:c6:43:1b:e7:bb:1e:ac:c5:c3:6b:5d:5e:c5:09:03:9a:08 ------BEGIN CERTIFICATE----- -MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEM -BQAwWjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dp -ZXMsIEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAe -Fw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEwMTlaMFoxCzAJBgNVBAYTAkNOMSUw -IwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtU -cnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUAA4IC -DwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNS -T1QY4SxzlZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqK -AtCWHwDNBSHvBm3dIZwZQ0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1 -nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/VP68czH5GX6zfZBCK70bwkPAPLfSIC7Ep -qq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1AgdB4SQXMeJNnKziyhWTXA -yB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm9WAPzJMs -hH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gX -zhqcD0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAv -kV34PmVACxmZySYgWmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msT -f9FkPz2ccEblooV7WIQn3MSAPmeamseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jA -uPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCFTIcQcf+eQxuulXUtgQIDAQAB -o2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj7zjKsK5Xf/Ih -MBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8E -BAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4 -wM8zAQLpw6o1D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2 -XFNFV1pF1AWZLy4jVe5jaN/TG3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1 -JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNjduMNhXJEIlU/HHzp/LgV6FL6qj6j -ITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstlcHboCoWASzY9M/eV -VHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys+TIx -xHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1on -AX1daBli2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d -7XB4tmBZrOFdRWOPyN9yaFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2Ntjj -gKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsASZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV -+Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFRJQJ6+N1rZdVtTTDIZbpo -FGWsJwt0ivKH ------END CERTIFICATE----- - -# Issuer: CN=TrustAsia Global Root CA G4 O=TrustAsia Technologies, Inc. -# Subject: CN=TrustAsia Global Root CA G4 O=TrustAsia Technologies, Inc. -# Label: "TrustAsia Global Root CA G4" -# Serial: 451799571007117016466790293371524403291602933463 -# MD5 Fingerprint: 54:dd:b2:d7:5f:d8:3e:ed:7c:e0:0b:2e:cc:ed:eb:eb -# SHA1 Fingerprint: 57:73:a5:61:5d:80:b2:e6:ac:38:82:fc:68:07:31:ac:9f:b5:92:5a -# SHA256 Fingerprint: be:4b:56:cb:50:56:c0:13:6a:52:6d:f4:44:50:8d:aa:36:a0:b5:4f:42:e4:ac:38:f7:2a:f4:70:e4:79:65:4c ------BEGIN CERTIFICATE----- -MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMw -WjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs -IEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0y -MTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJaMFoxCzAJBgNVBAYTAkNOMSUwIwYD -VQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtUcnVz -dEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATx -s8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbw -LxYI+hW8m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJij -YzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mD -pm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/pDHel4NZg6ZvccveMA4GA1UdDwEB/wQE -AwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AAbbd+NvBNEU/zy4k6LHiR -UKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xkdUfFVZDj -/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA== ------END CERTIFICATE----- - -# Issuer: CN=Telekom Security TLS ECC Root 2020 O=Deutsche Telekom Security GmbH -# Subject: CN=Telekom Security TLS ECC Root 2020 O=Deutsche Telekom Security GmbH -# Label: "Telekom Security TLS ECC Root 2020" -# Serial: 72082518505882327255703894282316633856 -# MD5 Fingerprint: c1:ab:fe:6a:10:2c:03:8d:bc:1c:22:32:c0:85:a7:fd -# SHA1 Fingerprint: c0:f8:96:c5:a9:3b:01:06:21:07:da:18:42:48:bc:e9:9d:88:d5:ec -# SHA256 Fingerprint: 57:8a:f4:de:d0:85:3f:4e:59:98:db:4a:ea:f9:cb:ea:8d:94:5f:60:b6:20:a3:8d:1a:3c:13:b2:bc:7b:a8:e1 ------BEGIN CERTIFICATE----- -MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQsw -CQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBH -bWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIw -MB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIzNTk1OVowYzELMAkGA1UEBhMCREUx -JzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkGA1UE -AwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqGSM49 -AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/O -tdKPD/M12kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDP -f8iAC8GXs7s1J8nCG6NCMEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6f -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2cA -MGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZMo7k+5Dck2TOrbRBR2Di -z6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdUga/sf+Rn -27iQ7t0l ------END CERTIFICATE----- - -# Issuer: CN=Telekom Security TLS RSA Root 2023 O=Deutsche Telekom Security GmbH -# Subject: CN=Telekom Security TLS RSA Root 2023 O=Deutsche Telekom Security GmbH -# Label: "Telekom Security TLS RSA Root 2023" -# Serial: 44676229530606711399881795178081572759 -# MD5 Fingerprint: bf:5b:eb:54:40:cd:48:71:c4:20:8d:7d:de:0a:42:f2 -# SHA1 Fingerprint: 54:d3:ac:b3:bd:57:56:f6:85:9d:ce:e5:c3:21:e2:d4:ad:83:d0:93 -# SHA256 Fingerprint: ef:c6:5c:ad:bb:59:ad:b6:ef:e8:4d:a2:23:11:b3:56:24:b7:1b:3b:1e:a0:da:8b:66:55:17:4e:c8:97:86:46 ------BEGIN CERTIFICATE----- -MIIFszCCA5ugAwIBAgIQIZxULej27HF3+k7ow3BXlzANBgkqhkiG9w0BAQwFADBj -MQswCQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0 -eSBHbWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBSU0EgUm9vdCAy -MDIzMB4XDTIzMDMyODEyMTY0NVoXDTQ4MDMyNzIzNTk1OVowYzELMAkGA1UEBhMC -REUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkG -A1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgUlNBIFJvb3QgMjAyMzCCAiIwDQYJ -KoZIhvcNAQEBBQADggIPADCCAgoCggIBAO01oYGA88tKaVvC+1GDrib94W7zgRJ9 -cUD/h3VCKSHtgVIs3xLBGYSJwb3FKNXVS2xE1kzbB5ZKVXrKNoIENqil/Cf2SfHV -cp6R+SPWcHu79ZvB7JPPGeplfohwoHP89v+1VmLhc2o0mD6CuKyVU/QBoCcHcqMA -U6DksquDOFczJZSfvkgdmOGjup5czQRxUX11eKvzWarE4GC+j4NSuHUaQTXtvPM6 -Y+mpFEXX5lLRbtLevOP1Czvm4MS9Q2QTps70mDdsipWol8hHD/BeEIvnHRz+sTug -BTNoBUGCwQMrAcjnj02r6LX2zWtEtefdi+zqJbQAIldNsLGyMcEWzv/9FIS3R/qy -8XDe24tsNlikfLMR0cN3f1+2JeANxdKz+bi4d9s3cXFH42AYTyS2dTd4uaNir73J -co4vzLuu2+QVUhkHM/tqty1LkCiCc/4YizWN26cEar7qwU02OxY2kTLvtkCJkUPg -8qKrBC7m8kwOFjQgrIfBLX7JZkcXFBGk8/ehJImr2BrIoVyxo/eMbcgByU/J7MT8 -rFEz0ciD0cmfHdRHNCk+y7AO+oMLKFjlKdw/fKifybYKu6boRhYPluV75Gp6SG12 -mAWl3G0eQh5C2hrgUve1g8Aae3g1LDj1H/1Joy7SWWO/gLCMk3PLNaaZlSJhZQNg -+y+TS/qanIA7AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtqeX -gj10hZv3PJ+TmpV5dVKMbUcwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS2 -p5eCPXSFm/c8n5OalXl1UoxtRzANBgkqhkiG9w0BAQwFAAOCAgEAqMxhpr51nhVQ -pGv7qHBFfLp+sVr8WyP6Cnf4mHGCDG3gXkaqk/QeoMPhk9tLrbKmXauw1GLLXrtm -9S3ul0A8Yute1hTWjOKWi0FpkzXmuZlrYrShF2Y0pmtjxrlO8iLpWA1WQdH6DErw -M807u20hOq6OcrXDSvvpfeWxm4bu4uB9tPcy/SKE8YXJN3nptT+/XOR0so8RYgDd -GGah2XsjX/GO1WfoVNpbOms2b/mBsTNHM3dA+VKq3dSDz4V4mZqTuXNnQkYRIer+ -CqkbGmVps4+uFrb2S1ayLfmlyOw7YqPta9BO1UAJpB+Y1zqlklkg5LB9zVtzaL1t -xKITDmcZuI1CfmwMmm6gJC3VRRvcxAIU/oVbZZfKTpBQCHpCNfnqwmbU+AGuHrS+ -w6jv/naaoqYfRvaE7fzbzsQCzndILIyy7MMAo+wsVRjBfhnu4S/yrYObnqsZ38aK -L4x35bcF7DvB7L6Gs4a8wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+lj -X273CXE2whJdV/LItM3z7gLfEdxquVeEHVlNjM7IDiPCtyaaEBRx/pOyiriA8A4Q -ntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0o82bNSQ3+pCTE4FCxpgm -dTdmQRCsu/WU48IxK63nI1bMNSWSs1A= ------END CERTIFICATE----- - -# Issuer: CN=TWCA CYBER Root CA O=TAIWAN-CA OU=Root CA -# Subject: CN=TWCA CYBER Root CA O=TAIWAN-CA OU=Root CA -# Label: "TWCA CYBER Root CA" -# Serial: 85076849864375384482682434040119489222 -# MD5 Fingerprint: 0b:33:a0:97:52:95:d4:a9:fd:bb:db:6e:a3:55:5b:51 -# SHA1 Fingerprint: f6:b1:1c:1a:83:38:e9:7b:db:b3:a8:c8:33:24:e0:2d:9c:7f:26:66 -# SHA256 Fingerprint: 3f:63:bb:28:14:be:17:4e:c8:b6:43:9c:f0:8d:6d:56:f0:b7:c4:05:88:3a:56:48:a3:34:42:4d:6b:3e:c5:58 ------BEGIN CERTIFICATE----- -MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQ -MQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290 -IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5 -WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FO -LUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3Qg -Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1sTs6P -40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxF -avcokPFhV8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/ -34bKS1PE2Y2yHer43CdTo0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684i -JkXXYJndzk834H/nY62wuFm40AZoNWDTNq5xQwTxaWV4fPMf88oon1oglWa0zbfu -j3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK/c/WMw+f+5eesRycnupf -Xtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkHIuNZW0CP -2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDA -S9TMfAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDA -oS/xUgXJP+92ZuJF2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzC -kHDXShi8fgGwsOsVHkQGzaRP6AzRwyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW -5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83QOGt4A1WNzAd -BgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIB -AGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0t -tGlTITVX1olNc79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn -68xDiBaiA9a5F/gZbG0jAn/xX9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNn -TKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDRIG4kqIQnoVesqlVYL9zZyvpoBJ7t -RCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq/p1hvIbZv97Tujqx -f36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0RFxbI -Qh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz -8ppy6rBePm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4 -NxKfKjLji7gh7MMrZQzvIt6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzX -xeSDwWrruoBa3lwtcHb4yOWHh8qgnaHlIhInD0Q9HWzq1MKLL295q39QpsQZp6F6 -t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X ------END CERTIFICATE----- - -# Issuer: CN=SecureSign Root CA12 O=Cybertrust Japan Co., Ltd. -# Subject: CN=SecureSign Root CA12 O=Cybertrust Japan Co., Ltd. -# Label: "SecureSign Root CA12" -# Serial: 587887345431707215246142177076162061960426065942 -# MD5 Fingerprint: c6:89:ca:64:42:9b:62:08:49:0b:1e:7f:e9:07:3d:e8 -# SHA1 Fingerprint: 7a:22:1e:3d:de:1b:06:ac:9e:c8:47:70:16:8e:3c:e5:f7:6b:06:f4 -# SHA256 Fingerprint: 3f:03:4b:b5:70:4d:44:b2:d0:85:45:a0:20:57:de:93:eb:f3:90:5f:ce:72:1a:cb:c7:30:c0:6d:da:ee:90:4e ------BEGIN CERTIFICATE----- -MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQEL -BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u -LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgw -NTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD -eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS -b290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3emhF -KxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mt -p7JIKwccJ/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zd -J1M3s6oYwlkm7Fsf0uZlfO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gur -FzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBFEaCeVESE99g2zvVQR9wsMJvuwPWW0v4J -hscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1UefNzFJM3IFTQy2VYzxV4+K -h9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsF -AAOCAQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6Ld -mmQOmFxv3Y67ilQiLUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJ -mBClnW8Zt7vPemVV2zfrPIpyMpcemik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA -8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPSvWKErI4cqc1avTc7bgoitPQV -55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhgaaaI5gdka9at/ -yOPiZwud9AzqVN/Ssq+xIvEg37xEHA== ------END CERTIFICATE----- - -# Issuer: CN=SecureSign Root CA14 O=Cybertrust Japan Co., Ltd. -# Subject: CN=SecureSign Root CA14 O=Cybertrust Japan Co., Ltd. -# Label: "SecureSign Root CA14" -# Serial: 575790784512929437950770173562378038616896959179 -# MD5 Fingerprint: 71:0d:72:fa:92:19:65:5e:89:04:ac:16:33:f0:bc:d5 -# SHA1 Fingerprint: dd:50:c0:f7:79:b3:64:2e:74:a2:b8:9d:9f:d3:40:dd:bb:f0:f2:4f -# SHA256 Fingerprint: 4b:00:9c:10:34:49:4f:9a:b5:6b:ba:3b:a1:d6:27:31:fc:4d:20:d8:95:5a:dc:ec:10:a9:25:60:72:61:e3:38 ------BEGIN CERTIFICATE----- -MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEM -BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u -LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgw -NzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD -eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS -b290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh1oq/ -FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOg -vlIfX8xnbacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy -6pJxaeQp8E+BgQQ8sqVb1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo -/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9J -kdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOEkJTRX45zGRBdAuVwpcAQ -0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSxjVIHvXib -y8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac -18izju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs -0Wq2XSqypWa9a4X0dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIAB -SMbHdPTGrMNASRZhdCyvjG817XsYAFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVL -ApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeqYR3r6/wtbyPk -86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0E -rX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ib -ed87hwriZLoAymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopT -zfFP7ELyk+OZpDc8h7hi2/DsHzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHS -DCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPGFrojutzdfhrGe0K22VoF3Jpf1d+4 -2kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6qnsb58Nn4DSEC5MUo -FlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/OfVy -K4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6 -dB7h7sxaOgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtl -Lor6CZpO2oYofaphNdgOpygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB -365jJ6UeTo3cKXhZ+PmhIIynJkBugnLNeLLIjzwec+fBH7/PzqUqm9tEZDKgu39c -JRNItX+S ------END CERTIFICATE----- - -# Issuer: CN=SecureSign Root CA15 O=Cybertrust Japan Co., Ltd. -# Subject: CN=SecureSign Root CA15 O=Cybertrust Japan Co., Ltd. -# Label: "SecureSign Root CA15" -# Serial: 126083514594751269499665114766174399806381178503 -# MD5 Fingerprint: 13:30:fc:c4:62:a6:a9:de:b5:c1:68:af:b5:d2:31:47 -# SHA1 Fingerprint: cb:ba:83:c8:c1:5a:5d:f1:f9:73:6f:ca:d7:ef:28:13:06:4a:07:7d -# SHA256 Fingerprint: e7:78:f0:f0:95:fe:84:37:29:cd:1a:00:82:17:9e:53:14:a9:c2:91:44:28:05:e1:fb:1d:8f:b6:b8:88:6c:3a ------BEGIN CERTIFICATE----- -MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMw -UTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBM -dGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMy -NTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJl -cnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBSb290 -IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5GdCx4 -wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSR -ZHX+AezB2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMB -Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT -9DAKBggqhkjOPQQDAwNoADBlAjEA2S6Jfl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp -4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJSwdLZrWeqrqgHkHZAXQ6 -bkU6iYAZezKYVWOr62Nuk22rGwlgMU4= ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST BR Root CA 2 2023 O=D-Trust GmbH -# Subject: CN=D-TRUST BR Root CA 2 2023 O=D-Trust GmbH -# Label: "D-TRUST BR Root CA 2 2023" -# Serial: 153168538924886464690566649552453098598 -# MD5 Fingerprint: e1:09:ed:d3:60:d4:56:1b:47:1f:b7:0c:5f:1b:5f:85 -# SHA1 Fingerprint: 2d:b0:70:ee:71:94:af:69:68:17:db:79:ce:58:9f:a0:6b:96:f7:87 -# SHA256 Fingerprint: 05:52:e6:f8:3f:df:65:e8:fa:96:70:e6:66:df:28:a4:e2:13:40:b5:10:cb:e5:25:66:f9:7c:4f:b9:4b:2b:d1 ------BEGIN CERTIFICATE----- -MIIFqTCCA5GgAwIBAgIQczswBEhb2U14LnNLyaHcZjANBgkqhkiG9w0BAQ0FADBI -MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE -LVRSVVNUIEJSIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA4NTYzMVoXDTM4MDUw -OTA4NTYzMFowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEi -MCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDIgMjAyMzCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBAK7/CVmRgApKaOYkP7in5Mg6CjoWzckjYaCTcfKr -i3OPoGdlYNJUa2NRb0kz4HIHE304zQaSBylSa053bATTlfrdTIzZXcFhfUvnKLNE -gXtRr90zsWh81k5M/itoucpmacTsXld/9w3HnDY25QdgrMBM6ghs7wZ8T1soegj8 -k12b9py0i4a6Ibn08OhZWiihNIQaJZG2tY/vsvmA+vk9PBFy2OMvhnbFeSzBqZCT -Rphny4NqoFAjpzv2gTng7fC5v2Xx2Mt6++9zA84A9H3X4F07ZrjcjrqDy4d2A/wl -2ecjbwb9Z/Pg/4S8R7+1FhhGaRTMBffb00msa8yr5LULQyReS2tNZ9/WtT5PeB+U -cSTq3nD88ZP+npNa5JRal1QMNXtfbO4AHyTsA7oC9Xb0n9Sa7YUsOCIvx9gvdhFP -/Wxc6PWOJ4d/GUohR5AdeY0cW/jPSoXk7bNbjb7EZChdQcRurDhaTyN0dKkSw/bS -uREVMweR2Ds3OmMwBtHFIjYoYiMQ4EbMl6zWK11kJNXuHA7e+whadSr2Y23OC0K+ -0bpwHJwh5Q8xaRfX/Aq03u2AnMuStIv13lmiWAmlY0cL4UEyNEHZmrHZqLAbWt4N -DfTisl01gLmB1IRpkQLLddCNxbU9CZEJjxShFHR5PtbJFR2kWVki3PaKRT08EtY+ -XTIvAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUZ5Dw1t61 -GNVGKX5cq/ieCLxklRAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRCMEAwPqA8oDqG -OGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfYnJfcm9vdF9jYV8y -XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQA097N3U9swFrktpSHxQCF16+tI -FoE9c+CeJyrrd6kTpGoKWloUMz1oH4Guaf2Mn2VsNELZLdB/eBaxOqwjMa1ef67n -riv6uvw8l5VAk1/DLQOj7aRvU9f6QA4w9QAgLABMjDu0ox+2v5Eyq6+SmNMW5tTR -VFxDWy6u71cqqLRvpO8NVhTaIasgdp4D/Ca4nj8+AybmTNudX0KEPUUDAxxZiMrc -LmEkWqTqJwtzEr5SswrPMhfiHocaFpVIbVrg0M8JkiZmkdijYQ6qgYF/6FKC0ULn -4B0Y+qSFNueG4A3rvNTJ1jxD8V1Jbn6Bm2m1iWKPiFLY1/4nwSPFyysCu7Ff/vtD -hQNGvl3GyiEm/9cCnnRK3PgTFbGBVzbLZVzRHTF36SXDw7IyN9XxmAnkbWOACKsG -koHU6XCPpz+y7YaMgmo1yEJagtFSGkUPFaUA8JR7ZSdXOUPPfH/mvTWze/EZTN46 -ls/pdu4D58JDUjxqgejBWoC9EV2Ta/vH5mQ/u2kc6d0li690yVRAysuTEwrt+2aS -Ecr1wPrYg1UDfNPFIkZ1cGt5SAYqgpq/5usWDiJFAbzdNpQ0qTUmiteXue4Icr80 -knCDgKs4qllo3UCkGJCy89UDyibK79XH4I9TjvAA46jtn/mtd+ArY0+ew+43u3gJ -hJ65bvspmZDogNOfJA== ------END CERTIFICATE----- - -# Issuer: CN=TrustAsia TLS ECC Root CA O=TrustAsia Technologies, Inc. -# Subject: CN=TrustAsia TLS ECC Root CA O=TrustAsia Technologies, Inc. -# Label: "TrustAsia TLS ECC Root CA" -# Serial: 310892014698942880364840003424242768478804666567 -# MD5 Fingerprint: 09:48:04:77:d2:fc:65:93:71:66:b1:11:95:4f:06:8c -# SHA1 Fingerprint: b5:ec:39:f3:a1:66:37:ae:c3:05:94:57:e2:be:11:be:b7:a1:7f:36 -# SHA256 Fingerprint: c0:07:6b:9e:f0:53:1f:b1:a6:56:d6:7c:4e:be:97:cd:5d:ba:a4:1e:f4:45:98:ac:c2:48:98:78:c9:2d:87:11 ------BEGIN CERTIFICATE----- -MIICMTCCAbegAwIBAgIUNnThTXxlE8msg1UloD5Sfi9QaMcwCgYIKoZIzj0EAwMw -WDELMAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs -IEluYy4xIjAgBgNVBAMTGVRydXN0QXNpYSBUTFMgRUNDIFJvb3QgQ0EwHhcNMjQw -NTE1MDU0MTU2WhcNNDQwNTE1MDU0MTU1WjBYMQswCQYDVQQGEwJDTjElMCMGA1UE -ChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywgSW5jLjEiMCAGA1UEAxMZVHJ1c3RB -c2lhIFRMUyBFQ0MgUm9vdCBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLh/pVs/ -AT598IhtrimY4ZtcU5nb9wj/1WrgjstEpvDBjL1P1M7UiFPoXlfXTr4sP/MSpwDp -guMqWzJ8S5sUKZ74LYO1644xST0mYekdcouJtgq7nDM1D9rs3qlKH8kzsaNCMEAw -DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQULIVTu7FDzTLqnqOH/qKYqKaT6RAw -DgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMFRH18MtYYZI9HlaVQ01 -L18N9mdsd0AaRuf4aFtOJx24mH1/k78ITcTaRTChD15KeAIxAKORh/IRM4PDwYqR -OkwrULG9IpRdNYlzg8WbGf60oenUoWa2AaU2+dhoYSi3dOGiMQ== ------END CERTIFICATE----- - -# Issuer: CN=TrustAsia TLS RSA Root CA O=TrustAsia Technologies, Inc. -# Subject: CN=TrustAsia TLS RSA Root CA O=TrustAsia Technologies, Inc. -# Label: "TrustAsia TLS RSA Root CA" -# Serial: 160405846464868906657516898462547310235378010780 -# MD5 Fingerprint: 3b:9e:c3:86:0f:34:3c:6b:c5:46:c4:8e:1d:e7:19:12 -# SHA1 Fingerprint: a5:46:50:c5:62:ea:95:9a:1a:a7:04:6f:17:58:c7:29:53:3d:03:fa -# SHA256 Fingerprint: 06:c0:8d:7d:af:d8:76:97:1e:b1:12:4f:e6:7f:84:7e:c0:c7:a1:58:d3:ea:53:cb:e9:40:e2:ea:97:91:f4:c3 ------BEGIN CERTIFICATE----- -MIIFgDCCA2igAwIBAgIUHBjYz+VTPyI1RlNUJDxsR9FcSpwwDQYJKoZIhvcNAQEM -BQAwWDELMAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dp -ZXMsIEluYy4xIjAgBgNVBAMTGVRydXN0QXNpYSBUTFMgUlNBIFJvb3QgQ0EwHhcN -MjQwNTE1MDU0MTU3WhcNNDQwNTE1MDU0MTU2WjBYMQswCQYDVQQGEwJDTjElMCMG -A1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywgSW5jLjEiMCAGA1UEAxMZVHJ1 -c3RBc2lhIFRMUyBSU0EgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC -AgoCggIBAMMWuBtqpERz5dZO9LnPWwvB0ZqB9WOwj0PBuwhaGnrhB3YmH49pVr7+ -NmDQDIPNlOrnxS1cLwUWAp4KqC/lYCZUlviYQB2srp10Zy9U+5RjmOMmSoPGlbYJ -Q1DNDX3eRA5gEk9bNb2/mThtfWza4mhzH/kxpRkQcwUqwzIZheo0qt1CHjCNP561 -HmHVb70AcnKtEj+qpklz8oYVlQwQX1Fkzv93uMltrOXVmPGZLmzjyUT5tUMnCE32 -ft5EebuyjBza00tsLtbDeLdM1aTk2tyKjg7/D8OmYCYozza/+lcK7Fs/6TAWe8Tb -xNRkoDD75f0dcZLdKY9BWN4ArTr9PXwaqLEX8E40eFgl1oUh63kd0Nyrz2I8sMeX -i9bQn9P+PN7F4/w6g3CEIR0JwqH8uyghZVNgepBtljhb//HXeltt08lwSUq6HTrQ -UNoyIBnkiz/r1RYmNzz7dZ6wB3C4FGB33PYPXFIKvF1tjVEK2sUYyJtt3LCDs3+j -TnhMmCWr8n4uIF6CFabW2I+s5c0yhsj55NqJ4js+k8UTav/H9xj8Z7XvGCxUq0DT -bE3txci3OE9kxJRMT6DNrqXGJyV1J23G2pyOsAWZ1SgRxSHUuPzHlqtKZFlhaxP8 -S8ySpg+kUb8OWJDZgoM5pl+z+m6Ss80zDoWo8SnTq1mt1tve1CuBAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLgHkXlcBvRG/XtZylomkadFK/hT -MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQwFAAOCAgEAIZtqBSBdGBanEqT3 -Rz/NyjuujsCCztxIJXgXbODgcMTWltnZ9r96nBO7U5WS/8+S4PPFJzVXqDuiGev4 -iqME3mmL5Dw8veWv0BIb5Ylrc5tvJQJLkIKvQMKtuppgJFqBTQUYo+IzeXoLH5Pt -7DlK9RME7I10nYEKqG/odv6LTytpEoYKNDbdgptvT+Bz3Ul/KD7JO6NXBNiT2Twp -2xIQaOHEibgGIOcberyxk2GaGUARtWqFVwHxtlotJnMnlvm5P1vQiJ3koP26TpUJ -g3933FEFlJ0gcXax7PqJtZwuhfG5WyRasQmr2soaB82G39tp27RIGAAtvKLEiUUj -pQ7hRGU+isFqMB3iYPg6qocJQrmBktwliJiJ8Xw18WLK7nn4GS/+X/jbh87qqA8M -pugLoDzga5SYnH+tBuYc6kIQX+ImFTw3OffXvO645e8D7r0i+yiGNFjEWn9hongP -XvPKnbwbPKfILfanIhHKA9jnZwqKDss1jjQ52MjqjZ9k4DewbNfFj8GQYSbbJIwe -SsCI3zWQzj8C9GRh3sfIB5XeMhg6j6JCQCTl1jNdfK7vsU1P1FeQNWrcrgSXSYk0 -ly4wBOeY99sLAZDBHwo/+ML+TvrbmnNzFrwFuHnYWa8G5z9nODmxfKuU4CkUpijy -323imttUQ/hHWKNddBWcwauwxzQ= ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST EV Root CA 2 2023 O=D-Trust GmbH -# Subject: CN=D-TRUST EV Root CA 2 2023 O=D-Trust GmbH -# Label: "D-TRUST EV Root CA 2 2023" -# Serial: 139766439402180512324132425437959641711 -# MD5 Fingerprint: 96:b4:78:09:f0:09:cb:77:eb:bb:1b:4d:6f:36:bc:b6 -# SHA1 Fingerprint: a5:5b:d8:47:6c:8f:19:f7:4c:f4:6d:6b:b6:c2:79:82:22:df:54:8b -# SHA256 Fingerprint: 8e:82:21:b2:e7:d4:00:78:36:a1:67:2f:0d:cc:29:9c:33:bc:07:d3:16:f1:32:fa:1a:20:6d:58:71:50:f1:ce ------BEGIN CERTIFICATE----- -MIIFqTCCA5GgAwIBAgIQaSYJfoBLTKCnjHhiU19abzANBgkqhkiG9w0BAQ0FADBI -MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE -LVRSVVNUIEVWIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA5MTAzM1oXDTM4MDUw -OTA5MTAzMlowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEi -MCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDIgMjAyMzCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBANiOo4mAC7JXUtypU0w3uX9jFxPvp1sjW2l1sJkK -F8GLxNuo4MwxusLyzV3pt/gdr2rElYfXR8mV2IIEUD2BCP/kPbOx1sWy/YgJ25yE -7CUXFId/MHibaljJtnMoPDT3mfd/06b4HEV8rSyMlD/YZxBTfiLNTiVR8CUkNRFe -EMbsh2aJgWi6zCudR3Mfvc2RpHJqnKIbGKBv7FD0fUDCqDDPvXPIEysQEx6Lmqg6 -lHPTGGkKSv/BAQP/eX+1SH977ugpbzZMlWGG2Pmic4ruri+W7mjNPU0oQvlFKzIb -RlUWaqZLKfm7lVa/Rh3sHZMdwGWyH6FDrlaeoLGPaxK3YG14C8qKXO0elg6DpkiV -jTujIcSuWMYAsoS0I6SWhjW42J7YrDRJmGOVxcttSEfi8i4YHtAxq9107PncjLgc -jmgjutDzUNzPZY9zOjLHfP7KgiJPvo5iR2blzYfi6NUPGJ/lBHJLRjwQ8kTCZFZx -TnXonMkmdMV9WdEKWw9t/p51HBjGGjp82A0EzM23RWV6sY+4roRIPrN6TagD4uJ+ -ARZZaBhDM7DS3LAaQzXupdqpRlyuhoFBAUp0JuyfBr/CBTdkdXgpaP3F9ev+R/nk -hbDhezGdpn9yo7nELC7MmVcOIQxFAZRl62UJxmMiCzNJkkg8/M3OsD6Onov4/knF -NXJHAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqvyREBuH -kV8Wub9PS5FeAByxMoAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRCMEAwPqA8oDqG -OGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfZXZfcm9vdF9jYV8y -XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQCTy6UfmRHsmg1fLBWTxj++EI14 -QvBukEdHjqOSMo1wj/Zbjb6JzkcBahsgIIlbyIIQbODnmaprxiqgYzWRaoUlrRc4 -pZt+UPJ26oUFKidBK7GB0aL2QHWpDsvxVUjY7NHss+jOFKE17MJeNRqrphYBBo7q -3C+jisosketSjl8MmxfPy3MHGcRqwnNU73xDUmPBEcrCRbH0O1P1aa4846XerOhU -t7KR/aypH/KH5BfGSah82ApB9PI+53c0BFLd6IHyTS9URZ0V4U/M5d40VxDJI3IX -cI1QcB9WbMy5/zpaT2N6w25lBx2Eof+pDGOJbbJAiDnXH3dotfyc1dZnaVuodNv8 -ifYbMvekJKZ2t0dT741Jj6m2g1qllpBFYfXeA08mD6iL8AOWsKwV0HFaanuU5nCT -2vFp4LJiTZ6P/4mdm13NRemUAiKN4DV/6PEEeXFsVIP4M7kFMhtYVRFP0OUnR3Hs -7dpn1mKmS00PaaLJvOwiS5THaJQXfuKOKD62xur1NGyfN4gHONuGcfrNlUhDbqNP -gofXNJhuS5N5YHVpD/Aa1VP6IQzCP+k/HxiMkl14p3ZnGbuy6n/pcAlWVqOwDAst -Nl7F6cTVg8uGF5csbBNvh1qvSaYd2804BC5f4ko1Di1L+KIkBI3Y4WNeApI02phh -XBxvWHZks/wCuPWdCg== ------END CERTIFICATE----- - -# Issuer: CN=SwissSign RSA TLS Root CA 2022 - 1 O=SwissSign AG -# Subject: CN=SwissSign RSA TLS Root CA 2022 - 1 O=SwissSign AG -# Label: "SwissSign RSA TLS Root CA 2022 - 1" -# Serial: 388078645722908516278762308316089881486363258315 -# MD5 Fingerprint: 16:2e:e4:19:76:81:85:ba:8e:91:58:f1:15:ef:72:39 -# SHA1 Fingerprint: 81:34:0a:be:4c:cd:ce:cc:e7:7d:cc:8a:d4:57:e2:45:a0:77:5d:ce -# SHA256 Fingerprint: 19:31:44:f4:31:e0:fd:db:74:07:17:d4:de:92:6a:57:11:33:88:4b:43:60:d3:0e:27:29:13:cb:e6:60:ce:41 ------BEGIN CERTIFICATE----- -MIIFkzCCA3ugAwIBAgIUQ/oMX04bgBhE79G0TzUfRPSA7cswDQYJKoZIhvcNAQEL -BQAwUTELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzErMCkGA1UE -AxMiU3dpc3NTaWduIFJTQSBUTFMgUm9vdCBDQSAyMDIyIC0gMTAeFw0yMjA2MDgx -MTA4MjJaFw00NzA2MDgxMTA4MjJaMFExCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxT -d2lzc1NpZ24gQUcxKzApBgNVBAMTIlN3aXNzU2lnbiBSU0EgVExTIFJvb3QgQ0Eg -MjAyMiAtIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDLKmjiC8NX -vDVjvHClO/OMPE5Xlm7DTjak9gLKHqquuN6orx122ro10JFwB9+zBvKK8i5VUXu7 -LCTLf5ImgKO0lPaCoaTo+nUdWfMHamFk4saMla+ju45vVs9xzF6BYQ1t8qsCLqSX -5XH8irCRIFucdFJtrhUnWXjyCcplDn/L9Ovn3KlMd/YrFgSVrpxxpT8q2kFC5zyE -EPThPYxr4iuRR1VPuFa+Rd4iUU1OKNlfGUEGjw5NBuBwQCMBauTLE5tzrE0USJIt -/m2n+IdreXXhvhCxqohAWVTXz8TQm0SzOGlkjIHRI36qOTw7D59Ke4LKa2/KIj4x -0LDQKhySio/YGZxH5D4MucLNvkEM+KRHBdvBFzA4OmnczcNpI/2aDwLOEGrOyvi5 -KaM2iYauC8BPY7kGWUleDsFpswrzd34unYyzJ5jSmY0lpx+Gs6ZUcDj8fV3oT4MM -0ZPlEuRU2j7yrTrePjxF8CgPBrnh25d7mUWe3f6VWQQvdT/TromZhqwUtKiE+shd -OxtYk8EXlFXIC+OCeYSf8wCENO7cMdWP8vpPlkwGqnj73mSiI80fPsWMvDdUDrta -clXvyFu1cvh43zcgTFeRc5JzrBh3Q4IgaezprClG5QtO+DdziZaKHG29777YtvTK -wP1H8K4LWCDFyB02rpeNUIMmJCn3nTsPBQIDAQABo2MwYTAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBRvjmKLk0Ow4UD2p8P98Q+4 -DxU4pTAdBgNVHQ4EFgQUb45ii5NDsOFA9qfD/fEPuA8VOKUwDQYJKoZIhvcNAQEL -BQADggIBAKwsKUF9+lz1GpUYvyypiqkkVHX1uECry6gkUSsYP2OprphWKwVDIqO3 -10aewCoSPY6WlkDfDDOLazeROpW7OSltwAJsipQLBwJNGD77+3v1dj2b9l4wBlgz -Hqp41eZUBDqyggmNzhYzWUUo8aWjlw5DI/0LIICQ/+Mmz7hkkeUFjxOgdg3XNwwQ -iJb0Pr6VvfHDffCjw3lHC1ySFWPtUnWK50Zpy1FVCypM9fJkT6lc/2cyjlUtMoIc -gC9qkfjLvH4YoiaoLqNTKIftV+Vlek4ASltOU8liNr3CjlvrzG4ngRhZi0Rjn9UM -ZfQpZX+RLOV/fuiJz48gy20HQhFRJjKKLjpHE7iNvUcNCfAWpO2Whi4Z2L6MOuhF -LhG6rlrnub+xzI/goP+4s9GFe3lmozm1O2bYQL7Pt2eLSMkZJVX8vY3PXtpOpvJp -zv1/THfQwUY1mFwjmwJFQ5Ra3bxHrSL+ul4vkSkphnsh3m5kt8sNjzdbowhq6/Td -Ao9QAwKxuDdollDruF/UKIqlIgyKhPBZLtU30WHlQnNYKoH3dtvi4k0NX/a3vgW0 -rk4N3hY9A4GzJl5LuEsAz/+MF7psYC0nhzck5npgL7XTgwSqT0N1osGDsieYK7EO -gLrAhV5Cud+xYJHT6xh+cHiudoO+cVrQkOPKwRYlZ0rwtnu64ZzZ ------END CERTIFICATE----- - -# Issuer: CN=OISTE Server Root ECC G1 O=OISTE Foundation -# Subject: CN=OISTE Server Root ECC G1 O=OISTE Foundation -# Label: "OISTE Server Root ECC G1" -# Serial: 47819833811561661340092227008453318557 -# MD5 Fingerprint: 42:a7:d2:35:ae:02:92:db:19:76:08:de:2f:05:b4:d4 -# SHA1 Fingerprint: 3b:f6:8b:09:ae:2a:92:7b:ba:e3:8d:3f:11:95:d9:e6:44:0c:45:e2 -# SHA256 Fingerprint: ee:c9:97:c0:c3:0f:21:6f:7e:3b:8b:30:7d:2b:ae:42:41:2d:75:3f:c8:21:9d:af:d1:52:0b:25:72:85:0f:49 ------BEGIN CERTIFICATE----- -MIICNTCCAbqgAwIBAgIQI/nD1jWvjyhLH/BU6n6XnTAKBggqhkjOPQQDAzBLMQsw -CQYDVQQGEwJDSDEZMBcGA1UECgwQT0lTVEUgRm91bmRhdGlvbjEhMB8GA1UEAwwY -T0lTVEUgU2VydmVyIFJvb3QgRUNDIEcxMB4XDTIzMDUzMTE0NDIyOFoXDTQ4MDUy -NDE0NDIyN1owSzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoMEE9JU1RFIEZvdW5kYXRp -b24xITAfBgNVBAMMGE9JU1RFIFNlcnZlciBSb290IEVDQyBHMTB2MBAGByqGSM49 -AgEGBSuBBAAiA2IABBcv+hK8rBjzCvRE1nZCnrPoH7d5qVi2+GXROiFPqOujvqQy -cvO2Ackr/XeFblPdreqqLiWStukhEaivtUwL85Zgmjvn6hp4LrQ95SjeHIC6XG4N -2xml4z+cKrhAS93mT6NjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBQ3 -TYhlz/w9itWj8UnATgwQb0K0nDAdBgNVHQ4EFgQUN02IZc/8PYrVo/FJwE4MEG9C -tJwwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2kAMGYCMQCpKjAd0MKfkFFR -QD6VVCHNFmb3U2wIFjnQEnx/Yxvf4zgAOdktUyBFCxxgZzFDJe0CMQCSia7pXGKD -YmH5LVerVrkR3SW+ak5KGoJr3M/TvEqzPNcum9v4KGm8ay3sMaE641c= ------END CERTIFICATE----- - -# Issuer: CN=OISTE Server Root RSA G1 O=OISTE Foundation -# Subject: CN=OISTE Server Root RSA G1 O=OISTE Foundation -# Label: "OISTE Server Root RSA G1" -# Serial: 113845518112613905024960613408179309848 -# MD5 Fingerprint: 23:a7:9e:d4:70:b8:b9:14:57:41:8a:7e:44:59:e2:68 -# SHA1 Fingerprint: f7:00:34:25:94:88:68:31:e4:34:87:3f:70:fe:86:b3:86:9f:f0:6e -# SHA256 Fingerprint: 9a:e3:62:32:a5:18:9f:fd:db:35:3d:fd:26:52:0c:01:53:95:d2:27:77:da:c5:9d:b5:7b:98:c0:89:a6:51:e6 ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIQVaXZZ5Qoxu0M+ifdWwFNGDANBgkqhkiG9w0BAQwFADBL -MQswCQYDVQQGEwJDSDEZMBcGA1UECgwQT0lTVEUgRm91bmRhdGlvbjEhMB8GA1UE -AwwYT0lTVEUgU2VydmVyIFJvb3QgUlNBIEcxMB4XDTIzMDUzMTE0MzcxNloXDTQ4 -MDUyNDE0MzcxNVowSzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoMEE9JU1RFIEZvdW5k -YXRpb24xITAfBgNVBAMMGE9JU1RFIFNlcnZlciBSb290IFJTQSBHMTCCAiIwDQYJ -KoZIhvcNAQEBBQADggIPADCCAgoCggIBAKqu9KuCz/vlNwvn1ZatkOhLKdxVYOPM -vLO8LZK55KN68YG0nnJyQ98/qwsmtO57Gmn7KNByXEptaZnwYx4M0rH/1ow00O7b -rEi56rAUjtgHqSSY3ekJvqgiG1k50SeH3BzN+Puz6+mTeO0Pzjd8JnduodgsIUzk -ik/HEzxux9UTl7Ko2yRpg1bTacuCErudG/L4NPKYKyqOBGf244ehHa1uzjZ0Dl4z -O8vbUZeUapU8zhhabkvG/AePLhq5SvdkNCncpo1Q4Y2LS+VIG24ugBA/5J8bZT8R -tOpXaZ+0AOuFJJkk9SGdl6r7NH8CaxWQrbueWhl/pIzY+m0o/DjH40ytas7ZTpOS -jswMZ78LS5bOZmdTaMsXEY5Z96ycG7mOaES3GK/m5Q9l3JUJsJMStR8+lKXHiHUh -sd4JJCpM4rzsTGdHwimIuQq6+cF0zowYJmXa92/GjHtoXAvuY8BeS/FOzJ8vD+Ho -mnqT8eDI278n5mUpezbgMxVz8p1rhAhoKzYHKyfMeNhqhw5HdPSqoBNdZH702xSu -+zrkL8Fl47l6QGzwBrd7KJvX4V84c5Ss2XCTLdyEr0YconosP4EmQufU2MVshGYR -i3drVByjtdgQ8K4p92cIiBdcuJd5z+orKu5YM+Vt6SmqZQENghPsJQtdLEByFSnT -kCz3GkPVavBpAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU -8snBDw1jALvsRQ5KH7WxszbNDo0wHQYDVR0OBBYEFPLJwQ8NYwC77EUOSh+1sbM2 -zQ6NMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQwFAAOCAgEANGd5sjrG5T33 -I3K5Ce+SrScfoE4KsvXaFwyihdJ+klH9FWXXXGtkFu6KRcoMQzZENdl//nk6HOjG -5D1rd9QhEOP28yBOqb6J8xycqd+8MDoX0TJD0KqKchxRKEzdNsjkLWd9kYccnbz8 -qyiWXmFcuCIzGEgWUOrKL+mlSdx/PKQZvDatkuK59EvV6wit53j+F8Bdh3foZ3dP -AGav9LEDOr4SfEE15fSmG0eLy3n31r8Xbk5l8PjaV8GUgeV6Vg27Rn9vkf195hfk -gSe7BYhW3SCl95gtkRlpMV+bMPKZrXJAlszYd2abtNUOshD+FKrDgHGdPY3ofRRs -YWSGRqbXVMW215AWRqWFyp464+YTFrYVI8ypKVL9AMb2kI5Wj4kI3Zaq5tNqqYY1 -9tVFeEJKRvwDyF7YZvZFZSS0vod7VSCd9521Kvy5YhnLbDuv0204bKt7ph6N/Ome -/msVuduCmsuY33OhkKCgxeDoAaijFJzIwZqsFVAzje18KotzlUBDJvyBpCpfOZC3 -J8tRd/iWkx7P8nd9H0aTolkelUTFLXVksNb54Dxp6gS1HAviRkRNQzuXSXERvSS2 -wq1yVAb+axj5d9spLFKebXd7Yv0PTY6YMjAwcRLWJTXjn/hvnLXrahut6hDTlhZy -BiElxky8j3C7DOReIoMt0r7+hVu05L0= ------END CERTIFICATE----- - -# Issuer: CN=e-Szigno TLS Root CA 2023 O=Microsec Ltd. -# Subject: CN=e-Szigno TLS Root CA 2023 O=Microsec Ltd. -# Label: "e-Szigno TLS Root CA 2023" -# Serial: 71934828665710877219916191754 -# MD5 Fingerprint: 6a:e9:99:74:a5:da:5e:f1:d9:2e:f2:c8:d1:86:8b:71 -# SHA1 Fingerprint: 6f:9a:d5:d5:df:e8:2c:eb:be:37:07:ee:4f:4f:52:58:29:41:d1:fe -# SHA256 Fingerprint: b4:91:41:50:2d:00:66:3d:74:0f:2e:7e:c3:40:c5:28:00:96:26:66:12:1a:36:d0:9c:f7:dd:2b:90:38:4f:b4 ------BEGIN CERTIFICATE----- -MIICzzCCAjGgAwIBAgINAOhvGHvWOWuYSkmYCjAKBggqhkjOPQQDBDB1MQswCQYD -VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 -ZC4xFzAVBgNVBGEMDlZBVEhVLTIzNTg0NDk3MSIwIAYDVQQDDBllLVN6aWdubyBU -TFMgUm9vdCBDQSAyMDIzMB4XDTIzMDcxNzE0MDAwMFoXDTM4MDcxNzE0MDAwMFow -dTELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRYwFAYDVQQKDA1NaWNy -b3NlYyBMdGQuMRcwFQYDVQRhDA5WQVRIVS0yMzU4NDQ5NzEiMCAGA1UEAwwZZS1T -emlnbm8gVExTIFJvb3QgQ0EgMjAyMzCBmzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAE -AGgP36J8PKp0iGEKjcJMpQEiFNT3YHdCnAo4YKGMZz6zY+n6kbCLS+Y53wLCMAFS -AL/fjO1ZrTJlqwlZULUZwmgcAOAFX9pQJhzDrAQixTpN7+lXWDajwRlTEArRzT/v -SzUaQ49CE0y5LBqcvjC2xN7cS53kpDzLLtmt3999Cd8ukv+ho2MwYTAPBgNVHRMB -Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUWYQCYlpGePVd3I8K -ECgj3NXW+0UwHwYDVR0jBBgwFoAUWYQCYlpGePVd3I8KECgj3NXW+0UwCgYIKoZI -zj0EAwQDgYsAMIGHAkIBLdqu9S54tma4n7Zwf2Z0z+yOfP7AAXmazlIC58PRDHpt -y7Ve7hekm9sEdu4pKeiv+62sUvTXK9Z3hBC9xdIoaDQCQTV2WnXzkoYI9bIeCvZl -C9p2x1L/Cx6AcCIwwzPbGO2E14vs7dOoY4G1VnxHx1YwlGhza9IuqbnZLBwpvQy6 -uWWL ------END CERTIFICATE----- diff --git a/notification-service/venv/Lib/site-packages/certifi/core.py b/notification-service/venv/Lib/site-packages/certifi/core.py deleted file mode 100644 index 1c9661c..0000000 --- a/notification-service/venv/Lib/site-packages/certifi/core.py +++ /dev/null @@ -1,83 +0,0 @@ -""" -certifi.py -~~~~~~~~~~ - -This module returns the installation location of cacert.pem or its contents. -""" -import sys -import atexit - -def exit_cacert_ctx() -> None: - _CACERT_CTX.__exit__(None, None, None) # type: ignore[union-attr] - - -if sys.version_info >= (3, 11): - - from importlib.resources import as_file, files - - _CACERT_CTX = None - _CACERT_PATH = None - - def where() -> str: - # This is slightly terrible, but we want to delay extracting the file - # in cases where we're inside of a zipimport situation until someone - # actually calls where(), but we don't want to re-extract the file - # on every call of where(), so we'll do it once then store it in a - # global variable. - global _CACERT_CTX - global _CACERT_PATH - if _CACERT_PATH is None: - # This is slightly janky, the importlib.resources API wants you to - # manage the cleanup of this file, so it doesn't actually return a - # path, it returns a context manager that will give you the path - # when you enter it and will do any cleanup when you leave it. In - # the common case of not needing a temporary file, it will just - # return the file system location and the __exit__() is a no-op. - # - # We also have to hold onto the actual context manager, because - # it will do the cleanup whenever it gets garbage collected, so - # we will also store that at the global level as well. - _CACERT_CTX = as_file(files("certifi").joinpath("cacert.pem")) - _CACERT_PATH = str(_CACERT_CTX.__enter__()) - atexit.register(exit_cacert_ctx) - - return _CACERT_PATH - - def contents() -> str: - return files("certifi").joinpath("cacert.pem").read_text(encoding="ascii") - -else: - - from importlib.resources import path as get_path, read_text - - _CACERT_CTX = None - _CACERT_PATH = None - - def where() -> str: - # This is slightly terrible, but we want to delay extracting the - # file in cases where we're inside of a zipimport situation until - # someone actually calls where(), but we don't want to re-extract - # the file on every call of where(), so we'll do it once then store - # it in a global variable. - global _CACERT_CTX - global _CACERT_PATH - if _CACERT_PATH is None: - # This is slightly janky, the importlib.resources API wants you - # to manage the cleanup of this file, so it doesn't actually - # return a path, it returns a context manager that will give - # you the path when you enter it and will do any cleanup when - # you leave it. In the common case of not needing a temporary - # file, it will just return the file system location and the - # __exit__() is a no-op. - # - # We also have to hold onto the actual context manager, because - # it will do the cleanup whenever it gets garbage collected, so - # we will also store that at the global level as well. - _CACERT_CTX = get_path("certifi", "cacert.pem") - _CACERT_PATH = str(_CACERT_CTX.__enter__()) - atexit.register(exit_cacert_ctx) - - return _CACERT_PATH - - def contents() -> str: - return read_text("certifi", "cacert.pem", encoding="ascii") diff --git a/notification-service/venv/Lib/site-packages/certifi/py.typed b/notification-service/venv/Lib/site-packages/certifi/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/INSTALLER b/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/METADATA b/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/METADATA deleted file mode 100644 index 67508e5..0000000 --- a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/METADATA +++ /dev/null @@ -1,68 +0,0 @@ -Metadata-Version: 2.4 -Name: cffi -Version: 2.0.0 -Summary: Foreign Function Interface for Python calling C code. -Author: Armin Rigo, Maciej Fijalkowski -Maintainer: Matt Davis, Matt Clay, Matti Picus -License-Expression: MIT -Project-URL: Documentation, https://cffi.readthedocs.io/ -Project-URL: Changelog, https://cffi.readthedocs.io/en/latest/whatsnew.html -Project-URL: Downloads, https://github.com/python-cffi/cffi/releases -Project-URL: Contact, https://groups.google.com/forum/#!forum/python-cffi -Project-URL: Source Code, https://github.com/python-cffi/cffi -Project-URL: Issue Tracker, https://github.com/python-cffi/cffi/issues -Classifier: Programming Language :: Python -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 :: Free Threading :: 2 - Beta -Classifier: Programming Language :: Python :: Implementation :: CPython -Requires-Python: >=3.9 -Description-Content-Type: text/markdown -License-File: LICENSE -License-File: AUTHORS -Requires-Dist: pycparser; implementation_name != "PyPy" -Dynamic: license-file - -[![GitHub Actions Status](https://github.com/python-cffi/cffi/actions/workflows/ci.yaml/badge.svg?branch=main)](https://github.com/python-cffi/cffi/actions/workflows/ci.yaml?query=branch%3Amain++) -[![PyPI version](https://img.shields.io/pypi/v/cffi.svg)](https://pypi.org/project/cffi) -[![Read the Docs](https://img.shields.io/badge/docs-latest-blue.svg)][Documentation] - - -CFFI -==== - -Foreign Function Interface for Python calling C code. - -Please see the [Documentation] or uncompiled in the `doc/` subdirectory. - -Download --------- - -[Download page](https://github.com/python-cffi/cffi/releases) - -Source Code ------------ - -Source code is publicly available on -[GitHub](https://github.com/python-cffi/cffi). - -Contact -------- - -[Mailing list](https://groups.google.com/forum/#!forum/python-cffi) - -Testing/development tips ------------------------- - -After `git clone` or `wget && tar`, we will get a directory called `cffi` or `cffi-x.x.x`. we call it `repo-directory`. To run tests under CPython, run the following in the `repo-directory`: - - pip install pytest - pip install -e . # editable install of CFFI for local development - pytest src/c/ testing/ - -[Documentation]: http://cffi.readthedocs.org/ diff --git a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/RECORD b/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/RECORD deleted file mode 100644 index b44794d..0000000 --- a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/RECORD +++ /dev/null @@ -1,49 +0,0 @@ -_cffi_backend.cp312-win_amd64.pyd,sha256=U940r8OTnYG_JJi3dCXFLiw_MWT4z-JUPTrMjyQTRIg,181248 -cffi-2.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -cffi-2.0.0.dist-info/METADATA,sha256=ZET6EC-RAp729tW1o4YJl61x9srq0O0A_tZ4N3Mi3uc,2627 -cffi-2.0.0.dist-info/RECORD,, -cffi-2.0.0.dist-info/WHEEL,sha256=8UP9x9puWI0P1V_d7K2oMTBqfeLNm21CTzZ_Ptr0NXU,101 -cffi-2.0.0.dist-info/entry_points.txt,sha256=y6jTxnyeuLnL-XJcDv8uML3n6wyYiGRg8MTp_QGJ9Ho,75 -cffi-2.0.0.dist-info/licenses/AUTHORS,sha256=KmemC7-zN1nWfWRf8TG45ta8TK_CMtdR_Kw-2k0xTMg,208 -cffi-2.0.0.dist-info/licenses/LICENSE,sha256=W6JN3FcGf5JJrdZEw6_EGl1tw34jQz73Wdld83Cwr2M,1123 -cffi-2.0.0.dist-info/top_level.txt,sha256=rE7WR3rZfNKxWI9-jn6hsHCAl7MDkB-FmuQbxWjFehQ,19 -cffi/__init__.py,sha256=-ksBQ7MfDzVvbBlV_ftYBWAmEqfA86ljIzMxzaZeAlI,511 -cffi/__pycache__/__init__.cpython-312.pyc,, -cffi/__pycache__/_imp_emulation.cpython-312.pyc,, -cffi/__pycache__/_shimmed_dist_utils.cpython-312.pyc,, -cffi/__pycache__/api.cpython-312.pyc,, -cffi/__pycache__/backend_ctypes.cpython-312.pyc,, -cffi/__pycache__/cffi_opcode.cpython-312.pyc,, -cffi/__pycache__/commontypes.cpython-312.pyc,, -cffi/__pycache__/cparser.cpython-312.pyc,, -cffi/__pycache__/error.cpython-312.pyc,, -cffi/__pycache__/ffiplatform.cpython-312.pyc,, -cffi/__pycache__/lock.cpython-312.pyc,, -cffi/__pycache__/model.cpython-312.pyc,, -cffi/__pycache__/pkgconfig.cpython-312.pyc,, -cffi/__pycache__/recompiler.cpython-312.pyc,, -cffi/__pycache__/setuptools_ext.cpython-312.pyc,, -cffi/__pycache__/vengine_cpy.cpython-312.pyc,, -cffi/__pycache__/vengine_gen.cpython-312.pyc,, -cffi/__pycache__/verifier.cpython-312.pyc,, -cffi/_cffi_errors.h,sha256=zQXt7uR_m8gUW-fI2hJg0KoSkJFwXv8RGUkEDZ177dQ,3908 -cffi/_cffi_include.h,sha256=Exhmgm9qzHWzWivjfTe0D7Xp4rPUkVxdNuwGhMTMzbw,15055 -cffi/_embedding.h,sha256=Ai33FHblE7XSpHOCp8kPcWwN5_9BV14OvN0JVa6ITpw,18786 -cffi/_imp_emulation.py,sha256=RxREG8zAbI2RPGBww90u_5fi8sWdahpdipOoPzkp7C0,2960 -cffi/_shimmed_dist_utils.py,sha256=Bjj2wm8yZbvFvWEx5AEfmqaqZyZFhYfoyLLQHkXZuao,2230 -cffi/api.py,sha256=alBv6hZQkjpmZplBphdaRn2lPO9-CORs_M7ixabvZWI,42169 -cffi/backend_ctypes.py,sha256=h5ZIzLc6BFVXnGyc9xPqZWUS7qGy7yFSDqXe68Sa8z4,42454 -cffi/cffi_opcode.py,sha256=JDV5l0R0_OadBX_uE7xPPTYtMdmpp8I9UYd6av7aiDU,5731 -cffi/commontypes.py,sha256=7N6zPtCFlvxXMWhHV08psUjdYIK2XgsN3yo5dgua_v4,2805 -cffi/cparser.py,sha256=QUTfmlL-aO-MYR8bFGlvAUHc36OQr7XYLe0WLkGFjRo,44790 -cffi/error.py,sha256=v6xTiS4U0kvDcy4h_BDRo5v39ZQuj-IMRYLv5ETddZs,877 -cffi/ffiplatform.py,sha256=avxFjdikYGJoEtmJO7ewVmwG_VEVl6EZ_WaNhZYCqv4,3584 -cffi/lock.py,sha256=l9TTdwMIMpi6jDkJGnQgE9cvTIR7CAntIJr8EGHt3pY,747 -cffi/model.py,sha256=W30UFQZE73jL5Mx5N81YT77us2W2iJjTm0XYfnwz1cg,21797 -cffi/parse_c_type.h,sha256=OdwQfwM9ktq6vlCB43exFQmxDBtj2MBNdK8LYl15tjw,5976 -cffi/pkgconfig.py,sha256=LP1w7vmWvmKwyqLaU1Z243FOWGNQMrgMUZrvgFuOlco,4374 -cffi/recompiler.py,sha256=78J6lMEEOygXNmjN9-fOFFO3j7eW-iFxSrxfvQb54bY,65509 -cffi/setuptools_ext.py,sha256=0rCwBJ1W7FHWtiMKfNXsSST88V8UXrui5oeXFlDNLG8,9411 -cffi/vengine_cpy.py,sha256=oyQKD23kpE0aChUKA8Jg0e723foPiYzLYEdb-J0MiNs,43881 -cffi/vengine_gen.py,sha256=DUlEIrDiVin1Pnhn1sfoamnS5NLqfJcOdhRoeSNeJRg,26939 -cffi/verifier.py,sha256=oX8jpaohg2Qm3aHcznidAdvrVm5N4sQYG0a3Eo5mIl4,11182 diff --git a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/WHEEL b/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/WHEEL deleted file mode 100644 index 10ac2c2..0000000 --- a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (80.9.0) -Root-Is-Purelib: false -Tag: cp312-cp312-win_amd64 - diff --git a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/entry_points.txt b/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/entry_points.txt deleted file mode 100644 index 4b0274f..0000000 --- a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/entry_points.txt +++ /dev/null @@ -1,2 +0,0 @@ -[distutils.setup_keywords] -cffi_modules = cffi.setuptools_ext:cffi_modules diff --git a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/licenses/AUTHORS b/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/licenses/AUTHORS deleted file mode 100644 index 370a25d..0000000 --- a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/licenses/AUTHORS +++ /dev/null @@ -1,8 +0,0 @@ -This package has been mostly done by Armin Rigo with help from -Maciej Fijałkowski. The idea is heavily based (although not directly -copied) from LuaJIT ffi by Mike Pall. - - -Other contributors: - - Google Inc. diff --git a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/licenses/LICENSE b/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/licenses/LICENSE deleted file mode 100644 index 0a1dbfb..0000000 --- a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/licenses/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ - -Except when otherwise stated (look for LICENSE files in directories or -information at the beginning of each file) all software and -documentation is licensed as follows: - - MIT No Attribution - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or - sell copies of the Software, and to permit persons to whom the - Software is furnished to do so. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - diff --git a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/top_level.txt b/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/top_level.txt deleted file mode 100644 index f645779..0000000 --- a/notification-service/venv/Lib/site-packages/cffi-2.0.0.dist-info/top_level.txt +++ /dev/null @@ -1,2 +0,0 @@ -_cffi_backend -cffi diff --git a/notification-service/venv/Lib/site-packages/cffi/__init__.py b/notification-service/venv/Lib/site-packages/cffi/__init__.py deleted file mode 100644 index c99ec3d..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -__all__ = ['FFI', 'VerificationError', 'VerificationMissing', 'CDefError', - 'FFIError'] - -from .api import FFI -from .error import CDefError, FFIError, VerificationError, VerificationMissing -from .error import PkgConfigError - -__version__ = "2.0.0" -__version_info__ = (2, 0, 0) - -# The verifier module file names are based on the CRC32 of a string that -# contains the following version number. It may be older than __version__ -# if nothing is clearly incompatible. -__version_verifier_modules__ = "0.8.6" diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 0d20801..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/_imp_emulation.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/_imp_emulation.cpython-312.pyc deleted file mode 100644 index 9158708..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/_imp_emulation.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/_shimmed_dist_utils.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/_shimmed_dist_utils.cpython-312.pyc deleted file mode 100644 index 6d5a21d..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/_shimmed_dist_utils.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/api.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/api.cpython-312.pyc deleted file mode 100644 index 97c2023..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/api.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/backend_ctypes.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/backend_ctypes.cpython-312.pyc deleted file mode 100644 index 96b009f..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/backend_ctypes.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/cffi_opcode.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/cffi_opcode.cpython-312.pyc deleted file mode 100644 index 757e41d..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/cffi_opcode.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/commontypes.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/commontypes.cpython-312.pyc deleted file mode 100644 index 3280514..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/commontypes.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/cparser.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/cparser.cpython-312.pyc deleted file mode 100644 index 94e9233..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/cparser.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/error.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/error.cpython-312.pyc deleted file mode 100644 index 2ed8602..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/error.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/ffiplatform.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/ffiplatform.cpython-312.pyc deleted file mode 100644 index 0d00d0b..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/ffiplatform.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/lock.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/lock.cpython-312.pyc deleted file mode 100644 index 1d788de..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/lock.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/model.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/model.cpython-312.pyc deleted file mode 100644 index 811dc4b..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/model.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/pkgconfig.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/pkgconfig.cpython-312.pyc deleted file mode 100644 index 51d2c78..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/pkgconfig.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/recompiler.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/recompiler.cpython-312.pyc deleted file mode 100644 index 986a75c..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/recompiler.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/setuptools_ext.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/setuptools_ext.cpython-312.pyc deleted file mode 100644 index 302787e..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/setuptools_ext.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/vengine_cpy.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/vengine_cpy.cpython-312.pyc deleted file mode 100644 index 16f5ec2..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/vengine_cpy.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/vengine_gen.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/vengine_gen.cpython-312.pyc deleted file mode 100644 index 9fe8c33..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/vengine_gen.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/__pycache__/verifier.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cffi/__pycache__/verifier.cpython-312.pyc deleted file mode 100644 index 3ade0d6..0000000 Binary files a/notification-service/venv/Lib/site-packages/cffi/__pycache__/verifier.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cffi/_cffi_errors.h b/notification-service/venv/Lib/site-packages/cffi/_cffi_errors.h deleted file mode 100644 index 158e059..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/_cffi_errors.h +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef CFFI_MESSAGEBOX -# ifdef _MSC_VER -# define CFFI_MESSAGEBOX 1 -# else -# define CFFI_MESSAGEBOX 0 -# endif -#endif - - -#if CFFI_MESSAGEBOX -/* Windows only: logic to take the Python-CFFI embedding logic - initialization errors and display them in a background thread - with MessageBox. The idea is that if the whole program closes - as a result of this problem, then likely it is already a console - program and you can read the stderr output in the console too. - If it is not a console program, then it will likely show its own - dialog to complain, or generally not abruptly close, and for this - case the background thread should stay alive. -*/ -static void *volatile _cffi_bootstrap_text; - -static PyObject *_cffi_start_error_capture(void) -{ - PyObject *result = NULL; - PyObject *x, *m, *bi; - - if (InterlockedCompareExchangePointer(&_cffi_bootstrap_text, - (void *)1, NULL) != NULL) - return (PyObject *)1; - - m = PyImport_AddModule("_cffi_error_capture"); - if (m == NULL) - goto error; - - result = PyModule_GetDict(m); - if (result == NULL) - goto error; - -#if PY_MAJOR_VERSION >= 3 - bi = PyImport_ImportModule("builtins"); -#else - bi = PyImport_ImportModule("__builtin__"); -#endif - if (bi == NULL) - goto error; - PyDict_SetItemString(result, "__builtins__", bi); - Py_DECREF(bi); - - x = PyRun_String( - "import sys\n" - "class FileLike:\n" - " def write(self, x):\n" - " try:\n" - " of.write(x)\n" - " except: pass\n" - " self.buf += x\n" - " def flush(self):\n" - " pass\n" - "fl = FileLike()\n" - "fl.buf = ''\n" - "of = sys.stderr\n" - "sys.stderr = fl\n" - "def done():\n" - " sys.stderr = of\n" - " return fl.buf\n", /* make sure the returned value stays alive */ - Py_file_input, - result, result); - Py_XDECREF(x); - - error: - if (PyErr_Occurred()) - { - PyErr_WriteUnraisable(Py_None); - PyErr_Clear(); - } - return result; -} - -#pragma comment(lib, "user32.lib") - -static DWORD WINAPI _cffi_bootstrap_dialog(LPVOID ignored) -{ - Sleep(666); /* may be interrupted if the whole process is closing */ -#if PY_MAJOR_VERSION >= 3 - MessageBoxW(NULL, (wchar_t *)_cffi_bootstrap_text, - L"Python-CFFI error", - MB_OK | MB_ICONERROR); -#else - MessageBoxA(NULL, (char *)_cffi_bootstrap_text, - "Python-CFFI error", - MB_OK | MB_ICONERROR); -#endif - _cffi_bootstrap_text = NULL; - return 0; -} - -static void _cffi_stop_error_capture(PyObject *ecap) -{ - PyObject *s; - void *text; - - if (ecap == (PyObject *)1) - return; - - if (ecap == NULL) - goto error; - - s = PyRun_String("done()", Py_eval_input, ecap, ecap); - if (s == NULL) - goto error; - - /* Show a dialog box, but in a background thread, and - never show multiple dialog boxes at once. */ -#if PY_MAJOR_VERSION >= 3 - text = PyUnicode_AsWideCharString(s, NULL); -#else - text = PyString_AsString(s); -#endif - - _cffi_bootstrap_text = text; - - if (text != NULL) - { - HANDLE h; - h = CreateThread(NULL, 0, _cffi_bootstrap_dialog, - NULL, 0, NULL); - if (h != NULL) - CloseHandle(h); - } - /* decref the string, but it should stay alive as 'fl.buf' - in the small module above. It will really be freed only if - we later get another similar error. So it's a leak of at - most one copy of the small module. That's fine for this - situation which is usually a "fatal error" anyway. */ - Py_DECREF(s); - PyErr_Clear(); - return; - - error: - _cffi_bootstrap_text = NULL; - PyErr_Clear(); -} - -#else - -static PyObject *_cffi_start_error_capture(void) { return NULL; } -static void _cffi_stop_error_capture(PyObject *ecap) { } - -#endif diff --git a/notification-service/venv/Lib/site-packages/cffi/_cffi_include.h b/notification-service/venv/Lib/site-packages/cffi/_cffi_include.h deleted file mode 100644 index 908a1d7..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/_cffi_include.h +++ /dev/null @@ -1,389 +0,0 @@ -#define _CFFI_ - -/* We try to define Py_LIMITED_API before including Python.h. - - Mess: we can only define it if Py_DEBUG, Py_TRACE_REFS and - Py_REF_DEBUG are not defined. This is a best-effort approximation: - we can learn about Py_DEBUG from pyconfig.h, but it is unclear if - the same works for the other two macros. Py_DEBUG implies them, - but not the other way around. - - The implementation is messy (issue #350): on Windows, with _MSC_VER, - we have to define Py_LIMITED_API even before including pyconfig.h. - In that case, we guess what pyconfig.h will do to the macros above, - and check our guess after the #include. - - Note that on Windows, with CPython 3.x, you need >= 3.5 and virtualenv - version >= 16.0.0. With older versions of either, you don't get a - copy of PYTHON3.DLL in the virtualenv. We can't check the version of - CPython *before* we even include pyconfig.h. ffi.set_source() puts - a ``#define _CFFI_NO_LIMITED_API'' at the start of this file if it is - running on Windows < 3.5, as an attempt at fixing it, but that's - arguably wrong because it may not be the target version of Python. - Still better than nothing I guess. As another workaround, you can - remove the definition of Py_LIMITED_API here. - - See also 'py_limited_api' in cffi/setuptools_ext.py. -*/ -#if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API) -# ifdef _MSC_VER -# if !defined(_DEBUG) && !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) && !defined(_CFFI_NO_LIMITED_API) -# define Py_LIMITED_API -# endif -# include - /* sanity-check: Py_LIMITED_API will cause crashes if any of these - are also defined. Normally, the Python file PC/pyconfig.h does not - cause any of these to be defined, with the exception that _DEBUG - causes Py_DEBUG. Double-check that. */ -# ifdef Py_LIMITED_API -# if defined(Py_DEBUG) -# error "pyconfig.h unexpectedly defines Py_DEBUG, but Py_LIMITED_API is set" -# endif -# if defined(Py_TRACE_REFS) -# error "pyconfig.h unexpectedly defines Py_TRACE_REFS, but Py_LIMITED_API is set" -# endif -# if defined(Py_REF_DEBUG) -# error "pyconfig.h unexpectedly defines Py_REF_DEBUG, but Py_LIMITED_API is set" -# endif -# endif -# else -# include -# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) && !defined(_CFFI_NO_LIMITED_API) -# define Py_LIMITED_API -# endif -# endif -#endif - -#include -#ifdef __cplusplus -extern "C" { -#endif -#include -#include "parse_c_type.h" - -/* this block of #ifs should be kept exactly identical between - c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py - and cffi/_cffi_include.h */ -#if defined(_MSC_VER) -# include /* for alloca() */ -# if _MSC_VER < 1600 /* MSVC < 2010 */ - typedef __int8 int8_t; - typedef __int16 int16_t; - typedef __int32 int32_t; - typedef __int64 int64_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; - typedef unsigned __int64 uint64_t; - typedef __int8 int_least8_t; - typedef __int16 int_least16_t; - typedef __int32 int_least32_t; - typedef __int64 int_least64_t; - typedef unsigned __int8 uint_least8_t; - typedef unsigned __int16 uint_least16_t; - typedef unsigned __int32 uint_least32_t; - typedef unsigned __int64 uint_least64_t; - typedef __int8 int_fast8_t; - typedef __int16 int_fast16_t; - typedef __int32 int_fast32_t; - typedef __int64 int_fast64_t; - typedef unsigned __int8 uint_fast8_t; - typedef unsigned __int16 uint_fast16_t; - typedef unsigned __int32 uint_fast32_t; - typedef unsigned __int64 uint_fast64_t; - typedef __int64 intmax_t; - typedef unsigned __int64 uintmax_t; -# else -# include -# endif -# if _MSC_VER < 1800 /* MSVC < 2013 */ -# ifndef __cplusplus - typedef unsigned char _Bool; -# endif -# endif -# define _cffi_float_complex_t _Fcomplex /* include for it */ -# define _cffi_double_complex_t _Dcomplex /* include for it */ -#else -# include -# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) -# include -# endif -# define _cffi_float_complex_t float _Complex -# define _cffi_double_complex_t double _Complex -#endif - -#ifdef __GNUC__ -# define _CFFI_UNUSED_FN __attribute__((unused)) -#else -# define _CFFI_UNUSED_FN /* nothing */ -#endif - -#ifdef __cplusplus -# ifndef _Bool - typedef bool _Bool; /* semi-hackish: C++ has no _Bool; bool is builtin */ -# endif -#endif - -/********** CPython-specific section **********/ -#ifndef PYPY_VERSION - - -#if PY_MAJOR_VERSION >= 3 -# define PyInt_FromLong PyLong_FromLong -#endif - -#define _cffi_from_c_double PyFloat_FromDouble -#define _cffi_from_c_float PyFloat_FromDouble -#define _cffi_from_c_long PyInt_FromLong -#define _cffi_from_c_ulong PyLong_FromUnsignedLong -#define _cffi_from_c_longlong PyLong_FromLongLong -#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong -#define _cffi_from_c__Bool PyBool_FromLong - -#define _cffi_to_c_double PyFloat_AsDouble -#define _cffi_to_c_float PyFloat_AsDouble - -#define _cffi_from_c_int(x, type) \ - (((type)-1) > 0 ? /* unsigned */ \ - (sizeof(type) < sizeof(long) ? \ - PyInt_FromLong((long)x) : \ - sizeof(type) == sizeof(long) ? \ - PyLong_FromUnsignedLong((unsigned long)x) : \ - PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ - (sizeof(type) <= sizeof(long) ? \ - PyInt_FromLong((long)x) : \ - PyLong_FromLongLong((long long)x))) - -#define _cffi_to_c_int(o, type) \ - ((type)( \ - sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ - : (type)_cffi_to_c_i8(o)) : \ - sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ - : (type)_cffi_to_c_i16(o)) : \ - sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ - : (type)_cffi_to_c_i32(o)) : \ - sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ - : (type)_cffi_to_c_i64(o)) : \ - (Py_FatalError("unsupported size for type " #type), (type)0))) - -#define _cffi_to_c_i8 \ - ((int(*)(PyObject *))_cffi_exports[1]) -#define _cffi_to_c_u8 \ - ((int(*)(PyObject *))_cffi_exports[2]) -#define _cffi_to_c_i16 \ - ((int(*)(PyObject *))_cffi_exports[3]) -#define _cffi_to_c_u16 \ - ((int(*)(PyObject *))_cffi_exports[4]) -#define _cffi_to_c_i32 \ - ((int(*)(PyObject *))_cffi_exports[5]) -#define _cffi_to_c_u32 \ - ((unsigned int(*)(PyObject *))_cffi_exports[6]) -#define _cffi_to_c_i64 \ - ((long long(*)(PyObject *))_cffi_exports[7]) -#define _cffi_to_c_u64 \ - ((unsigned long long(*)(PyObject *))_cffi_exports[8]) -#define _cffi_to_c_char \ - ((int(*)(PyObject *))_cffi_exports[9]) -#define _cffi_from_c_pointer \ - ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[10]) -#define _cffi_to_c_pointer \ - ((char *(*)(PyObject *, struct _cffi_ctypedescr *))_cffi_exports[11]) -#define _cffi_get_struct_layout \ - not used any more -#define _cffi_restore_errno \ - ((void(*)(void))_cffi_exports[13]) -#define _cffi_save_errno \ - ((void(*)(void))_cffi_exports[14]) -#define _cffi_from_c_char \ - ((PyObject *(*)(char))_cffi_exports[15]) -#define _cffi_from_c_deref \ - ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[16]) -#define _cffi_to_c \ - ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[17]) -#define _cffi_from_c_struct \ - ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[18]) -#define _cffi_to_c_wchar_t \ - ((_cffi_wchar_t(*)(PyObject *))_cffi_exports[19]) -#define _cffi_from_c_wchar_t \ - ((PyObject *(*)(_cffi_wchar_t))_cffi_exports[20]) -#define _cffi_to_c_long_double \ - ((long double(*)(PyObject *))_cffi_exports[21]) -#define _cffi_to_c__Bool \ - ((_Bool(*)(PyObject *))_cffi_exports[22]) -#define _cffi_prepare_pointer_call_argument \ - ((Py_ssize_t(*)(struct _cffi_ctypedescr *, \ - PyObject *, char **))_cffi_exports[23]) -#define _cffi_convert_array_from_object \ - ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[24]) -#define _CFFI_CPIDX 25 -#define _cffi_call_python \ - ((void(*)(struct _cffi_externpy_s *, char *))_cffi_exports[_CFFI_CPIDX]) -#define _cffi_to_c_wchar3216_t \ - ((int(*)(PyObject *))_cffi_exports[26]) -#define _cffi_from_c_wchar3216_t \ - ((PyObject *(*)(int))_cffi_exports[27]) -#define _CFFI_NUM_EXPORTS 28 - -struct _cffi_ctypedescr; - -static void *_cffi_exports[_CFFI_NUM_EXPORTS]; - -#define _cffi_type(index) ( \ - assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \ - (struct _cffi_ctypedescr *)_cffi_types[index]) - -static PyObject *_cffi_init(const char *module_name, Py_ssize_t version, - const struct _cffi_type_context_s *ctx) -{ - PyObject *module, *o_arg, *new_module; - void *raw[] = { - (void *)module_name, - (void *)version, - (void *)_cffi_exports, - (void *)ctx, - }; - - module = PyImport_ImportModule("_cffi_backend"); - if (module == NULL) - goto failure; - - o_arg = PyLong_FromVoidPtr((void *)raw); - if (o_arg == NULL) - goto failure; - - new_module = PyObject_CallMethod( - module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg); - - Py_DECREF(o_arg); - Py_DECREF(module); - return new_module; - - failure: - Py_XDECREF(module); - return NULL; -} - - -#ifdef HAVE_WCHAR_H -typedef wchar_t _cffi_wchar_t; -#else -typedef uint16_t _cffi_wchar_t; /* same random pick as _cffi_backend.c */ -#endif - -_CFFI_UNUSED_FN static uint16_t _cffi_to_c_char16_t(PyObject *o) -{ - if (sizeof(_cffi_wchar_t) == 2) - return (uint16_t)_cffi_to_c_wchar_t(o); - else - return (uint16_t)_cffi_to_c_wchar3216_t(o); -} - -_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char16_t(uint16_t x) -{ - if (sizeof(_cffi_wchar_t) == 2) - return _cffi_from_c_wchar_t((_cffi_wchar_t)x); - else - return _cffi_from_c_wchar3216_t((int)x); -} - -_CFFI_UNUSED_FN static int _cffi_to_c_char32_t(PyObject *o) -{ - if (sizeof(_cffi_wchar_t) == 4) - return (int)_cffi_to_c_wchar_t(o); - else - return (int)_cffi_to_c_wchar3216_t(o); -} - -_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char32_t(unsigned int x) -{ - if (sizeof(_cffi_wchar_t) == 4) - return _cffi_from_c_wchar_t((_cffi_wchar_t)x); - else - return _cffi_from_c_wchar3216_t((int)x); -} - -union _cffi_union_alignment_u { - unsigned char m_char; - unsigned short m_short; - unsigned int m_int; - unsigned long m_long; - unsigned long long m_longlong; - float m_float; - double m_double; - long double m_longdouble; -}; - -struct _cffi_freeme_s { - struct _cffi_freeme_s *next; - union _cffi_union_alignment_u alignment; -}; - -_CFFI_UNUSED_FN static int -_cffi_convert_array_argument(struct _cffi_ctypedescr *ctptr, PyObject *arg, - char **output_data, Py_ssize_t datasize, - struct _cffi_freeme_s **freeme) -{ - char *p; - if (datasize < 0) - return -1; - - p = *output_data; - if (p == NULL) { - struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc( - offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize); - if (fp == NULL) - return -1; - fp->next = *freeme; - *freeme = fp; - p = *output_data = (char *)&fp->alignment; - } - memset((void *)p, 0, (size_t)datasize); - return _cffi_convert_array_from_object(p, ctptr, arg); -} - -_CFFI_UNUSED_FN static void -_cffi_free_array_arguments(struct _cffi_freeme_s *freeme) -{ - do { - void *p = (void *)freeme; - freeme = freeme->next; - PyObject_Free(p); - } while (freeme != NULL); -} - -/********** end CPython-specific section **********/ -#else -_CFFI_UNUSED_FN -static void (*_cffi_call_python_org)(struct _cffi_externpy_s *, char *); -# define _cffi_call_python _cffi_call_python_org -#endif - - -#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0])) - -#define _cffi_prim_int(size, sign) \ - ((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) : \ - (size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \ - (size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \ - (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \ - _CFFI__UNKNOWN_PRIM) - -#define _cffi_prim_float(size) \ - ((size) == sizeof(float) ? _CFFI_PRIM_FLOAT : \ - (size) == sizeof(double) ? _CFFI_PRIM_DOUBLE : \ - (size) == sizeof(long double) ? _CFFI__UNKNOWN_LONG_DOUBLE : \ - _CFFI__UNKNOWN_FLOAT_PRIM) - -#define _cffi_check_int(got, got_nonpos, expected) \ - ((got_nonpos) == (expected <= 0) && \ - (got) == (unsigned long long)expected) - -#ifdef MS_WIN32 -# define _cffi_stdcall __stdcall -#else -# define _cffi_stdcall /* nothing */ -#endif - -#ifdef __cplusplus -} -#endif diff --git a/notification-service/venv/Lib/site-packages/cffi/_embedding.h b/notification-service/venv/Lib/site-packages/cffi/_embedding.h deleted file mode 100644 index 64c04f6..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/_embedding.h +++ /dev/null @@ -1,550 +0,0 @@ - -/***** Support code for embedding *****/ - -#ifdef __cplusplus -extern "C" { -#endif - - -#if defined(_WIN32) -# define CFFI_DLLEXPORT __declspec(dllexport) -#elif defined(__GNUC__) -# define CFFI_DLLEXPORT __attribute__((visibility("default"))) -#else -# define CFFI_DLLEXPORT /* nothing */ -#endif - - -/* There are two global variables of type _cffi_call_python_fnptr: - - * _cffi_call_python, which we declare just below, is the one called - by ``extern "Python"`` implementations. - - * _cffi_call_python_org, which on CPython is actually part of the - _cffi_exports[] array, is the function pointer copied from - _cffi_backend. If _cffi_start_python() fails, then this is set - to NULL; otherwise, it should never be NULL. - - After initialization is complete, both are equal. However, the - first one remains equal to &_cffi_start_and_call_python until the - very end of initialization, when we are (or should be) sure that - concurrent threads also see a completely initialized world, and - only then is it changed. -*/ -#undef _cffi_call_python -typedef void (*_cffi_call_python_fnptr)(struct _cffi_externpy_s *, char *); -static void _cffi_start_and_call_python(struct _cffi_externpy_s *, char *); -static _cffi_call_python_fnptr _cffi_call_python = &_cffi_start_and_call_python; - - -#ifndef _MSC_VER - /* --- Assuming a GCC not infinitely old --- */ -# define cffi_compare_and_swap(l,o,n) __sync_bool_compare_and_swap(l,o,n) -# define cffi_write_barrier() __sync_synchronize() -# if !defined(__amd64__) && !defined(__x86_64__) && \ - !defined(__i386__) && !defined(__i386) -# define cffi_read_barrier() __sync_synchronize() -# else -# define cffi_read_barrier() (void)0 -# endif -#else - /* --- Windows threads version --- */ -# include -# define cffi_compare_and_swap(l,o,n) \ - (InterlockedCompareExchangePointer(l,n,o) == (o)) -# define cffi_write_barrier() InterlockedCompareExchange(&_cffi_dummy,0,0) -# define cffi_read_barrier() (void)0 -static volatile LONG _cffi_dummy; -#endif - -#ifdef WITH_THREAD -# ifndef _MSC_VER -# include - static pthread_mutex_t _cffi_embed_startup_lock; -# else - static CRITICAL_SECTION _cffi_embed_startup_lock; -# endif - static char _cffi_embed_startup_lock_ready = 0; -#endif - -static void _cffi_acquire_reentrant_mutex(void) -{ - static void *volatile lock = NULL; - - while (!cffi_compare_and_swap(&lock, NULL, (void *)1)) { - /* should ideally do a spin loop instruction here, but - hard to do it portably and doesn't really matter I - think: pthread_mutex_init() should be very fast, and - this is only run at start-up anyway. */ - } - -#ifdef WITH_THREAD - if (!_cffi_embed_startup_lock_ready) { -# ifndef _MSC_VER - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&_cffi_embed_startup_lock, &attr); -# else - InitializeCriticalSection(&_cffi_embed_startup_lock); -# endif - _cffi_embed_startup_lock_ready = 1; - } -#endif - - while (!cffi_compare_and_swap(&lock, (void *)1, NULL)) - ; - -#ifndef _MSC_VER - pthread_mutex_lock(&_cffi_embed_startup_lock); -#else - EnterCriticalSection(&_cffi_embed_startup_lock); -#endif -} - -static void _cffi_release_reentrant_mutex(void) -{ -#ifndef _MSC_VER - pthread_mutex_unlock(&_cffi_embed_startup_lock); -#else - LeaveCriticalSection(&_cffi_embed_startup_lock); -#endif -} - - -/********** CPython-specific section **********/ -#ifndef PYPY_VERSION - -#include "_cffi_errors.h" - - -#define _cffi_call_python_org _cffi_exports[_CFFI_CPIDX] - -PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(void); /* forward */ - -static void _cffi_py_initialize(void) -{ - /* XXX use initsigs=0, which "skips initialization registration of - signal handlers, which might be useful when Python is - embedded" according to the Python docs. But review and think - if it should be a user-controllable setting. - - XXX we should also give a way to write errors to a buffer - instead of to stderr. - - XXX if importing 'site' fails, CPython (any version) calls - exit(). Should we try to work around this behavior here? - */ - Py_InitializeEx(0); -} - -static int _cffi_initialize_python(void) -{ - /* This initializes Python, imports _cffi_backend, and then the - present .dll/.so is set up as a CPython C extension module. - */ - int result; - PyGILState_STATE state; - PyObject *pycode=NULL, *global_dict=NULL, *x; - PyObject *builtins; - - state = PyGILState_Ensure(); - - /* Call the initxxx() function from the present module. It will - create and initialize us as a CPython extension module, instead - of letting the startup Python code do it---it might reimport - the same .dll/.so and get maybe confused on some platforms. - It might also have troubles locating the .dll/.so again for all - I know. - */ - (void)_CFFI_PYTHON_STARTUP_FUNC(); - if (PyErr_Occurred()) - goto error; - - /* Now run the Python code provided to ffi.embedding_init_code(). - */ - pycode = Py_CompileString(_CFFI_PYTHON_STARTUP_CODE, - "", - Py_file_input); - if (pycode == NULL) - goto error; - global_dict = PyDict_New(); - if (global_dict == NULL) - goto error; - builtins = PyEval_GetBuiltins(); - if (builtins == NULL) - goto error; - if (PyDict_SetItemString(global_dict, "__builtins__", builtins) < 0) - goto error; - x = PyEval_EvalCode( -#if PY_MAJOR_VERSION < 3 - (PyCodeObject *) -#endif - pycode, global_dict, global_dict); - if (x == NULL) - goto error; - Py_DECREF(x); - - /* Done! Now if we've been called from - _cffi_start_and_call_python() in an ``extern "Python"``, we can - only hope that the Python code did correctly set up the - corresponding @ffi.def_extern() function. Otherwise, the - general logic of ``extern "Python"`` functions (inside the - _cffi_backend module) will find that the reference is still - missing and print an error. - */ - result = 0; - done: - Py_XDECREF(pycode); - Py_XDECREF(global_dict); - PyGILState_Release(state); - return result; - - error:; - { - /* Print as much information as potentially useful. - Debugging load-time failures with embedding is not fun - */ - PyObject *ecap; - PyObject *exception, *v, *tb, *f, *modules, *mod; - PyErr_Fetch(&exception, &v, &tb); - ecap = _cffi_start_error_capture(); - f = PySys_GetObject((char *)"stderr"); - if (f != NULL && f != Py_None) { - PyFile_WriteString( - "Failed to initialize the Python-CFFI embedding logic:\n\n", f); - } - - if (exception != NULL) { - PyErr_NormalizeException(&exception, &v, &tb); - PyErr_Display(exception, v, tb); - } - Py_XDECREF(exception); - Py_XDECREF(v); - Py_XDECREF(tb); - - if (f != NULL && f != Py_None) { - PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME - "\ncompiled with cffi version: 2.0.0" - "\n_cffi_backend module: ", f); - modules = PyImport_GetModuleDict(); - mod = PyDict_GetItemString(modules, "_cffi_backend"); - if (mod == NULL) { - PyFile_WriteString("not loaded", f); - } - else { - v = PyObject_GetAttrString(mod, "__file__"); - PyFile_WriteObject(v, f, 0); - Py_XDECREF(v); - } - PyFile_WriteString("\nsys.path: ", f); - PyFile_WriteObject(PySys_GetObject((char *)"path"), f, 0); - PyFile_WriteString("\n\n", f); - } - _cffi_stop_error_capture(ecap); - } - result = -1; - goto done; -} - -#if PY_VERSION_HEX < 0x03080000 -PyAPI_DATA(char *) _PyParser_TokenNames[]; /* from CPython */ -#endif - -static int _cffi_carefully_make_gil(void) -{ - /* This does the basic initialization of Python. It can be called - completely concurrently from unrelated threads. It assumes - that we don't hold the GIL before (if it exists), and we don't - hold it afterwards. - - (What it really does used to be completely different in Python 2 - and Python 3, with the Python 2 solution avoiding the spin-lock - around the Py_InitializeEx() call. However, after recent changes - to CPython 2.7 (issue #358) it no longer works. So we use the - Python 3 solution everywhere.) - - This initializes Python by calling Py_InitializeEx(). - Important: this must not be called concurrently at all. - So we use a global variable as a simple spin lock. This global - variable must be from 'libpythonX.Y.so', not from this - cffi-based extension module, because it must be shared from - different cffi-based extension modules. - - In Python < 3.8, we choose - _PyParser_TokenNames[0] as a completely arbitrary pointer value - that is never written to. The default is to point to the - string "ENDMARKER". We change it temporarily to point to the - next character in that string. (Yes, I know it's REALLY - obscure.) - - In Python >= 3.8, this string array is no longer writable, so - instead we pick PyCapsuleType.tp_version_tag. We can't change - Python < 3.8 because someone might use a mixture of cffi - embedded modules, some of which were compiled before this file - changed. - - In Python >= 3.12, this stopped working because that particular - tp_version_tag gets modified during interpreter startup. It's - arguably a bad idea before 3.12 too, but again we can't change - that because someone might use a mixture of cffi embedded - modules, and no-one reported a bug so far. In Python >= 3.12 - we go instead for PyCapsuleType.tp_as_buffer, which is supposed - to always be NULL. We write to it temporarily a pointer to - a struct full of NULLs, which is semantically the same. - */ - -#ifdef WITH_THREAD -# if PY_VERSION_HEX < 0x03080000 - char *volatile *lock = (char *volatile *)_PyParser_TokenNames; - char *old_value, *locked_value; - - while (1) { /* spin loop */ - old_value = *lock; - locked_value = old_value + 1; - if (old_value[0] == 'E') { - assert(old_value[1] == 'N'); - if (cffi_compare_and_swap(lock, old_value, locked_value)) - break; - } - else { - assert(old_value[0] == 'N'); - /* should ideally do a spin loop instruction here, but - hard to do it portably and doesn't really matter I - think: PyEval_InitThreads() should be very fast, and - this is only run at start-up anyway. */ - } - } -# else -# if PY_VERSION_HEX < 0x030C0000 - int volatile *lock = (int volatile *)&PyCapsule_Type.tp_version_tag; - int old_value, locked_value = -42; - assert(!(PyCapsule_Type.tp_flags & Py_TPFLAGS_HAVE_VERSION_TAG)); -# else - static struct ebp_s { PyBufferProcs buf; int mark; } empty_buffer_procs; - empty_buffer_procs.mark = -42; - PyBufferProcs *volatile *lock = (PyBufferProcs *volatile *) - &PyCapsule_Type.tp_as_buffer; - PyBufferProcs *old_value, *locked_value = &empty_buffer_procs.buf; -# endif - - while (1) { /* spin loop */ - old_value = *lock; - if (old_value == 0) { - if (cffi_compare_and_swap(lock, old_value, locked_value)) - break; - } - else { -# if PY_VERSION_HEX < 0x030C0000 - assert(old_value == locked_value); -# else - /* The pointer should point to a possibly different - empty_buffer_procs from another C extension module */ - assert(((struct ebp_s *)old_value)->mark == -42); -# endif - /* should ideally do a spin loop instruction here, but - hard to do it portably and doesn't really matter I - think: PyEval_InitThreads() should be very fast, and - this is only run at start-up anyway. */ - } - } -# endif -#endif - - /* call Py_InitializeEx() */ - if (!Py_IsInitialized()) { - _cffi_py_initialize(); -#if PY_VERSION_HEX < 0x03070000 - PyEval_InitThreads(); -#endif - PyEval_SaveThread(); /* release the GIL */ - /* the returned tstate must be the one that has been stored into the - autoTLSkey by _PyGILState_Init() called from Py_Initialize(). */ - } - else { -#if PY_VERSION_HEX < 0x03070000 - /* PyEval_InitThreads() is always a no-op from CPython 3.7 */ - PyGILState_STATE state = PyGILState_Ensure(); - PyEval_InitThreads(); - PyGILState_Release(state); -#endif - } - -#ifdef WITH_THREAD - /* release the lock */ - while (!cffi_compare_and_swap(lock, locked_value, old_value)) - ; -#endif - - return 0; -} - -/********** end CPython-specific section **********/ - - -#else - - -/********** PyPy-specific section **********/ - -PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(const void *[]); /* forward */ - -static struct _cffi_pypy_init_s { - const char *name; - void *func; /* function pointer */ - const char *code; -} _cffi_pypy_init = { - _CFFI_MODULE_NAME, - _CFFI_PYTHON_STARTUP_FUNC, - _CFFI_PYTHON_STARTUP_CODE, -}; - -extern int pypy_carefully_make_gil(const char *); -extern int pypy_init_embedded_cffi_module(int, struct _cffi_pypy_init_s *); - -static int _cffi_carefully_make_gil(void) -{ - return pypy_carefully_make_gil(_CFFI_MODULE_NAME); -} - -static int _cffi_initialize_python(void) -{ - return pypy_init_embedded_cffi_module(0xB011, &_cffi_pypy_init); -} - -/********** end PyPy-specific section **********/ - - -#endif - - -#ifdef __GNUC__ -__attribute__((noinline)) -#endif -static _cffi_call_python_fnptr _cffi_start_python(void) -{ - /* Delicate logic to initialize Python. This function can be - called multiple times concurrently, e.g. when the process calls - its first ``extern "Python"`` functions in multiple threads at - once. It can also be called recursively, in which case we must - ignore it. We also have to consider what occurs if several - different cffi-based extensions reach this code in parallel - threads---it is a different copy of the code, then, and we - can't have any shared global variable unless it comes from - 'libpythonX.Y.so'. - - Idea: - - * _cffi_carefully_make_gil(): "carefully" call - PyEval_InitThreads() (possibly with Py_InitializeEx() first). - - * then we use a (local) custom lock to make sure that a call to this - cffi-based extension will wait if another call to the *same* - extension is running the initialization in another thread. - It is reentrant, so that a recursive call will not block, but - only one from a different thread. - - * then we grab the GIL and (Python 2) we call Py_InitializeEx(). - At this point, concurrent calls to Py_InitializeEx() are not - possible: we have the GIL. - - * do the rest of the specific initialization, which may - temporarily release the GIL but not the custom lock. - Only release the custom lock when we are done. - */ - static char called = 0; - - if (_cffi_carefully_make_gil() != 0) - return NULL; - - _cffi_acquire_reentrant_mutex(); - - /* Here the GIL exists, but we don't have it. We're only protected - from concurrency by the reentrant mutex. */ - - /* This file only initializes the embedded module once, the first - time this is called, even if there are subinterpreters. */ - if (!called) { - called = 1; /* invoke _cffi_initialize_python() only once, - but don't set '_cffi_call_python' right now, - otherwise concurrent threads won't call - this function at all (we need them to wait) */ - if (_cffi_initialize_python() == 0) { - /* now initialization is finished. Switch to the fast-path. */ - - /* We would like nobody to see the new value of - '_cffi_call_python' without also seeing the rest of the - data initialized. However, this is not possible. But - the new value of '_cffi_call_python' is the function - 'cffi_call_python()' from _cffi_backend. So: */ - cffi_write_barrier(); - /* ^^^ we put a write barrier here, and a corresponding - read barrier at the start of cffi_call_python(). This - ensures that after that read barrier, we see everything - done here before the write barrier. - */ - - assert(_cffi_call_python_org != NULL); - _cffi_call_python = (_cffi_call_python_fnptr)_cffi_call_python_org; - } - else { - /* initialization failed. Reset this to NULL, even if it was - already set to some other value. Future calls to - _cffi_start_python() are still forced to occur, and will - always return NULL from now on. */ - _cffi_call_python_org = NULL; - } - } - - _cffi_release_reentrant_mutex(); - - return (_cffi_call_python_fnptr)_cffi_call_python_org; -} - -static -void _cffi_start_and_call_python(struct _cffi_externpy_s *externpy, char *args) -{ - _cffi_call_python_fnptr fnptr; - int current_err = errno; -#ifdef _MSC_VER - int current_lasterr = GetLastError(); -#endif - fnptr = _cffi_start_python(); - if (fnptr == NULL) { - fprintf(stderr, "function %s() called, but initialization code " - "failed. Returning 0.\n", externpy->name); - memset(args, 0, externpy->size_of_result); - } -#ifdef _MSC_VER - SetLastError(current_lasterr); -#endif - errno = current_err; - - if (fnptr != NULL) - fnptr(externpy, args); -} - - -/* The cffi_start_python() function makes sure Python is initialized - and our cffi module is set up. It can be called manually from the - user C code. The same effect is obtained automatically from any - dll-exported ``extern "Python"`` function. This function returns - -1 if initialization failed, 0 if all is OK. */ -_CFFI_UNUSED_FN -static int cffi_start_python(void) -{ - if (_cffi_call_python == &_cffi_start_and_call_python) { - if (_cffi_start_python() == NULL) - return -1; - } - cffi_read_barrier(); - return 0; -} - -#undef cffi_compare_and_swap -#undef cffi_write_barrier -#undef cffi_read_barrier - -#ifdef __cplusplus -} -#endif diff --git a/notification-service/venv/Lib/site-packages/cffi/_imp_emulation.py b/notification-service/venv/Lib/site-packages/cffi/_imp_emulation.py deleted file mode 100644 index 136abdd..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/_imp_emulation.py +++ /dev/null @@ -1,83 +0,0 @@ - -try: - # this works on Python < 3.12 - from imp import * - -except ImportError: - # this is a limited emulation for Python >= 3.12. - # Note that this is used only for tests or for the old ffi.verify(). - # This is copied from the source code of Python 3.11. - - from _imp import (acquire_lock, release_lock, - is_builtin, is_frozen) - - from importlib._bootstrap import _load - - from importlib import machinery - import os - import sys - import tokenize - - SEARCH_ERROR = 0 - PY_SOURCE = 1 - PY_COMPILED = 2 - C_EXTENSION = 3 - PY_RESOURCE = 4 - PKG_DIRECTORY = 5 - C_BUILTIN = 6 - PY_FROZEN = 7 - PY_CODERESOURCE = 8 - IMP_HOOK = 9 - - def get_suffixes(): - extensions = [(s, 'rb', C_EXTENSION) - for s in machinery.EXTENSION_SUFFIXES] - source = [(s, 'r', PY_SOURCE) for s in machinery.SOURCE_SUFFIXES] - bytecode = [(s, 'rb', PY_COMPILED) for s in machinery.BYTECODE_SUFFIXES] - return extensions + source + bytecode - - def find_module(name, path=None): - if not isinstance(name, str): - raise TypeError("'name' must be a str, not {}".format(type(name))) - elif not isinstance(path, (type(None), list)): - # Backwards-compatibility - raise RuntimeError("'path' must be None or a list, " - "not {}".format(type(path))) - - if path is None: - if is_builtin(name): - return None, None, ('', '', C_BUILTIN) - elif is_frozen(name): - return None, None, ('', '', PY_FROZEN) - else: - path = sys.path - - for entry in path: - package_directory = os.path.join(entry, name) - for suffix in ['.py', machinery.BYTECODE_SUFFIXES[0]]: - package_file_name = '__init__' + suffix - file_path = os.path.join(package_directory, package_file_name) - if os.path.isfile(file_path): - return None, package_directory, ('', '', PKG_DIRECTORY) - for suffix, mode, type_ in get_suffixes(): - file_name = name + suffix - file_path = os.path.join(entry, file_name) - if os.path.isfile(file_path): - break - else: - continue - break # Break out of outer loop when breaking out of inner loop. - else: - raise ImportError(name, name=name) - - encoding = None - if 'b' not in mode: - with open(file_path, 'rb') as file: - encoding = tokenize.detect_encoding(file.readline)[0] - file = open(file_path, mode, encoding=encoding) - return file, file_path, (suffix, mode, type_) - - def load_dynamic(name, path, file=None): - loader = machinery.ExtensionFileLoader(name, path) - spec = machinery.ModuleSpec(name=name, loader=loader, origin=path) - return _load(spec) diff --git a/notification-service/venv/Lib/site-packages/cffi/_shimmed_dist_utils.py b/notification-service/venv/Lib/site-packages/cffi/_shimmed_dist_utils.py deleted file mode 100644 index c3d2312..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/_shimmed_dist_utils.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Temporary shim module to indirect the bits of distutils we need from setuptools/distutils while providing useful -error messages beyond `No module named 'distutils' on Python >= 3.12, or when setuptools' vendored distutils is broken. - -This is a compromise to avoid a hard-dep on setuptools for Python >= 3.12, since many users don't need runtime compilation support from CFFI. -""" -import sys - -try: - # import setuptools first; this is the most robust way to ensure its embedded distutils is available - # (the .pth shim should usually work, but this is even more robust) - import setuptools -except Exception as ex: - if sys.version_info >= (3, 12): - # Python 3.12 has no built-in distutils to fall back on, so any import problem is fatal - raise Exception("This CFFI feature requires setuptools on Python >= 3.12. The setuptools module is missing or non-functional.") from ex - - # silently ignore on older Pythons (support fallback to stdlib distutils where available) -else: - del setuptools - -try: - # bring in just the bits of distutils we need, whether they really came from setuptools or stdlib-embedded distutils - from distutils import log, sysconfig - from distutils.ccompiler import CCompiler - from distutils.command.build_ext import build_ext - from distutils.core import Distribution, Extension - from distutils.dir_util import mkpath - from distutils.errors import DistutilsSetupError, CompileError, LinkError - from distutils.log import set_threshold, set_verbosity - - if sys.platform == 'win32': - try: - # FUTURE: msvc9compiler module was removed in setuptools 74; consider removing, as it's only used by an ancient patch in `recompiler` - from distutils.msvc9compiler import MSVCCompiler - except ImportError: - MSVCCompiler = None -except Exception as ex: - if sys.version_info >= (3, 12): - raise Exception("This CFFI feature requires setuptools on Python >= 3.12. Please install the setuptools package.") from ex - - # anything older, just let the underlying distutils import error fly - raise Exception("This CFFI feature requires distutils. Please install the distutils or setuptools package.") from ex - -del sys diff --git a/notification-service/venv/Lib/site-packages/cffi/api.py b/notification-service/venv/Lib/site-packages/cffi/api.py deleted file mode 100644 index 5a474f3..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/api.py +++ /dev/null @@ -1,967 +0,0 @@ -import sys, types -from .lock import allocate_lock -from .error import CDefError -from . import model - -try: - callable -except NameError: - # Python 3.1 - from collections import Callable - callable = lambda x: isinstance(x, Callable) - -try: - basestring -except NameError: - # Python 3.x - basestring = str - -_unspecified = object() - - - -class FFI(object): - r''' - The main top-level class that you instantiate once, or once per module. - - Example usage: - - ffi = FFI() - ffi.cdef(""" - int printf(const char *, ...); - """) - - C = ffi.dlopen(None) # standard library - -or- - C = ffi.verify() # use a C compiler: verify the decl above is right - - C.printf("hello, %s!\n", ffi.new("char[]", "world")) - ''' - - def __init__(self, backend=None): - """Create an FFI instance. The 'backend' argument is used to - select a non-default backend, mostly for tests. - """ - if backend is None: - # You need PyPy (>= 2.0 beta), or a CPython (>= 2.6) with - # _cffi_backend.so compiled. - import _cffi_backend as backend - from . import __version__ - if backend.__version__ != __version__: - # bad version! Try to be as explicit as possible. - if hasattr(backend, '__file__'): - # CPython - raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. When we import the top-level '_cffi_backend' extension module, we get version %s, located in %r. The two versions should be equal; check your installation." % ( - __version__, __file__, - backend.__version__, backend.__file__)) - else: - # PyPy - raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. This interpreter comes with a built-in '_cffi_backend' module, which is version %s. The two versions should be equal; check your installation." % ( - __version__, __file__, backend.__version__)) - # (If you insist you can also try to pass the option - # 'backend=backend_ctypes.CTypesBackend()', but don't - # rely on it! It's probably not going to work well.) - - from . import cparser - self._backend = backend - self._lock = allocate_lock() - self._parser = cparser.Parser() - self._cached_btypes = {} - self._parsed_types = types.ModuleType('parsed_types').__dict__ - self._new_types = types.ModuleType('new_types').__dict__ - self._function_caches = [] - self._libraries = [] - self._cdefsources = [] - self._included_ffis = [] - self._windows_unicode = None - self._init_once_cache = {} - self._cdef_version = None - self._embedding = None - self._typecache = model.get_typecache(backend) - if hasattr(backend, 'set_ffi'): - backend.set_ffi(self) - for name in list(backend.__dict__): - if name.startswith('RTLD_'): - setattr(self, name, getattr(backend, name)) - # - with self._lock: - self.BVoidP = self._get_cached_btype(model.voidp_type) - self.BCharA = self._get_cached_btype(model.char_array_type) - if isinstance(backend, types.ModuleType): - # _cffi_backend: attach these constants to the class - if not hasattr(FFI, 'NULL'): - FFI.NULL = self.cast(self.BVoidP, 0) - FFI.CData, FFI.CType = backend._get_types() - else: - # ctypes backend: attach these constants to the instance - self.NULL = self.cast(self.BVoidP, 0) - self.CData, self.CType = backend._get_types() - self.buffer = backend.buffer - - def cdef(self, csource, override=False, packed=False, pack=None): - """Parse the given C source. This registers all declared functions, - types, and global variables. The functions and global variables can - then be accessed via either 'ffi.dlopen()' or 'ffi.verify()'. - The types can be used in 'ffi.new()' and other functions. - If 'packed' is specified as True, all structs declared inside this - cdef are packed, i.e. laid out without any field alignment at all. - Alternatively, 'pack' can be a small integer, and requests for - alignment greater than that are ignored (pack=1 is equivalent to - packed=True). - """ - self._cdef(csource, override=override, packed=packed, pack=pack) - - def embedding_api(self, csource, packed=False, pack=None): - self._cdef(csource, packed=packed, pack=pack, dllexport=True) - if self._embedding is None: - self._embedding = '' - - def _cdef(self, csource, override=False, **options): - if not isinstance(csource, str): # unicode, on Python 2 - if not isinstance(csource, basestring): - raise TypeError("cdef() argument must be a string") - csource = csource.encode('ascii') - with self._lock: - self._cdef_version = object() - self._parser.parse(csource, override=override, **options) - self._cdefsources.append(csource) - if override: - for cache in self._function_caches: - cache.clear() - finishlist = self._parser._recomplete - if finishlist: - self._parser._recomplete = [] - for tp in finishlist: - tp.finish_backend_type(self, finishlist) - - def dlopen(self, name, flags=0): - """Load and return a dynamic library identified by 'name'. - The standard C library can be loaded by passing None. - Note that functions and types declared by 'ffi.cdef()' are not - linked to a particular library, just like C headers; in the - library we only look for the actual (untyped) symbols. - """ - if not (isinstance(name, basestring) or - name is None or - isinstance(name, self.CData)): - raise TypeError("dlopen(name): name must be a file name, None, " - "or an already-opened 'void *' handle") - with self._lock: - lib, function_cache = _make_ffi_library(self, name, flags) - self._function_caches.append(function_cache) - self._libraries.append(lib) - return lib - - def dlclose(self, lib): - """Close a library obtained with ffi.dlopen(). After this call, - access to functions or variables from the library will fail - (possibly with a segmentation fault). - """ - type(lib).__cffi_close__(lib) - - def _typeof_locked(self, cdecl): - # call me with the lock! - key = cdecl - if key in self._parsed_types: - return self._parsed_types[key] - # - if not isinstance(cdecl, str): # unicode, on Python 2 - cdecl = cdecl.encode('ascii') - # - type = self._parser.parse_type(cdecl) - really_a_function_type = type.is_raw_function - if really_a_function_type: - type = type.as_function_pointer() - btype = self._get_cached_btype(type) - result = btype, really_a_function_type - self._parsed_types[key] = result - return result - - def _typeof(self, cdecl, consider_function_as_funcptr=False): - # string -> ctype object - try: - result = self._parsed_types[cdecl] - except KeyError: - with self._lock: - result = self._typeof_locked(cdecl) - # - btype, really_a_function_type = result - if really_a_function_type and not consider_function_as_funcptr: - raise CDefError("the type %r is a function type, not a " - "pointer-to-function type" % (cdecl,)) - return btype - - def typeof(self, cdecl): - """Parse the C type given as a string and return the - corresponding object. - It can also be used on 'cdata' instance to get its C type. - """ - if isinstance(cdecl, basestring): - return self._typeof(cdecl) - if isinstance(cdecl, self.CData): - return self._backend.typeof(cdecl) - if isinstance(cdecl, types.BuiltinFunctionType): - res = _builtin_function_type(cdecl) - if res is not None: - return res - if (isinstance(cdecl, types.FunctionType) - and hasattr(cdecl, '_cffi_base_type')): - with self._lock: - return self._get_cached_btype(cdecl._cffi_base_type) - raise TypeError(type(cdecl)) - - def sizeof(self, cdecl): - """Return the size in bytes of the argument. It can be a - string naming a C type, or a 'cdata' instance. - """ - if isinstance(cdecl, basestring): - BType = self._typeof(cdecl) - return self._backend.sizeof(BType) - else: - return self._backend.sizeof(cdecl) - - def alignof(self, cdecl): - """Return the natural alignment size in bytes of the C type - given as a string. - """ - if isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl) - return self._backend.alignof(cdecl) - - def offsetof(self, cdecl, *fields_or_indexes): - """Return the offset of the named field inside the given - structure or array, which must be given as a C type name. - You can give several field names in case of nested structures. - You can also give numeric values which correspond to array - items, in case of an array type. - """ - if isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl) - return self._typeoffsetof(cdecl, *fields_or_indexes)[1] - - def new(self, cdecl, init=None): - """Allocate an instance according to the specified C type and - return a pointer to it. The specified C type must be either a - pointer or an array: ``new('X *')`` allocates an X and returns - a pointer to it, whereas ``new('X[n]')`` allocates an array of - n X'es and returns an array referencing it (which works - mostly like a pointer, like in C). You can also use - ``new('X[]', n)`` to allocate an array of a non-constant - length n. - - The memory is initialized following the rules of declaring a - global variable in C: by default it is zero-initialized, but - an explicit initializer can be given which can be used to - fill all or part of the memory. - - When the returned object goes out of scope, the memory - is freed. In other words the returned object has - ownership of the value of type 'cdecl' that it points to. This - means that the raw data can be used as long as this object is - kept alive, but must not be used for a longer time. Be careful - about that when copying the pointer to the memory somewhere - else, e.g. into another structure. - """ - if isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl) - return self._backend.newp(cdecl, init) - - def new_allocator(self, alloc=None, free=None, - should_clear_after_alloc=True): - """Return a new allocator, i.e. a function that behaves like ffi.new() - but uses the provided low-level 'alloc' and 'free' functions. - - 'alloc' is called with the size as argument. If it returns NULL, a - MemoryError is raised. 'free' is called with the result of 'alloc' - as argument. Both can be either Python function or directly C - functions. If 'free' is None, then no free function is called. - If both 'alloc' and 'free' are None, the default is used. - - If 'should_clear_after_alloc' is set to False, then the memory - returned by 'alloc' is assumed to be already cleared (or you are - fine with garbage); otherwise CFFI will clear it. - """ - compiled_ffi = self._backend.FFI() - allocator = compiled_ffi.new_allocator(alloc, free, - should_clear_after_alloc) - def allocate(cdecl, init=None): - if isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl) - return allocator(cdecl, init) - return allocate - - def cast(self, cdecl, source): - """Similar to a C cast: returns an instance of the named C - type initialized with the given 'source'. The source is - casted between integers or pointers of any type. - """ - if isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl) - return self._backend.cast(cdecl, source) - - def string(self, cdata, maxlen=-1): - """Return a Python string (or unicode string) from the 'cdata'. - If 'cdata' is a pointer or array of characters or bytes, returns - the null-terminated string. The returned string extends until - the first null character, or at most 'maxlen' characters. If - 'cdata' is an array then 'maxlen' defaults to its length. - - If 'cdata' is a pointer or array of wchar_t, returns a unicode - string following the same rules. - - If 'cdata' is a single character or byte or a wchar_t, returns - it as a string or unicode string. - - If 'cdata' is an enum, returns the value of the enumerator as a - string, or 'NUMBER' if the value is out of range. - """ - return self._backend.string(cdata, maxlen) - - def unpack(self, cdata, length): - """Unpack an array of C data of the given length, - returning a Python string/unicode/list. - - If 'cdata' is a pointer to 'char', returns a byte string. - It does not stop at the first null. This is equivalent to: - ffi.buffer(cdata, length)[:] - - If 'cdata' is a pointer to 'wchar_t', returns a unicode string. - 'length' is measured in wchar_t's; it is not the size in bytes. - - If 'cdata' is a pointer to anything else, returns a list of - 'length' items. This is a faster equivalent to: - [cdata[i] for i in range(length)] - """ - return self._backend.unpack(cdata, length) - - #def buffer(self, cdata, size=-1): - # """Return a read-write buffer object that references the raw C data - # pointed to by the given 'cdata'. The 'cdata' must be a pointer or - # an array. Can be passed to functions expecting a buffer, or directly - # manipulated with: - # - # buf[:] get a copy of it in a regular string, or - # buf[idx] as a single character - # buf[:] = ... - # buf[idx] = ... change the content - # """ - # note that 'buffer' is a type, set on this instance by __init__ - - def from_buffer(self, cdecl, python_buffer=_unspecified, - require_writable=False): - """Return a cdata of the given type pointing to the data of the - given Python object, which must support the buffer interface. - Note that this is not meant to be used on the built-in types - str or unicode (you can build 'char[]' arrays explicitly) - but only on objects containing large quantities of raw data - in some other format, like 'array.array' or numpy arrays. - - The first argument is optional and default to 'char[]'. - """ - if python_buffer is _unspecified: - cdecl, python_buffer = self.BCharA, cdecl - elif isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl) - return self._backend.from_buffer(cdecl, python_buffer, - require_writable) - - def memmove(self, dest, src, n): - """ffi.memmove(dest, src, n) copies n bytes of memory from src to dest. - - Like the C function memmove(), the memory areas may overlap; - apart from that it behaves like the C function memcpy(). - - 'src' can be any cdata ptr or array, or any Python buffer object. - 'dest' can be any cdata ptr or array, or a writable Python buffer - object. The size to copy, 'n', is always measured in bytes. - - Unlike other methods, this one supports all Python buffer including - byte strings and bytearrays---but it still does not support - non-contiguous buffers. - """ - return self._backend.memmove(dest, src, n) - - def callback(self, cdecl, python_callable=None, error=None, onerror=None): - """Return a callback object or a decorator making such a - callback object. 'cdecl' must name a C function pointer type. - The callback invokes the specified 'python_callable' (which may - be provided either directly or via a decorator). Important: the - callback object must be manually kept alive for as long as the - callback may be invoked from the C level. - """ - def callback_decorator_wrap(python_callable): - if not callable(python_callable): - raise TypeError("the 'python_callable' argument " - "is not callable") - return self._backend.callback(cdecl, python_callable, - error, onerror) - if isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl, consider_function_as_funcptr=True) - if python_callable is None: - return callback_decorator_wrap # decorator mode - else: - return callback_decorator_wrap(python_callable) # direct mode - - def getctype(self, cdecl, replace_with=''): - """Return a string giving the C type 'cdecl', which may be itself - a string or a object. If 'replace_with' is given, it gives - extra text to append (or insert for more complicated C types), like - a variable name, or '*' to get actually the C type 'pointer-to-cdecl'. - """ - if isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl) - replace_with = replace_with.strip() - if (replace_with.startswith('*') - and '&[' in self._backend.getcname(cdecl, '&')): - replace_with = '(%s)' % replace_with - elif replace_with and not replace_with[0] in '[(': - replace_with = ' ' + replace_with - return self._backend.getcname(cdecl, replace_with) - - def gc(self, cdata, destructor, size=0): - """Return a new cdata object that points to the same - data. Later, when this new cdata object is garbage-collected, - 'destructor(old_cdata_object)' will be called. - - The optional 'size' gives an estimate of the size, used to - trigger the garbage collection more eagerly. So far only used - on PyPy. It tells the GC that the returned object keeps alive - roughly 'size' bytes of external memory. - """ - return self._backend.gcp(cdata, destructor, size) - - def _get_cached_btype(self, type): - assert self._lock.acquire(False) is False - # call me with the lock! - try: - BType = self._cached_btypes[type] - except KeyError: - finishlist = [] - BType = type.get_cached_btype(self, finishlist) - for type in finishlist: - type.finish_backend_type(self, finishlist) - return BType - - def verify(self, source='', tmpdir=None, **kwargs): - """Verify that the current ffi signatures compile on this - machine, and return a dynamic library object. The dynamic - library can be used to call functions and access global - variables declared in this 'ffi'. The library is compiled - by the C compiler: it gives you C-level API compatibility - (including calling macros). This is unlike 'ffi.dlopen()', - which requires binary compatibility in the signatures. - """ - from .verifier import Verifier, _caller_dir_pycache - # - # If set_unicode(True) was called, insert the UNICODE and - # _UNICODE macro declarations - if self._windows_unicode: - self._apply_windows_unicode(kwargs) - # - # Set the tmpdir here, and not in Verifier.__init__: it picks - # up the caller's directory, which we want to be the caller of - # ffi.verify(), as opposed to the caller of Veritier(). - tmpdir = tmpdir or _caller_dir_pycache() - # - # Make a Verifier() and use it to load the library. - self.verifier = Verifier(self, source, tmpdir, **kwargs) - lib = self.verifier.load_library() - # - # Save the loaded library for keep-alive purposes, even - # if the caller doesn't keep it alive itself (it should). - self._libraries.append(lib) - return lib - - def _get_errno(self): - return self._backend.get_errno() - def _set_errno(self, errno): - self._backend.set_errno(errno) - errno = property(_get_errno, _set_errno, None, - "the value of 'errno' from/to the C calls") - - def getwinerror(self, code=-1): - return self._backend.getwinerror(code) - - def _pointer_to(self, ctype): - with self._lock: - return model.pointer_cache(self, ctype) - - def addressof(self, cdata, *fields_or_indexes): - """Return the address of a . - If 'fields_or_indexes' are given, returns the address of that - field or array item in the structure or array, recursively in - case of nested structures. - """ - try: - ctype = self._backend.typeof(cdata) - except TypeError: - if '__addressof__' in type(cdata).__dict__: - return type(cdata).__addressof__(cdata, *fields_or_indexes) - raise - if fields_or_indexes: - ctype, offset = self._typeoffsetof(ctype, *fields_or_indexes) - else: - if ctype.kind == "pointer": - raise TypeError("addressof(pointer)") - offset = 0 - ctypeptr = self._pointer_to(ctype) - return self._backend.rawaddressof(ctypeptr, cdata, offset) - - def _typeoffsetof(self, ctype, field_or_index, *fields_or_indexes): - ctype, offset = self._backend.typeoffsetof(ctype, field_or_index) - for field1 in fields_or_indexes: - ctype, offset1 = self._backend.typeoffsetof(ctype, field1, 1) - offset += offset1 - return ctype, offset - - def include(self, ffi_to_include): - """Includes the typedefs, structs, unions and enums defined - in another FFI instance. Usage is similar to a #include in C, - where a part of the program might include types defined in - another part for its own usage. Note that the include() - method has no effect on functions, constants and global - variables, which must anyway be accessed directly from the - lib object returned by the original FFI instance. - """ - if not isinstance(ffi_to_include, FFI): - raise TypeError("ffi.include() expects an argument that is also of" - " type cffi.FFI, not %r" % ( - type(ffi_to_include).__name__,)) - if ffi_to_include is self: - raise ValueError("self.include(self)") - with ffi_to_include._lock: - with self._lock: - self._parser.include(ffi_to_include._parser) - self._cdefsources.append('[') - self._cdefsources.extend(ffi_to_include._cdefsources) - self._cdefsources.append(']') - self._included_ffis.append(ffi_to_include) - - def new_handle(self, x): - return self._backend.newp_handle(self.BVoidP, x) - - def from_handle(self, x): - return self._backend.from_handle(x) - - def release(self, x): - self._backend.release(x) - - def set_unicode(self, enabled_flag): - """Windows: if 'enabled_flag' is True, enable the UNICODE and - _UNICODE defines in C, and declare the types like TCHAR and LPTCSTR - to be (pointers to) wchar_t. If 'enabled_flag' is False, - declare these types to be (pointers to) plain 8-bit characters. - This is mostly for backward compatibility; you usually want True. - """ - if self._windows_unicode is not None: - raise ValueError("set_unicode() can only be called once") - enabled_flag = bool(enabled_flag) - if enabled_flag: - self.cdef("typedef wchar_t TBYTE;" - "typedef wchar_t TCHAR;" - "typedef const wchar_t *LPCTSTR;" - "typedef const wchar_t *PCTSTR;" - "typedef wchar_t *LPTSTR;" - "typedef wchar_t *PTSTR;" - "typedef TBYTE *PTBYTE;" - "typedef TCHAR *PTCHAR;") - else: - self.cdef("typedef char TBYTE;" - "typedef char TCHAR;" - "typedef const char *LPCTSTR;" - "typedef const char *PCTSTR;" - "typedef char *LPTSTR;" - "typedef char *PTSTR;" - "typedef TBYTE *PTBYTE;" - "typedef TCHAR *PTCHAR;") - self._windows_unicode = enabled_flag - - def _apply_windows_unicode(self, kwds): - defmacros = kwds.get('define_macros', ()) - if not isinstance(defmacros, (list, tuple)): - raise TypeError("'define_macros' must be a list or tuple") - defmacros = list(defmacros) + [('UNICODE', '1'), - ('_UNICODE', '1')] - kwds['define_macros'] = defmacros - - def _apply_embedding_fix(self, kwds): - # must include an argument like "-lpython2.7" for the compiler - def ensure(key, value): - lst = kwds.setdefault(key, []) - if value not in lst: - lst.append(value) - # - if '__pypy__' in sys.builtin_module_names: - import os - if sys.platform == "win32": - # we need 'libpypy-c.lib'. Current distributions of - # pypy (>= 4.1) contain it as 'libs/python27.lib'. - pythonlib = "python{0[0]}{0[1]}".format(sys.version_info) - if hasattr(sys, 'prefix'): - ensure('library_dirs', os.path.join(sys.prefix, 'libs')) - else: - # we need 'libpypy-c.{so,dylib}', which should be by - # default located in 'sys.prefix/bin' for installed - # systems. - if sys.version_info < (3,): - pythonlib = "pypy-c" - else: - pythonlib = "pypy3-c" - if hasattr(sys, 'prefix'): - ensure('library_dirs', os.path.join(sys.prefix, 'bin')) - # On uninstalled pypy's, the libpypy-c is typically found in - # .../pypy/goal/. - if hasattr(sys, 'prefix'): - ensure('library_dirs', os.path.join(sys.prefix, 'pypy', 'goal')) - else: - if sys.platform == "win32": - template = "python%d%d" - if hasattr(sys, 'gettotalrefcount'): - template += '_d' - else: - try: - import sysconfig - except ImportError: # 2.6 - from cffi._shimmed_dist_utils import sysconfig - template = "python%d.%d" - if sysconfig.get_config_var('DEBUG_EXT'): - template += sysconfig.get_config_var('DEBUG_EXT') - pythonlib = (template % - (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) - if hasattr(sys, 'abiflags'): - pythonlib += sys.abiflags - ensure('libraries', pythonlib) - if sys.platform == "win32": - ensure('extra_link_args', '/MANIFEST') - - def set_source(self, module_name, source, source_extension='.c', **kwds): - import os - if hasattr(self, '_assigned_source'): - raise ValueError("set_source() cannot be called several times " - "per ffi object") - if not isinstance(module_name, basestring): - raise TypeError("'module_name' must be a string") - if os.sep in module_name or (os.altsep and os.altsep in module_name): - raise ValueError("'module_name' must not contain '/': use a dotted " - "name to make a 'package.module' location") - self._assigned_source = (str(module_name), source, - source_extension, kwds) - - def set_source_pkgconfig(self, module_name, pkgconfig_libs, source, - source_extension='.c', **kwds): - from . import pkgconfig - if not isinstance(pkgconfig_libs, list): - raise TypeError("the pkgconfig_libs argument must be a list " - "of package names") - kwds2 = pkgconfig.flags_from_pkgconfig(pkgconfig_libs) - pkgconfig.merge_flags(kwds, kwds2) - self.set_source(module_name, source, source_extension, **kwds) - - def distutils_extension(self, tmpdir='build', verbose=True): - from cffi._shimmed_dist_utils import mkpath - from .recompiler import recompile - # - if not hasattr(self, '_assigned_source'): - if hasattr(self, 'verifier'): # fallback, 'tmpdir' ignored - return self.verifier.get_extension() - raise ValueError("set_source() must be called before" - " distutils_extension()") - module_name, source, source_extension, kwds = self._assigned_source - if source is None: - raise TypeError("distutils_extension() is only for C extension " - "modules, not for dlopen()-style pure Python " - "modules") - mkpath(tmpdir) - ext, updated = recompile(self, module_name, - source, tmpdir=tmpdir, extradir=tmpdir, - source_extension=source_extension, - call_c_compiler=False, **kwds) - if verbose: - if updated: - sys.stderr.write("regenerated: %r\n" % (ext.sources[0],)) - else: - sys.stderr.write("not modified: %r\n" % (ext.sources[0],)) - return ext - - def emit_c_code(self, filename): - from .recompiler import recompile - # - if not hasattr(self, '_assigned_source'): - raise ValueError("set_source() must be called before emit_c_code()") - module_name, source, source_extension, kwds = self._assigned_source - if source is None: - raise TypeError("emit_c_code() is only for C extension modules, " - "not for dlopen()-style pure Python modules") - recompile(self, module_name, source, - c_file=filename, call_c_compiler=False, - uses_ffiplatform=False, **kwds) - - def emit_python_code(self, filename): - from .recompiler import recompile - # - if not hasattr(self, '_assigned_source'): - raise ValueError("set_source() must be called before emit_c_code()") - module_name, source, source_extension, kwds = self._assigned_source - if source is not None: - raise TypeError("emit_python_code() is only for dlopen()-style " - "pure Python modules, not for C extension modules") - recompile(self, module_name, source, - c_file=filename, call_c_compiler=False, - uses_ffiplatform=False, **kwds) - - def compile(self, tmpdir='.', verbose=0, target=None, debug=None): - """The 'target' argument gives the final file name of the - compiled DLL. Use '*' to force distutils' choice, suitable for - regular CPython C API modules. Use a file name ending in '.*' - to ask for the system's default extension for dynamic libraries - (.so/.dll/.dylib). - - The default is '*' when building a non-embedded C API extension, - and (module_name + '.*') when building an embedded library. - """ - from .recompiler import recompile - # - if not hasattr(self, '_assigned_source'): - raise ValueError("set_source() must be called before compile()") - module_name, source, source_extension, kwds = self._assigned_source - return recompile(self, module_name, source, tmpdir=tmpdir, - target=target, source_extension=source_extension, - compiler_verbose=verbose, debug=debug, **kwds) - - def init_once(self, func, tag): - # Read _init_once_cache[tag], which is either (False, lock) if - # we're calling the function now in some thread, or (True, result). - # Don't call setdefault() in most cases, to avoid allocating and - # immediately freeing a lock; but still use setdefaut() to avoid - # races. - try: - x = self._init_once_cache[tag] - except KeyError: - x = self._init_once_cache.setdefault(tag, (False, allocate_lock())) - # Common case: we got (True, result), so we return the result. - if x[0]: - return x[1] - # Else, it's a lock. Acquire it to serialize the following tests. - with x[1]: - # Read again from _init_once_cache the current status. - x = self._init_once_cache[tag] - if x[0]: - return x[1] - # Call the function and store the result back. - result = func() - self._init_once_cache[tag] = (True, result) - return result - - def embedding_init_code(self, pysource): - if self._embedding: - raise ValueError("embedding_init_code() can only be called once") - # fix 'pysource' before it gets dumped into the C file: - # - remove empty lines at the beginning, so it starts at "line 1" - # - dedent, if all non-empty lines are indented - # - check for SyntaxErrors - import re - match = re.match(r'\s*\n', pysource) - if match: - pysource = pysource[match.end():] - lines = pysource.splitlines() or [''] - prefix = re.match(r'\s*', lines[0]).group() - for i in range(1, len(lines)): - line = lines[i] - if line.rstrip(): - while not line.startswith(prefix): - prefix = prefix[:-1] - i = len(prefix) - lines = [line[i:]+'\n' for line in lines] - pysource = ''.join(lines) - # - compile(pysource, "cffi_init", "exec") - # - self._embedding = pysource - - def def_extern(self, *args, **kwds): - raise ValueError("ffi.def_extern() is only available on API-mode FFI " - "objects") - - def list_types(self): - """Returns the user type names known to this FFI instance. - This returns a tuple containing three lists of names: - (typedef_names, names_of_structs, names_of_unions) - """ - typedefs = [] - structs = [] - unions = [] - for key in self._parser._declarations: - if key.startswith('typedef '): - typedefs.append(key[8:]) - elif key.startswith('struct '): - structs.append(key[7:]) - elif key.startswith('union '): - unions.append(key[6:]) - typedefs.sort() - structs.sort() - unions.sort() - return (typedefs, structs, unions) - - -def _load_backend_lib(backend, name, flags): - import os - if not isinstance(name, basestring): - if sys.platform != "win32" or name is not None: - return backend.load_library(name, flags) - name = "c" # Windows: load_library(None) fails, but this works - # on Python 2 (backward compatibility hack only) - first_error = None - if '.' in name or '/' in name or os.sep in name: - try: - return backend.load_library(name, flags) - except OSError as e: - first_error = e - import ctypes.util - path = ctypes.util.find_library(name) - if path is None: - if name == "c" and sys.platform == "win32" and sys.version_info >= (3,): - raise OSError("dlopen(None) cannot work on Windows for Python 3 " - "(see http://bugs.python.org/issue23606)") - msg = ("ctypes.util.find_library() did not manage " - "to locate a library called %r" % (name,)) - if first_error is not None: - msg = "%s. Additionally, %s" % (first_error, msg) - raise OSError(msg) - return backend.load_library(path, flags) - -def _make_ffi_library(ffi, libname, flags): - backend = ffi._backend - backendlib = _load_backend_lib(backend, libname, flags) - # - def accessor_function(name): - key = 'function ' + name - tp, _ = ffi._parser._declarations[key] - BType = ffi._get_cached_btype(tp) - value = backendlib.load_function(BType, name) - library.__dict__[name] = value - # - def accessor_variable(name): - key = 'variable ' + name - tp, _ = ffi._parser._declarations[key] - BType = ffi._get_cached_btype(tp) - read_variable = backendlib.read_variable - write_variable = backendlib.write_variable - setattr(FFILibrary, name, property( - lambda self: read_variable(BType, name), - lambda self, value: write_variable(BType, name, value))) - # - def addressof_var(name): - try: - return addr_variables[name] - except KeyError: - with ffi._lock: - if name not in addr_variables: - key = 'variable ' + name - tp, _ = ffi._parser._declarations[key] - BType = ffi._get_cached_btype(tp) - if BType.kind != 'array': - BType = model.pointer_cache(ffi, BType) - p = backendlib.load_function(BType, name) - addr_variables[name] = p - return addr_variables[name] - # - def accessor_constant(name): - raise NotImplementedError("non-integer constant '%s' cannot be " - "accessed from a dlopen() library" % (name,)) - # - def accessor_int_constant(name): - library.__dict__[name] = ffi._parser._int_constants[name] - # - accessors = {} - accessors_version = [False] - addr_variables = {} - # - def update_accessors(): - if accessors_version[0] is ffi._cdef_version: - return - # - for key, (tp, _) in ffi._parser._declarations.items(): - if not isinstance(tp, model.EnumType): - tag, name = key.split(' ', 1) - if tag == 'function': - accessors[name] = accessor_function - elif tag == 'variable': - accessors[name] = accessor_variable - elif tag == 'constant': - accessors[name] = accessor_constant - else: - for i, enumname in enumerate(tp.enumerators): - def accessor_enum(name, tp=tp, i=i): - tp.check_not_partial() - library.__dict__[name] = tp.enumvalues[i] - accessors[enumname] = accessor_enum - for name in ffi._parser._int_constants: - accessors.setdefault(name, accessor_int_constant) - accessors_version[0] = ffi._cdef_version - # - def make_accessor(name): - with ffi._lock: - if name in library.__dict__ or name in FFILibrary.__dict__: - return # added by another thread while waiting for the lock - if name not in accessors: - update_accessors() - if name not in accessors: - raise AttributeError(name) - accessors[name](name) - # - class FFILibrary(object): - def __getattr__(self, name): - make_accessor(name) - return getattr(self, name) - def __setattr__(self, name, value): - try: - property = getattr(self.__class__, name) - except AttributeError: - make_accessor(name) - setattr(self, name, value) - else: - property.__set__(self, value) - def __dir__(self): - with ffi._lock: - update_accessors() - return accessors.keys() - def __addressof__(self, name): - if name in library.__dict__: - return library.__dict__[name] - if name in FFILibrary.__dict__: - return addressof_var(name) - make_accessor(name) - if name in library.__dict__: - return library.__dict__[name] - if name in FFILibrary.__dict__: - return addressof_var(name) - raise AttributeError("cffi library has no function or " - "global variable named '%s'" % (name,)) - def __cffi_close__(self): - backendlib.close_lib() - self.__dict__.clear() - # - if isinstance(libname, basestring): - try: - if not isinstance(libname, str): # unicode, on Python 2 - libname = libname.encode('utf-8') - FFILibrary.__name__ = 'FFILibrary_%s' % libname - except UnicodeError: - pass - library = FFILibrary() - return library, library.__dict__ - -def _builtin_function_type(func): - # a hack to make at least ffi.typeof(builtin_function) work, - # if the builtin function was obtained by 'vengine_cpy'. - import sys - try: - module = sys.modules[func.__module__] - ffi = module._cffi_original_ffi - types_of_builtin_funcs = module._cffi_types_of_builtin_funcs - tp = types_of_builtin_funcs[func] - except (KeyError, AttributeError, TypeError): - return None - else: - with ffi._lock: - return ffi._get_cached_btype(tp) diff --git a/notification-service/venv/Lib/site-packages/cffi/backend_ctypes.py b/notification-service/venv/Lib/site-packages/cffi/backend_ctypes.py deleted file mode 100644 index e7956a7..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/backend_ctypes.py +++ /dev/null @@ -1,1121 +0,0 @@ -import ctypes, ctypes.util, operator, sys -from . import model - -if sys.version_info < (3,): - bytechr = chr -else: - unicode = str - long = int - xrange = range - bytechr = lambda num: bytes([num]) - -class CTypesType(type): - pass - -class CTypesData(object): - __metaclass__ = CTypesType - __slots__ = ['__weakref__'] - __name__ = '' - - def __init__(self, *args): - raise TypeError("cannot instantiate %r" % (self.__class__,)) - - @classmethod - def _newp(cls, init): - raise TypeError("expected a pointer or array ctype, got '%s'" - % (cls._get_c_name(),)) - - @staticmethod - def _to_ctypes(value): - raise TypeError - - @classmethod - def _arg_to_ctypes(cls, *value): - try: - ctype = cls._ctype - except AttributeError: - raise TypeError("cannot create an instance of %r" % (cls,)) - if value: - res = cls._to_ctypes(*value) - if not isinstance(res, ctype): - res = cls._ctype(res) - else: - res = cls._ctype() - return res - - @classmethod - def _create_ctype_obj(cls, init): - if init is None: - return cls._arg_to_ctypes() - else: - return cls._arg_to_ctypes(init) - - @staticmethod - def _from_ctypes(ctypes_value): - raise TypeError - - @classmethod - def _get_c_name(cls, replace_with=''): - return cls._reftypename.replace(' &', replace_with) - - @classmethod - def _fix_class(cls): - cls.__name__ = 'CData<%s>' % (cls._get_c_name(),) - cls.__qualname__ = 'CData<%s>' % (cls._get_c_name(),) - cls.__module__ = 'ffi' - - def _get_own_repr(self): - raise NotImplementedError - - def _addr_repr(self, address): - if address == 0: - return 'NULL' - else: - if address < 0: - address += 1 << (8*ctypes.sizeof(ctypes.c_void_p)) - return '0x%x' % address - - def __repr__(self, c_name=None): - own = self._get_own_repr() - return '' % (c_name or self._get_c_name(), own) - - def _convert_to_address(self, BClass): - if BClass is None: - raise TypeError("cannot convert %r to an address" % ( - self._get_c_name(),)) - else: - raise TypeError("cannot convert %r to %r" % ( - self._get_c_name(), BClass._get_c_name())) - - @classmethod - def _get_size(cls): - return ctypes.sizeof(cls._ctype) - - def _get_size_of_instance(self): - return ctypes.sizeof(self._ctype) - - @classmethod - def _cast_from(cls, source): - raise TypeError("cannot cast to %r" % (cls._get_c_name(),)) - - def _cast_to_integer(self): - return self._convert_to_address(None) - - @classmethod - def _alignment(cls): - return ctypes.alignment(cls._ctype) - - def __iter__(self): - raise TypeError("cdata %r does not support iteration" % ( - self._get_c_name()),) - - def _make_cmp(name): - cmpfunc = getattr(operator, name) - def cmp(self, other): - v_is_ptr = not isinstance(self, CTypesGenericPrimitive) - w_is_ptr = (isinstance(other, CTypesData) and - not isinstance(other, CTypesGenericPrimitive)) - if v_is_ptr and w_is_ptr: - return cmpfunc(self._convert_to_address(None), - other._convert_to_address(None)) - elif v_is_ptr or w_is_ptr: - return NotImplemented - else: - if isinstance(self, CTypesGenericPrimitive): - self = self._value - if isinstance(other, CTypesGenericPrimitive): - other = other._value - return cmpfunc(self, other) - cmp.func_name = name - return cmp - - __eq__ = _make_cmp('__eq__') - __ne__ = _make_cmp('__ne__') - __lt__ = _make_cmp('__lt__') - __le__ = _make_cmp('__le__') - __gt__ = _make_cmp('__gt__') - __ge__ = _make_cmp('__ge__') - - def __hash__(self): - return hash(self._convert_to_address(None)) - - def _to_string(self, maxlen): - raise TypeError("string(): %r" % (self,)) - - -class CTypesGenericPrimitive(CTypesData): - __slots__ = [] - - def __hash__(self): - return hash(self._value) - - def _get_own_repr(self): - return repr(self._from_ctypes(self._value)) - - -class CTypesGenericArray(CTypesData): - __slots__ = [] - - @classmethod - def _newp(cls, init): - return cls(init) - - def __iter__(self): - for i in xrange(len(self)): - yield self[i] - - def _get_own_repr(self): - return self._addr_repr(ctypes.addressof(self._blob)) - - -class CTypesGenericPtr(CTypesData): - __slots__ = ['_address', '_as_ctype_ptr'] - _automatic_casts = False - kind = "pointer" - - @classmethod - def _newp(cls, init): - return cls(init) - - @classmethod - def _cast_from(cls, source): - if source is None: - address = 0 - elif isinstance(source, CTypesData): - address = source._cast_to_integer() - elif isinstance(source, (int, long)): - address = source - else: - raise TypeError("bad type for cast to %r: %r" % - (cls, type(source).__name__)) - return cls._new_pointer_at(address) - - @classmethod - def _new_pointer_at(cls, address): - self = cls.__new__(cls) - self._address = address - self._as_ctype_ptr = ctypes.cast(address, cls._ctype) - return self - - def _get_own_repr(self): - try: - return self._addr_repr(self._address) - except AttributeError: - return '???' - - def _cast_to_integer(self): - return self._address - - def __nonzero__(self): - return bool(self._address) - __bool__ = __nonzero__ - - @classmethod - def _to_ctypes(cls, value): - if not isinstance(value, CTypesData): - raise TypeError("unexpected %s object" % type(value).__name__) - address = value._convert_to_address(cls) - return ctypes.cast(address, cls._ctype) - - @classmethod - def _from_ctypes(cls, ctypes_ptr): - address = ctypes.cast(ctypes_ptr, ctypes.c_void_p).value or 0 - return cls._new_pointer_at(address) - - @classmethod - def _initialize(cls, ctypes_ptr, value): - if value: - ctypes_ptr.contents = cls._to_ctypes(value).contents - - def _convert_to_address(self, BClass): - if (BClass in (self.__class__, None) or BClass._automatic_casts - or self._automatic_casts): - return self._address - else: - return CTypesData._convert_to_address(self, BClass) - - -class CTypesBaseStructOrUnion(CTypesData): - __slots__ = ['_blob'] - - @classmethod - def _create_ctype_obj(cls, init): - # may be overridden - raise TypeError("cannot instantiate opaque type %s" % (cls,)) - - def _get_own_repr(self): - return self._addr_repr(ctypes.addressof(self._blob)) - - @classmethod - def _offsetof(cls, fieldname): - return getattr(cls._ctype, fieldname).offset - - def _convert_to_address(self, BClass): - if getattr(BClass, '_BItem', None) is self.__class__: - return ctypes.addressof(self._blob) - else: - return CTypesData._convert_to_address(self, BClass) - - @classmethod - def _from_ctypes(cls, ctypes_struct_or_union): - self = cls.__new__(cls) - self._blob = ctypes_struct_or_union - return self - - @classmethod - def _to_ctypes(cls, value): - return value._blob - - def __repr__(self, c_name=None): - return CTypesData.__repr__(self, c_name or self._get_c_name(' &')) - - -class CTypesBackend(object): - - PRIMITIVE_TYPES = { - 'char': ctypes.c_char, - 'short': ctypes.c_short, - 'int': ctypes.c_int, - 'long': ctypes.c_long, - 'long long': ctypes.c_longlong, - 'signed char': ctypes.c_byte, - 'unsigned char': ctypes.c_ubyte, - 'unsigned short': ctypes.c_ushort, - 'unsigned int': ctypes.c_uint, - 'unsigned long': ctypes.c_ulong, - 'unsigned long long': ctypes.c_ulonglong, - 'float': ctypes.c_float, - 'double': ctypes.c_double, - '_Bool': ctypes.c_bool, - } - - for _name in ['unsigned long long', 'unsigned long', - 'unsigned int', 'unsigned short', 'unsigned char']: - _size = ctypes.sizeof(PRIMITIVE_TYPES[_name]) - PRIMITIVE_TYPES['uint%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name] - if _size == ctypes.sizeof(ctypes.c_void_p): - PRIMITIVE_TYPES['uintptr_t'] = PRIMITIVE_TYPES[_name] - if _size == ctypes.sizeof(ctypes.c_size_t): - PRIMITIVE_TYPES['size_t'] = PRIMITIVE_TYPES[_name] - - for _name in ['long long', 'long', 'int', 'short', 'signed char']: - _size = ctypes.sizeof(PRIMITIVE_TYPES[_name]) - PRIMITIVE_TYPES['int%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name] - if _size == ctypes.sizeof(ctypes.c_void_p): - PRIMITIVE_TYPES['intptr_t'] = PRIMITIVE_TYPES[_name] - PRIMITIVE_TYPES['ptrdiff_t'] = PRIMITIVE_TYPES[_name] - if _size == ctypes.sizeof(ctypes.c_size_t): - PRIMITIVE_TYPES['ssize_t'] = PRIMITIVE_TYPES[_name] - - - def __init__(self): - self.RTLD_LAZY = 0 # not supported anyway by ctypes - self.RTLD_NOW = 0 - self.RTLD_GLOBAL = ctypes.RTLD_GLOBAL - self.RTLD_LOCAL = ctypes.RTLD_LOCAL - - def set_ffi(self, ffi): - self.ffi = ffi - - def _get_types(self): - return CTypesData, CTypesType - - def load_library(self, path, flags=0): - cdll = ctypes.CDLL(path, flags) - return CTypesLibrary(self, cdll) - - def new_void_type(self): - class CTypesVoid(CTypesData): - __slots__ = [] - _reftypename = 'void &' - @staticmethod - def _from_ctypes(novalue): - return None - @staticmethod - def _to_ctypes(novalue): - if novalue is not None: - raise TypeError("None expected, got %s object" % - (type(novalue).__name__,)) - return None - CTypesVoid._fix_class() - return CTypesVoid - - def new_primitive_type(self, name): - if name == 'wchar_t': - raise NotImplementedError(name) - ctype = self.PRIMITIVE_TYPES[name] - if name == 'char': - kind = 'char' - elif name in ('float', 'double'): - kind = 'float' - else: - if name in ('signed char', 'unsigned char'): - kind = 'byte' - elif name == '_Bool': - kind = 'bool' - else: - kind = 'int' - is_signed = (ctype(-1).value == -1) - # - def _cast_source_to_int(source): - if isinstance(source, (int, long, float)): - source = int(source) - elif isinstance(source, CTypesData): - source = source._cast_to_integer() - elif isinstance(source, bytes): - source = ord(source) - elif source is None: - source = 0 - else: - raise TypeError("bad type for cast to %r: %r" % - (CTypesPrimitive, type(source).__name__)) - return source - # - kind1 = kind - class CTypesPrimitive(CTypesGenericPrimitive): - __slots__ = ['_value'] - _ctype = ctype - _reftypename = '%s &' % name - kind = kind1 - - def __init__(self, value): - self._value = value - - @staticmethod - def _create_ctype_obj(init): - if init is None: - return ctype() - return ctype(CTypesPrimitive._to_ctypes(init)) - - if kind == 'int' or kind == 'byte': - @classmethod - def _cast_from(cls, source): - source = _cast_source_to_int(source) - source = ctype(source).value # cast within range - return cls(source) - def __int__(self): - return self._value - - if kind == 'bool': - @classmethod - def _cast_from(cls, source): - if not isinstance(source, (int, long, float)): - source = _cast_source_to_int(source) - return cls(bool(source)) - def __int__(self): - return int(self._value) - - if kind == 'char': - @classmethod - def _cast_from(cls, source): - source = _cast_source_to_int(source) - source = bytechr(source & 0xFF) - return cls(source) - def __int__(self): - return ord(self._value) - - if kind == 'float': - @classmethod - def _cast_from(cls, source): - if isinstance(source, float): - pass - elif isinstance(source, CTypesGenericPrimitive): - if hasattr(source, '__float__'): - source = float(source) - else: - source = int(source) - else: - source = _cast_source_to_int(source) - source = ctype(source).value # fix precision - return cls(source) - def __int__(self): - return int(self._value) - def __float__(self): - return self._value - - _cast_to_integer = __int__ - - if kind == 'int' or kind == 'byte' or kind == 'bool': - @staticmethod - def _to_ctypes(x): - if not isinstance(x, (int, long)): - if isinstance(x, CTypesData): - x = int(x) - else: - raise TypeError("integer expected, got %s" % - type(x).__name__) - if ctype(x).value != x: - if not is_signed and x < 0: - raise OverflowError("%s: negative integer" % name) - else: - raise OverflowError("%s: integer out of bounds" - % name) - return x - - if kind == 'char': - @staticmethod - def _to_ctypes(x): - if isinstance(x, bytes) and len(x) == 1: - return x - if isinstance(x, CTypesPrimitive): # > - return x._value - raise TypeError("character expected, got %s" % - type(x).__name__) - def __nonzero__(self): - return ord(self._value) != 0 - else: - def __nonzero__(self): - return self._value != 0 - __bool__ = __nonzero__ - - if kind == 'float': - @staticmethod - def _to_ctypes(x): - if not isinstance(x, (int, long, float, CTypesData)): - raise TypeError("float expected, got %s" % - type(x).__name__) - return ctype(x).value - - @staticmethod - def _from_ctypes(value): - return getattr(value, 'value', value) - - @staticmethod - def _initialize(blob, init): - blob.value = CTypesPrimitive._to_ctypes(init) - - if kind == 'char': - def _to_string(self, maxlen): - return self._value - if kind == 'byte': - def _to_string(self, maxlen): - return chr(self._value & 0xff) - # - CTypesPrimitive._fix_class() - return CTypesPrimitive - - def new_pointer_type(self, BItem): - getbtype = self.ffi._get_cached_btype - if BItem is getbtype(model.PrimitiveType('char')): - kind = 'charp' - elif BItem in (getbtype(model.PrimitiveType('signed char')), - getbtype(model.PrimitiveType('unsigned char'))): - kind = 'bytep' - elif BItem is getbtype(model.void_type): - kind = 'voidp' - else: - kind = 'generic' - # - class CTypesPtr(CTypesGenericPtr): - __slots__ = ['_own'] - if kind == 'charp': - __slots__ += ['__as_strbuf'] - _BItem = BItem - if hasattr(BItem, '_ctype'): - _ctype = ctypes.POINTER(BItem._ctype) - _bitem_size = ctypes.sizeof(BItem._ctype) - else: - _ctype = ctypes.c_void_p - if issubclass(BItem, CTypesGenericArray): - _reftypename = BItem._get_c_name('(* &)') - else: - _reftypename = BItem._get_c_name(' * &') - - def __init__(self, init): - ctypeobj = BItem._create_ctype_obj(init) - if kind == 'charp': - self.__as_strbuf = ctypes.create_string_buffer( - ctypeobj.value + b'\x00') - self._as_ctype_ptr = ctypes.cast( - self.__as_strbuf, self._ctype) - else: - self._as_ctype_ptr = ctypes.pointer(ctypeobj) - self._address = ctypes.cast(self._as_ctype_ptr, - ctypes.c_void_p).value - self._own = True - - def __add__(self, other): - if isinstance(other, (int, long)): - return self._new_pointer_at(self._address + - other * self._bitem_size) - else: - return NotImplemented - - def __sub__(self, other): - if isinstance(other, (int, long)): - return self._new_pointer_at(self._address - - other * self._bitem_size) - elif type(self) is type(other): - return (self._address - other._address) // self._bitem_size - else: - return NotImplemented - - def __getitem__(self, index): - if getattr(self, '_own', False) and index != 0: - raise IndexError - return BItem._from_ctypes(self._as_ctype_ptr[index]) - - def __setitem__(self, index, value): - self._as_ctype_ptr[index] = BItem._to_ctypes(value) - - if kind == 'charp' or kind == 'voidp': - @classmethod - def _arg_to_ctypes(cls, *value): - if value and isinstance(value[0], bytes): - return ctypes.c_char_p(value[0]) - else: - return super(CTypesPtr, cls)._arg_to_ctypes(*value) - - if kind == 'charp' or kind == 'bytep': - def _to_string(self, maxlen): - if maxlen < 0: - maxlen = sys.maxsize - p = ctypes.cast(self._as_ctype_ptr, - ctypes.POINTER(ctypes.c_char)) - n = 0 - while n < maxlen and p[n] != b'\x00': - n += 1 - return b''.join([p[i] for i in range(n)]) - - def _get_own_repr(self): - if getattr(self, '_own', False): - return 'owning %d bytes' % ( - ctypes.sizeof(self._as_ctype_ptr.contents),) - return super(CTypesPtr, self)._get_own_repr() - # - if (BItem is self.ffi._get_cached_btype(model.void_type) or - BItem is self.ffi._get_cached_btype(model.PrimitiveType('char'))): - CTypesPtr._automatic_casts = True - # - CTypesPtr._fix_class() - return CTypesPtr - - def new_array_type(self, CTypesPtr, length): - if length is None: - brackets = ' &[]' - else: - brackets = ' &[%d]' % length - BItem = CTypesPtr._BItem - getbtype = self.ffi._get_cached_btype - if BItem is getbtype(model.PrimitiveType('char')): - kind = 'char' - elif BItem in (getbtype(model.PrimitiveType('signed char')), - getbtype(model.PrimitiveType('unsigned char'))): - kind = 'byte' - else: - kind = 'generic' - # - class CTypesArray(CTypesGenericArray): - __slots__ = ['_blob', '_own'] - if length is not None: - _ctype = BItem._ctype * length - else: - __slots__.append('_ctype') - _reftypename = BItem._get_c_name(brackets) - _declared_length = length - _CTPtr = CTypesPtr - - def __init__(self, init): - if length is None: - if isinstance(init, (int, long)): - len1 = init - init = None - elif kind == 'char' and isinstance(init, bytes): - len1 = len(init) + 1 # extra null - else: - init = tuple(init) - len1 = len(init) - self._ctype = BItem._ctype * len1 - self._blob = self._ctype() - self._own = True - if init is not None: - self._initialize(self._blob, init) - - @staticmethod - def _initialize(blob, init): - if isinstance(init, bytes): - init = [init[i:i+1] for i in range(len(init))] - else: - if isinstance(init, CTypesGenericArray): - if (len(init) != len(blob) or - not isinstance(init, CTypesArray)): - raise TypeError("length/type mismatch: %s" % (init,)) - init = tuple(init) - if len(init) > len(blob): - raise IndexError("too many initializers") - addr = ctypes.cast(blob, ctypes.c_void_p).value - PTR = ctypes.POINTER(BItem._ctype) - itemsize = ctypes.sizeof(BItem._ctype) - for i, value in enumerate(init): - p = ctypes.cast(addr + i * itemsize, PTR) - BItem._initialize(p.contents, value) - - def __len__(self): - return len(self._blob) - - def __getitem__(self, index): - if not (0 <= index < len(self._blob)): - raise IndexError - return BItem._from_ctypes(self._blob[index]) - - def __setitem__(self, index, value): - if not (0 <= index < len(self._blob)): - raise IndexError - self._blob[index] = BItem._to_ctypes(value) - - if kind == 'char' or kind == 'byte': - def _to_string(self, maxlen): - if maxlen < 0: - maxlen = len(self._blob) - p = ctypes.cast(self._blob, - ctypes.POINTER(ctypes.c_char)) - n = 0 - while n < maxlen and p[n] != b'\x00': - n += 1 - return b''.join([p[i] for i in range(n)]) - - def _get_own_repr(self): - if getattr(self, '_own', False): - return 'owning %d bytes' % (ctypes.sizeof(self._blob),) - return super(CTypesArray, self)._get_own_repr() - - def _convert_to_address(self, BClass): - if BClass in (CTypesPtr, None) or BClass._automatic_casts: - return ctypes.addressof(self._blob) - else: - return CTypesData._convert_to_address(self, BClass) - - @staticmethod - def _from_ctypes(ctypes_array): - self = CTypesArray.__new__(CTypesArray) - self._blob = ctypes_array - return self - - @staticmethod - def _arg_to_ctypes(value): - return CTypesPtr._arg_to_ctypes(value) - - def __add__(self, other): - if isinstance(other, (int, long)): - return CTypesPtr._new_pointer_at( - ctypes.addressof(self._blob) + - other * ctypes.sizeof(BItem._ctype)) - else: - return NotImplemented - - @classmethod - def _cast_from(cls, source): - raise NotImplementedError("casting to %r" % ( - cls._get_c_name(),)) - # - CTypesArray._fix_class() - return CTypesArray - - def _new_struct_or_union(self, kind, name, base_ctypes_class): - # - class struct_or_union(base_ctypes_class): - pass - struct_or_union.__name__ = '%s_%s' % (kind, name) - kind1 = kind - # - class CTypesStructOrUnion(CTypesBaseStructOrUnion): - __slots__ = ['_blob'] - _ctype = struct_or_union - _reftypename = '%s &' % (name,) - _kind = kind = kind1 - # - CTypesStructOrUnion._fix_class() - return CTypesStructOrUnion - - def new_struct_type(self, name): - return self._new_struct_or_union('struct', name, ctypes.Structure) - - def new_union_type(self, name): - return self._new_struct_or_union('union', name, ctypes.Union) - - def complete_struct_or_union(self, CTypesStructOrUnion, fields, tp, - totalsize=-1, totalalignment=-1, sflags=0, - pack=0): - if totalsize >= 0 or totalalignment >= 0: - raise NotImplementedError("the ctypes backend of CFFI does not support " - "structures completed by verify(); please " - "compile and install the _cffi_backend module.") - struct_or_union = CTypesStructOrUnion._ctype - fnames = [fname for (fname, BField, bitsize) in fields] - btypes = [BField for (fname, BField, bitsize) in fields] - bitfields = [bitsize for (fname, BField, bitsize) in fields] - # - bfield_types = {} - cfields = [] - for (fname, BField, bitsize) in fields: - if bitsize < 0: - cfields.append((fname, BField._ctype)) - bfield_types[fname] = BField - else: - cfields.append((fname, BField._ctype, bitsize)) - bfield_types[fname] = Ellipsis - if sflags & 8: - struct_or_union._pack_ = 1 - elif pack: - struct_or_union._pack_ = pack - struct_or_union._fields_ = cfields - CTypesStructOrUnion._bfield_types = bfield_types - # - @staticmethod - def _create_ctype_obj(init): - result = struct_or_union() - if init is not None: - initialize(result, init) - return result - CTypesStructOrUnion._create_ctype_obj = _create_ctype_obj - # - def initialize(blob, init): - if is_union: - if len(init) > 1: - raise ValueError("union initializer: %d items given, but " - "only one supported (use a dict if needed)" - % (len(init),)) - if not isinstance(init, dict): - if isinstance(init, (bytes, unicode)): - raise TypeError("union initializer: got a str") - init = tuple(init) - if len(init) > len(fnames): - raise ValueError("too many values for %s initializer" % - CTypesStructOrUnion._get_c_name()) - init = dict(zip(fnames, init)) - addr = ctypes.addressof(blob) - for fname, value in init.items(): - BField, bitsize = name2fieldtype[fname] - assert bitsize < 0, \ - "not implemented: initializer with bit fields" - offset = CTypesStructOrUnion._offsetof(fname) - PTR = ctypes.POINTER(BField._ctype) - p = ctypes.cast(addr + offset, PTR) - BField._initialize(p.contents, value) - is_union = CTypesStructOrUnion._kind == 'union' - name2fieldtype = dict(zip(fnames, zip(btypes, bitfields))) - # - for fname, BField, bitsize in fields: - if fname == '': - raise NotImplementedError("nested anonymous structs/unions") - if hasattr(CTypesStructOrUnion, fname): - raise ValueError("the field name %r conflicts in " - "the ctypes backend" % fname) - if bitsize < 0: - def getter(self, fname=fname, BField=BField, - offset=CTypesStructOrUnion._offsetof(fname), - PTR=ctypes.POINTER(BField._ctype)): - addr = ctypes.addressof(self._blob) - p = ctypes.cast(addr + offset, PTR) - return BField._from_ctypes(p.contents) - def setter(self, value, fname=fname, BField=BField): - setattr(self._blob, fname, BField._to_ctypes(value)) - # - if issubclass(BField, CTypesGenericArray): - setter = None - if BField._declared_length == 0: - def getter(self, fname=fname, BFieldPtr=BField._CTPtr, - offset=CTypesStructOrUnion._offsetof(fname), - PTR=ctypes.POINTER(BField._ctype)): - addr = ctypes.addressof(self._blob) - p = ctypes.cast(addr + offset, PTR) - return BFieldPtr._from_ctypes(p) - # - else: - def getter(self, fname=fname, BField=BField): - return BField._from_ctypes(getattr(self._blob, fname)) - def setter(self, value, fname=fname, BField=BField): - # xxx obscure workaround - value = BField._to_ctypes(value) - oldvalue = getattr(self._blob, fname) - setattr(self._blob, fname, value) - if value != getattr(self._blob, fname): - setattr(self._blob, fname, oldvalue) - raise OverflowError("value too large for bitfield") - setattr(CTypesStructOrUnion, fname, property(getter, setter)) - # - CTypesPtr = self.ffi._get_cached_btype(model.PointerType(tp)) - for fname in fnames: - if hasattr(CTypesPtr, fname): - raise ValueError("the field name %r conflicts in " - "the ctypes backend" % fname) - def getter(self, fname=fname): - return getattr(self[0], fname) - def setter(self, value, fname=fname): - setattr(self[0], fname, value) - setattr(CTypesPtr, fname, property(getter, setter)) - - def new_function_type(self, BArgs, BResult, has_varargs): - nameargs = [BArg._get_c_name() for BArg in BArgs] - if has_varargs: - nameargs.append('...') - nameargs = ', '.join(nameargs) - # - class CTypesFunctionPtr(CTypesGenericPtr): - __slots__ = ['_own_callback', '_name'] - _ctype = ctypes.CFUNCTYPE(getattr(BResult, '_ctype', None), - *[BArg._ctype for BArg in BArgs], - use_errno=True) - _reftypename = BResult._get_c_name('(* &)(%s)' % (nameargs,)) - - def __init__(self, init, error=None): - # create a callback to the Python callable init() - import traceback - assert not has_varargs, "varargs not supported for callbacks" - if getattr(BResult, '_ctype', None) is not None: - error = BResult._from_ctypes( - BResult._create_ctype_obj(error)) - else: - error = None - def callback(*args): - args2 = [] - for arg, BArg in zip(args, BArgs): - args2.append(BArg._from_ctypes(arg)) - try: - res2 = init(*args2) - res2 = BResult._to_ctypes(res2) - except: - traceback.print_exc() - res2 = error - if issubclass(BResult, CTypesGenericPtr): - if res2: - res2 = ctypes.cast(res2, ctypes.c_void_p).value - # .value: http://bugs.python.org/issue1574593 - else: - res2 = None - #print repr(res2) - return res2 - if issubclass(BResult, CTypesGenericPtr): - # The only pointers callbacks can return are void*s: - # http://bugs.python.org/issue5710 - callback_ctype = ctypes.CFUNCTYPE( - ctypes.c_void_p, - *[BArg._ctype for BArg in BArgs], - use_errno=True) - else: - callback_ctype = CTypesFunctionPtr._ctype - self._as_ctype_ptr = callback_ctype(callback) - self._address = ctypes.cast(self._as_ctype_ptr, - ctypes.c_void_p).value - self._own_callback = init - - @staticmethod - def _initialize(ctypes_ptr, value): - if value: - raise NotImplementedError("ctypes backend: not supported: " - "initializers for function pointers") - - def __repr__(self): - c_name = getattr(self, '_name', None) - if c_name: - i = self._reftypename.index('(* &)') - if self._reftypename[i-1] not in ' )*': - c_name = ' ' + c_name - c_name = self._reftypename.replace('(* &)', c_name) - return CTypesData.__repr__(self, c_name) - - def _get_own_repr(self): - if getattr(self, '_own_callback', None) is not None: - return 'calling %r' % (self._own_callback,) - return super(CTypesFunctionPtr, self)._get_own_repr() - - def __call__(self, *args): - if has_varargs: - assert len(args) >= len(BArgs) - extraargs = args[len(BArgs):] - args = args[:len(BArgs)] - else: - assert len(args) == len(BArgs) - ctypes_args = [] - for arg, BArg in zip(args, BArgs): - ctypes_args.append(BArg._arg_to_ctypes(arg)) - if has_varargs: - for i, arg in enumerate(extraargs): - if arg is None: - ctypes_args.append(ctypes.c_void_p(0)) # NULL - continue - if not isinstance(arg, CTypesData): - raise TypeError( - "argument %d passed in the variadic part " - "needs to be a cdata object (got %s)" % - (1 + len(BArgs) + i, type(arg).__name__)) - ctypes_args.append(arg._arg_to_ctypes(arg)) - result = self._as_ctype_ptr(*ctypes_args) - return BResult._from_ctypes(result) - # - CTypesFunctionPtr._fix_class() - return CTypesFunctionPtr - - def new_enum_type(self, name, enumerators, enumvalues, CTypesInt): - assert isinstance(name, str) - reverse_mapping = dict(zip(reversed(enumvalues), - reversed(enumerators))) - # - class CTypesEnum(CTypesInt): - __slots__ = [] - _reftypename = '%s &' % name - - def _get_own_repr(self): - value = self._value - try: - return '%d: %s' % (value, reverse_mapping[value]) - except KeyError: - return str(value) - - def _to_string(self, maxlen): - value = self._value - try: - return reverse_mapping[value] - except KeyError: - return str(value) - # - CTypesEnum._fix_class() - return CTypesEnum - - def get_errno(self): - return ctypes.get_errno() - - def set_errno(self, value): - ctypes.set_errno(value) - - def string(self, b, maxlen=-1): - return b._to_string(maxlen) - - def buffer(self, bptr, size=-1): - raise NotImplementedError("buffer() with ctypes backend") - - def sizeof(self, cdata_or_BType): - if isinstance(cdata_or_BType, CTypesData): - return cdata_or_BType._get_size_of_instance() - else: - assert issubclass(cdata_or_BType, CTypesData) - return cdata_or_BType._get_size() - - def alignof(self, BType): - assert issubclass(BType, CTypesData) - return BType._alignment() - - def newp(self, BType, source): - if not issubclass(BType, CTypesData): - raise TypeError - return BType._newp(source) - - def cast(self, BType, source): - return BType._cast_from(source) - - def callback(self, BType, source, error, onerror): - assert onerror is None # XXX not implemented - return BType(source, error) - - _weakref_cache_ref = None - - def gcp(self, cdata, destructor, size=0): - if self._weakref_cache_ref is None: - import weakref - class MyRef(weakref.ref): - def __eq__(self, other): - myref = self() - return self is other or ( - myref is not None and myref is other()) - def __ne__(self, other): - return not (self == other) - def __hash__(self): - try: - return self._hash - except AttributeError: - self._hash = hash(self()) - return self._hash - self._weakref_cache_ref = {}, MyRef - weak_cache, MyRef = self._weakref_cache_ref - - if destructor is None: - try: - del weak_cache[MyRef(cdata)] - except KeyError: - raise TypeError("Can remove destructor only on a object " - "previously returned by ffi.gc()") - return None - - def remove(k): - cdata, destructor = weak_cache.pop(k, (None, None)) - if destructor is not None: - destructor(cdata) - - new_cdata = self.cast(self.typeof(cdata), cdata) - assert new_cdata is not cdata - weak_cache[MyRef(new_cdata, remove)] = (cdata, destructor) - return new_cdata - - typeof = type - - def getcname(self, BType, replace_with): - return BType._get_c_name(replace_with) - - def typeoffsetof(self, BType, fieldname, num=0): - if isinstance(fieldname, str): - if num == 0 and issubclass(BType, CTypesGenericPtr): - BType = BType._BItem - if not issubclass(BType, CTypesBaseStructOrUnion): - raise TypeError("expected a struct or union ctype") - BField = BType._bfield_types[fieldname] - if BField is Ellipsis: - raise TypeError("not supported for bitfields") - return (BField, BType._offsetof(fieldname)) - elif isinstance(fieldname, (int, long)): - if issubclass(BType, CTypesGenericArray): - BType = BType._CTPtr - if not issubclass(BType, CTypesGenericPtr): - raise TypeError("expected an array or ptr ctype") - BItem = BType._BItem - offset = BItem._get_size() * fieldname - if offset > sys.maxsize: - raise OverflowError - return (BItem, offset) - else: - raise TypeError(type(fieldname)) - - def rawaddressof(self, BTypePtr, cdata, offset=None): - if isinstance(cdata, CTypesBaseStructOrUnion): - ptr = ctypes.pointer(type(cdata)._to_ctypes(cdata)) - elif isinstance(cdata, CTypesGenericPtr): - if offset is None or not issubclass(type(cdata)._BItem, - CTypesBaseStructOrUnion): - raise TypeError("unexpected cdata type") - ptr = type(cdata)._to_ctypes(cdata) - elif isinstance(cdata, CTypesGenericArray): - ptr = type(cdata)._to_ctypes(cdata) - else: - raise TypeError("expected a ") - if offset: - ptr = ctypes.cast( - ctypes.c_void_p( - ctypes.cast(ptr, ctypes.c_void_p).value + offset), - type(ptr)) - return BTypePtr._from_ctypes(ptr) - - -class CTypesLibrary(object): - - def __init__(self, backend, cdll): - self.backend = backend - self.cdll = cdll - - def load_function(self, BType, name): - c_func = getattr(self.cdll, name) - funcobj = BType._from_ctypes(c_func) - funcobj._name = name - return funcobj - - def read_variable(self, BType, name): - try: - ctypes_obj = BType._ctype.in_dll(self.cdll, name) - except AttributeError as e: - raise NotImplementedError(e) - return BType._from_ctypes(ctypes_obj) - - def write_variable(self, BType, name, value): - new_ctypes_obj = BType._to_ctypes(value) - ctypes_obj = BType._ctype.in_dll(self.cdll, name) - ctypes.memmove(ctypes.addressof(ctypes_obj), - ctypes.addressof(new_ctypes_obj), - ctypes.sizeof(BType._ctype)) diff --git a/notification-service/venv/Lib/site-packages/cffi/cffi_opcode.py b/notification-service/venv/Lib/site-packages/cffi/cffi_opcode.py deleted file mode 100644 index 6421df6..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/cffi_opcode.py +++ /dev/null @@ -1,187 +0,0 @@ -from .error import VerificationError - -class CffiOp(object): - def __init__(self, op, arg): - self.op = op - self.arg = arg - - def as_c_expr(self): - if self.op is None: - assert isinstance(self.arg, str) - return '(_cffi_opcode_t)(%s)' % (self.arg,) - classname = CLASS_NAME[self.op] - return '_CFFI_OP(_CFFI_OP_%s, %s)' % (classname, self.arg) - - def as_python_bytes(self): - if self.op is None and self.arg.isdigit(): - value = int(self.arg) # non-negative: '-' not in self.arg - if value >= 2**31: - raise OverflowError("cannot emit %r: limited to 2**31-1" - % (self.arg,)) - return format_four_bytes(value) - if isinstance(self.arg, str): - raise VerificationError("cannot emit to Python: %r" % (self.arg,)) - return format_four_bytes((self.arg << 8) | self.op) - - def __str__(self): - classname = CLASS_NAME.get(self.op, self.op) - return '(%s %s)' % (classname, self.arg) - -def format_four_bytes(num): - return '\\x%02X\\x%02X\\x%02X\\x%02X' % ( - (num >> 24) & 0xFF, - (num >> 16) & 0xFF, - (num >> 8) & 0xFF, - (num ) & 0xFF) - -OP_PRIMITIVE = 1 -OP_POINTER = 3 -OP_ARRAY = 5 -OP_OPEN_ARRAY = 7 -OP_STRUCT_UNION = 9 -OP_ENUM = 11 -OP_FUNCTION = 13 -OP_FUNCTION_END = 15 -OP_NOOP = 17 -OP_BITFIELD = 19 -OP_TYPENAME = 21 -OP_CPYTHON_BLTN_V = 23 # varargs -OP_CPYTHON_BLTN_N = 25 # noargs -OP_CPYTHON_BLTN_O = 27 # O (i.e. a single arg) -OP_CONSTANT = 29 -OP_CONSTANT_INT = 31 -OP_GLOBAL_VAR = 33 -OP_DLOPEN_FUNC = 35 -OP_DLOPEN_CONST = 37 -OP_GLOBAL_VAR_F = 39 -OP_EXTERN_PYTHON = 41 - -PRIM_VOID = 0 -PRIM_BOOL = 1 -PRIM_CHAR = 2 -PRIM_SCHAR = 3 -PRIM_UCHAR = 4 -PRIM_SHORT = 5 -PRIM_USHORT = 6 -PRIM_INT = 7 -PRIM_UINT = 8 -PRIM_LONG = 9 -PRIM_ULONG = 10 -PRIM_LONGLONG = 11 -PRIM_ULONGLONG = 12 -PRIM_FLOAT = 13 -PRIM_DOUBLE = 14 -PRIM_LONGDOUBLE = 15 - -PRIM_WCHAR = 16 -PRIM_INT8 = 17 -PRIM_UINT8 = 18 -PRIM_INT16 = 19 -PRIM_UINT16 = 20 -PRIM_INT32 = 21 -PRIM_UINT32 = 22 -PRIM_INT64 = 23 -PRIM_UINT64 = 24 -PRIM_INTPTR = 25 -PRIM_UINTPTR = 26 -PRIM_PTRDIFF = 27 -PRIM_SIZE = 28 -PRIM_SSIZE = 29 -PRIM_INT_LEAST8 = 30 -PRIM_UINT_LEAST8 = 31 -PRIM_INT_LEAST16 = 32 -PRIM_UINT_LEAST16 = 33 -PRIM_INT_LEAST32 = 34 -PRIM_UINT_LEAST32 = 35 -PRIM_INT_LEAST64 = 36 -PRIM_UINT_LEAST64 = 37 -PRIM_INT_FAST8 = 38 -PRIM_UINT_FAST8 = 39 -PRIM_INT_FAST16 = 40 -PRIM_UINT_FAST16 = 41 -PRIM_INT_FAST32 = 42 -PRIM_UINT_FAST32 = 43 -PRIM_INT_FAST64 = 44 -PRIM_UINT_FAST64 = 45 -PRIM_INTMAX = 46 -PRIM_UINTMAX = 47 -PRIM_FLOATCOMPLEX = 48 -PRIM_DOUBLECOMPLEX = 49 -PRIM_CHAR16 = 50 -PRIM_CHAR32 = 51 - -_NUM_PRIM = 52 -_UNKNOWN_PRIM = -1 -_UNKNOWN_FLOAT_PRIM = -2 -_UNKNOWN_LONG_DOUBLE = -3 - -_IO_FILE_STRUCT = -1 - -PRIMITIVE_TO_INDEX = { - 'char': PRIM_CHAR, - 'short': PRIM_SHORT, - 'int': PRIM_INT, - 'long': PRIM_LONG, - 'long long': PRIM_LONGLONG, - 'signed char': PRIM_SCHAR, - 'unsigned char': PRIM_UCHAR, - 'unsigned short': PRIM_USHORT, - 'unsigned int': PRIM_UINT, - 'unsigned long': PRIM_ULONG, - 'unsigned long long': PRIM_ULONGLONG, - 'float': PRIM_FLOAT, - 'double': PRIM_DOUBLE, - 'long double': PRIM_LONGDOUBLE, - '_cffi_float_complex_t': PRIM_FLOATCOMPLEX, - '_cffi_double_complex_t': PRIM_DOUBLECOMPLEX, - '_Bool': PRIM_BOOL, - 'wchar_t': PRIM_WCHAR, - 'char16_t': PRIM_CHAR16, - 'char32_t': PRIM_CHAR32, - 'int8_t': PRIM_INT8, - 'uint8_t': PRIM_UINT8, - 'int16_t': PRIM_INT16, - 'uint16_t': PRIM_UINT16, - 'int32_t': PRIM_INT32, - 'uint32_t': PRIM_UINT32, - 'int64_t': PRIM_INT64, - 'uint64_t': PRIM_UINT64, - 'intptr_t': PRIM_INTPTR, - 'uintptr_t': PRIM_UINTPTR, - 'ptrdiff_t': PRIM_PTRDIFF, - 'size_t': PRIM_SIZE, - 'ssize_t': PRIM_SSIZE, - 'int_least8_t': PRIM_INT_LEAST8, - 'uint_least8_t': PRIM_UINT_LEAST8, - 'int_least16_t': PRIM_INT_LEAST16, - 'uint_least16_t': PRIM_UINT_LEAST16, - 'int_least32_t': PRIM_INT_LEAST32, - 'uint_least32_t': PRIM_UINT_LEAST32, - 'int_least64_t': PRIM_INT_LEAST64, - 'uint_least64_t': PRIM_UINT_LEAST64, - 'int_fast8_t': PRIM_INT_FAST8, - 'uint_fast8_t': PRIM_UINT_FAST8, - 'int_fast16_t': PRIM_INT_FAST16, - 'uint_fast16_t': PRIM_UINT_FAST16, - 'int_fast32_t': PRIM_INT_FAST32, - 'uint_fast32_t': PRIM_UINT_FAST32, - 'int_fast64_t': PRIM_INT_FAST64, - 'uint_fast64_t': PRIM_UINT_FAST64, - 'intmax_t': PRIM_INTMAX, - 'uintmax_t': PRIM_UINTMAX, - } - -F_UNION = 0x01 -F_CHECK_FIELDS = 0x02 -F_PACKED = 0x04 -F_EXTERNAL = 0x08 -F_OPAQUE = 0x10 - -G_FLAGS = dict([('_CFFI_' + _key, globals()[_key]) - for _key in ['F_UNION', 'F_CHECK_FIELDS', 'F_PACKED', - 'F_EXTERNAL', 'F_OPAQUE']]) - -CLASS_NAME = {} -for _name, _value in list(globals().items()): - if _name.startswith('OP_') and isinstance(_value, int): - CLASS_NAME[_value] = _name[3:] diff --git a/notification-service/venv/Lib/site-packages/cffi/commontypes.py b/notification-service/venv/Lib/site-packages/cffi/commontypes.py deleted file mode 100644 index d4dae35..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/commontypes.py +++ /dev/null @@ -1,82 +0,0 @@ -import sys -from . import model -from .error import FFIError - - -COMMON_TYPES = {} - -try: - # fetch "bool" and all simple Windows types - from _cffi_backend import _get_common_types - _get_common_types(COMMON_TYPES) -except ImportError: - pass - -COMMON_TYPES['FILE'] = model.unknown_type('FILE', '_IO_FILE') -COMMON_TYPES['bool'] = '_Bool' # in case we got ImportError above -COMMON_TYPES['float _Complex'] = '_cffi_float_complex_t' -COMMON_TYPES['double _Complex'] = '_cffi_double_complex_t' - -for _type in model.PrimitiveType.ALL_PRIMITIVE_TYPES: - if _type.endswith('_t'): - COMMON_TYPES[_type] = _type -del _type - -_CACHE = {} - -def resolve_common_type(parser, commontype): - try: - return _CACHE[commontype] - except KeyError: - cdecl = COMMON_TYPES.get(commontype, commontype) - if not isinstance(cdecl, str): - result, quals = cdecl, 0 # cdecl is already a BaseType - elif cdecl in model.PrimitiveType.ALL_PRIMITIVE_TYPES: - result, quals = model.PrimitiveType(cdecl), 0 - elif cdecl == 'set-unicode-needed': - raise FFIError("The Windows type %r is only available after " - "you call ffi.set_unicode()" % (commontype,)) - else: - if commontype == cdecl: - raise FFIError( - "Unsupported type: %r. Please look at " - "http://cffi.readthedocs.io/en/latest/cdef.html#ffi-cdef-limitations " - "and file an issue if you think this type should really " - "be supported." % (commontype,)) - result, quals = parser.parse_type_and_quals(cdecl) # recursive - - assert isinstance(result, model.BaseTypeByIdentity) - _CACHE[commontype] = result, quals - return result, quals - - -# ____________________________________________________________ -# extra types for Windows (most of them are in commontypes.c) - - -def win_common_types(): - return { - "UNICODE_STRING": model.StructType( - "_UNICODE_STRING", - ["Length", - "MaximumLength", - "Buffer"], - [model.PrimitiveType("unsigned short"), - model.PrimitiveType("unsigned short"), - model.PointerType(model.PrimitiveType("wchar_t"))], - [-1, -1, -1]), - "PUNICODE_STRING": "UNICODE_STRING *", - "PCUNICODE_STRING": "const UNICODE_STRING *", - - "TBYTE": "set-unicode-needed", - "TCHAR": "set-unicode-needed", - "LPCTSTR": "set-unicode-needed", - "PCTSTR": "set-unicode-needed", - "LPTSTR": "set-unicode-needed", - "PTSTR": "set-unicode-needed", - "PTBYTE": "set-unicode-needed", - "PTCHAR": "set-unicode-needed", - } - -if sys.platform == 'win32': - COMMON_TYPES.update(win_common_types()) diff --git a/notification-service/venv/Lib/site-packages/cffi/cparser.py b/notification-service/venv/Lib/site-packages/cffi/cparser.py deleted file mode 100644 index dd590d8..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/cparser.py +++ /dev/null @@ -1,1015 +0,0 @@ -from . import model -from .commontypes import COMMON_TYPES, resolve_common_type -from .error import FFIError, CDefError -try: - from . import _pycparser as pycparser -except ImportError: - import pycparser -import weakref, re, sys - -try: - if sys.version_info < (3,): - import thread as _thread - else: - import _thread - lock = _thread.allocate_lock() -except ImportError: - lock = None - -def _workaround_for_static_import_finders(): - # Issue #392: packaging tools like cx_Freeze can not find these - # because pycparser uses exec dynamic import. This is an obscure - # workaround. This function is never called. - import pycparser.yacctab - import pycparser.lextab - -CDEF_SOURCE_STRING = "" -_r_comment = re.compile(r"/\*.*?\*/|//([^\n\\]|\\.)*?$", - re.DOTALL | re.MULTILINE) -_r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)" - r"\b((?:[^\n\\]|\\.)*?)$", - re.DOTALL | re.MULTILINE) -_r_line_directive = re.compile(r"^[ \t]*#[ \t]*(?:line|\d+)\b.*$", re.MULTILINE) -_r_partial_enum = re.compile(r"=\s*\.\.\.\s*[,}]|\.\.\.\s*\}") -_r_enum_dotdotdot = re.compile(r"__dotdotdot\d+__$") -_r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]") -_r_words = re.compile(r"\w+|\S") -_parser_cache = None -_r_int_literal = re.compile(r"-?0?x?[0-9a-f]+[lu]*$", re.IGNORECASE) -_r_stdcall1 = re.compile(r"\b(__stdcall|WINAPI)\b") -_r_stdcall2 = re.compile(r"[(]\s*(__stdcall|WINAPI)\b") -_r_cdecl = re.compile(r"\b__cdecl\b") -_r_extern_python = re.compile(r'\bextern\s*"' - r'(Python|Python\s*\+\s*C|C\s*\+\s*Python)"\s*.') -_r_star_const_space = re.compile( # matches "* const " - r"[*]\s*((const|volatile|restrict)\b\s*)+") -_r_int_dotdotdot = re.compile(r"(\b(int|long|short|signed|unsigned|char)\s*)+" - r"\.\.\.") -_r_float_dotdotdot = re.compile(r"\b(double|float)\s*\.\.\.") - -def _get_parser(): - global _parser_cache - if _parser_cache is None: - _parser_cache = pycparser.CParser() - return _parser_cache - -def _workaround_for_old_pycparser(csource): - # Workaround for a pycparser issue (fixed between pycparser 2.10 and - # 2.14): "char*const***" gives us a wrong syntax tree, the same as - # for "char***(*const)". This means we can't tell the difference - # afterwards. But "char(*const(***))" gives us the right syntax - # tree. The issue only occurs if there are several stars in - # sequence with no parenthesis in between, just possibly qualifiers. - # Attempt to fix it by adding some parentheses in the source: each - # time we see "* const" or "* const *", we add an opening - # parenthesis before each star---the hard part is figuring out where - # to close them. - parts = [] - while True: - match = _r_star_const_space.search(csource) - if not match: - break - #print repr(''.join(parts)+csource), '=>', - parts.append(csource[:match.start()]) - parts.append('('); closing = ')' - parts.append(match.group()) # e.g. "* const " - endpos = match.end() - if csource.startswith('*', endpos): - parts.append('('); closing += ')' - level = 0 - i = endpos - while i < len(csource): - c = csource[i] - if c == '(': - level += 1 - elif c == ')': - if level == 0: - break - level -= 1 - elif c in ',;=': - if level == 0: - break - i += 1 - csource = csource[endpos:i] + closing + csource[i:] - #print repr(''.join(parts)+csource) - parts.append(csource) - return ''.join(parts) - -def _preprocess_extern_python(csource): - # input: `extern "Python" int foo(int);` or - # `extern "Python" { int foo(int); }` - # output: - # void __cffi_extern_python_start; - # int foo(int); - # void __cffi_extern_python_stop; - # - # input: `extern "Python+C" int foo(int);` - # output: - # void __cffi_extern_python_plus_c_start; - # int foo(int); - # void __cffi_extern_python_stop; - parts = [] - while True: - match = _r_extern_python.search(csource) - if not match: - break - endpos = match.end() - 1 - #print - #print ''.join(parts)+csource - #print '=>' - parts.append(csource[:match.start()]) - if 'C' in match.group(1): - parts.append('void __cffi_extern_python_plus_c_start; ') - else: - parts.append('void __cffi_extern_python_start; ') - if csource[endpos] == '{': - # grouping variant - closing = csource.find('}', endpos) - if closing < 0: - raise CDefError("'extern \"Python\" {': no '}' found") - if csource.find('{', endpos + 1, closing) >= 0: - raise NotImplementedError("cannot use { } inside a block " - "'extern \"Python\" { ... }'") - parts.append(csource[endpos+1:closing]) - csource = csource[closing+1:] - else: - # non-grouping variant - semicolon = csource.find(';', endpos) - if semicolon < 0: - raise CDefError("'extern \"Python\": no ';' found") - parts.append(csource[endpos:semicolon+1]) - csource = csource[semicolon+1:] - parts.append(' void __cffi_extern_python_stop;') - #print ''.join(parts)+csource - #print - parts.append(csource) - return ''.join(parts) - -def _warn_for_string_literal(csource): - if '"' not in csource: - return - for line in csource.splitlines(): - if '"' in line and not line.lstrip().startswith('#'): - import warnings - warnings.warn("String literal found in cdef() or type source. " - "String literals are ignored here, but you should " - "remove them anyway because some character sequences " - "confuse pre-parsing.") - break - -def _warn_for_non_extern_non_static_global_variable(decl): - if not decl.storage: - import warnings - warnings.warn("Global variable '%s' in cdef(): for consistency " - "with C it should have a storage class specifier " - "(usually 'extern')" % (decl.name,)) - -def _remove_line_directives(csource): - # _r_line_directive matches whole lines, without the final \n, if they - # start with '#line' with some spacing allowed, or '#NUMBER'. This - # function stores them away and replaces them with exactly the string - # '#line@N', where N is the index in the list 'line_directives'. - line_directives = [] - def replace(m): - i = len(line_directives) - line_directives.append(m.group()) - return '#line@%d' % i - csource = _r_line_directive.sub(replace, csource) - return csource, line_directives - -def _put_back_line_directives(csource, line_directives): - def replace(m): - s = m.group() - if not s.startswith('#line@'): - raise AssertionError("unexpected #line directive " - "(should have been processed and removed") - return line_directives[int(s[6:])] - return _r_line_directive.sub(replace, csource) - -def _preprocess(csource): - # First, remove the lines of the form '#line N "filename"' because - # the "filename" part could confuse the rest - csource, line_directives = _remove_line_directives(csource) - # Remove comments. NOTE: this only work because the cdef() section - # should not contain any string literals (except in line directives)! - def replace_keeping_newlines(m): - return ' ' + m.group().count('\n') * '\n' - csource = _r_comment.sub(replace_keeping_newlines, csource) - # Remove the "#define FOO x" lines - macros = {} - for match in _r_define.finditer(csource): - macroname, macrovalue = match.groups() - macrovalue = macrovalue.replace('\\\n', '').strip() - macros[macroname] = macrovalue - csource = _r_define.sub('', csource) - # - if pycparser.__version__ < '2.14': - csource = _workaround_for_old_pycparser(csource) - # - # BIG HACK: replace WINAPI or __stdcall with "volatile const". - # It doesn't make sense for the return type of a function to be - # "volatile volatile const", so we abuse it to detect __stdcall... - # Hack number 2 is that "int(volatile *fptr)();" is not valid C - # syntax, so we place the "volatile" before the opening parenthesis. - csource = _r_stdcall2.sub(' volatile volatile const(', csource) - csource = _r_stdcall1.sub(' volatile volatile const ', csource) - csource = _r_cdecl.sub(' ', csource) - # - # Replace `extern "Python"` with start/end markers - csource = _preprocess_extern_python(csource) - # - # Now there should not be any string literal left; warn if we get one - _warn_for_string_literal(csource) - # - # Replace "[...]" with "[__dotdotdotarray__]" - csource = _r_partial_array.sub('[__dotdotdotarray__]', csource) - # - # Replace "...}" with "__dotdotdotNUM__}". This construction should - # occur only at the end of enums; at the end of structs we have "...;}" - # and at the end of vararg functions "...);". Also replace "=...[,}]" - # with ",__dotdotdotNUM__[,}]": this occurs in the enums too, when - # giving an unknown value. - matches = list(_r_partial_enum.finditer(csource)) - for number, match in enumerate(reversed(matches)): - p = match.start() - if csource[p] == '=': - p2 = csource.find('...', p, match.end()) - assert p2 > p - csource = '%s,__dotdotdot%d__ %s' % (csource[:p], number, - csource[p2+3:]) - else: - assert csource[p:p+3] == '...' - csource = '%s __dotdotdot%d__ %s' % (csource[:p], number, - csource[p+3:]) - # Replace "int ..." or "unsigned long int..." with "__dotdotdotint__" - csource = _r_int_dotdotdot.sub(' __dotdotdotint__ ', csource) - # Replace "float ..." or "double..." with "__dotdotdotfloat__" - csource = _r_float_dotdotdot.sub(' __dotdotdotfloat__ ', csource) - # Replace all remaining "..." with the same name, "__dotdotdot__", - # which is declared with a typedef for the purpose of C parsing. - csource = csource.replace('...', ' __dotdotdot__ ') - # Finally, put back the line directives - csource = _put_back_line_directives(csource, line_directives) - return csource, macros - -def _common_type_names(csource): - # Look in the source for what looks like usages of types from the - # list of common types. A "usage" is approximated here as the - # appearance of the word, minus a "definition" of the type, which - # is the last word in a "typedef" statement. Approximative only - # but should be fine for all the common types. - look_for_words = set(COMMON_TYPES) - look_for_words.add(';') - look_for_words.add(',') - look_for_words.add('(') - look_for_words.add(')') - look_for_words.add('typedef') - words_used = set() - is_typedef = False - paren = 0 - previous_word = '' - for word in _r_words.findall(csource): - if word in look_for_words: - if word == ';': - if is_typedef: - words_used.discard(previous_word) - look_for_words.discard(previous_word) - is_typedef = False - elif word == 'typedef': - is_typedef = True - paren = 0 - elif word == '(': - paren += 1 - elif word == ')': - paren -= 1 - elif word == ',': - if is_typedef and paren == 0: - words_used.discard(previous_word) - look_for_words.discard(previous_word) - else: # word in COMMON_TYPES - words_used.add(word) - previous_word = word - return words_used - - -class Parser(object): - - def __init__(self): - self._declarations = {} - self._included_declarations = set() - self._anonymous_counter = 0 - self._structnode2type = weakref.WeakKeyDictionary() - self._options = {} - self._int_constants = {} - self._recomplete = [] - self._uses_new_feature = None - - def _parse(self, csource): - csource, macros = _preprocess(csource) - # XXX: for more efficiency we would need to poke into the - # internals of CParser... the following registers the - # typedefs, because their presence or absence influences the - # parsing itself (but what they are typedef'ed to plays no role) - ctn = _common_type_names(csource) - typenames = [] - for name in sorted(self._declarations): - if name.startswith('typedef '): - name = name[8:] - typenames.append(name) - ctn.discard(name) - typenames += sorted(ctn) - # - csourcelines = [] - csourcelines.append('# 1 ""') - for typename in typenames: - csourcelines.append('typedef int %s;' % typename) - csourcelines.append('typedef int __dotdotdotint__, __dotdotdotfloat__,' - ' __dotdotdot__;') - # this forces pycparser to consider the following in the file - # called from line 1 - csourcelines.append('# 1 "%s"' % (CDEF_SOURCE_STRING,)) - csourcelines.append(csource) - csourcelines.append('') # see test_missing_newline_bug - fullcsource = '\n'.join(csourcelines) - if lock is not None: - lock.acquire() # pycparser is not thread-safe... - try: - ast = _get_parser().parse(fullcsource) - except pycparser.c_parser.ParseError as e: - self.convert_pycparser_error(e, csource) - finally: - if lock is not None: - lock.release() - # csource will be used to find buggy source text - return ast, macros, csource - - def _convert_pycparser_error(self, e, csource): - # xxx look for ":NUM:" at the start of str(e) - # and interpret that as a line number. This will not work if - # the user gives explicit ``# NUM "FILE"`` directives. - line = None - msg = str(e) - match = re.match(r"%s:(\d+):" % (CDEF_SOURCE_STRING,), msg) - if match: - linenum = int(match.group(1), 10) - csourcelines = csource.splitlines() - if 1 <= linenum <= len(csourcelines): - line = csourcelines[linenum-1] - return line - - def convert_pycparser_error(self, e, csource): - line = self._convert_pycparser_error(e, csource) - - msg = str(e) - if line: - msg = 'cannot parse "%s"\n%s' % (line.strip(), msg) - else: - msg = 'parse error\n%s' % (msg,) - raise CDefError(msg) - - def parse(self, csource, override=False, packed=False, pack=None, - dllexport=False): - if packed: - if packed != True: - raise ValueError("'packed' should be False or True; use " - "'pack' to give another value") - if pack: - raise ValueError("cannot give both 'pack' and 'packed'") - pack = 1 - elif pack: - if pack & (pack - 1): - raise ValueError("'pack' must be a power of two, not %r" % - (pack,)) - else: - pack = 0 - prev_options = self._options - try: - self._options = {'override': override, - 'packed': pack, - 'dllexport': dllexport} - self._internal_parse(csource) - finally: - self._options = prev_options - - def _internal_parse(self, csource): - ast, macros, csource = self._parse(csource) - # add the macros - self._process_macros(macros) - # find the first "__dotdotdot__" and use that as a separator - # between the repeated typedefs and the real csource - iterator = iter(ast.ext) - for decl in iterator: - if decl.name == '__dotdotdot__': - break - else: - assert 0 - current_decl = None - # - try: - self._inside_extern_python = '__cffi_extern_python_stop' - for decl in iterator: - current_decl = decl - if isinstance(decl, pycparser.c_ast.Decl): - self._parse_decl(decl) - elif isinstance(decl, pycparser.c_ast.Typedef): - if not decl.name: - raise CDefError("typedef does not declare any name", - decl) - quals = 0 - if (isinstance(decl.type.type, pycparser.c_ast.IdentifierType) and - decl.type.type.names[-1].startswith('__dotdotdot')): - realtype = self._get_unknown_type(decl) - elif (isinstance(decl.type, pycparser.c_ast.PtrDecl) and - isinstance(decl.type.type, pycparser.c_ast.TypeDecl) and - isinstance(decl.type.type.type, - pycparser.c_ast.IdentifierType) and - decl.type.type.type.names[-1].startswith('__dotdotdot')): - realtype = self._get_unknown_ptr_type(decl) - else: - realtype, quals = self._get_type_and_quals( - decl.type, name=decl.name, partial_length_ok=True, - typedef_example="*(%s *)0" % (decl.name,)) - self._declare('typedef ' + decl.name, realtype, quals=quals) - elif decl.__class__.__name__ == 'Pragma': - # skip pragma, only in pycparser 2.15 - import warnings - warnings.warn( - "#pragma in cdef() are entirely ignored. " - "They should be removed for now, otherwise your " - "code might behave differently in a future version " - "of CFFI if #pragma support gets added. Note that " - "'#pragma pack' needs to be replaced with the " - "'packed' keyword argument to cdef().") - else: - raise CDefError("unexpected <%s>: this construct is valid " - "C but not valid in cdef()" % - decl.__class__.__name__, decl) - except CDefError as e: - if len(e.args) == 1: - e.args = e.args + (current_decl,) - raise - except FFIError as e: - msg = self._convert_pycparser_error(e, csource) - if msg: - e.args = (e.args[0] + "\n *** Err: %s" % msg,) - raise - - def _add_constants(self, key, val): - if key in self._int_constants: - if self._int_constants[key] == val: - return # ignore identical double declarations - raise FFIError( - "multiple declarations of constant: %s" % (key,)) - self._int_constants[key] = val - - def _add_integer_constant(self, name, int_str): - int_str = int_str.lower().rstrip("ul") - neg = int_str.startswith('-') - if neg: - int_str = int_str[1:] - # "010" is not valid oct in py3 - if (int_str.startswith("0") and int_str != '0' - and not int_str.startswith("0x")): - int_str = "0o" + int_str[1:] - pyvalue = int(int_str, 0) - if neg: - pyvalue = -pyvalue - self._add_constants(name, pyvalue) - self._declare('macro ' + name, pyvalue) - - def _process_macros(self, macros): - for key, value in macros.items(): - value = value.strip() - if _r_int_literal.match(value): - self._add_integer_constant(key, value) - elif value == '...': - self._declare('macro ' + key, value) - else: - raise CDefError( - 'only supports one of the following syntax:\n' - ' #define %s ... (literally dot-dot-dot)\n' - ' #define %s NUMBER (with NUMBER an integer' - ' constant, decimal/hex/octal)\n' - 'got:\n' - ' #define %s %s' - % (key, key, key, value)) - - def _declare_function(self, tp, quals, decl): - tp = self._get_type_pointer(tp, quals) - if self._options.get('dllexport'): - tag = 'dllexport_python ' - elif self._inside_extern_python == '__cffi_extern_python_start': - tag = 'extern_python ' - elif self._inside_extern_python == '__cffi_extern_python_plus_c_start': - tag = 'extern_python_plus_c ' - else: - tag = 'function ' - self._declare(tag + decl.name, tp) - - def _parse_decl(self, decl): - node = decl.type - if isinstance(node, pycparser.c_ast.FuncDecl): - tp, quals = self._get_type_and_quals(node, name=decl.name) - assert isinstance(tp, model.RawFunctionType) - self._declare_function(tp, quals, decl) - else: - if isinstance(node, pycparser.c_ast.Struct): - self._get_struct_union_enum_type('struct', node) - elif isinstance(node, pycparser.c_ast.Union): - self._get_struct_union_enum_type('union', node) - elif isinstance(node, pycparser.c_ast.Enum): - self._get_struct_union_enum_type('enum', node) - elif not decl.name: - raise CDefError("construct does not declare any variable", - decl) - # - if decl.name: - tp, quals = self._get_type_and_quals(node, - partial_length_ok=True) - if tp.is_raw_function: - self._declare_function(tp, quals, decl) - elif (tp.is_integer_type() and - hasattr(decl, 'init') and - hasattr(decl.init, 'value') and - _r_int_literal.match(decl.init.value)): - self._add_integer_constant(decl.name, decl.init.value) - elif (tp.is_integer_type() and - isinstance(decl.init, pycparser.c_ast.UnaryOp) and - decl.init.op == '-' and - hasattr(decl.init.expr, 'value') and - _r_int_literal.match(decl.init.expr.value)): - self._add_integer_constant(decl.name, - '-' + decl.init.expr.value) - elif (tp is model.void_type and - decl.name.startswith('__cffi_extern_python_')): - # hack: `extern "Python"` in the C source is replaced - # with "void __cffi_extern_python_start;" and - # "void __cffi_extern_python_stop;" - self._inside_extern_python = decl.name - else: - if self._inside_extern_python !='__cffi_extern_python_stop': - raise CDefError( - "cannot declare constants or " - "variables with 'extern \"Python\"'") - if (quals & model.Q_CONST) and not tp.is_array_type: - self._declare('constant ' + decl.name, tp, quals=quals) - else: - _warn_for_non_extern_non_static_global_variable(decl) - self._declare('variable ' + decl.name, tp, quals=quals) - - def parse_type(self, cdecl): - return self.parse_type_and_quals(cdecl)[0] - - def parse_type_and_quals(self, cdecl): - ast, macros = self._parse('void __dummy(\n%s\n);' % cdecl)[:2] - assert not macros - exprnode = ast.ext[-1].type.args.params[0] - if isinstance(exprnode, pycparser.c_ast.ID): - raise CDefError("unknown identifier '%s'" % (exprnode.name,)) - return self._get_type_and_quals(exprnode.type) - - def _declare(self, name, obj, included=False, quals=0): - if name in self._declarations: - prevobj, prevquals = self._declarations[name] - if prevobj is obj and prevquals == quals: - return - if not self._options.get('override'): - raise FFIError( - "multiple declarations of %s (for interactive usage, " - "try cdef(xx, override=True))" % (name,)) - assert '__dotdotdot__' not in name.split() - self._declarations[name] = (obj, quals) - if included: - self._included_declarations.add(obj) - - def _extract_quals(self, type): - quals = 0 - if isinstance(type, (pycparser.c_ast.TypeDecl, - pycparser.c_ast.PtrDecl)): - if 'const' in type.quals: - quals |= model.Q_CONST - if 'volatile' in type.quals: - quals |= model.Q_VOLATILE - if 'restrict' in type.quals: - quals |= model.Q_RESTRICT - return quals - - def _get_type_pointer(self, type, quals, declname=None): - if isinstance(type, model.RawFunctionType): - return type.as_function_pointer() - if (isinstance(type, model.StructOrUnionOrEnum) and - type.name.startswith('$') and type.name[1:].isdigit() and - type.forcename is None and declname is not None): - return model.NamedPointerType(type, declname, quals) - return model.PointerType(type, quals) - - def _get_type_and_quals(self, typenode, name=None, partial_length_ok=False, - typedef_example=None): - # first, dereference typedefs, if we have it already parsed, we're good - if (isinstance(typenode, pycparser.c_ast.TypeDecl) and - isinstance(typenode.type, pycparser.c_ast.IdentifierType) and - len(typenode.type.names) == 1 and - ('typedef ' + typenode.type.names[0]) in self._declarations): - tp, quals = self._declarations['typedef ' + typenode.type.names[0]] - quals |= self._extract_quals(typenode) - return tp, quals - # - if isinstance(typenode, pycparser.c_ast.ArrayDecl): - # array type - if typenode.dim is None: - length = None - else: - length = self._parse_constant( - typenode.dim, partial_length_ok=partial_length_ok) - # a hack: in 'typedef int foo_t[...][...];', don't use '...' as - # the length but use directly the C expression that would be - # generated by recompiler.py. This lets the typedef be used in - # many more places within recompiler.py - if typedef_example is not None: - if length == '...': - length = '_cffi_array_len(%s)' % (typedef_example,) - typedef_example = "*" + typedef_example - # - tp, quals = self._get_type_and_quals(typenode.type, - partial_length_ok=partial_length_ok, - typedef_example=typedef_example) - return model.ArrayType(tp, length), quals - # - if isinstance(typenode, pycparser.c_ast.PtrDecl): - # pointer type - itemtype, itemquals = self._get_type_and_quals(typenode.type) - tp = self._get_type_pointer(itemtype, itemquals, declname=name) - quals = self._extract_quals(typenode) - return tp, quals - # - if isinstance(typenode, pycparser.c_ast.TypeDecl): - quals = self._extract_quals(typenode) - type = typenode.type - if isinstance(type, pycparser.c_ast.IdentifierType): - # assume a primitive type. get it from .names, but reduce - # synonyms to a single chosen combination - names = list(type.names) - if names != ['signed', 'char']: # keep this unmodified - prefixes = {} - while names: - name = names[0] - if name in ('short', 'long', 'signed', 'unsigned'): - prefixes[name] = prefixes.get(name, 0) + 1 - del names[0] - else: - break - # ignore the 'signed' prefix below, and reorder the others - newnames = [] - for prefix in ('unsigned', 'short', 'long'): - for i in range(prefixes.get(prefix, 0)): - newnames.append(prefix) - if not names: - names = ['int'] # implicitly - if names == ['int']: # but kill it if 'short' or 'long' - if 'short' in prefixes or 'long' in prefixes: - names = [] - names = newnames + names - ident = ' '.join(names) - if ident == 'void': - return model.void_type, quals - if ident == '__dotdotdot__': - raise FFIError(':%d: bad usage of "..."' % - typenode.coord.line) - tp0, quals0 = resolve_common_type(self, ident) - return tp0, (quals | quals0) - # - if isinstance(type, pycparser.c_ast.Struct): - # 'struct foobar' - tp = self._get_struct_union_enum_type('struct', type, name) - return tp, quals - # - if isinstance(type, pycparser.c_ast.Union): - # 'union foobar' - tp = self._get_struct_union_enum_type('union', type, name) - return tp, quals - # - if isinstance(type, pycparser.c_ast.Enum): - # 'enum foobar' - tp = self._get_struct_union_enum_type('enum', type, name) - return tp, quals - # - if isinstance(typenode, pycparser.c_ast.FuncDecl): - # a function type - return self._parse_function_type(typenode, name), 0 - # - # nested anonymous structs or unions end up here - if isinstance(typenode, pycparser.c_ast.Struct): - return self._get_struct_union_enum_type('struct', typenode, name, - nested=True), 0 - if isinstance(typenode, pycparser.c_ast.Union): - return self._get_struct_union_enum_type('union', typenode, name, - nested=True), 0 - # - raise FFIError(":%d: bad or unsupported type declaration" % - typenode.coord.line) - - def _parse_function_type(self, typenode, funcname=None): - params = list(getattr(typenode.args, 'params', [])) - for i, arg in enumerate(params): - if not hasattr(arg, 'type'): - raise CDefError("%s arg %d: unknown type '%s'" - " (if you meant to use the old C syntax of giving" - " untyped arguments, it is not supported)" - % (funcname or 'in expression', i + 1, - getattr(arg, 'name', '?'))) - ellipsis = ( - len(params) > 0 and - isinstance(params[-1].type, pycparser.c_ast.TypeDecl) and - isinstance(params[-1].type.type, - pycparser.c_ast.IdentifierType) and - params[-1].type.type.names == ['__dotdotdot__']) - if ellipsis: - params.pop() - if not params: - raise CDefError( - "%s: a function with only '(...)' as argument" - " is not correct C" % (funcname or 'in expression')) - args = [self._as_func_arg(*self._get_type_and_quals(argdeclnode.type)) - for argdeclnode in params] - if not ellipsis and args == [model.void_type]: - args = [] - result, quals = self._get_type_and_quals(typenode.type) - # the 'quals' on the result type are ignored. HACK: we absure them - # to detect __stdcall functions: we textually replace "__stdcall" - # with "volatile volatile const" above. - abi = None - if hasattr(typenode.type, 'quals'): # else, probable syntax error anyway - if typenode.type.quals[-3:] == ['volatile', 'volatile', 'const']: - abi = '__stdcall' - return model.RawFunctionType(tuple(args), result, ellipsis, abi) - - def _as_func_arg(self, type, quals): - if isinstance(type, model.ArrayType): - return model.PointerType(type.item, quals) - elif isinstance(type, model.RawFunctionType): - return type.as_function_pointer() - else: - return type - - def _get_struct_union_enum_type(self, kind, type, name=None, nested=False): - # First, a level of caching on the exact 'type' node of the AST. - # This is obscure, but needed because pycparser "unrolls" declarations - # such as "typedef struct { } foo_t, *foo_p" and we end up with - # an AST that is not a tree, but a DAG, with the "type" node of the - # two branches foo_t and foo_p of the trees being the same node. - # It's a bit silly but detecting "DAG-ness" in the AST tree seems - # to be the only way to distinguish this case from two independent - # structs. See test_struct_with_two_usages. - try: - return self._structnode2type[type] - except KeyError: - pass - # - # Note that this must handle parsing "struct foo" any number of - # times and always return the same StructType object. Additionally, - # one of these times (not necessarily the first), the fields of - # the struct can be specified with "struct foo { ...fields... }". - # If no name is given, then we have to create a new anonymous struct - # with no caching; in this case, the fields are either specified - # right now or never. - # - force_name = name - name = type.name - # - # get the type or create it if needed - if name is None: - # 'force_name' is used to guess a more readable name for - # anonymous structs, for the common case "typedef struct { } foo". - if force_name is not None: - explicit_name = '$%s' % force_name - else: - self._anonymous_counter += 1 - explicit_name = '$%d' % self._anonymous_counter - tp = None - else: - explicit_name = name - key = '%s %s' % (kind, name) - tp, _ = self._declarations.get(key, (None, None)) - # - if tp is None: - if kind == 'struct': - tp = model.StructType(explicit_name, None, None, None) - elif kind == 'union': - tp = model.UnionType(explicit_name, None, None, None) - elif kind == 'enum': - if explicit_name == '__dotdotdot__': - raise CDefError("Enums cannot be declared with ...") - tp = self._build_enum_type(explicit_name, type.values) - else: - raise AssertionError("kind = %r" % (kind,)) - if name is not None: - self._declare(key, tp) - else: - if kind == 'enum' and type.values is not None: - raise NotImplementedError( - "enum %s: the '{}' declaration should appear on the first " - "time the enum is mentioned, not later" % explicit_name) - if not tp.forcename: - tp.force_the_name(force_name) - if tp.forcename and '$' in tp.name: - self._declare('anonymous %s' % tp.forcename, tp) - # - self._structnode2type[type] = tp - # - # enums: done here - if kind == 'enum': - return tp - # - # is there a 'type.decls'? If yes, then this is the place in the - # C sources that declare the fields. If no, then just return the - # existing type, possibly still incomplete. - if type.decls is None: - return tp - # - if tp.fldnames is not None: - raise CDefError("duplicate declaration of struct %s" % name) - fldnames = [] - fldtypes = [] - fldbitsize = [] - fldquals = [] - for decl in type.decls: - if (isinstance(decl.type, pycparser.c_ast.IdentifierType) and - ''.join(decl.type.names) == '__dotdotdot__'): - # XXX pycparser is inconsistent: 'names' should be a list - # of strings, but is sometimes just one string. Use - # str.join() as a way to cope with both. - self._make_partial(tp, nested) - continue - if decl.bitsize is None: - bitsize = -1 - else: - bitsize = self._parse_constant(decl.bitsize) - self._partial_length = False - type, fqual = self._get_type_and_quals(decl.type, - partial_length_ok=True) - if self._partial_length: - self._make_partial(tp, nested) - if isinstance(type, model.StructType) and type.partial: - self._make_partial(tp, nested) - fldnames.append(decl.name or '') - fldtypes.append(type) - fldbitsize.append(bitsize) - fldquals.append(fqual) - tp.fldnames = tuple(fldnames) - tp.fldtypes = tuple(fldtypes) - tp.fldbitsize = tuple(fldbitsize) - tp.fldquals = tuple(fldquals) - if fldbitsize != [-1] * len(fldbitsize): - if isinstance(tp, model.StructType) and tp.partial: - raise NotImplementedError("%s: using both bitfields and '...;'" - % (tp,)) - tp.packed = self._options.get('packed') - if tp.completed: # must be re-completed: it is not opaque any more - tp.completed = 0 - self._recomplete.append(tp) - return tp - - def _make_partial(self, tp, nested): - if not isinstance(tp, model.StructOrUnion): - raise CDefError("%s cannot be partial" % (tp,)) - if not tp.has_c_name() and not nested: - raise NotImplementedError("%s is partial but has no C name" %(tp,)) - tp.partial = True - - def _parse_constant(self, exprnode, partial_length_ok=False): - # for now, limited to expressions that are an immediate number - # or positive/negative number - if isinstance(exprnode, pycparser.c_ast.Constant): - s = exprnode.value - if '0' <= s[0] <= '9': - s = s.rstrip('uUlL') - try: - if s.startswith('0'): - return int(s, 8) - else: - return int(s, 10) - except ValueError: - if len(s) > 1: - if s.lower()[0:2] == '0x': - return int(s, 16) - elif s.lower()[0:2] == '0b': - return int(s, 2) - raise CDefError("invalid constant %r" % (s,)) - elif s[0] == "'" and s[-1] == "'" and ( - len(s) == 3 or (len(s) == 4 and s[1] == "\\")): - return ord(s[-2]) - else: - raise CDefError("invalid constant %r" % (s,)) - # - if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and - exprnode.op == '+'): - return self._parse_constant(exprnode.expr) - # - if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and - exprnode.op == '-'): - return -self._parse_constant(exprnode.expr) - # load previously defined int constant - if (isinstance(exprnode, pycparser.c_ast.ID) and - exprnode.name in self._int_constants): - return self._int_constants[exprnode.name] - # - if (isinstance(exprnode, pycparser.c_ast.ID) and - exprnode.name == '__dotdotdotarray__'): - if partial_length_ok: - self._partial_length = True - return '...' - raise FFIError(":%d: unsupported '[...]' here, cannot derive " - "the actual array length in this context" - % exprnode.coord.line) - # - if isinstance(exprnode, pycparser.c_ast.BinaryOp): - left = self._parse_constant(exprnode.left) - right = self._parse_constant(exprnode.right) - if exprnode.op == '+': - return left + right - elif exprnode.op == '-': - return left - right - elif exprnode.op == '*': - return left * right - elif exprnode.op == '/': - return self._c_div(left, right) - elif exprnode.op == '%': - return left - self._c_div(left, right) * right - elif exprnode.op == '<<': - return left << right - elif exprnode.op == '>>': - return left >> right - elif exprnode.op == '&': - return left & right - elif exprnode.op == '|': - return left | right - elif exprnode.op == '^': - return left ^ right - # - raise FFIError(":%d: unsupported expression: expected a " - "simple numeric constant" % exprnode.coord.line) - - def _c_div(self, a, b): - result = a // b - if ((a < 0) ^ (b < 0)) and (a % b) != 0: - result += 1 - return result - - def _build_enum_type(self, explicit_name, decls): - if decls is not None: - partial = False - enumerators = [] - enumvalues = [] - nextenumvalue = 0 - for enum in decls.enumerators: - if _r_enum_dotdotdot.match(enum.name): - partial = True - continue - if enum.value is not None: - nextenumvalue = self._parse_constant(enum.value) - enumerators.append(enum.name) - enumvalues.append(nextenumvalue) - self._add_constants(enum.name, nextenumvalue) - nextenumvalue += 1 - enumerators = tuple(enumerators) - enumvalues = tuple(enumvalues) - tp = model.EnumType(explicit_name, enumerators, enumvalues) - tp.partial = partial - else: # opaque enum - tp = model.EnumType(explicit_name, (), ()) - return tp - - def include(self, other): - for name, (tp, quals) in other._declarations.items(): - if name.startswith('anonymous $enum_$'): - continue # fix for test_anonymous_enum_include - kind = name.split(' ', 1)[0] - if kind in ('struct', 'union', 'enum', 'anonymous', 'typedef'): - self._declare(name, tp, included=True, quals=quals) - for k, v in other._int_constants.items(): - self._add_constants(k, v) - - def _get_unknown_type(self, decl): - typenames = decl.type.type.names - if typenames == ['__dotdotdot__']: - return model.unknown_type(decl.name) - - if typenames == ['__dotdotdotint__']: - if self._uses_new_feature is None: - self._uses_new_feature = "'typedef int... %s'" % decl.name - return model.UnknownIntegerType(decl.name) - - if typenames == ['__dotdotdotfloat__']: - # note: not for 'long double' so far - if self._uses_new_feature is None: - self._uses_new_feature = "'typedef float... %s'" % decl.name - return model.UnknownFloatType(decl.name) - - raise FFIError(':%d: unsupported usage of "..." in typedef' - % decl.coord.line) - - def _get_unknown_ptr_type(self, decl): - if decl.type.type.type.names == ['__dotdotdot__']: - return model.unknown_ptr_type(decl.name) - raise FFIError(':%d: unsupported usage of "..." in typedef' - % decl.coord.line) diff --git a/notification-service/venv/Lib/site-packages/cffi/error.py b/notification-service/venv/Lib/site-packages/cffi/error.py deleted file mode 100644 index 0a27247..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/error.py +++ /dev/null @@ -1,31 +0,0 @@ - -class FFIError(Exception): - __module__ = 'cffi' - -class CDefError(Exception): - __module__ = 'cffi' - def __str__(self): - try: - current_decl = self.args[1] - filename = current_decl.coord.file - linenum = current_decl.coord.line - prefix = '%s:%d: ' % (filename, linenum) - except (AttributeError, TypeError, IndexError): - prefix = '' - return '%s%s' % (prefix, self.args[0]) - -class VerificationError(Exception): - """ An error raised when verification fails - """ - __module__ = 'cffi' - -class VerificationMissing(Exception): - """ An error raised when incomplete structures are passed into - cdef, but no verification has been done - """ - __module__ = 'cffi' - -class PkgConfigError(Exception): - """ An error raised for missing modules in pkg-config - """ - __module__ = 'cffi' diff --git a/notification-service/venv/Lib/site-packages/cffi/ffiplatform.py b/notification-service/venv/Lib/site-packages/cffi/ffiplatform.py deleted file mode 100644 index adca28f..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/ffiplatform.py +++ /dev/null @@ -1,113 +0,0 @@ -import sys, os -from .error import VerificationError - - -LIST_OF_FILE_NAMES = ['sources', 'include_dirs', 'library_dirs', - 'extra_objects', 'depends'] - -def get_extension(srcfilename, modname, sources=(), **kwds): - from cffi._shimmed_dist_utils import Extension - allsources = [srcfilename] - for src in sources: - allsources.append(os.path.normpath(src)) - return Extension(name=modname, sources=allsources, **kwds) - -def compile(tmpdir, ext, compiler_verbose=0, debug=None): - """Compile a C extension module using distutils.""" - - saved_environ = os.environ.copy() - try: - outputfilename = _build(tmpdir, ext, compiler_verbose, debug) - outputfilename = os.path.abspath(outputfilename) - finally: - # workaround for a distutils bugs where some env vars can - # become longer and longer every time it is used - for key, value in saved_environ.items(): - if os.environ.get(key) != value: - os.environ[key] = value - return outputfilename - -def _build(tmpdir, ext, compiler_verbose=0, debug=None): - # XXX compact but horrible :-( - from cffi._shimmed_dist_utils import Distribution, CompileError, LinkError, set_threshold, set_verbosity - - dist = Distribution({'ext_modules': [ext]}) - dist.parse_config_files() - options = dist.get_option_dict('build_ext') - if debug is None: - debug = sys.flags.debug - options['debug'] = ('ffiplatform', debug) - options['force'] = ('ffiplatform', True) - options['build_lib'] = ('ffiplatform', tmpdir) - options['build_temp'] = ('ffiplatform', tmpdir) - # - try: - old_level = set_threshold(0) or 0 - try: - set_verbosity(compiler_verbose) - dist.run_command('build_ext') - cmd_obj = dist.get_command_obj('build_ext') - [soname] = cmd_obj.get_outputs() - finally: - set_threshold(old_level) - except (CompileError, LinkError) as e: - raise VerificationError('%s: %s' % (e.__class__.__name__, e)) - # - return soname - -try: - from os.path import samefile -except ImportError: - def samefile(f1, f2): - return os.path.abspath(f1) == os.path.abspath(f2) - -def maybe_relative_path(path): - if not os.path.isabs(path): - return path # already relative - dir = path - names = [] - while True: - prevdir = dir - dir, name = os.path.split(prevdir) - if dir == prevdir or not dir: - return path # failed to make it relative - names.append(name) - try: - if samefile(dir, os.curdir): - names.reverse() - return os.path.join(*names) - except OSError: - pass - -# ____________________________________________________________ - -try: - int_or_long = (int, long) - import cStringIO -except NameError: - int_or_long = int # Python 3 - import io as cStringIO - -def _flatten(x, f): - if isinstance(x, str): - f.write('%ds%s' % (len(x), x)) - elif isinstance(x, dict): - keys = sorted(x.keys()) - f.write('%dd' % len(keys)) - for key in keys: - _flatten(key, f) - _flatten(x[key], f) - elif isinstance(x, (list, tuple)): - f.write('%dl' % len(x)) - for value in x: - _flatten(value, f) - elif isinstance(x, int_or_long): - f.write('%di' % (x,)) - else: - raise TypeError( - "the keywords to verify() contains unsupported object %r" % (x,)) - -def flatten(x): - f = cStringIO.StringIO() - _flatten(x, f) - return f.getvalue() diff --git a/notification-service/venv/Lib/site-packages/cffi/lock.py b/notification-service/venv/Lib/site-packages/cffi/lock.py deleted file mode 100644 index db91b71..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/lock.py +++ /dev/null @@ -1,30 +0,0 @@ -import sys - -if sys.version_info < (3,): - try: - from thread import allocate_lock - except ImportError: - from dummy_thread import allocate_lock -else: - try: - from _thread import allocate_lock - except ImportError: - from _dummy_thread import allocate_lock - - -##import sys -##l1 = allocate_lock - -##class allocate_lock(object): -## def __init__(self): -## self._real = l1() -## def __enter__(self): -## for i in range(4, 0, -1): -## print sys._getframe(i).f_code -## print -## return self._real.__enter__() -## def __exit__(self, *args): -## return self._real.__exit__(*args) -## def acquire(self, f): -## assert f is False -## return self._real.acquire(f) diff --git a/notification-service/venv/Lib/site-packages/cffi/model.py b/notification-service/venv/Lib/site-packages/cffi/model.py deleted file mode 100644 index e5f4cae..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/model.py +++ /dev/null @@ -1,618 +0,0 @@ -import types -import weakref - -from .lock import allocate_lock -from .error import CDefError, VerificationError, VerificationMissing - -# type qualifiers -Q_CONST = 0x01 -Q_RESTRICT = 0x02 -Q_VOLATILE = 0x04 - -def qualify(quals, replace_with): - if quals & Q_CONST: - replace_with = ' const ' + replace_with.lstrip() - if quals & Q_VOLATILE: - replace_with = ' volatile ' + replace_with.lstrip() - if quals & Q_RESTRICT: - # It seems that __restrict is supported by gcc and msvc. - # If you hit some different compiler, add a #define in - # _cffi_include.h for it (and in its copies, documented there) - replace_with = ' __restrict ' + replace_with.lstrip() - return replace_with - - -class BaseTypeByIdentity(object): - is_array_type = False - is_raw_function = False - - def get_c_name(self, replace_with='', context='a C file', quals=0): - result = self.c_name_with_marker - assert result.count('&') == 1 - # some logic duplication with ffi.getctype()... :-( - replace_with = replace_with.strip() - if replace_with: - if replace_with.startswith('*') and '&[' in result: - replace_with = '(%s)' % replace_with - elif not replace_with[0] in '[(': - replace_with = ' ' + replace_with - replace_with = qualify(quals, replace_with) - result = result.replace('&', replace_with) - if '$' in result: - raise VerificationError( - "cannot generate '%s' in %s: unknown type name" - % (self._get_c_name(), context)) - return result - - def _get_c_name(self): - return self.c_name_with_marker.replace('&', '') - - def has_c_name(self): - return '$' not in self._get_c_name() - - def is_integer_type(self): - return False - - def get_cached_btype(self, ffi, finishlist, can_delay=False): - try: - BType = ffi._cached_btypes[self] - except KeyError: - BType = self.build_backend_type(ffi, finishlist) - BType2 = ffi._cached_btypes.setdefault(self, BType) - assert BType2 is BType - return BType - - def __repr__(self): - return '<%s>' % (self._get_c_name(),) - - def _get_items(self): - return [(name, getattr(self, name)) for name in self._attrs_] - - -class BaseType(BaseTypeByIdentity): - - def __eq__(self, other): - return (self.__class__ == other.__class__ and - self._get_items() == other._get_items()) - - def __ne__(self, other): - return not self == other - - def __hash__(self): - return hash((self.__class__, tuple(self._get_items()))) - - -class VoidType(BaseType): - _attrs_ = () - - def __init__(self): - self.c_name_with_marker = 'void&' - - def build_backend_type(self, ffi, finishlist): - return global_cache(self, ffi, 'new_void_type') - -void_type = VoidType() - - -class BasePrimitiveType(BaseType): - def is_complex_type(self): - return False - - -class PrimitiveType(BasePrimitiveType): - _attrs_ = ('name',) - - ALL_PRIMITIVE_TYPES = { - 'char': 'c', - 'short': 'i', - 'int': 'i', - 'long': 'i', - 'long long': 'i', - 'signed char': 'i', - 'unsigned char': 'i', - 'unsigned short': 'i', - 'unsigned int': 'i', - 'unsigned long': 'i', - 'unsigned long long': 'i', - 'float': 'f', - 'double': 'f', - 'long double': 'f', - '_cffi_float_complex_t': 'j', - '_cffi_double_complex_t': 'j', - '_Bool': 'i', - # the following types are not primitive in the C sense - 'wchar_t': 'c', - 'char16_t': 'c', - 'char32_t': 'c', - 'int8_t': 'i', - 'uint8_t': 'i', - 'int16_t': 'i', - 'uint16_t': 'i', - 'int32_t': 'i', - 'uint32_t': 'i', - 'int64_t': 'i', - 'uint64_t': 'i', - 'int_least8_t': 'i', - 'uint_least8_t': 'i', - 'int_least16_t': 'i', - 'uint_least16_t': 'i', - 'int_least32_t': 'i', - 'uint_least32_t': 'i', - 'int_least64_t': 'i', - 'uint_least64_t': 'i', - 'int_fast8_t': 'i', - 'uint_fast8_t': 'i', - 'int_fast16_t': 'i', - 'uint_fast16_t': 'i', - 'int_fast32_t': 'i', - 'uint_fast32_t': 'i', - 'int_fast64_t': 'i', - 'uint_fast64_t': 'i', - 'intptr_t': 'i', - 'uintptr_t': 'i', - 'intmax_t': 'i', - 'uintmax_t': 'i', - 'ptrdiff_t': 'i', - 'size_t': 'i', - 'ssize_t': 'i', - } - - def __init__(self, name): - assert name in self.ALL_PRIMITIVE_TYPES - self.name = name - self.c_name_with_marker = name + '&' - - def is_char_type(self): - return self.ALL_PRIMITIVE_TYPES[self.name] == 'c' - def is_integer_type(self): - return self.ALL_PRIMITIVE_TYPES[self.name] == 'i' - def is_float_type(self): - return self.ALL_PRIMITIVE_TYPES[self.name] == 'f' - def is_complex_type(self): - return self.ALL_PRIMITIVE_TYPES[self.name] == 'j' - - def build_backend_type(self, ffi, finishlist): - return global_cache(self, ffi, 'new_primitive_type', self.name) - - -class UnknownIntegerType(BasePrimitiveType): - _attrs_ = ('name',) - - def __init__(self, name): - self.name = name - self.c_name_with_marker = name + '&' - - def is_integer_type(self): - return True - - def build_backend_type(self, ffi, finishlist): - raise NotImplementedError("integer type '%s' can only be used after " - "compilation" % self.name) - -class UnknownFloatType(BasePrimitiveType): - _attrs_ = ('name', ) - - def __init__(self, name): - self.name = name - self.c_name_with_marker = name + '&' - - def build_backend_type(self, ffi, finishlist): - raise NotImplementedError("float type '%s' can only be used after " - "compilation" % self.name) - - -class BaseFunctionType(BaseType): - _attrs_ = ('args', 'result', 'ellipsis', 'abi') - - def __init__(self, args, result, ellipsis, abi=None): - self.args = args - self.result = result - self.ellipsis = ellipsis - self.abi = abi - # - reprargs = [arg._get_c_name() for arg in self.args] - if self.ellipsis: - reprargs.append('...') - reprargs = reprargs or ['void'] - replace_with = self._base_pattern % (', '.join(reprargs),) - if abi is not None: - replace_with = replace_with[:1] + abi + ' ' + replace_with[1:] - self.c_name_with_marker = ( - self.result.c_name_with_marker.replace('&', replace_with)) - - -class RawFunctionType(BaseFunctionType): - # Corresponds to a C type like 'int(int)', which is the C type of - # a function, but not a pointer-to-function. The backend has no - # notion of such a type; it's used temporarily by parsing. - _base_pattern = '(&)(%s)' - is_raw_function = True - - def build_backend_type(self, ffi, finishlist): - raise CDefError("cannot render the type %r: it is a function " - "type, not a pointer-to-function type" % (self,)) - - def as_function_pointer(self): - return FunctionPtrType(self.args, self.result, self.ellipsis, self.abi) - - -class FunctionPtrType(BaseFunctionType): - _base_pattern = '(*&)(%s)' - - def build_backend_type(self, ffi, finishlist): - result = self.result.get_cached_btype(ffi, finishlist) - args = [] - for tp in self.args: - args.append(tp.get_cached_btype(ffi, finishlist)) - abi_args = () - if self.abi == "__stdcall": - if not self.ellipsis: # __stdcall ignored for variadic funcs - try: - abi_args = (ffi._backend.FFI_STDCALL,) - except AttributeError: - pass - return global_cache(self, ffi, 'new_function_type', - tuple(args), result, self.ellipsis, *abi_args) - - def as_raw_function(self): - return RawFunctionType(self.args, self.result, self.ellipsis, self.abi) - - -class PointerType(BaseType): - _attrs_ = ('totype', 'quals') - - def __init__(self, totype, quals=0): - self.totype = totype - self.quals = quals - extra = " *&" - if totype.is_array_type: - extra = "(%s)" % (extra.lstrip(),) - extra = qualify(quals, extra) - self.c_name_with_marker = totype.c_name_with_marker.replace('&', extra) - - def build_backend_type(self, ffi, finishlist): - BItem = self.totype.get_cached_btype(ffi, finishlist, can_delay=True) - return global_cache(self, ffi, 'new_pointer_type', BItem) - -voidp_type = PointerType(void_type) - -def ConstPointerType(totype): - return PointerType(totype, Q_CONST) - -const_voidp_type = ConstPointerType(void_type) - - -class NamedPointerType(PointerType): - _attrs_ = ('totype', 'name') - - def __init__(self, totype, name, quals=0): - PointerType.__init__(self, totype, quals) - self.name = name - self.c_name_with_marker = name + '&' - - -class ArrayType(BaseType): - _attrs_ = ('item', 'length') - is_array_type = True - - def __init__(self, item, length): - self.item = item - self.length = length - # - if length is None: - brackets = '&[]' - elif length == '...': - brackets = '&[/*...*/]' - else: - brackets = '&[%s]' % length - self.c_name_with_marker = ( - self.item.c_name_with_marker.replace('&', brackets)) - - def length_is_unknown(self): - return isinstance(self.length, str) - - def resolve_length(self, newlength): - return ArrayType(self.item, newlength) - - def build_backend_type(self, ffi, finishlist): - if self.length_is_unknown(): - raise CDefError("cannot render the type %r: unknown length" % - (self,)) - self.item.get_cached_btype(ffi, finishlist) # force the item BType - BPtrItem = PointerType(self.item).get_cached_btype(ffi, finishlist) - return global_cache(self, ffi, 'new_array_type', BPtrItem, self.length) - -char_array_type = ArrayType(PrimitiveType('char'), None) - - -class StructOrUnionOrEnum(BaseTypeByIdentity): - _attrs_ = ('name',) - forcename = None - - def build_c_name_with_marker(self): - name = self.forcename or '%s %s' % (self.kind, self.name) - self.c_name_with_marker = name + '&' - - def force_the_name(self, forcename): - self.forcename = forcename - self.build_c_name_with_marker() - - def get_official_name(self): - assert self.c_name_with_marker.endswith('&') - return self.c_name_with_marker[:-1] - - -class StructOrUnion(StructOrUnionOrEnum): - fixedlayout = None - completed = 0 - partial = False - packed = 0 - - def __init__(self, name, fldnames, fldtypes, fldbitsize, fldquals=None): - self.name = name - self.fldnames = fldnames - self.fldtypes = fldtypes - self.fldbitsize = fldbitsize - self.fldquals = fldquals - self.build_c_name_with_marker() - - def anonymous_struct_fields(self): - if self.fldtypes is not None: - for name, type in zip(self.fldnames, self.fldtypes): - if name == '' and isinstance(type, StructOrUnion): - yield type - - def enumfields(self, expand_anonymous_struct_union=True): - fldquals = self.fldquals - if fldquals is None: - fldquals = (0,) * len(self.fldnames) - for name, type, bitsize, quals in zip(self.fldnames, self.fldtypes, - self.fldbitsize, fldquals): - if (name == '' and isinstance(type, StructOrUnion) - and expand_anonymous_struct_union): - # nested anonymous struct/union - for result in type.enumfields(): - yield result - else: - yield (name, type, bitsize, quals) - - def force_flatten(self): - # force the struct or union to have a declaration that lists - # directly all fields returned by enumfields(), flattening - # nested anonymous structs/unions. - names = [] - types = [] - bitsizes = [] - fldquals = [] - for name, type, bitsize, quals in self.enumfields(): - names.append(name) - types.append(type) - bitsizes.append(bitsize) - fldquals.append(quals) - self.fldnames = tuple(names) - self.fldtypes = tuple(types) - self.fldbitsize = tuple(bitsizes) - self.fldquals = tuple(fldquals) - - def get_cached_btype(self, ffi, finishlist, can_delay=False): - BType = StructOrUnionOrEnum.get_cached_btype(self, ffi, finishlist, - can_delay) - if not can_delay: - self.finish_backend_type(ffi, finishlist) - return BType - - def finish_backend_type(self, ffi, finishlist): - if self.completed: - if self.completed != 2: - raise NotImplementedError("recursive structure declaration " - "for '%s'" % (self.name,)) - return - BType = ffi._cached_btypes[self] - # - self.completed = 1 - # - if self.fldtypes is None: - pass # not completing it: it's an opaque struct - # - elif self.fixedlayout is None: - fldtypes = [tp.get_cached_btype(ffi, finishlist) - for tp in self.fldtypes] - lst = list(zip(self.fldnames, fldtypes, self.fldbitsize)) - extra_flags = () - if self.packed: - if self.packed == 1: - extra_flags = (8,) # SF_PACKED - else: - extra_flags = (0, self.packed) - ffi._backend.complete_struct_or_union(BType, lst, self, - -1, -1, *extra_flags) - # - else: - fldtypes = [] - fieldofs, fieldsize, totalsize, totalalignment = self.fixedlayout - for i in range(len(self.fldnames)): - fsize = fieldsize[i] - ftype = self.fldtypes[i] - # - if isinstance(ftype, ArrayType) and ftype.length_is_unknown(): - # fix the length to match the total size - BItemType = ftype.item.get_cached_btype(ffi, finishlist) - nlen, nrest = divmod(fsize, ffi.sizeof(BItemType)) - if nrest != 0: - self._verification_error( - "field '%s.%s' has a bogus size?" % ( - self.name, self.fldnames[i] or '{}')) - ftype = ftype.resolve_length(nlen) - self.fldtypes = (self.fldtypes[:i] + (ftype,) + - self.fldtypes[i+1:]) - # - BFieldType = ftype.get_cached_btype(ffi, finishlist) - if isinstance(ftype, ArrayType) and ftype.length is None: - assert fsize == 0 - else: - bitemsize = ffi.sizeof(BFieldType) - if bitemsize != fsize: - self._verification_error( - "field '%s.%s' is declared as %d bytes, but is " - "really %d bytes" % (self.name, - self.fldnames[i] or '{}', - bitemsize, fsize)) - fldtypes.append(BFieldType) - # - lst = list(zip(self.fldnames, fldtypes, self.fldbitsize, fieldofs)) - ffi._backend.complete_struct_or_union(BType, lst, self, - totalsize, totalalignment) - self.completed = 2 - - def _verification_error(self, msg): - raise VerificationError(msg) - - def check_not_partial(self): - if self.partial and self.fixedlayout is None: - raise VerificationMissing(self._get_c_name()) - - def build_backend_type(self, ffi, finishlist): - self.check_not_partial() - finishlist.append(self) - # - return global_cache(self, ffi, 'new_%s_type' % self.kind, - self.get_official_name(), key=self) - - -class StructType(StructOrUnion): - kind = 'struct' - - -class UnionType(StructOrUnion): - kind = 'union' - - -class EnumType(StructOrUnionOrEnum): - kind = 'enum' - partial = False - partial_resolved = False - - def __init__(self, name, enumerators, enumvalues, baseinttype=None): - self.name = name - self.enumerators = enumerators - self.enumvalues = enumvalues - self.baseinttype = baseinttype - self.build_c_name_with_marker() - - def force_the_name(self, forcename): - StructOrUnionOrEnum.force_the_name(self, forcename) - if self.forcename is None: - name = self.get_official_name() - self.forcename = '$' + name.replace(' ', '_') - - def check_not_partial(self): - if self.partial and not self.partial_resolved: - raise VerificationMissing(self._get_c_name()) - - def build_backend_type(self, ffi, finishlist): - self.check_not_partial() - base_btype = self.build_baseinttype(ffi, finishlist) - return global_cache(self, ffi, 'new_enum_type', - self.get_official_name(), - self.enumerators, self.enumvalues, - base_btype, key=self) - - def build_baseinttype(self, ffi, finishlist): - if self.baseinttype is not None: - return self.baseinttype.get_cached_btype(ffi, finishlist) - # - if self.enumvalues: - smallest_value = min(self.enumvalues) - largest_value = max(self.enumvalues) - else: - import warnings - try: - # XXX! The goal is to ensure that the warnings.warn() - # will not suppress the warning. We want to get it - # several times if we reach this point several times. - __warningregistry__.clear() - except NameError: - pass - warnings.warn("%r has no values explicitly defined; " - "guessing that it is equivalent to 'unsigned int'" - % self._get_c_name()) - smallest_value = largest_value = 0 - if smallest_value < 0: # needs a signed type - sign = 1 - candidate1 = PrimitiveType("int") - candidate2 = PrimitiveType("long") - else: - sign = 0 - candidate1 = PrimitiveType("unsigned int") - candidate2 = PrimitiveType("unsigned long") - btype1 = candidate1.get_cached_btype(ffi, finishlist) - btype2 = candidate2.get_cached_btype(ffi, finishlist) - size1 = ffi.sizeof(btype1) - size2 = ffi.sizeof(btype2) - if (smallest_value >= ((-1) << (8*size1-1)) and - largest_value < (1 << (8*size1-sign))): - return btype1 - if (smallest_value >= ((-1) << (8*size2-1)) and - largest_value < (1 << (8*size2-sign))): - return btype2 - raise CDefError("%s values don't all fit into either 'long' " - "or 'unsigned long'" % self._get_c_name()) - -def unknown_type(name, structname=None): - if structname is None: - structname = '$%s' % name - tp = StructType(structname, None, None, None) - tp.force_the_name(name) - tp.origin = "unknown_type" - return tp - -def unknown_ptr_type(name, structname=None): - if structname is None: - structname = '$$%s' % name - tp = StructType(structname, None, None, None) - return NamedPointerType(tp, name) - - -global_lock = allocate_lock() -_typecache_cffi_backend = weakref.WeakValueDictionary() - -def get_typecache(backend): - # returns _typecache_cffi_backend if backend is the _cffi_backend - # module, or type(backend).__typecache if backend is an instance of - # CTypesBackend (or some FakeBackend class during tests) - if isinstance(backend, types.ModuleType): - return _typecache_cffi_backend - with global_lock: - if not hasattr(type(backend), '__typecache'): - type(backend).__typecache = weakref.WeakValueDictionary() - return type(backend).__typecache - -def global_cache(srctype, ffi, funcname, *args, **kwds): - key = kwds.pop('key', (funcname, args)) - assert not kwds - try: - return ffi._typecache[key] - except KeyError: - pass - try: - res = getattr(ffi._backend, funcname)(*args) - except NotImplementedError as e: - raise NotImplementedError("%s: %r: %s" % (funcname, srctype, e)) - # note that setdefault() on WeakValueDictionary is not atomic - # and contains a rare bug (http://bugs.python.org/issue19542); - # we have to use a lock and do it ourselves - cache = ffi._typecache - with global_lock: - res1 = cache.get(key) - if res1 is None: - cache[key] = res - return res - else: - return res1 - -def pointer_cache(ffi, BType): - return global_cache('?', ffi, 'new_pointer_type', BType) - -def attach_exception_info(e, name): - if e.args and type(e.args[0]) is str: - e.args = ('%s: %s' % (name, e.args[0]),) + e.args[1:] diff --git a/notification-service/venv/Lib/site-packages/cffi/parse_c_type.h b/notification-service/venv/Lib/site-packages/cffi/parse_c_type.h deleted file mode 100644 index 84e4ef8..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/parse_c_type.h +++ /dev/null @@ -1,181 +0,0 @@ - -/* This part is from file 'cffi/parse_c_type.h'. It is copied at the - beginning of C sources generated by CFFI's ffi.set_source(). */ - -typedef void *_cffi_opcode_t; - -#define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8)) -#define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode) -#define _CFFI_GETARG(cffi_opcode) (((intptr_t)cffi_opcode) >> 8) - -#define _CFFI_OP_PRIMITIVE 1 -#define _CFFI_OP_POINTER 3 -#define _CFFI_OP_ARRAY 5 -#define _CFFI_OP_OPEN_ARRAY 7 -#define _CFFI_OP_STRUCT_UNION 9 -#define _CFFI_OP_ENUM 11 -#define _CFFI_OP_FUNCTION 13 -#define _CFFI_OP_FUNCTION_END 15 -#define _CFFI_OP_NOOP 17 -#define _CFFI_OP_BITFIELD 19 -#define _CFFI_OP_TYPENAME 21 -#define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs -#define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs -#define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg) -#define _CFFI_OP_CONSTANT 29 -#define _CFFI_OP_CONSTANT_INT 31 -#define _CFFI_OP_GLOBAL_VAR 33 -#define _CFFI_OP_DLOPEN_FUNC 35 -#define _CFFI_OP_DLOPEN_CONST 37 -#define _CFFI_OP_GLOBAL_VAR_F 39 -#define _CFFI_OP_EXTERN_PYTHON 41 - -#define _CFFI_PRIM_VOID 0 -#define _CFFI_PRIM_BOOL 1 -#define _CFFI_PRIM_CHAR 2 -#define _CFFI_PRIM_SCHAR 3 -#define _CFFI_PRIM_UCHAR 4 -#define _CFFI_PRIM_SHORT 5 -#define _CFFI_PRIM_USHORT 6 -#define _CFFI_PRIM_INT 7 -#define _CFFI_PRIM_UINT 8 -#define _CFFI_PRIM_LONG 9 -#define _CFFI_PRIM_ULONG 10 -#define _CFFI_PRIM_LONGLONG 11 -#define _CFFI_PRIM_ULONGLONG 12 -#define _CFFI_PRIM_FLOAT 13 -#define _CFFI_PRIM_DOUBLE 14 -#define _CFFI_PRIM_LONGDOUBLE 15 - -#define _CFFI_PRIM_WCHAR 16 -#define _CFFI_PRIM_INT8 17 -#define _CFFI_PRIM_UINT8 18 -#define _CFFI_PRIM_INT16 19 -#define _CFFI_PRIM_UINT16 20 -#define _CFFI_PRIM_INT32 21 -#define _CFFI_PRIM_UINT32 22 -#define _CFFI_PRIM_INT64 23 -#define _CFFI_PRIM_UINT64 24 -#define _CFFI_PRIM_INTPTR 25 -#define _CFFI_PRIM_UINTPTR 26 -#define _CFFI_PRIM_PTRDIFF 27 -#define _CFFI_PRIM_SIZE 28 -#define _CFFI_PRIM_SSIZE 29 -#define _CFFI_PRIM_INT_LEAST8 30 -#define _CFFI_PRIM_UINT_LEAST8 31 -#define _CFFI_PRIM_INT_LEAST16 32 -#define _CFFI_PRIM_UINT_LEAST16 33 -#define _CFFI_PRIM_INT_LEAST32 34 -#define _CFFI_PRIM_UINT_LEAST32 35 -#define _CFFI_PRIM_INT_LEAST64 36 -#define _CFFI_PRIM_UINT_LEAST64 37 -#define _CFFI_PRIM_INT_FAST8 38 -#define _CFFI_PRIM_UINT_FAST8 39 -#define _CFFI_PRIM_INT_FAST16 40 -#define _CFFI_PRIM_UINT_FAST16 41 -#define _CFFI_PRIM_INT_FAST32 42 -#define _CFFI_PRIM_UINT_FAST32 43 -#define _CFFI_PRIM_INT_FAST64 44 -#define _CFFI_PRIM_UINT_FAST64 45 -#define _CFFI_PRIM_INTMAX 46 -#define _CFFI_PRIM_UINTMAX 47 -#define _CFFI_PRIM_FLOATCOMPLEX 48 -#define _CFFI_PRIM_DOUBLECOMPLEX 49 -#define _CFFI_PRIM_CHAR16 50 -#define _CFFI_PRIM_CHAR32 51 - -#define _CFFI__NUM_PRIM 52 -#define _CFFI__UNKNOWN_PRIM (-1) -#define _CFFI__UNKNOWN_FLOAT_PRIM (-2) -#define _CFFI__UNKNOWN_LONG_DOUBLE (-3) - -#define _CFFI__IO_FILE_STRUCT (-1) - - -struct _cffi_global_s { - const char *name; - void *address; - _cffi_opcode_t type_op; - void *size_or_direct_fn; // OP_GLOBAL_VAR: size, or 0 if unknown - // OP_CPYTHON_BLTN_*: addr of direct function -}; - -struct _cffi_getconst_s { - unsigned long long value; - const struct _cffi_type_context_s *ctx; - int gindex; -}; - -struct _cffi_struct_union_s { - const char *name; - int type_index; // -> _cffi_types, on a OP_STRUCT_UNION - int flags; // _CFFI_F_* flags below - size_t size; - int alignment; - int first_field_index; // -> _cffi_fields array - int num_fields; -}; -#define _CFFI_F_UNION 0x01 // is a union, not a struct -#define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the - // "standard layout" or if some are missing -#define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed struct -#define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include() -#define _CFFI_F_OPAQUE 0x10 // opaque - -struct _cffi_field_s { - const char *name; - size_t field_offset; - size_t field_size; - _cffi_opcode_t field_type_op; -}; - -struct _cffi_enum_s { - const char *name; - int type_index; // -> _cffi_types, on a OP_ENUM - int type_prim; // _CFFI_PRIM_xxx - const char *enumerators; // comma-delimited string -}; - -struct _cffi_typename_s { - const char *name; - int type_index; /* if opaque, points to a possibly artificial - OP_STRUCT which is itself opaque */ -}; - -struct _cffi_type_context_s { - _cffi_opcode_t *types; - const struct _cffi_global_s *globals; - const struct _cffi_field_s *fields; - const struct _cffi_struct_union_s *struct_unions; - const struct _cffi_enum_s *enums; - const struct _cffi_typename_s *typenames; - int num_globals; - int num_struct_unions; - int num_enums; - int num_typenames; - const char *const *includes; - int num_types; - int flags; /* future extension */ -}; - -struct _cffi_parse_info_s { - const struct _cffi_type_context_s *ctx; - _cffi_opcode_t *output; - unsigned int output_size; - size_t error_location; - const char *error_message; -}; - -struct _cffi_externpy_s { - const char *name; - size_t size_of_result; - void *reserved1, *reserved2; -}; - -#ifdef _CFFI_INTERNAL -static int parse_c_type(struct _cffi_parse_info_s *info, const char *input); -static int search_in_globals(const struct _cffi_type_context_s *ctx, - const char *search, size_t search_len); -static int search_in_struct_unions(const struct _cffi_type_context_s *ctx, - const char *search, size_t search_len); -#endif diff --git a/notification-service/venv/Lib/site-packages/cffi/pkgconfig.py b/notification-service/venv/Lib/site-packages/cffi/pkgconfig.py deleted file mode 100644 index 5c93f15..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/pkgconfig.py +++ /dev/null @@ -1,121 +0,0 @@ -# pkg-config, https://www.freedesktop.org/wiki/Software/pkg-config/ integration for cffi -import sys, os, subprocess - -from .error import PkgConfigError - - -def merge_flags(cfg1, cfg2): - """Merge values from cffi config flags cfg2 to cf1 - - Example: - merge_flags({"libraries": ["one"]}, {"libraries": ["two"]}) - {"libraries": ["one", "two"]} - """ - for key, value in cfg2.items(): - if key not in cfg1: - cfg1[key] = value - else: - if not isinstance(cfg1[key], list): - raise TypeError("cfg1[%r] should be a list of strings" % (key,)) - if not isinstance(value, list): - raise TypeError("cfg2[%r] should be a list of strings" % (key,)) - cfg1[key].extend(value) - return cfg1 - - -def call(libname, flag, encoding=sys.getfilesystemencoding()): - """Calls pkg-config and returns the output if found - """ - a = ["pkg-config", "--print-errors"] - a.append(flag) - a.append(libname) - try: - pc = subprocess.Popen(a, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - except EnvironmentError as e: - raise PkgConfigError("cannot run pkg-config: %s" % (str(e).strip(),)) - - bout, berr = pc.communicate() - if pc.returncode != 0: - try: - berr = berr.decode(encoding) - except Exception: - pass - raise PkgConfigError(berr.strip()) - - if sys.version_info >= (3,) and not isinstance(bout, str): # Python 3.x - try: - bout = bout.decode(encoding) - except UnicodeDecodeError: - raise PkgConfigError("pkg-config %s %s returned bytes that cannot " - "be decoded with encoding %r:\n%r" % - (flag, libname, encoding, bout)) - - if os.altsep != '\\' and '\\' in bout: - raise PkgConfigError("pkg-config %s %s returned an unsupported " - "backslash-escaped output:\n%r" % - (flag, libname, bout)) - return bout - - -def flags_from_pkgconfig(libs): - r"""Return compiler line flags for FFI.set_source based on pkg-config output - - Usage - ... - ffibuilder.set_source("_foo", pkgconfig = ["libfoo", "libbar >= 1.8.3"]) - - If pkg-config is installed on build machine, then arguments include_dirs, - library_dirs, libraries, define_macros, extra_compile_args and - extra_link_args are extended with an output of pkg-config for libfoo and - libbar. - - Raises PkgConfigError in case the pkg-config call fails. - """ - - def get_include_dirs(string): - return [x[2:] for x in string.split() if x.startswith("-I")] - - def get_library_dirs(string): - return [x[2:] for x in string.split() if x.startswith("-L")] - - def get_libraries(string): - return [x[2:] for x in string.split() if x.startswith("-l")] - - # convert -Dfoo=bar to list of tuples [("foo", "bar")] expected by distutils - def get_macros(string): - def _macro(x): - x = x[2:] # drop "-D" - if '=' in x: - return tuple(x.split("=", 1)) # "-Dfoo=bar" => ("foo", "bar") - else: - return (x, None) # "-Dfoo" => ("foo", None) - return [_macro(x) for x in string.split() if x.startswith("-D")] - - def get_other_cflags(string): - return [x for x in string.split() if not x.startswith("-I") and - not x.startswith("-D")] - - def get_other_libs(string): - return [x for x in string.split() if not x.startswith("-L") and - not x.startswith("-l")] - - # return kwargs for given libname - def kwargs(libname): - fse = sys.getfilesystemencoding() - all_cflags = call(libname, "--cflags") - all_libs = call(libname, "--libs") - return { - "include_dirs": get_include_dirs(all_cflags), - "library_dirs": get_library_dirs(all_libs), - "libraries": get_libraries(all_libs), - "define_macros": get_macros(all_cflags), - "extra_compile_args": get_other_cflags(all_cflags), - "extra_link_args": get_other_libs(all_libs), - } - - # merge all arguments together - ret = {} - for libname in libs: - lib_flags = kwargs(libname) - merge_flags(ret, lib_flags) - return ret diff --git a/notification-service/venv/Lib/site-packages/cffi/recompiler.py b/notification-service/venv/Lib/site-packages/cffi/recompiler.py deleted file mode 100644 index 7734a34..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/recompiler.py +++ /dev/null @@ -1,1598 +0,0 @@ -import io, os, sys, sysconfig -from . import ffiplatform, model -from .error import VerificationError -from .cffi_opcode import * - -VERSION_BASE = 0x2601 -VERSION_EMBEDDED = 0x2701 -VERSION_CHAR16CHAR32 = 0x2801 - -USE_LIMITED_API = ((sys.platform != 'win32' or sys.version_info < (3, 0) or - sys.version_info >= (3, 5)) and - not sysconfig.get_config_var("Py_GIL_DISABLED")) # free-threaded doesn't yet support limited API - -class GlobalExpr: - def __init__(self, name, address, type_op, size=0, check_value=0): - self.name = name - self.address = address - self.type_op = type_op - self.size = size - self.check_value = check_value - - def as_c_expr(self): - return ' { "%s", (void *)%s, %s, (void *)%s },' % ( - self.name, self.address, self.type_op.as_c_expr(), self.size) - - def as_python_expr(self): - return "b'%s%s',%d" % (self.type_op.as_python_bytes(), self.name, - self.check_value) - -class FieldExpr: - def __init__(self, name, field_offset, field_size, fbitsize, field_type_op): - self.name = name - self.field_offset = field_offset - self.field_size = field_size - self.fbitsize = fbitsize - self.field_type_op = field_type_op - - def as_c_expr(self): - spaces = " " * len(self.name) - return (' { "%s", %s,\n' % (self.name, self.field_offset) + - ' %s %s,\n' % (spaces, self.field_size) + - ' %s %s },' % (spaces, self.field_type_op.as_c_expr())) - - def as_python_expr(self): - raise NotImplementedError - - def as_field_python_expr(self): - if self.field_type_op.op == OP_NOOP: - size_expr = '' - elif self.field_type_op.op == OP_BITFIELD: - size_expr = format_four_bytes(self.fbitsize) - else: - raise NotImplementedError - return "b'%s%s%s'" % (self.field_type_op.as_python_bytes(), - size_expr, - self.name) - -class StructUnionExpr: - def __init__(self, name, type_index, flags, size, alignment, comment, - first_field_index, c_fields): - self.name = name - self.type_index = type_index - self.flags = flags - self.size = size - self.alignment = alignment - self.comment = comment - self.first_field_index = first_field_index - self.c_fields = c_fields - - def as_c_expr(self): - return (' { "%s", %d, %s,' % (self.name, self.type_index, self.flags) - + '\n %s, %s, ' % (self.size, self.alignment) - + '%d, %d ' % (self.first_field_index, len(self.c_fields)) - + ('/* %s */ ' % self.comment if self.comment else '') - + '},') - - def as_python_expr(self): - flags = eval(self.flags, G_FLAGS) - fields_expr = [c_field.as_field_python_expr() - for c_field in self.c_fields] - return "(b'%s%s%s',%s)" % ( - format_four_bytes(self.type_index), - format_four_bytes(flags), - self.name, - ','.join(fields_expr)) - -class EnumExpr: - def __init__(self, name, type_index, size, signed, allenums): - self.name = name - self.type_index = type_index - self.size = size - self.signed = signed - self.allenums = allenums - - def as_c_expr(self): - return (' { "%s", %d, _cffi_prim_int(%s, %s),\n' - ' "%s" },' % (self.name, self.type_index, - self.size, self.signed, self.allenums)) - - def as_python_expr(self): - prim_index = { - (1, 0): PRIM_UINT8, (1, 1): PRIM_INT8, - (2, 0): PRIM_UINT16, (2, 1): PRIM_INT16, - (4, 0): PRIM_UINT32, (4, 1): PRIM_INT32, - (8, 0): PRIM_UINT64, (8, 1): PRIM_INT64, - }[self.size, self.signed] - return "b'%s%s%s\\x00%s'" % (format_four_bytes(self.type_index), - format_four_bytes(prim_index), - self.name, self.allenums) - -class TypenameExpr: - def __init__(self, name, type_index): - self.name = name - self.type_index = type_index - - def as_c_expr(self): - return ' { "%s", %d },' % (self.name, self.type_index) - - def as_python_expr(self): - return "b'%s%s'" % (format_four_bytes(self.type_index), self.name) - - -# ____________________________________________________________ - - -class Recompiler: - _num_externpy = 0 - - def __init__(self, ffi, module_name, target_is_python=False): - self.ffi = ffi - self.module_name = module_name - self.target_is_python = target_is_python - self._version = VERSION_BASE - - def needs_version(self, ver): - self._version = max(self._version, ver) - - def collect_type_table(self): - self._typesdict = {} - self._generate("collecttype") - # - all_decls = sorted(self._typesdict, key=str) - # - # prepare all FUNCTION bytecode sequences first - self.cffi_types = [] - for tp in all_decls: - if tp.is_raw_function: - assert self._typesdict[tp] is None - self._typesdict[tp] = len(self.cffi_types) - self.cffi_types.append(tp) # placeholder - for tp1 in tp.args: - assert isinstance(tp1, (model.VoidType, - model.BasePrimitiveType, - model.PointerType, - model.StructOrUnionOrEnum, - model.FunctionPtrType)) - if self._typesdict[tp1] is None: - self._typesdict[tp1] = len(self.cffi_types) - self.cffi_types.append(tp1) # placeholder - self.cffi_types.append('END') # placeholder - # - # prepare all OTHER bytecode sequences - for tp in all_decls: - if not tp.is_raw_function and self._typesdict[tp] is None: - self._typesdict[tp] = len(self.cffi_types) - self.cffi_types.append(tp) # placeholder - if tp.is_array_type and tp.length is not None: - self.cffi_types.append('LEN') # placeholder - assert None not in self._typesdict.values() - # - # collect all structs and unions and enums - self._struct_unions = {} - self._enums = {} - for tp in all_decls: - if isinstance(tp, model.StructOrUnion): - self._struct_unions[tp] = None - elif isinstance(tp, model.EnumType): - self._enums[tp] = None - for i, tp in enumerate(sorted(self._struct_unions, - key=lambda tp: tp.name)): - self._struct_unions[tp] = i - for i, tp in enumerate(sorted(self._enums, - key=lambda tp: tp.name)): - self._enums[tp] = i - # - # emit all bytecode sequences now - for tp in all_decls: - method = getattr(self, '_emit_bytecode_' + tp.__class__.__name__) - method(tp, self._typesdict[tp]) - # - # consistency check - for op in self.cffi_types: - assert isinstance(op, CffiOp) - self.cffi_types = tuple(self.cffi_types) # don't change any more - - def _enum_fields(self, tp): - # When producing C, expand all anonymous struct/union fields. - # That's necessary to have C code checking the offsets of the - # individual fields contained in them. When producing Python, - # don't do it and instead write it like it is, with the - # corresponding fields having an empty name. Empty names are - # recognized at runtime when we import the generated Python - # file. - expand_anonymous_struct_union = not self.target_is_python - return tp.enumfields(expand_anonymous_struct_union) - - def _do_collect_type(self, tp): - if not isinstance(tp, model.BaseTypeByIdentity): - if isinstance(tp, tuple): - for x in tp: - self._do_collect_type(x) - return - if tp not in self._typesdict: - self._typesdict[tp] = None - if isinstance(tp, model.FunctionPtrType): - self._do_collect_type(tp.as_raw_function()) - elif isinstance(tp, model.StructOrUnion): - if tp.fldtypes is not None and ( - tp not in self.ffi._parser._included_declarations): - for name1, tp1, _, _ in self._enum_fields(tp): - self._do_collect_type(self._field_type(tp, name1, tp1)) - else: - for _, x in tp._get_items(): - self._do_collect_type(x) - - def _generate(self, step_name): - lst = self.ffi._parser._declarations.items() - for name, (tp, quals) in sorted(lst): - kind, realname = name.split(' ', 1) - try: - method = getattr(self, '_generate_cpy_%s_%s' % (kind, - step_name)) - except AttributeError: - raise VerificationError( - "not implemented in recompile(): %r" % name) - try: - self._current_quals = quals - method(tp, realname) - except Exception as e: - model.attach_exception_info(e, name) - raise - - # ---------- - - ALL_STEPS = ["global", "field", "struct_union", "enum", "typename"] - - def collect_step_tables(self): - # collect the declarations for '_cffi_globals', '_cffi_typenames', etc. - self._lsts = {} - for step_name in self.ALL_STEPS: - self._lsts[step_name] = [] - self._seen_struct_unions = set() - self._generate("ctx") - self._add_missing_struct_unions() - # - for step_name in self.ALL_STEPS: - lst = self._lsts[step_name] - if step_name != "field": - lst.sort(key=lambda entry: entry.name) - self._lsts[step_name] = tuple(lst) # don't change any more - # - # check for a possible internal inconsistency: _cffi_struct_unions - # should have been generated with exactly self._struct_unions - lst = self._lsts["struct_union"] - for tp, i in self._struct_unions.items(): - assert i < len(lst) - assert lst[i].name == tp.name - assert len(lst) == len(self._struct_unions) - # same with enums - lst = self._lsts["enum"] - for tp, i in self._enums.items(): - assert i < len(lst) - assert lst[i].name == tp.name - assert len(lst) == len(self._enums) - - # ---------- - - def _prnt(self, what=''): - self._f.write(what + '\n') - - def write_source_to_f(self, f, preamble): - if self.target_is_python: - assert preamble is None - self.write_py_source_to_f(f) - else: - assert preamble is not None - self.write_c_source_to_f(f, preamble) - - def _rel_readlines(self, filename): - g = open(os.path.join(os.path.dirname(__file__), filename), 'r') - lines = g.readlines() - g.close() - return lines - - def write_c_source_to_f(self, f, preamble): - self._f = f - prnt = self._prnt - if self.ffi._embedding is not None: - prnt('#define _CFFI_USE_EMBEDDING') - if not USE_LIMITED_API: - prnt('#define _CFFI_NO_LIMITED_API') - # - # first the '#include' (actually done by inlining the file's content) - lines = self._rel_readlines('_cffi_include.h') - i = lines.index('#include "parse_c_type.h"\n') - lines[i:i+1] = self._rel_readlines('parse_c_type.h') - prnt(''.join(lines)) - # - # if we have ffi._embedding != None, we give it here as a macro - # and include an extra file - base_module_name = self.module_name.split('.')[-1] - if self.ffi._embedding is not None: - prnt('#define _CFFI_MODULE_NAME "%s"' % (self.module_name,)) - prnt('static const char _CFFI_PYTHON_STARTUP_CODE[] = {') - self._print_string_literal_in_array(self.ffi._embedding) - prnt('0 };') - prnt('#ifdef PYPY_VERSION') - prnt('# define _CFFI_PYTHON_STARTUP_FUNC _cffi_pypyinit_%s' % ( - base_module_name,)) - prnt('#elif PY_MAJOR_VERSION >= 3') - prnt('# define _CFFI_PYTHON_STARTUP_FUNC PyInit_%s' % ( - base_module_name,)) - prnt('#else') - prnt('# define _CFFI_PYTHON_STARTUP_FUNC init%s' % ( - base_module_name,)) - prnt('#endif') - lines = self._rel_readlines('_embedding.h') - i = lines.index('#include "_cffi_errors.h"\n') - lines[i:i+1] = self._rel_readlines('_cffi_errors.h') - prnt(''.join(lines)) - self.needs_version(VERSION_EMBEDDED) - # - # then paste the C source given by the user, verbatim. - prnt('/************************************************************/') - prnt() - prnt(preamble) - prnt() - prnt('/************************************************************/') - prnt() - # - # the declaration of '_cffi_types' - prnt('static void *_cffi_types[] = {') - typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()]) - for i, op in enumerate(self.cffi_types): - comment = '' - if i in typeindex2type: - comment = ' // ' + typeindex2type[i]._get_c_name() - prnt('/* %2d */ %s,%s' % (i, op.as_c_expr(), comment)) - if not self.cffi_types: - prnt(' 0') - prnt('};') - prnt() - # - # call generate_cpy_xxx_decl(), for every xxx found from - # ffi._parser._declarations. This generates all the functions. - self._seen_constants = set() - self._generate("decl") - # - # the declaration of '_cffi_globals' and '_cffi_typenames' - nums = {} - for step_name in self.ALL_STEPS: - lst = self._lsts[step_name] - nums[step_name] = len(lst) - if nums[step_name] > 0: - prnt('static const struct _cffi_%s_s _cffi_%ss[] = {' % ( - step_name, step_name)) - for entry in lst: - prnt(entry.as_c_expr()) - prnt('};') - prnt() - # - # the declaration of '_cffi_includes' - if self.ffi._included_ffis: - prnt('static const char * const _cffi_includes[] = {') - for ffi_to_include in self.ffi._included_ffis: - try: - included_module_name, included_source = ( - ffi_to_include._assigned_source[:2]) - except AttributeError: - raise VerificationError( - "ffi object %r includes %r, but the latter has not " - "been prepared with set_source()" % ( - self.ffi, ffi_to_include,)) - if included_source is None: - raise VerificationError( - "not implemented yet: ffi.include() of a Python-based " - "ffi inside a C-based ffi") - prnt(' "%s",' % (included_module_name,)) - prnt(' NULL') - prnt('};') - prnt() - # - # the declaration of '_cffi_type_context' - prnt('static const struct _cffi_type_context_s _cffi_type_context = {') - prnt(' _cffi_types,') - for step_name in self.ALL_STEPS: - if nums[step_name] > 0: - prnt(' _cffi_%ss,' % step_name) - else: - prnt(' NULL, /* no %ss */' % step_name) - for step_name in self.ALL_STEPS: - if step_name != "field": - prnt(' %d, /* num_%ss */' % (nums[step_name], step_name)) - if self.ffi._included_ffis: - prnt(' _cffi_includes,') - else: - prnt(' NULL, /* no includes */') - prnt(' %d, /* num_types */' % (len(self.cffi_types),)) - flags = 0 - if self._num_externpy > 0 or self.ffi._embedding is not None: - flags |= 1 # set to mean that we use extern "Python" - prnt(' %d, /* flags */' % flags) - prnt('};') - prnt() - # - # the init function - prnt('#ifdef __GNUC__') - prnt('# pragma GCC visibility push(default) /* for -fvisibility= */') - prnt('#endif') - prnt() - prnt('#ifdef PYPY_VERSION') - prnt('PyMODINIT_FUNC') - prnt('_cffi_pypyinit_%s(const void *p[])' % (base_module_name,)) - prnt('{') - if flags & 1: - prnt(' if (((intptr_t)p[0]) >= 0x0A03) {') - prnt(' _cffi_call_python_org = ' - '(void(*)(struct _cffi_externpy_s *, char *))p[1];') - prnt(' }') - prnt(' p[0] = (const void *)0x%x;' % self._version) - prnt(' p[1] = &_cffi_type_context;') - prnt('#if PY_MAJOR_VERSION >= 3') - prnt(' return NULL;') - prnt('#endif') - prnt('}') - # on Windows, distutils insists on putting init_cffi_xyz in - # 'export_symbols', so instead of fighting it, just give up and - # give it one - prnt('# ifdef _MSC_VER') - prnt(' PyMODINIT_FUNC') - prnt('# if PY_MAJOR_VERSION >= 3') - prnt(' PyInit_%s(void) { return NULL; }' % (base_module_name,)) - prnt('# else') - prnt(' init%s(void) { }' % (base_module_name,)) - prnt('# endif') - prnt('# endif') - prnt('#elif PY_MAJOR_VERSION >= 3') - prnt('PyMODINIT_FUNC') - prnt('PyInit_%s(void)' % (base_module_name,)) - prnt('{') - prnt(' return _cffi_init("%s", 0x%x, &_cffi_type_context);' % ( - self.module_name, self._version)) - prnt('}') - prnt('#else') - prnt('PyMODINIT_FUNC') - prnt('init%s(void)' % (base_module_name,)) - prnt('{') - prnt(' _cffi_init("%s", 0x%x, &_cffi_type_context);' % ( - self.module_name, self._version)) - prnt('}') - prnt('#endif') - prnt() - prnt('#ifdef __GNUC__') - prnt('# pragma GCC visibility pop') - prnt('#endif') - self._version = None - - def _to_py(self, x): - if isinstance(x, str): - return "b'%s'" % (x,) - if isinstance(x, (list, tuple)): - rep = [self._to_py(item) for item in x] - if len(rep) == 1: - rep.append('') - return "(%s)" % (','.join(rep),) - return x.as_python_expr() # Py2: unicode unexpected; Py3: bytes unexp. - - def write_py_source_to_f(self, f): - self._f = f - prnt = self._prnt - # - # header - prnt("# auto-generated file") - prnt("import _cffi_backend") - # - # the 'import' of the included ffis - num_includes = len(self.ffi._included_ffis or ()) - for i in range(num_includes): - ffi_to_include = self.ffi._included_ffis[i] - try: - included_module_name, included_source = ( - ffi_to_include._assigned_source[:2]) - except AttributeError: - raise VerificationError( - "ffi object %r includes %r, but the latter has not " - "been prepared with set_source()" % ( - self.ffi, ffi_to_include,)) - if included_source is not None: - raise VerificationError( - "not implemented yet: ffi.include() of a C-based " - "ffi inside a Python-based ffi") - prnt('from %s import ffi as _ffi%d' % (included_module_name, i)) - prnt() - prnt("ffi = _cffi_backend.FFI('%s'," % (self.module_name,)) - prnt(" _version = 0x%x," % (self._version,)) - self._version = None - # - # the '_types' keyword argument - self.cffi_types = tuple(self.cffi_types) # don't change any more - types_lst = [op.as_python_bytes() for op in self.cffi_types] - prnt(' _types = %s,' % (self._to_py(''.join(types_lst)),)) - typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()]) - # - # the keyword arguments from ALL_STEPS - for step_name in self.ALL_STEPS: - lst = self._lsts[step_name] - if len(lst) > 0 and step_name != "field": - prnt(' _%ss = %s,' % (step_name, self._to_py(lst))) - # - # the '_includes' keyword argument - if num_includes > 0: - prnt(' _includes = (%s,),' % ( - ', '.join(['_ffi%d' % i for i in range(num_includes)]),)) - # - # the footer - prnt(')') - - # ---------- - - def _gettypenum(self, type): - # a KeyError here is a bug. please report it! :-) - return self._typesdict[type] - - def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode): - extraarg = '' - if isinstance(tp, model.BasePrimitiveType) and not tp.is_complex_type(): - if tp.is_integer_type() and tp.name != '_Bool': - converter = '_cffi_to_c_int' - extraarg = ', %s' % tp.name - elif isinstance(tp, model.UnknownFloatType): - # don't check with is_float_type(): it may be a 'long - # double' here, and _cffi_to_c_double would loose precision - converter = '(%s)_cffi_to_c_double' % (tp.get_c_name(''),) - else: - cname = tp.get_c_name('') - converter = '(%s)_cffi_to_c_%s' % (cname, - tp.name.replace(' ', '_')) - if cname in ('char16_t', 'char32_t'): - self.needs_version(VERSION_CHAR16CHAR32) - errvalue = '-1' - # - elif isinstance(tp, model.PointerType): - self._convert_funcarg_to_c_ptr_or_array(tp, fromvar, - tovar, errcode) - return - # - elif (isinstance(tp, model.StructOrUnionOrEnum) or - isinstance(tp, model.BasePrimitiveType)): - # a struct (not a struct pointer) as a function argument; - # or, a complex (the same code works) - self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)' - % (tovar, self._gettypenum(tp), fromvar)) - self._prnt(' %s;' % errcode) - return - # - elif isinstance(tp, model.FunctionPtrType): - converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('') - extraarg = ', _cffi_type(%d)' % self._gettypenum(tp) - errvalue = 'NULL' - # - else: - raise NotImplementedError(tp) - # - self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg)) - self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % ( - tovar, tp.get_c_name(''), errvalue)) - self._prnt(' %s;' % errcode) - - def _extra_local_variables(self, tp, localvars, freelines): - if isinstance(tp, model.PointerType): - localvars.add('Py_ssize_t datasize') - localvars.add('struct _cffi_freeme_s *large_args_free = NULL') - freelines.add('if (large_args_free != NULL)' - ' _cffi_free_array_arguments(large_args_free);') - - def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): - self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') - self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( - self._gettypenum(tp), fromvar, tovar)) - self._prnt(' if (datasize != 0) {') - self._prnt(' %s = ((size_t)datasize) <= 640 ? ' - '(%s)alloca((size_t)datasize) : NULL;' % ( - tovar, tp.get_c_name(''))) - self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, ' - '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar)) - self._prnt(' datasize, &large_args_free) < 0)') - self._prnt(' %s;' % errcode) - self._prnt(' }') - - def _convert_expr_from_c(self, tp, var, context): - if isinstance(tp, model.BasePrimitiveType): - if tp.is_integer_type() and tp.name != '_Bool': - return '_cffi_from_c_int(%s, %s)' % (var, tp.name) - elif isinstance(tp, model.UnknownFloatType): - return '_cffi_from_c_double(%s)' % (var,) - elif tp.name != 'long double' and not tp.is_complex_type(): - cname = tp.name.replace(' ', '_') - if cname in ('char16_t', 'char32_t'): - self.needs_version(VERSION_CHAR16CHAR32) - return '_cffi_from_c_%s(%s)' % (cname, var) - else: - return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, (model.PointerType, model.FunctionPtrType)): - return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, model.ArrayType): - return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( - var, self._gettypenum(model.PointerType(tp.item))) - elif isinstance(tp, model.StructOrUnion): - if tp.fldnames is None: - raise TypeError("'%s' is used as %s, but is opaque" % ( - tp._get_c_name(), context)) - return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, model.EnumType): - return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - else: - raise NotImplementedError(tp) - - # ---------- - # typedefs - - def _typedef_type(self, tp, name): - return self._global_type(tp, "(*(%s *)0)" % (name,)) - - def _generate_cpy_typedef_collecttype(self, tp, name): - self._do_collect_type(self._typedef_type(tp, name)) - - def _generate_cpy_typedef_decl(self, tp, name): - pass - - def _typedef_ctx(self, tp, name): - type_index = self._typesdict[tp] - self._lsts["typename"].append(TypenameExpr(name, type_index)) - - def _generate_cpy_typedef_ctx(self, tp, name): - tp = self._typedef_type(tp, name) - self._typedef_ctx(tp, name) - if getattr(tp, "origin", None) == "unknown_type": - self._struct_ctx(tp, tp.name, approxname=None) - elif isinstance(tp, model.NamedPointerType): - self._struct_ctx(tp.totype, tp.totype.name, approxname=tp.name, - named_ptr=tp) - - # ---------- - # function declarations - - def _generate_cpy_function_collecttype(self, tp, name): - self._do_collect_type(tp.as_raw_function()) - if tp.ellipsis and not self.target_is_python: - self._do_collect_type(tp) - - def _generate_cpy_function_decl(self, tp, name): - assert not self.target_is_python - assert isinstance(tp, model.FunctionPtrType) - if tp.ellipsis: - # cannot support vararg functions better than this: check for its - # exact type (including the fixed arguments), and build it as a - # constant function pointer (no CPython wrapper) - self._generate_cpy_constant_decl(tp, name) - return - prnt = self._prnt - numargs = len(tp.args) - if numargs == 0: - argname = 'noarg' - elif numargs == 1: - argname = 'arg0' - else: - argname = 'args' - # - # ------------------------------ - # the 'd' version of the function, only for addressof(lib, 'func') - arguments = [] - call_arguments = [] - context = 'argument of %s' % name - for i, type in enumerate(tp.args): - arguments.append(type.get_c_name(' x%d' % i, context)) - call_arguments.append('x%d' % i) - repr_arguments = ', '.join(arguments) - repr_arguments = repr_arguments or 'void' - if tp.abi: - abi = tp.abi + ' ' - else: - abi = '' - name_and_arguments = '%s_cffi_d_%s(%s)' % (abi, name, repr_arguments) - prnt('static %s' % (tp.result.get_c_name(name_and_arguments),)) - prnt('{') - call_arguments = ', '.join(call_arguments) - result_code = 'return ' - if isinstance(tp.result, model.VoidType): - result_code = '' - prnt(' %s%s(%s);' % (result_code, name, call_arguments)) - prnt('}') - # - prnt('#ifndef PYPY_VERSION') # ------------------------------ - # - prnt('static PyObject *') - prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname)) - prnt('{') - # - context = 'argument of %s' % name - for i, type in enumerate(tp.args): - arg = type.get_c_name(' x%d' % i, context) - prnt(' %s;' % arg) - # - localvars = set() - freelines = set() - for type in tp.args: - self._extra_local_variables(type, localvars, freelines) - for decl in sorted(localvars): - prnt(' %s;' % (decl,)) - # - if not isinstance(tp.result, model.VoidType): - result_code = 'result = ' - context = 'result of %s' % name - result_decl = ' %s;' % tp.result.get_c_name(' result', context) - prnt(result_decl) - prnt(' PyObject *pyresult;') - else: - result_decl = None - result_code = '' - # - if len(tp.args) > 1: - rng = range(len(tp.args)) - for i in rng: - prnt(' PyObject *arg%d;' % i) - prnt() - prnt(' if (!PyArg_UnpackTuple(args, "%s", %d, %d, %s))' % ( - name, len(rng), len(rng), - ', '.join(['&arg%d' % i for i in rng]))) - prnt(' return NULL;') - prnt() - # - for i, type in enumerate(tp.args): - self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i, - 'return NULL') - prnt() - # - prnt(' Py_BEGIN_ALLOW_THREADS') - prnt(' _cffi_restore_errno();') - call_arguments = ['x%d' % i for i in range(len(tp.args))] - call_arguments = ', '.join(call_arguments) - prnt(' { %s%s(%s); }' % (result_code, name, call_arguments)) - prnt(' _cffi_save_errno();') - prnt(' Py_END_ALLOW_THREADS') - prnt() - # - prnt(' (void)self; /* unused */') - if numargs == 0: - prnt(' (void)noarg; /* unused */') - if result_code: - prnt(' pyresult = %s;' % - self._convert_expr_from_c(tp.result, 'result', 'result type')) - for freeline in freelines: - prnt(' ' + freeline) - prnt(' return pyresult;') - else: - for freeline in freelines: - prnt(' ' + freeline) - prnt(' Py_INCREF(Py_None);') - prnt(' return Py_None;') - prnt('}') - # - prnt('#else') # ------------------------------ - # - # the PyPy version: need to replace struct/union arguments with - # pointers, and if the result is a struct/union, insert a first - # arg that is a pointer to the result. We also do that for - # complex args and return type. - def need_indirection(type): - return (isinstance(type, model.StructOrUnion) or - (isinstance(type, model.PrimitiveType) and - type.is_complex_type())) - difference = False - arguments = [] - call_arguments = [] - context = 'argument of %s' % name - for i, type in enumerate(tp.args): - indirection = '' - if need_indirection(type): - indirection = '*' - difference = True - arg = type.get_c_name(' %sx%d' % (indirection, i), context) - arguments.append(arg) - call_arguments.append('%sx%d' % (indirection, i)) - tp_result = tp.result - if need_indirection(tp_result): - context = 'result of %s' % name - arg = tp_result.get_c_name(' *result', context) - arguments.insert(0, arg) - tp_result = model.void_type - result_decl = None - result_code = '*result = ' - difference = True - if difference: - repr_arguments = ', '.join(arguments) - repr_arguments = repr_arguments or 'void' - name_and_arguments = '%s_cffi_f_%s(%s)' % (abi, name, - repr_arguments) - prnt('static %s' % (tp_result.get_c_name(name_and_arguments),)) - prnt('{') - if result_decl: - prnt(result_decl) - call_arguments = ', '.join(call_arguments) - prnt(' { %s%s(%s); }' % (result_code, name, call_arguments)) - if result_decl: - prnt(' return result;') - prnt('}') - else: - prnt('# define _cffi_f_%s _cffi_d_%s' % (name, name)) - # - prnt('#endif') # ------------------------------ - prnt() - - def _generate_cpy_function_ctx(self, tp, name): - if tp.ellipsis and not self.target_is_python: - self._generate_cpy_constant_ctx(tp, name) - return - type_index = self._typesdict[tp.as_raw_function()] - numargs = len(tp.args) - if self.target_is_python: - meth_kind = OP_DLOPEN_FUNC - elif numargs == 0: - meth_kind = OP_CPYTHON_BLTN_N # 'METH_NOARGS' - elif numargs == 1: - meth_kind = OP_CPYTHON_BLTN_O # 'METH_O' - else: - meth_kind = OP_CPYTHON_BLTN_V # 'METH_VARARGS' - self._lsts["global"].append( - GlobalExpr(name, '_cffi_f_%s' % name, - CffiOp(meth_kind, type_index), - size='_cffi_d_%s' % name)) - - # ---------- - # named structs or unions - - def _field_type(self, tp_struct, field_name, tp_field): - if isinstance(tp_field, model.ArrayType): - actual_length = tp_field.length - if actual_length == '...': - ptr_struct_name = tp_struct.get_c_name('*') - actual_length = '_cffi_array_len(((%s)0)->%s)' % ( - ptr_struct_name, field_name) - tp_item = self._field_type(tp_struct, '%s[0]' % field_name, - tp_field.item) - tp_field = model.ArrayType(tp_item, actual_length) - return tp_field - - def _struct_collecttype(self, tp): - self._do_collect_type(tp) - if self.target_is_python: - # also requires nested anon struct/unions in ABI mode, recursively - for fldtype in tp.anonymous_struct_fields(): - self._struct_collecttype(fldtype) - - def _struct_decl(self, tp, cname, approxname): - if tp.fldtypes is None: - return - prnt = self._prnt - checkfuncname = '_cffi_checkfld_%s' % (approxname,) - prnt('_CFFI_UNUSED_FN') - prnt('static void %s(%s *p)' % (checkfuncname, cname)) - prnt('{') - prnt(' /* only to generate compile-time warnings or errors */') - prnt(' (void)p;') - for fname, ftype, fbitsize, fqual in self._enum_fields(tp): - try: - if ftype.is_integer_type() or fbitsize >= 0: - # accept all integers, but complain on float or double - if fname != '': - prnt(" (void)((p->%s) | 0); /* check that '%s.%s' is " - "an integer */" % (fname, cname, fname)) - continue - # only accept exactly the type declared, except that '[]' - # is interpreted as a '*' and so will match any array length. - # (It would also match '*', but that's harder to detect...) - while (isinstance(ftype, model.ArrayType) - and (ftype.length is None or ftype.length == '...')): - ftype = ftype.item - fname = fname + '[0]' - prnt(' { %s = &p->%s; (void)tmp; }' % ( - ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), - fname)) - except VerificationError as e: - prnt(' /* %s */' % str(e)) # cannot verify it, ignore - prnt('}') - prnt('struct _cffi_align_%s { char x; %s y; };' % (approxname, cname)) - prnt() - - def _struct_ctx(self, tp, cname, approxname, named_ptr=None): - type_index = self._typesdict[tp] - reason_for_not_expanding = None - flags = [] - if isinstance(tp, model.UnionType): - flags.append("_CFFI_F_UNION") - if tp.fldtypes is None: - flags.append("_CFFI_F_OPAQUE") - reason_for_not_expanding = "opaque" - if (tp not in self.ffi._parser._included_declarations and - (named_ptr is None or - named_ptr not in self.ffi._parser._included_declarations)): - if tp.fldtypes is None: - pass # opaque - elif tp.partial or any(tp.anonymous_struct_fields()): - pass # field layout obtained silently from the C compiler - else: - flags.append("_CFFI_F_CHECK_FIELDS") - if tp.packed: - if tp.packed > 1: - raise NotImplementedError( - "%r is declared with 'pack=%r'; only 0 or 1 are " - "supported in API mode (try to use \"...;\", which " - "does not require a 'pack' declaration)" % - (tp, tp.packed)) - flags.append("_CFFI_F_PACKED") - else: - flags.append("_CFFI_F_EXTERNAL") - reason_for_not_expanding = "external" - flags = '|'.join(flags) or '0' - c_fields = [] - if reason_for_not_expanding is None: - enumfields = list(self._enum_fields(tp)) - for fldname, fldtype, fbitsize, fqual in enumfields: - fldtype = self._field_type(tp, fldname, fldtype) - self._check_not_opaque(fldtype, - "field '%s.%s'" % (tp.name, fldname)) - # cname is None for _add_missing_struct_unions() only - op = OP_NOOP - if fbitsize >= 0: - op = OP_BITFIELD - size = '%d /* bits */' % fbitsize - elif cname is None or ( - isinstance(fldtype, model.ArrayType) and - fldtype.length is None): - size = '(size_t)-1' - else: - size = 'sizeof(((%s)0)->%s)' % ( - tp.get_c_name('*') if named_ptr is None - else named_ptr.name, - fldname) - if cname is None or fbitsize >= 0: - offset = '(size_t)-1' - elif named_ptr is not None: - offset = '(size_t)(((char *)&((%s)4096)->%s) - (char *)4096)' % ( - named_ptr.name, fldname) - else: - offset = 'offsetof(%s, %s)' % (tp.get_c_name(''), fldname) - c_fields.append( - FieldExpr(fldname, offset, size, fbitsize, - CffiOp(op, self._typesdict[fldtype]))) - first_field_index = len(self._lsts["field"]) - self._lsts["field"].extend(c_fields) - # - if cname is None: # unknown name, for _add_missing_struct_unions - size = '(size_t)-2' - align = -2 - comment = "unnamed" - else: - if named_ptr is not None: - size = 'sizeof(*(%s)0)' % (named_ptr.name,) - align = '-1 /* unknown alignment */' - else: - size = 'sizeof(%s)' % (cname,) - align = 'offsetof(struct _cffi_align_%s, y)' % (approxname,) - comment = None - else: - size = '(size_t)-1' - align = -1 - first_field_index = -1 - comment = reason_for_not_expanding - self._lsts["struct_union"].append( - StructUnionExpr(tp.name, type_index, flags, size, align, comment, - first_field_index, c_fields)) - self._seen_struct_unions.add(tp) - - def _check_not_opaque(self, tp, location): - while isinstance(tp, model.ArrayType): - tp = tp.item - if isinstance(tp, model.StructOrUnion) and tp.fldtypes is None: - raise TypeError( - "%s is of an opaque type (not declared in cdef())" % location) - - def _add_missing_struct_unions(self): - # not very nice, but some struct declarations might be missing - # because they don't have any known C name. Check that they are - # not partial (we can't complete or verify them!) and emit them - # anonymously. - lst = list(self._struct_unions.items()) - lst.sort(key=lambda tp_order: tp_order[1]) - for tp, order in lst: - if tp not in self._seen_struct_unions: - if tp.partial: - raise NotImplementedError("internal inconsistency: %r is " - "partial but was not seen at " - "this point" % (tp,)) - if tp.name.startswith('$') and tp.name[1:].isdigit(): - approxname = tp.name[1:] - elif tp.name == '_IO_FILE' and tp.forcename == 'FILE': - approxname = 'FILE' - self._typedef_ctx(tp, 'FILE') - else: - raise NotImplementedError("internal inconsistency: %r" % - (tp,)) - self._struct_ctx(tp, None, approxname) - - def _generate_cpy_struct_collecttype(self, tp, name): - self._struct_collecttype(tp) - _generate_cpy_union_collecttype = _generate_cpy_struct_collecttype - - def _struct_names(self, tp): - cname = tp.get_c_name('') - if ' ' in cname: - return cname, cname.replace(' ', '_') - else: - return cname, '_' + cname - - def _generate_cpy_struct_decl(self, tp, name): - self._struct_decl(tp, *self._struct_names(tp)) - _generate_cpy_union_decl = _generate_cpy_struct_decl - - def _generate_cpy_struct_ctx(self, tp, name): - self._struct_ctx(tp, *self._struct_names(tp)) - _generate_cpy_union_ctx = _generate_cpy_struct_ctx - - # ---------- - # 'anonymous' declarations. These are produced for anonymous structs - # or unions; the 'name' is obtained by a typedef. - - def _generate_cpy_anonymous_collecttype(self, tp, name): - if isinstance(tp, model.EnumType): - self._generate_cpy_enum_collecttype(tp, name) - else: - self._struct_collecttype(tp) - - def _generate_cpy_anonymous_decl(self, tp, name): - if isinstance(tp, model.EnumType): - self._generate_cpy_enum_decl(tp) - else: - self._struct_decl(tp, name, 'typedef_' + name) - - def _generate_cpy_anonymous_ctx(self, tp, name): - if isinstance(tp, model.EnumType): - self._enum_ctx(tp, name) - else: - self._struct_ctx(tp, name, 'typedef_' + name) - - # ---------- - # constants, declared with "static const ..." - - def _generate_cpy_const(self, is_int, name, tp=None, category='const', - check_value=None): - if (category, name) in self._seen_constants: - raise VerificationError( - "duplicate declaration of %s '%s'" % (category, name)) - self._seen_constants.add((category, name)) - # - prnt = self._prnt - funcname = '_cffi_%s_%s' % (category, name) - if is_int: - prnt('static int %s(unsigned long long *o)' % funcname) - prnt('{') - prnt(' int n = (%s) <= 0;' % (name,)) - prnt(' *o = (unsigned long long)((%s) | 0);' - ' /* check that %s is an integer */' % (name, name)) - if check_value is not None: - if check_value > 0: - check_value = '%dU' % (check_value,) - prnt(' if (!_cffi_check_int(*o, n, %s))' % (check_value,)) - prnt(' n |= 2;') - prnt(' return n;') - prnt('}') - else: - assert check_value is None - prnt('static void %s(char *o)' % funcname) - prnt('{') - prnt(' *(%s)o = %s;' % (tp.get_c_name('*'), name)) - prnt('}') - prnt() - - def _generate_cpy_constant_collecttype(self, tp, name): - is_int = tp.is_integer_type() - if not is_int or self.target_is_python: - self._do_collect_type(tp) - - def _generate_cpy_constant_decl(self, tp, name): - is_int = tp.is_integer_type() - self._generate_cpy_const(is_int, name, tp) - - def _generate_cpy_constant_ctx(self, tp, name): - if not self.target_is_python and tp.is_integer_type(): - type_op = CffiOp(OP_CONSTANT_INT, -1) - else: - if self.target_is_python: - const_kind = OP_DLOPEN_CONST - else: - const_kind = OP_CONSTANT - type_index = self._typesdict[tp] - type_op = CffiOp(const_kind, type_index) - self._lsts["global"].append( - GlobalExpr(name, '_cffi_const_%s' % name, type_op)) - - # ---------- - # enums - - def _generate_cpy_enum_collecttype(self, tp, name): - self._do_collect_type(tp) - - def _generate_cpy_enum_decl(self, tp, name=None): - for enumerator in tp.enumerators: - self._generate_cpy_const(True, enumerator) - - def _enum_ctx(self, tp, cname): - type_index = self._typesdict[tp] - type_op = CffiOp(OP_ENUM, -1) - if self.target_is_python: - tp.check_not_partial() - for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): - self._lsts["global"].append( - GlobalExpr(enumerator, '_cffi_const_%s' % enumerator, type_op, - check_value=enumvalue)) - # - if cname is not None and '$' not in cname and not self.target_is_python: - size = "sizeof(%s)" % cname - signed = "((%s)-1) <= 0" % cname - else: - basetp = tp.build_baseinttype(self.ffi, []) - size = self.ffi.sizeof(basetp) - signed = int(int(self.ffi.cast(basetp, -1)) < 0) - allenums = ",".join(tp.enumerators) - self._lsts["enum"].append( - EnumExpr(tp.name, type_index, size, signed, allenums)) - - def _generate_cpy_enum_ctx(self, tp, name): - self._enum_ctx(tp, tp._get_c_name()) - - # ---------- - # macros: for now only for integers - - def _generate_cpy_macro_collecttype(self, tp, name): - pass - - def _generate_cpy_macro_decl(self, tp, name): - if tp == '...': - check_value = None - else: - check_value = tp # an integer - self._generate_cpy_const(True, name, check_value=check_value) - - def _generate_cpy_macro_ctx(self, tp, name): - if tp == '...': - if self.target_is_python: - raise VerificationError( - "cannot use the syntax '...' in '#define %s ...' when " - "using the ABI mode" % (name,)) - check_value = None - else: - check_value = tp # an integer - type_op = CffiOp(OP_CONSTANT_INT, -1) - self._lsts["global"].append( - GlobalExpr(name, '_cffi_const_%s' % name, type_op, - check_value=check_value)) - - # ---------- - # global variables - - def _global_type(self, tp, global_name): - if isinstance(tp, model.ArrayType): - actual_length = tp.length - if actual_length == '...': - actual_length = '_cffi_array_len(%s)' % (global_name,) - tp_item = self._global_type(tp.item, '%s[0]' % global_name) - tp = model.ArrayType(tp_item, actual_length) - return tp - - def _generate_cpy_variable_collecttype(self, tp, name): - self._do_collect_type(self._global_type(tp, name)) - - def _generate_cpy_variable_decl(self, tp, name): - prnt = self._prnt - tp = self._global_type(tp, name) - if isinstance(tp, model.ArrayType) and tp.length is None: - tp = tp.item - ampersand = '' - else: - ampersand = '&' - # This code assumes that casts from "tp *" to "void *" is a - # no-op, i.e. a function that returns a "tp *" can be called - # as if it returned a "void *". This should be generally true - # on any modern machine. The only exception to that rule (on - # uncommon architectures, and as far as I can tell) might be - # if 'tp' were a function type, but that is not possible here. - # (If 'tp' is a function _pointer_ type, then casts from "fn_t - # **" to "void *" are again no-ops, as far as I can tell.) - decl = '*_cffi_var_%s(void)' % (name,) - prnt('static ' + tp.get_c_name(decl, quals=self._current_quals)) - prnt('{') - prnt(' return %s(%s);' % (ampersand, name)) - prnt('}') - prnt() - - def _generate_cpy_variable_ctx(self, tp, name): - tp = self._global_type(tp, name) - type_index = self._typesdict[tp] - if self.target_is_python: - op = OP_GLOBAL_VAR - else: - op = OP_GLOBAL_VAR_F - self._lsts["global"].append( - GlobalExpr(name, '_cffi_var_%s' % name, CffiOp(op, type_index))) - - # ---------- - # extern "Python" - - def _generate_cpy_extern_python_collecttype(self, tp, name): - assert isinstance(tp, model.FunctionPtrType) - self._do_collect_type(tp) - _generate_cpy_dllexport_python_collecttype = \ - _generate_cpy_extern_python_plus_c_collecttype = \ - _generate_cpy_extern_python_collecttype - - def _extern_python_decl(self, tp, name, tag_and_space): - prnt = self._prnt - if isinstance(tp.result, model.VoidType): - size_of_result = '0' - else: - context = 'result of %s' % name - size_of_result = '(int)sizeof(%s)' % ( - tp.result.get_c_name('', context),) - prnt('static struct _cffi_externpy_s _cffi_externpy__%s =' % name) - prnt(' { "%s.%s", %s, 0, 0 };' % ( - self.module_name, name, size_of_result)) - prnt() - # - arguments = [] - context = 'argument of %s' % name - for i, type in enumerate(tp.args): - arg = type.get_c_name(' a%d' % i, context) - arguments.append(arg) - # - repr_arguments = ', '.join(arguments) - repr_arguments = repr_arguments or 'void' - name_and_arguments = '%s(%s)' % (name, repr_arguments) - if tp.abi == "__stdcall": - name_and_arguments = '_cffi_stdcall ' + name_and_arguments - # - def may_need_128_bits(tp): - return (isinstance(tp, model.PrimitiveType) and - tp.name == 'long double') - # - size_of_a = max(len(tp.args)*8, 8) - if may_need_128_bits(tp.result): - size_of_a = max(size_of_a, 16) - if isinstance(tp.result, model.StructOrUnion): - size_of_a = 'sizeof(%s) > %d ? sizeof(%s) : %d' % ( - tp.result.get_c_name(''), size_of_a, - tp.result.get_c_name(''), size_of_a) - prnt('%s%s' % (tag_and_space, tp.result.get_c_name(name_and_arguments))) - prnt('{') - prnt(' char a[%s];' % size_of_a) - prnt(' char *p = a;') - for i, type in enumerate(tp.args): - arg = 'a%d' % i - if (isinstance(type, model.StructOrUnion) or - may_need_128_bits(type)): - arg = '&' + arg - type = model.PointerType(type) - prnt(' *(%s)(p + %d) = %s;' % (type.get_c_name('*'), i*8, arg)) - prnt(' _cffi_call_python(&_cffi_externpy__%s, p);' % name) - if not isinstance(tp.result, model.VoidType): - prnt(' return *(%s)p;' % (tp.result.get_c_name('*'),)) - prnt('}') - prnt() - self._num_externpy += 1 - - def _generate_cpy_extern_python_decl(self, tp, name): - self._extern_python_decl(tp, name, 'static ') - - def _generate_cpy_dllexport_python_decl(self, tp, name): - self._extern_python_decl(tp, name, 'CFFI_DLLEXPORT ') - - def _generate_cpy_extern_python_plus_c_decl(self, tp, name): - self._extern_python_decl(tp, name, '') - - def _generate_cpy_extern_python_ctx(self, tp, name): - if self.target_is_python: - raise VerificationError( - "cannot use 'extern \"Python\"' in the ABI mode") - if tp.ellipsis: - raise NotImplementedError("a vararg function is extern \"Python\"") - type_index = self._typesdict[tp] - type_op = CffiOp(OP_EXTERN_PYTHON, type_index) - self._lsts["global"].append( - GlobalExpr(name, '&_cffi_externpy__%s' % name, type_op, name)) - - _generate_cpy_dllexport_python_ctx = \ - _generate_cpy_extern_python_plus_c_ctx = \ - _generate_cpy_extern_python_ctx - - def _print_string_literal_in_array(self, s): - prnt = self._prnt - prnt('// # NB. this is not a string because of a size limit in MSVC') - if not isinstance(s, bytes): # unicode - s = s.encode('utf-8') # -> bytes - else: - s.decode('utf-8') # got bytes, check for valid utf-8 - try: - s.decode('ascii') - except UnicodeDecodeError: - s = b'# -*- encoding: utf8 -*-\n' + s - for line in s.splitlines(True): - comment = line - if type('//') is bytes: # python2 - line = map(ord, line) # make a list of integers - else: # python3 - # type(line) is bytes, which enumerates like a list of integers - comment = ascii(comment)[1:-1] - prnt(('// ' + comment).rstrip()) - printed_line = '' - for c in line: - if len(printed_line) >= 76: - prnt(printed_line) - printed_line = '' - printed_line += '%d,' % (c,) - prnt(printed_line) - - # ---------- - # emitting the opcodes for individual types - - def _emit_bytecode_VoidType(self, tp, index): - self.cffi_types[index] = CffiOp(OP_PRIMITIVE, PRIM_VOID) - - def _emit_bytecode_PrimitiveType(self, tp, index): - prim_index = PRIMITIVE_TO_INDEX[tp.name] - self.cffi_types[index] = CffiOp(OP_PRIMITIVE, prim_index) - - def _emit_bytecode_UnknownIntegerType(self, tp, index): - s = ('_cffi_prim_int(sizeof(%s), (\n' - ' ((%s)-1) | 0 /* check that %s is an integer type */\n' - ' ) <= 0)' % (tp.name, tp.name, tp.name)) - self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s) - - def _emit_bytecode_UnknownFloatType(self, tp, index): - s = ('_cffi_prim_float(sizeof(%s) *\n' - ' (((%s)1) / 2) * 2 /* integer => 0, float => 1 */\n' - ' )' % (tp.name, tp.name)) - self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s) - - def _emit_bytecode_RawFunctionType(self, tp, index): - self.cffi_types[index] = CffiOp(OP_FUNCTION, self._typesdict[tp.result]) - index += 1 - for tp1 in tp.args: - realindex = self._typesdict[tp1] - if index != realindex: - if isinstance(tp1, model.PrimitiveType): - self._emit_bytecode_PrimitiveType(tp1, index) - else: - self.cffi_types[index] = CffiOp(OP_NOOP, realindex) - index += 1 - flags = int(tp.ellipsis) - if tp.abi is not None: - if tp.abi == '__stdcall': - flags |= 2 - else: - raise NotImplementedError("abi=%r" % (tp.abi,)) - self.cffi_types[index] = CffiOp(OP_FUNCTION_END, flags) - - def _emit_bytecode_PointerType(self, tp, index): - self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[tp.totype]) - - _emit_bytecode_ConstPointerType = _emit_bytecode_PointerType - _emit_bytecode_NamedPointerType = _emit_bytecode_PointerType - - def _emit_bytecode_FunctionPtrType(self, tp, index): - raw = tp.as_raw_function() - self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[raw]) - - def _emit_bytecode_ArrayType(self, tp, index): - item_index = self._typesdict[tp.item] - if tp.length is None: - self.cffi_types[index] = CffiOp(OP_OPEN_ARRAY, item_index) - elif tp.length == '...': - raise VerificationError( - "type %s badly placed: the '...' array length can only be " - "used on global arrays or on fields of structures" % ( - str(tp).replace('/*...*/', '...'),)) - else: - assert self.cffi_types[index + 1] == 'LEN' - self.cffi_types[index] = CffiOp(OP_ARRAY, item_index) - self.cffi_types[index + 1] = CffiOp(None, str(tp.length)) - - def _emit_bytecode_StructType(self, tp, index): - struct_index = self._struct_unions[tp] - self.cffi_types[index] = CffiOp(OP_STRUCT_UNION, struct_index) - _emit_bytecode_UnionType = _emit_bytecode_StructType - - def _emit_bytecode_EnumType(self, tp, index): - enum_index = self._enums[tp] - self.cffi_types[index] = CffiOp(OP_ENUM, enum_index) - - -if sys.version_info >= (3,): - NativeIO = io.StringIO -else: - class NativeIO(io.BytesIO): - def write(self, s): - if isinstance(s, unicode): - s = s.encode('ascii') - super(NativeIO, self).write(s) - -def _is_file_like(maybefile): - # compare to xml.etree.ElementTree._get_writer - return hasattr(maybefile, 'write') - -def _make_c_or_py_source(ffi, module_name, preamble, target_file, verbose): - if verbose: - print("generating %s" % (target_file,)) - recompiler = Recompiler(ffi, module_name, - target_is_python=(preamble is None)) - recompiler.collect_type_table() - recompiler.collect_step_tables() - if _is_file_like(target_file): - recompiler.write_source_to_f(target_file, preamble) - return True - f = NativeIO() - recompiler.write_source_to_f(f, preamble) - output = f.getvalue() - try: - with open(target_file, 'r') as f1: - if f1.read(len(output) + 1) != output: - raise IOError - if verbose: - print("(already up-to-date)") - return False # already up-to-date - except IOError: - tmp_file = '%s.~%d' % (target_file, os.getpid()) - with open(tmp_file, 'w') as f1: - f1.write(output) - try: - os.rename(tmp_file, target_file) - except OSError: - os.unlink(target_file) - os.rename(tmp_file, target_file) - return True - -def make_c_source(ffi, module_name, preamble, target_c_file, verbose=False): - assert preamble is not None - return _make_c_or_py_source(ffi, module_name, preamble, target_c_file, - verbose) - -def make_py_source(ffi, module_name, target_py_file, verbose=False): - return _make_c_or_py_source(ffi, module_name, None, target_py_file, - verbose) - -def _modname_to_file(outputdir, modname, extension): - parts = modname.split('.') - try: - os.makedirs(os.path.join(outputdir, *parts[:-1])) - except OSError: - pass - parts[-1] += extension - return os.path.join(outputdir, *parts), parts - - -# Aaargh. Distutils is not tested at all for the purpose of compiling -# DLLs that are not extension modules. Here are some hacks to work -# around that, in the _patch_for_*() functions... - -def _patch_meth(patchlist, cls, name, new_meth): - old = getattr(cls, name) - patchlist.append((cls, name, old)) - setattr(cls, name, new_meth) - return old - -def _unpatch_meths(patchlist): - for cls, name, old_meth in reversed(patchlist): - setattr(cls, name, old_meth) - -def _patch_for_embedding(patchlist): - if sys.platform == 'win32': - # we must not remove the manifest when building for embedding! - # FUTURE: this module was removed in setuptools 74; this is likely dead code and should be removed, - # since the toolchain it supports (VS2005-2008) is also long dead. - from cffi._shimmed_dist_utils import MSVCCompiler - if MSVCCompiler is not None: - _patch_meth(patchlist, MSVCCompiler, '_remove_visual_c_ref', - lambda self, manifest_file: manifest_file) - - if sys.platform == 'darwin': - # we must not make a '-bundle', but a '-dynamiclib' instead - from cffi._shimmed_dist_utils import CCompiler - def my_link_shared_object(self, *args, **kwds): - if '-bundle' in self.linker_so: - self.linker_so = list(self.linker_so) - i = self.linker_so.index('-bundle') - self.linker_so[i] = '-dynamiclib' - return old_link_shared_object(self, *args, **kwds) - old_link_shared_object = _patch_meth(patchlist, CCompiler, - 'link_shared_object', - my_link_shared_object) - -def _patch_for_target(patchlist, target): - from cffi._shimmed_dist_utils import build_ext - # if 'target' is different from '*', we need to patch some internal - # method to just return this 'target' value, instead of having it - # built from module_name - if target.endswith('.*'): - target = target[:-2] - if sys.platform == 'win32': - target += '.dll' - elif sys.platform == 'darwin': - target += '.dylib' - else: - target += '.so' - _patch_meth(patchlist, build_ext, 'get_ext_filename', - lambda self, ext_name: target) - - -def recompile(ffi, module_name, preamble, tmpdir='.', call_c_compiler=True, - c_file=None, source_extension='.c', extradir=None, - compiler_verbose=1, target=None, debug=None, - uses_ffiplatform=True, **kwds): - if not isinstance(module_name, str): - module_name = module_name.encode('ascii') - if ffi._windows_unicode: - ffi._apply_windows_unicode(kwds) - if preamble is not None: - if call_c_compiler and _is_file_like(c_file): - raise TypeError("Writing to file-like objects is not supported " - "with call_c_compiler=True") - embedding = (ffi._embedding is not None) - if embedding: - ffi._apply_embedding_fix(kwds) - if c_file is None: - c_file, parts = _modname_to_file(tmpdir, module_name, - source_extension) - if extradir: - parts = [extradir] + parts - ext_c_file = os.path.join(*parts) - else: - ext_c_file = c_file - # - if target is None: - if embedding: - target = '%s.*' % module_name - else: - target = '*' - # - if uses_ffiplatform: - ext = ffiplatform.get_extension(ext_c_file, module_name, **kwds) - else: - ext = None - updated = make_c_source(ffi, module_name, preamble, c_file, - verbose=compiler_verbose) - if call_c_compiler: - patchlist = [] - cwd = os.getcwd() - try: - if embedding: - _patch_for_embedding(patchlist) - if target != '*': - _patch_for_target(patchlist, target) - if compiler_verbose: - if tmpdir == '.': - msg = 'the current directory is' - else: - msg = 'setting the current directory to' - print('%s %r' % (msg, os.path.abspath(tmpdir))) - os.chdir(tmpdir) - outputfilename = ffiplatform.compile('.', ext, - compiler_verbose, debug) - finally: - os.chdir(cwd) - _unpatch_meths(patchlist) - return outputfilename - else: - return ext, updated - else: - if c_file is None: - c_file, _ = _modname_to_file(tmpdir, module_name, '.py') - updated = make_py_source(ffi, module_name, c_file, - verbose=compiler_verbose) - if call_c_compiler: - return c_file - else: - return None, updated - diff --git a/notification-service/venv/Lib/site-packages/cffi/setuptools_ext.py b/notification-service/venv/Lib/site-packages/cffi/setuptools_ext.py deleted file mode 100644 index 5cdd246..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/setuptools_ext.py +++ /dev/null @@ -1,229 +0,0 @@ -import os -import sys -import sysconfig - -try: - basestring -except NameError: - # Python 3.x - basestring = str - -def error(msg): - from cffi._shimmed_dist_utils import DistutilsSetupError - raise DistutilsSetupError(msg) - - -def execfile(filename, glob): - # We use execfile() (here rewritten for Python 3) instead of - # __import__() to load the build script. The problem with - # a normal import is that in some packages, the intermediate - # __init__.py files may already try to import the file that - # we are generating. - with open(filename) as f: - src = f.read() - src += '\n' # Python 2.6 compatibility - code = compile(src, filename, 'exec') - exec(code, glob, glob) - - -def add_cffi_module(dist, mod_spec): - from cffi.api import FFI - - if not isinstance(mod_spec, basestring): - error("argument to 'cffi_modules=...' must be a str or a list of str," - " not %r" % (type(mod_spec).__name__,)) - mod_spec = str(mod_spec) - try: - build_file_name, ffi_var_name = mod_spec.split(':') - except ValueError: - error("%r must be of the form 'path/build.py:ffi_variable'" % - (mod_spec,)) - if not os.path.exists(build_file_name): - ext = '' - rewritten = build_file_name.replace('.', '/') + '.py' - if os.path.exists(rewritten): - ext = ' (rewrite cffi_modules to [%r])' % ( - rewritten + ':' + ffi_var_name,) - error("%r does not name an existing file%s" % (build_file_name, ext)) - - mod_vars = {'__name__': '__cffi__', '__file__': build_file_name} - execfile(build_file_name, mod_vars) - - try: - ffi = mod_vars[ffi_var_name] - except KeyError: - error("%r: object %r not found in module" % (mod_spec, - ffi_var_name)) - if not isinstance(ffi, FFI): - ffi = ffi() # maybe it's a function instead of directly an ffi - if not isinstance(ffi, FFI): - error("%r is not an FFI instance (got %r)" % (mod_spec, - type(ffi).__name__)) - if not hasattr(ffi, '_assigned_source'): - error("%r: the set_source() method was not called" % (mod_spec,)) - module_name, source, source_extension, kwds = ffi._assigned_source - if ffi._windows_unicode: - kwds = kwds.copy() - ffi._apply_windows_unicode(kwds) - - if source is None: - _add_py_module(dist, ffi, module_name) - else: - _add_c_module(dist, ffi, module_name, source, source_extension, kwds) - -def _set_py_limited_api(Extension, kwds): - """ - Add py_limited_api to kwds if setuptools >= 26 is in use. - Do not alter the setting if it already exists. - Setuptools takes care of ignoring the flag on Python 2 and PyPy. - - CPython itself should ignore the flag in a debugging version - (by not listing .abi3.so in the extensions it supports), but - it doesn't so far, creating troubles. That's why we check - for "not hasattr(sys, 'gettotalrefcount')" (the 2.7 compatible equivalent - of 'd' not in sys.abiflags). (http://bugs.python.org/issue28401) - - On Windows, with CPython <= 3.4, it's better not to use py_limited_api - because virtualenv *still* doesn't copy PYTHON3.DLL on these versions. - Recently (2020) we started shipping only >= 3.5 wheels, though. So - we'll give it another try and set py_limited_api on Windows >= 3.5. - """ - from cffi._shimmed_dist_utils import log - from cffi import recompiler - - if ('py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount') - and recompiler.USE_LIMITED_API): - import setuptools - try: - setuptools_major_version = int(setuptools.__version__.partition('.')[0]) - if setuptools_major_version >= 26: - kwds['py_limited_api'] = True - except ValueError: # certain development versions of setuptools - # If we don't know the version number of setuptools, we - # try to set 'py_limited_api' anyway. At worst, we get a - # warning. - kwds['py_limited_api'] = True - - if sysconfig.get_config_var("Py_GIL_DISABLED"): - if kwds.get('py_limited_api'): - log.info("Ignoring py_limited_api=True for free-threaded build.") - - kwds['py_limited_api'] = False - - if kwds.get('py_limited_api') is False: - # avoid setting Py_LIMITED_API if py_limited_api=False - # which _cffi_include.h does unless _CFFI_NO_LIMITED_API is defined - kwds.setdefault("define_macros", []).append(("_CFFI_NO_LIMITED_API", None)) - return kwds - -def _add_c_module(dist, ffi, module_name, source, source_extension, kwds): - # We are a setuptools extension. Need this build_ext for py_limited_api. - from setuptools.command.build_ext import build_ext - from cffi._shimmed_dist_utils import Extension, log, mkpath - from cffi import recompiler - - allsources = ['$PLACEHOLDER'] - allsources.extend(kwds.pop('sources', [])) - kwds = _set_py_limited_api(Extension, kwds) - ext = Extension(name=module_name, sources=allsources, **kwds) - - def make_mod(tmpdir, pre_run=None): - c_file = os.path.join(tmpdir, module_name + source_extension) - log.info("generating cffi module %r" % c_file) - mkpath(tmpdir) - # a setuptools-only, API-only hook: called with the "ext" and "ffi" - # arguments just before we turn the ffi into C code. To use it, - # subclass the 'distutils.command.build_ext.build_ext' class and - # add a method 'def pre_run(self, ext, ffi)'. - if pre_run is not None: - pre_run(ext, ffi) - updated = recompiler.make_c_source(ffi, module_name, source, c_file) - if not updated: - log.info("already up-to-date") - return c_file - - if dist.ext_modules is None: - dist.ext_modules = [] - dist.ext_modules.append(ext) - - base_class = dist.cmdclass.get('build_ext', build_ext) - class build_ext_make_mod(base_class): - def run(self): - if ext.sources[0] == '$PLACEHOLDER': - pre_run = getattr(self, 'pre_run', None) - ext.sources[0] = make_mod(self.build_temp, pre_run) - base_class.run(self) - dist.cmdclass['build_ext'] = build_ext_make_mod - # NB. multiple runs here will create multiple 'build_ext_make_mod' - # classes. Even in this case the 'build_ext' command should be - # run once; but just in case, the logic above does nothing if - # called again. - - -def _add_py_module(dist, ffi, module_name): - from setuptools.command.build_py import build_py - from setuptools.command.build_ext import build_ext - from cffi._shimmed_dist_utils import log, mkpath - from cffi import recompiler - - def generate_mod(py_file): - log.info("generating cffi module %r" % py_file) - mkpath(os.path.dirname(py_file)) - updated = recompiler.make_py_source(ffi, module_name, py_file) - if not updated: - log.info("already up-to-date") - - base_class = dist.cmdclass.get('build_py', build_py) - class build_py_make_mod(base_class): - def run(self): - base_class.run(self) - module_path = module_name.split('.') - module_path[-1] += '.py' - generate_mod(os.path.join(self.build_lib, *module_path)) - def get_source_files(self): - # This is called from 'setup.py sdist' only. Exclude - # the generate .py module in this case. - saved_py_modules = self.py_modules - try: - if saved_py_modules: - self.py_modules = [m for m in saved_py_modules - if m != module_name] - return base_class.get_source_files(self) - finally: - self.py_modules = saved_py_modules - dist.cmdclass['build_py'] = build_py_make_mod - - # distutils and setuptools have no notion I could find of a - # generated python module. If we don't add module_name to - # dist.py_modules, then things mostly work but there are some - # combination of options (--root and --record) that will miss - # the module. So we add it here, which gives a few apparently - # harmless warnings about not finding the file outside the - # build directory. - # Then we need to hack more in get_source_files(); see above. - if dist.py_modules is None: - dist.py_modules = [] - dist.py_modules.append(module_name) - - # the following is only for "build_ext -i" - base_class_2 = dist.cmdclass.get('build_ext', build_ext) - class build_ext_make_mod(base_class_2): - def run(self): - base_class_2.run(self) - if self.inplace: - # from get_ext_fullpath() in distutils/command/build_ext.py - module_path = module_name.split('.') - package = '.'.join(module_path[:-1]) - build_py = self.get_finalized_command('build_py') - package_dir = build_py.get_package_dir(package) - file_name = module_path[-1] + '.py' - generate_mod(os.path.join(package_dir, file_name)) - dist.cmdclass['build_ext'] = build_ext_make_mod - -def cffi_modules(dist, attr, value): - assert attr == 'cffi_modules' - if isinstance(value, basestring): - value = [value] - - for cffi_module in value: - add_cffi_module(dist, cffi_module) diff --git a/notification-service/venv/Lib/site-packages/cffi/vengine_cpy.py b/notification-service/venv/Lib/site-packages/cffi/vengine_cpy.py deleted file mode 100644 index 02e6a47..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/vengine_cpy.py +++ /dev/null @@ -1,1087 +0,0 @@ -# -# DEPRECATED: implementation for ffi.verify() -# -import sys -from . import model -from .error import VerificationError -from . import _imp_emulation as imp - - -class VCPythonEngine(object): - _class_key = 'x' - _gen_python_module = True - - def __init__(self, verifier): - self.verifier = verifier - self.ffi = verifier.ffi - self._struct_pending_verification = {} - self._types_of_builtin_functions = {} - - def patch_extension_kwds(self, kwds): - pass - - def find_module(self, module_name, path, so_suffixes): - try: - f, filename, descr = imp.find_module(module_name, path) - except ImportError: - return None - if f is not None: - f.close() - # Note that after a setuptools installation, there are both .py - # and .so files with the same basename. The code here relies on - # imp.find_module() locating the .so in priority. - if descr[0] not in so_suffixes: - return None - return filename - - def collect_types(self): - self._typesdict = {} - self._generate("collecttype") - - def _prnt(self, what=''): - self._f.write(what + '\n') - - def _gettypenum(self, type): - # a KeyError here is a bug. please report it! :-) - return self._typesdict[type] - - def _do_collect_type(self, tp): - if ((not isinstance(tp, model.PrimitiveType) - or tp.name == 'long double') - and tp not in self._typesdict): - num = len(self._typesdict) - self._typesdict[tp] = num - - def write_source_to_f(self): - self.collect_types() - # - # The new module will have a _cffi_setup() function that receives - # objects from the ffi world, and that calls some setup code in - # the module. This setup code is split in several independent - # functions, e.g. one per constant. The functions are "chained" - # by ending in a tail call to each other. - # - # This is further split in two chained lists, depending on if we - # can do it at import-time or if we must wait for _cffi_setup() to - # provide us with the objects. This is needed because we - # need the values of the enum constants in order to build the - # that we may have to pass to _cffi_setup(). - # - # The following two 'chained_list_constants' items contains - # the head of these two chained lists, as a string that gives the - # call to do, if any. - self._chained_list_constants = ['((void)lib,0)', '((void)lib,0)'] - # - prnt = self._prnt - # first paste some standard set of lines that are mostly '#define' - prnt(cffimod_header) - prnt() - # then paste the C source given by the user, verbatim. - prnt(self.verifier.preamble) - prnt() - # - # call generate_cpy_xxx_decl(), for every xxx found from - # ffi._parser._declarations. This generates all the functions. - self._generate("decl") - # - # implement the function _cffi_setup_custom() as calling the - # head of the chained list. - self._generate_setup_custom() - prnt() - # - # produce the method table, including the entries for the - # generated Python->C function wrappers, which are done - # by generate_cpy_function_method(). - prnt('static PyMethodDef _cffi_methods[] = {') - self._generate("method") - prnt(' {"_cffi_setup", _cffi_setup, METH_VARARGS, NULL},') - prnt(' {NULL, NULL, 0, NULL} /* Sentinel */') - prnt('};') - prnt() - # - # standard init. - modname = self.verifier.get_module_name() - constants = self._chained_list_constants[False] - prnt('#if PY_MAJOR_VERSION >= 3') - prnt() - prnt('static struct PyModuleDef _cffi_module_def = {') - prnt(' PyModuleDef_HEAD_INIT,') - prnt(' "%s",' % modname) - prnt(' NULL,') - prnt(' -1,') - prnt(' _cffi_methods,') - prnt(' NULL, NULL, NULL, NULL') - prnt('};') - prnt() - prnt('PyMODINIT_FUNC') - prnt('PyInit_%s(void)' % modname) - prnt('{') - prnt(' PyObject *lib;') - prnt(' lib = PyModule_Create(&_cffi_module_def);') - prnt(' if (lib == NULL)') - prnt(' return NULL;') - prnt(' if (%s < 0 || _cffi_init() < 0) {' % (constants,)) - prnt(' Py_DECREF(lib);') - prnt(' return NULL;') - prnt(' }') - prnt('#if Py_GIL_DISABLED') - prnt(' PyUnstable_Module_SetGIL(lib, Py_MOD_GIL_NOT_USED);') - prnt('#endif') - prnt(' return lib;') - prnt('}') - prnt() - prnt('#else') - prnt() - prnt('PyMODINIT_FUNC') - prnt('init%s(void)' % modname) - prnt('{') - prnt(' PyObject *lib;') - prnt(' lib = Py_InitModule("%s", _cffi_methods);' % modname) - prnt(' if (lib == NULL)') - prnt(' return;') - prnt(' if (%s < 0 || _cffi_init() < 0)' % (constants,)) - prnt(' return;') - prnt(' return;') - prnt('}') - prnt() - prnt('#endif') - - def load_library(self, flags=None): - # XXX review all usages of 'self' here! - # import it as a new extension module - imp.acquire_lock() - try: - if hasattr(sys, "getdlopenflags"): - previous_flags = sys.getdlopenflags() - try: - if hasattr(sys, "setdlopenflags") and flags is not None: - sys.setdlopenflags(flags) - module = imp.load_dynamic(self.verifier.get_module_name(), - self.verifier.modulefilename) - except ImportError as e: - error = "importing %r: %s" % (self.verifier.modulefilename, e) - raise VerificationError(error) - finally: - if hasattr(sys, "setdlopenflags"): - sys.setdlopenflags(previous_flags) - finally: - imp.release_lock() - # - # call loading_cpy_struct() to get the struct layout inferred by - # the C compiler - self._load(module, 'loading') - # - # the C code will need the objects. Collect them in - # order in a list. - revmapping = dict([(value, key) - for (key, value) in self._typesdict.items()]) - lst = [revmapping[i] for i in range(len(revmapping))] - lst = list(map(self.ffi._get_cached_btype, lst)) - # - # build the FFILibrary class and instance and call _cffi_setup(). - # this will set up some fields like '_cffi_types', and only then - # it will invoke the chained list of functions that will really - # build (notably) the constant objects, as if they are - # pointers, and store them as attributes on the 'library' object. - class FFILibrary(object): - _cffi_python_module = module - _cffi_ffi = self.ffi - _cffi_dir = [] - def __dir__(self): - return FFILibrary._cffi_dir + list(self.__dict__) - library = FFILibrary() - if module._cffi_setup(lst, VerificationError, library): - import warnings - warnings.warn("reimporting %r might overwrite older definitions" - % (self.verifier.get_module_name())) - # - # finally, call the loaded_cpy_xxx() functions. This will perform - # the final adjustments, like copying the Python->C wrapper - # functions from the module to the 'library' object, and setting - # up the FFILibrary class with properties for the global C variables. - self._load(module, 'loaded', library=library) - module._cffi_original_ffi = self.ffi - module._cffi_types_of_builtin_funcs = self._types_of_builtin_functions - return library - - def _get_declarations(self): - lst = [(key, tp) for (key, (tp, qual)) in - self.ffi._parser._declarations.items()] - lst.sort() - return lst - - def _generate(self, step_name): - for name, tp in self._get_declarations(): - kind, realname = name.split(' ', 1) - try: - method = getattr(self, '_generate_cpy_%s_%s' % (kind, - step_name)) - except AttributeError: - raise VerificationError( - "not implemented in verify(): %r" % name) - try: - method(tp, realname) - except Exception as e: - model.attach_exception_info(e, name) - raise - - def _load(self, module, step_name, **kwds): - for name, tp in self._get_declarations(): - kind, realname = name.split(' ', 1) - method = getattr(self, '_%s_cpy_%s' % (step_name, kind)) - try: - method(tp, realname, module, **kwds) - except Exception as e: - model.attach_exception_info(e, name) - raise - - def _generate_nothing(self, tp, name): - pass - - def _loaded_noop(self, tp, name, module, **kwds): - pass - - # ---------- - - def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode): - extraarg = '' - if isinstance(tp, model.PrimitiveType): - if tp.is_integer_type() and tp.name != '_Bool': - converter = '_cffi_to_c_int' - extraarg = ', %s' % tp.name - elif tp.is_complex_type(): - raise VerificationError( - "not implemented in verify(): complex types") - else: - converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''), - tp.name.replace(' ', '_')) - errvalue = '-1' - # - elif isinstance(tp, model.PointerType): - self._convert_funcarg_to_c_ptr_or_array(tp, fromvar, - tovar, errcode) - return - # - elif isinstance(tp, (model.StructOrUnion, model.EnumType)): - # a struct (not a struct pointer) as a function argument - self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)' - % (tovar, self._gettypenum(tp), fromvar)) - self._prnt(' %s;' % errcode) - return - # - elif isinstance(tp, model.FunctionPtrType): - converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('') - extraarg = ', _cffi_type(%d)' % self._gettypenum(tp) - errvalue = 'NULL' - # - else: - raise NotImplementedError(tp) - # - self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg)) - self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % ( - tovar, tp.get_c_name(''), errvalue)) - self._prnt(' %s;' % errcode) - - def _extra_local_variables(self, tp, localvars, freelines): - if isinstance(tp, model.PointerType): - localvars.add('Py_ssize_t datasize') - localvars.add('struct _cffi_freeme_s *large_args_free = NULL') - freelines.add('if (large_args_free != NULL)' - ' _cffi_free_array_arguments(large_args_free);') - - def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): - self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') - self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( - self._gettypenum(tp), fromvar, tovar)) - self._prnt(' if (datasize != 0) {') - self._prnt(' %s = ((size_t)datasize) <= 640 ? ' - 'alloca((size_t)datasize) : NULL;' % (tovar,)) - self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, ' - '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar)) - self._prnt(' datasize, &large_args_free) < 0)') - self._prnt(' %s;' % errcode) - self._prnt(' }') - - def _convert_expr_from_c(self, tp, var, context): - if isinstance(tp, model.PrimitiveType): - if tp.is_integer_type() and tp.name != '_Bool': - return '_cffi_from_c_int(%s, %s)' % (var, tp.name) - elif tp.name != 'long double': - return '_cffi_from_c_%s(%s)' % (tp.name.replace(' ', '_'), var) - else: - return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, (model.PointerType, model.FunctionPtrType)): - return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, model.ArrayType): - return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( - var, self._gettypenum(model.PointerType(tp.item))) - elif isinstance(tp, model.StructOrUnion): - if tp.fldnames is None: - raise TypeError("'%s' is used as %s, but is opaque" % ( - tp._get_c_name(), context)) - return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, model.EnumType): - return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - else: - raise NotImplementedError(tp) - - # ---------- - # typedefs: generates no code so far - - _generate_cpy_typedef_collecttype = _generate_nothing - _generate_cpy_typedef_decl = _generate_nothing - _generate_cpy_typedef_method = _generate_nothing - _loading_cpy_typedef = _loaded_noop - _loaded_cpy_typedef = _loaded_noop - - # ---------- - # function declarations - - def _generate_cpy_function_collecttype(self, tp, name): - assert isinstance(tp, model.FunctionPtrType) - if tp.ellipsis: - self._do_collect_type(tp) - else: - # don't call _do_collect_type(tp) in this common case, - # otherwise test_autofilled_struct_as_argument fails - for type in tp.args: - self._do_collect_type(type) - self._do_collect_type(tp.result) - - def _generate_cpy_function_decl(self, tp, name): - assert isinstance(tp, model.FunctionPtrType) - if tp.ellipsis: - # cannot support vararg functions better than this: check for its - # exact type (including the fixed arguments), and build it as a - # constant function pointer (no CPython wrapper) - self._generate_cpy_const(False, name, tp) - return - prnt = self._prnt - numargs = len(tp.args) - if numargs == 0: - argname = 'noarg' - elif numargs == 1: - argname = 'arg0' - else: - argname = 'args' - prnt('static PyObject *') - prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname)) - prnt('{') - # - context = 'argument of %s' % name - for i, type in enumerate(tp.args): - prnt(' %s;' % type.get_c_name(' x%d' % i, context)) - # - localvars = set() - freelines = set() - for type in tp.args: - self._extra_local_variables(type, localvars, freelines) - for decl in sorted(localvars): - prnt(' %s;' % (decl,)) - # - if not isinstance(tp.result, model.VoidType): - result_code = 'result = ' - context = 'result of %s' % name - prnt(' %s;' % tp.result.get_c_name(' result', context)) - prnt(' PyObject *pyresult;') - else: - result_code = '' - # - if len(tp.args) > 1: - rng = range(len(tp.args)) - for i in rng: - prnt(' PyObject *arg%d;' % i) - prnt() - prnt(' if (!PyArg_ParseTuple(args, "%s:%s", %s))' % ( - 'O' * numargs, name, ', '.join(['&arg%d' % i for i in rng]))) - prnt(' return NULL;') - prnt() - # - for i, type in enumerate(tp.args): - self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i, - 'return NULL') - prnt() - # - prnt(' Py_BEGIN_ALLOW_THREADS') - prnt(' _cffi_restore_errno();') - prnt(' { %s%s(%s); }' % ( - result_code, name, - ', '.join(['x%d' % i for i in range(len(tp.args))]))) - prnt(' _cffi_save_errno();') - prnt(' Py_END_ALLOW_THREADS') - prnt() - # - prnt(' (void)self; /* unused */') - if numargs == 0: - prnt(' (void)noarg; /* unused */') - if result_code: - prnt(' pyresult = %s;' % - self._convert_expr_from_c(tp.result, 'result', 'result type')) - for freeline in freelines: - prnt(' ' + freeline) - prnt(' return pyresult;') - else: - for freeline in freelines: - prnt(' ' + freeline) - prnt(' Py_INCREF(Py_None);') - prnt(' return Py_None;') - prnt('}') - prnt() - - def _generate_cpy_function_method(self, tp, name): - if tp.ellipsis: - return - numargs = len(tp.args) - if numargs == 0: - meth = 'METH_NOARGS' - elif numargs == 1: - meth = 'METH_O' - else: - meth = 'METH_VARARGS' - self._prnt(' {"%s", _cffi_f_%s, %s, NULL},' % (name, name, meth)) - - _loading_cpy_function = _loaded_noop - - def _loaded_cpy_function(self, tp, name, module, library): - if tp.ellipsis: - return - func = getattr(module, name) - setattr(library, name, func) - self._types_of_builtin_functions[func] = tp - - # ---------- - # named structs - - _generate_cpy_struct_collecttype = _generate_nothing - def _generate_cpy_struct_decl(self, tp, name): - assert name == tp.name - self._generate_struct_or_union_decl(tp, 'struct', name) - def _generate_cpy_struct_method(self, tp, name): - self._generate_struct_or_union_method(tp, 'struct', name) - def _loading_cpy_struct(self, tp, name, module): - self._loading_struct_or_union(tp, 'struct', name, module) - def _loaded_cpy_struct(self, tp, name, module, **kwds): - self._loaded_struct_or_union(tp) - - _generate_cpy_union_collecttype = _generate_nothing - def _generate_cpy_union_decl(self, tp, name): - assert name == tp.name - self._generate_struct_or_union_decl(tp, 'union', name) - def _generate_cpy_union_method(self, tp, name): - self._generate_struct_or_union_method(tp, 'union', name) - def _loading_cpy_union(self, tp, name, module): - self._loading_struct_or_union(tp, 'union', name, module) - def _loaded_cpy_union(self, tp, name, module, **kwds): - self._loaded_struct_or_union(tp) - - def _generate_struct_or_union_decl(self, tp, prefix, name): - if tp.fldnames is None: - return # nothing to do with opaque structs - checkfuncname = '_cffi_check_%s_%s' % (prefix, name) - layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) - cname = ('%s %s' % (prefix, name)).strip() - # - prnt = self._prnt - prnt('static void %s(%s *p)' % (checkfuncname, cname)) - prnt('{') - prnt(' /* only to generate compile-time warnings or errors */') - prnt(' (void)p;') - for fname, ftype, fbitsize, fqual in tp.enumfields(): - if (isinstance(ftype, model.PrimitiveType) - and ftype.is_integer_type()) or fbitsize >= 0: - # accept all integers, but complain on float or double - prnt(' (void)((p->%s) << 1);' % fname) - else: - # only accept exactly the type declared. - try: - prnt(' { %s = &p->%s; (void)tmp; }' % ( - ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), - fname)) - except VerificationError as e: - prnt(' /* %s */' % str(e)) # cannot verify it, ignore - prnt('}') - prnt('static PyObject *') - prnt('%s(PyObject *self, PyObject *noarg)' % (layoutfuncname,)) - prnt('{') - prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname) - prnt(' static Py_ssize_t nums[] = {') - prnt(' sizeof(%s),' % cname) - prnt(' offsetof(struct _cffi_aligncheck, y),') - for fname, ftype, fbitsize, fqual in tp.enumfields(): - if fbitsize >= 0: - continue # xxx ignore fbitsize for now - prnt(' offsetof(%s, %s),' % (cname, fname)) - if isinstance(ftype, model.ArrayType) and ftype.length is None: - prnt(' 0, /* %s */' % ftype._get_c_name()) - else: - prnt(' sizeof(((%s *)0)->%s),' % (cname, fname)) - prnt(' -1') - prnt(' };') - prnt(' (void)self; /* unused */') - prnt(' (void)noarg; /* unused */') - prnt(' return _cffi_get_struct_layout(nums);') - prnt(' /* the next line is not executed, but compiled */') - prnt(' %s(0);' % (checkfuncname,)) - prnt('}') - prnt() - - def _generate_struct_or_union_method(self, tp, prefix, name): - if tp.fldnames is None: - return # nothing to do with opaque structs - layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) - self._prnt(' {"%s", %s, METH_NOARGS, NULL},' % (layoutfuncname, - layoutfuncname)) - - def _loading_struct_or_union(self, tp, prefix, name, module): - if tp.fldnames is None: - return # nothing to do with opaque structs - layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) - # - function = getattr(module, layoutfuncname) - layout = function() - if isinstance(tp, model.StructOrUnion) and tp.partial: - # use the function()'s sizes and offsets to guide the - # layout of the struct - totalsize = layout[0] - totalalignment = layout[1] - fieldofs = layout[2::2] - fieldsize = layout[3::2] - tp.force_flatten() - assert len(fieldofs) == len(fieldsize) == len(tp.fldnames) - tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment - else: - cname = ('%s %s' % (prefix, name)).strip() - self._struct_pending_verification[tp] = layout, cname - - def _loaded_struct_or_union(self, tp): - if tp.fldnames is None: - return # nothing to do with opaque structs - self.ffi._get_cached_btype(tp) # force 'fixedlayout' to be considered - - if tp in self._struct_pending_verification: - # check that the layout sizes and offsets match the real ones - def check(realvalue, expectedvalue, msg): - if realvalue != expectedvalue: - raise VerificationError( - "%s (we have %d, but C compiler says %d)" - % (msg, expectedvalue, realvalue)) - ffi = self.ffi - BStruct = ffi._get_cached_btype(tp) - layout, cname = self._struct_pending_verification.pop(tp) - check(layout[0], ffi.sizeof(BStruct), "wrong total size") - check(layout[1], ffi.alignof(BStruct), "wrong total alignment") - i = 2 - for fname, ftype, fbitsize, fqual in tp.enumfields(): - if fbitsize >= 0: - continue # xxx ignore fbitsize for now - check(layout[i], ffi.offsetof(BStruct, fname), - "wrong offset for field %r" % (fname,)) - if layout[i+1] != 0: - BField = ffi._get_cached_btype(ftype) - check(layout[i+1], ffi.sizeof(BField), - "wrong size for field %r" % (fname,)) - i += 2 - assert i == len(layout) - - # ---------- - # 'anonymous' declarations. These are produced for anonymous structs - # or unions; the 'name' is obtained by a typedef. - - _generate_cpy_anonymous_collecttype = _generate_nothing - - def _generate_cpy_anonymous_decl(self, tp, name): - if isinstance(tp, model.EnumType): - self._generate_cpy_enum_decl(tp, name, '') - else: - self._generate_struct_or_union_decl(tp, '', name) - - def _generate_cpy_anonymous_method(self, tp, name): - if not isinstance(tp, model.EnumType): - self._generate_struct_or_union_method(tp, '', name) - - def _loading_cpy_anonymous(self, tp, name, module): - if isinstance(tp, model.EnumType): - self._loading_cpy_enum(tp, name, module) - else: - self._loading_struct_or_union(tp, '', name, module) - - def _loaded_cpy_anonymous(self, tp, name, module, **kwds): - if isinstance(tp, model.EnumType): - self._loaded_cpy_enum(tp, name, module, **kwds) - else: - self._loaded_struct_or_union(tp) - - # ---------- - # constants, likely declared with '#define' - - def _generate_cpy_const(self, is_int, name, tp=None, category='const', - vartp=None, delayed=True, size_too=False, - check_value=None): - prnt = self._prnt - funcname = '_cffi_%s_%s' % (category, name) - prnt('static int %s(PyObject *lib)' % funcname) - prnt('{') - prnt(' PyObject *o;') - prnt(' int res;') - if not is_int: - prnt(' %s;' % (vartp or tp).get_c_name(' i', name)) - else: - assert category == 'const' - # - if check_value is not None: - self._check_int_constant_value(name, check_value) - # - if not is_int: - if category == 'var': - realexpr = '&' + name - else: - realexpr = name - prnt(' i = (%s);' % (realexpr,)) - prnt(' o = %s;' % (self._convert_expr_from_c(tp, 'i', - 'variable type'),)) - assert delayed - else: - prnt(' o = _cffi_from_c_int_const(%s);' % name) - prnt(' if (o == NULL)') - prnt(' return -1;') - if size_too: - prnt(' {') - prnt(' PyObject *o1 = o;') - prnt(' o = Py_BuildValue("On", o1, (Py_ssize_t)sizeof(%s));' - % (name,)) - prnt(' Py_DECREF(o1);') - prnt(' if (o == NULL)') - prnt(' return -1;') - prnt(' }') - prnt(' res = PyObject_SetAttrString(lib, "%s", o);' % name) - prnt(' Py_DECREF(o);') - prnt(' if (res < 0)') - prnt(' return -1;') - prnt(' return %s;' % self._chained_list_constants[delayed]) - self._chained_list_constants[delayed] = funcname + '(lib)' - prnt('}') - prnt() - - def _generate_cpy_constant_collecttype(self, tp, name): - is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() - if not is_int: - self._do_collect_type(tp) - - def _generate_cpy_constant_decl(self, tp, name): - is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() - self._generate_cpy_const(is_int, name, tp) - - _generate_cpy_constant_method = _generate_nothing - _loading_cpy_constant = _loaded_noop - _loaded_cpy_constant = _loaded_noop - - # ---------- - # enums - - def _check_int_constant_value(self, name, value, err_prefix=''): - prnt = self._prnt - if value <= 0: - prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % ( - name, name, value)) - else: - prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % ( - name, name, value)) - prnt(' char buf[64];') - prnt(' if ((%s) <= 0)' % name) - prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % name) - prnt(' else') - prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' % - name) - prnt(' PyErr_Format(_cffi_VerificationError,') - prnt(' "%s%s has the real value %s, not %s",') - prnt(' "%s", "%s", buf, "%d");' % ( - err_prefix, name, value)) - prnt(' return -1;') - prnt(' }') - - def _enum_funcname(self, prefix, name): - # "$enum_$1" => "___D_enum____D_1" - name = name.replace('$', '___D_') - return '_cffi_e_%s_%s' % (prefix, name) - - def _generate_cpy_enum_decl(self, tp, name, prefix='enum'): - if tp.partial: - for enumerator in tp.enumerators: - self._generate_cpy_const(True, enumerator, delayed=False) - return - # - funcname = self._enum_funcname(prefix, name) - prnt = self._prnt - prnt('static int %s(PyObject *lib)' % funcname) - prnt('{') - for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): - self._check_int_constant_value(enumerator, enumvalue, - "enum %s: " % name) - prnt(' return %s;' % self._chained_list_constants[True]) - self._chained_list_constants[True] = funcname + '(lib)' - prnt('}') - prnt() - - _generate_cpy_enum_collecttype = _generate_nothing - _generate_cpy_enum_method = _generate_nothing - - def _loading_cpy_enum(self, tp, name, module): - if tp.partial: - enumvalues = [getattr(module, enumerator) - for enumerator in tp.enumerators] - tp.enumvalues = tuple(enumvalues) - tp.partial_resolved = True - - def _loaded_cpy_enum(self, tp, name, module, library): - for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): - setattr(library, enumerator, enumvalue) - - # ---------- - # macros: for now only for integers - - def _generate_cpy_macro_decl(self, tp, name): - if tp == '...': - check_value = None - else: - check_value = tp # an integer - self._generate_cpy_const(True, name, check_value=check_value) - - _generate_cpy_macro_collecttype = _generate_nothing - _generate_cpy_macro_method = _generate_nothing - _loading_cpy_macro = _loaded_noop - _loaded_cpy_macro = _loaded_noop - - # ---------- - # global variables - - def _generate_cpy_variable_collecttype(self, tp, name): - if isinstance(tp, model.ArrayType): - tp_ptr = model.PointerType(tp.item) - else: - tp_ptr = model.PointerType(tp) - self._do_collect_type(tp_ptr) - - def _generate_cpy_variable_decl(self, tp, name): - if isinstance(tp, model.ArrayType): - tp_ptr = model.PointerType(tp.item) - self._generate_cpy_const(False, name, tp, vartp=tp_ptr, - size_too = tp.length_is_unknown()) - else: - tp_ptr = model.PointerType(tp) - self._generate_cpy_const(False, name, tp_ptr, category='var') - - _generate_cpy_variable_method = _generate_nothing - _loading_cpy_variable = _loaded_noop - - def _loaded_cpy_variable(self, tp, name, module, library): - value = getattr(library, name) - if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the - # sense that "a=..." is forbidden - if tp.length_is_unknown(): - assert isinstance(value, tuple) - (value, size) = value - BItemType = self.ffi._get_cached_btype(tp.item) - length, rest = divmod(size, self.ffi.sizeof(BItemType)) - if rest != 0: - raise VerificationError( - "bad size: %r does not seem to be an array of %s" % - (name, tp.item)) - tp = tp.resolve_length(length) - # 'value' is a which we have to replace with - # a if the N is actually known - if tp.length is not None: - BArray = self.ffi._get_cached_btype(tp) - value = self.ffi.cast(BArray, value) - setattr(library, name, value) - return - # remove ptr= from the library instance, and replace - # it by a property on the class, which reads/writes into ptr[0]. - ptr = value - delattr(library, name) - def getter(library): - return ptr[0] - def setter(library, value): - ptr[0] = value - setattr(type(library), name, property(getter, setter)) - type(library)._cffi_dir.append(name) - - # ---------- - - def _generate_setup_custom(self): - prnt = self._prnt - prnt('static int _cffi_setup_custom(PyObject *lib)') - prnt('{') - prnt(' return %s;' % self._chained_list_constants[True]) - prnt('}') - -cffimod_header = r''' -#include -#include - -/* this block of #ifs should be kept exactly identical between - c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py - and cffi/_cffi_include.h */ -#if defined(_MSC_VER) -# include /* for alloca() */ -# if _MSC_VER < 1600 /* MSVC < 2010 */ - typedef __int8 int8_t; - typedef __int16 int16_t; - typedef __int32 int32_t; - typedef __int64 int64_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; - typedef unsigned __int64 uint64_t; - typedef __int8 int_least8_t; - typedef __int16 int_least16_t; - typedef __int32 int_least32_t; - typedef __int64 int_least64_t; - typedef unsigned __int8 uint_least8_t; - typedef unsigned __int16 uint_least16_t; - typedef unsigned __int32 uint_least32_t; - typedef unsigned __int64 uint_least64_t; - typedef __int8 int_fast8_t; - typedef __int16 int_fast16_t; - typedef __int32 int_fast32_t; - typedef __int64 int_fast64_t; - typedef unsigned __int8 uint_fast8_t; - typedef unsigned __int16 uint_fast16_t; - typedef unsigned __int32 uint_fast32_t; - typedef unsigned __int64 uint_fast64_t; - typedef __int64 intmax_t; - typedef unsigned __int64 uintmax_t; -# else -# include -# endif -# if _MSC_VER < 1800 /* MSVC < 2013 */ -# ifndef __cplusplus - typedef unsigned char _Bool; -# endif -# endif -# define _cffi_float_complex_t _Fcomplex /* include for it */ -# define _cffi_double_complex_t _Dcomplex /* include for it */ -#else -# include -# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) -# include -# endif -# define _cffi_float_complex_t float _Complex -# define _cffi_double_complex_t double _Complex -#endif - -#if PY_MAJOR_VERSION < 3 -# undef PyCapsule_CheckExact -# undef PyCapsule_GetPointer -# define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule)) -# define PyCapsule_GetPointer(capsule, name) \ - (PyCObject_AsVoidPtr(capsule)) -#endif - -#if PY_MAJOR_VERSION >= 3 -# define PyInt_FromLong PyLong_FromLong -#endif - -#define _cffi_from_c_double PyFloat_FromDouble -#define _cffi_from_c_float PyFloat_FromDouble -#define _cffi_from_c_long PyInt_FromLong -#define _cffi_from_c_ulong PyLong_FromUnsignedLong -#define _cffi_from_c_longlong PyLong_FromLongLong -#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong -#define _cffi_from_c__Bool PyBool_FromLong - -#define _cffi_to_c_double PyFloat_AsDouble -#define _cffi_to_c_float PyFloat_AsDouble - -#define _cffi_from_c_int_const(x) \ - (((x) > 0) ? \ - ((unsigned long long)(x) <= (unsigned long long)LONG_MAX) ? \ - PyInt_FromLong((long)(x)) : \ - PyLong_FromUnsignedLongLong((unsigned long long)(x)) : \ - ((long long)(x) >= (long long)LONG_MIN) ? \ - PyInt_FromLong((long)(x)) : \ - PyLong_FromLongLong((long long)(x))) - -#define _cffi_from_c_int(x, type) \ - (((type)-1) > 0 ? /* unsigned */ \ - (sizeof(type) < sizeof(long) ? \ - PyInt_FromLong((long)x) : \ - sizeof(type) == sizeof(long) ? \ - PyLong_FromUnsignedLong((unsigned long)x) : \ - PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ - (sizeof(type) <= sizeof(long) ? \ - PyInt_FromLong((long)x) : \ - PyLong_FromLongLong((long long)x))) - -#define _cffi_to_c_int(o, type) \ - ((type)( \ - sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ - : (type)_cffi_to_c_i8(o)) : \ - sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ - : (type)_cffi_to_c_i16(o)) : \ - sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ - : (type)_cffi_to_c_i32(o)) : \ - sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ - : (type)_cffi_to_c_i64(o)) : \ - (Py_FatalError("unsupported size for type " #type), (type)0))) - -#define _cffi_to_c_i8 \ - ((int(*)(PyObject *))_cffi_exports[1]) -#define _cffi_to_c_u8 \ - ((int(*)(PyObject *))_cffi_exports[2]) -#define _cffi_to_c_i16 \ - ((int(*)(PyObject *))_cffi_exports[3]) -#define _cffi_to_c_u16 \ - ((int(*)(PyObject *))_cffi_exports[4]) -#define _cffi_to_c_i32 \ - ((int(*)(PyObject *))_cffi_exports[5]) -#define _cffi_to_c_u32 \ - ((unsigned int(*)(PyObject *))_cffi_exports[6]) -#define _cffi_to_c_i64 \ - ((long long(*)(PyObject *))_cffi_exports[7]) -#define _cffi_to_c_u64 \ - ((unsigned long long(*)(PyObject *))_cffi_exports[8]) -#define _cffi_to_c_char \ - ((int(*)(PyObject *))_cffi_exports[9]) -#define _cffi_from_c_pointer \ - ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10]) -#define _cffi_to_c_pointer \ - ((char *(*)(PyObject *, CTypeDescrObject *))_cffi_exports[11]) -#define _cffi_get_struct_layout \ - ((PyObject *(*)(Py_ssize_t[]))_cffi_exports[12]) -#define _cffi_restore_errno \ - ((void(*)(void))_cffi_exports[13]) -#define _cffi_save_errno \ - ((void(*)(void))_cffi_exports[14]) -#define _cffi_from_c_char \ - ((PyObject *(*)(char))_cffi_exports[15]) -#define _cffi_from_c_deref \ - ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16]) -#define _cffi_to_c \ - ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17]) -#define _cffi_from_c_struct \ - ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[18]) -#define _cffi_to_c_wchar_t \ - ((wchar_t(*)(PyObject *))_cffi_exports[19]) -#define _cffi_from_c_wchar_t \ - ((PyObject *(*)(wchar_t))_cffi_exports[20]) -#define _cffi_to_c_long_double \ - ((long double(*)(PyObject *))_cffi_exports[21]) -#define _cffi_to_c__Bool \ - ((_Bool(*)(PyObject *))_cffi_exports[22]) -#define _cffi_prepare_pointer_call_argument \ - ((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23]) -#define _cffi_convert_array_from_object \ - ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24]) -#define _CFFI_NUM_EXPORTS 25 - -typedef struct _ctypedescr CTypeDescrObject; - -static void *_cffi_exports[_CFFI_NUM_EXPORTS]; -static PyObject *_cffi_types, *_cffi_VerificationError; - -static int _cffi_setup_custom(PyObject *lib); /* forward */ - -static PyObject *_cffi_setup(PyObject *self, PyObject *args) -{ - PyObject *library; - int was_alive = (_cffi_types != NULL); - (void)self; /* unused */ - if (!PyArg_ParseTuple(args, "OOO", &_cffi_types, &_cffi_VerificationError, - &library)) - return NULL; - Py_INCREF(_cffi_types); - Py_INCREF(_cffi_VerificationError); - if (_cffi_setup_custom(library) < 0) - return NULL; - return PyBool_FromLong(was_alive); -} - -union _cffi_union_alignment_u { - unsigned char m_char; - unsigned short m_short; - unsigned int m_int; - unsigned long m_long; - unsigned long long m_longlong; - float m_float; - double m_double; - long double m_longdouble; -}; - -struct _cffi_freeme_s { - struct _cffi_freeme_s *next; - union _cffi_union_alignment_u alignment; -}; - -#ifdef __GNUC__ - __attribute__((unused)) -#endif -static int _cffi_convert_array_argument(CTypeDescrObject *ctptr, PyObject *arg, - char **output_data, Py_ssize_t datasize, - struct _cffi_freeme_s **freeme) -{ - char *p; - if (datasize < 0) - return -1; - - p = *output_data; - if (p == NULL) { - struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc( - offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize); - if (fp == NULL) - return -1; - fp->next = *freeme; - *freeme = fp; - p = *output_data = (char *)&fp->alignment; - } - memset((void *)p, 0, (size_t)datasize); - return _cffi_convert_array_from_object(p, ctptr, arg); -} - -#ifdef __GNUC__ - __attribute__((unused)) -#endif -static void _cffi_free_array_arguments(struct _cffi_freeme_s *freeme) -{ - do { - void *p = (void *)freeme; - freeme = freeme->next; - PyObject_Free(p); - } while (freeme != NULL); -} - -static int _cffi_init(void) -{ - PyObject *module, *c_api_object = NULL; - - module = PyImport_ImportModule("_cffi_backend"); - if (module == NULL) - goto failure; - - c_api_object = PyObject_GetAttrString(module, "_C_API"); - if (c_api_object == NULL) - goto failure; - if (!PyCapsule_CheckExact(c_api_object)) { - PyErr_SetNone(PyExc_ImportError); - goto failure; - } - memcpy(_cffi_exports, PyCapsule_GetPointer(c_api_object, "cffi"), - _CFFI_NUM_EXPORTS * sizeof(void *)); - - Py_DECREF(module); - Py_DECREF(c_api_object); - return 0; - - failure: - Py_XDECREF(module); - Py_XDECREF(c_api_object); - return -1; -} - -#define _cffi_type(num) ((CTypeDescrObject *)PyList_GET_ITEM(_cffi_types, num)) - -/**********/ -''' diff --git a/notification-service/venv/Lib/site-packages/cffi/vengine_gen.py b/notification-service/venv/Lib/site-packages/cffi/vengine_gen.py deleted file mode 100644 index bffc821..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/vengine_gen.py +++ /dev/null @@ -1,679 +0,0 @@ -# -# DEPRECATED: implementation for ffi.verify() -# -import sys, os -import types - -from . import model -from .error import VerificationError - - -class VGenericEngine(object): - _class_key = 'g' - _gen_python_module = False - - def __init__(self, verifier): - self.verifier = verifier - self.ffi = verifier.ffi - self.export_symbols = [] - self._struct_pending_verification = {} - - def patch_extension_kwds(self, kwds): - # add 'export_symbols' to the dictionary. Note that we add the - # list before filling it. When we fill it, it will thus also show - # up in kwds['export_symbols']. - kwds.setdefault('export_symbols', self.export_symbols) - - def find_module(self, module_name, path, so_suffixes): - for so_suffix in so_suffixes: - basename = module_name + so_suffix - if path is None: - path = sys.path - for dirname in path: - filename = os.path.join(dirname, basename) - if os.path.isfile(filename): - return filename - - def collect_types(self): - pass # not needed in the generic engine - - def _prnt(self, what=''): - self._f.write(what + '\n') - - def write_source_to_f(self): - prnt = self._prnt - # first paste some standard set of lines that are mostly '#include' - prnt(cffimod_header) - # then paste the C source given by the user, verbatim. - prnt(self.verifier.preamble) - # - # call generate_gen_xxx_decl(), for every xxx found from - # ffi._parser._declarations. This generates all the functions. - self._generate('decl') - # - # on Windows, distutils insists on putting init_cffi_xyz in - # 'export_symbols', so instead of fighting it, just give up and - # give it one - if sys.platform == 'win32': - if sys.version_info >= (3,): - prefix = 'PyInit_' - else: - prefix = 'init' - modname = self.verifier.get_module_name() - prnt("void %s%s(void) { }\n" % (prefix, modname)) - - def load_library(self, flags=0): - # import it with the CFFI backend - backend = self.ffi._backend - # needs to make a path that contains '/', on Posix - filename = os.path.join(os.curdir, self.verifier.modulefilename) - module = backend.load_library(filename, flags) - # - # call loading_gen_struct() to get the struct layout inferred by - # the C compiler - self._load(module, 'loading') - - # build the FFILibrary class and instance, this is a module subclass - # because modules are expected to have usually-constant-attributes and - # in PyPy this means the JIT is able to treat attributes as constant, - # which we want. - class FFILibrary(types.ModuleType): - _cffi_generic_module = module - _cffi_ffi = self.ffi - _cffi_dir = [] - def __dir__(self): - return FFILibrary._cffi_dir - library = FFILibrary("") - # - # finally, call the loaded_gen_xxx() functions. This will set - # up the 'library' object. - self._load(module, 'loaded', library=library) - return library - - def _get_declarations(self): - lst = [(key, tp) for (key, (tp, qual)) in - self.ffi._parser._declarations.items()] - lst.sort() - return lst - - def _generate(self, step_name): - for name, tp in self._get_declarations(): - kind, realname = name.split(' ', 1) - try: - method = getattr(self, '_generate_gen_%s_%s' % (kind, - step_name)) - except AttributeError: - raise VerificationError( - "not implemented in verify(): %r" % name) - try: - method(tp, realname) - except Exception as e: - model.attach_exception_info(e, name) - raise - - def _load(self, module, step_name, **kwds): - for name, tp in self._get_declarations(): - kind, realname = name.split(' ', 1) - method = getattr(self, '_%s_gen_%s' % (step_name, kind)) - try: - method(tp, realname, module, **kwds) - except Exception as e: - model.attach_exception_info(e, name) - raise - - def _generate_nothing(self, tp, name): - pass - - def _loaded_noop(self, tp, name, module, **kwds): - pass - - # ---------- - # typedefs: generates no code so far - - _generate_gen_typedef_decl = _generate_nothing - _loading_gen_typedef = _loaded_noop - _loaded_gen_typedef = _loaded_noop - - # ---------- - # function declarations - - def _generate_gen_function_decl(self, tp, name): - assert isinstance(tp, model.FunctionPtrType) - if tp.ellipsis: - # cannot support vararg functions better than this: check for its - # exact type (including the fixed arguments), and build it as a - # constant function pointer (no _cffi_f_%s wrapper) - self._generate_gen_const(False, name, tp) - return - prnt = self._prnt - numargs = len(tp.args) - argnames = [] - for i, type in enumerate(tp.args): - indirection = '' - if isinstance(type, model.StructOrUnion): - indirection = '*' - argnames.append('%sx%d' % (indirection, i)) - context = 'argument of %s' % name - arglist = [type.get_c_name(' %s' % arg, context) - for type, arg in zip(tp.args, argnames)] - tpresult = tp.result - if isinstance(tpresult, model.StructOrUnion): - arglist.insert(0, tpresult.get_c_name(' *r', context)) - tpresult = model.void_type - arglist = ', '.join(arglist) or 'void' - wrappername = '_cffi_f_%s' % name - self.export_symbols.append(wrappername) - if tp.abi: - abi = tp.abi + ' ' - else: - abi = '' - funcdecl = ' %s%s(%s)' % (abi, wrappername, arglist) - context = 'result of %s' % name - prnt(tpresult.get_c_name(funcdecl, context)) - prnt('{') - # - if isinstance(tp.result, model.StructOrUnion): - result_code = '*r = ' - elif not isinstance(tp.result, model.VoidType): - result_code = 'return ' - else: - result_code = '' - prnt(' %s%s(%s);' % (result_code, name, ', '.join(argnames))) - prnt('}') - prnt() - - _loading_gen_function = _loaded_noop - - def _loaded_gen_function(self, tp, name, module, library): - assert isinstance(tp, model.FunctionPtrType) - if tp.ellipsis: - newfunction = self._load_constant(False, tp, name, module) - else: - indirections = [] - base_tp = tp - if (any(isinstance(typ, model.StructOrUnion) for typ in tp.args) - or isinstance(tp.result, model.StructOrUnion)): - indirect_args = [] - for i, typ in enumerate(tp.args): - if isinstance(typ, model.StructOrUnion): - typ = model.PointerType(typ) - indirections.append((i, typ)) - indirect_args.append(typ) - indirect_result = tp.result - if isinstance(indirect_result, model.StructOrUnion): - if indirect_result.fldtypes is None: - raise TypeError("'%s' is used as result type, " - "but is opaque" % ( - indirect_result._get_c_name(),)) - indirect_result = model.PointerType(indirect_result) - indirect_args.insert(0, indirect_result) - indirections.insert(0, ("result", indirect_result)) - indirect_result = model.void_type - tp = model.FunctionPtrType(tuple(indirect_args), - indirect_result, tp.ellipsis) - BFunc = self.ffi._get_cached_btype(tp) - wrappername = '_cffi_f_%s' % name - newfunction = module.load_function(BFunc, wrappername) - for i, typ in indirections: - newfunction = self._make_struct_wrapper(newfunction, i, typ, - base_tp) - setattr(library, name, newfunction) - type(library)._cffi_dir.append(name) - - def _make_struct_wrapper(self, oldfunc, i, tp, base_tp): - backend = self.ffi._backend - BType = self.ffi._get_cached_btype(tp) - if i == "result": - ffi = self.ffi - def newfunc(*args): - res = ffi.new(BType) - oldfunc(res, *args) - return res[0] - else: - def newfunc(*args): - args = args[:i] + (backend.newp(BType, args[i]),) + args[i+1:] - return oldfunc(*args) - newfunc._cffi_base_type = base_tp - return newfunc - - # ---------- - # named structs - - def _generate_gen_struct_decl(self, tp, name): - assert name == tp.name - self._generate_struct_or_union_decl(tp, 'struct', name) - - def _loading_gen_struct(self, tp, name, module): - self._loading_struct_or_union(tp, 'struct', name, module) - - def _loaded_gen_struct(self, tp, name, module, **kwds): - self._loaded_struct_or_union(tp) - - def _generate_gen_union_decl(self, tp, name): - assert name == tp.name - self._generate_struct_or_union_decl(tp, 'union', name) - - def _loading_gen_union(self, tp, name, module): - self._loading_struct_or_union(tp, 'union', name, module) - - def _loaded_gen_union(self, tp, name, module, **kwds): - self._loaded_struct_or_union(tp) - - def _generate_struct_or_union_decl(self, tp, prefix, name): - if tp.fldnames is None: - return # nothing to do with opaque structs - checkfuncname = '_cffi_check_%s_%s' % (prefix, name) - layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) - cname = ('%s %s' % (prefix, name)).strip() - # - prnt = self._prnt - prnt('static void %s(%s *p)' % (checkfuncname, cname)) - prnt('{') - prnt(' /* only to generate compile-time warnings or errors */') - prnt(' (void)p;') - for fname, ftype, fbitsize, fqual in tp.enumfields(): - if (isinstance(ftype, model.PrimitiveType) - and ftype.is_integer_type()) or fbitsize >= 0: - # accept all integers, but complain on float or double - prnt(' (void)((p->%s) << 1);' % fname) - else: - # only accept exactly the type declared. - try: - prnt(' { %s = &p->%s; (void)tmp; }' % ( - ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), - fname)) - except VerificationError as e: - prnt(' /* %s */' % str(e)) # cannot verify it, ignore - prnt('}') - self.export_symbols.append(layoutfuncname) - prnt('intptr_t %s(intptr_t i)' % (layoutfuncname,)) - prnt('{') - prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname) - prnt(' static intptr_t nums[] = {') - prnt(' sizeof(%s),' % cname) - prnt(' offsetof(struct _cffi_aligncheck, y),') - for fname, ftype, fbitsize, fqual in tp.enumfields(): - if fbitsize >= 0: - continue # xxx ignore fbitsize for now - prnt(' offsetof(%s, %s),' % (cname, fname)) - if isinstance(ftype, model.ArrayType) and ftype.length is None: - prnt(' 0, /* %s */' % ftype._get_c_name()) - else: - prnt(' sizeof(((%s *)0)->%s),' % (cname, fname)) - prnt(' -1') - prnt(' };') - prnt(' return nums[i];') - prnt(' /* the next line is not executed, but compiled */') - prnt(' %s(0);' % (checkfuncname,)) - prnt('}') - prnt() - - def _loading_struct_or_union(self, tp, prefix, name, module): - if tp.fldnames is None: - return # nothing to do with opaque structs - layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) - # - BFunc = self.ffi._typeof_locked("intptr_t(*)(intptr_t)")[0] - function = module.load_function(BFunc, layoutfuncname) - layout = [] - num = 0 - while True: - x = function(num) - if x < 0: break - layout.append(x) - num += 1 - if isinstance(tp, model.StructOrUnion) and tp.partial: - # use the function()'s sizes and offsets to guide the - # layout of the struct - totalsize = layout[0] - totalalignment = layout[1] - fieldofs = layout[2::2] - fieldsize = layout[3::2] - tp.force_flatten() - assert len(fieldofs) == len(fieldsize) == len(tp.fldnames) - tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment - else: - cname = ('%s %s' % (prefix, name)).strip() - self._struct_pending_verification[tp] = layout, cname - - def _loaded_struct_or_union(self, tp): - if tp.fldnames is None: - return # nothing to do with opaque structs - self.ffi._get_cached_btype(tp) # force 'fixedlayout' to be considered - - if tp in self._struct_pending_verification: - # check that the layout sizes and offsets match the real ones - def check(realvalue, expectedvalue, msg): - if realvalue != expectedvalue: - raise VerificationError( - "%s (we have %d, but C compiler says %d)" - % (msg, expectedvalue, realvalue)) - ffi = self.ffi - BStruct = ffi._get_cached_btype(tp) - layout, cname = self._struct_pending_verification.pop(tp) - check(layout[0], ffi.sizeof(BStruct), "wrong total size") - check(layout[1], ffi.alignof(BStruct), "wrong total alignment") - i = 2 - for fname, ftype, fbitsize, fqual in tp.enumfields(): - if fbitsize >= 0: - continue # xxx ignore fbitsize for now - check(layout[i], ffi.offsetof(BStruct, fname), - "wrong offset for field %r" % (fname,)) - if layout[i+1] != 0: - BField = ffi._get_cached_btype(ftype) - check(layout[i+1], ffi.sizeof(BField), - "wrong size for field %r" % (fname,)) - i += 2 - assert i == len(layout) - - # ---------- - # 'anonymous' declarations. These are produced for anonymous structs - # or unions; the 'name' is obtained by a typedef. - - def _generate_gen_anonymous_decl(self, tp, name): - if isinstance(tp, model.EnumType): - self._generate_gen_enum_decl(tp, name, '') - else: - self._generate_struct_or_union_decl(tp, '', name) - - def _loading_gen_anonymous(self, tp, name, module): - if isinstance(tp, model.EnumType): - self._loading_gen_enum(tp, name, module, '') - else: - self._loading_struct_or_union(tp, '', name, module) - - def _loaded_gen_anonymous(self, tp, name, module, **kwds): - if isinstance(tp, model.EnumType): - self._loaded_gen_enum(tp, name, module, **kwds) - else: - self._loaded_struct_or_union(tp) - - # ---------- - # constants, likely declared with '#define' - - def _generate_gen_const(self, is_int, name, tp=None, category='const', - check_value=None): - prnt = self._prnt - funcname = '_cffi_%s_%s' % (category, name) - self.export_symbols.append(funcname) - if check_value is not None: - assert is_int - assert category == 'const' - prnt('int %s(char *out_error)' % funcname) - prnt('{') - self._check_int_constant_value(name, check_value) - prnt(' return 0;') - prnt('}') - elif is_int: - assert category == 'const' - prnt('int %s(long long *out_value)' % funcname) - prnt('{') - prnt(' *out_value = (long long)(%s);' % (name,)) - prnt(' return (%s) <= 0;' % (name,)) - prnt('}') - else: - assert tp is not None - assert check_value is None - if category == 'var': - ampersand = '&' - else: - ampersand = '' - extra = '' - if category == 'const' and isinstance(tp, model.StructOrUnion): - extra = 'const *' - ampersand = '&' - prnt(tp.get_c_name(' %s%s(void)' % (extra, funcname), name)) - prnt('{') - prnt(' return (%s%s);' % (ampersand, name)) - prnt('}') - prnt() - - def _generate_gen_constant_decl(self, tp, name): - is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() - self._generate_gen_const(is_int, name, tp) - - _loading_gen_constant = _loaded_noop - - def _load_constant(self, is_int, tp, name, module, check_value=None): - funcname = '_cffi_const_%s' % name - if check_value is not None: - assert is_int - self._load_known_int_constant(module, funcname) - value = check_value - elif is_int: - BType = self.ffi._typeof_locked("long long*")[0] - BFunc = self.ffi._typeof_locked("int(*)(long long*)")[0] - function = module.load_function(BFunc, funcname) - p = self.ffi.new(BType) - negative = function(p) - value = int(p[0]) - if value < 0 and not negative: - BLongLong = self.ffi._typeof_locked("long long")[0] - value += (1 << (8*self.ffi.sizeof(BLongLong))) - else: - assert check_value is None - fntypeextra = '(*)(void)' - if isinstance(tp, model.StructOrUnion): - fntypeextra = '*' + fntypeextra - BFunc = self.ffi._typeof_locked(tp.get_c_name(fntypeextra, name))[0] - function = module.load_function(BFunc, funcname) - value = function() - if isinstance(tp, model.StructOrUnion): - value = value[0] - return value - - def _loaded_gen_constant(self, tp, name, module, library): - is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() - value = self._load_constant(is_int, tp, name, module) - setattr(library, name, value) - type(library)._cffi_dir.append(name) - - # ---------- - # enums - - def _check_int_constant_value(self, name, value): - prnt = self._prnt - if value <= 0: - prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % ( - name, name, value)) - else: - prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % ( - name, name, value)) - prnt(' char buf[64];') - prnt(' if ((%s) <= 0)' % name) - prnt(' sprintf(buf, "%%ld", (long)(%s));' % name) - prnt(' else') - prnt(' sprintf(buf, "%%lu", (unsigned long)(%s));' % - name) - prnt(' sprintf(out_error, "%s has the real value %s, not %s",') - prnt(' "%s", buf, "%d");' % (name[:100], value)) - prnt(' return -1;') - prnt(' }') - - def _load_known_int_constant(self, module, funcname): - BType = self.ffi._typeof_locked("char[]")[0] - BFunc = self.ffi._typeof_locked("int(*)(char*)")[0] - function = module.load_function(BFunc, funcname) - p = self.ffi.new(BType, 256) - if function(p) < 0: - error = self.ffi.string(p) - if sys.version_info >= (3,): - error = str(error, 'utf-8') - raise VerificationError(error) - - def _enum_funcname(self, prefix, name): - # "$enum_$1" => "___D_enum____D_1" - name = name.replace('$', '___D_') - return '_cffi_e_%s_%s' % (prefix, name) - - def _generate_gen_enum_decl(self, tp, name, prefix='enum'): - if tp.partial: - for enumerator in tp.enumerators: - self._generate_gen_const(True, enumerator) - return - # - funcname = self._enum_funcname(prefix, name) - self.export_symbols.append(funcname) - prnt = self._prnt - prnt('int %s(char *out_error)' % funcname) - prnt('{') - for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): - self._check_int_constant_value(enumerator, enumvalue) - prnt(' return 0;') - prnt('}') - prnt() - - def _loading_gen_enum(self, tp, name, module, prefix='enum'): - if tp.partial: - enumvalues = [self._load_constant(True, tp, enumerator, module) - for enumerator in tp.enumerators] - tp.enumvalues = tuple(enumvalues) - tp.partial_resolved = True - else: - funcname = self._enum_funcname(prefix, name) - self._load_known_int_constant(module, funcname) - - def _loaded_gen_enum(self, tp, name, module, library): - for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): - setattr(library, enumerator, enumvalue) - type(library)._cffi_dir.append(enumerator) - - # ---------- - # macros: for now only for integers - - def _generate_gen_macro_decl(self, tp, name): - if tp == '...': - check_value = None - else: - check_value = tp # an integer - self._generate_gen_const(True, name, check_value=check_value) - - _loading_gen_macro = _loaded_noop - - def _loaded_gen_macro(self, tp, name, module, library): - if tp == '...': - check_value = None - else: - check_value = tp # an integer - value = self._load_constant(True, tp, name, module, - check_value=check_value) - setattr(library, name, value) - type(library)._cffi_dir.append(name) - - # ---------- - # global variables - - def _generate_gen_variable_decl(self, tp, name): - if isinstance(tp, model.ArrayType): - if tp.length_is_unknown(): - prnt = self._prnt - funcname = '_cffi_sizeof_%s' % (name,) - self.export_symbols.append(funcname) - prnt("size_t %s(void)" % funcname) - prnt("{") - prnt(" return sizeof(%s);" % (name,)) - prnt("}") - tp_ptr = model.PointerType(tp.item) - self._generate_gen_const(False, name, tp_ptr) - else: - tp_ptr = model.PointerType(tp) - self._generate_gen_const(False, name, tp_ptr, category='var') - - _loading_gen_variable = _loaded_noop - - def _loaded_gen_variable(self, tp, name, module, library): - if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the - # sense that "a=..." is forbidden - if tp.length_is_unknown(): - funcname = '_cffi_sizeof_%s' % (name,) - BFunc = self.ffi._typeof_locked('size_t(*)(void)')[0] - function = module.load_function(BFunc, funcname) - size = function() - BItemType = self.ffi._get_cached_btype(tp.item) - length, rest = divmod(size, self.ffi.sizeof(BItemType)) - if rest != 0: - raise VerificationError( - "bad size: %r does not seem to be an array of %s" % - (name, tp.item)) - tp = tp.resolve_length(length) - tp_ptr = model.PointerType(tp.item) - value = self._load_constant(False, tp_ptr, name, module) - # 'value' is a which we have to replace with - # a if the N is actually known - if tp.length is not None: - BArray = self.ffi._get_cached_btype(tp) - value = self.ffi.cast(BArray, value) - setattr(library, name, value) - type(library)._cffi_dir.append(name) - return - # remove ptr= from the library instance, and replace - # it by a property on the class, which reads/writes into ptr[0]. - funcname = '_cffi_var_%s' % name - BFunc = self.ffi._typeof_locked(tp.get_c_name('*(*)(void)', name))[0] - function = module.load_function(BFunc, funcname) - ptr = function() - def getter(library): - return ptr[0] - def setter(library, value): - ptr[0] = value - setattr(type(library), name, property(getter, setter)) - type(library)._cffi_dir.append(name) - -cffimod_header = r''' -#include -#include -#include -#include -#include /* XXX for ssize_t on some platforms */ - -/* this block of #ifs should be kept exactly identical between - c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py - and cffi/_cffi_include.h */ -#if defined(_MSC_VER) -# include /* for alloca() */ -# if _MSC_VER < 1600 /* MSVC < 2010 */ - typedef __int8 int8_t; - typedef __int16 int16_t; - typedef __int32 int32_t; - typedef __int64 int64_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; - typedef unsigned __int64 uint64_t; - typedef __int8 int_least8_t; - typedef __int16 int_least16_t; - typedef __int32 int_least32_t; - typedef __int64 int_least64_t; - typedef unsigned __int8 uint_least8_t; - typedef unsigned __int16 uint_least16_t; - typedef unsigned __int32 uint_least32_t; - typedef unsigned __int64 uint_least64_t; - typedef __int8 int_fast8_t; - typedef __int16 int_fast16_t; - typedef __int32 int_fast32_t; - typedef __int64 int_fast64_t; - typedef unsigned __int8 uint_fast8_t; - typedef unsigned __int16 uint_fast16_t; - typedef unsigned __int32 uint_fast32_t; - typedef unsigned __int64 uint_fast64_t; - typedef __int64 intmax_t; - typedef unsigned __int64 uintmax_t; -# else -# include -# endif -# if _MSC_VER < 1800 /* MSVC < 2013 */ -# ifndef __cplusplus - typedef unsigned char _Bool; -# endif -# endif -# define _cffi_float_complex_t _Fcomplex /* include for it */ -# define _cffi_double_complex_t _Dcomplex /* include for it */ -#else -# include -# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) -# include -# endif -# define _cffi_float_complex_t float _Complex -# define _cffi_double_complex_t double _Complex -#endif -''' diff --git a/notification-service/venv/Lib/site-packages/cffi/verifier.py b/notification-service/venv/Lib/site-packages/cffi/verifier.py deleted file mode 100644 index e392a2b..0000000 --- a/notification-service/venv/Lib/site-packages/cffi/verifier.py +++ /dev/null @@ -1,306 +0,0 @@ -# -# DEPRECATED: implementation for ffi.verify() -# -import sys, os, binascii, shutil, io -from . import __version_verifier_modules__ -from . import ffiplatform -from .error import VerificationError - -if sys.version_info >= (3, 3): - import importlib.machinery - def _extension_suffixes(): - return importlib.machinery.EXTENSION_SUFFIXES[:] -else: - import imp - def _extension_suffixes(): - return [suffix for suffix, _, type in imp.get_suffixes() - if type == imp.C_EXTENSION] - - -if sys.version_info >= (3,): - NativeIO = io.StringIO -else: - class NativeIO(io.BytesIO): - def write(self, s): - if isinstance(s, unicode): - s = s.encode('ascii') - super(NativeIO, self).write(s) - - -class Verifier(object): - - def __init__(self, ffi, preamble, tmpdir=None, modulename=None, - ext_package=None, tag='', force_generic_engine=False, - source_extension='.c', flags=None, relative_to=None, **kwds): - if ffi._parser._uses_new_feature: - raise VerificationError( - "feature not supported with ffi.verify(), but only " - "with ffi.set_source(): %s" % (ffi._parser._uses_new_feature,)) - self.ffi = ffi - self.preamble = preamble - if not modulename: - flattened_kwds = ffiplatform.flatten(kwds) - vengine_class = _locate_engine_class(ffi, force_generic_engine) - self._vengine = vengine_class(self) - self._vengine.patch_extension_kwds(kwds) - self.flags = flags - self.kwds = self.make_relative_to(kwds, relative_to) - # - if modulename: - if tag: - raise TypeError("can't specify both 'modulename' and 'tag'") - else: - key = '\x00'.join(['%d.%d' % sys.version_info[:2], - __version_verifier_modules__, - preamble, flattened_kwds] + - ffi._cdefsources) - if sys.version_info >= (3,): - key = key.encode('utf-8') - k1 = hex(binascii.crc32(key[0::2]) & 0xffffffff) - k1 = k1.lstrip('0x').rstrip('L') - k2 = hex(binascii.crc32(key[1::2]) & 0xffffffff) - k2 = k2.lstrip('0').rstrip('L') - modulename = '_cffi_%s_%s%s%s' % (tag, self._vengine._class_key, - k1, k2) - suffix = _get_so_suffixes()[0] - self.tmpdir = tmpdir or _caller_dir_pycache() - self.sourcefilename = os.path.join(self.tmpdir, modulename + source_extension) - self.modulefilename = os.path.join(self.tmpdir, modulename + suffix) - self.ext_package = ext_package - self._has_source = False - self._has_module = False - - def write_source(self, file=None): - """Write the C source code. It is produced in 'self.sourcefilename', - which can be tweaked beforehand.""" - with self.ffi._lock: - if self._has_source and file is None: - raise VerificationError( - "source code already written") - self._write_source(file) - - def compile_module(self): - """Write the C source code (if not done already) and compile it. - This produces a dynamic link library in 'self.modulefilename'.""" - with self.ffi._lock: - if self._has_module: - raise VerificationError("module already compiled") - if not self._has_source: - self._write_source() - self._compile_module() - - def load_library(self): - """Get a C module from this Verifier instance. - Returns an instance of a FFILibrary class that behaves like the - objects returned by ffi.dlopen(), but that delegates all - operations to the C module. If necessary, the C code is written - and compiled first. - """ - with self.ffi._lock: - if not self._has_module: - self._locate_module() - if not self._has_module: - if not self._has_source: - self._write_source() - self._compile_module() - return self._load_library() - - def get_module_name(self): - basename = os.path.basename(self.modulefilename) - # kill both the .so extension and the other .'s, as introduced - # by Python 3: 'basename.cpython-33m.so' - basename = basename.split('.', 1)[0] - # and the _d added in Python 2 debug builds --- but try to be - # conservative and not kill a legitimate _d - if basename.endswith('_d') and hasattr(sys, 'gettotalrefcount'): - basename = basename[:-2] - return basename - - def get_extension(self): - if not self._has_source: - with self.ffi._lock: - if not self._has_source: - self._write_source() - sourcename = ffiplatform.maybe_relative_path(self.sourcefilename) - modname = self.get_module_name() - return ffiplatform.get_extension(sourcename, modname, **self.kwds) - - def generates_python_module(self): - return self._vengine._gen_python_module - - def make_relative_to(self, kwds, relative_to): - if relative_to and os.path.dirname(relative_to): - dirname = os.path.dirname(relative_to) - kwds = kwds.copy() - for key in ffiplatform.LIST_OF_FILE_NAMES: - if key in kwds: - lst = kwds[key] - if not isinstance(lst, (list, tuple)): - raise TypeError("keyword '%s' should be a list or tuple" - % (key,)) - lst = [os.path.join(dirname, fn) for fn in lst] - kwds[key] = lst - return kwds - - # ---------- - - def _locate_module(self): - if not os.path.isfile(self.modulefilename): - if self.ext_package: - try: - pkg = __import__(self.ext_package, None, None, ['__doc__']) - except ImportError: - return # cannot import the package itself, give up - # (e.g. it might be called differently before installation) - path = pkg.__path__ - else: - path = None - filename = self._vengine.find_module(self.get_module_name(), path, - _get_so_suffixes()) - if filename is None: - return - self.modulefilename = filename - self._vengine.collect_types() - self._has_module = True - - def _write_source_to(self, file): - self._vengine._f = file - try: - self._vengine.write_source_to_f() - finally: - del self._vengine._f - - def _write_source(self, file=None): - if file is not None: - self._write_source_to(file) - else: - # Write our source file to an in memory file. - f = NativeIO() - self._write_source_to(f) - source_data = f.getvalue() - - # Determine if this matches the current file - if os.path.exists(self.sourcefilename): - with open(self.sourcefilename, "r") as fp: - needs_written = not (fp.read() == source_data) - else: - needs_written = True - - # Actually write the file out if it doesn't match - if needs_written: - _ensure_dir(self.sourcefilename) - with open(self.sourcefilename, "w") as fp: - fp.write(source_data) - - # Set this flag - self._has_source = True - - def _compile_module(self): - # compile this C source - tmpdir = os.path.dirname(self.sourcefilename) - outputfilename = ffiplatform.compile(tmpdir, self.get_extension()) - try: - same = ffiplatform.samefile(outputfilename, self.modulefilename) - except OSError: - same = False - if not same: - _ensure_dir(self.modulefilename) - shutil.move(outputfilename, self.modulefilename) - self._has_module = True - - def _load_library(self): - assert self._has_module - if self.flags is not None: - return self._vengine.load_library(self.flags) - else: - return self._vengine.load_library() - -# ____________________________________________________________ - -_FORCE_GENERIC_ENGINE = False # for tests - -def _locate_engine_class(ffi, force_generic_engine): - if _FORCE_GENERIC_ENGINE: - force_generic_engine = True - if not force_generic_engine: - if '__pypy__' in sys.builtin_module_names: - force_generic_engine = True - else: - try: - import _cffi_backend - except ImportError: - _cffi_backend = '?' - if ffi._backend is not _cffi_backend: - force_generic_engine = True - if force_generic_engine: - from . import vengine_gen - return vengine_gen.VGenericEngine - else: - from . import vengine_cpy - return vengine_cpy.VCPythonEngine - -# ____________________________________________________________ - -_TMPDIR = None - -def _caller_dir_pycache(): - if _TMPDIR: - return _TMPDIR - result = os.environ.get('CFFI_TMPDIR') - if result: - return result - filename = sys._getframe(2).f_code.co_filename - return os.path.abspath(os.path.join(os.path.dirname(filename), - '__pycache__')) - -def set_tmpdir(dirname): - """Set the temporary directory to use instead of __pycache__.""" - global _TMPDIR - _TMPDIR = dirname - -def cleanup_tmpdir(tmpdir=None, keep_so=False): - """Clean up the temporary directory by removing all files in it - called `_cffi_*.{c,so}` as well as the `build` subdirectory.""" - tmpdir = tmpdir or _caller_dir_pycache() - try: - filelist = os.listdir(tmpdir) - except OSError: - return - if keep_so: - suffix = '.c' # only remove .c files - else: - suffix = _get_so_suffixes()[0].lower() - for fn in filelist: - if fn.lower().startswith('_cffi_') and ( - fn.lower().endswith(suffix) or fn.lower().endswith('.c')): - try: - os.unlink(os.path.join(tmpdir, fn)) - except OSError: - pass - clean_dir = [os.path.join(tmpdir, 'build')] - for dir in clean_dir: - try: - for fn in os.listdir(dir): - fn = os.path.join(dir, fn) - if os.path.isdir(fn): - clean_dir.append(fn) - else: - os.unlink(fn) - except OSError: - pass - -def _get_so_suffixes(): - suffixes = _extension_suffixes() - if not suffixes: - # bah, no C_EXTENSION available. Occurs on pypy without cpyext - if sys.platform == 'win32': - suffixes = [".pyd"] - else: - suffixes = [".so"] - - return suffixes - -def _ensure_dir(filename): - dirname = os.path.dirname(filename) - if dirname and not os.path.isdir(dirname): - os.makedirs(dirname) diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/INSTALLER b/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/METADATA b/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/METADATA deleted file mode 100644 index 6b5a360..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/METADATA +++ /dev/null @@ -1,808 +0,0 @@ -Metadata-Version: 2.4 -Name: charset-normalizer -Version: 3.4.7 -Summary: The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet. -Author-email: "Ahmed R. TAHRI" -Maintainer-email: "Ahmed R. TAHRI" -License: MIT -Project-URL: Changelog, https://github.com/jawah/charset_normalizer/blob/master/CHANGELOG.md -Project-URL: Documentation, https://charset-normalizer.readthedocs.io/ -Project-URL: Code, https://github.com/jawah/charset_normalizer -Project-URL: Issue tracker, https://github.com/jawah/charset_normalizer/issues -Keywords: encoding,charset,charset-detector,detector,normalization,unicode,chardet,detect -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -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 :: Only -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Programming Language :: Python :: Free Threading :: 4 - Resilient -Classifier: Topic :: Text Processing :: Linguistic -Classifier: Topic :: Utilities -Classifier: Typing :: Typed -Requires-Python: >=3.7 -Description-Content-Type: text/markdown -License-File: LICENSE -Provides-Extra: unicode-backport -Dynamic: license-file - -

Charset Detection, for Everyone 👋

- -

- The Real First Universal Charset Detector
- - - - - Download Count Total - - - - -

-

- Featured Packages
- - Static Badge - - - Static Badge - -

-

- In other language (unofficial port - by the community)
- - Static Badge - -

- -> A library that helps you read text from an unknown charset encoding.
Motivated by `chardet`, -> I'm trying to resolve the issue by taking a new approach. -> All IANA character set names for which the Python core library provides codecs are supported. -> You can also register your own set of codecs, and yes, it would work as-is. - -

- >>>>> 👉 Try Me Online Now, Then Adopt Me 👈 <<<<< -

- -This project offers you an alternative to **Universal Charset Encoding Detector**, also known as **Chardet**. - -| Feature | [Chardet](https://github.com/chardet/chardet) | Charset Normalizer | [cChardet](https://github.com/PyYoshi/cChardet) | -|--------------------------------------------------|:---------------------------------------------:|:-----------------------------------------------------------------------------------------------:|:-----------------------------------------------:| -| `Fast` | ✅ | ✅ | ✅ | -| `Universal`[^1] | ❌ | ✅ | ❌ | -| `Reliable` **without** distinguishable standards | ✅ | ✅ | ✅ | -| `Reliable` **with** distinguishable standards | ✅ | ✅ | ✅ | -| `License` | _Disputed_[^2]
_restrictive_ | MIT | MPL-1.1
_restrictive_ | -| `Native Python` | ✅ | ✅ | ❌ | -| `Detect spoken language` | ✅ | ✅ | N/A | -| `UnicodeDecodeError Safety` | ✅ | ✅ | ❌ | -| `Whl Size (min)` | 500 kB | 150 kB | ~200 kB | -| `Supported Encoding` | 99 | [99](https://charset-normalizer.readthedocs.io/en/latest/user/support.html#supported-encodings) | 40 | -| `Can register custom encoding` | ❌ | ✅ | ❌ | - -

-Reading Normalized TextCat Reading Text -

- -[^1]: They are clearly using specific code for a specific encoding even if covering most of used one. -[^2]: Chardet 7.0+ was relicensed from LGPL-2.1 to MIT following an AI-assisted rewrite. This relicensing is disputed on two independent grounds: **(a)** the original author [contests](https://github.com/chardet/chardet/issues/327) that the maintainer had the right to relicense, arguing the rewrite is a derivative work of the LGPL-licensed codebase since it was not a clean room implementation; **(b)** the copyright claim itself is [questionable](https://github.com/chardet/chardet/issues/334) given the code was primarily generated by an LLM, and AI-generated output may not be copyrightable under most jurisdictions. Either issue alone could undermine the MIT license. Beyond licensing, the rewrite raises questions about responsible use of AI in open source: key architectural ideas pioneered by charset-normalizer - notably decode-first validity filtering (our foundational approach since v1) and encoding pairwise similarity with the same algorithm and threshold — surfaced in chardet 7 without acknowledgment. The project also imported test files from charset-normalizer to train and benchmark against it, then claimed superior accuracy on those very files. Charset-normalizer has always been MIT-licensed, encoding-agnostic by design, and built on a verifiable human-authored history. - -## ⚡ Performance - -This package offer better performances (99th, and 95th) against Chardet. Here are some numbers. - -| Package | Accuracy | Mean per file (ms) | File per sec (est) | -|---------------------------------------------------|:--------:|:------------------:|:------------------:| -| [chardet 7.1](https://github.com/chardet/chardet) | 89 % | 3 ms | 333 file/sec | -| charset-normalizer | **97 %** | 3 ms | 333 file/sec | - -| Package | 99th percentile | 95th percentile | 50th percentile | -|---------------------------------------------------|:---------------:|:---------------:|:---------------:| -| [chardet 7.1](https://github.com/chardet/chardet) | 32 ms | 17 ms | < 1 ms | -| charset-normalizer | 16 ms | 10 ms | 1 ms | - -_updated as of March 2026 using CPython 3.12, Charset-Normalizer 3.4.6, and Chardet 7.1.0_ - -~Chardet's performance on larger file (1MB+) are very poor. Expect huge difference on large payload.~ No longer the case since Chardet 7.0+ - -> Stats are generated using 400+ files using default parameters. More details on used files, see GHA workflows. -> And yes, these results might change at any time. The dataset can be updated to include more files. -> The actual delays heavily depends on your CPU capabilities. The factors should remain the same. -> Chardet claims on his documentation to have a greater accuracy than us based on the dataset they trained Chardet on(...) -> Well, it's normal, the opposite would have been worrying. Whereas charset-normalizer don't train on anything, our solution -> is based on a completely different algorithm, still heuristic through, it does not need weights across every encoding tables. - -## ✨ Installation - -Using pip: - -```sh -pip install charset-normalizer -U -``` - -## 🚀 Basic Usage - -### CLI -This package comes with a CLI. - -``` -usage: normalizer [-h] [-v] [-a] [-n] [-m] [-r] [-f] [-t THRESHOLD] - file [file ...] - -The Real First Universal Charset Detector. Discover originating encoding used -on text file. Normalize text to unicode. - -positional arguments: - files File(s) to be analysed - -optional arguments: - -h, --help show this help message and exit - -v, --verbose Display complementary information about file if any. - Stdout will contain logs about the detection process. - -a, --with-alternative - Output complementary possibilities if any. Top-level - JSON WILL be a list. - -n, --normalize Permit to normalize input file. If not set, program - does not write anything. - -m, --minimal Only output the charset detected to STDOUT. Disabling - JSON output. - -r, --replace Replace file when trying to normalize it instead of - creating a new one. - -f, --force Replace file without asking if you are sure, use this - flag with caution. - -t THRESHOLD, --threshold THRESHOLD - Define a custom maximum amount of chaos allowed in - decoded content. 0. <= chaos <= 1. - --version Show version information and exit. -``` - -```bash -normalizer ./data/sample.1.fr.srt -``` - -or - -```bash -python -m charset_normalizer ./data/sample.1.fr.srt -``` - -🎉 Since version 1.4.0 the CLI produce easily usable stdout result in JSON format. - -```json -{ - "path": "/home/default/projects/charset_normalizer/data/sample.1.fr.srt", - "encoding": "cp1252", - "encoding_aliases": [ - "1252", - "windows_1252" - ], - "alternative_encodings": [ - "cp1254", - "cp1256", - "cp1258", - "iso8859_14", - "iso8859_15", - "iso8859_16", - "iso8859_3", - "iso8859_9", - "latin_1", - "mbcs" - ], - "language": "French", - "alphabets": [ - "Basic Latin", - "Latin-1 Supplement" - ], - "has_sig_or_bom": false, - "chaos": 0.149, - "coherence": 97.152, - "unicode_path": null, - "is_preferred": true -} -``` - -### Python -*Just print out normalized text* -```python -from charset_normalizer import from_path - -results = from_path('./my_subtitle.srt') - -print(str(results.best())) -``` - -*Upgrade your code without effort* -```python -from charset_normalizer import detect -``` - -The above code will behave the same as **chardet**. We ensure that we offer the best (reasonable) BC result possible. - -See the docs for advanced usage : [readthedocs.io](https://charset-normalizer.readthedocs.io/en/latest/) - -## 😇 Why - -When I started using Chardet, I noticed that it was not suited to my expectations, and I wanted to propose a -reliable alternative using a completely different method. Also! I never back down on a good challenge! - -I **don't care** about the **originating charset** encoding, because **two different tables** can -produce **two identical rendered string.** -What I want is to get readable text, the best I can. - -In a way, **I'm brute forcing text decoding.** How cool is that ? 😎 - -Don't confuse package **ftfy** with charset-normalizer or chardet. ftfy goal is to repair Unicode string whereas charset-normalizer to convert raw file in unknown encoding to unicode. - -## 🍰 How - - - Discard all charset encoding table that could not fit the binary content. - - Measure noise, or the mess once opened (by chunks) with a corresponding charset encoding. - - Extract matches with the lowest mess detected. - - Additionally, we measure coherence / probe for a language. - -**Wait a minute**, what is noise/mess and coherence according to **YOU ?** - -*Noise :* I opened hundred of text files, **written by humans**, with the wrong encoding table. **I observed**, then -**I established** some ground rules about **what is obvious** when **it seems like** a mess (aka. defining noise in rendered text). - I know that my interpretation of what is noise is probably incomplete, feel free to contribute in order to - improve or rewrite it. - -*Coherence :* For each language there is on earth, we have computed ranked letter appearance occurrences (the best we can). So I thought -that intel is worth something here. So I use those records against decoded text to check if I can detect intelligent design. - -## ⚡ Known limitations - - - Language detection is unreliable when text contains two or more languages sharing identical letters. (eg. HTML (english tags) + Turkish content (Sharing Latin characters)) - - Every charset detector heavily depends on sufficient content. In common cases, do not bother run detection on very tiny content. - -## ⚠️ About Python EOLs - -**If you are running:** - -- Python >=2.7,<3.5: Unsupported -- Python 3.5: charset-normalizer < 2.1 -- Python 3.6: charset-normalizer < 3.1 - -Upgrade your Python interpreter as soon as possible. - -## 👤 Contributing - -Contributions, issues and feature requests are very much welcome.
-Feel free to check [issues page](https://github.com/ousret/charset_normalizer/issues) if you want to contribute. - -## 📝 License - -Copyright © [Ahmed TAHRI @Ousret](https://github.com/Ousret).
-This project is [MIT](https://github.com/Ousret/charset_normalizer/blob/master/LICENSE) licensed. - -Characters frequencies used in this project © 2012 [Denny Vrandečić](http://simia.net/letters/) - -## 💼 For Enterprise - -Professional support for charset-normalizer is available as part of the [Tidelift -Subscription][1]. Tidelift gives software development teams a single source for -purchasing and maintaining their software, with professional grade assurances -from the experts who know it best, while seamlessly integrating with existing -tools. - -[1]: https://tidelift.com/subscription/pkg/pypi-charset-normalizer?utm_source=pypi-charset-normalizer&utm_medium=readme - -[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7297/badge)](https://www.bestpractices.dev/projects/7297) - -# Changelog -All notable changes to charset-normalizer will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - -## [3.4.7](https://github.com/Ousret/charset_normalizer/compare/3.4.6...3.4.7) (2026-04-02) - -### Changed -- Pre-built optimized version using mypy[c] v1.20. -- Relax `setuptools` constraint to `setuptools>=68,<82.1`. - -### Fixed -- Correctly remove SIG remnant in utf-7 decoded string. (#718) (#716) - -## [3.4.6](https://github.com/Ousret/charset_normalizer/compare/3.4.5...3.4.6) (2026-03-15) - -### Changed -- Flattened the logic in `charset_normalizer.md` for higher performance. Removed `eligible(..)` and `feed(...)` - in favor of `feed_info(...)`. -- Raised upper bound for mypy[c] to 1.20, for our optimized version. -- Updated `UNICODE_RANGES_COMBINED` using Unicode blocks v17. - -### Fixed -- Edge case where noise difference between two candidates can be almost insignificant. (#672) -- CLI `--normalize` writing to wrong path when passing multiple files in. (#702) - -### Misc -- Freethreaded pre-built wheels now shipped in PyPI starting with 3.14t. (#616) - -## [3.4.5](https://github.com/Ousret/charset_normalizer/compare/3.4.4...3.4.5) (2026-03-06) - -### Changed -- Update `setuptools` constraint to `setuptools>=68,<=82`. -- Raised upper bound of mypyc for the optional pre-built extension to v1.19.1 - -### Fixed -- Add explicit link to lib math in our optimized build. (#692) -- Logger level not restored correctly for empty byte sequences. (#701) -- TypeError when passing bytearray to from_bytes. (#703) - -### Misc -- Applied safe micro-optimizations in both our noise detector and language detector. -- Rewrote the `query_yes_no` function (inside CLI) to avoid using ambiguous licensed code. -- Added `cd.py` submodule into mypyc optional compilation to reduce further the performance impact. - -## [3.4.4](https://github.com/Ousret/charset_normalizer/compare/3.4.2...3.4.4) (2025-10-13) - -### Changed -- Bound `setuptools` to a specific constraint `setuptools>=68,<=81`. -- Raised upper bound of mypyc for the optional pre-built extension to v1.18.2 - -### Removed -- `setuptools-scm` as a build dependency. - -### Misc -- Enforced hashes in `dev-requirements.txt` and created `ci-requirements.txt` for security purposes. -- Additional pre-built wheels for riscv64, s390x, and armv7l architectures. -- Restore ` multiple.intoto.jsonl` in GitHub releases in addition to individual attestation file per wheel. - -## [3.4.3](https://github.com/Ousret/charset_normalizer/compare/3.4.2...3.4.3) (2025-08-09) - -### Changed -- mypy(c) is no longer a required dependency at build time if `CHARSET_NORMALIZER_USE_MYPYC` isn't set to `1`. (#595) (#583) -- automatically lower confidence on small bytes samples that are not Unicode in `detect` output legacy function. (#391) - -### Added -- Custom build backend to overcome inability to mark mypy as an optional dependency in the build phase. -- Support for Python 3.14 - -### Fixed -- sdist archive contained useless directories. -- automatically fallback on valid UTF-16 or UTF-32 even if the md says it's noisy. (#633) - -### Misc -- SBOM are automatically published to the relevant GitHub release to comply with regulatory changes. - Each published wheel comes with its SBOM. We choose CycloneDX as the format. -- Prebuilt optimized wheel are no longer distributed by default for CPython 3.7 due to a change in cibuildwheel. - -## [3.4.2](https://github.com/Ousret/charset_normalizer/compare/3.4.1...3.4.2) (2025-05-02) - -### Fixed -- Addressed the DeprecationWarning in our CLI regarding `argparse.FileType` by backporting the target class into the package. (#591) -- Improved the overall reliability of the detector with CJK Ideographs. (#605) (#587) - -### Changed -- Optional mypyc compilation upgraded to version 1.15 for Python >= 3.8 - -## [3.4.1](https://github.com/Ousret/charset_normalizer/compare/3.4.0...3.4.1) (2024-12-24) - -### Changed -- Project metadata are now stored using `pyproject.toml` instead of `setup.cfg` using setuptools as the build backend. -- Enforce annotation delayed loading for a simpler and consistent types in the project. -- Optional mypyc compilation upgraded to version 1.14 for Python >= 3.8 - -### Added -- pre-commit configuration. -- noxfile. - -### Removed -- `build-requirements.txt` as per using `pyproject.toml` native build configuration. -- `bin/integration.py` and `bin/serve.py` in favor of downstream integration test (see noxfile). -- `setup.cfg` in favor of `pyproject.toml` metadata configuration. -- Unused `utils.range_scan` function. - -### Fixed -- Converting content to Unicode bytes may insert `utf_8` instead of preferred `utf-8`. (#572) -- Deprecation warning "'count' is passed as positional argument" when converting to Unicode bytes on Python 3.13+ - -## [3.4.0](https://github.com/Ousret/charset_normalizer/compare/3.3.2...3.4.0) (2024-10-08) - -### Added -- Argument `--no-preemptive` in the CLI to prevent the detector to search for hints. -- Support for Python 3.13 (#512) - -### Fixed -- Relax the TypeError exception thrown when trying to compare a CharsetMatch with anything else than a CharsetMatch. -- Improved the general reliability of the detector based on user feedbacks. (#520) (#509) (#498) (#407) (#537) -- Declared charset in content (preemptive detection) not changed when converting to utf-8 bytes. (#381) - -## [3.3.2](https://github.com/Ousret/charset_normalizer/compare/3.3.1...3.3.2) (2023-10-31) - -### Fixed -- Unintentional memory usage regression when using large payload that match several encoding (#376) -- Regression on some detection case showcased in the documentation (#371) - -### Added -- Noise (md) probe that identify malformed arabic representation due to the presence of letters in isolated form (credit to my wife) - -## [3.3.1](https://github.com/Ousret/charset_normalizer/compare/3.3.0...3.3.1) (2023-10-22) - -### Changed -- Optional mypyc compilation upgraded to version 1.6.1 for Python >= 3.8 -- Improved the general detection reliability based on reports from the community - -## [3.3.0](https://github.com/Ousret/charset_normalizer/compare/3.2.0...3.3.0) (2023-09-30) - -### Added -- Allow to execute the CLI (e.g. normalizer) through `python -m charset_normalizer.cli` or `python -m charset_normalizer` -- Support for 9 forgotten encoding that are supported by Python but unlisted in `encoding.aliases` as they have no alias (#323) - -### Removed -- (internal) Redundant utils.is_ascii function and unused function is_private_use_only -- (internal) charset_normalizer.assets is moved inside charset_normalizer.constant - -### Changed -- (internal) Unicode code blocks in constants are updated using the latest v15.0.0 definition to improve detection -- Optional mypyc compilation upgraded to version 1.5.1 for Python >= 3.8 - -### Fixed -- Unable to properly sort CharsetMatch when both chaos/noise and coherence were close due to an unreachable condition in \_\_lt\_\_ (#350) - -## [3.2.0](https://github.com/Ousret/charset_normalizer/compare/3.1.0...3.2.0) (2023-06-07) - -### Changed -- Typehint for function `from_path` no longer enforce `PathLike` as its first argument -- Minor improvement over the global detection reliability - -### Added -- Introduce function `is_binary` that relies on main capabilities, and optimized to detect binaries -- Propagate `enable_fallback` argument throughout `from_bytes`, `from_path`, and `from_fp` that allow a deeper control over the detection (default True) -- Explicit support for Python 3.12 - -### Fixed -- Edge case detection failure where a file would contain 'very-long' camel cased word (Issue #289) - -## [3.1.0](https://github.com/Ousret/charset_normalizer/compare/3.0.1...3.1.0) (2023-03-06) - -### Added -- Argument `should_rename_legacy` for legacy function `detect` and disregard any new arguments without errors (PR #262) - -### Removed -- Support for Python 3.6 (PR #260) - -### Changed -- Optional speedup provided by mypy/c 1.0.1 - -## [3.0.1](https://github.com/Ousret/charset_normalizer/compare/3.0.0...3.0.1) (2022-11-18) - -### Fixed -- Multi-bytes cutter/chunk generator did not always cut correctly (PR #233) - -### Changed -- Speedup provided by mypy/c 0.990 on Python >= 3.7 - -## [3.0.0](https://github.com/Ousret/charset_normalizer/compare/2.1.1...3.0.0) (2022-10-20) - -### Added -- Extend the capability of explain=True when cp_isolation contains at most two entries (min one), will log in details of the Mess-detector results -- Support for alternative language frequency set in charset_normalizer.assets.FREQUENCIES -- Add parameter `language_threshold` in `from_bytes`, `from_path` and `from_fp` to adjust the minimum expected coherence ratio -- `normalizer --version` now specify if current version provide extra speedup (meaning mypyc compilation whl) - -### Changed -- Build with static metadata using 'build' frontend -- Make the language detection stricter -- Optional: Module `md.py` can be compiled using Mypyc to provide an extra speedup up to 4x faster than v2.1 - -### Fixed -- CLI with opt --normalize fail when using full path for files -- TooManyAccentuatedPlugin induce false positive on the mess detection when too few alpha character have been fed to it -- Sphinx warnings when generating the documentation - -### Removed -- Coherence detector no longer return 'Simple English' instead return 'English' -- Coherence detector no longer return 'Classical Chinese' instead return 'Chinese' -- Breaking: Method `first()` and `best()` from CharsetMatch -- UTF-7 will no longer appear as "detected" without a recognized SIG/mark (is unreliable/conflict with ASCII) -- Breaking: Class aliases CharsetDetector, CharsetDoctor, CharsetNormalizerMatch and CharsetNormalizerMatches -- Breaking: Top-level function `normalize` -- Breaking: Properties `chaos_secondary_pass`, `coherence_non_latin` and `w_counter` from CharsetMatch -- Support for the backport `unicodedata2` - -## [3.0.0rc1](https://github.com/Ousret/charset_normalizer/compare/3.0.0b2...3.0.0rc1) (2022-10-18) - -### Added -- Extend the capability of explain=True when cp_isolation contains at most two entries (min one), will log in details of the Mess-detector results -- Support for alternative language frequency set in charset_normalizer.assets.FREQUENCIES -- Add parameter `language_threshold` in `from_bytes`, `from_path` and `from_fp` to adjust the minimum expected coherence ratio - -### Changed -- Build with static metadata using 'build' frontend -- Make the language detection stricter - -### Fixed -- CLI with opt --normalize fail when using full path for files -- TooManyAccentuatedPlugin induce false positive on the mess detection when too few alpha character have been fed to it - -### Removed -- Coherence detector no longer return 'Simple English' instead return 'English' -- Coherence detector no longer return 'Classical Chinese' instead return 'Chinese' - -## [3.0.0b2](https://github.com/Ousret/charset_normalizer/compare/3.0.0b1...3.0.0b2) (2022-08-21) - -### Added -- `normalizer --version` now specify if current version provide extra speedup (meaning mypyc compilation whl) - -### Removed -- Breaking: Method `first()` and `best()` from CharsetMatch -- UTF-7 will no longer appear as "detected" without a recognized SIG/mark (is unreliable/conflict with ASCII) - -### Fixed -- Sphinx warnings when generating the documentation - -## [3.0.0b1](https://github.com/Ousret/charset_normalizer/compare/2.1.0...3.0.0b1) (2022-08-15) - -### Changed -- Optional: Module `md.py` can be compiled using Mypyc to provide an extra speedup up to 4x faster than v2.1 - -### Removed -- Breaking: Class aliases CharsetDetector, CharsetDoctor, CharsetNormalizerMatch and CharsetNormalizerMatches -- Breaking: Top-level function `normalize` -- Breaking: Properties `chaos_secondary_pass`, `coherence_non_latin` and `w_counter` from CharsetMatch -- Support for the backport `unicodedata2` - -## [2.1.1](https://github.com/Ousret/charset_normalizer/compare/2.1.0...2.1.1) (2022-08-19) - -### Deprecated -- Function `normalize` scheduled for removal in 3.0 - -### Changed -- Removed useless call to decode in fn is_unprintable (#206) - -### Fixed -- Third-party library (i18n xgettext) crashing not recognizing utf_8 (PEP 263) with underscore from [@aleksandernovikov](https://github.com/aleksandernovikov) (#204) - -## [2.1.0](https://github.com/Ousret/charset_normalizer/compare/2.0.12...2.1.0) (2022-06-19) - -### Added -- Output the Unicode table version when running the CLI with `--version` (PR #194) - -### Changed -- Re-use decoded buffer for single byte character sets from [@nijel](https://github.com/nijel) (PR #175) -- Fixing some performance bottlenecks from [@deedy5](https://github.com/deedy5) (PR #183) - -### Fixed -- Workaround potential bug in cpython with Zero Width No-Break Space located in Arabic Presentation Forms-B, Unicode 1.1 not acknowledged as space (PR #175) -- CLI default threshold aligned with the API threshold from [@oleksandr-kuzmenko](https://github.com/oleksandr-kuzmenko) (PR #181) - -### Removed -- Support for Python 3.5 (PR #192) - -### Deprecated -- Use of backport unicodedata from `unicodedata2` as Python is quickly catching up, scheduled for removal in 3.0 (PR #194) - -## [2.0.12](https://github.com/Ousret/charset_normalizer/compare/2.0.11...2.0.12) (2022-02-12) - -### Fixed -- ASCII miss-detection on rare cases (PR #170) - -## [2.0.11](https://github.com/Ousret/charset_normalizer/compare/2.0.10...2.0.11) (2022-01-30) - -### Added -- Explicit support for Python 3.11 (PR #164) - -### Changed -- The logging behavior have been completely reviewed, now using only TRACE and DEBUG levels (PR #163 #165) - -## [2.0.10](https://github.com/Ousret/charset_normalizer/compare/2.0.9...2.0.10) (2022-01-04) - -### Fixed -- Fallback match entries might lead to UnicodeDecodeError for large bytes sequence (PR #154) - -### Changed -- Skipping the language-detection (CD) on ASCII (PR #155) - -## [2.0.9](https://github.com/Ousret/charset_normalizer/compare/2.0.8...2.0.9) (2021-12-03) - -### Changed -- Moderating the logging impact (since 2.0.8) for specific environments (PR #147) - -### Fixed -- Wrong logging level applied when setting kwarg `explain` to True (PR #146) - -## [2.0.8](https://github.com/Ousret/charset_normalizer/compare/2.0.7...2.0.8) (2021-11-24) -### Changed -- Improvement over Vietnamese detection (PR #126) -- MD improvement on trailing data and long foreign (non-pure latin) data (PR #124) -- Efficiency improvements in cd/alphabet_languages from [@adbar](https://github.com/adbar) (PR #122) -- call sum() without an intermediary list following PEP 289 recommendations from [@adbar](https://github.com/adbar) (PR #129) -- Code style as refactored by Sourcery-AI (PR #131) -- Minor adjustment on the MD around european words (PR #133) -- Remove and replace SRTs from assets / tests (PR #139) -- Initialize the library logger with a `NullHandler` by default from [@nmaynes](https://github.com/nmaynes) (PR #135) -- Setting kwarg `explain` to True will add provisionally (bounded to function lifespan) a specific stream handler (PR #135) - -### Fixed -- Fix large (misleading) sequence giving UnicodeDecodeError (PR #137) -- Avoid using too insignificant chunk (PR #137) - -### Added -- Add and expose function `set_logging_handler` to configure a specific StreamHandler from [@nmaynes](https://github.com/nmaynes) (PR #135) -- Add `CHANGELOG.md` entries, format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) (PR #141) - -## [2.0.7](https://github.com/Ousret/charset_normalizer/compare/2.0.6...2.0.7) (2021-10-11) -### Added -- Add support for Kazakh (Cyrillic) language detection (PR #109) - -### Changed -- Further, improve inferring the language from a given single-byte code page (PR #112) -- Vainly trying to leverage PEP263 when PEP3120 is not supported (PR #116) -- Refactoring for potential performance improvements in loops from [@adbar](https://github.com/adbar) (PR #113) -- Various detection improvement (MD+CD) (PR #117) - -### Removed -- Remove redundant logging entry about detected language(s) (PR #115) - -### Fixed -- Fix a minor inconsistency between Python 3.5 and other versions regarding language detection (PR #117 #102) - -## [2.0.6](https://github.com/Ousret/charset_normalizer/compare/2.0.5...2.0.6) (2021-09-18) -### Fixed -- Unforeseen regression with the loss of the backward-compatibility with some older minor of Python 3.5.x (PR #100) -- Fix CLI crash when using --minimal output in certain cases (PR #103) - -### Changed -- Minor improvement to the detection efficiency (less than 1%) (PR #106 #101) - -## [2.0.5](https://github.com/Ousret/charset_normalizer/compare/2.0.4...2.0.5) (2021-09-14) -### Changed -- The project now comply with: flake8, mypy, isort and black to ensure a better overall quality (PR #81) -- The BC-support with v1.x was improved, the old staticmethods are restored (PR #82) -- The Unicode detection is slightly improved (PR #93) -- Add syntax sugar \_\_bool\_\_ for results CharsetMatches list-container (PR #91) - -### Removed -- The project no longer raise warning on tiny content given for detection, will be simply logged as warning instead (PR #92) - -### Fixed -- In some rare case, the chunks extractor could cut in the middle of a multi-byte character and could mislead the mess detection (PR #95) -- Some rare 'space' characters could trip up the UnprintablePlugin/Mess detection (PR #96) -- The MANIFEST.in was not exhaustive (PR #78) - -## [2.0.4](https://github.com/Ousret/charset_normalizer/compare/2.0.3...2.0.4) (2021-07-30) -### Fixed -- The CLI no longer raise an unexpected exception when no encoding has been found (PR #70) -- Fix accessing the 'alphabets' property when the payload contains surrogate characters (PR #68) -- The logger could mislead (explain=True) on detected languages and the impact of one MBCS match (PR #72) -- Submatch factoring could be wrong in rare edge cases (PR #72) -- Multiple files given to the CLI were ignored when publishing results to STDOUT. (After the first path) (PR #72) -- Fix line endings from CRLF to LF for certain project files (PR #67) - -### Changed -- Adjust the MD to lower the sensitivity, thus improving the global detection reliability (PR #69 #76) -- Allow fallback on specified encoding if any (PR #71) - -## [2.0.3](https://github.com/Ousret/charset_normalizer/compare/2.0.2...2.0.3) (2021-07-16) -### Changed -- Part of the detection mechanism has been improved to be less sensitive, resulting in more accurate detection results. Especially ASCII. (PR #63) -- According to the community wishes, the detection will fall back on ASCII or UTF-8 in a last-resort case. (PR #64) - -## [2.0.2](https://github.com/Ousret/charset_normalizer/compare/2.0.1...2.0.2) (2021-07-15) -### Fixed -- Empty/Too small JSON payload miss-detection fixed. Report from [@tseaver](https://github.com/tseaver) (PR #59) - -### Changed -- Don't inject unicodedata2 into sys.modules from [@akx](https://github.com/akx) (PR #57) - -## [2.0.1](https://github.com/Ousret/charset_normalizer/compare/2.0.0...2.0.1) (2021-07-13) -### Fixed -- Make it work where there isn't a filesystem available, dropping assets frequencies.json. Report from [@sethmlarson](https://github.com/sethmlarson). (PR #55) -- Using explain=False permanently disable the verbose output in the current runtime (PR #47) -- One log entry (language target preemptive) was not show in logs when using explain=True (PR #47) -- Fix undesired exception (ValueError) on getitem of instance CharsetMatches (PR #52) - -### Changed -- Public function normalize default args values were not aligned with from_bytes (PR #53) - -### Added -- You may now use charset aliases in cp_isolation and cp_exclusion arguments (PR #47) - -## [2.0.0](https://github.com/Ousret/charset_normalizer/compare/1.4.1...2.0.0) (2021-07-02) -### Changed -- 4x to 5 times faster than the previous 1.4.0 release. At least 2x faster than Chardet. -- Accent has been made on UTF-8 detection, should perform rather instantaneous. -- The backward compatibility with Chardet has been greatly improved. The legacy detect function returns an identical charset name whenever possible. -- The detection mechanism has been slightly improved, now Turkish content is detected correctly (most of the time) -- The program has been rewritten to ease the readability and maintainability. (+Using static typing)+ -- utf_7 detection has been reinstated. - -### Removed -- This package no longer require anything when used with Python 3.5 (Dropped cached_property) -- Removed support for these languages: Catalan, Esperanto, Kazakh, Baque, Volapük, Azeri, Galician, Nynorsk, Macedonian, and Serbocroatian. -- The exception hook on UnicodeDecodeError has been removed. - -### Deprecated -- Methods coherence_non_latin, w_counter, chaos_secondary_pass of the class CharsetMatch are now deprecated and scheduled for removal in v3.0 - -### Fixed -- The CLI output used the relative path of the file(s). Should be absolute. - -## [1.4.1](https://github.com/Ousret/charset_normalizer/compare/1.4.0...1.4.1) (2021-05-28) -### Fixed -- Logger configuration/usage no longer conflict with others (PR #44) - -## [1.4.0](https://github.com/Ousret/charset_normalizer/compare/1.3.9...1.4.0) (2021-05-21) -### Removed -- Using standard logging instead of using the package loguru. -- Dropping nose test framework in favor of the maintained pytest. -- Choose to not use dragonmapper package to help with gibberish Chinese/CJK text. -- Require cached_property only for Python 3.5 due to constraint. Dropping for every other interpreter version. -- Stop support for UTF-7 that does not contain a SIG. -- Dropping PrettyTable, replaced with pure JSON output in CLI. - -### Fixed -- BOM marker in a CharsetNormalizerMatch instance could be False in rare cases even if obviously present. Due to the sub-match factoring process. -- Not searching properly for the BOM when trying utf32/16 parent codec. - -### Changed -- Improving the package final size by compressing frequencies.json. -- Huge improvement over the larges payload. - -### Added -- CLI now produces JSON consumable output. -- Return ASCII if given sequences fit. Given reasonable confidence. - -## [1.3.9](https://github.com/Ousret/charset_normalizer/compare/1.3.8...1.3.9) (2021-05-13) - -### Fixed -- In some very rare cases, you may end up getting encode/decode errors due to a bad bytes payload (PR #40) - -## [1.3.8](https://github.com/Ousret/charset_normalizer/compare/1.3.7...1.3.8) (2021-05-12) - -### Fixed -- Empty given payload for detection may cause an exception if trying to access the `alphabets` property. (PR #39) - -## [1.3.7](https://github.com/Ousret/charset_normalizer/compare/1.3.6...1.3.7) (2021-05-12) - -### Fixed -- The legacy detect function should return UTF-8-SIG if sig is present in the payload. (PR #38) - -## [1.3.6](https://github.com/Ousret/charset_normalizer/compare/1.3.5...1.3.6) (2021-02-09) - -### Changed -- Amend the previous release to allow prettytable 2.0 (PR #35) - -## [1.3.5](https://github.com/Ousret/charset_normalizer/compare/1.3.4...1.3.5) (2021-02-08) - -### Fixed -- Fix error while using the package with a python pre-release interpreter (PR #33) - -### Changed -- Dependencies refactoring, constraints revised. - -### Added -- Add python 3.9 and 3.10 to the supported interpreters - -MIT License - -Copyright (c) 2025 TAHRI Ahmed R. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/RECORD b/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/RECORD deleted file mode 100644 index 4715ccc..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/RECORD +++ /dev/null @@ -1,36 +0,0 @@ -../../Scripts/normalizer.exe,sha256=5yx59snFmb9grKAZXWKc_w7r_VTc8W-cCyCQVGqdNmQ,108512 -81d243bd2c585b0f4821__mypyc.cp312-win_amd64.pyd,sha256=UgVvS5ZPG8BBkGSjdKMuVu-FzLFhFmlx0m9Gp0kL0jg,219136 -charset_normalizer-3.4.7.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -charset_normalizer-3.4.7.dist-info/METADATA,sha256=0llkYJSRRJSKgCIy09lSxe0sJGV1SBWfRvNSjKX5-rs,41739 -charset_normalizer-3.4.7.dist-info/RECORD,, -charset_normalizer-3.4.7.dist-info/WHEEL,sha256=rR5QfsWcZl3mra5AmSD7Fd0dzQxZ3lHCpDo70IkfDK4,101 -charset_normalizer-3.4.7.dist-info/entry_points.txt,sha256=ADSTKrkXZ3hhdOVFi6DcUEHQRS0xfxDIE_pEz4wLIXA,65 -charset_normalizer-3.4.7.dist-info/licenses/LICENSE,sha256=GFd0hdNwTxpHne2OVzwJds_tMV_S_ReYP6mI2kwvcNE,1092 -charset_normalizer-3.4.7.dist-info/top_level.txt,sha256=c_vZbitqecT2GfK3zdxSTLCn8C-6pGnHQY5o_5Y32M0,47 -charset_normalizer/__init__.py,sha256=0NT8MHi7SKq3juMqYfOdrkzjisK0L73lneNHH4qaUAs,1638 -charset_normalizer/__main__.py,sha256=2sj_BS6H0sU25C1bMqz9DVwa6kOK9lchSEbSU-_iu7M,115 -charset_normalizer/__pycache__/__init__.cpython-312.pyc,, -charset_normalizer/__pycache__/__main__.cpython-312.pyc,, -charset_normalizer/__pycache__/api.cpython-312.pyc,, -charset_normalizer/__pycache__/cd.cpython-312.pyc,, -charset_normalizer/__pycache__/constant.cpython-312.pyc,, -charset_normalizer/__pycache__/legacy.cpython-312.pyc,, -charset_normalizer/__pycache__/md.cpython-312.pyc,, -charset_normalizer/__pycache__/models.cpython-312.pyc,, -charset_normalizer/__pycache__/utils.cpython-312.pyc,, -charset_normalizer/__pycache__/version.cpython-312.pyc,, -charset_normalizer/api.py,sha256=mHkwxdTIzOWLNDsADQ0IpedjW8MY0VNWan1MMexenfc,39832 -charset_normalizer/cd.cp312-win_amd64.pyd,sha256=rsIFGGzoYHel-PtGnpJM1ffhg9rtU_nek2LnfzvzY38,10752 -charset_normalizer/cd.py,sha256=oxPRzNqGqGMm6V4Os7lI2jQK_Pe8vgzEOWtIH4FWYhQ,15628 -charset_normalizer/cli/__init__.py,sha256=d9MUx-1V_qD3x9igIy4JT4oC5CU0yjulk7QyZWeRFhg,144 -charset_normalizer/cli/__main__.py,sha256=8TfOJ7pE3_USMlquyzg1TnEvSWdshj3Vmycsmsd0EJA,12302 -charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc,, -charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc,, -charset_normalizer/constant.py,sha256=CA94LLkydl625rnSViIv_egUOpzZx1mAAUmCu3QN5mQ,46481 -charset_normalizer/legacy.py,sha256=MCz6fcVj-h_VG9lMgnMUibESu4iAQqznE6HbMdleQIM,2740 -charset_normalizer/md.cp312-win_amd64.pyd,sha256=aEMJEcxPyFODKFKMFbGBGbWfum3vLYSrIh0iPmZ3umY,10752 -charset_normalizer/md.py,sha256=_Sv-zOZTD64bz7LsMcs5GEOBdJdvYreOiVjtUiEcVuU,31377 -charset_normalizer/models.py,sha256=wzkS2p-SXFmfOcGhs5Xt_eke1OwxthBGCXwSkAMG2_c,13190 -charset_normalizer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -charset_normalizer/utils.py,sha256=NzMBuvIt5IZ5_sYqboqJs7L1X_uWhwz5RfPWBYaDPX0,12704 -charset_normalizer/version.py,sha256=R38VXV25CgZdFHNOs5FpuL29tVaU302SYUBvWpWCVNw,123 diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/WHEEL b/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/WHEEL deleted file mode 100644 index 8e73156..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (82.0.1) -Root-Is-Purelib: false -Tag: cp312-cp312-win_amd64 - diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/entry_points.txt b/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/entry_points.txt deleted file mode 100644 index 65619e7..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/entry_points.txt +++ /dev/null @@ -1,2 +0,0 @@ -[console_scripts] -normalizer = charset_normalizer.cli:cli_detect diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/licenses/LICENSE b/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/licenses/LICENSE deleted file mode 100644 index 9725772..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/licenses/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 TAHRI Ahmed R. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/top_level.txt b/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/top_level.txt deleted file mode 100644 index 89847be..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer-3.4.7.dist-info/top_level.txt +++ /dev/null @@ -1,2 +0,0 @@ -81d243bd2c585b0f4821__mypyc -charset_normalizer diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/__init__.py b/notification-service/venv/Lib/site-packages/charset_normalizer/__init__.py deleted file mode 100644 index 0d3a379..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer/__init__.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -Charset-Normalizer -~~~~~~~~~~~~~~ -The Real First Universal Charset Detector. -A library that helps you read text from an unknown charset encoding. -Motivated by chardet, This package is trying to resolve the issue by taking a new approach. -All IANA character set names for which the Python core library provides codecs are supported. - -Basic usage: - >>> from charset_normalizer import from_bytes - >>> results = from_bytes('Bсеки човек има право на образование. Oбразованието!'.encode('utf_8')) - >>> best_guess = results.best() - >>> str(best_guess) - 'Bсеки човек има право на образование. Oбразованието!' - -Others methods and usages are available - see the full documentation -at . -:copyright: (c) 2021 by Ahmed TAHRI -:license: MIT, see LICENSE for more details. -""" - -from __future__ import annotations - -import logging - -from .api import from_bytes, from_fp, from_path, is_binary -from .legacy import detect -from .models import CharsetMatch, CharsetMatches -from .utils import set_logging_handler -from .version import VERSION, __version__ - -__all__ = ( - "from_fp", - "from_path", - "from_bytes", - "is_binary", - "detect", - "CharsetMatch", - "CharsetMatches", - "__version__", - "VERSION", - "set_logging_handler", -) - -# Attach a NullHandler to the top level logger by default -# https://docs.python.org/3.3/howto/logging.html#configuring-logging-for-a-library - -logging.getLogger("charset_normalizer").addHandler(logging.NullHandler()) diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/__main__.py b/notification-service/venv/Lib/site-packages/charset_normalizer/__main__.py deleted file mode 100644 index e0e76f7..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer/__main__.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import annotations - -from .cli import cli_detect - -if __name__ == "__main__": - cli_detect() diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 191ed01..0000000 Binary files a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/__main__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/__main__.cpython-312.pyc deleted file mode 100644 index 544b235..0000000 Binary files a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/__main__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/api.cpython-312.pyc b/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/api.cpython-312.pyc deleted file mode 100644 index 91d005b..0000000 Binary files a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/api.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/cd.cpython-312.pyc b/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/cd.cpython-312.pyc deleted file mode 100644 index 9348a0d..0000000 Binary files a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/cd.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/constant.cpython-312.pyc b/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/constant.cpython-312.pyc deleted file mode 100644 index c266f54..0000000 Binary files a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/constant.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/legacy.cpython-312.pyc b/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/legacy.cpython-312.pyc deleted file mode 100644 index b57e622..0000000 Binary files a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/legacy.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/md.cpython-312.pyc b/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/md.cpython-312.pyc deleted file mode 100644 index aad0a62..0000000 Binary files a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/md.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/models.cpython-312.pyc b/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/models.cpython-312.pyc deleted file mode 100644 index 7d5135e..0000000 Binary files a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/models.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/utils.cpython-312.pyc b/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/utils.cpython-312.pyc deleted file mode 100644 index 6b663b2..0000000 Binary files a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/utils.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/version.cpython-312.pyc b/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/version.cpython-312.pyc deleted file mode 100644 index e3ffffa..0000000 Binary files a/notification-service/venv/Lib/site-packages/charset_normalizer/__pycache__/version.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/api.py b/notification-service/venv/Lib/site-packages/charset_normalizer/api.py deleted file mode 100644 index 50cb955..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer/api.py +++ /dev/null @@ -1,988 +0,0 @@ -from __future__ import annotations - -import logging -from os import PathLike -from typing import BinaryIO - -from .cd import ( - coherence_ratio, - encoding_languages, - mb_encoding_languages, - merge_coherence_ratios, -) -from .constant import ( - IANA_SUPPORTED, - IANA_SUPPORTED_SIMILAR, - TOO_BIG_SEQUENCE, - TOO_SMALL_SEQUENCE, - TRACE, -) -from .md import mess_ratio -from .models import CharsetMatch, CharsetMatches -from .utils import ( - any_specified_encoding, - cut_sequence_chunks, - iana_name, - identify_sig_or_bom, - is_multi_byte_encoding, - should_strip_sig_or_bom, -) - -logger = logging.getLogger("charset_normalizer") -explain_handler = logging.StreamHandler() -explain_handler.setFormatter( - logging.Formatter("%(asctime)s | %(levelname)s | %(message)s") -) - -# Pre-compute a reordered encoding list: multibyte first, then single-byte. -# This allows the mb_definitive_match optimization to fire earlier, skipping -# all single-byte encodings for genuine CJK content. Multibyte codecs -# hard-fail (UnicodeDecodeError) on single-byte data almost instantly, so -# testing them first costs negligible time for non-CJK files. -_mb_supported: list[str] = [] -_sb_supported: list[str] = [] - -for _supported_enc in IANA_SUPPORTED: - try: - if is_multi_byte_encoding(_supported_enc): - _mb_supported.append(_supported_enc) - else: - _sb_supported.append(_supported_enc) - except ImportError: - _sb_supported.append(_supported_enc) - -IANA_SUPPORTED_MB_FIRST: list[str] = _mb_supported + _sb_supported - - -def from_bytes( - sequences: bytes | bytearray, - steps: int = 5, - chunk_size: int = 512, - threshold: float = 0.2, - cp_isolation: list[str] | None = None, - cp_exclusion: list[str] | None = None, - preemptive_behaviour: bool = True, - explain: bool = False, - language_threshold: float = 0.1, - enable_fallback: bool = True, -) -> CharsetMatches: - """ - Given a raw bytes sequence, return the best possibles charset usable to render str objects. - If there is no results, it is a strong indicator that the source is binary/not text. - By default, the process will extract 5 blocks of 512o each to assess the mess and coherence of a given sequence. - And will give up a particular code page after 20% of measured mess. Those criteria are customizable at will. - - The preemptive behavior DOES NOT replace the traditional detection workflow, it prioritize a particular code page - but never take it for granted. Can improve the performance. - - You may want to focus your attention to some code page or/and not others, use cp_isolation and cp_exclusion for that - purpose. - - This function will strip the SIG in the payload/sequence every time except on UTF-16, UTF-32. - By default the library does not setup any handler other than the NullHandler, if you choose to set the 'explain' - toggle to True it will alter the logger configuration to add a StreamHandler that is suitable for debugging. - Custom logging format and handler can be set manually. - """ - - if not isinstance(sequences, (bytearray, bytes)): - raise TypeError( - "Expected object of type bytes or bytearray, got: {}".format( - type(sequences) - ) - ) - - if explain: - previous_logger_level: int = logger.level - logger.addHandler(explain_handler) - logger.setLevel(TRACE) - - length: int = len(sequences) - - if length == 0: - logger.debug("Encoding detection on empty bytes, assuming utf_8 intention.") - if explain: # Defensive: ensure exit path clean handler - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - return CharsetMatches([CharsetMatch(sequences, "utf_8", 0.0, False, [], "")]) - - if cp_isolation is not None: - logger.log( - TRACE, - "cp_isolation is set. use this flag for debugging purpose. " - "limited list of encoding allowed : %s.", - ", ".join(cp_isolation), - ) - cp_isolation = [iana_name(cp, False) for cp in cp_isolation] - else: - cp_isolation = [] - - if cp_exclusion is not None: - logger.log( - TRACE, - "cp_exclusion is set. use this flag for debugging purpose. " - "limited list of encoding excluded : %s.", - ", ".join(cp_exclusion), - ) - cp_exclusion = [iana_name(cp, False) for cp in cp_exclusion] - else: - cp_exclusion = [] - - if length <= (chunk_size * steps): - logger.log( - TRACE, - "override steps (%i) and chunk_size (%i) as content does not fit (%i byte(s) given) parameters.", - steps, - chunk_size, - length, - ) - steps = 1 - chunk_size = length - - if steps > 1 and length / steps < chunk_size: - chunk_size = int(length / steps) - - is_too_small_sequence: bool = len(sequences) < TOO_SMALL_SEQUENCE - is_too_large_sequence: bool = len(sequences) >= TOO_BIG_SEQUENCE - - if is_too_small_sequence: - logger.log( - TRACE, - "Trying to detect encoding from a tiny portion of ({}) byte(s).".format( - length - ), - ) - elif is_too_large_sequence: - logger.log( - TRACE, - "Using lazy str decoding because the payload is quite large, ({}) byte(s).".format( - length - ), - ) - - prioritized_encodings: list[str] = [] - - specified_encoding: str | None = ( - any_specified_encoding(sequences) if preemptive_behaviour else None - ) - - if specified_encoding is not None: - prioritized_encodings.append(specified_encoding) - logger.log( - TRACE, - "Detected declarative mark in sequence. Priority +1 given for %s.", - specified_encoding, - ) - - tested: set[str] = set() - tested_but_hard_failure: list[str] = [] - tested_but_soft_failure: list[str] = [] - soft_failure_skip: set[str] = set() - success_fast_tracked: set[str] = set() - - # Cache for decoded payload deduplication: hash(decoded_payload) -> (mean_mess_ratio, cd_ratios_merged, passed) - # When multiple encodings decode to the exact same string, we can skip the expensive - # mess_ratio and coherence_ratio analysis and reuse the results from the first encoding. - payload_result_cache: dict[int, tuple[float, list[tuple[str, float]], bool]] = {} - - # When a definitive result (chaos=0.0 and good coherence) is found after testing - # the prioritized encodings (ascii, utf_8), we can significantly reduce the remaining - # work. Encodings that target completely different language families (e.g., Cyrillic - # when the definitive match is Latin) are skipped entirely. - # Additionally, for same-family encodings that pass chaos probing, we reuse the - # definitive match's coherence ratios instead of recomputing them — a major savings - # since coherence_ratio accounts for ~30% of total time on slow Latin files. - definitive_match_found: bool = False - definitive_target_languages: set[str] = set() - # After the definitive match fires, we cap the number of additional same-family - # single-byte encodings that pass chaos probing. Once we've accumulated enough - # good candidates (N), further same-family SB encodings are unlikely to produce - # a better best() result and just waste mess_ratio + coherence_ratio time. - # The first encoding to trigger the definitive match is NOT counted (it's already in). - post_definitive_sb_success_count: int = 0 - POST_DEFINITIVE_SB_CAP: int = 7 - - # When a non-UTF multibyte encoding passes chaos probing with significant multibyte - # content (decoded length < 98% of raw length), skip all remaining single-byte encodings. - # Rationale: multi-byte decoders (CJK) have strict byte-sequence validation — if they - # decode without error AND pass chaos probing with substantial multibyte content, the - # data is genuinely multibyte encoded. Single-byte encodings will always decode (every - # byte maps to something) but waste time on mess_ratio before failing. - # The 98% threshold prevents false triggers on files that happen to have a few valid - # multibyte pairs (e.g., cp424/_ude_1.txt where big5 decodes with 99% ratio). - mb_definitive_match_found: bool = False - - fallback_ascii: CharsetMatch | None = None - fallback_u8: CharsetMatch | None = None - fallback_specified: CharsetMatch | None = None - - results: CharsetMatches = CharsetMatches() - - early_stop_results: CharsetMatches = CharsetMatches() - - sig_encoding, sig_payload = identify_sig_or_bom(sequences) - - if sig_encoding is not None: - prioritized_encodings.append(sig_encoding) - logger.log( - TRACE, - "Detected a SIG or BOM mark on first %i byte(s). Priority +1 given for %s.", - len(sig_payload), - sig_encoding, - ) - - prioritized_encodings.append("ascii") - - if "utf_8" not in prioritized_encodings: - prioritized_encodings.append("utf_8") - - for encoding_iana in prioritized_encodings + IANA_SUPPORTED_MB_FIRST: - if cp_isolation and encoding_iana not in cp_isolation: - continue - - if cp_exclusion and encoding_iana in cp_exclusion: - continue - - if encoding_iana in tested: - continue - - tested.add(encoding_iana) - - decoded_payload: str | None = None - bom_or_sig_available: bool = sig_encoding == encoding_iana - strip_sig_or_bom: bool = bom_or_sig_available and should_strip_sig_or_bom( - encoding_iana - ) - - if encoding_iana in {"utf_16", "utf_32"} and not bom_or_sig_available: - logger.log( - TRACE, - "Encoding %s won't be tested as-is because it require a BOM. Will try some sub-encoder LE/BE.", - encoding_iana, - ) - continue - if encoding_iana in {"utf_7"} and not bom_or_sig_available: - logger.log( - TRACE, - "Encoding %s won't be tested as-is because detection is unreliable without BOM/SIG.", - encoding_iana, - ) - continue - - # Skip encodings similar to ones that already soft-failed (high mess ratio). - # Checked BEFORE the expensive decode attempt. - if encoding_iana in soft_failure_skip: - logger.log( - TRACE, - "%s is deemed too similar to a code page that was already considered unsuited. Continuing!", - encoding_iana, - ) - continue - - # Skip encodings that were already fast-tracked from a similar successful encoding. - if encoding_iana in success_fast_tracked: - logger.log( - TRACE, - "Skipping %s: already fast-tracked from a similar successful encoding.", - encoding_iana, - ) - continue - - try: - is_multi_byte_decoder: bool = is_multi_byte_encoding(encoding_iana) - except (ModuleNotFoundError, ImportError): # Defensive: - logger.log( - TRACE, - "Encoding %s does not provide an IncrementalDecoder", - encoding_iana, - ) - continue - - # When we've already found a definitive match (chaos=0.0 with good coherence) - # after testing the prioritized encodings, skip encodings that target - # completely different language families. This avoids running expensive - # mess_ratio + coherence_ratio on clearly unrelated candidates (e.g., Cyrillic - # when the definitive match is Latin-based). - if definitive_match_found: - if not is_multi_byte_decoder: - enc_languages = set(encoding_languages(encoding_iana)) - else: - enc_languages = set(mb_encoding_languages(encoding_iana)) - if not enc_languages.intersection(definitive_target_languages): - logger.log( - TRACE, - "Skipping %s: definitive match already found, this encoding targets different languages (%s vs %s).", - encoding_iana, - enc_languages, - definitive_target_languages, - ) - continue - - # After the definitive match, cap the number of additional same-family - # single-byte encodings that pass chaos probing. This avoids testing the - # tail of rare, low-value same-family encodings (mac_iceland, cp860, etc.) - # that almost never change best() but each cost ~1-2ms of mess_ratio + coherence. - if ( - definitive_match_found - and not is_multi_byte_decoder - and post_definitive_sb_success_count >= POST_DEFINITIVE_SB_CAP - ): - logger.log( - TRACE, - "Skipping %s: already accumulated %d same-family results after definitive match (cap=%d).", - encoding_iana, - post_definitive_sb_success_count, - POST_DEFINITIVE_SB_CAP, - ) - continue - - # When a multibyte encoding with significant multibyte content has already - # passed chaos probing, skip all single-byte encodings. They will either fail - # chaos probing (wasting mess_ratio time) or produce inferior results. - if mb_definitive_match_found and not is_multi_byte_decoder: - logger.log( - TRACE, - "Skipping single-byte %s: multi-byte definitive match already found.", - encoding_iana, - ) - continue - - try: - if is_too_large_sequence and is_multi_byte_decoder is False: - str( - ( - sequences[: int(50e4)] - if strip_sig_or_bom is False - else sequences[len(sig_payload) : int(50e4)] - ), - encoding=encoding_iana, - ) - else: - # UTF-7 BOM is encoded in modified Base64 whose byte boundary - # can overlap with the next character. Stripping raw SIG bytes - # before decoding may leave stray bytes that decode as garbage. - # Decode the full sequence and remove the leading BOM char instead. - # see https://github.com/jawah/charset_normalizer/issues/718 - # and https://github.com/jawah/charset_normalizer/issues/716 - if encoding_iana == "utf_7" and bom_or_sig_available: - decoded_payload = str( - sequences, - encoding=encoding_iana, - ) - if decoded_payload and decoded_payload[0] == "\ufeff": - decoded_payload = decoded_payload[1:] - else: - decoded_payload = str( - ( - sequences - if strip_sig_or_bom is False - else sequences[len(sig_payload) :] - ), - encoding=encoding_iana, - ) - except (UnicodeDecodeError, LookupError) as e: - if not isinstance(e, LookupError): - logger.log( - TRACE, - "Code page %s does not fit given bytes sequence at ALL. %s", - encoding_iana, - str(e), - ) - tested_but_hard_failure.append(encoding_iana) - continue - - r_ = range( - 0 if not bom_or_sig_available else len(sig_payload), - length, - int(length / steps), - ) - - multi_byte_bonus: bool = ( - is_multi_byte_decoder - and decoded_payload is not None - and len(decoded_payload) < length - ) - - if multi_byte_bonus: - logger.log( - TRACE, - "Code page %s is a multi byte encoding table and it appear that at least one character " - "was encoded using n-bytes.", - encoding_iana, - ) - - # Payload-hash deduplication: if another encoding already decoded to the - # exact same string, reuse its mess_ratio and coherence results entirely. - # This is strictly more general than the old IANA_SUPPORTED_SIMILAR approach - # because it catches ALL identical decoding, not just pre-mapped ones. - if decoded_payload is not None and not is_multi_byte_decoder: - payload_hash: int = hash(decoded_payload) - cached = payload_result_cache.get(payload_hash) - if cached is not None: - cached_mess, cached_cd, cached_passed = cached - if cached_passed: - # The previous encoding with identical output passed chaos probing. - fast_match = CharsetMatch( - sequences, - encoding_iana, - cached_mess, - bom_or_sig_available, - cached_cd, - ( - decoded_payload - if ( - is_too_large_sequence is False - or encoding_iana - in [specified_encoding, "ascii", "utf_8"] - ) - else None - ), - preemptive_declaration=specified_encoding, - ) - results.append(fast_match) - success_fast_tracked.add(encoding_iana) - logger.log( - TRACE, - "%s fast-tracked (identical decoded payload to a prior encoding, chaos=%f %%).", - encoding_iana, - round(cached_mess * 100, ndigits=3), - ) - - if ( - encoding_iana in [specified_encoding, "ascii", "utf_8"] - and cached_mess < 0.1 - ): - if cached_mess == 0.0: - logger.debug( - "Encoding detection: %s is most likely the one.", - fast_match.encoding, - ) - if explain: - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - return CharsetMatches([fast_match]) - early_stop_results.append(fast_match) - - if ( - len(early_stop_results) - and (specified_encoding is None or specified_encoding in tested) - and "ascii" in tested - and "utf_8" in tested - ): - probable_result: CharsetMatch = early_stop_results.best() # type: ignore[assignment] - logger.debug( - "Encoding detection: %s is most likely the one.", - probable_result.encoding, - ) - if explain: - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - return CharsetMatches([probable_result]) - - continue - else: - # The previous encoding with identical output failed chaos probing. - tested_but_soft_failure.append(encoding_iana) - logger.log( - TRACE, - "%s fast-skipped (identical decoded payload to a prior encoding that failed chaos probing).", - encoding_iana, - ) - # Prepare fallbacks for special encodings even when skipped. - if enable_fallback and encoding_iana in [ - "ascii", - "utf_8", - specified_encoding, - "utf_16", - "utf_32", - ]: - fallback_entry = CharsetMatch( - sequences, - encoding_iana, - threshold, - bom_or_sig_available, - [], - decoded_payload, - preemptive_declaration=specified_encoding, - ) - if encoding_iana == specified_encoding: - fallback_specified = fallback_entry - elif encoding_iana == "ascii": - fallback_ascii = fallback_entry - else: - fallback_u8 = fallback_entry - continue - - max_chunk_gave_up: int = int(len(r_) / 4) - - max_chunk_gave_up = max(max_chunk_gave_up, 2) - early_stop_count: int = 0 - lazy_str_hard_failure = False - - md_chunks: list[str] = [] - md_ratios = [] - - try: - for chunk in cut_sequence_chunks( - sequences, - encoding_iana, - r_, - chunk_size, - bom_or_sig_available, - strip_sig_or_bom, - sig_payload, - is_multi_byte_decoder, - decoded_payload, - ): - md_chunks.append(chunk) - - md_ratios.append( - mess_ratio( - chunk, - threshold, - explain is True and 1 <= len(cp_isolation) <= 2, - ) - ) - - if md_ratios[-1] >= threshold: - early_stop_count += 1 - - if (early_stop_count >= max_chunk_gave_up) or ( - bom_or_sig_available and strip_sig_or_bom is False - ): - break - except ( - UnicodeDecodeError - ) as e: # Lazy str loading may have missed something there - logger.log( - TRACE, - "LazyStr Loading: After MD chunk decode, code page %s does not fit given bytes sequence at ALL. %s", - encoding_iana, - str(e), - ) - early_stop_count = max_chunk_gave_up - lazy_str_hard_failure = True - - # We might want to check the sequence again with the whole content - # Only if initial MD tests passes - if ( - not lazy_str_hard_failure - and is_too_large_sequence - and not is_multi_byte_decoder - ): - try: - sequences[int(50e3) :].decode(encoding_iana, errors="strict") - except UnicodeDecodeError as e: - logger.log( - TRACE, - "LazyStr Loading: After final lookup, code page %s does not fit given bytes sequence at ALL. %s", - encoding_iana, - str(e), - ) - tested_but_hard_failure.append(encoding_iana) - continue - - mean_mess_ratio: float = sum(md_ratios) / len(md_ratios) if md_ratios else 0.0 - if mean_mess_ratio >= threshold or early_stop_count >= max_chunk_gave_up: - tested_but_soft_failure.append(encoding_iana) - if encoding_iana in IANA_SUPPORTED_SIMILAR: - soft_failure_skip.update(IANA_SUPPORTED_SIMILAR[encoding_iana]) - # Cache this soft-failure so identical decoding from other encodings - # can be skipped immediately. - if decoded_payload is not None and not is_multi_byte_decoder: - payload_result_cache.setdefault( - hash(decoded_payload), (mean_mess_ratio, [], False) - ) - logger.log( - TRACE, - "%s was excluded because of initial chaos probing. Gave up %i time(s). " - "Computed mean chaos is %f %%.", - encoding_iana, - early_stop_count, - round(mean_mess_ratio * 100, ndigits=3), - ) - # Preparing those fallbacks in case we got nothing. - if ( - enable_fallback - and encoding_iana - in ["ascii", "utf_8", specified_encoding, "utf_16", "utf_32"] - and not lazy_str_hard_failure - ): - fallback_entry = CharsetMatch( - sequences, - encoding_iana, - threshold, - bom_or_sig_available, - [], - decoded_payload, - preemptive_declaration=specified_encoding, - ) - if encoding_iana == specified_encoding: - fallback_specified = fallback_entry - elif encoding_iana == "ascii": - fallback_ascii = fallback_entry - else: - fallback_u8 = fallback_entry - continue - - logger.log( - TRACE, - "%s passed initial chaos probing. Mean measured chaos is %f %%", - encoding_iana, - round(mean_mess_ratio * 100, ndigits=3), - ) - - if not is_multi_byte_decoder: - target_languages: list[str] = encoding_languages(encoding_iana) - else: - target_languages = mb_encoding_languages(encoding_iana) - - if target_languages: - logger.log( - TRACE, - "{} should target any language(s) of {}".format( - encoding_iana, str(target_languages) - ), - ) - - cd_ratios = [] - - # Run coherence detection on all chunks. We previously tried limiting to - # 1-2 chunks for post-definitive encodings to save time, but this caused - # coverage regressions by producing unrepresentative coherence scores. - # The SB cap and language-family skip optimizations provide sufficient - # speedup without sacrificing coherence accuracy. - if encoding_iana != "ascii": - # We shall skip the CD when its about ASCII - # Most of the time its not relevant to run "language-detection" on it. - for chunk in md_chunks: - chunk_languages = coherence_ratio( - chunk, - language_threshold, - ",".join(target_languages) if target_languages else None, - ) - - cd_ratios.append(chunk_languages) - cd_ratios_merged = merge_coherence_ratios(cd_ratios) - else: - cd_ratios_merged = merge_coherence_ratios(cd_ratios) - - if cd_ratios_merged: - logger.log( - TRACE, - "We detected language {} using {}".format( - cd_ratios_merged, encoding_iana - ), - ) - - current_match = CharsetMatch( - sequences, - encoding_iana, - mean_mess_ratio, - bom_or_sig_available, - cd_ratios_merged, - ( - decoded_payload - if ( - is_too_large_sequence is False - or encoding_iana in [specified_encoding, "ascii", "utf_8"] - ) - else None - ), - preemptive_declaration=specified_encoding, - ) - - results.append(current_match) - - # Cache the successful result for payload-hash deduplication. - if decoded_payload is not None and not is_multi_byte_decoder: - payload_result_cache.setdefault( - hash(decoded_payload), - (mean_mess_ratio, cd_ratios_merged, True), - ) - - # Count post-definitive same-family SB successes for the early termination cap. - # Only count low-mess encodings (< 2%) toward the cap. High-mess encodings are - # marginal results that shouldn't prevent better-quality candidates from being - # tested. For example, iso8859_4 (mess=0%) should not be skipped just because - # 7 high-mess Latin encodings (cp1252 at 8%, etc.) were tried first. - if ( - definitive_match_found - and not is_multi_byte_decoder - and mean_mess_ratio < 0.02 - ): - post_definitive_sb_success_count += 1 - - if ( - encoding_iana in [specified_encoding, "ascii", "utf_8"] - and mean_mess_ratio < 0.1 - ): - # If md says nothing to worry about, then... stop immediately! - if mean_mess_ratio == 0.0: - logger.debug( - "Encoding detection: %s is most likely the one.", - current_match.encoding, - ) - if explain: # Defensive: ensure exit path clean handler - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - return CharsetMatches([current_match]) - - early_stop_results.append(current_match) - - if ( - len(early_stop_results) - and (specified_encoding is None or specified_encoding in tested) - and "ascii" in tested - and "utf_8" in tested - ): - probable_result = early_stop_results.best() # type: ignore[assignment] - logger.debug( - "Encoding detection: %s is most likely the one.", - probable_result.encoding, # type: ignore[union-attr] - ) - if explain: # Defensive: ensure exit path clean handler - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - - return CharsetMatches([probable_result]) - - # Once we find a result with good coherence (>= 0.5) after testing the - # prioritized encodings (ascii, utf_8), activate "definitive mode": skip - # encodings that target completely different language families. This avoids - # running expensive mess_ratio + coherence_ratio on clearly unrelated - # candidates (e.g., Cyrillic encodings when the match is Latin-based). - # We require coherence >= 0.5 to avoid false positives (e.g., cp1251 decoding - # Hebrew text with 0.0 chaos but wrong language detection at coherence 0.33). - if not definitive_match_found and not is_multi_byte_decoder: - best_coherence = ( - max((v for _, v in cd_ratios_merged), default=0.0) - if cd_ratios_merged - else 0.0 - ) - if best_coherence >= 0.5 and "ascii" in tested and "utf_8" in tested: - definitive_match_found = True - definitive_target_languages.update(target_languages) - logger.log( - TRACE, - "Definitive match found: %s (chaos=%.3f, coherence=%.2f). Encodings targeting different language families will be skipped.", - encoding_iana, - mean_mess_ratio, - best_coherence, - ) - - # When a non-UTF multibyte encoding passes chaos probing with significant - # multibyte content (decoded < 98% of raw), activate mb_definitive_match. - # This skips all remaining single-byte encodings which would either soft-fail - # (running expensive mess_ratio for nothing) or produce inferior results. - if ( - not mb_definitive_match_found - and is_multi_byte_decoder - and multi_byte_bonus - and decoded_payload is not None - and len(decoded_payload) < length * 0.98 - and encoding_iana - not in { - "utf_8", - "utf_8_sig", - "utf_16", - "utf_16_be", - "utf_16_le", - "utf_32", - "utf_32_be", - "utf_32_le", - "utf_7", - } - and "ascii" in tested - and "utf_8" in tested - ): - mb_definitive_match_found = True - logger.log( - TRACE, - "Multi-byte definitive match: %s (chaos=%.3f, decoded=%d/%d=%.1f%%). Single-byte encodings will be skipped.", - encoding_iana, - mean_mess_ratio, - len(decoded_payload), - length, - len(decoded_payload) / length * 100, - ) - - if encoding_iana == sig_encoding: - logger.debug( - "Encoding detection: %s is most likely the one as we detected a BOM or SIG within " - "the beginning of the sequence.", - encoding_iana, - ) - if explain: # Defensive: ensure exit path clean handler - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - return CharsetMatches([results[encoding_iana]]) - - if len(results) == 0: - if fallback_u8 or fallback_ascii or fallback_specified: - logger.log( - TRACE, - "Nothing got out of the detection process. Using ASCII/UTF-8/Specified fallback.", - ) - - if fallback_specified: - logger.debug( - "Encoding detection: %s will be used as a fallback match", - fallback_specified.encoding, - ) - results.append(fallback_specified) - elif ( - (fallback_u8 and fallback_ascii is None) - or ( - fallback_u8 - and fallback_ascii - and fallback_u8.fingerprint != fallback_ascii.fingerprint - ) - or (fallback_u8 is not None) - ): - logger.debug("Encoding detection: utf_8 will be used as a fallback match") - results.append(fallback_u8) - elif fallback_ascii: - logger.debug("Encoding detection: ascii will be used as a fallback match") - results.append(fallback_ascii) - - if results: - logger.debug( - "Encoding detection: Found %s as plausible (best-candidate) for content. With %i alternatives.", - results.best().encoding, # type: ignore - len(results) - 1, - ) - else: - logger.debug("Encoding detection: Unable to determine any suitable charset.") - - if explain: - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - - return results - - -def from_fp( - fp: BinaryIO, - steps: int = 5, - chunk_size: int = 512, - threshold: float = 0.20, - cp_isolation: list[str] | None = None, - cp_exclusion: list[str] | None = None, - preemptive_behaviour: bool = True, - explain: bool = False, - language_threshold: float = 0.1, - enable_fallback: bool = True, -) -> CharsetMatches: - """ - Same thing than the function from_bytes but using a file pointer that is already ready. - Will not close the file pointer. - """ - return from_bytes( - fp.read(), - steps, - chunk_size, - threshold, - cp_isolation, - cp_exclusion, - preemptive_behaviour, - explain, - language_threshold, - enable_fallback, - ) - - -def from_path( - path: str | bytes | PathLike, # type: ignore[type-arg] - steps: int = 5, - chunk_size: int = 512, - threshold: float = 0.20, - cp_isolation: list[str] | None = None, - cp_exclusion: list[str] | None = None, - preemptive_behaviour: bool = True, - explain: bool = False, - language_threshold: float = 0.1, - enable_fallback: bool = True, -) -> CharsetMatches: - """ - Same thing than the function from_bytes but with one extra step. Opening and reading given file path in binary mode. - Can raise IOError. - """ - with open(path, "rb") as fp: - return from_fp( - fp, - steps, - chunk_size, - threshold, - cp_isolation, - cp_exclusion, - preemptive_behaviour, - explain, - language_threshold, - enable_fallback, - ) - - -def is_binary( - fp_or_path_or_payload: PathLike | str | BinaryIO | bytes, # type: ignore[type-arg] - steps: int = 5, - chunk_size: int = 512, - threshold: float = 0.20, - cp_isolation: list[str] | None = None, - cp_exclusion: list[str] | None = None, - preemptive_behaviour: bool = True, - explain: bool = False, - language_threshold: float = 0.1, - enable_fallback: bool = False, -) -> bool: - """ - Detect if the given input (file, bytes, or path) points to a binary file. aka. not a string. - Based on the same main heuristic algorithms and default kwargs at the sole exception that fallbacks match - are disabled to be stricter around ASCII-compatible but unlikely to be a string. - """ - if isinstance(fp_or_path_or_payload, (str, PathLike)): - guesses = from_path( - fp_or_path_or_payload, - steps=steps, - chunk_size=chunk_size, - threshold=threshold, - cp_isolation=cp_isolation, - cp_exclusion=cp_exclusion, - preemptive_behaviour=preemptive_behaviour, - explain=explain, - language_threshold=language_threshold, - enable_fallback=enable_fallback, - ) - elif isinstance( - fp_or_path_or_payload, - ( - bytes, - bytearray, - ), - ): - guesses = from_bytes( - fp_or_path_or_payload, - steps=steps, - chunk_size=chunk_size, - threshold=threshold, - cp_isolation=cp_isolation, - cp_exclusion=cp_exclusion, - preemptive_behaviour=preemptive_behaviour, - explain=explain, - language_threshold=language_threshold, - enable_fallback=enable_fallback, - ) - else: - guesses = from_fp( - fp_or_path_or_payload, - steps=steps, - chunk_size=chunk_size, - threshold=threshold, - cp_isolation=cp_isolation, - cp_exclusion=cp_exclusion, - preemptive_behaviour=preemptive_behaviour, - explain=explain, - language_threshold=language_threshold, - enable_fallback=enable_fallback, - ) - - return not guesses diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/cd.cp312-win_amd64.pyd b/notification-service/venv/Lib/site-packages/charset_normalizer/cd.cp312-win_amd64.pyd deleted file mode 100644 index d0c07fb..0000000 Binary files a/notification-service/venv/Lib/site-packages/charset_normalizer/cd.cp312-win_amd64.pyd and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/cd.py b/notification-service/venv/Lib/site-packages/charset_normalizer/cd.py deleted file mode 100644 index 9545d35..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer/cd.py +++ /dev/null @@ -1,454 +0,0 @@ -from __future__ import annotations - -import importlib -from codecs import IncrementalDecoder -from collections import Counter -from functools import lru_cache -from typing import Counter as TypeCounter - -from .constant import ( - FREQUENCIES, - KO_NAMES, - LANGUAGE_SUPPORTED_COUNT, - TOO_SMALL_SEQUENCE, - ZH_NAMES, - _FREQUENCIES_SET, - _FREQUENCIES_RANK, -) -from .md import is_suspiciously_successive_range -from .models import CoherenceMatches -from .utils import ( - is_accentuated, - is_latin, - is_multi_byte_encoding, - is_unicode_range_secondary, - unicode_range, -) - - -def encoding_unicode_range(iana_name: str) -> list[str]: - """ - Return associated unicode ranges in a single byte code page. - """ - if is_multi_byte_encoding(iana_name): - raise OSError( # Defensive: - "Function not supported on multi-byte code page" - ) - - decoder = importlib.import_module(f"encodings.{iana_name}").IncrementalDecoder - - p: IncrementalDecoder = decoder(errors="ignore") - seen_ranges: dict[str, int] = {} - character_count: int = 0 - - for i in range(0x40, 0xFF): - chunk: str = p.decode(bytes([i])) - - if chunk: - character_range: str | None = unicode_range(chunk) - - if character_range is None: - continue - - if is_unicode_range_secondary(character_range) is False: - if character_range not in seen_ranges: - seen_ranges[character_range] = 0 - seen_ranges[character_range] += 1 - character_count += 1 - - return sorted( - [ - character_range - for character_range in seen_ranges - if seen_ranges[character_range] / character_count >= 0.15 - ] - ) - - -def unicode_range_languages(primary_range: str) -> list[str]: - """ - Return inferred languages used with a unicode range. - """ - languages: list[str] = [] - - for language, characters in FREQUENCIES.items(): - for character in characters: - if unicode_range(character) == primary_range: - languages.append(language) - break - - return languages - - -@lru_cache() -def encoding_languages(iana_name: str) -> list[str]: - """ - Single-byte encoding language association. Some code page are heavily linked to particular language(s). - This function does the correspondence. - """ - unicode_ranges: list[str] = encoding_unicode_range(iana_name) - primary_range: str | None = None - - for specified_range in unicode_ranges: - if "Latin" not in specified_range: - primary_range = specified_range - break - - if primary_range is None: - return ["Latin Based"] - - return unicode_range_languages(primary_range) - - -@lru_cache() -def mb_encoding_languages(iana_name: str) -> list[str]: - """ - Multi-byte encoding language association. Some code page are heavily linked to particular language(s). - This function does the correspondence. - """ - if ( - iana_name.startswith("shift_") - or iana_name.startswith("iso2022_jp") - or iana_name.startswith("euc_j") - or iana_name == "cp932" - ): - return ["Japanese"] - if iana_name.startswith("gb") or iana_name in ZH_NAMES: - return ["Chinese"] - if iana_name.startswith("iso2022_kr") or iana_name in KO_NAMES: - return ["Korean"] - - return [] - - -@lru_cache(maxsize=LANGUAGE_SUPPORTED_COUNT) -def get_target_features(language: str) -> tuple[bool, bool]: - """ - Determine main aspects from a supported language if it contains accents and if is pure Latin. - """ - target_have_accents: bool = False - target_pure_latin: bool = True - - for character in FREQUENCIES[language]: - if not target_have_accents and is_accentuated(character): - target_have_accents = True - if target_pure_latin and is_latin(character) is False: - target_pure_latin = False - - return target_have_accents, target_pure_latin - - -def alphabet_languages( - characters: list[str], ignore_non_latin: bool = False -) -> list[str]: - """ - Return associated languages associated to given characters. - """ - languages: list[tuple[str, float]] = [] - - characters_set: frozenset[str] = frozenset(characters) - source_have_accents = any(is_accentuated(character) for character in characters) - - for language, language_characters in FREQUENCIES.items(): - target_have_accents, target_pure_latin = get_target_features(language) - - if ignore_non_latin and target_pure_latin is False: - continue - - if target_have_accents is False and source_have_accents: - continue - - character_count: int = len(language_characters) - - character_match_count: int = len(_FREQUENCIES_SET[language] & characters_set) - - ratio: float = character_match_count / character_count - - if ratio >= 0.2: - languages.append((language, ratio)) - - languages = sorted(languages, key=lambda x: x[1], reverse=True) - - return [compatible_language[0] for compatible_language in languages] - - -def characters_popularity_compare( - language: str, ordered_characters: list[str] -) -> float: - """ - Determine if a ordered characters list (by occurrence from most appearance to rarest) match a particular language. - The result is a ratio between 0. (absolutely no correspondence) and 1. (near perfect fit). - Beware that is function is not strict on the match in order to ease the detection. (Meaning close match is 1.) - """ - if language not in FREQUENCIES: - raise ValueError(f"{language} not available") # Defensive: - - character_approved_count: int = 0 - frequencies_language_set: frozenset[str] = _FREQUENCIES_SET[language] - lang_rank: dict[str, int] = _FREQUENCIES_RANK[language] - - ordered_characters_count: int = len(ordered_characters) - target_language_characters_count: int = len(FREQUENCIES[language]) - - large_alphabet: bool = target_language_characters_count > 26 - - expected_projection_ratio: float = ( - target_language_characters_count / ordered_characters_count - ) - - # Pre-built rank dict for ordered_characters (avoids repeated list slicing). - ordered_rank: dict[str, int] = { - char: rank for rank, char in enumerate(ordered_characters) - } - - # Pre-compute characters common to both orderings. - # Avoids repeated `c in ordered_rank` dict lookups in the inner counts. - common_chars: list[tuple[int, int]] = [ - (lr, ordered_rank[c]) for c, lr in lang_rank.items() if c in ordered_rank - ] - - # Pre-extract lr and orr arrays for faster iteration in the inner loop. - # Plain integer loops with local arrays are much faster under mypyc than - # generator expression sums over a list of tuples. - common_count: int = len(common_chars) - common_lr: list[int] = [p[0] for p in common_chars] - common_orr: list[int] = [p[1] for p in common_chars] - - for character, character_rank in zip( - ordered_characters, range(0, ordered_characters_count) - ): - if character not in frequencies_language_set: - continue - - character_rank_in_language: int = lang_rank[character] - character_rank_projection: int = int(character_rank * expected_projection_ratio) - - if ( - large_alphabet is False - and abs(character_rank_projection - character_rank_in_language) > 4 - ): - continue - - if ( - large_alphabet is True - and abs(character_rank_projection - character_rank_in_language) - < target_language_characters_count / 3 - ): - character_approved_count += 1 - continue - - # Count how many characters appear "before" in both orderings, - # and how many appear "at or after" in both orderings. - # Single pass over pre-extracted arrays — much faster under mypyc - # than two generator expression sums. - before_match_count: int = 0 - after_match_count: int = 0 - for i in range(common_count): - lr_i: int = common_lr[i] - orr_i: int = common_orr[i] - if lr_i < character_rank_in_language: - if orr_i < character_rank: - before_match_count += 1 - else: - if orr_i >= character_rank: - after_match_count += 1 - - after_len: int = target_language_characters_count - character_rank_in_language - - if character_rank_in_language == 0 and before_match_count <= 4: - character_approved_count += 1 - continue - - if after_len == 0 and after_match_count <= 4: - character_approved_count += 1 - continue - - if ( - character_rank_in_language > 0 - and before_match_count / character_rank_in_language >= 0.4 - ) or (after_len > 0 and after_match_count / after_len >= 0.4): - character_approved_count += 1 - continue - - return character_approved_count / len(ordered_characters) - - -def alpha_unicode_split(decoded_sequence: str) -> list[str]: - """ - Given a decoded text sequence, return a list of str. Unicode range / alphabet separation. - Ex. a text containing English/Latin with a bit a Hebrew will return two items in the resulting list; - One containing the latin letters and the other hebrew. - """ - layers: dict[str, list[str]] = {} - - # Fast path: track single-layer key to skip dict iteration for single-script text. - single_layer_key: str | None = None - multi_layer: bool = False - - # Cache the last character_range and its resolved layer to avoid repeated - # is_suspiciously_successive_range calls for consecutive same-range chars. - prev_character_range: str | None = None - prev_layer_target: str | None = None - - for character in decoded_sequence: - if character.isalpha() is False: - continue - - # ASCII fast-path: a-z and A-Z are always "Basic Latin". - # Avoids unicode_range() function call overhead for the most common case. - character_ord: int = ord(character) - if character_ord < 128: - character_range: str | None = "Basic Latin" - else: - character_range = unicode_range(character) - - if character_range is None: - continue - - # Fast path: same range as previous character → reuse cached layer target. - if character_range == prev_character_range: - if prev_layer_target is not None: - layers[prev_layer_target].append(character) - continue - - layer_target_range: str | None = None - - if multi_layer: - for discovered_range in layers: - if ( - is_suspiciously_successive_range(discovered_range, character_range) - is False - ): - layer_target_range = discovered_range - break - elif single_layer_key is not None: - if ( - is_suspiciously_successive_range(single_layer_key, character_range) - is False - ): - layer_target_range = single_layer_key - - if layer_target_range is None: - layer_target_range = character_range - - if layer_target_range not in layers: - layers[layer_target_range] = [] - if single_layer_key is None: - single_layer_key = layer_target_range - else: - multi_layer = True - - layers[layer_target_range].append(character) - - # Cache for next iteration - prev_character_range = character_range - prev_layer_target = layer_target_range - - return ["".join(chars).lower() for chars in layers.values()] - - -def merge_coherence_ratios(results: list[CoherenceMatches]) -> CoherenceMatches: - """ - This function merge results previously given by the function coherence_ratio. - The return type is the same as coherence_ratio. - """ - per_language_ratios: dict[str, list[float]] = {} - for result in results: - for sub_result in result: - language, ratio = sub_result - if language not in per_language_ratios: - per_language_ratios[language] = [ratio] - continue - per_language_ratios[language].append(ratio) - - merge = [ - ( - language, - round( - sum(per_language_ratios[language]) / len(per_language_ratios[language]), - 4, - ), - ) - for language in per_language_ratios - ] - - return sorted(merge, key=lambda x: x[1], reverse=True) - - -def filter_alt_coherence_matches(results: CoherenceMatches) -> CoherenceMatches: - """ - We shall NOT return "English—" in CoherenceMatches because it is an alternative - of "English". This function only keeps the best match and remove the em-dash in it. - """ - index_results: dict[str, list[float]] = dict() - - for result in results: - language, ratio = result - no_em_name: str = language.replace("—", "") - - if no_em_name not in index_results: - index_results[no_em_name] = [] - - index_results[no_em_name].append(ratio) - - if any(len(index_results[e]) > 1 for e in index_results): - filtered_results: CoherenceMatches = [] - - for language in index_results: - filtered_results.append((language, max(index_results[language]))) - - return filtered_results - - return results - - -@lru_cache(maxsize=2048) -def coherence_ratio( - decoded_sequence: str, threshold: float = 0.1, lg_inclusion: str | None = None -) -> CoherenceMatches: - """ - Detect ANY language that can be identified in given sequence. The sequence will be analysed by layers. - A layer = Character extraction by alphabets/ranges. - """ - - results: list[tuple[str, float]] = [] - ignore_non_latin: bool = False - - sufficient_match_count: int = 0 - - lg_inclusion_list = lg_inclusion.split(",") if lg_inclusion is not None else [] - if "Latin Based" in lg_inclusion_list: - ignore_non_latin = True - lg_inclusion_list.remove("Latin Based") - - for layer in alpha_unicode_split(decoded_sequence): - sequence_frequencies: TypeCounter[str] = Counter(layer) - most_common = sequence_frequencies.most_common() - - character_count: int = len(layer) - - if character_count <= TOO_SMALL_SEQUENCE: - continue - - popular_character_ordered: list[str] = [c for c, o in most_common] - - for language in lg_inclusion_list or alphabet_languages( - popular_character_ordered, ignore_non_latin - ): - ratio: float = characters_popularity_compare( - language, popular_character_ordered - ) - - if ratio < threshold: - continue - elif ratio >= 0.8: - sufficient_match_count += 1 - - results.append((language, round(ratio, 4))) - - if sufficient_match_count >= 3: - break - - return sorted( - filter_alt_coherence_matches(results), key=lambda x: x[1], reverse=True - ) diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/cli/__init__.py b/notification-service/venv/Lib/site-packages/charset_normalizer/cli/__init__.py deleted file mode 100644 index 543a5a4..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer/cli/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import annotations - -from .__main__ import cli_detect, query_yes_no - -__all__ = ( - "cli_detect", - "query_yes_no", -) diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/cli/__main__.py b/notification-service/venv/Lib/site-packages/charset_normalizer/cli/__main__.py deleted file mode 100644 index ad843c1..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer/cli/__main__.py +++ /dev/null @@ -1,362 +0,0 @@ -from __future__ import annotations - -import argparse -import sys -import typing -from json import dumps -from os.path import abspath, basename, dirname, join, realpath -from platform import python_version -from unicodedata import unidata_version - -import charset_normalizer.md as md_module -from charset_normalizer import from_fp -from charset_normalizer.models import CliDetectionResult -from charset_normalizer.version import __version__ - - -def query_yes_no(question: str, default: str = "yes") -> bool: # Defensive: - """Ask a yes/no question via input() and return the answer as a bool.""" - prompt = " [Y/n] " if default == "yes" else " [y/N] " - - while True: - choice = input(question + prompt).strip().lower() - if not choice: - return default == "yes" - if choice in ("y", "yes"): - return True - if choice in ("n", "no"): - return False - print("Please respond with 'y' or 'n'.") - - -class FileType: - """Factory for creating file object types - - Instances of FileType are typically passed as type= arguments to the - ArgumentParser add_argument() method. - - Keyword Arguments: - - mode -- A string indicating how the file is to be opened. Accepts the - same values as the builtin open() function. - - bufsize -- The file's desired buffer size. Accepts the same values as - the builtin open() function. - - encoding -- The file's encoding. Accepts the same values as the - builtin open() function. - - errors -- A string indicating how encoding and decoding errors are to - be handled. Accepts the same value as the builtin open() function. - - Backported from CPython 3.12 - """ - - def __init__( - self, - mode: str = "r", - bufsize: int = -1, - encoding: str | None = None, - errors: str | None = None, - ): - self._mode = mode - self._bufsize = bufsize - self._encoding = encoding - self._errors = errors - - def __call__(self, string: str) -> typing.IO: # type: ignore[type-arg] - # the special argument "-" means sys.std{in,out} - if string == "-": - if "r" in self._mode: - return sys.stdin.buffer if "b" in self._mode else sys.stdin - elif any(c in self._mode for c in "wax"): - return sys.stdout.buffer if "b" in self._mode else sys.stdout - else: - msg = f'argument "-" with mode {self._mode}' - raise ValueError(msg) - - # all other arguments are used as file names - try: - return open(string, self._mode, self._bufsize, self._encoding, self._errors) - except OSError as e: - message = f"can't open '{string}': {e}" - raise argparse.ArgumentTypeError(message) - - def __repr__(self) -> str: - args = self._mode, self._bufsize - kwargs = [("encoding", self._encoding), ("errors", self._errors)] - args_str = ", ".join( - [repr(arg) for arg in args if arg != -1] - + [f"{kw}={arg!r}" for kw, arg in kwargs if arg is not None] - ) - return f"{type(self).__name__}({args_str})" - - -def cli_detect(argv: list[str] | None = None) -> int: - """ - CLI assistant using ARGV and ArgumentParser - :param argv: - :return: 0 if everything is fine, anything else equal trouble - """ - parser = argparse.ArgumentParser( - description="The Real First Universal Charset Detector. " - "Discover originating encoding used on text file. " - "Normalize text to unicode." - ) - - parser.add_argument( - "files", type=FileType("rb"), nargs="+", help="File(s) to be analysed" - ) - parser.add_argument( - "-v", - "--verbose", - action="store_true", - default=False, - dest="verbose", - help="Display complementary information about file if any. " - "Stdout will contain logs about the detection process.", - ) - parser.add_argument( - "-a", - "--with-alternative", - action="store_true", - default=False, - dest="alternatives", - help="Output complementary possibilities if any. Top-level JSON WILL be a list.", - ) - parser.add_argument( - "-n", - "--normalize", - action="store_true", - default=False, - dest="normalize", - help="Permit to normalize input file. If not set, program does not write anything.", - ) - parser.add_argument( - "-m", - "--minimal", - action="store_true", - default=False, - dest="minimal", - help="Only output the charset detected to STDOUT. Disabling JSON output.", - ) - parser.add_argument( - "-r", - "--replace", - action="store_true", - default=False, - dest="replace", - help="Replace file when trying to normalize it instead of creating a new one.", - ) - parser.add_argument( - "-f", - "--force", - action="store_true", - default=False, - dest="force", - help="Replace file without asking if you are sure, use this flag with caution.", - ) - parser.add_argument( - "-i", - "--no-preemptive", - action="store_true", - default=False, - dest="no_preemptive", - help="Disable looking at a charset declaration to hint the detector.", - ) - parser.add_argument( - "-t", - "--threshold", - action="store", - default=0.2, - type=float, - dest="threshold", - help="Define a custom maximum amount of noise allowed in decoded content. 0. <= noise <= 1.", - ) - parser.add_argument( - "--version", - action="version", - version="Charset-Normalizer {} - Python {} - Unicode {} - SpeedUp {}".format( - __version__, - python_version(), - unidata_version, - "OFF" if md_module.__file__.lower().endswith(".py") else "ON", - ), - help="Show version information and exit.", - ) - - args = parser.parse_args(argv) - - if args.replace is True and args.normalize is False: - if args.files: - for my_file in args.files: - my_file.close() - print("Use --replace in addition of --normalize only.", file=sys.stderr) - return 1 - - if args.force is True and args.replace is False: - if args.files: - for my_file in args.files: - my_file.close() - print("Use --force in addition of --replace only.", file=sys.stderr) - return 1 - - if args.threshold < 0.0 or args.threshold > 1.0: - if args.files: - for my_file in args.files: - my_file.close() - print("--threshold VALUE should be between 0. AND 1.", file=sys.stderr) - return 1 - - x_ = [] - - for my_file in args.files: - matches = from_fp( - my_file, - threshold=args.threshold, - explain=args.verbose, - preemptive_behaviour=args.no_preemptive is False, - ) - - best_guess = matches.best() - - if best_guess is None: - print( - 'Unable to identify originating encoding for "{}". {}'.format( - my_file.name, - ( - "Maybe try increasing maximum amount of chaos." - if args.threshold < 1.0 - else "" - ), - ), - file=sys.stderr, - ) - x_.append( - CliDetectionResult( - abspath(my_file.name), - None, - [], - [], - "Unknown", - [], - False, - 1.0, - 0.0, - None, - True, - ) - ) - else: - cli_result = CliDetectionResult( - abspath(my_file.name), - best_guess.encoding, - best_guess.encoding_aliases, - [ - cp - for cp in best_guess.could_be_from_charset - if cp != best_guess.encoding - ], - best_guess.language, - best_guess.alphabets, - best_guess.bom, - best_guess.percent_chaos, - best_guess.percent_coherence, - None, - True, - ) - x_.append(cli_result) - - if len(matches) > 1 and args.alternatives: - for el in matches: - if el != best_guess: - x_.append( - CliDetectionResult( - abspath(my_file.name), - el.encoding, - el.encoding_aliases, - [ - cp - for cp in el.could_be_from_charset - if cp != el.encoding - ], - el.language, - el.alphabets, - el.bom, - el.percent_chaos, - el.percent_coherence, - None, - False, - ) - ) - - if args.normalize is True: - if best_guess.encoding.startswith("utf") is True: - print( - '"{}" file does not need to be normalized, as it already came from unicode.'.format( - my_file.name - ), - file=sys.stderr, - ) - if my_file.closed is False: - my_file.close() - continue - - dir_path = dirname(realpath(my_file.name)) - file_name = basename(realpath(my_file.name)) - - o_: list[str] = file_name.split(".") - - if args.replace is False: - o_.insert(-1, best_guess.encoding) - if my_file.closed is False: - my_file.close() - elif ( - args.force is False - and query_yes_no( - 'Are you sure to normalize "{}" by replacing it ?'.format( - my_file.name - ), - "no", - ) - is False - ): - if my_file.closed is False: - my_file.close() - continue - - try: - cli_result.unicode_path = join(dir_path, ".".join(o_)) - - with open(cli_result.unicode_path, "wb") as fp: - fp.write(best_guess.output()) - except OSError as e: # Defensive: - print(str(e), file=sys.stderr) - if my_file.closed is False: - my_file.close() - return 2 - - if my_file.closed is False: - my_file.close() - - if args.minimal is False: - print( - dumps( - [el.__dict__ for el in x_] if len(x_) > 1 else x_[0].__dict__, - ensure_ascii=True, - indent=4, - ) - ) - else: - for my_file in args.files: - print( - ", ".join( - [ - el.encoding or "undefined" - for el in x_ - if el.path == abspath(my_file.name) - ] - ) - ) - - return 0 - - -if __name__ == "__main__": # Defensive: - cli_detect() diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index f64de21..0000000 Binary files a/notification-service/venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc deleted file mode 100644 index 00f2339..0000000 Binary files a/notification-service/venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/constant.py b/notification-service/venv/Lib/site-packages/charset_normalizer/constant.py deleted file mode 100644 index e1297d2..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer/constant.py +++ /dev/null @@ -1,2050 +0,0 @@ -from __future__ import annotations - -from codecs import BOM_UTF8, BOM_UTF16_BE, BOM_UTF16_LE, BOM_UTF32_BE, BOM_UTF32_LE -from encodings.aliases import aliases -from re import IGNORECASE -from re import compile as re_compile - -# Contain for each eligible encoding a list of/item bytes SIG/BOM -ENCODING_MARKS: dict[str, bytes | list[bytes]] = { - "utf_8": BOM_UTF8, - "utf_7": [ - b"\x2b\x2f\x76\x38\x2d", - b"\x2b\x2f\x76\x38", - b"\x2b\x2f\x76\x39", - b"\x2b\x2f\x76\x2b", - b"\x2b\x2f\x76\x2f", - ], - "gb18030": b"\x84\x31\x95\x33", - "utf_32": [BOM_UTF32_BE, BOM_UTF32_LE], - "utf_16": [BOM_UTF16_BE, BOM_UTF16_LE], -} - -TOO_SMALL_SEQUENCE: int = 32 -TOO_BIG_SEQUENCE: int = int(10e6) - -UTF8_MAXIMAL_ALLOCATION: int = 1_112_064 - -# Up-to-date Unicode ucd/17.0.0 -UNICODE_RANGES_COMBINED: dict[str, range] = { - "Control character": range(32), - "Basic Latin": range(32, 128), - "Latin-1 Supplement": range(128, 256), - "Latin Extended-A": range(256, 384), - "Latin Extended-B": range(384, 592), - "IPA Extensions": range(592, 688), - "Spacing Modifier Letters": range(688, 768), - "Combining Diacritical Marks": range(768, 880), - "Greek and Coptic": range(880, 1024), - "Cyrillic": range(1024, 1280), - "Cyrillic Supplement": range(1280, 1328), - "Armenian": range(1328, 1424), - "Hebrew": range(1424, 1536), - "Arabic": range(1536, 1792), - "Syriac": range(1792, 1872), - "Arabic Supplement": range(1872, 1920), - "Thaana": range(1920, 1984), - "NKo": range(1984, 2048), - "Samaritan": range(2048, 2112), - "Mandaic": range(2112, 2144), - "Syriac Supplement": range(2144, 2160), - "Arabic Extended-B": range(2160, 2208), - "Arabic Extended-A": range(2208, 2304), - "Devanagari": range(2304, 2432), - "Bengali": range(2432, 2560), - "Gurmukhi": range(2560, 2688), - "Gujarati": range(2688, 2816), - "Oriya": range(2816, 2944), - "Tamil": range(2944, 3072), - "Telugu": range(3072, 3200), - "Kannada": range(3200, 3328), - "Malayalam": range(3328, 3456), - "Sinhala": range(3456, 3584), - "Thai": range(3584, 3712), - "Lao": range(3712, 3840), - "Tibetan": range(3840, 4096), - "Myanmar": range(4096, 4256), - "Georgian": range(4256, 4352), - "Hangul Jamo": range(4352, 4608), - "Ethiopic": range(4608, 4992), - "Ethiopic Supplement": range(4992, 5024), - "Cherokee": range(5024, 5120), - "Unified Canadian Aboriginal Syllabics": range(5120, 5760), - "Ogham": range(5760, 5792), - "Runic": range(5792, 5888), - "Tagalog": range(5888, 5920), - "Hanunoo": range(5920, 5952), - "Buhid": range(5952, 5984), - "Tagbanwa": range(5984, 6016), - "Khmer": range(6016, 6144), - "Mongolian": range(6144, 6320), - "Unified Canadian Aboriginal Syllabics Extended": range(6320, 6400), - "Limbu": range(6400, 6480), - "Tai Le": range(6480, 6528), - "New Tai Lue": range(6528, 6624), - "Khmer Symbols": range(6624, 6656), - "Buginese": range(6656, 6688), - "Tai Tham": range(6688, 6832), - "Combining Diacritical Marks Extended": range(6832, 6912), - "Balinese": range(6912, 7040), - "Sundanese": range(7040, 7104), - "Batak": range(7104, 7168), - "Lepcha": range(7168, 7248), - "Ol Chiki": range(7248, 7296), - "Cyrillic Extended-C": range(7296, 7312), - "Georgian Extended": range(7312, 7360), - "Sundanese Supplement": range(7360, 7376), - "Vedic Extensions": range(7376, 7424), - "Phonetic Extensions": range(7424, 7552), - "Phonetic Extensions Supplement": range(7552, 7616), - "Combining Diacritical Marks Supplement": range(7616, 7680), - "Latin Extended Additional": range(7680, 7936), - "Greek Extended": range(7936, 8192), - "General Punctuation": range(8192, 8304), - "Superscripts and Subscripts": range(8304, 8352), - "Currency Symbols": range(8352, 8400), - "Combining Diacritical Marks for Symbols": range(8400, 8448), - "Letterlike Symbols": range(8448, 8528), - "Number Forms": range(8528, 8592), - "Arrows": range(8592, 8704), - "Mathematical Operators": range(8704, 8960), - "Miscellaneous Technical": range(8960, 9216), - "Control Pictures": range(9216, 9280), - "Optical Character Recognition": range(9280, 9312), - "Enclosed Alphanumerics": range(9312, 9472), - "Box Drawing": range(9472, 9600), - "Block Elements": range(9600, 9632), - "Geometric Shapes": range(9632, 9728), - "Miscellaneous Symbols": range(9728, 9984), - "Dingbats": range(9984, 10176), - "Miscellaneous Mathematical Symbols-A": range(10176, 10224), - "Supplemental Arrows-A": range(10224, 10240), - "Braille Patterns": range(10240, 10496), - "Supplemental Arrows-B": range(10496, 10624), - "Miscellaneous Mathematical Symbols-B": range(10624, 10752), - "Supplemental Mathematical Operators": range(10752, 11008), - "Miscellaneous Symbols and Arrows": range(11008, 11264), - "Glagolitic": range(11264, 11360), - "Latin Extended-C": range(11360, 11392), - "Coptic": range(11392, 11520), - "Georgian Supplement": range(11520, 11568), - "Tifinagh": range(11568, 11648), - "Ethiopic Extended": range(11648, 11744), - "Cyrillic Extended-A": range(11744, 11776), - "Supplemental Punctuation": range(11776, 11904), - "CJK Radicals Supplement": range(11904, 12032), - "Kangxi Radicals": range(12032, 12256), - "Ideographic Description Characters": range(12272, 12288), - "CJK Symbols and Punctuation": range(12288, 12352), - "Hiragana": range(12352, 12448), - "Katakana": range(12448, 12544), - "Bopomofo": range(12544, 12592), - "Hangul Compatibility Jamo": range(12592, 12688), - "Kanbun": range(12688, 12704), - "Bopomofo Extended": range(12704, 12736), - "CJK Strokes": range(12736, 12784), - "Katakana Phonetic Extensions": range(12784, 12800), - "Enclosed CJK Letters and Months": range(12800, 13056), - "CJK Compatibility": range(13056, 13312), - "CJK Unified Ideographs Extension A": range(13312, 19904), - "Yijing Hexagram Symbols": range(19904, 19968), - "CJK Unified Ideographs": range(19968, 40960), - "Yi Syllables": range(40960, 42128), - "Yi Radicals": range(42128, 42192), - "Lisu": range(42192, 42240), - "Vai": range(42240, 42560), - "Cyrillic Extended-B": range(42560, 42656), - "Bamum": range(42656, 42752), - "Modifier Tone Letters": range(42752, 42784), - "Latin Extended-D": range(42784, 43008), - "Syloti Nagri": range(43008, 43056), - "Common Indic Number Forms": range(43056, 43072), - "Phags-pa": range(43072, 43136), - "Saurashtra": range(43136, 43232), - "Devanagari Extended": range(43232, 43264), - "Kayah Li": range(43264, 43312), - "Rejang": range(43312, 43360), - "Hangul Jamo Extended-A": range(43360, 43392), - "Javanese": range(43392, 43488), - "Myanmar Extended-B": range(43488, 43520), - "Cham": range(43520, 43616), - "Myanmar Extended-A": range(43616, 43648), - "Tai Viet": range(43648, 43744), - "Meetei Mayek Extensions": range(43744, 43776), - "Ethiopic Extended-A": range(43776, 43824), - "Latin Extended-E": range(43824, 43888), - "Cherokee Supplement": range(43888, 43968), - "Meetei Mayek": range(43968, 44032), - "Hangul Syllables": range(44032, 55216), - "Hangul Jamo Extended-B": range(55216, 55296), - "High Surrogates": range(55296, 56192), - "High Private Use Surrogates": range(56192, 56320), - "Low Surrogates": range(56320, 57344), - "Private Use Area": range(57344, 63744), - "CJK Compatibility Ideographs": range(63744, 64256), - "Alphabetic Presentation Forms": range(64256, 64336), - "Arabic Presentation Forms-A": range(64336, 65024), - "Variation Selectors": range(65024, 65040), - "Vertical Forms": range(65040, 65056), - "Combining Half Marks": range(65056, 65072), - "CJK Compatibility Forms": range(65072, 65104), - "Small Form Variants": range(65104, 65136), - "Arabic Presentation Forms-B": range(65136, 65280), - "Halfwidth and Fullwidth Forms": range(65280, 65520), - "Specials": range(65520, 65536), - "Linear B Syllabary": range(65536, 65664), - "Linear B Ideograms": range(65664, 65792), - "Aegean Numbers": range(65792, 65856), - "Ancient Greek Numbers": range(65856, 65936), - "Ancient Symbols": range(65936, 66000), - "Phaistos Disc": range(66000, 66048), - "Lycian": range(66176, 66208), - "Carian": range(66208, 66272), - "Coptic Epact Numbers": range(66272, 66304), - "Old Italic": range(66304, 66352), - "Gothic": range(66352, 66384), - "Old Permic": range(66384, 66432), - "Ugaritic": range(66432, 66464), - "Old Persian": range(66464, 66528), - "Deseret": range(66560, 66640), - "Shavian": range(66640, 66688), - "Osmanya": range(66688, 66736), - "Osage": range(66736, 66816), - "Elbasan": range(66816, 66864), - "Caucasian Albanian": range(66864, 66928), - "Vithkuqi": range(66928, 67008), - "Todhri": range(67008, 67072), - "Linear A": range(67072, 67456), - "Latin Extended-F": range(67456, 67520), - "Cypriot Syllabary": range(67584, 67648), - "Imperial Aramaic": range(67648, 67680), - "Palmyrene": range(67680, 67712), - "Nabataean": range(67712, 67760), - "Hatran": range(67808, 67840), - "Phoenician": range(67840, 67872), - "Lydian": range(67872, 67904), - "Sidetic": range(67904, 67936), - "Meroitic Hieroglyphs": range(67968, 68000), - "Meroitic Cursive": range(68000, 68096), - "Kharoshthi": range(68096, 68192), - "Old South Arabian": range(68192, 68224), - "Old North Arabian": range(68224, 68256), - "Manichaean": range(68288, 68352), - "Avestan": range(68352, 68416), - "Inscriptional Parthian": range(68416, 68448), - "Inscriptional Pahlavi": range(68448, 68480), - "Psalter Pahlavi": range(68480, 68528), - "Old Turkic": range(68608, 68688), - "Old Hungarian": range(68736, 68864), - "Hanifi Rohingya": range(68864, 68928), - "Garay": range(68928, 69008), - "Rumi Numeral Symbols": range(69216, 69248), - "Yezidi": range(69248, 69312), - "Arabic Extended-C": range(69312, 69376), - "Old Sogdian": range(69376, 69424), - "Sogdian": range(69424, 69488), - "Old Uyghur": range(69488, 69552), - "Chorasmian": range(69552, 69600), - "Elymaic": range(69600, 69632), - "Brahmi": range(69632, 69760), - "Kaithi": range(69760, 69840), - "Sora Sompeng": range(69840, 69888), - "Chakma": range(69888, 69968), - "Mahajani": range(69968, 70016), - "Sharada": range(70016, 70112), - "Sinhala Archaic Numbers": range(70112, 70144), - "Khojki": range(70144, 70224), - "Multani": range(70272, 70320), - "Khudawadi": range(70320, 70400), - "Grantha": range(70400, 70528), - "Tulu-Tigalari": range(70528, 70656), - "Newa": range(70656, 70784), - "Tirhuta": range(70784, 70880), - "Siddham": range(71040, 71168), - "Modi": range(71168, 71264), - "Mongolian Supplement": range(71264, 71296), - "Takri": range(71296, 71376), - "Myanmar Extended-C": range(71376, 71424), - "Ahom": range(71424, 71504), - "Dogra": range(71680, 71760), - "Warang Citi": range(71840, 71936), - "Dives Akuru": range(71936, 72032), - "Nandinagari": range(72096, 72192), - "Zanabazar Square": range(72192, 72272), - "Soyombo": range(72272, 72368), - "Unified Canadian Aboriginal Syllabics Extended-A": range(72368, 72384), - "Pau Cin Hau": range(72384, 72448), - "Devanagari Extended-A": range(72448, 72544), - "Sharada Supplement": range(72544, 72576), - "Sunuwar": range(72640, 72704), - "Bhaiksuki": range(72704, 72816), - "Marchen": range(72816, 72896), - "Masaram Gondi": range(72960, 73056), - "Gunjala Gondi": range(73056, 73136), - "Tolong Siki": range(73136, 73200), - "Makasar": range(73440, 73472), - "Kawi": range(73472, 73568), - "Lisu Supplement": range(73648, 73664), - "Tamil Supplement": range(73664, 73728), - "Cuneiform": range(73728, 74752), - "Cuneiform Numbers and Punctuation": range(74752, 74880), - "Early Dynastic Cuneiform": range(74880, 75088), - "Cypro-Minoan": range(77712, 77824), - "Egyptian Hieroglyphs": range(77824, 78896), - "Egyptian Hieroglyph Format Controls": range(78896, 78944), - "Egyptian Hieroglyphs Extended-A": range(78944, 82944), - "Anatolian Hieroglyphs": range(82944, 83584), - "Gurung Khema": range(90368, 90432), - "Bamum Supplement": range(92160, 92736), - "Mro": range(92736, 92784), - "Tangsa": range(92784, 92880), - "Bassa Vah": range(92880, 92928), - "Pahawh Hmong": range(92928, 93072), - "Kirat Rai": range(93504, 93568), - "Medefaidrin": range(93760, 93856), - "Beria Erfe": range(93856, 93920), - "Miao": range(93952, 94112), - "Ideographic Symbols and Punctuation": range(94176, 94208), - "Tangut": range(94208, 100352), - "Tangut Components": range(100352, 101120), - "Khitan Small Script": range(101120, 101632), - "Tangut Supplement": range(101632, 101760), - "Tangut Components Supplement": range(101760, 101888), - "Kana Extended-B": range(110576, 110592), - "Kana Supplement": range(110592, 110848), - "Kana Extended-A": range(110848, 110896), - "Small Kana Extension": range(110896, 110960), - "Nushu": range(110960, 111360), - "Duployan": range(113664, 113824), - "Shorthand Format Controls": range(113824, 113840), - "Symbols for Legacy Computing Supplement": range(117760, 118464), - "Miscellaneous Symbols Supplement": range(118464, 118528), - "Znamenny Musical Notation": range(118528, 118736), - "Byzantine Musical Symbols": range(118784, 119040), - "Musical Symbols": range(119040, 119296), - "Ancient Greek Musical Notation": range(119296, 119376), - "Kaktovik Numerals": range(119488, 119520), - "Mayan Numerals": range(119520, 119552), - "Tai Xuan Jing Symbols": range(119552, 119648), - "Counting Rod Numerals": range(119648, 119680), - "Mathematical Alphanumeric Symbols": range(119808, 120832), - "Sutton SignWriting": range(120832, 121520), - "Latin Extended-G": range(122624, 122880), - "Glagolitic Supplement": range(122880, 122928), - "Cyrillic Extended-D": range(122928, 123024), - "Nyiakeng Puachue Hmong": range(123136, 123216), - "Toto": range(123536, 123584), - "Wancho": range(123584, 123648), - "Nag Mundari": range(124112, 124160), - "Ol Onal": range(124368, 124416), - "Tai Yo": range(124608, 124672), - "Ethiopic Extended-B": range(124896, 124928), - "Mende Kikakui": range(124928, 125152), - "Adlam": range(125184, 125280), - "Indic Siyaq Numbers": range(126064, 126144), - "Ottoman Siyaq Numbers": range(126208, 126288), - "Arabic Mathematical Alphabetic Symbols": range(126464, 126720), - "Mahjong Tiles": range(126976, 127024), - "Domino Tiles": range(127024, 127136), - "Playing Cards": range(127136, 127232), - "Enclosed Alphanumeric Supplement": range(127232, 127488), - "Enclosed Ideographic Supplement": range(127488, 127744), - "Miscellaneous Symbols and Pictographs": range(127744, 128512), - "Emoticons": range(128512, 128592), - "Ornamental Dingbats": range(128592, 128640), - "Transport and Map Symbols": range(128640, 128768), - "Alchemical Symbols": range(128768, 128896), - "Geometric Shapes Extended": range(128896, 129024), - "Supplemental Arrows-C": range(129024, 129280), - "Supplemental Symbols and Pictographs": range(129280, 129536), - "Chess Symbols": range(129536, 129648), - "Symbols and Pictographs Extended-A": range(129648, 129792), - "Symbols for Legacy Computing": range(129792, 130048), - "CJK Unified Ideographs Extension B": range(131072, 173792), - "CJK Unified Ideographs Extension C": range(173824, 177984), - "CJK Unified Ideographs Extension D": range(177984, 178208), - "CJK Unified Ideographs Extension E": range(178208, 183984), - "CJK Unified Ideographs Extension F": range(183984, 191472), - "CJK Unified Ideographs Extension I": range(191472, 192096), - "CJK Compatibility Ideographs Supplement": range(194560, 195104), - "CJK Unified Ideographs Extension G": range(196608, 201552), - "CJK Unified Ideographs Extension H": range(201552, 205744), - "CJK Unified Ideographs Extension J": range(205744, 210048), - "Tags": range(917504, 917632), - "Variation Selectors Supplement": range(917760, 918000), - "Supplementary Private Use Area-A": range(983040, 1048576), - "Supplementary Private Use Area-B": range(1048576, 1114112), -} - - -UNICODE_SECONDARY_RANGE_KEYWORD: list[str] = [ - "Supplement", - "Extended", - "Extensions", - "Modifier", - "Marks", - "Punctuation", - "Symbols", - "Forms", - "Operators", - "Miscellaneous", - "Drawing", - "Block", - "Shapes", - "Supplemental", - "Tags", -] - -RE_POSSIBLE_ENCODING_INDICATION = re_compile( - r"(?:(?:encoding)|(?:charset)|(?:coding))(?:[\:= ]{1,10})(?:[\"\']?)([a-zA-Z0-9\-_]+)(?:[\"\']?)", - IGNORECASE, -) - -IANA_NO_ALIASES = [ - "cp720", - "cp737", - "cp856", - "cp874", - "cp875", - "cp1006", - "koi8_r", - "koi8_t", - "koi8_u", -] - -IANA_SUPPORTED: list[str] = sorted( - filter( - lambda x: x.endswith("_codec") is False - and x not in {"rot_13", "tactis", "mbcs"}, - list(set(aliases.values())) + IANA_NO_ALIASES, - ) -) - -IANA_SUPPORTED_COUNT: int = len(IANA_SUPPORTED) - -# pre-computed code page that are similar using the function cp_similarity. -IANA_SUPPORTED_SIMILAR: dict[str, list[str]] = { - "cp037": ["cp1026", "cp1140", "cp273", "cp500"], - "cp1026": ["cp037", "cp1140", "cp273", "cp500"], - "cp1125": ["cp866"], - "cp1140": ["cp037", "cp1026", "cp273", "cp500"], - "cp1250": ["iso8859_2"], - "cp1251": ["kz1048", "ptcp154"], - "cp1252": ["iso8859_15", "iso8859_9", "latin_1"], - "cp1253": ["iso8859_7"], - "cp1254": ["iso8859_15", "iso8859_9", "latin_1"], - "cp1257": ["iso8859_13"], - "cp273": ["cp037", "cp1026", "cp1140", "cp500"], - "cp437": ["cp850", "cp858", "cp860", "cp861", "cp862", "cp863", "cp865"], - "cp500": ["cp037", "cp1026", "cp1140", "cp273"], - "cp850": ["cp437", "cp857", "cp858", "cp865"], - "cp857": ["cp850", "cp858", "cp865"], - "cp858": ["cp437", "cp850", "cp857", "cp865"], - "cp860": ["cp437", "cp861", "cp862", "cp863", "cp865"], - "cp861": ["cp437", "cp860", "cp862", "cp863", "cp865"], - "cp862": ["cp437", "cp860", "cp861", "cp863", "cp865"], - "cp863": ["cp437", "cp860", "cp861", "cp862", "cp865"], - "cp865": ["cp437", "cp850", "cp857", "cp858", "cp860", "cp861", "cp862", "cp863"], - "cp866": ["cp1125"], - "iso8859_10": ["iso8859_14", "iso8859_15", "iso8859_4", "iso8859_9", "latin_1"], - "iso8859_11": ["tis_620"], - "iso8859_13": ["cp1257"], - "iso8859_14": [ - "iso8859_10", - "iso8859_15", - "iso8859_16", - "iso8859_3", - "iso8859_9", - "latin_1", - ], - "iso8859_15": [ - "cp1252", - "cp1254", - "iso8859_10", - "iso8859_14", - "iso8859_16", - "iso8859_3", - "iso8859_9", - "latin_1", - ], - "iso8859_16": [ - "iso8859_14", - "iso8859_15", - "iso8859_2", - "iso8859_3", - "iso8859_9", - "latin_1", - ], - "iso8859_2": ["cp1250", "iso8859_16", "iso8859_4"], - "iso8859_3": ["iso8859_14", "iso8859_15", "iso8859_16", "iso8859_9", "latin_1"], - "iso8859_4": ["iso8859_10", "iso8859_2", "iso8859_9", "latin_1"], - "iso8859_7": ["cp1253"], - "iso8859_9": [ - "cp1252", - "cp1254", - "cp1258", - "iso8859_10", - "iso8859_14", - "iso8859_15", - "iso8859_16", - "iso8859_3", - "iso8859_4", - "latin_1", - ], - "kz1048": ["cp1251", "ptcp154"], - "latin_1": [ - "cp1252", - "cp1254", - "cp1258", - "iso8859_10", - "iso8859_14", - "iso8859_15", - "iso8859_16", - "iso8859_3", - "iso8859_4", - "iso8859_9", - ], - "mac_iceland": ["mac_roman", "mac_turkish"], - "mac_roman": ["mac_iceland", "mac_turkish"], - "mac_turkish": ["mac_iceland", "mac_roman"], - "ptcp154": ["cp1251", "kz1048"], - "tis_620": ["iso8859_11"], -} - - -CHARDET_CORRESPONDENCE: dict[str, str] = { - "iso2022_kr": "ISO-2022-KR", - "iso2022_jp": "ISO-2022-JP", - "euc_kr": "EUC-KR", - "tis_620": "TIS-620", - "utf_32": "UTF-32", - "euc_jp": "EUC-JP", - "koi8_r": "KOI8-R", - "iso8859_1": "ISO-8859-1", - "iso8859_2": "ISO-8859-2", - "iso8859_5": "ISO-8859-5", - "iso8859_6": "ISO-8859-6", - "iso8859_7": "ISO-8859-7", - "iso8859_8": "ISO-8859-8", - "utf_16": "UTF-16", - "cp855": "IBM855", - "mac_cyrillic": "MacCyrillic", - "gb2312": "GB2312", - "gb18030": "GB18030", - "cp932": "CP932", - "cp866": "IBM866", - "utf_8": "utf-8", - "utf_8_sig": "UTF-8-SIG", - "shift_jis": "SHIFT_JIS", - "big5": "Big5", - "cp1250": "windows-1250", - "cp1251": "windows-1251", - "cp1252": "Windows-1252", - "cp1253": "windows-1253", - "cp1255": "windows-1255", - "cp1256": "windows-1256", - "cp1254": "Windows-1254", - "cp949": "CP949", -} - - -COMMON_SAFE_ASCII_CHARACTERS: frozenset[str] = frozenset( - { - "<", - ">", - "=", - ":", - "/", - "&", - ";", - "{", - "}", - "[", - "]", - ",", - "|", - '"', - "-", - "(", - ")", - } -) - -# Sample character sets — replace with full lists if needed -COMMON_CHINESE_CHARACTERS = "的一是在不了有和人这中大为上个国我以要他时来用们生到作地于出就分对成会可主发年动同工也能下过子说产种面而方后多定行学法所民得经十三之进着等部度家电力里如水化高自二理起小物现实加量都两体制机当使点从业本去把性好应开它合还因由其些然前外天政四日那社义事平形相全表间样与关各重新线内数正心反你明看原又么利比或但质气第向道命此变条只没结解问意建月公无系军很情者最立代想已通并提直题党程展五果料象员革位入常文总次品式活设及管特件长求老头基资边流路级少图山统接知较将组见计别她手角期根论运农指几九区强放决西被干做必战先回则任取据处队南给色光门即保治北造百规热领七海口东导器压志世金增争济阶油思术极交受联什认六共权收证改清己美再采转更单风切打白教速花带安场身车例真务具万每目至达走积示议声报斗完类八离华名确才科张信马节话米整空元况今集温传土许步群广石记需段研界拉林律叫且究观越织装影算低持音众书布复容儿须际商非验连断深难近矿千周委素技备半办青省列习响约支般史感劳便团往酸历市克何除消构府太准精值号率族维划选标写存候毛亲快效斯院查江型眼王按格养易置派层片始却专状育厂京识适属圆包火住调满县局照参红细引听该铁价严龙飞" - -COMMON_JAPANESE_CHARACTERS = "日一国年大十二本中長出三時行見月分後前生五間上東四今金九入学高円子外八六下来気小七山話女北午百書先名川千水半男西電校語土木聞食車何南万毎白天母火右読友左休父雨" - -COMMON_KOREAN_CHARACTERS = "一二三四五六七八九十百千萬上下左右中人女子大小山川日月火水木金土父母天地國名年時文校學生" - -# Combine all into a frozenset -COMMON_CJK_CHARACTERS = frozenset( - "".join( - [ - COMMON_CHINESE_CHARACTERS, - COMMON_JAPANESE_CHARACTERS, - COMMON_KOREAN_CHARACTERS, - ] - ) -) - -KO_NAMES: frozenset[str] = frozenset({"johab", "cp949", "euc_kr"}) -ZH_NAMES: frozenset[str] = frozenset({"big5", "cp950", "big5hkscs", "hz"}) - -# Logging LEVEL below DEBUG -TRACE: int = 5 - - -# Language label that contain the em dash "—" -# character are to be considered alternative seq to origin -FREQUENCIES: dict[str, list[str]] = { - "English": [ - "e", - "a", - "t", - "i", - "o", - "n", - "s", - "r", - "h", - "l", - "d", - "c", - "u", - "m", - "f", - "p", - "g", - "w", - "y", - "b", - "v", - "k", - "x", - "j", - "z", - "q", - ], - "English—": [ - "e", - "a", - "t", - "i", - "o", - "n", - "s", - "r", - "h", - "l", - "d", - "c", - "m", - "u", - "f", - "p", - "g", - "w", - "b", - "y", - "v", - "k", - "j", - "x", - "z", - "q", - ], - "German": [ - "e", - "n", - "i", - "r", - "s", - "t", - "a", - "d", - "h", - "u", - "l", - "g", - "o", - "c", - "m", - "b", - "f", - "k", - "w", - "z", - "p", - "v", - "ü", - "ä", - "ö", - "j", - ], - "French": [ - "e", - "a", - "s", - "n", - "i", - "t", - "r", - "l", - "u", - "o", - "d", - "c", - "p", - "m", - "é", - "v", - "g", - "f", - "b", - "h", - "q", - "à", - "x", - "è", - "y", - "j", - ], - "Dutch": [ - "e", - "n", - "a", - "i", - "r", - "t", - "o", - "d", - "s", - "l", - "g", - "h", - "v", - "m", - "u", - "k", - "c", - "p", - "b", - "w", - "j", - "z", - "f", - "y", - "x", - "ë", - ], - "Italian": [ - "e", - "i", - "a", - "o", - "n", - "l", - "t", - "r", - "s", - "c", - "d", - "u", - "p", - "m", - "g", - "v", - "f", - "b", - "z", - "h", - "q", - "è", - "à", - "k", - "y", - "ò", - ], - "Polish": [ - "a", - "i", - "o", - "e", - "n", - "r", - "z", - "w", - "s", - "c", - "t", - "k", - "y", - "d", - "p", - "m", - "u", - "l", - "j", - "ł", - "g", - "b", - "h", - "ą", - "ę", - "ó", - ], - "Spanish": [ - "e", - "a", - "o", - "n", - "s", - "r", - "i", - "l", - "d", - "t", - "c", - "u", - "m", - "p", - "b", - "g", - "v", - "f", - "y", - "ó", - "h", - "q", - "í", - "j", - "z", - "á", - ], - "Russian": [ - "о", - "е", - "а", - "и", - "н", - "т", - "с", - "р", - "в", - "л", - "к", - "м", - "д", - "п", - "у", - "г", - "я", - "ы", - "з", - "б", - "й", - "ь", - "ч", - "х", - "ж", - "ц", - ], - # Jap-Kanji - "Japanese": [ - "日", - "一", - "人", - "年", - "大", - "十", - "二", - "本", - "中", - "長", - "出", - "三", - "時", - "行", - "見", - "月", - "分", - "後", - "前", - "生", - "五", - "間", - "上", - "東", - "四", - "今", - "金", - "九", - "入", - "学", - "高", - "円", - "子", - "外", - "八", - "六", - "下", - "来", - "気", - "小", - "七", - "山", - "話", - "女", - "北", - "午", - "百", - "書", - "先", - "名", - "川", - "千", - "水", - "半", - "男", - "西", - "電", - "校", - "語", - "土", - "木", - "聞", - "食", - "車", - "何", - "南", - "万", - "毎", - "白", - "天", - "母", - "火", - "右", - "読", - "友", - "左", - "休", - "父", - "雨", - ], - # Jap-Katakana - "Japanese—": [ - "ー", - "ン", - "ス", - "・", - "ル", - "ト", - "リ", - "イ", - "ア", - "ラ", - "ッ", - "ク", - "ド", - "シ", - "レ", - "ジ", - "タ", - "フ", - "ロ", - "カ", - "テ", - "マ", - "ィ", - "グ", - "バ", - "ム", - "プ", - "オ", - "コ", - "デ", - "ニ", - "ウ", - "メ", - "サ", - "ビ", - "ナ", - "ブ", - "ャ", - "エ", - "ュ", - "チ", - "キ", - "ズ", - "ダ", - "パ", - "ミ", - "ェ", - "ョ", - "ハ", - "セ", - "ベ", - "ガ", - "モ", - "ツ", - "ネ", - "ボ", - "ソ", - "ノ", - "ァ", - "ヴ", - "ワ", - "ポ", - "ペ", - "ピ", - "ケ", - "ゴ", - "ギ", - "ザ", - "ホ", - "ゲ", - "ォ", - "ヤ", - "ヒ", - "ユ", - "ヨ", - "ヘ", - "ゼ", - "ヌ", - "ゥ", - "ゾ", - "ヶ", - "ヂ", - "ヲ", - "ヅ", - "ヵ", - "ヱ", - "ヰ", - "ヮ", - "ヽ", - "゠", - "ヾ", - "ヷ", - "ヿ", - "ヸ", - "ヹ", - "ヺ", - ], - # Jap-Hiragana - "Japanese——": [ - "の", - "に", - "る", - "た", - "と", - "は", - "し", - "い", - "を", - "で", - "て", - "が", - "な", - "れ", - "か", - "ら", - "さ", - "っ", - "り", - "す", - "あ", - "も", - "こ", - "ま", - "う", - "く", - "よ", - "き", - "ん", - "め", - "お", - "け", - "そ", - "つ", - "だ", - "や", - "え", - "ど", - "わ", - "ち", - "み", - "せ", - "じ", - "ば", - "へ", - "び", - "ず", - "ろ", - "ほ", - "げ", - "む", - "べ", - "ひ", - "ょ", - "ゆ", - "ぶ", - "ご", - "ゃ", - "ね", - "ふ", - "ぐ", - "ぎ", - "ぼ", - "ゅ", - "づ", - "ざ", - "ぞ", - "ぬ", - "ぜ", - "ぱ", - "ぽ", - "ぷ", - "ぴ", - "ぃ", - "ぁ", - "ぇ", - "ぺ", - "ゞ", - "ぢ", - "ぉ", - "ぅ", - "ゐ", - "ゝ", - "ゑ", - "゛", - "゜", - "ゎ", - "ゔ", - "゚", - "ゟ", - "゙", - "ゕ", - "ゖ", - ], - "Portuguese": [ - "a", - "e", - "o", - "s", - "i", - "r", - "d", - "n", - "t", - "m", - "u", - "c", - "l", - "p", - "g", - "v", - "b", - "f", - "h", - "ã", - "q", - "é", - "ç", - "á", - "z", - "í", - ], - "Swedish": [ - "e", - "a", - "n", - "r", - "t", - "s", - "i", - "l", - "d", - "o", - "m", - "k", - "g", - "v", - "h", - "f", - "u", - "p", - "ä", - "c", - "b", - "ö", - "å", - "y", - "j", - "x", - ], - "Chinese": [ - "的", - "一", - "是", - "不", - "了", - "在", - "人", - "有", - "我", - "他", - "这", - "个", - "们", - "中", - "来", - "上", - "大", - "为", - "和", - "国", - "地", - "到", - "以", - "说", - "时", - "要", - "就", - "出", - "会", - "可", - "也", - "你", - "对", - "生", - "能", - "而", - "子", - "那", - "得", - "于", - "着", - "下", - "自", - "之", - "年", - "过", - "发", - "后", - "作", - "里", - "用", - "道", - "行", - "所", - "然", - "家", - "种", - "事", - "成", - "方", - "多", - "经", - "么", - "去", - "法", - "学", - "如", - "都", - "同", - "现", - "当", - "没", - "动", - "面", - "起", - "看", - "定", - "天", - "分", - "还", - "进", - "好", - "小", - "部", - "其", - "些", - "主", - "样", - "理", - "心", - "她", - "本", - "前", - "开", - "但", - "因", - "只", - "从", - "想", - "实", - ], - "Ukrainian": [ - "о", - "а", - "н", - "і", - "и", - "р", - "в", - "т", - "е", - "с", - "к", - "л", - "у", - "д", - "м", - "п", - "з", - "я", - "ь", - "б", - "г", - "й", - "ч", - "х", - "ц", - "ї", - ], - "Norwegian": [ - "e", - "r", - "n", - "t", - "a", - "s", - "i", - "o", - "l", - "d", - "g", - "k", - "m", - "v", - "f", - "p", - "u", - "b", - "h", - "å", - "y", - "j", - "ø", - "c", - "æ", - "w", - ], - "Finnish": [ - "a", - "i", - "n", - "t", - "e", - "s", - "l", - "o", - "u", - "k", - "ä", - "m", - "r", - "v", - "j", - "h", - "p", - "y", - "d", - "ö", - "g", - "c", - "b", - "f", - "w", - "z", - ], - "Vietnamese": [ - "n", - "h", - "t", - "i", - "c", - "g", - "a", - "o", - "u", - "m", - "l", - "r", - "à", - "đ", - "s", - "e", - "v", - "p", - "b", - "y", - "ư", - "d", - "á", - "k", - "ộ", - "ế", - ], - "Czech": [ - "o", - "e", - "a", - "n", - "t", - "s", - "i", - "l", - "v", - "r", - "k", - "d", - "u", - "m", - "p", - "í", - "c", - "h", - "z", - "á", - "y", - "j", - "b", - "ě", - "é", - "ř", - ], - "Hungarian": [ - "e", - "a", - "t", - "l", - "s", - "n", - "k", - "r", - "i", - "o", - "z", - "á", - "é", - "g", - "m", - "b", - "y", - "v", - "d", - "h", - "u", - "p", - "j", - "ö", - "f", - "c", - ], - "Korean": [ - "이", - "다", - "에", - "의", - "는", - "로", - "하", - "을", - "가", - "고", - "지", - "서", - "한", - "은", - "기", - "으", - "년", - "대", - "사", - "시", - "를", - "리", - "도", - "인", - "스", - "일", - ], - "Indonesian": [ - "a", - "n", - "e", - "i", - "r", - "t", - "u", - "s", - "d", - "k", - "m", - "l", - "g", - "p", - "b", - "o", - "h", - "y", - "j", - "c", - "w", - "f", - "v", - "z", - "x", - "q", - ], - "Turkish": [ - "a", - "e", - "i", - "n", - "r", - "l", - "ı", - "k", - "d", - "t", - "s", - "m", - "y", - "u", - "o", - "b", - "ü", - "ş", - "v", - "g", - "z", - "h", - "c", - "p", - "ç", - "ğ", - ], - "Romanian": [ - "e", - "i", - "a", - "r", - "n", - "t", - "u", - "l", - "o", - "c", - "s", - "d", - "p", - "m", - "ă", - "f", - "v", - "î", - "g", - "b", - "ș", - "ț", - "z", - "h", - "â", - "j", - ], - "Farsi": [ - "ا", - "ی", - "ر", - "د", - "ن", - "ه", - "و", - "م", - "ت", - "ب", - "س", - "ل", - "ک", - "ش", - "ز", - "ف", - "گ", - "ع", - "خ", - "ق", - "ج", - "آ", - "پ", - "ح", - "ط", - "ص", - ], - "Arabic": [ - "ا", - "ل", - "ي", - "م", - "و", - "ن", - "ر", - "ت", - "ب", - "ة", - "ع", - "د", - "س", - "ف", - "ه", - "ك", - "ق", - "أ", - "ح", - "ج", - "ش", - "ط", - "ص", - "ى", - "خ", - "إ", - ], - "Danish": [ - "e", - "r", - "n", - "t", - "a", - "i", - "s", - "d", - "l", - "o", - "g", - "m", - "k", - "f", - "v", - "u", - "b", - "h", - "p", - "å", - "y", - "ø", - "æ", - "c", - "j", - "w", - ], - "Serbian": [ - "а", - "и", - "о", - "е", - "н", - "р", - "с", - "у", - "т", - "к", - "ј", - "в", - "д", - "м", - "п", - "л", - "г", - "з", - "б", - "a", - "i", - "e", - "o", - "n", - "ц", - "ш", - ], - "Lithuanian": [ - "i", - "a", - "s", - "o", - "r", - "e", - "t", - "n", - "u", - "k", - "m", - "l", - "p", - "v", - "d", - "j", - "g", - "ė", - "b", - "y", - "ų", - "š", - "ž", - "c", - "ą", - "į", - ], - "Slovene": [ - "e", - "a", - "i", - "o", - "n", - "r", - "s", - "l", - "t", - "j", - "v", - "k", - "d", - "p", - "m", - "u", - "z", - "b", - "g", - "h", - "č", - "c", - "š", - "ž", - "f", - "y", - ], - "Slovak": [ - "o", - "a", - "e", - "n", - "i", - "r", - "v", - "t", - "s", - "l", - "k", - "d", - "m", - "p", - "u", - "c", - "h", - "j", - "b", - "z", - "á", - "y", - "ý", - "í", - "č", - "é", - ], - "Hebrew": [ - "י", - "ו", - "ה", - "ל", - "ר", - "ב", - "ת", - "מ", - "א", - "ש", - "נ", - "ע", - "ם", - "ד", - "ק", - "ח", - "פ", - "ס", - "כ", - "ג", - "ט", - "צ", - "ן", - "ז", - "ך", - ], - "Bulgarian": [ - "а", - "и", - "о", - "е", - "н", - "т", - "р", - "с", - "в", - "л", - "к", - "д", - "п", - "м", - "з", - "г", - "я", - "ъ", - "у", - "б", - "ч", - "ц", - "й", - "ж", - "щ", - "х", - ], - "Croatian": [ - "a", - "i", - "o", - "e", - "n", - "r", - "j", - "s", - "t", - "u", - "k", - "l", - "v", - "d", - "m", - "p", - "g", - "z", - "b", - "c", - "č", - "h", - "š", - "ž", - "ć", - "f", - ], - "Hindi": [ - "क", - "र", - "स", - "न", - "त", - "म", - "ह", - "प", - "य", - "ल", - "व", - "ज", - "द", - "ग", - "ब", - "श", - "ट", - "अ", - "ए", - "थ", - "भ", - "ड", - "च", - "ध", - "ष", - "इ", - ], - "Estonian": [ - "a", - "i", - "e", - "s", - "t", - "l", - "u", - "n", - "o", - "k", - "r", - "d", - "m", - "v", - "g", - "p", - "j", - "h", - "ä", - "b", - "õ", - "ü", - "f", - "c", - "ö", - "y", - ], - "Thai": [ - "า", - "น", - "ร", - "อ", - "ก", - "เ", - "ง", - "ม", - "ย", - "ล", - "ว", - "ด", - "ท", - "ส", - "ต", - "ะ", - "ป", - "บ", - "ค", - "ห", - "แ", - "จ", - "พ", - "ช", - "ข", - "ใ", - ], - "Greek": [ - "α", - "τ", - "ο", - "ι", - "ε", - "ν", - "ρ", - "σ", - "κ", - "η", - "π", - "ς", - "υ", - "μ", - "λ", - "ί", - "ό", - "ά", - "γ", - "έ", - "δ", - "ή", - "ω", - "χ", - "θ", - "ύ", - ], - "Tamil": [ - "க", - "த", - "ப", - "ட", - "ர", - "ம", - "ல", - "ன", - "வ", - "ற", - "ய", - "ள", - "ச", - "ந", - "இ", - "ண", - "அ", - "ஆ", - "ழ", - "ங", - "எ", - "உ", - "ஒ", - "ஸ", - ], - "Kazakh": [ - "а", - "ы", - "е", - "н", - "т", - "р", - "л", - "і", - "д", - "с", - "м", - "қ", - "к", - "о", - "б", - "и", - "у", - "ғ", - "ж", - "ң", - "з", - "ш", - "й", - "п", - "г", - "ө", - ], -} - -LANGUAGE_SUPPORTED_COUNT: int = len(FREQUENCIES) - -# Bit flags for unified character classification. -# A single unicodedata.name() call sets all relevant flags at once. -_LATIN: int = 1 -_ACCENTUATED: int = 1 << 1 -_CJK: int = 1 << 2 -_HANGUL: int = 1 << 3 -_KATAKANA: int = 1 << 4 -_HIRAGANA: int = 1 << 5 -_THAI: int = 1 << 6 -_ARABIC: int = 1 << 7 -_ARABIC_ISOLATED_FORM: int = 1 << 8 - -_ACCENT_KEYWORDS: tuple[str, ...] = ( - "WITH GRAVE", - "WITH ACUTE", - "WITH CEDILLA", - "WITH DIAERESIS", - "WITH CIRCUMFLEX", - "WITH TILDE", - "WITH MACRON", - "WITH RING ABOVE", -) - -# Pre-built lookup structures for FREQUENCIES (computed once at import time). -# character -> rank mapping per language (replaces list .index() calls). -_FREQUENCIES_RANK: dict[str, dict[str, int]] = { - lang: {char: rank for rank, char in enumerate(chars)} - for lang, chars in FREQUENCIES.items() -} - -# frozenset per language (avoids rebuilding set() per call). -_FREQUENCIES_SET: dict[str, frozenset[str]] = { - lang: frozenset(chars) for lang, chars in FREQUENCIES.items() -} diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/legacy.py b/notification-service/venv/Lib/site-packages/charset_normalizer/legacy.py deleted file mode 100644 index 293c1ef..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer/legacy.py +++ /dev/null @@ -1,79 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING, Any -from warnings import warn - -from .api import from_bytes -from .constant import CHARDET_CORRESPONDENCE, TOO_SMALL_SEQUENCE - -if TYPE_CHECKING: - from typing import TypedDict - - class ResultDict(TypedDict): - encoding: str | None - language: str - confidence: float | None - - -def detect( - byte_str: bytes, should_rename_legacy: bool = False, **kwargs: Any -) -> ResultDict: - """ - chardet legacy method - Detect the encoding of the given byte string. It should be mostly backward-compatible. - Encoding name will match Chardet own writing whenever possible. (Not on encoding name unsupported by it) - This function is deprecated and should be used to migrate your project easily, consult the documentation for - further information. Not planned for removal. - - :param byte_str: The byte sequence to examine. - :param should_rename_legacy: Should we rename legacy encodings - to their more modern equivalents? - """ - if len(kwargs): - warn( - f"charset-normalizer disregard arguments '{','.join(list(kwargs.keys()))}' in legacy function detect()" - ) - - if not isinstance(byte_str, (bytearray, bytes)): - raise TypeError( # pragma: nocover - f"Expected object of type bytes or bytearray, got: {type(byte_str)}" - ) - - if isinstance(byte_str, bytearray): - byte_str = bytes(byte_str) - - r = from_bytes(byte_str).best() - - encoding = r.encoding if r is not None else None - language = r.language if r is not None and r.language != "Unknown" else "" - confidence = 1.0 - r.chaos if r is not None else None - - # automatically lower confidence - # on small bytes samples. - # https://github.com/jawah/charset_normalizer/issues/391 - if ( - confidence is not None - and confidence >= 0.9 - and encoding - not in { - "utf_8", - "ascii", - } - and r.bom is False # type: ignore[union-attr] - and len(byte_str) < TOO_SMALL_SEQUENCE - ): - confidence -= 0.2 - - # Note: CharsetNormalizer does not return 'UTF-8-SIG' as the sig get stripped in the detection/normalization process - # but chardet does return 'utf-8-sig' and it is a valid codec name. - if r is not None and encoding == "utf_8" and r.bom: - encoding += "_sig" - - if should_rename_legacy is False and encoding in CHARDET_CORRESPONDENCE: - encoding = CHARDET_CORRESPONDENCE[encoding] - - return { - "encoding": encoding, - "language": language, - "confidence": confidence, - } diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/md.cp312-win_amd64.pyd b/notification-service/venv/Lib/site-packages/charset_normalizer/md.cp312-win_amd64.pyd deleted file mode 100644 index 244f4a7..0000000 Binary files a/notification-service/venv/Lib/site-packages/charset_normalizer/md.cp312-win_amd64.pyd and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/md.py b/notification-service/venv/Lib/site-packages/charset_normalizer/md.py deleted file mode 100644 index b41d9cf..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer/md.py +++ /dev/null @@ -1,936 +0,0 @@ -from __future__ import annotations - -import sys -from functools import lru_cache -from logging import getLogger - -if sys.version_info >= (3, 8): - from typing import final -else: - try: - from typing_extensions import final - except ImportError: - - def final(cls): # type: ignore[misc,no-untyped-def] - return cls - - -from .constant import ( - COMMON_CJK_CHARACTERS, - COMMON_SAFE_ASCII_CHARACTERS, - TRACE, - UNICODE_SECONDARY_RANGE_KEYWORD, - _ACCENTUATED, - _ARABIC, - _ARABIC_ISOLATED_FORM, - _CJK, - _HANGUL, - _HIRAGANA, - _KATAKANA, - _LATIN, - _THAI, -) -from .utils import ( - _character_flags, - is_emoticon, - is_punctuation, - is_separator, - is_symbol, - remove_accent, - unicode_range, -) - -# Combined bitmask for CJK/Hangul/Katakana/Hiragana/Thai glyph detection. -_GLYPH_MASK: int = _CJK | _HANGUL | _KATAKANA | _HIRAGANA | _THAI - - -@final -class CharInfo: - """Pre-computed character properties shared across all detectors. - - Instantiated once and reused via :meth:`update` on every character - in the hot loop so that redundant calls to str methods - (``isalpha``, ``isupper``, …) and cached utility functions - (``_character_flags``, ``is_punctuation``, …) are avoided when - several plugins need the same information. - """ - - __slots__ = ( - "character", - "printable", - "alpha", - "upper", - "lower", - "space", - "digit", - "is_ascii", - "case_variable", - "flags", - "accentuated", - "latin", - "is_cjk", - "is_arabic", - "is_glyph", - "punct", - "sym", - ) - - def __init__(self) -> None: - self.character: str = "" - self.printable: bool = False - self.alpha: bool = False - self.upper: bool = False - self.lower: bool = False - self.space: bool = False - self.digit: bool = False - self.is_ascii: bool = False - self.case_variable: bool = False - self.flags: int = 0 - self.accentuated: bool = False - self.latin: bool = False - self.is_cjk: bool = False - self.is_arabic: bool = False - self.is_glyph: bool = False - self.punct: bool = False - self.sym: bool = False - - def update(self, character: str) -> None: - """Update all properties for *character* (called once per character).""" - self.character = character - - # ASCII fast-path: for characters with ord < 128, we can skip - # _character_flags() entirely and derive most properties from ord. - o: int = ord(character) - if o < 128: - self.is_ascii = True - self.accentuated = False - self.is_cjk = False - self.is_arabic = False - self.is_glyph = False - # ASCII alpha: a-z (97-122) or A-Z (65-90) - if 65 <= o <= 90: - # Uppercase ASCII letter - self.alpha = True - self.upper = True - self.lower = False - self.space = False - self.digit = False - self.printable = True - self.case_variable = True - self.flags = _LATIN - self.latin = True - self.punct = False - self.sym = False - elif 97 <= o <= 122: - # Lowercase ASCII letter - self.alpha = True - self.upper = False - self.lower = True - self.space = False - self.digit = False - self.printable = True - self.case_variable = True - self.flags = _LATIN - self.latin = True - self.punct = False - self.sym = False - elif 48 <= o <= 57: - # ASCII digit 0-9 - self.alpha = False - self.upper = False - self.lower = False - self.space = False - self.digit = True - self.printable = True - self.case_variable = False - self.flags = 0 - self.latin = False - self.punct = False - self.sym = False - elif o == 32 or (9 <= o <= 13): - # Space, tab, newline, etc. - self.alpha = False - self.upper = False - self.lower = False - self.space = True - self.digit = False - self.printable = o == 32 - self.case_variable = False - self.flags = 0 - self.latin = False - self.punct = False - self.sym = False - else: - # Other ASCII (punctuation, symbols, control chars) - self.printable = character.isprintable() - self.alpha = False - self.upper = False - self.lower = False - self.space = False - self.digit = False - self.case_variable = False - self.flags = 0 - self.latin = False - self.punct = is_punctuation(character) if self.printable else False - self.sym = is_symbol(character) if self.printable else False - else: - # Non-ASCII path - self.is_ascii = False - self.printable = character.isprintable() - self.alpha = character.isalpha() - self.upper = character.isupper() - self.lower = character.islower() - self.space = character.isspace() - self.digit = character.isdigit() - self.case_variable = self.lower != self.upper - - # Flag-based classification (single unicodedata.name() call, lru-cached) - flags: int - if self.alpha: - flags = _character_flags(character) - else: - flags = 0 - self.flags = flags - self.accentuated = bool(flags & _ACCENTUATED) - self.latin = bool(flags & _LATIN) - self.is_cjk = bool(flags & _CJK) - self.is_arabic = bool(flags & _ARABIC) - self.is_glyph = bool(flags & _GLYPH_MASK) - - # Eagerly compute punct and sym (avoids property dispatch overhead - # on 300K+ accesses in the hot loop). - self.punct = is_punctuation(character) if self.printable else False - self.sym = is_symbol(character) if self.printable else False - - -class MessDetectorPlugin: - """ - Base abstract class used for mess detection plugins. - All detectors MUST extend and implement given methods. - """ - - __slots__ = () - - def feed_info(self, character: str, info: CharInfo) -> None: - """ - The main routine to be executed upon character. - Insert the logic in witch the text would be considered chaotic. - """ - raise NotImplementedError # Defensive: - - def reset(self) -> None: # Defensive: - """ - Permit to reset the plugin to the initial state. - """ - raise NotImplementedError - - @property - def ratio(self) -> float: - """ - Compute the chaos ratio based on what your feed() has seen. - Must NOT be lower than 0.; No restriction gt 0. - """ - raise NotImplementedError # Defensive: - - -@final -class TooManySymbolOrPunctuationPlugin(MessDetectorPlugin): - __slots__ = ( - "_punctuation_count", - "_symbol_count", - "_character_count", - "_last_printable_char", - "_frenzy_symbol_in_word", - ) - - def __init__(self) -> None: - self._punctuation_count: int = 0 - self._symbol_count: int = 0 - self._character_count: int = 0 - - self._last_printable_char: str | None = None - self._frenzy_symbol_in_word: bool = False - - def feed_info(self, character: str, info: CharInfo) -> None: - """Optimized feed using pre-computed character info.""" - self._character_count += 1 - - if ( - character != self._last_printable_char - and character not in COMMON_SAFE_ASCII_CHARACTERS - ): - if info.punct: - self._punctuation_count += 1 - elif not info.digit and info.sym and not is_emoticon(character): - self._symbol_count += 2 - - self._last_printable_char = character - - def reset(self) -> None: # Abstract - self._punctuation_count = 0 - self._character_count = 0 - self._symbol_count = 0 - - @property - def ratio(self) -> float: - if self._character_count == 0: - return 0.0 - - ratio_of_punctuation: float = ( - self._punctuation_count + self._symbol_count - ) / self._character_count - - return ratio_of_punctuation if ratio_of_punctuation >= 0.3 else 0.0 - - -@final -class TooManyAccentuatedPlugin(MessDetectorPlugin): - __slots__ = ("_character_count", "_accentuated_count") - - def __init__(self) -> None: - self._character_count: int = 0 - self._accentuated_count: int = 0 - - def feed_info(self, character: str, info: CharInfo) -> None: - """Optimized feed using pre-computed character info.""" - self._character_count += 1 - - if info.accentuated: - self._accentuated_count += 1 - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._accentuated_count = 0 - - @property - def ratio(self) -> float: - if self._character_count < 8: - return 0.0 - - ratio_of_accentuation: float = self._accentuated_count / self._character_count - return ratio_of_accentuation if ratio_of_accentuation >= 0.35 else 0.0 - - -@final -class UnprintablePlugin(MessDetectorPlugin): - __slots__ = ("_unprintable_count", "_character_count") - - def __init__(self) -> None: - self._unprintable_count: int = 0 - self._character_count: int = 0 - - def feed_info(self, character: str, info: CharInfo) -> None: - """Optimized feed using pre-computed character info.""" - if ( - not info.space - and not info.printable - and character != "\x1a" - and character != "\ufeff" - ): - self._unprintable_count += 1 - self._character_count += 1 - - def reset(self) -> None: # Abstract - self._unprintable_count = 0 - - @property - def ratio(self) -> float: - if self._character_count == 0: # Defensive: - return 0.0 - - return (self._unprintable_count * 8) / self._character_count - - -@final -class SuspiciousDuplicateAccentPlugin(MessDetectorPlugin): - __slots__ = ( - "_successive_count", - "_character_count", - "_last_latin_character", - "_last_was_accentuated", - ) - - def __init__(self) -> None: - self._successive_count: int = 0 - self._character_count: int = 0 - - self._last_latin_character: str | None = None - self._last_was_accentuated: bool = False - - def feed_info(self, character: str, info: CharInfo) -> None: - """Optimized feed using pre-computed character info.""" - self._character_count += 1 - if ( - self._last_latin_character is not None - and info.accentuated - and self._last_was_accentuated - ): - if info.upper and self._last_latin_character.isupper(): - self._successive_count += 1 - if remove_accent(character) == remove_accent(self._last_latin_character): - self._successive_count += 1 - self._last_latin_character = character - self._last_was_accentuated = info.accentuated - - def reset(self) -> None: # Abstract - self._successive_count = 0 - self._character_count = 0 - self._last_latin_character = None - self._last_was_accentuated = False - - @property - def ratio(self) -> float: - if self._character_count == 0: - return 0.0 - - return (self._successive_count * 2) / self._character_count - - -@final -class SuspiciousRange(MessDetectorPlugin): - __slots__ = ( - "_suspicious_successive_range_count", - "_character_count", - "_last_printable_seen", - "_last_printable_range", - ) - - def __init__(self) -> None: - self._suspicious_successive_range_count: int = 0 - self._character_count: int = 0 - self._last_printable_seen: str | None = None - self._last_printable_range: str | None = None - - def feed_info(self, character: str, info: CharInfo) -> None: - """Optimized feed using pre-computed character info.""" - self._character_count += 1 - - if info.space or info.punct or character in COMMON_SAFE_ASCII_CHARACTERS: - self._last_printable_seen = None - self._last_printable_range = None - return - - if self._last_printable_seen is None: - self._last_printable_seen = character - self._last_printable_range = unicode_range(character) - return - - unicode_range_a: str | None = self._last_printable_range - unicode_range_b: str | None = unicode_range(character) - - if is_suspiciously_successive_range(unicode_range_a, unicode_range_b): - self._suspicious_successive_range_count += 1 - - self._last_printable_seen = character - self._last_printable_range = unicode_range_b - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._suspicious_successive_range_count = 0 - self._last_printable_seen = None - self._last_printable_range = None - - @property - def ratio(self) -> float: - if self._character_count <= 13: - return 0.0 - - ratio_of_suspicious_range_usage: float = ( - self._suspicious_successive_range_count * 2 - ) / self._character_count - - return ratio_of_suspicious_range_usage - - -@final -class SuperWeirdWordPlugin(MessDetectorPlugin): - __slots__ = ( - "_word_count", - "_bad_word_count", - "_foreign_long_count", - "_is_current_word_bad", - "_foreign_long_watch", - "_character_count", - "_bad_character_count", - "_buffer_length", - "_buffer_last_char", - "_buffer_last_char_accentuated", - "_buffer_accent_count", - "_buffer_glyph_count", - "_buffer_upper_count", - ) - - def __init__(self) -> None: - self._word_count: int = 0 - self._bad_word_count: int = 0 - self._foreign_long_count: int = 0 - - self._is_current_word_bad: bool = False - self._foreign_long_watch: bool = False - - self._character_count: int = 0 - self._bad_character_count: int = 0 - - self._buffer_length: int = 0 - self._buffer_last_char: str | None = None - self._buffer_last_char_accentuated: bool = False - self._buffer_accent_count: int = 0 - self._buffer_glyph_count: int = 0 - self._buffer_upper_count: int = 0 - - def feed_info(self, character: str, info: CharInfo) -> None: - """Optimized feed using pre-computed character info.""" - if info.alpha: - self._buffer_length += 1 - self._buffer_last_char = character - - if info.upper: - self._buffer_upper_count += 1 - - self._buffer_last_char_accentuated = info.accentuated - - if info.accentuated: - self._buffer_accent_count += 1 - if ( - not self._foreign_long_watch - and (not info.latin or info.accentuated) - and not info.is_glyph - ): - self._foreign_long_watch = True - if info.is_glyph: - self._buffer_glyph_count += 1 - return - if not self._buffer_length: - return - if info.space or info.punct or is_separator(character): - self._word_count += 1 - buffer_length: int = self._buffer_length - - self._character_count += buffer_length - - if buffer_length >= 4: - if self._buffer_accent_count / buffer_length >= 0.5: - self._is_current_word_bad = True - elif ( - self._buffer_last_char_accentuated - and self._buffer_last_char.isupper() # type: ignore[union-attr] - and self._buffer_upper_count != buffer_length - ): - self._foreign_long_count += 1 - self._is_current_word_bad = True - elif self._buffer_glyph_count == 1: - self._is_current_word_bad = True - self._foreign_long_count += 1 - if buffer_length >= 24 and self._foreign_long_watch: - probable_camel_cased: bool = ( - self._buffer_upper_count > 0 - and self._buffer_upper_count / buffer_length <= 0.3 - ) - - if not probable_camel_cased: - self._foreign_long_count += 1 - self._is_current_word_bad = True - - if self._is_current_word_bad: - self._bad_word_count += 1 - self._bad_character_count += buffer_length - self._is_current_word_bad = False - - self._foreign_long_watch = False - self._buffer_length = 0 - self._buffer_last_char = None - self._buffer_last_char_accentuated = False - self._buffer_accent_count = 0 - self._buffer_glyph_count = 0 - self._buffer_upper_count = 0 - elif ( - character not in {"<", ">", "-", "=", "~", "|", "_"} - and not info.digit - and info.sym - ): - self._is_current_word_bad = True - self._buffer_length += 1 - self._buffer_last_char = character - self._buffer_last_char_accentuated = False - - def reset(self) -> None: # Abstract - self._buffer_length = 0 - self._buffer_last_char = None - self._buffer_last_char_accentuated = False - self._is_current_word_bad = False - self._foreign_long_watch = False - self._bad_word_count = 0 - self._word_count = 0 - self._character_count = 0 - self._bad_character_count = 0 - self._foreign_long_count = 0 - self._buffer_accent_count = 0 - self._buffer_glyph_count = 0 - self._buffer_upper_count = 0 - - @property - def ratio(self) -> float: - if self._word_count <= 10 and self._foreign_long_count == 0: - return 0.0 - - return self._bad_character_count / self._character_count - - -@final -class CjkUncommonPlugin(MessDetectorPlugin): - """ - Detect messy CJK text that probably means nothing. - """ - - __slots__ = ("_character_count", "_uncommon_count") - - def __init__(self) -> None: - self._character_count: int = 0 - self._uncommon_count: int = 0 - - def feed_info(self, character: str, info: CharInfo) -> None: - """Optimized feed using pre-computed character info.""" - self._character_count += 1 - - if character not in COMMON_CJK_CHARACTERS: - self._uncommon_count += 1 - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._uncommon_count = 0 - - @property - def ratio(self) -> float: - if self._character_count < 8: - return 0.0 - - uncommon_form_usage: float = self._uncommon_count / self._character_count - - # we can be pretty sure it's garbage when uncommon characters are widely - # used. otherwise it could just be traditional chinese for example. - return uncommon_form_usage / 10 if uncommon_form_usage > 0.5 else 0.0 - - -@final -class ArchaicUpperLowerPlugin(MessDetectorPlugin): - __slots__ = ( - "_buf", - "_character_count_since_last_sep", - "_successive_upper_lower_count", - "_successive_upper_lower_count_final", - "_character_count", - "_last_alpha_seen", - "_last_alpha_seen_upper", - "_last_alpha_seen_lower", - "_current_ascii_only", - ) - - def __init__(self) -> None: - self._buf: bool = False - - self._character_count_since_last_sep: int = 0 - - self._successive_upper_lower_count: int = 0 - self._successive_upper_lower_count_final: int = 0 - - self._character_count: int = 0 - - self._last_alpha_seen: str | None = None - self._last_alpha_seen_upper: bool = False - self._last_alpha_seen_lower: bool = False - self._current_ascii_only: bool = True - - def feed_info(self, character: str, info: CharInfo) -> None: - """Optimized feed using pre-computed character info.""" - is_concerned: bool = info.alpha and info.case_variable - chunk_sep: bool = not is_concerned - - if chunk_sep and self._character_count_since_last_sep > 0: - if ( - self._character_count_since_last_sep <= 64 - and not info.digit - and not self._current_ascii_only - ): - self._successive_upper_lower_count_final += ( - self._successive_upper_lower_count - ) - - self._successive_upper_lower_count = 0 - self._character_count_since_last_sep = 0 - self._last_alpha_seen = None - self._buf = False - self._character_count += 1 - self._current_ascii_only = True - - return - - if self._current_ascii_only and not info.is_ascii: - self._current_ascii_only = False - - if self._last_alpha_seen is not None: - if (info.upper and self._last_alpha_seen_lower) or ( - info.lower and self._last_alpha_seen_upper - ): - if self._buf: - self._successive_upper_lower_count += 2 - self._buf = False - else: - self._buf = True - else: - self._buf = False - - self._character_count += 1 - self._character_count_since_last_sep += 1 - self._last_alpha_seen = character - self._last_alpha_seen_upper = info.upper - self._last_alpha_seen_lower = info.lower - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._character_count_since_last_sep = 0 - self._successive_upper_lower_count = 0 - self._successive_upper_lower_count_final = 0 - self._last_alpha_seen = None - self._last_alpha_seen_upper = False - self._last_alpha_seen_lower = False - self._buf = False - self._current_ascii_only = True - - @property - def ratio(self) -> float: - if self._character_count == 0: # Defensive: - return 0.0 - - return self._successive_upper_lower_count_final / self._character_count - - -@final -class ArabicIsolatedFormPlugin(MessDetectorPlugin): - __slots__ = ("_character_count", "_isolated_form_count") - - def __init__(self) -> None: - self._character_count: int = 0 - self._isolated_form_count: int = 0 - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._isolated_form_count = 0 - - def feed_info(self, character: str, info: CharInfo) -> None: - """Optimized feed using pre-computed character info.""" - self._character_count += 1 - - if info.flags & _ARABIC_ISOLATED_FORM: - self._isolated_form_count += 1 - - @property - def ratio(self) -> float: - if self._character_count < 8: - return 0.0 - - isolated_form_usage: float = self._isolated_form_count / self._character_count - - return isolated_form_usage - - -@lru_cache(maxsize=1024) -def is_suspiciously_successive_range( - unicode_range_a: str | None, unicode_range_b: str | None -) -> bool: - """ - Determine if two Unicode range seen next to each other can be considered as suspicious. - """ - if unicode_range_a is None or unicode_range_b is None: - return True - - if unicode_range_a == unicode_range_b: - return False - - if "Latin" in unicode_range_a and "Latin" in unicode_range_b: - return False - - if "Emoticons" in unicode_range_a or "Emoticons" in unicode_range_b: - return False - - # Latin characters can be accompanied with a combining diacritical mark - # eg. Vietnamese. - if ("Latin" in unicode_range_a or "Latin" in unicode_range_b) and ( - "Combining" in unicode_range_a or "Combining" in unicode_range_b - ): - return False - - keywords_range_a, keywords_range_b = ( - unicode_range_a.split(" "), - unicode_range_b.split(" "), - ) - - for el in keywords_range_a: - if el in UNICODE_SECONDARY_RANGE_KEYWORD: - continue - if el in keywords_range_b: - return False - - # Japanese Exception - range_a_jp_chars, range_b_jp_chars = ( - unicode_range_a - in ( - "Hiragana", - "Katakana", - ), - unicode_range_b in ("Hiragana", "Katakana"), - ) - if (range_a_jp_chars or range_b_jp_chars) and ( - "CJK" in unicode_range_a or "CJK" in unicode_range_b - ): - return False - if range_a_jp_chars and range_b_jp_chars: - return False - - if "Hangul" in unicode_range_a or "Hangul" in unicode_range_b: - if "CJK" in unicode_range_a or "CJK" in unicode_range_b: - return False - if unicode_range_a == "Basic Latin" or unicode_range_b == "Basic Latin": - return False - - # Chinese/Japanese use dedicated range for punctuation and/or separators. - if ("CJK" in unicode_range_a or "CJK" in unicode_range_b) or ( - unicode_range_a in ["Katakana", "Hiragana"] - and unicode_range_b in ["Katakana", "Hiragana"] - ): - if "Punctuation" in unicode_range_a or "Punctuation" in unicode_range_b: - return False - if "Forms" in unicode_range_a or "Forms" in unicode_range_b: - return False - if unicode_range_a == "Basic Latin" or unicode_range_b == "Basic Latin": - return False - - return True - - -@lru_cache(maxsize=2048) -def mess_ratio( - decoded_sequence: str, maximum_threshold: float = 0.2, debug: bool = False -) -> float: - """ - Compute a mess ratio given a decoded bytes sequence. The maximum threshold does stop the computation earlier. - """ - - seq_len: int = len(decoded_sequence) - - if seq_len < 511: - step: int = 32 - elif seq_len < 1024: - step = 64 - else: - step = 128 - - # Create each detector as a named local variable (unrolled from the generic loop). - # This eliminates per-character iteration over the detector list and - # per-character eligible() virtual dispatch, while keeping every plugin class - # intact and fully readable. - d_sp: TooManySymbolOrPunctuationPlugin = TooManySymbolOrPunctuationPlugin() - d_ta: TooManyAccentuatedPlugin = TooManyAccentuatedPlugin() - d_up: UnprintablePlugin = UnprintablePlugin() - d_sda: SuspiciousDuplicateAccentPlugin = SuspiciousDuplicateAccentPlugin() - d_sr: SuspiciousRange = SuspiciousRange() - d_sw: SuperWeirdWordPlugin = SuperWeirdWordPlugin() - d_cu: CjkUncommonPlugin = CjkUncommonPlugin() - d_au: ArchaicUpperLowerPlugin = ArchaicUpperLowerPlugin() - d_ai: ArabicIsolatedFormPlugin = ArabicIsolatedFormPlugin() - - # Local references for feed_info methods called in the hot loop. - d_sp_feed = d_sp.feed_info - d_ta_feed = d_ta.feed_info - d_up_feed = d_up.feed_info - d_sda_feed = d_sda.feed_info - d_sr_feed = d_sr.feed_info - d_sw_feed = d_sw.feed_info - d_cu_feed = d_cu.feed_info - d_au_feed = d_au.feed_info - d_ai_feed = d_ai.feed_info - - # Single reusable CharInfo object (avoids per-character allocation). - info: CharInfo = CharInfo() - info_update = info.update - - mean_mess_ratio: float - - for block_start in range(0, seq_len, step): - for character in decoded_sequence[block_start : block_start + step]: - # Pre-compute all character properties once (shared across all plugins). - info_update(character) - - # Detectors with eligible() == always True - d_up_feed(character, info) - d_sw_feed(character, info) - d_au_feed(character, info) - - # Detectors with eligible() == isprintable - if info.printable: - d_sp_feed(character, info) - d_sr_feed(character, info) - - # Detectors with eligible() == isalpha - if info.alpha: - d_ta_feed(character, info) - # SuspiciousDuplicateAccent: isalpha() and is_latin() - if info.latin: - d_sda_feed(character, info) - # CjkUncommon: is_cjk() - if info.is_cjk: - d_cu_feed(character, info) - # ArabicIsolatedForm: is_arabic() - if info.is_arabic: - d_ai_feed(character, info) - - mean_mess_ratio = ( - d_sp.ratio - + d_ta.ratio - + d_up.ratio - + d_sda.ratio - + d_sr.ratio - + d_sw.ratio - + d_cu.ratio - + d_au.ratio - + d_ai.ratio - ) - - if mean_mess_ratio >= maximum_threshold: - break - else: - # Flush last word buffer in SuperWeirdWordPlugin via trailing newline. - info_update("\n") - d_sw_feed("\n", info) - d_au_feed("\n", info) - d_up_feed("\n", info) - - mean_mess_ratio = ( - d_sp.ratio - + d_ta.ratio - + d_up.ratio - + d_sda.ratio - + d_sr.ratio - + d_sw.ratio - + d_cu.ratio - + d_au.ratio - + d_ai.ratio - ) - - if debug: # Defensive: - logger = getLogger("charset_normalizer") - - logger.log( - TRACE, - "Mess-detector extended-analysis start. " - f"intermediary_mean_mess_ratio_calc={step} mean_mess_ratio={mean_mess_ratio} " - f"maximum_threshold={maximum_threshold}", - ) - - if seq_len > 16: - logger.log(TRACE, f"Starting with: {decoded_sequence[:16]}") - logger.log(TRACE, f"Ending with: {decoded_sequence[-16::]}") - - for dt in [d_sp, d_ta, d_up, d_sda, d_sr, d_sw, d_cu, d_au, d_ai]: - logger.log(TRACE, f"{dt.__class__}: {dt.ratio}") - - return round(mean_mess_ratio, 3) diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/models.py b/notification-service/venv/Lib/site-packages/charset_normalizer/models.py deleted file mode 100644 index 382de15..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer/models.py +++ /dev/null @@ -1,369 +0,0 @@ -from __future__ import annotations - -from encodings.aliases import aliases -from json import dumps -from re import sub -from typing import Any, Iterator, List, Tuple - -from .constant import RE_POSSIBLE_ENCODING_INDICATION, TOO_BIG_SEQUENCE -from .utils import iana_name, is_multi_byte_encoding, unicode_range - - -class CharsetMatch: - def __init__( - self, - payload: bytes | bytearray, - guessed_encoding: str, - mean_mess_ratio: float, - has_sig_or_bom: bool, - languages: CoherenceMatches, - decoded_payload: str | None = None, - preemptive_declaration: str | None = None, - ): - self._payload: bytes | bytearray = payload - - self._encoding: str = guessed_encoding - self._mean_mess_ratio: float = mean_mess_ratio - self._languages: CoherenceMatches = languages - self._has_sig_or_bom: bool = has_sig_or_bom - self._unicode_ranges: list[str] | None = None - - self._leaves: list[CharsetMatch] = [] - self._mean_coherence_ratio: float = 0.0 - - self._output_payload: bytes | None = None - self._output_encoding: str | None = None - - self._string: str | None = decoded_payload - - self._preemptive_declaration: str | None = preemptive_declaration - - def __eq__(self, other: object) -> bool: - if not isinstance(other, CharsetMatch): - if isinstance(other, str): - return iana_name(other) == self.encoding - return False - return self.encoding == other.encoding and self.fingerprint == other.fingerprint - - def __lt__(self, other: object) -> bool: - """ - Implemented to make sorted available upon CharsetMatches items. - """ - if not isinstance(other, CharsetMatch): - raise ValueError - - chaos_difference: float = abs(self.chaos - other.chaos) - coherence_difference: float = abs(self.coherence - other.coherence) - - # Below 0.5% difference --> Use Coherence - if chaos_difference < 0.005 and coherence_difference > 0.02: - return self.coherence > other.coherence - elif chaos_difference < 0.005 and coherence_difference <= 0.02: - # When having a difficult decision, use the result that decoded as many multi-byte as possible. - # preserve RAM usage! - if len(self._payload) >= TOO_BIG_SEQUENCE: - return self.chaos < other.chaos - return self.multi_byte_usage > other.multi_byte_usage - - return self.chaos < other.chaos - - @property - def multi_byte_usage(self) -> float: - return 1.0 - (len(str(self)) / len(self.raw)) - - def __str__(self) -> str: - # Lazy Str Loading - if self._string is None: - self._string = str(self._payload, self._encoding, "strict") - # UTF-7 BOM is encoded in modified Base64 whose byte boundary - # can overlap with the next character, so raw-byte stripping - # is unreliable. Strip the decoded BOM character instead. - if ( - self._has_sig_or_bom - and self._encoding == "utf_7" - and self._string - and self._string[0] == "\ufeff" - ): - self._string = self._string[1:] - return self._string - - def __repr__(self) -> str: - return f"" - - def add_submatch(self, other: CharsetMatch) -> None: - if not isinstance(other, CharsetMatch) or other == self: - raise ValueError( - "Unable to add instance <{}> as a submatch of a CharsetMatch".format( - other.__class__ - ) - ) - - other._string = None # Unload RAM usage; dirty trick. - self._leaves.append(other) - - @property - def encoding(self) -> str: - return self._encoding - - @property - def encoding_aliases(self) -> list[str]: - """ - Encoding name are known by many name, using this could help when searching for IBM855 when it's listed as CP855. - """ - also_known_as: list[str] = [] - for u, p in aliases.items(): - if self.encoding == u: - also_known_as.append(p) - elif self.encoding == p: - also_known_as.append(u) - return also_known_as - - @property - def bom(self) -> bool: - return self._has_sig_or_bom - - @property - def byte_order_mark(self) -> bool: - return self._has_sig_or_bom - - @property - def languages(self) -> list[str]: - """ - Return the complete list of possible languages found in decoded sequence. - Usually not really useful. Returned list may be empty even if 'language' property return something != 'Unknown'. - """ - return [e[0] for e in self._languages] - - @property - def language(self) -> str: - """ - Most probable language found in decoded sequence. If none were detected or inferred, the property will return - "Unknown". - """ - if not self._languages: - # Trying to infer the language based on the given encoding - # Its either English or we should not pronounce ourselves in certain cases. - if "ascii" in self.could_be_from_charset: - return "English" - - # doing it there to avoid circular import - from charset_normalizer.cd import encoding_languages, mb_encoding_languages - - languages = ( - mb_encoding_languages(self.encoding) - if is_multi_byte_encoding(self.encoding) - else encoding_languages(self.encoding) - ) - - if len(languages) == 0 or "Latin Based" in languages: - return "Unknown" - - return languages[0] - - return self._languages[0][0] - - @property - def chaos(self) -> float: - return self._mean_mess_ratio - - @property - def coherence(self) -> float: - if not self._languages: - return 0.0 - return self._languages[0][1] - - @property - def percent_chaos(self) -> float: - return round(self.chaos * 100, ndigits=3) - - @property - def percent_coherence(self) -> float: - return round(self.coherence * 100, ndigits=3) - - @property - def raw(self) -> bytes | bytearray: - """ - Original untouched bytes. - """ - return self._payload - - @property - def submatch(self) -> list[CharsetMatch]: - return self._leaves - - @property - def has_submatch(self) -> bool: - return len(self._leaves) > 0 - - @property - def alphabets(self) -> list[str]: - if self._unicode_ranges is not None: - return self._unicode_ranges - # list detected ranges - detected_ranges: list[str | None] = [unicode_range(char) for char in str(self)] - # filter and sort - self._unicode_ranges = sorted(list({r for r in detected_ranges if r})) - return self._unicode_ranges - - @property - def could_be_from_charset(self) -> list[str]: - """ - The complete list of encoding that output the exact SAME str result and therefore could be the originating - encoding. - This list does include the encoding available in property 'encoding'. - """ - return [self._encoding] + [m.encoding for m in self._leaves] - - def output(self, encoding: str = "utf_8") -> bytes: - """ - Method to get re-encoded bytes payload using given target encoding. Default to UTF-8. - Any errors will be simply ignored by the encoder NOT replaced. - """ - if self._output_encoding is None or self._output_encoding != encoding: - self._output_encoding = encoding - decoded_string = str(self) - if ( - self._preemptive_declaration is not None - and self._preemptive_declaration.lower() - not in ["utf-8", "utf8", "utf_8"] - ): - patched_header = sub( - RE_POSSIBLE_ENCODING_INDICATION, - lambda m: m.string[m.span()[0] : m.span()[1]].replace( - m.groups()[0], - iana_name(self._output_encoding).replace("_", "-"), # type: ignore[arg-type] - ), - decoded_string[:8192], - count=1, - ) - - decoded_string = patched_header + decoded_string[8192:] - - self._output_payload = decoded_string.encode(encoding, "replace") - - return self._output_payload # type: ignore - - @property - def fingerprint(self) -> int: - """ - Retrieve a hash fingerprint of the decoded payload, used for deduplication. - """ - return hash(str(self)) - - -class CharsetMatches: - """ - Container with every CharsetMatch items ordered by default from most probable to the less one. - Act like a list(iterable) but does not implements all related methods. - """ - - def __init__(self, results: list[CharsetMatch] | None = None): - self._results: list[CharsetMatch] = sorted(results) if results else [] - - def __iter__(self) -> Iterator[CharsetMatch]: - yield from self._results - - def __getitem__(self, item: int | str) -> CharsetMatch: - """ - Retrieve a single item either by its position or encoding name (alias may be used here). - Raise KeyError upon invalid index or encoding not present in results. - """ - if isinstance(item, int): - return self._results[item] - if isinstance(item, str): - item = iana_name(item, False) - for result in self._results: - if item in result.could_be_from_charset: - return result - raise KeyError - - def __len__(self) -> int: - return len(self._results) - - def __bool__(self) -> bool: - return len(self._results) > 0 - - def append(self, item: CharsetMatch) -> None: - """ - Insert a single match. Will be inserted accordingly to preserve sort. - Can be inserted as a submatch. - """ - if not isinstance(item, CharsetMatch): - raise ValueError( - "Cannot append instance '{}' to CharsetMatches".format( - str(item.__class__) - ) - ) - # We should disable the submatch factoring when the input file is too heavy (conserve RAM usage) - if len(item.raw) < TOO_BIG_SEQUENCE: - for match in self._results: - if match.fingerprint == item.fingerprint and match.chaos == item.chaos: - match.add_submatch(item) - return - self._results.append(item) - self._results = sorted(self._results) - - def best(self) -> CharsetMatch | None: - """ - Simply return the first match. Strict equivalent to matches[0]. - """ - if not self._results: - return None - return self._results[0] - - def first(self) -> CharsetMatch | None: - """ - Redundant method, call the method best(). Kept for BC reasons. - """ - return self.best() - - -CoherenceMatch = Tuple[str, float] -CoherenceMatches = List[CoherenceMatch] - - -class CliDetectionResult: - def __init__( - self, - path: str, - encoding: str | None, - encoding_aliases: list[str], - alternative_encodings: list[str], - language: str, - alphabets: list[str], - has_sig_or_bom: bool, - chaos: float, - coherence: float, - unicode_path: str | None, - is_preferred: bool, - ): - self.path: str = path - self.unicode_path: str | None = unicode_path - self.encoding: str | None = encoding - self.encoding_aliases: list[str] = encoding_aliases - self.alternative_encodings: list[str] = alternative_encodings - self.language: str = language - self.alphabets: list[str] = alphabets - self.has_sig_or_bom: bool = has_sig_or_bom - self.chaos: float = chaos - self.coherence: float = coherence - self.is_preferred: bool = is_preferred - - @property - def __dict__(self) -> dict[str, Any]: # type: ignore - return { - "path": self.path, - "encoding": self.encoding, - "encoding_aliases": self.encoding_aliases, - "alternative_encodings": self.alternative_encodings, - "language": self.language, - "alphabets": self.alphabets, - "has_sig_or_bom": self.has_sig_or_bom, - "chaos": self.chaos, - "coherence": self.coherence, - "unicode_path": self.unicode_path, - "is_preferred": self.is_preferred, - } - - def to_json(self) -> str: - return dumps(self.__dict__, ensure_ascii=True, indent=4) diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/py.typed b/notification-service/venv/Lib/site-packages/charset_normalizer/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/utils.py b/notification-service/venv/Lib/site-packages/charset_normalizer/utils.py deleted file mode 100644 index 0f529b5..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer/utils.py +++ /dev/null @@ -1,422 +0,0 @@ -from __future__ import annotations - -import importlib -import logging -import unicodedata -from bisect import bisect_right -from codecs import IncrementalDecoder -from encodings.aliases import aliases -from functools import lru_cache -from re import findall -from typing import Generator - -from _multibytecodec import ( # type: ignore[import-not-found,import] - MultibyteIncrementalDecoder, -) - -from .constant import ( - ENCODING_MARKS, - IANA_SUPPORTED_SIMILAR, - RE_POSSIBLE_ENCODING_INDICATION, - UNICODE_RANGES_COMBINED, - UNICODE_SECONDARY_RANGE_KEYWORD, - UTF8_MAXIMAL_ALLOCATION, - COMMON_CJK_CHARACTERS, - _LATIN, - _CJK, - _HANGUL, - _KATAKANA, - _HIRAGANA, - _THAI, - _ARABIC, - _ARABIC_ISOLATED_FORM, - _ACCENT_KEYWORDS, - _ACCENTUATED, -) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def _character_flags(character: str) -> int: - """Compute all name-based classification flags with a single unicodedata.name() call.""" - try: - desc: str = unicodedata.name(character) - except ValueError: - return 0 - - flags: int = 0 - - if "LATIN" in desc: - flags |= _LATIN - if "CJK" in desc: - flags |= _CJK - if "HANGUL" in desc: - flags |= _HANGUL - if "KATAKANA" in desc: - flags |= _KATAKANA - if "HIRAGANA" in desc: - flags |= _HIRAGANA - if "THAI" in desc: - flags |= _THAI - if "ARABIC" in desc: - flags |= _ARABIC - if "ISOLATED FORM" in desc: - flags |= _ARABIC_ISOLATED_FORM - - for kw in _ACCENT_KEYWORDS: - if kw in desc: - flags |= _ACCENTUATED - break - - return flags - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_accentuated(character: str) -> bool: - return bool(_character_flags(character) & _ACCENTUATED) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def remove_accent(character: str) -> str: - decomposed: str = unicodedata.decomposition(character) - if not decomposed: - return character - - codes: list[str] = decomposed.split(" ") - - return chr(int(codes[0], 16)) - - -# Pre-built sorted lookup table for O(log n) binary search in unicode_range(). -# Each entry is (range_start, range_end_exclusive, range_name). -_UNICODE_RANGES_SORTED: list[tuple[int, int, str]] = sorted( - (ord_range.start, ord_range.stop, name) - for name, ord_range in UNICODE_RANGES_COMBINED.items() -) -_UNICODE_RANGE_STARTS: list[int] = [e[0] for e in _UNICODE_RANGES_SORTED] - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def unicode_range(character: str) -> str | None: - """ - Retrieve the Unicode range official name from a single character. - """ - character_ord: int = ord(character) - - # Binary search: find the rightmost range whose start <= character_ord - idx = bisect_right(_UNICODE_RANGE_STARTS, character_ord) - 1 - if idx >= 0: - start, stop, name = _UNICODE_RANGES_SORTED[idx] - if character_ord < stop: - return name - - return None - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_latin(character: str) -> bool: - return bool(_character_flags(character) & _LATIN) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_punctuation(character: str) -> bool: - character_category: str = unicodedata.category(character) - - if "P" in character_category: - return True - - character_range: str | None = unicode_range(character) - - if character_range is None: - return False - - return "Punctuation" in character_range - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_symbol(character: str) -> bool: - character_category: str = unicodedata.category(character) - - if "S" in character_category or "N" in character_category: - return True - - character_range: str | None = unicode_range(character) - - if character_range is None: - return False - - return "Forms" in character_range and character_category != "Lo" - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_emoticon(character: str) -> bool: - character_range: str | None = unicode_range(character) - - if character_range is None: - return False - - return "Emoticons" in character_range or "Pictographs" in character_range - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_separator(character: str) -> bool: - if character.isspace() or character in {"|", "+", "<", ">"}: - return True - - character_category: str = unicodedata.category(character) - - return "Z" in character_category or character_category in {"Po", "Pd", "Pc"} - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_case_variable(character: str) -> bool: - return character.islower() != character.isupper() - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_cjk(character: str) -> bool: - return bool(_character_flags(character) & _CJK) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_hiragana(character: str) -> bool: - return bool(_character_flags(character) & _HIRAGANA) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_katakana(character: str) -> bool: - return bool(_character_flags(character) & _KATAKANA) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_hangul(character: str) -> bool: - return bool(_character_flags(character) & _HANGUL) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_thai(character: str) -> bool: - return bool(_character_flags(character) & _THAI) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_arabic(character: str) -> bool: - return bool(_character_flags(character) & _ARABIC) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_arabic_isolated_form(character: str) -> bool: - return bool(_character_flags(character) & _ARABIC_ISOLATED_FORM) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_cjk_uncommon(character: str) -> bool: - return character not in COMMON_CJK_CHARACTERS - - -@lru_cache(maxsize=len(UNICODE_RANGES_COMBINED)) -def is_unicode_range_secondary(range_name: str) -> bool: - return any(keyword in range_name for keyword in UNICODE_SECONDARY_RANGE_KEYWORD) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_unprintable(character: str) -> bool: - return ( - character.isspace() is False # includes \n \t \r \v - and character.isprintable() is False - and character != "\x1a" # Why? Its the ASCII substitute character. - and character != "\ufeff" # bug discovered in Python, - # Zero Width No-Break Space located in Arabic Presentation Forms-B, Unicode 1.1 not acknowledged as space. - ) - - -def any_specified_encoding( - sequence: bytes | bytearray, search_zone: int = 8192 -) -> str | None: - """ - Extract using ASCII-only decoder any specified encoding in the first n-bytes. - """ - if not isinstance(sequence, (bytes, bytearray)): - raise TypeError - - seq_len: int = len(sequence) - - results: list[str] = findall( - RE_POSSIBLE_ENCODING_INDICATION, - sequence[: min(seq_len, search_zone)].decode("ascii", errors="ignore"), - ) - - if len(results) == 0: - return None - - for specified_encoding in results: - specified_encoding = specified_encoding.lower().replace("-", "_") - - encoding_alias: str - encoding_iana: str - - for encoding_alias, encoding_iana in aliases.items(): - if encoding_alias == specified_encoding: - return encoding_iana - if encoding_iana == specified_encoding: - return encoding_iana - - return None - - -@lru_cache(maxsize=128) -def is_multi_byte_encoding(name: str) -> bool: - """ - Verify is a specific encoding is a multi byte one based on it IANA name - """ - return name in { - "utf_8", - "utf_8_sig", - "utf_16", - "utf_16_be", - "utf_16_le", - "utf_32", - "utf_32_le", - "utf_32_be", - "utf_7", - } or issubclass( - importlib.import_module(f"encodings.{name}").IncrementalDecoder, - MultibyteIncrementalDecoder, - ) - - -def identify_sig_or_bom(sequence: bytes | bytearray) -> tuple[str | None, bytes]: - """ - Identify and extract SIG/BOM in given sequence. - """ - - for iana_encoding in ENCODING_MARKS: - marks: bytes | list[bytes] = ENCODING_MARKS[iana_encoding] - - if isinstance(marks, bytes): - marks = [marks] - - for mark in marks: - if sequence.startswith(mark): - return iana_encoding, mark - - return None, b"" - - -def should_strip_sig_or_bom(iana_encoding: str) -> bool: - return iana_encoding not in {"utf_16", "utf_32"} - - -def iana_name(cp_name: str, strict: bool = True) -> str: - """Returns the Python normalized encoding name (Not the IANA official name).""" - cp_name = cp_name.lower().replace("-", "_") - - encoding_alias: str - encoding_iana: str - - for encoding_alias, encoding_iana in aliases.items(): - if cp_name in [encoding_alias, encoding_iana]: - return encoding_iana - - if strict: - raise ValueError(f"Unable to retrieve IANA for '{cp_name}'") - - return cp_name - - -def cp_similarity(iana_name_a: str, iana_name_b: str) -> float: - if is_multi_byte_encoding(iana_name_a) or is_multi_byte_encoding(iana_name_b): - return 0.0 - - decoder_a = importlib.import_module(f"encodings.{iana_name_a}").IncrementalDecoder - decoder_b = importlib.import_module(f"encodings.{iana_name_b}").IncrementalDecoder - - id_a: IncrementalDecoder = decoder_a(errors="ignore") - id_b: IncrementalDecoder = decoder_b(errors="ignore") - - character_match_count: int = 0 - - for i in range(256): - to_be_decoded: bytes = bytes([i]) - if id_a.decode(to_be_decoded) == id_b.decode(to_be_decoded): - character_match_count += 1 - - return character_match_count / 256 - - -def is_cp_similar(iana_name_a: str, iana_name_b: str) -> bool: - """ - Determine if two code page are at least 80% similar. IANA_SUPPORTED_SIMILAR dict was generated using - the function cp_similarity. - """ - return ( - iana_name_a in IANA_SUPPORTED_SIMILAR - and iana_name_b in IANA_SUPPORTED_SIMILAR[iana_name_a] - ) - - -def set_logging_handler( - name: str = "charset_normalizer", - level: int = logging.INFO, - format_string: str = "%(asctime)s | %(levelname)s | %(message)s", -) -> None: - logger = logging.getLogger(name) - logger.setLevel(level) - - handler = logging.StreamHandler() - handler.setFormatter(logging.Formatter(format_string)) - logger.addHandler(handler) - - -def cut_sequence_chunks( - sequences: bytes | bytearray, - encoding_iana: str, - offsets: range, - chunk_size: int, - bom_or_sig_available: bool, - strip_sig_or_bom: bool, - sig_payload: bytes, - is_multi_byte_decoder: bool, - decoded_payload: str | None = None, -) -> Generator[str, None, None]: - if decoded_payload and is_multi_byte_decoder is False: - for i in offsets: - chunk = decoded_payload[i : i + chunk_size] - if not chunk: - break - yield chunk - else: - for i in offsets: - chunk_end = i + chunk_size - if chunk_end > len(sequences) + 8: - continue - - cut_sequence = sequences[i : i + chunk_size] - - if bom_or_sig_available and strip_sig_or_bom is False: - cut_sequence = sig_payload + cut_sequence - - chunk = cut_sequence.decode( - encoding_iana, - errors="ignore" if is_multi_byte_decoder else "strict", - ) - - # multi-byte bad cutting detector and adjustment - # not the cleanest way to perform that fix but clever enough for now. - if is_multi_byte_decoder and i > 0: - chunk_partial_size_chk: int = min(chunk_size, 16) - - if ( - decoded_payload - and chunk[:chunk_partial_size_chk] not in decoded_payload - ): - for j in range(i, i - 4, -1): - cut_sequence = sequences[j:chunk_end] - - if bom_or_sig_available and strip_sig_or_bom is False: - cut_sequence = sig_payload + cut_sequence - - chunk = cut_sequence.decode(encoding_iana, errors="ignore") - - if chunk[:chunk_partial_size_chk] in decoded_payload: - break - - yield chunk diff --git a/notification-service/venv/Lib/site-packages/charset_normalizer/version.py b/notification-service/venv/Lib/site-packages/charset_normalizer/version.py deleted file mode 100644 index a93d367..0000000 --- a/notification-service/venv/Lib/site-packages/charset_normalizer/version.py +++ /dev/null @@ -1,8 +0,0 @@ -""" -Expose version -""" - -from __future__ import annotations - -__version__ = "3.4.7" -VERSION = __version__.split(".") diff --git a/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/INSTALLER b/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/METADATA b/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/METADATA deleted file mode 100644 index 21d7a0c..0000000 --- a/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/METADATA +++ /dev/null @@ -1,84 +0,0 @@ -Metadata-Version: 2.4 -Name: click -Version: 8.4.1 -Summary: Composable command line interface toolkit -Maintainer-email: Pallets -Requires-Python: >=3.10 -Description-Content-Type: text/markdown -License-Expression: BSD-3-Clause -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Typing :: Typed -License-File: LICENSE.txt -Requires-Dist: colorama; platform_system == 'Windows' -Project-URL: Changes, https://click.palletsprojects.com/page/changes/ -Project-URL: Chat, https://discord.gg/pallets -Project-URL: Documentation, https://click.palletsprojects.com/ -Project-URL: Donate, https://palletsprojects.com/donate -Project-URL: Source, https://github.com/pallets/click/ - -
- -# Click - -Click is a Python package for creating beautiful command line interfaces -in a composable way with as little code as necessary. It's the "Command -Line Interface Creation Kit". It's highly configurable but comes with -sensible defaults out of the box. - -It aims to make the process of writing command line tools quick and fun -while also preventing any frustration caused by the inability to -implement an intended CLI API. - -Click in three points: - -- Arbitrary nesting of commands -- Automatic help page generation -- Supports lazy loading of subcommands at runtime - - -## A Simple Example - -```python -import click - -@click.command() -@click.option("--count", default=1, help="Number of greetings.") -@click.option("--name", prompt="Your name", help="The person to greet.") -def hello(count, name): - """Simple program that greets NAME for a total of COUNT times.""" - for _ in range(count): - click.echo(f"Hello, {name}!") - -if __name__ == '__main__': - hello() -``` - -``` -$ python hello.py --count=3 -Your name: Click -Hello, Click! -Hello, Click! -Hello, Click! -``` - - -## Donate - -The Pallets organization develops and supports Click and other popular -packages. In order to grow the community of contributors and users, and -allow the maintainers to devote more time to the projects, [please -donate today][]. - -[please donate today]: https://palletsprojects.com/donate - -## Contributing - -See our [detailed contributing documentation][contrib] for many ways to -contribute, including reporting issues, requesting features, asking or answering -questions, and making PRs. - -[contrib]: https://palletsprojects.com/contributing/ - diff --git a/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/RECORD b/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/RECORD deleted file mode 100644 index 3b06bd8..0000000 --- a/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/RECORD +++ /dev/null @@ -1,40 +0,0 @@ -click-8.4.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -click-8.4.1.dist-info/METADATA,sha256=uWALc7Y-Ixjj35al3B2qNsyXk-0tf578YgIsL1Vbn98,2621 -click-8.4.1.dist-info/RECORD,, -click-8.4.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 -click-8.4.1.dist-info/licenses/LICENSE.txt,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475 -click/__init__.py,sha256=FId2fXCSJB3yeWD-e2uON-mBhFa2Yc9MvXGmHu8OXG0,4634 -click/__pycache__/__init__.cpython-312.pyc,, -click/__pycache__/_compat.cpython-312.pyc,, -click/__pycache__/_termui_impl.cpython-312.pyc,, -click/__pycache__/_textwrap.cpython-312.pyc,, -click/__pycache__/_utils.cpython-312.pyc,, -click/__pycache__/_winconsole.cpython-312.pyc,, -click/__pycache__/core.cpython-312.pyc,, -click/__pycache__/decorators.cpython-312.pyc,, -click/__pycache__/exceptions.cpython-312.pyc,, -click/__pycache__/formatting.cpython-312.pyc,, -click/__pycache__/globals.cpython-312.pyc,, -click/__pycache__/parser.cpython-312.pyc,, -click/__pycache__/shell_completion.cpython-312.pyc,, -click/__pycache__/termui.cpython-312.pyc,, -click/__pycache__/testing.cpython-312.pyc,, -click/__pycache__/types.cpython-312.pyc,, -click/__pycache__/utils.cpython-312.pyc,, -click/_compat.py,sha256=XK1woqBSPRb1KNAwWwVsSMfEm8ZlfDwBCjceWzSGmEY,18910 -click/_termui_impl.py,sha256=VNyWY27pm0JUq12WK__pJNYxeUoDyfNwYEgE6vz_cnM,30411 -click/_textwrap.py,sha256=7Z0N7Vmn-66TNSTUwp6OXJbcUXRmYET9h9c2ucD8oQQ,6270 -click/_utils.py,sha256=eCZCtwJtsYD5QYkkNWJ8MY_8ABIjy8MczgMMyVY32rQ,996 -click/_winconsole.py,sha256=KSxfNbMlYRa6GOJuCLgsg2Pb3dVkgJNPqLJPae-Pa10,8543 -click/core.py,sha256=CQaJ0ALw4zyyVp6E7gP6a_G88eiuXE9mBzFnIJQ-igY,137917 -click/decorators.py,sha256=xgR8vZAClhWVkzitP22k6jETFRhKralh81zvA69Csd0,18467 -click/exceptions.py,sha256=FJitDd6MSZLj6CtKQWpkQzHnfsUw3UypxDU0t76bn0c,11294 -click/formatting.py,sha256=r6kGLpPyF0Cva6uSTwSZ_8ONRE7jp93I1C0JVRYQEqE,10370 -click/globals.py,sha256=gM-Nh6A4M0HB_SgkaF5M4ncGGMDHc_flHXu9_oh4GEU,1923 -click/parser.py,sha256=oJ-fU_3mvxugIuNtHaCATZ56lgEmHRggjJiSqEgYrjA,19052 -click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -click/shell_completion.py,sha256=QxeFb3RapNSP8ZwvK2BDVI2jrEKS1RbJaeuFMrHJAnU,21748 -click/termui.py,sha256=hflZ_tK7P4WUv_ef_RVVRL7n0nRPhTD0wN0pkHE7hDo,33000 -click/testing.py,sha256=0k_v5By_5ZO2McjBT7lTqQ57W8QJuW0_5Sx7d2ZLKec,25717 -click/types.py,sha256=UiVEx0yoQtrWO2wH22NgME4LfDxMNQi8j1qtJupYIpw,42783 -click/utils.py,sha256=YsTNrChEfwDXl39CTC_yWnQ-ZVkZxYjFESRCfEgClY4,20386 diff --git a/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/WHEEL b/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/WHEEL deleted file mode 100644 index d8b9936..0000000 --- a/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: flit 3.12.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/licenses/LICENSE.txt b/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/licenses/LICENSE.txt deleted file mode 100644 index d12a849..0000000 --- a/notification-service/venv/Lib/site-packages/click-8.4.1.dist-info/licenses/LICENSE.txt +++ /dev/null @@ -1,28 +0,0 @@ -Copyright 2014 Pallets - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/notification-service/venv/Lib/site-packages/click/__init__.py b/notification-service/venv/Lib/site-packages/click/__init__.py deleted file mode 100644 index 64be7e0..0000000 --- a/notification-service/venv/Lib/site-packages/click/__init__.py +++ /dev/null @@ -1,126 +0,0 @@ -""" -Click is a simple Python module inspired by the stdlib optparse to make -writing command line scripts fun. Unlike other modules, it's based -around a simple API that does not come with too much magic and is -composable. -""" - -from __future__ import annotations - -from .core import Argument as Argument -from .core import Command as Command -from .core import CommandCollection as CommandCollection -from .core import Context as Context -from .core import Group as Group -from .core import Option as Option -from .core import Parameter as Parameter -from .core import ParameterSource as ParameterSource -from .decorators import argument as argument -from .decorators import command as command -from .decorators import confirmation_option as confirmation_option -from .decorators import group as group -from .decorators import help_option as help_option -from .decorators import make_pass_decorator as make_pass_decorator -from .decorators import option as option -from .decorators import pass_context as pass_context -from .decorators import pass_obj as pass_obj -from .decorators import password_option as password_option -from .decorators import version_option as version_option -from .exceptions import Abort as Abort -from .exceptions import BadArgumentUsage as BadArgumentUsage -from .exceptions import BadOptionUsage as BadOptionUsage -from .exceptions import BadParameter as BadParameter -from .exceptions import ClickException as ClickException -from .exceptions import FileError as FileError -from .exceptions import MissingParameter as MissingParameter -from .exceptions import NoSuchCommand as NoSuchCommand -from .exceptions import NoSuchOption as NoSuchOption -from .exceptions import UsageError as UsageError -from .formatting import HelpFormatter as HelpFormatter -from .formatting import wrap_text as wrap_text -from .globals import get_current_context as get_current_context -from .termui import clear as clear -from .termui import confirm as confirm -from .termui import echo_via_pager as echo_via_pager -from .termui import edit as edit -from .termui import get_pager_file as get_pager_file -from .termui import getchar as getchar -from .termui import launch as launch -from .termui import pause as pause -from .termui import progressbar as progressbar -from .termui import prompt as prompt -from .termui import secho as secho -from .termui import style as style -from .termui import unstyle as unstyle -from .types import BOOL as BOOL -from .types import Choice as Choice -from .types import DateTime as DateTime -from .types import File as File -from .types import FLOAT as FLOAT -from .types import FloatRange as FloatRange -from .types import INT as INT -from .types import IntRange as IntRange -from .types import ParamType as ParamType -from .types import Path as Path -from .types import STRING as STRING -from .types import Tuple as Tuple -from .types import UNPROCESSED as UNPROCESSED -from .types import UUID as UUID -from .utils import echo as echo -from .utils import format_filename as format_filename -from .utils import get_app_dir as get_app_dir -from .utils import get_binary_stream as get_binary_stream -from .utils import get_text_stream as get_text_stream -from .utils import open_file as open_file - - -def __getattr__(name: str) -> object: - import warnings - - if name == "BaseCommand": - from .core import _BaseCommand - - warnings.warn( - "'BaseCommand' is deprecated and will be removed in Click 9.0. Use" - " 'Command' instead.", - DeprecationWarning, - stacklevel=2, - ) - return _BaseCommand - - if name == "MultiCommand": - from .core import _MultiCommand - - warnings.warn( - "'MultiCommand' is deprecated and will be removed in Click 9.0. Use" - " 'Group' instead.", - DeprecationWarning, - stacklevel=2, - ) - return _MultiCommand - - if name == "OptionParser": - from .parser import _OptionParser - - warnings.warn( - "'OptionParser' is deprecated and will be removed in Click 9.0. The" - " old parser is available in 'optparse'.", - DeprecationWarning, - stacklevel=2, - ) - return _OptionParser - - if name == "__version__": - import importlib.metadata - import warnings - - warnings.warn( - "The '__version__' attribute is deprecated and will be removed in" - " Click 9.1. Use feature detection or" - " 'importlib.metadata.version(\"click\")' instead.", - DeprecationWarning, - stacklevel=2, - ) - return importlib.metadata.version("click") - - raise AttributeError(name) diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 6de635f..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/_compat.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/_compat.cpython-312.pyc deleted file mode 100644 index abc2240..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/_compat.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/_termui_impl.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/_termui_impl.cpython-312.pyc deleted file mode 100644 index 46256e9..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/_termui_impl.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/_textwrap.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/_textwrap.cpython-312.pyc deleted file mode 100644 index cabc74c..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/_textwrap.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/_utils.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/_utils.cpython-312.pyc deleted file mode 100644 index 52479f6..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/_utils.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/_winconsole.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/_winconsole.cpython-312.pyc deleted file mode 100644 index 72e7bc8..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/_winconsole.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/core.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/core.cpython-312.pyc deleted file mode 100644 index df181b5..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/core.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/decorators.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/decorators.cpython-312.pyc deleted file mode 100644 index 04e3011..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/decorators.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/exceptions.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/exceptions.cpython-312.pyc deleted file mode 100644 index 36b578e..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/exceptions.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/formatting.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/formatting.cpython-312.pyc deleted file mode 100644 index e1630fd..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/formatting.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/globals.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/globals.cpython-312.pyc deleted file mode 100644 index 8eb2372..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/globals.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/parser.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/parser.cpython-312.pyc deleted file mode 100644 index 5cf346b..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/parser.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/shell_completion.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/shell_completion.cpython-312.pyc deleted file mode 100644 index de6bf20..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/shell_completion.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/termui.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/termui.cpython-312.pyc deleted file mode 100644 index 6e5b944..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/termui.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/testing.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/testing.cpython-312.pyc deleted file mode 100644 index def9274..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/testing.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/types.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/types.cpython-312.pyc deleted file mode 100644 index 9e9c580..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/types.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/__pycache__/utils.cpython-312.pyc b/notification-service/venv/Lib/site-packages/click/__pycache__/utils.cpython-312.pyc deleted file mode 100644 index 6bbe4bd..0000000 Binary files a/notification-service/venv/Lib/site-packages/click/__pycache__/utils.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/click/_compat.py b/notification-service/venv/Lib/site-packages/click/_compat.py deleted file mode 100644 index 36c0e53..0000000 --- a/notification-service/venv/Lib/site-packages/click/_compat.py +++ /dev/null @@ -1,627 +0,0 @@ -from __future__ import annotations - -import codecs -import collections.abc as cabc -import io -import os -import re -import sys -import typing as t -from types import TracebackType -from weakref import WeakKeyDictionary - -CYGWIN = sys.platform.startswith("cygwin") -WIN = sys.platform.startswith("win") -MAC = sys.platform == "darwin" -auto_wrap_for_ansi: t.Callable[[t.TextIO], t.TextIO] | None = None -_ansi_re = re.compile(r"\033\[[;?0-9]*[a-zA-Z]") - - -def _make_text_stream( - stream: t.BinaryIO, - encoding: str | None, - errors: str | None, - force_readable: bool = False, - force_writable: bool = False, -) -> t.TextIO: - if encoding is None: - encoding = get_best_encoding(stream) - if errors is None: - errors = "replace" - return _NonClosingTextIOWrapper( - stream, - encoding, - errors, - line_buffering=True, - force_readable=force_readable, - force_writable=force_writable, - ) - - -def is_ascii_encoding(encoding: str) -> bool: - """Checks if a given encoding is ascii.""" - try: - return codecs.lookup(encoding).name == "ascii" - except LookupError: - return False - - -def get_best_encoding(stream: t.IO[t.Any]) -> str: - """Returns the default stream encoding if not found.""" - rv = getattr(stream, "encoding", None) or sys.getdefaultencoding() - if is_ascii_encoding(rv): - return "utf-8" - return rv - - -class _NonClosingTextIOWrapper(io.TextIOWrapper): - def __init__( - self, - stream: t.BinaryIO, - encoding: str | None, - errors: str | None, - force_readable: bool = False, - force_writable: bool = False, - **extra: t.Any, - ) -> None: - self._stream = stream = t.cast( - t.BinaryIO, _FixupStream(stream, force_readable, force_writable) - ) - super().__init__(stream, encoding, errors, **extra) - - def __del__(self) -> None: - try: - self.detach() - except Exception: - pass - - def isatty(self) -> bool: - # https://bitbucket.org/pypy/pypy/issue/1803 - return self._stream.isatty() - - -class _FixupStream: - """The new io interface needs more from streams than streams - traditionally implement. As such, this fix-up code is necessary in - some circumstances. - - The forcing of readable and writable flags are there because some tools - put badly patched objects on sys (one such offender are certain version - of jupyter notebook). - """ - - def __init__( - self, - stream: t.BinaryIO, - force_readable: bool = False, - force_writable: bool = False, - ): - self._stream = stream - self._force_readable = force_readable - self._force_writable = force_writable - - def __getattr__(self, name: str) -> t.Any: - return getattr(self._stream, name) - - def read1(self, size: int) -> bytes: - f = getattr(self._stream, "read1", None) - - if f is not None: - return t.cast(bytes, f(size)) - - return self._stream.read(size) - - def readable(self) -> bool: - if self._force_readable: - return True - x = getattr(self._stream, "readable", None) - if x is not None: - return t.cast(bool, x()) - try: - self._stream.read(0) - except Exception: - return False - return True - - def writable(self) -> bool: - if self._force_writable: - return True - x = getattr(self._stream, "writable", None) - if x is not None: - return t.cast(bool, x()) - try: - self._stream.write(b"") - except Exception: - try: - self._stream.write(b"") - except Exception: - return False - return True - - def seekable(self) -> bool: - x = getattr(self._stream, "seekable", None) - if x is not None: - return t.cast(bool, x()) - try: - self._stream.seek(self._stream.tell()) - except Exception: - return False - return True - - -def _is_binary_reader(stream: t.IO[t.Any], default: bool = False) -> bool: - try: - return isinstance(stream.read(0), bytes) - except Exception: - return default - # This happens in some cases where the stream was already - # closed. In this case, we assume the default. - - -def _is_binary_writer(stream: t.IO[t.Any], default: bool = False) -> bool: - try: - stream.write(b"") - except Exception: - try: - stream.write("") - return False - except Exception: - pass - return default - return True - - -def _find_binary_reader(stream: t.IO[t.Any]) -> t.BinaryIO | None: - # We need to figure out if the given stream is already binary. - # This can happen because the official docs recommend detaching - # the streams to get binary streams. Some code might do this, so - # we need to deal with this case explicitly. - if _is_binary_reader(stream, False): - return t.cast(t.BinaryIO, stream) - - buf = getattr(stream, "buffer", None) - - # Same situation here; this time we assume that the buffer is - # actually binary in case it's closed. - if buf is not None and _is_binary_reader(buf, True): - return t.cast(t.BinaryIO, buf) - - return None - - -def _find_binary_writer(stream: t.IO[t.Any]) -> t.BinaryIO | None: - # We need to figure out if the given stream is already binary. - # This can happen because the official docs recommend detaching - # the streams to get binary streams. Some code might do this, so - # we need to deal with this case explicitly. - if _is_binary_writer(stream, False): - return t.cast(t.BinaryIO, stream) - - buf = getattr(stream, "buffer", None) - - # Same situation here; this time we assume that the buffer is - # actually binary in case it's closed. - if buf is not None and _is_binary_writer(buf, True): - return t.cast(t.BinaryIO, buf) - - return None - - -def _stream_is_misconfigured(stream: t.TextIO) -> bool: - """A stream is misconfigured if its encoding is ASCII.""" - # If the stream does not have an encoding set, we assume it's set - # to ASCII. This appears to happen in certain unittest - # environments. It's not quite clear what the correct behavior is - # but this at least will force Click to recover somehow. - return is_ascii_encoding(getattr(stream, "encoding", None) or "ascii") - - -def _is_compat_stream_attr(stream: t.TextIO, attr: str, value: str | None) -> bool: - """A stream attribute is compatible if it is equal to the - desired value or the desired value is unset and the attribute - has a value. - """ - stream_value = getattr(stream, attr, None) - return stream_value == value or (value is None and stream_value is not None) - - -def _is_compatible_text_stream( - stream: t.TextIO, encoding: str | None, errors: str | None -) -> bool: - """Check if a stream's encoding and errors attributes are - compatible with the desired values. - """ - return _is_compat_stream_attr( - stream, "encoding", encoding - ) and _is_compat_stream_attr(stream, "errors", errors) - - -def _force_correct_text_stream( - text_stream: t.IO[t.Any], - encoding: str | None, - errors: str | None, - is_binary: t.Callable[[t.IO[t.Any], bool], bool], - find_binary: t.Callable[[t.IO[t.Any]], t.BinaryIO | None], - force_readable: bool = False, - force_writable: bool = False, -) -> t.TextIO: - if is_binary(text_stream, False): - binary_reader = t.cast(t.BinaryIO, text_stream) - else: - text_stream = t.cast(t.TextIO, text_stream) - # If the stream looks compatible, and won't default to a - # misconfigured ascii encoding, return it as-is. - if _is_compatible_text_stream(text_stream, encoding, errors) and not ( - encoding is None and _stream_is_misconfigured(text_stream) - ): - return text_stream - - # Otherwise, get the underlying binary reader. - possible_binary_reader = find_binary(text_stream) - - # If that's not possible, silently use the original reader - # and get mojibake instead of exceptions. - if possible_binary_reader is None: - return text_stream - - binary_reader = possible_binary_reader - - # Default errors to replace instead of strict in order to get - # something that works. - if errors is None: - errors = "replace" - - # Wrap the binary stream in a text stream with the correct - # encoding parameters. - return _make_text_stream( - binary_reader, - encoding, - errors, - force_readable=force_readable, - force_writable=force_writable, - ) - - -def _force_correct_text_reader( - text_reader: t.IO[t.Any], - encoding: str | None, - errors: str | None, - force_readable: bool = False, -) -> t.TextIO: - return _force_correct_text_stream( - text_reader, - encoding, - errors, - _is_binary_reader, - _find_binary_reader, - force_readable=force_readable, - ) - - -def _force_correct_text_writer( - text_writer: t.IO[t.Any], - encoding: str | None, - errors: str | None, - force_writable: bool = False, -) -> t.TextIO: - return _force_correct_text_stream( - text_writer, - encoding, - errors, - _is_binary_writer, - _find_binary_writer, - force_writable=force_writable, - ) - - -def get_binary_stdin() -> t.BinaryIO: - reader = _find_binary_reader(sys.stdin) - if reader is None: - raise RuntimeError("Was not able to determine binary stream for sys.stdin.") - return reader - - -def get_binary_stdout() -> t.BinaryIO: - writer = _find_binary_writer(sys.stdout) - if writer is None: - raise RuntimeError("Was not able to determine binary stream for sys.stdout.") - return writer - - -def get_binary_stderr() -> t.BinaryIO: - writer = _find_binary_writer(sys.stderr) - if writer is None: - raise RuntimeError("Was not able to determine binary stream for sys.stderr.") - return writer - - -def get_text_stdin(encoding: str | None = None, errors: str | None = None) -> t.TextIO: - rv = _get_windows_console_stream(sys.stdin, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_reader(sys.stdin, encoding, errors, force_readable=True) - - -def get_text_stdout(encoding: str | None = None, errors: str | None = None) -> t.TextIO: - rv = _get_windows_console_stream(sys.stdout, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_writer(sys.stdout, encoding, errors, force_writable=True) - - -def get_text_stderr(encoding: str | None = None, errors: str | None = None) -> t.TextIO: - rv = _get_windows_console_stream(sys.stderr, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_writer(sys.stderr, encoding, errors, force_writable=True) - - -def _wrap_io_open( - file: str | os.PathLike[str] | int, - mode: str, - encoding: str | None, - errors: str | None, -) -> t.IO[t.Any]: - """Handles not passing ``encoding`` and ``errors`` in binary mode.""" - if "b" in mode: - return open(file, mode) - - return open(file, mode, encoding=encoding, errors=errors) - - -def open_stream( - filename: str | os.PathLike[str], - mode: str = "r", - encoding: str | None = None, - errors: str | None = "strict", - atomic: bool = False, -) -> tuple[t.IO[t.Any], bool]: - binary = "b" in mode - filename = os.fspath(filename) - - # Standard streams first. These are simple because they ignore the - # atomic flag. Use fsdecode to handle Path("-"). - if os.fsdecode(filename) == "-": - if any(m in mode for m in ["w", "a", "x"]): - if binary: - return get_binary_stdout(), False - return get_text_stdout(encoding=encoding, errors=errors), False - if binary: - return get_binary_stdin(), False - return get_text_stdin(encoding=encoding, errors=errors), False - - # Non-atomic writes directly go out through the regular open functions. - if not atomic: - return _wrap_io_open(filename, mode, encoding, errors), True - - # Some usability stuff for atomic writes - if "a" in mode: - raise ValueError( - "Appending to an existing file is not supported, because that" - " would involve an expensive `copy`-operation to a temporary" - " file. Open the file in normal `w`-mode and copy explicitly" - " if that's what you're after." - ) - if "x" in mode: - raise ValueError("Use the `overwrite`-parameter instead.") - if "w" not in mode: - raise ValueError("Atomic writes only make sense with `w`-mode.") - - # Atomic writes are more complicated. They work by opening a file - # as a proxy in the same folder and then using the fdopen - # functionality to wrap it in a Python file. Then we wrap it in an - # atomic file that moves the file over on close. - import errno - import random - - try: - perm: int | None = os.stat(filename).st_mode - except OSError: - perm = None - - flags = os.O_RDWR | os.O_CREAT | os.O_EXCL - - if binary: - flags |= getattr(os, "O_BINARY", 0) - - while True: - tmp_filename = os.path.join( - os.path.dirname(filename), - f".__atomic-write{random.randrange(1 << 32):08x}", - ) - try: - fd = os.open(tmp_filename, flags, 0o666 if perm is None else perm) - break - except OSError as e: - if e.errno == errno.EEXIST or ( - os.name == "nt" - and e.errno == errno.EACCES - and os.path.isdir(e.filename) - and os.access(e.filename, os.W_OK) - ): - continue - raise - - if perm is not None: - os.chmod(tmp_filename, perm) # in case perm includes bits in umask - - f = _wrap_io_open(fd, mode, encoding, errors) - af = _AtomicFile(f, tmp_filename, os.path.realpath(filename)) - return t.cast(t.IO[t.Any], af), True - - -class _AtomicFile: - def __init__(self, f: t.IO[t.Any], tmp_filename: str, real_filename: str) -> None: - self._f = f - self._tmp_filename = tmp_filename - self._real_filename = real_filename - self.closed = False - - @property - def name(self) -> str: - return self._real_filename - - def close(self, delete: bool = False) -> None: - if self.closed: - return - self._f.close() - os.replace(self._tmp_filename, self._real_filename) - self.closed = True - - def __getattr__(self, name: str) -> t.Any: - return getattr(self._f, name) - - def __enter__(self) -> _AtomicFile: - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_value: BaseException | None, - tb: TracebackType | None, - ) -> None: - self.close(delete=exc_type is not None) - - def __repr__(self) -> str: - return repr(self._f) - - -def strip_ansi(value: str) -> str: - return _ansi_re.sub("", value) - - -def _is_jupyter_kernel_output(stream: t.IO[t.Any]) -> bool: - while isinstance(stream, (_FixupStream, _NonClosingTextIOWrapper)): - stream = stream._stream - - return stream.__class__.__module__.startswith("ipykernel.") - - -def should_strip_ansi( - stream: t.IO[t.Any] | None = None, color: bool | None = None -) -> bool: - if color is None: - if stream is None: - stream = sys.stdin - elif hasattr(stream, "color"): - # ._termui_impl.MaybeStripAnsi handles stripping ansi itself, - # so we don't need to strip it here - return False - return not isatty(stream) and not _is_jupyter_kernel_output(stream) - return not color - - -# On Windows, wrap the output streams with colorama to support ANSI -# color codes. -# NOTE: double check is needed so mypy does not analyze this on Linux -if sys.platform.startswith("win") and WIN: - from ._winconsole import _get_windows_console_stream - - def _get_argv_encoding() -> str: - import locale - - return locale.getpreferredencoding() - - _ansi_stream_wrappers: cabc.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() - - def auto_wrap_for_ansi(stream: t.TextIO, color: bool | None = None) -> t.TextIO: - """Support ANSI color and style codes on Windows by wrapping a - stream with colorama. - """ - try: - cached = _ansi_stream_wrappers.get(stream) - except Exception: - cached = None - - if cached is not None: - return cached - - import colorama - - strip = should_strip_ansi(stream, color) - ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip) - rv = t.cast(t.TextIO, ansi_wrapper.stream) - _write = rv.write - - def _safe_write(s: str) -> int: - try: - return _write(s) - except BaseException: - ansi_wrapper.reset_all() - raise - - rv.write = _safe_write # type: ignore[method-assign] - - try: - _ansi_stream_wrappers[stream] = rv - except Exception: - pass - - return rv - -else: - - def _get_argv_encoding() -> str: - return getattr(sys.stdin, "encoding", None) or sys.getfilesystemencoding() - - def _get_windows_console_stream( - f: t.TextIO, encoding: str | None, errors: str | None - ) -> t.TextIO | None: - return None - - -def term_len(x: str) -> int: - return len(strip_ansi(x)) - - -def isatty(stream: t.IO[t.Any]) -> bool: - try: - return stream.isatty() - except Exception: - return False - - -def _make_cached_stream_func( - src_func: t.Callable[[], t.TextIO | None], - wrapper_func: t.Callable[[], t.TextIO], -) -> t.Callable[[], t.TextIO | None]: - cache: cabc.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() - - def func() -> t.TextIO | None: - stream = src_func() - - if stream is None: - return None - - try: - rv = cache.get(stream) - except Exception: - rv = None - if rv is not None: - return rv - rv = wrapper_func() - try: - cache[stream] = rv - except Exception: - pass - return rv - - return func - - -_default_text_stdin = _make_cached_stream_func(lambda: sys.stdin, get_text_stdin) -_default_text_stdout = _make_cached_stream_func(lambda: sys.stdout, get_text_stdout) -_default_text_stderr = _make_cached_stream_func(lambda: sys.stderr, get_text_stderr) - - -binary_streams: cabc.Mapping[str, t.Callable[[], t.BinaryIO]] = { - "stdin": get_binary_stdin, - "stdout": get_binary_stdout, - "stderr": get_binary_stderr, -} - -text_streams: cabc.Mapping[str, t.Callable[[str | None, str | None], t.TextIO]] = { - "stdin": get_text_stdin, - "stdout": get_text_stdout, - "stderr": get_text_stderr, -} diff --git a/notification-service/venv/Lib/site-packages/click/_termui_impl.py b/notification-service/venv/Lib/site-packages/click/_termui_impl.py deleted file mode 100644 index 76113e9..0000000 --- a/notification-service/venv/Lib/site-packages/click/_termui_impl.py +++ /dev/null @@ -1,929 +0,0 @@ -""" -This module contains implementations for the termui module. To keep the -import time of Click down, some infrequently used functionality is -placed in this module and only imported as needed. -""" - -from __future__ import annotations - -import collections.abc as cabc -import contextlib -import io -import math -import os -import shlex -import sys -import time -import typing as t -from gettext import gettext as _ -from io import StringIO -from pathlib import Path -from types import TracebackType - -from ._compat import _default_text_stdout -from ._compat import CYGWIN -from ._compat import get_best_encoding -from ._compat import isatty -from ._compat import strip_ansi -from ._compat import term_len -from ._compat import WIN -from .exceptions import ClickException -from .utils import echo - -V = t.TypeVar("V") - - -class _BufferedTextPagerStream(t.Protocol): - buffer: t.BinaryIO - - -def _has_binary_buffer( - stream: t.BinaryIO | t.TextIO, -) -> t.TypeGuard[_BufferedTextPagerStream]: - # TextIO is wider than TextIOWrapper; text-only streams such as StringIO - # are valid TextIO values but do not expose a binary buffer to wrap. - return getattr(stream, "buffer", None) is not None - - -if os.name == "nt": - BEFORE_BAR = "\r" - AFTER_BAR = "\n" -else: - BEFORE_BAR = "\r\033[?25l" - AFTER_BAR = "\033[?25h\n" - - -class ProgressBar(t.Generic[V]): - def __init__( - self, - iterable: cabc.Iterable[V] | None, - length: int | None = None, - fill_char: str = "#", - empty_char: str = " ", - bar_template: str = "%(bar)s", - info_sep: str = " ", - hidden: bool = False, - show_eta: bool = True, - show_percent: bool | None = None, - show_pos: bool = False, - item_show_func: t.Callable[[V | None], str | None] | None = None, - label: str | None = None, - file: t.TextIO | None = None, - color: bool | None = None, - update_min_steps: int = 1, - width: int = 30, - ) -> None: - self.fill_char = fill_char - self.empty_char = empty_char - self.bar_template = bar_template - self.info_sep = info_sep - self.hidden = hidden - self.show_eta = show_eta - self.show_percent = show_percent - self.show_pos = show_pos - self.item_show_func = item_show_func - self.label: str = label or "" - - if file is None: - file = _default_text_stdout() - - # There are no standard streams attached to write to. For example, - # pythonw on Windows. - if file is None: - file = StringIO() - - self.file = file - self.color = color - self.update_min_steps = update_min_steps - self._completed_intervals = 0 - self.width: int = width - self.autowidth: bool = width == 0 - - if length is None: - from operator import length_hint - - length = length_hint(iterable, -1) - - if length == -1: - length = None - if iterable is None: - if length is None: - raise TypeError("iterable or length is required") - iterable = t.cast("cabc.Iterable[V]", range(length)) - self.iter: cabc.Iterable[V] = iter(iterable) - self.length = length - self.pos: int = 0 - self.avg: list[float] = [] - self.last_eta: float - self.start: float - self.start = self.last_eta = time.time() - self.eta_known: bool = False - self.finished: bool = False - self.max_width: int | None = None - self.entered: bool = False - self.current_item: V | None = None - self._is_atty = isatty(self.file) - self._last_line: str | None = None - - def __enter__(self) -> ProgressBar[V]: - self.entered = True - self.render_progress() - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_value: BaseException | None, - tb: TracebackType | None, - ) -> None: - self.render_finish() - - def __iter__(self) -> cabc.Iterator[V]: - if not self.entered: - raise RuntimeError("You need to use progress bars in a with block.") - self.render_progress() - return self.generator() - - def __next__(self) -> V: - # Iteration is defined in terms of a generator function, - # returned by iter(self); use that to define next(). This works - # because `self.iter` is an iterable consumed by that generator, - # so it is re-entry safe. Calling `next(self.generator())` - # twice works and does "what you want". - return next(iter(self)) - - def render_finish(self) -> None: - if self.hidden or not self._is_atty: - return - self.file.write(AFTER_BAR) - self.file.flush() - - @property - def pct(self) -> float: - if self.finished: - return 1.0 - return min(self.pos / (float(self.length or 1) or 1), 1.0) - - @property - def time_per_iteration(self) -> float: - if not self.avg: - return 0.0 - return sum(self.avg) / float(len(self.avg)) - - @property - def eta(self) -> float: - if self.length is not None and not self.finished: - return self.time_per_iteration * (self.length - self.pos) - return 0.0 - - def format_eta(self) -> str: - if self.eta_known: - t = int(self.eta) - seconds = t % 60 - t //= 60 - minutes = t % 60 - t //= 60 - hours = t % 24 - t //= 24 - if t > 0: - return "{d}{day_label} {h:02}:{m:02}:{s:02}".format( - d=t, - day_label=_("d"), - h=hours, - m=minutes, - s=seconds, - ) - else: - return f"{hours:02}:{minutes:02}:{seconds:02}" - return "" - - def format_pos(self) -> str: - pos = str(self.pos) - if self.length is not None: - pos += f"/{self.length}" - return pos - - def format_pct(self) -> str: - return f"{int(self.pct * 100): 4}%"[1:] - - def format_bar(self) -> str: - if self.length is not None: - bar_length = int(self.pct * self.width) - bar = self.fill_char * bar_length - bar += self.empty_char * (self.width - bar_length) - elif self.finished: - bar = self.fill_char * self.width - else: - chars = list(self.empty_char * (self.width or 1)) - if self.time_per_iteration != 0: - chars[ - int( - (math.cos(self.pos * self.time_per_iteration) / 2.0 + 0.5) - * self.width - ) - ] = self.fill_char - bar = "".join(chars) - return bar - - def format_progress_line(self) -> str: - show_percent = self.show_percent - - info_bits = [] - if self.length is not None and show_percent is None: - show_percent = not self.show_pos - - if self.show_pos: - info_bits.append(self.format_pos()) - if show_percent: - info_bits.append(self.format_pct()) - if self.show_eta and self.eta_known and not self.finished: - info_bits.append(self.format_eta()) - if self.item_show_func is not None: - item_info = self.item_show_func(self.current_item) - if item_info is not None: - info_bits.append(item_info) - - return ( - self.bar_template - % { - "label": self.label, - "bar": self.format_bar(), - "info": self.info_sep.join(info_bits), - } - ).rstrip() - - def render_progress(self) -> None: - if self.hidden: - return - - if not self._is_atty: - # Only output the label once if the output is not a TTY. - if self._last_line != self.label: - self._last_line = self.label - echo(self.label, file=self.file, color=self.color) - return - - buf = [] - # Update width in case the terminal has been resized - if self.autowidth: - import shutil - - old_width = self.width - self.width = 0 - clutter_length = term_len(self.format_progress_line()) - new_width = max(0, shutil.get_terminal_size().columns - clutter_length) - if new_width < old_width and self.max_width is not None: - buf.append(BEFORE_BAR) - buf.append(" " * self.max_width) - self.max_width = new_width - self.width = new_width - - clear_width = self.width - if self.max_width is not None: - clear_width = self.max_width - - buf.append(BEFORE_BAR) - line = self.format_progress_line() - line_len = term_len(line) - if self.max_width is None or self.max_width < line_len: - self.max_width = line_len - - buf.append(line) - buf.append(" " * (clear_width - line_len)) - line = "".join(buf) - # Render the line only if it changed. - - if line != self._last_line: - self._last_line = line - echo(line, file=self.file, color=self.color, nl=False) - self.file.flush() - - def make_step(self, n_steps: int) -> None: - self.pos += n_steps - if self.length is not None and self.pos >= self.length: - self.finished = True - - if (time.time() - self.last_eta) < 1.0: - return - - self.last_eta = time.time() - - # self.avg is a rolling list of length <= 7 of steps where steps are - # defined as time elapsed divided by the total progress through - # self.length. - if self.pos: - step = (time.time() - self.start) / self.pos - else: - step = time.time() - self.start - - self.avg = self.avg[-6:] + [step] - - self.eta_known = self.length is not None - - def update(self, n_steps: int, current_item: V | None = None) -> None: - """Update the progress bar by advancing a specified number of - steps, and optionally set the ``current_item`` for this new - position. - - :param n_steps: Number of steps to advance. - :param current_item: Optional item to set as ``current_item`` - for the updated position. - - .. versionchanged:: 8.0 - Added the ``current_item`` optional parameter. - - .. versionchanged:: 8.0 - Only render when the number of steps meets the - ``update_min_steps`` threshold. - """ - if current_item is not None: - self.current_item = current_item - - self._completed_intervals += n_steps - - if self._completed_intervals >= self.update_min_steps: - self.make_step(self._completed_intervals) - self.render_progress() - self._completed_intervals = 0 - - def finish(self) -> None: - self.eta_known = False - self.current_item = None - self.finished = True - - def generator(self) -> cabc.Iterator[V]: - """Return a generator which yields the items added to the bar - during construction, and updates the progress bar *after* the - yielded block returns. - """ - # WARNING: the iterator interface for `ProgressBar` relies on - # this and only works because this is a simple generator which - # doesn't create or manage additional state. If this function - # changes, the impact should be evaluated both against - # `iter(bar)` and `next(bar)`. `next()` in particular may call - # `self.generator()` repeatedly, and this must remain safe in - # order for that interface to work. - if not self.entered: - raise RuntimeError("You need to use progress bars in a with block.") - - if not self._is_atty: - yield from self.iter - else: - for rv in self.iter: - self.current_item = rv - - # This allows show_item_func to be updated before the - # item is processed. Only trigger at the beginning of - # the update interval. - if self._completed_intervals == 0: - self.render_progress() - - yield rv - self.update(1) - - self.finish() - self.render_progress() - - -class MaybeStripAnsi(io.TextIOWrapper): - def __init__(self, stream: t.IO[bytes], *, color: bool, **kwargs: t.Any): - super().__init__(stream, **kwargs) - self.color = color - - def write(self, text: str) -> int: - if not self.color: - text = strip_ansi(text) - return super().write(text) - - -def _pager_contextmanager( - color: bool | None = None, -) -> t.ContextManager[tuple[t.BinaryIO | t.TextIO, str, bool]]: - """Decide what method to use for paging through text.""" - stdout = _default_text_stdout() - - # There are no standard streams attached to write to. For example, - # pythonw on Windows. - if stdout is None: - stdout = StringIO() - - if not isatty(sys.stdin) or not isatty(stdout): - return _nullpager(stdout, color) - - # Split using POSIX mode (the default) so that quote characters are - # stripped from tokens and quoted Windows paths are preserved. - # Non-POSIX mode retains quotes in tokens, and wrapping tokens - # with shlex.quote re-introduces quoting issues on Windows. - pager_cmd_parts = shlex.split(os.environ.get("PAGER", "")) - if pager_cmd_parts: - if WIN: - return _tempfilepager(pager_cmd_parts, color) - return _pipepager(pager_cmd_parts, color) - - if os.environ.get("TERM") in ("dumb", "emacs"): - return _nullpager(stdout, color) - if WIN or sys.platform.startswith("os2"): - return _tempfilepager(["more"], color) - return _pipepager(["less"], color) - - -@contextlib.contextmanager -def get_pager_file(color: bool | None = None) -> t.Generator[t.TextIO, None, None]: - """Context manager. - Yields a writable file-like object which can be used as an output pager. - .. versionadded:: 8.4 - :param color: controls if the pager supports ANSI colors or not. The - default is autodetection. - """ - with _pager_contextmanager(color=color) as (stream, encoding, color): - # Split streams by capabilities rather than the abstract TextIO / - # BinaryIO annotations: buffered text streams can be unwrapped to bytes, - # while text-only streams are yielded as-is. - if _has_binary_buffer(stream): - # Text stream backed by a binary buffer. - stream = MaybeStripAnsi(stream.buffer, color=color, encoding=encoding) - elif isinstance(stream, t.BinaryIO): - # Binary stream - stream = MaybeStripAnsi(stream, color=color, encoding=encoding) - try: - yield stream - finally: - stream.flush() - - -@contextlib.contextmanager -def _pipepager( - cmd_parts: list[str], color: bool | None = None -) -> t.Iterator[tuple[t.BinaryIO | t.TextIO, str, bool]]: - """Page through text by feeding it to another program. - - Invokes the pager via :class:`subprocess.Popen` with an ``argv`` list - produced by :func:`shlex.split`. The command is resolved to an absolute - path with :func:`shutil.which` as recommended by the - :mod:`subprocess` docs for Windows compatibility. - - Invoking a pager through this might support colors: if piping to - ``less`` and the user hasn't decided on colors, ``LESS=-R`` is set - automatically. - """ - # Split the command into the invoked CLI and its parameters. - if not cmd_parts: - stdout = _default_text_stdout() or StringIO() - yield stdout, "utf-8", False - return - - import shutil - - cmd = cmd_parts[0] - cmd_params = cmd_parts[1:] - - cmd_filepath = shutil.which(cmd) - if not cmd_filepath: - stdout = _default_text_stdout() or StringIO() - yield stdout, "utf-8", False - return - - # Produces a normalized absolute path string. - # multi-call binaries such as busybox derive their identity from the symlink - # less -> busybox. resolve() causes them to misbehave. (eg. less becomes busybox) - cmd_path = Path(cmd_filepath).absolute() - cmd_name = cmd_path.name - - import subprocess - - # Make a local copy of the environment to not affect the global one. - env = dict(os.environ) - - # If we're piping to less and the user hasn't decided on colors, we enable - # them by default we find the -R flag in the command line arguments. - if color is None and cmd_name == "less": - less_flags = f"{os.environ.get('LESS', '')}{' '.join(cmd_params)}" - if not less_flags: - env["LESS"] = "-R" - color = True - elif "r" in less_flags or "R" in less_flags: - color = True - - if color is None: - color = False - - c = subprocess.Popen( - [str(cmd_path)] + cmd_params, - shell=False, - stdin=subprocess.PIPE, - env=env, - errors="replace", - text=True, - ) - stdin = t.cast(t.BinaryIO, c.stdin) - encoding = get_best_encoding(stdin) - try: - yield stdin, encoding, color - except BrokenPipeError: - # In case the pager exited unexpectedly, ignore the broken pipe error. - pass - except Exception as e: - # In case there is an exception we want to close the pager immediately - # and let the caller handle it. - # Otherwise the pager will keep running, and the user may not notice - # the error message, or worse yet it may leave the terminal in a broken state. - c.terminate() - raise e - finally: - # We must close stdin and wait for the pager to exit before we continue - try: - stdin.close() - # Close implies flush, so it might throw a BrokenPipeError if the pager - # process exited already. - except BrokenPipeError: - pass - - # Less doesn't respect ^C, but catches it for its own UI purposes (aborting - # search or other commands inside less). - # - # That means when the user hits ^C, the parent process (click) terminates, - # but less is still alive, paging the output and messing up the terminal. - # - # If the user wants to make the pager exit on ^C, they should set - # `LESS='-K'`. It's not our decision to make. - while True: - try: - c.wait() - except KeyboardInterrupt: - pass - else: - break - - -@contextlib.contextmanager -def _tempfilepager( - cmd_parts: list[str], color: bool | None = None -) -> t.Iterator[tuple[t.BinaryIO | t.TextIO, str, bool]]: - """Page through text by invoking a program on a temporary file. - - Used as the primary pager strategy on Windows (where piping to - ``more`` adds spurious ``\\r\\n``), and as a fallback on other - platforms. The command is resolved to an absolute path with - :func:`shutil.which`. - """ - # Split the command into the invoked CLI and its parameters. - if not cmd_parts: - stdout = _default_text_stdout() or StringIO() - yield stdout, "utf-8", False - return - - import shutil - import subprocess - - cmd = cmd_parts[0] - - cmd_filepath = shutil.which(cmd) - if not cmd_filepath: - stdout = _default_text_stdout() or StringIO() - yield stdout, "utf-8", False - return - - # Produces a normalized absolute path string. - # multi-call binaries such as busybox derive their identity from the symlink - # less -> busybox. resolve() causes them to misbehave. (eg. less becomes busybox) - cmd_path = Path(cmd_filepath).absolute() - - import tempfile - - encoding = get_best_encoding(sys.stdout) - if color is None: - color = False - # On Windows, NamedTemporaryFile cannot be opened by another process - # while Python still has it open, so we use delete=False and clean up manually - # rather than using a contextmanager here. - f = tempfile.NamedTemporaryFile(mode="wb", delete=False) - try: - yield t.cast(t.BinaryIO, f), encoding, color - f.flush() - f.close() - subprocess.call([str(cmd_path), f.name]) - finally: - os.unlink(f.name) - - -class _SkipClose: - def __init__(self, stream: t.IO[t.Any]) -> None: - self.stream = stream - - def __getattr__(self, name: str) -> t.Any: - return getattr(self.stream, name) - - @property - def buffer(self) -> t.BinaryIO: - return _SkipClose(self.stream.buffer) # type: ignore[attr-defined, return-value] - - def close(self) -> None: - pass - - -@contextlib.contextmanager -def _nullpager( - stream: t.TextIO, color: bool | None = None -) -> t.Iterator[tuple[t.TextIO, str, bool]]: - """Simply print unformatted text. This is the ultimate fallback. Don't close the - output stream in this case, since it's coming from elsewhere rather than our - internal helpers. - """ - encoding = get_best_encoding(stream) - - if color is None: - color = False - - yield _SkipClose(stream), encoding, color # type: ignore[misc] - - -class Editor: - def __init__( - self, - editor: str | None = None, - env: cabc.Mapping[str, str] | None = None, - require_save: bool = True, - extension: str = ".txt", - ) -> None: - self.editor = editor - self.env = env - self.require_save = require_save - self.extension = extension - - def get_editor(self) -> str: - if self.editor is not None: - return self.editor - for key in "VISUAL", "EDITOR": - rv = os.environ.get(key) - if rv: - return rv - if WIN: - return "notepad" - - from shutil import which - - for editor in "sensible-editor", "vim", "nano": - if which(editor) is not None: - return editor - return "vi" - - def edit_files(self, filenames: cabc.Iterable[str]) -> None: - """Open files in the user's editor.""" - import shlex - import subprocess - - editor = self.get_editor() - environ: dict[str, str] | None = None - - if self.env: - environ = os.environ.copy() - environ.update(self.env) - - try: - # Split in POSIX mode (the default) for the same reasons as - # in pager(): strips quotes from tokens and preserves quoted - # Windows paths. - c = subprocess.Popen( - args=shlex.split(editor) + list(filenames), - env=environ, - ) - exit_code = c.wait() - if exit_code != 0: - raise ClickException( - _("{editor}: Editing failed").format(editor=editor) - ) - except OSError as e: - raise ClickException( - _("{editor}: Editing failed: {e}").format(editor=editor, e=e) - ) from e - - @t.overload - def edit(self, text: bytes | bytearray) -> bytes | None: ... - - # We cannot know whether or not the type expected is str or bytes when None - # is passed, so str is returned as that was what was done before. - @t.overload - def edit(self, text: str | None) -> str | None: ... - - def edit(self, text: str | bytes | bytearray | None) -> str | bytes | None: - import tempfile - - if text is None: - data: bytes | bytearray = b"" - elif isinstance(text, (bytes, bytearray)): - data = text - else: - if text and not text.endswith("\n"): - text += "\n" - - if WIN: - data = text.replace("\n", "\r\n").encode("utf-8-sig") - else: - data = text.encode("utf-8") - - fd, name = tempfile.mkstemp(prefix="editor-", suffix=self.extension) - f: t.BinaryIO - - try: - with os.fdopen(fd, "wb") as f: - f.write(data) - - # If the filesystem resolution is 1 second, like Mac OS - # 10.12 Extended, or 2 seconds, like FAT32, and the editor - # closes very fast, require_save can fail. Set the modified - # time to be 2 seconds in the past to work around this. - os.utime(name, (os.path.getatime(name), os.path.getmtime(name) - 2)) - # Depending on the resolution, the exact value might not be - # recorded, so get the new recorded value. - timestamp = os.path.getmtime(name) - - self.edit_files((name,)) - - if self.require_save and os.path.getmtime(name) == timestamp: - return None - - with open(name, "rb") as f: - rv = f.read() - - if isinstance(text, (bytes, bytearray)): - return rv - - return rv.decode("utf-8-sig").replace("\r\n", "\n") - finally: - os.unlink(name) - - -def open_url(url: str, wait: bool = False, locate: bool = False) -> int: - import subprocess - - def _unquote_file(url: str) -> str: - from urllib.parse import unquote - - if url.startswith("file://"): - url = unquote(url[7:]) - - return url - - if sys.platform == "darwin": - args = ["open"] - if wait: - args.append("-W") - if locate: - args.append("-R") - args.append(_unquote_file(url)) - null = open("/dev/null", "w") - try: - return subprocess.Popen(args, stderr=null).wait() - finally: - null.close() - elif WIN: - if locate: - url = _unquote_file(url) - args = ["explorer", "/select,", url] - try: - return subprocess.call(args) - except OSError: - return 127 - else: - try: - os.startfile(url) # type: ignore[attr-defined] - except OSError: - return 127 - return 0 - elif CYGWIN: - if locate: - url = _unquote_file(url) - args = ["cygstart", os.path.dirname(url)] - else: - args = ["cygstart"] - if wait: - args.append("-w") - args.append(url) - try: - return subprocess.call(args) - except OSError: - # Command not found - return 127 - - try: - if locate: - url = os.path.dirname(_unquote_file(url)) or "." - else: - url = _unquote_file(url) - c = subprocess.Popen(["xdg-open", url]) - if wait: - return c.wait() - return 0 - except OSError: - if url.startswith(("http://", "https://")) and not locate and not wait: - import webbrowser - - webbrowser.open(url) - return 0 - return 1 - - -def _translate_ch_to_exc(ch: str) -> None: - if ch == "\x03": - raise KeyboardInterrupt() - - if ch == "\x04" and not WIN: # Unix-like, Ctrl+D - raise EOFError() - - if ch == "\x1a" and WIN: # Windows, Ctrl+Z - raise EOFError() - - -if sys.platform == "win32": - import msvcrt - - @contextlib.contextmanager - def raw_terminal() -> cabc.Iterator[int]: - yield -1 - - def getchar(echo: bool) -> str: - # The function `getch` will return a bytes object corresponding to - # the pressed character. Since Windows 10 build 1803, it will also - # return \x00 when called a second time after pressing a regular key. - # - # `getwch` does not share this probably-bugged behavior. Moreover, it - # returns a Unicode object by default, which is what we want. - # - # Either of these functions will return \x00 or \xe0 to indicate - # a special key, and you need to call the same function again to get - # the "rest" of the code. The fun part is that \u00e0 is - # "latin small letter a with grave", so if you type that on a French - # keyboard, you _also_ get a \xe0. - # E.g., consider the Up arrow. This returns \xe0 and then \x48. The - # resulting Unicode string reads as "a with grave" + "capital H". - # This is indistinguishable from when the user actually types - # "a with grave" and then "capital H". - # - # When \xe0 is returned, we assume it's part of a special-key sequence - # and call `getwch` again, but that means that when the user types - # the \u00e0 character, `getchar` doesn't return until a second - # character is typed. - # The alternative is returning immediately, but that would mess up - # cross-platform handling of arrow keys and others that start with - # \xe0. Another option is using `getch`, but then we can't reliably - # read non-ASCII characters, because return values of `getch` are - # limited to the current 8-bit codepage. - # - # Anyway, Click doesn't claim to do this Right(tm), and using `getwch` - # is doing the right thing in more situations than with `getch`. - - if echo: - func = t.cast(t.Callable[[], str], msvcrt.getwche) - else: - func = t.cast(t.Callable[[], str], msvcrt.getwch) - - rv = func() - - if rv in ("\x00", "\xe0"): - # \x00 and \xe0 are control characters that indicate special key, - # see above. - rv += func() - - _translate_ch_to_exc(rv) - return rv - -else: - import termios - import tty - - @contextlib.contextmanager - def raw_terminal() -> cabc.Iterator[int]: - f: t.TextIO | None - fd: int - - if not isatty(sys.stdin): - f = open("/dev/tty") - fd = f.fileno() - else: - fd = sys.stdin.fileno() - f = None - - try: - old_settings = termios.tcgetattr(fd) - - try: - tty.setraw(fd) - yield fd - finally: - termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) - sys.stdout.flush() - - if f is not None: - f.close() - except termios.error: - pass - - def getchar(echo: bool) -> str: - with raw_terminal() as fd: - ch = os.read(fd, 32).decode(get_best_encoding(sys.stdin), "replace") - - if echo and isatty(sys.stdout): - sys.stdout.write(ch) - - _translate_ch_to_exc(ch) - return ch diff --git a/notification-service/venv/Lib/site-packages/click/_textwrap.py b/notification-service/venv/Lib/site-packages/click/_textwrap.py deleted file mode 100644 index 82840f2..0000000 --- a/notification-service/venv/Lib/site-packages/click/_textwrap.py +++ /dev/null @@ -1,188 +0,0 @@ -from __future__ import annotations - -import collections.abc as cabc -import textwrap -from contextlib import contextmanager - -from ._compat import _ansi_re -from ._compat import term_len - - -def _truncate_visible(text: str, n: int) -> str: - """Return the longest prefix of ``text`` containing at most ``n`` visible - characters. - - ANSI escape sequences inside the prefix are kept intact and do not count - toward the visible width. A cut is never placed inside an escape sequence. - """ - if n <= 0: - return "" - - visible = 0 - i = 0 - cut = 0 - end = len(text) - while i < end: - m = _ansi_re.match(text, i) - if m is not None: - i = m.end() - continue - visible += 1 - i += 1 - cut = i - if visible >= n: - break - return text[:cut] - - -class TextWrapper(textwrap.TextWrapper): - """``textwrap.TextWrapper`` variant that measures widths by visible - character count. - - ANSI escape sequences embedded in chunks, indents, or the placeholder are - excluded from the width budget. Without this, styled help text (a styled - ``Usage:`` prefix, a colorized option name, ...) would be wrapped earlier - than its visible length warrants and tokens would split mid-word. - """ - - def _handle_long_word( - self, - reversed_chunks: list[str], - cur_line: list[str], - cur_len: int, - width: int, - ) -> None: - space_left = max(width - cur_len, 1) - - if self.break_long_words: - last = reversed_chunks[-1] - cut = _truncate_visible(last, space_left) - res = last[len(cut) :] - cur_line.append(cut) - reversed_chunks[-1] = res - elif not cur_line: - cur_line.append(reversed_chunks.pop()) - - def _wrap_chunks(self, chunks: list[str]) -> list[str]: - """Wrap chunks counting widths in visible characters. - - Mirrors the algorithm of :meth:`textwrap.TextWrapper._wrap_chunks` - with every width measurement routed through - :func:`click._compat.term_len` instead of :func:`len`, so ANSI escape - bytes in chunks, indents, or the placeholder do not inflate the count. - - .. seealso:: - :class:`textwrap.TextWrapper` in the Python standard library documentation: - https://docs.python.org/3/library/textwrap.html#textwrap.TextWrapper - - Reference implementation in CPython: - https://github.com/python/cpython/blob/main/Lib/textwrap.py - """ - lines: list[str] = [] - if self.width <= 0: - raise ValueError(f"invalid width {self.width!r} (must be > 0)") - if self.max_lines is not None: - if self.max_lines > 1: - indent = self.subsequent_indent - else: - indent = self.initial_indent - if term_len(indent) + term_len(self.placeholder.lstrip()) > self.width: - raise ValueError("placeholder too large for max width") - - chunks.reverse() - - while chunks: - cur_line: list[str] = [] - cur_len = 0 - - if lines: - indent = self.subsequent_indent - else: - indent = self.initial_indent - - width = self.width - term_len(indent) - - if self.drop_whitespace and chunks[-1].strip() == "" and lines: - del chunks[-1] - - while chunks: - n = term_len(chunks[-1]) - - if cur_len + n <= width: - cur_line.append(chunks.pop()) - cur_len += n - - else: - break - - if chunks and term_len(chunks[-1]) > width: - self._handle_long_word(chunks, cur_line, cur_len, width) - cur_len = sum(map(term_len, cur_line)) - - if self.drop_whitespace and cur_line and cur_line[-1].strip() == "": - cur_len -= term_len(cur_line[-1]) - del cur_line[-1] - - if cur_line: - if ( - self.max_lines is None - or len(lines) + 1 < self.max_lines - or ( - not chunks - or self.drop_whitespace - and len(chunks) == 1 - and not chunks[0].strip() - ) - and cur_len <= width - ): - lines.append(indent + "".join(cur_line)) - else: - while cur_line: - if ( - cur_line[-1].strip() - and cur_len + term_len(self.placeholder) <= width - ): - cur_line.append(self.placeholder) - lines.append(indent + "".join(cur_line)) - break - cur_len -= term_len(cur_line[-1]) - del cur_line[-1] - else: - if lines: - prev_line = lines[-1].rstrip() - if ( - term_len(prev_line) + term_len(self.placeholder) - <= self.width - ): - lines[-1] = prev_line + self.placeholder - break - lines.append(indent + self.placeholder.lstrip()) - break - - return lines - - @contextmanager - def extra_indent(self, indent: str) -> cabc.Iterator[None]: - old_initial_indent = self.initial_indent - old_subsequent_indent = self.subsequent_indent - self.initial_indent += indent - self.subsequent_indent += indent - - try: - yield - finally: - self.initial_indent = old_initial_indent - self.subsequent_indent = old_subsequent_indent - - def indent_only(self, text: str) -> str: - rv = [] - - for idx, line in enumerate(text.splitlines()): - indent = self.initial_indent - - if idx > 0: - indent = self.subsequent_indent - - rv.append(f"{indent}{line}") - - return "\n".join(rv) diff --git a/notification-service/venv/Lib/site-packages/click/_utils.py b/notification-service/venv/Lib/site-packages/click/_utils.py deleted file mode 100644 index 05ee2e9..0000000 --- a/notification-service/venv/Lib/site-packages/click/_utils.py +++ /dev/null @@ -1,36 +0,0 @@ -from __future__ import annotations - -import enum -import typing as t - - -class Sentinel(enum.Enum): - """Enum used to define sentinel values. - - .. seealso:: - - `PEP 661 - Sentinel Values `_. - """ - - UNSET = object() - FLAG_NEEDS_VALUE = object() - - def __repr__(self) -> str: - return f"{self.__class__.__name__}.{self.name}" - - -UNSET: t.Literal[Sentinel.UNSET] = Sentinel.UNSET -"""Sentinel used to indicate that a value is not set.""" - -FLAG_NEEDS_VALUE: t.Literal[Sentinel.FLAG_NEEDS_VALUE] = Sentinel.FLAG_NEEDS_VALUE -"""Sentinel used to indicate an option was passed as a flag without a -value but is not a flag option. - -``Option.consume_value`` uses this to prompt or use the ``flag_value``. -""" - -T_UNSET: t.TypeAlias = t.Literal[Sentinel.UNSET] -"""Type hint for the :data:`UNSET` sentinel value.""" - -T_FLAG_NEEDS_VALUE: t.TypeAlias = t.Literal[Sentinel.FLAG_NEEDS_VALUE] -"""Type hint for the :data:`FLAG_NEEDS_VALUE` sentinel value.""" diff --git a/notification-service/venv/Lib/site-packages/click/_winconsole.py b/notification-service/venv/Lib/site-packages/click/_winconsole.py deleted file mode 100644 index d25178d..0000000 --- a/notification-service/venv/Lib/site-packages/click/_winconsole.py +++ /dev/null @@ -1,297 +0,0 @@ -# This module is based on the excellent work by Adam Bartoš who -# provided a lot of what went into the implementation here in -# the discussion to issue1602 in the Python bug tracker. -# -# There are some general differences in regards to how this works -# compared to the original patches as we do not need to patch -# the entire interpreter but just work in our little world of -# echo and prompt. -from __future__ import annotations - -import collections.abc as cabc -import io -import sys -import time -import typing as t -from ctypes import Array -from ctypes import byref -from ctypes import c_char -from ctypes import c_char_p -from ctypes import c_int -from ctypes import c_ssize_t -from ctypes import c_ulong -from ctypes import c_void_p -from ctypes import POINTER -from ctypes import py_object -from ctypes import Structure -from ctypes.wintypes import DWORD -from ctypes.wintypes import HANDLE -from ctypes.wintypes import LPCWSTR -from ctypes.wintypes import LPWSTR -from gettext import gettext as _ - -from ._compat import _NonClosingTextIOWrapper - -assert sys.platform == "win32" -import msvcrt # noqa: E402 -from ctypes import windll # noqa: E402 -from ctypes import WINFUNCTYPE # noqa: E402 - -c_ssize_p = POINTER(c_ssize_t) - -kernel32 = windll.kernel32 -GetStdHandle = kernel32.GetStdHandle -ReadConsoleW = kernel32.ReadConsoleW -WriteConsoleW = kernel32.WriteConsoleW -GetConsoleMode = kernel32.GetConsoleMode -GetLastError = kernel32.GetLastError -GetCommandLineW = WINFUNCTYPE(LPWSTR)(("GetCommandLineW", windll.kernel32)) -CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))( - ("CommandLineToArgvW", windll.shell32) -) -LocalFree = WINFUNCTYPE(c_void_p, c_void_p)(("LocalFree", windll.kernel32)) - -STDIN_HANDLE = GetStdHandle(-10) -STDOUT_HANDLE = GetStdHandle(-11) -STDERR_HANDLE = GetStdHandle(-12) - -PyBUF_SIMPLE = 0 -PyBUF_WRITABLE = 1 - -ERROR_SUCCESS = 0 -ERROR_NOT_ENOUGH_MEMORY = 8 -ERROR_OPERATION_ABORTED = 995 - -STDIN_FILENO = 0 -STDOUT_FILENO = 1 -STDERR_FILENO = 2 - -EOF = b"\x1a" -MAX_BYTES_WRITTEN = 32767 - -if t.TYPE_CHECKING: - try: - # Using `typing_extensions.Buffer` instead of `collections.abc` - # on Windows for some reason does not have `Sized` implemented. - from collections.abc import Buffer # type: ignore - except ImportError: - from typing_extensions import Buffer - -try: - from ctypes import pythonapi -except ImportError: - # On PyPy we cannot get buffers so our ability to operate here is - # severely limited. - get_buffer = None -else: - - class Py_buffer(Structure): - _fields_ = [ # noqa: RUF012 - ("buf", c_void_p), - ("obj", py_object), - ("len", c_ssize_t), - ("itemsize", c_ssize_t), - ("readonly", c_int), - ("ndim", c_int), - ("format", c_char_p), - ("shape", c_ssize_p), - ("strides", c_ssize_p), - ("suboffsets", c_ssize_p), - ("internal", c_void_p), - ] - - PyObject_GetBuffer = pythonapi.PyObject_GetBuffer - PyBuffer_Release = pythonapi.PyBuffer_Release - - def get_buffer(obj: Buffer, writable: bool = False) -> Array[c_char]: - buf = Py_buffer() - flags: int = PyBUF_WRITABLE if writable else PyBUF_SIMPLE - PyObject_GetBuffer(py_object(obj), byref(buf), flags) - - try: - buffer_type = c_char * buf.len - out: Array[c_char] = buffer_type.from_address(buf.buf) - return out - finally: - PyBuffer_Release(byref(buf)) - - -class _WindowsConsoleRawIOBase(io.RawIOBase): - def __init__(self, handle: int | None) -> None: - self.handle = handle - - def isatty(self) -> t.Literal[True]: - super().isatty() - return True - - -class _WindowsConsoleReader(_WindowsConsoleRawIOBase): - def readable(self) -> t.Literal[True]: - return True - - def readinto(self, b: Buffer) -> int: - bytes_to_be_read = len(b) - if not bytes_to_be_read: - return 0 - elif bytes_to_be_read % 2: - raise ValueError( - "cannot read odd number of bytes from UTF-16-LE encoded console" - ) - - buffer = get_buffer(b, writable=True) - code_units_to_be_read = bytes_to_be_read // 2 - code_units_read = c_ulong() - - rv = ReadConsoleW( - HANDLE(self.handle), - buffer, - code_units_to_be_read, - byref(code_units_read), - None, - ) - if GetLastError() == ERROR_OPERATION_ABORTED: - # wait for KeyboardInterrupt - time.sleep(0.1) - if not rv: - raise OSError(_("Windows error: {error}").format(error=GetLastError())) - - if buffer[0] == EOF: - return 0 - return 2 * code_units_read.value - - -class _WindowsConsoleWriter(_WindowsConsoleRawIOBase): - def writable(self) -> t.Literal[True]: - return True - - @staticmethod - def _get_error_message(errno: int) -> str: - if errno == ERROR_SUCCESS: - return "ERROR_SUCCESS" - elif errno == ERROR_NOT_ENOUGH_MEMORY: - return "ERROR_NOT_ENOUGH_MEMORY" - return _("Windows error: {error}").format(error=errno) - - def write(self, b: Buffer) -> int: - bytes_to_be_written = len(b) - buf = get_buffer(b) - code_units_to_be_written = min(bytes_to_be_written, MAX_BYTES_WRITTEN) // 2 - code_units_written = c_ulong() - - WriteConsoleW( - HANDLE(self.handle), - buf, - code_units_to_be_written, - byref(code_units_written), - None, - ) - bytes_written = 2 * code_units_written.value - - if bytes_written == 0 and bytes_to_be_written > 0: - raise OSError(self._get_error_message(GetLastError())) - return bytes_written - - -class ConsoleStream: - def __init__(self, text_stream: t.TextIO, byte_stream: t.BinaryIO) -> None: - self._text_stream = text_stream - self.buffer = byte_stream - - @property - def name(self) -> str: - return self.buffer.name - - def write(self, x: t.AnyStr) -> int: - if isinstance(x, str): - return self._text_stream.write(x) - try: - self.flush() - except Exception: - pass - return self.buffer.write(x) - - def writelines(self, lines: cabc.Iterable[t.AnyStr]) -> None: - for line in lines: - self.write(line) - - def __getattr__(self, name: str) -> t.Any: - return getattr(self._text_stream, name) - - def isatty(self) -> bool: - return self.buffer.isatty() - - def __repr__(self) -> str: - return f"" - - -def _get_text_stdin(buffer_stream: t.BinaryIO) -> t.TextIO: - text_stream = _NonClosingTextIOWrapper( - io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)), - "utf-16-le", - "strict", - line_buffering=True, - ) - return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) - - -def _get_text_stdout(buffer_stream: t.BinaryIO) -> t.TextIO: - text_stream = _NonClosingTextIOWrapper( - io.BufferedWriter(_WindowsConsoleWriter(STDOUT_HANDLE)), - "utf-16-le", - "strict", - line_buffering=True, - ) - return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) - - -def _get_text_stderr(buffer_stream: t.BinaryIO) -> t.TextIO: - text_stream = _NonClosingTextIOWrapper( - io.BufferedWriter(_WindowsConsoleWriter(STDERR_HANDLE)), - "utf-16-le", - "strict", - line_buffering=True, - ) - return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) - - -_stream_factories: cabc.Mapping[int, t.Callable[[t.BinaryIO], t.TextIO]] = { - 0: _get_text_stdin, - 1: _get_text_stdout, - 2: _get_text_stderr, -} - - -def _is_console(f: t.TextIO) -> bool: - if not hasattr(f, "fileno"): - return False - - try: - fileno = f.fileno() - except (OSError, io.UnsupportedOperation): - return False - - handle = msvcrt.get_osfhandle(fileno) - return bool(GetConsoleMode(handle, byref(DWORD()))) - - -def _get_windows_console_stream( - f: t.TextIO, encoding: str | None, errors: str | None -) -> t.TextIO | None: - if ( - get_buffer is None - or encoding not in {"utf-16-le", None} - or errors not in {"strict", None} - or not _is_console(f) - ): - return None - - func = _stream_factories.get(f.fileno()) - if func is None: - return None - - b = getattr(f, "buffer", None) - - if b is None: - return None - - return func(b) diff --git a/notification-service/venv/Lib/site-packages/click/core.py b/notification-service/venv/Lib/site-packages/click/core.py deleted file mode 100644 index bc04f64..0000000 --- a/notification-service/venv/Lib/site-packages/click/core.py +++ /dev/null @@ -1,3542 +0,0 @@ -from __future__ import annotations - -import collections.abc as cabc -import enum -import errno -import inspect -import os -import sys -import typing as t -from abc import ABC -from abc import abstractmethod -from collections import abc -from collections import Counter -from contextlib import AbstractContextManager -from contextlib import contextmanager -from contextlib import ExitStack -from functools import update_wrapper -from gettext import gettext as _ -from gettext import ngettext -from itertools import repeat -from types import TracebackType - -from . import types -from ._utils import FLAG_NEEDS_VALUE -from ._utils import UNSET -from .exceptions import Abort -from .exceptions import BadParameter -from .exceptions import ClickException -from .exceptions import Exit -from .exceptions import MissingParameter -from .exceptions import NoArgsIsHelpError -from .exceptions import NoSuchCommand -from .exceptions import UsageError -from .formatting import HelpFormatter -from .formatting import join_options -from .globals import pop_context -from .globals import push_context -from .parser import _OptionParser -from .parser import _split_opt -from .termui import confirm -from .termui import prompt -from .termui import style -from .utils import _detect_program_name -from .utils import _expand_args -from .utils import echo -from .utils import make_default_short_help -from .utils import make_str -from .utils import PacifyFlushWrapper - -if t.TYPE_CHECKING: - from .shell_completion import CompletionItem - -F = t.TypeVar("F", bound="t.Callable[..., t.Any]") -V = t.TypeVar("V") - - -def _complete_visible_commands( - ctx: Context, incomplete: str -) -> cabc.Iterator[tuple[str, Command]]: - """List all the subcommands of a group that start with the - incomplete value and aren't hidden. - - :param ctx: Invocation context for the group. - :param incomplete: Value being completed. May be empty. - """ - multi = t.cast(Group, ctx.command) - - for name in multi.list_commands(ctx): - if name.startswith(incomplete): - command = multi.get_command(ctx, name) - - if command is not None and not command.hidden: - yield name, command - - -def _check_nested_chain( - base_command: Group, cmd_name: str, cmd: Command, register: bool = False -) -> None: - if not base_command.chain or not isinstance(cmd, Group): - return - - if register: - message = ( - f"It is not possible to add the group {cmd_name!r} to another" - f" group {base_command.name!r} that is in chain mode." - ) - else: - message = ( - f"Found the group {cmd_name!r} as subcommand to another group " - f" {base_command.name!r} that is in chain mode. This is not supported." - ) - - raise RuntimeError(message) - - -def _format_deprecated_label(deprecated: bool | str) -> str: - """Return the parenthesized deprecation label shown in help text.""" - label = _("deprecated").upper() - if isinstance(deprecated, str): - return f"({label}: {deprecated})" - return f"({label})" - - -def _format_deprecated_suffix(deprecated: bool | str) -> str: - """Return the trailing reason for a ``DeprecationWarning`` message, - prefixed with a space, or an empty string when no reason was given. - """ - if isinstance(deprecated, str): - return f" {deprecated}" - return "" - - -def batch(iterable: cabc.Iterable[V], batch_size: int) -> list[tuple[V, ...]]: - return list(zip(*repeat(iter(iterable), batch_size), strict=False)) - - -@contextmanager -def augment_usage_errors( - ctx: Context, param: Parameter | None = None -) -> cabc.Iterator[None]: - """Context manager that attaches extra information to exceptions.""" - try: - yield - except BadParameter as e: - if e.ctx is None: - e.ctx = ctx - if param is not None and e.param is None: - e.param = param - raise - except UsageError as e: - if e.ctx is None: - e.ctx = ctx - raise - - -def iter_params_for_processing( - invocation_order: cabc.Sequence[Parameter], - declaration_order: cabc.Sequence[Parameter], -) -> list[Parameter]: - """Returns all declared parameters in the order they should be processed. - - The declared parameters are re-shuffled depending on the order in which - they were invoked, as well as the eagerness of each parameters. - - The invocation order takes precedence over the declaration order. I.e. the - order in which the user provided them to the CLI is respected. - - This behavior and its effect on callback evaluation is detailed at: - https://click.palletsprojects.com/en/stable/advanced/#callback-evaluation-order - """ - - def sort_key(item: Parameter) -> tuple[bool, float]: - try: - idx: float = invocation_order.index(item) - except ValueError: - idx = float("inf") - - return not item.is_eager, idx - - return sorted(declaration_order, key=sort_key) - - -class ParameterSource(enum.IntEnum): - """This is an :class:`~enum.IntEnum` that indicates the source of a - parameter's value. - - Use :meth:`click.Context.get_parameter_source` to get the - source for a parameter by name. - - Members are ordered from most explicit to least explicit source. - This allows comparison to check if a value was explicitly provided: - - .. code-block:: python - - source = ctx.get_parameter_source("port") - if source < click.ParameterSource.DEFAULT_MAP: - ... # value was explicitly set - - .. versionchanged:: 8.3.3 - Use :class:`~enum.IntEnum` and reorder members from most to - least explicit. Supports comparison operators. - - .. versionchanged:: 8.0 - Use :class:`~enum.Enum` and drop the ``validate`` method. - - .. versionchanged:: 8.0 - Added the ``PROMPT`` value. - """ - - PROMPT = enum.auto() - """Used a prompt to confirm a default or provide a value.""" - COMMANDLINE = enum.auto() - """The value was provided by the command line args.""" - ENVIRONMENT = enum.auto() - """The value was provided with an environment variable.""" - DEFAULT_MAP = enum.auto() - """Used a default provided by :attr:`Context.default_map`.""" - DEFAULT = enum.auto() - """Used the default specified by the parameter.""" - - -class Context: - """The context is a special internal object that holds state relevant - for the script execution at every single level. It's normally invisible - to commands unless they opt-in to getting access to it. - - The context is useful as it can pass internal objects around and can - control special execution features such as reading data from - environment variables. - - A context can be used as context manager in which case it will call - :meth:`close` on teardown. - - :param command: the command class for this context. - :param parent: the parent context. - :param info_name: the info name for this invocation. Generally this - is the most descriptive name for the script or - command. For the toplevel script it is usually - the name of the script, for commands below that it's - the name of the script. - :param obj: an arbitrary object of user data. - :param auto_envvar_prefix: the prefix to use for automatic environment - variables. If this is `None` then reading - from environment variables is disabled. This - does not affect manually set environment - variables which are always read. - :param default_map: a dictionary (like object) with default values - for parameters. - :param terminal_width: the width of the terminal. The default is - inherit from parent context. If no context - defines the terminal width then auto - detection will be applied. - :param max_content_width: the maximum width for content rendered by - Click (this currently only affects help - pages). This defaults to 80 characters if - not overridden. In other words: even if the - terminal is larger than that, Click will not - format things wider than 80 characters by - default. In addition to that, formatters might - add some safety mapping on the right. - :param resilient_parsing: if this flag is enabled then Click will - parse without any interactivity or callback - invocation. Default values will also be - ignored. This is useful for implementing - things such as completion support. - :param allow_extra_args: if this is set to `True` then extra arguments - at the end will not raise an error and will be - kept on the context. The default is to inherit - from the command. - :param allow_interspersed_args: if this is set to `False` then options - and arguments cannot be mixed. The - default is to inherit from the command. - :param ignore_unknown_options: instructs click to ignore options it does - not know and keeps them for later - processing. - :param help_option_names: optionally a list of strings that define how - the default help parameter is named. The - default is ``['--help']``. - :param token_normalize_func: an optional function that is used to - normalize tokens (options, choices, - etc.). This for instance can be used to - implement case insensitive behavior. - :param color: controls if the terminal supports ANSI colors or not. The - default is autodetection. This is only needed if ANSI - codes are used in texts that Click prints which is by - default not the case. This for instance would affect - help output. - :param show_default: Show the default value for commands. If this - value is not set, it defaults to the value from the parent - context. ``Command.show_default`` overrides this default for the - specific command. - - .. versionchanged:: 8.2 - The ``protected_args`` attribute is deprecated and will be removed in - Click 9.0. ``args`` will contain remaining unparsed tokens. - - .. versionchanged:: 8.1 - The ``show_default`` parameter is overridden by - ``Command.show_default``, instead of the other way around. - - .. versionchanged:: 8.0 - The ``show_default`` parameter defaults to the value from the - parent context. - - .. versionchanged:: 7.1 - Added the ``show_default`` parameter. - - .. versionchanged:: 4.0 - Added the ``color``, ``ignore_unknown_options``, and - ``max_content_width`` parameters. - - .. versionchanged:: 3.0 - Added the ``allow_extra_args`` and ``allow_interspersed_args`` - parameters. - - .. versionchanged:: 2.0 - Added the ``resilient_parsing``, ``help_option_names``, and - ``token_normalize_func`` parameters. - """ - - #: The formatter class to create with :meth:`make_formatter`. - #: - #: .. versionadded:: 8.0 - formatter_class: type[HelpFormatter] = HelpFormatter - - def __init__( - self, - command: Command, - parent: Context | None = None, - info_name: str | None = None, - obj: t.Any | None = None, - auto_envvar_prefix: str | None = None, - default_map: cabc.MutableMapping[str, t.Any] | None = None, - terminal_width: int | None = None, - max_content_width: int | None = None, - resilient_parsing: bool = False, - allow_extra_args: bool | None = None, - allow_interspersed_args: bool | None = None, - ignore_unknown_options: bool | None = None, - help_option_names: list[str] | None = None, - token_normalize_func: t.Callable[[str], str] | None = None, - color: bool | None = None, - show_default: bool | None = None, - ) -> None: - #: the parent context or `None` if none exists. - self.parent = parent - #: the :class:`Command` for this context. - self.command = command - #: the descriptive information name - self.info_name = info_name - #: Map of parameter names to their parsed values. Parameters - #: with ``expose_value=False`` are not stored. - self.params: dict[str, t.Any] = {} - #: the leftover arguments. - self.args: list[str] = [] - #: protected arguments. These are arguments that are prepended - #: to `args` when certain parsing scenarios are encountered but - #: must be never propagated to another arguments. This is used - #: to implement nested parsing. - self._protected_args: list[str] = [] - #: the collected prefixes of the command's options. - self._opt_prefixes: set[str] = set(parent._opt_prefixes) if parent else set() - - if obj is None and parent is not None: - obj = parent.obj - - #: the user object stored. - self.obj: t.Any = obj - self._meta: dict[str, t.Any] = getattr(parent, "meta", {}) - - #: A dictionary (-like object) with defaults for parameters. - if ( - default_map is None - and info_name is not None - and parent is not None - and parent.default_map is not None - ): - default_map = parent.default_map.get(info_name) - - self.default_map: cabc.MutableMapping[str, t.Any] | None = default_map - - #: This flag indicates if a subcommand is going to be executed. A - #: group callback can use this information to figure out if it's - #: being executed directly or because the execution flow passes - #: onwards to a subcommand. By default it's None, but it can be - #: the name of the subcommand to execute. - #: - #: If chaining is enabled this will be set to ``'*'`` in case - #: any commands are executed. It is however not possible to - #: figure out which ones. If you require this knowledge you - #: should use a :func:`result_callback`. - self.invoked_subcommand: str | None = None - - if terminal_width is None and parent is not None: - terminal_width = parent.terminal_width - - #: The width of the terminal (None is autodetection). - self.terminal_width: int | None = terminal_width - - if max_content_width is None and parent is not None: - max_content_width = parent.max_content_width - - #: The maximum width of formatted content (None implies a sensible - #: default which is 80 for most things). - self.max_content_width: int | None = max_content_width - - if allow_extra_args is None: - allow_extra_args = command.allow_extra_args - - #: Indicates if the context allows extra args or if it should - #: fail on parsing. - #: - #: .. versionadded:: 3.0 - self.allow_extra_args = allow_extra_args - - if allow_interspersed_args is None: - allow_interspersed_args = command.allow_interspersed_args - - #: Indicates if the context allows mixing of arguments and - #: options or not. - #: - #: .. versionadded:: 3.0 - self.allow_interspersed_args: bool = allow_interspersed_args - - if ignore_unknown_options is None: - ignore_unknown_options = command.ignore_unknown_options - - #: Instructs click to ignore options that a command does not - #: understand and will store it on the context for later - #: processing. This is primarily useful for situations where you - #: want to call into external programs. Generally this pattern is - #: strongly discouraged because it's not possibly to losslessly - #: forward all arguments. - #: - #: .. versionadded:: 4.0 - self.ignore_unknown_options: bool = ignore_unknown_options - - if help_option_names is None: - if parent is not None: - help_option_names = parent.help_option_names - else: - help_option_names = ["--help"] - - #: The names for the help options. - self.help_option_names: list[str] = help_option_names - - if token_normalize_func is None and parent is not None: - token_normalize_func = parent.token_normalize_func - - #: An optional normalization function for tokens. This is - #: options, choices, commands etc. - self.token_normalize_func: t.Callable[[str], str] | None = token_normalize_func - - #: Indicates if resilient parsing is enabled. In that case Click - #: will do its best to not cause any failures and default values - #: will be ignored. Useful for completion. - self.resilient_parsing: bool = resilient_parsing - - # If there is no envvar prefix yet, but the parent has one and - # the command on this level has a name, we can expand the envvar - # prefix automatically. - if auto_envvar_prefix is None: - if ( - parent is not None - and parent.auto_envvar_prefix is not None - and self.info_name is not None - ): - auto_envvar_prefix = ( - f"{parent.auto_envvar_prefix}_{self.info_name.upper()}" - ) - else: - auto_envvar_prefix = auto_envvar_prefix.upper() - - if auto_envvar_prefix is not None: - auto_envvar_prefix = auto_envvar_prefix.replace("-", "_") - - self.auto_envvar_prefix: str | None = auto_envvar_prefix - - if color is None and parent is not None: - color = parent.color - - #: Controls if styling output is wanted or not. - self.color: bool | None = color - - if show_default is None and parent is not None: - show_default = parent.show_default - - #: Show option default values when formatting help text. - self.show_default: bool | None = show_default - - self._close_callbacks: list[t.Callable[[], t.Any]] = [] - self._depth = 0 - self._parameter_source: dict[str, ParameterSource] = {} - # Tracks whether the option that currently owns each parameter slot in - # :attr:`params` had its ``default`` set explicitly by the user. Used - # to tie-break feature-switch groups where multiple options share a - # parameter name and both fall back to their default value. - # Refs: https://github.com/pallets/click/issues/3403 - self._param_default_explicit: dict[str, bool] = {} - self._exit_stack = ExitStack() - - @property - def protected_args(self) -> list[str]: - import warnings - - warnings.warn( - "'protected_args' is deprecated and will be removed in Click 9.0." - " 'args' will contain remaining unparsed tokens.", - DeprecationWarning, - stacklevel=2, - ) - return self._protected_args - - def to_info_dict(self) -> dict[str, t.Any]: - """Gather information that could be useful for a tool generating - user-facing documentation. This traverses the entire CLI - structure. - - .. code-block:: python - - with Context(cli) as ctx: - info = ctx.to_info_dict() - - .. versionadded:: 8.0 - """ - return { - "command": self.command.to_info_dict(self), - "info_name": self.info_name, - "allow_extra_args": self.allow_extra_args, - "allow_interspersed_args": self.allow_interspersed_args, - "ignore_unknown_options": self.ignore_unknown_options, - "auto_envvar_prefix": self.auto_envvar_prefix, - } - - def __enter__(self) -> Context: - self._depth += 1 - push_context(self) - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_value: BaseException | None, - tb: TracebackType | None, - ) -> bool | None: - self._depth -= 1 - exit_result: bool | None = None - if self._depth == 0: - exit_result = self._close_with_exception_info(exc_type, exc_value, tb) - pop_context() - - return exit_result - - @contextmanager - def scope(self, cleanup: bool = True) -> cabc.Iterator[Context]: - """This helper method can be used with the context object to promote - it to the current thread local (see :func:`get_current_context`). - The default behavior of this is to invoke the cleanup functions which - can be disabled by setting `cleanup` to `False`. The cleanup - functions are typically used for things such as closing file handles. - - If the cleanup is intended the context object can also be directly - used as a context manager. - - Example usage:: - - with ctx.scope(): - assert get_current_context() is ctx - - This is equivalent:: - - with ctx: - assert get_current_context() is ctx - - .. versionadded:: 5.0 - - :param cleanup: controls if the cleanup functions should be run or - not. The default is to run these functions. In - some situations the context only wants to be - temporarily pushed in which case this can be disabled. - Nested pushes automatically defer the cleanup. - """ - if not cleanup: - self._depth += 1 - try: - with self as rv: - yield rv - finally: - if not cleanup: - self._depth -= 1 - - @property - def meta(self) -> dict[str, t.Any]: - """This is a dictionary which is shared with all the contexts - that are nested. It exists so that click utilities can store some - state here if they need to. It is however the responsibility of - that code to manage this dictionary well. - - The keys are supposed to be unique dotted strings. For instance - module paths are a good choice for it. What is stored in there is - irrelevant for the operation of click. However what is important is - that code that places data here adheres to the general semantics of - the system. - - Example usage:: - - LANG_KEY = f'{__name__}.lang' - - def set_language(value): - ctx = get_current_context() - ctx.meta[LANG_KEY] = value - - def get_language(): - return get_current_context().meta.get(LANG_KEY, 'en_US') - - .. versionadded:: 5.0 - """ - return self._meta - - def make_formatter(self) -> HelpFormatter: - """Creates the :class:`~click.HelpFormatter` for the help and - usage output. - - To quickly customize the formatter class used without overriding - this method, set the :attr:`formatter_class` attribute. - - .. versionchanged:: 8.0 - Added the :attr:`formatter_class` attribute. - """ - return self.formatter_class( - width=self.terminal_width, max_width=self.max_content_width - ) - - def with_resource(self, context_manager: AbstractContextManager[V]) -> V: - """Register a resource as if it were used in a ``with`` - statement. The resource will be cleaned up when the context is - popped. - - Uses :meth:`contextlib.ExitStack.enter_context`. It calls the - resource's ``__enter__()`` method and returns the result. When - the context is popped, it closes the stack, which calls the - resource's ``__exit__()`` method. - - To register a cleanup function for something that isn't a - context manager, use :meth:`call_on_close`. Or use something - from :mod:`contextlib` to turn it into a context manager first. - - .. code-block:: python - - @click.group() - @click.option("--name") - @click.pass_context - def cli(ctx): - ctx.obj = ctx.with_resource(connect_db(name)) - - :param context_manager: The context manager to enter. - :return: Whatever ``context_manager.__enter__()`` returns. - - .. versionadded:: 8.0 - """ - return self._exit_stack.enter_context(context_manager) - - def call_on_close(self, f: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]: - """Register a function to be called when the context tears down. - - This can be used to close resources opened during the script - execution. Resources that support Python's context manager - protocol which would be used in a ``with`` statement should be - registered with :meth:`with_resource` instead. - - :param f: The function to execute on teardown. - """ - return self._exit_stack.callback(f) - - def close(self) -> None: - """Invoke all close callbacks registered with - :meth:`call_on_close`, and exit all context managers entered - with :meth:`with_resource`. - """ - self._close_with_exception_info(None, None, None) - - def _close_with_exception_info( - self, - exc_type: type[BaseException] | None, - exc_value: BaseException | None, - tb: TracebackType | None, - ) -> bool | None: - """Unwind the exit stack by calling its :meth:`__exit__` providing the exception - information to allow for exception handling by the various resources registered - using :meth;`with_resource` - - :return: Whatever ``exit_stack.__exit__()`` returns. - """ - exit_result = self._exit_stack.__exit__(exc_type, exc_value, tb) - # In case the context is reused, create a new exit stack. - self._exit_stack = ExitStack() - - return exit_result - - @property - def command_path(self) -> str: - """The computed command path. This is used for the ``usage`` - information on the help page. It's automatically created by - combining the info names of the chain of contexts to the root. - """ - rv = "" - if self.info_name is not None: - rv = self.info_name - if self.parent is not None: - parent_command_path = [self.parent.command_path] - - if isinstance(self.parent.command, Command): - for param in self.parent.command.get_params(self): - parent_command_path.extend(param.get_usage_pieces(self)) - - rv = f"{' '.join(parent_command_path)} {rv}" - return rv.lstrip() - - def find_root(self) -> Context: - """Finds the outermost context.""" - node = self - while node.parent is not None: - node = node.parent - return node - - def find_object(self, object_type: type[V]) -> V | None: - """Finds the closest object of a given type.""" - node: Context | None = self - - while node is not None: - if isinstance(node.obj, object_type): - return node.obj - - node = node.parent - - return None - - def ensure_object(self, object_type: type[V]) -> V: - """Like :meth:`find_object` but sets the innermost object to a - new instance of `object_type` if it does not exist. - """ - rv = self.find_object(object_type) - if rv is None: - self.obj = rv = object_type() - return rv - - def _default_map_has(self, name: str | None) -> bool: - """Check if :attr:`default_map` contains a real value for ``name``. - - Returns ``False`` when the key is absent, the map is ``None``, - ``name`` is ``None``, or the stored value is the internal - :data:`UNSET` sentinel. - """ - return ( - name is not None - and self.default_map is not None - and name in self.default_map - and self.default_map[name] is not UNSET - ) - - @t.overload - def lookup_default( - self, name: str, call: t.Literal[True] = True - ) -> t.Any | None: ... - - @t.overload - def lookup_default( - self, name: str, call: t.Literal[False] = ... - ) -> t.Any | t.Callable[[], t.Any] | None: ... - - def lookup_default(self, name: str, call: bool = True) -> t.Any | None: - """Get the default for a parameter from :attr:`default_map`. - - :param name: Name of the parameter. - :param call: If the default is a callable, call it. Disable to - return the callable instead. - - .. versionchanged:: 8.0 - Added the ``call`` parameter. - """ - if not self._default_map_has(name): - return None - - # Assert to make the type checker happy. - assert self.default_map is not None - value = self.default_map[name] - - if call and callable(value): - return value() - - return value - - def fail(self, message: str) -> t.NoReturn: - """Aborts the execution of the program with a specific error - message. - - :param message: the error message to fail with. - """ - raise UsageError(message, self) - - def abort(self) -> t.NoReturn: - """Aborts the script.""" - raise Abort() - - def exit(self, code: int = 0) -> t.NoReturn: - """Exits the application with a given exit code. - - .. versionchanged:: 8.2 - Callbacks and context managers registered with :meth:`call_on_close` - and :meth:`with_resource` are closed before exiting. - """ - self.close() - raise Exit(code) - - def get_usage(self) -> str: - """Helper method to get formatted usage string for the current - context and command. - """ - return self.command.get_usage(self) - - def get_help(self) -> str: - """Helper method to get formatted help page for the current - context and command. - """ - return self.command.get_help(self) - - def _make_sub_context(self, command: Command) -> Context: - """Create a new context of the same type as this context, but - for a new command. - - :meta private: - """ - return type(self)(command, info_name=command.name, parent=self) - - @t.overload - def invoke( - self, callback: t.Callable[..., V], /, *args: t.Any, **kwargs: t.Any - ) -> V: ... - - @t.overload - def invoke(self, callback: Command, /, *args: t.Any, **kwargs: t.Any) -> t.Any: ... - - def invoke( - self, callback: Command | t.Callable[..., V], /, *args: t.Any, **kwargs: t.Any - ) -> t.Any | V: - """Invokes a command callback in exactly the way it expects. There - are two ways to invoke this method: - - 1. the first argument can be a callback and all other arguments and - keyword arguments are forwarded directly to the function. - 2. the first argument is a click command object. In that case all - arguments are forwarded as well but proper click parameters - (options and click arguments) must be keyword arguments and Click - will fill in defaults. - - .. versionchanged:: 8.0 - All ``kwargs`` are tracked in :attr:`params` so they will be - passed if :meth:`forward` is called at multiple levels. - - .. versionchanged:: 3.2 - A new context is created, and missing arguments use default values. - """ - if isinstance(callback, Command): - other_cmd = callback - - if other_cmd.callback is None: - raise TypeError( - "The given command does not have a callback that can be invoked." - ) - else: - callback = t.cast("t.Callable[..., V]", other_cmd.callback) - - ctx = self._make_sub_context(other_cmd) - - for param in other_cmd.params: - if param.name not in kwargs and param.expose_value: - default_value = param.get_default(ctx) - # We explicitly hide the :attr:`UNSET` value to the user, as we - # choose to make it an implementation detail. And because ``invoke`` - # has been designed as part of Click public API, we return ``None`` - # instead. Refs: - # https://github.com/pallets/click/issues/3066 - # https://github.com/pallets/click/issues/3065 - # https://github.com/pallets/click/pull/3068 - if default_value is UNSET: - default_value = None - kwargs[param.name] = param.type_cast_value(ctx, default_value) - - # Track all kwargs as params, so that forward() will pass - # them on in subsequent calls. - ctx.params.update(kwargs) - else: - ctx = self - - with augment_usage_errors(self): - with ctx: - return callback(*args, **kwargs) - - def forward(self, cmd: Command, /, *args: t.Any, **kwargs: t.Any) -> t.Any: - """Similar to :meth:`invoke` but fills in default keyword - arguments from the current context if the other command expects - it. This cannot invoke callbacks directly, only other commands. - - .. versionchanged:: 8.0 - All ``kwargs`` are tracked in :attr:`params` so they will be - passed if ``forward`` is called at multiple levels. - """ - # Can only forward to other commands, not direct callbacks. - if not isinstance(cmd, Command): - raise TypeError("Callback is not a command.") - - for param in self.params: - if param not in kwargs: - kwargs[param] = self.params[param] - - return self.invoke(cmd, *args, **kwargs) - - def set_parameter_source(self, name: str, source: ParameterSource) -> None: - """Set the source of a parameter. This indicates the location - from which the value of the parameter was obtained. - - :param name: The name of the parameter. - :param source: A member of :class:`~click.core.ParameterSource`. - """ - self._parameter_source[name] = source - - def get_parameter_source(self, name: str) -> ParameterSource | None: - """Get the source of a parameter. This indicates the location - from which the value of the parameter was obtained. - - This can be useful for determining when a user specified a value - on the command line that is the same as the default value. It - will be :attr:`~click.core.ParameterSource.DEFAULT` only if the - value was actually taken from the default. - - :param name: The name of the parameter. - :rtype: ParameterSource - - .. versionchanged:: 8.0 - Returns ``None`` if the parameter was not provided from any - source. - """ - return self._parameter_source.get(name) - - -class Command: - """Commands are the basic building block of command line interfaces in - Click. A basic command handles command line parsing and might dispatch - more parsing to commands nested below it. - - :param name: the name of the command to use unless a group overrides it. - :param context_settings: an optional dictionary with defaults that are - passed to the context object. - :param callback: the callback to invoke. This is optional. - :param params: the parameters to register with this command. This can - be either :class:`Option` or :class:`Argument` objects. - :param help: the help string to use for this command. - :param epilog: like the help string but it's printed at the end of the - help page after everything else. - :param short_help: the short help to use for this command. This is - shown on the command listing of the parent command. - :param add_help_option: by default each command registers a ``--help`` - option. This can be disabled by this parameter. - :param no_args_is_help: this controls what happens if no arguments are - provided. This option is disabled by default. - If enabled this will add ``--help`` as argument - if no arguments are passed - :param hidden: hide this command from help outputs. - :param deprecated: If ``True`` or non-empty string, issues a message - indicating that the command is deprecated and highlights - its deprecation in --help. The message can be customized - by using a string as the value. - - .. versionchanged:: 8.2 - This is the base class for all commands, not ``BaseCommand``. - ``deprecated`` can be set to a string as well to customize the - deprecation message. - - .. versionchanged:: 8.1 - ``help``, ``epilog``, and ``short_help`` are stored unprocessed, - all formatting is done when outputting help text, not at init, - and is done even if not using the ``@command`` decorator. - - .. versionchanged:: 8.0 - Added a ``repr`` showing the command name. - - .. versionchanged:: 7.1 - Added the ``no_args_is_help`` parameter. - - .. versionchanged:: 2.0 - Added the ``context_settings`` parameter. - """ - - #: The context class to create with :meth:`make_context`. - #: - #: .. versionadded:: 8.0 - context_class: type[Context] = Context - - #: the default for the :attr:`Context.allow_extra_args` flag. - allow_extra_args = False - - #: the default for the :attr:`Context.allow_interspersed_args` flag. - allow_interspersed_args = True - - #: the default for the :attr:`Context.ignore_unknown_options` flag. - ignore_unknown_options = False - - def __init__( - self, - name: str | None, - context_settings: cabc.MutableMapping[str, t.Any] | None = None, - callback: t.Callable[..., t.Any] | None = None, - params: list[Parameter] | None = None, - help: str | None = None, - epilog: str | None = None, - short_help: str | None = None, - options_metavar: str | None = "[OPTIONS]", - add_help_option: bool = True, - no_args_is_help: bool = False, - hidden: bool = False, - deprecated: bool | str = False, - ) -> None: - #: the name the command thinks it has. Upon registering a command - #: on a :class:`Group` the group will default the command name - #: with this information. You should instead use the - #: :class:`Context`\'s :attr:`~Context.info_name` attribute. - self.name = name - - if context_settings is None: - context_settings = {} - - #: an optional dictionary with defaults passed to the context. - self.context_settings: cabc.MutableMapping[str, t.Any] = context_settings - - #: the callback to execute when the command fires. This might be - #: `None` in which case nothing happens. - self.callback = callback - #: the list of parameters for this command in the order they - #: should show up in the help page and execute. Eager parameters - #: will automatically be handled before non eager ones. - self.params: list[Parameter] = params or [] - self.help = help - self.epilog = epilog - self.options_metavar = options_metavar - self.short_help = short_help - self.add_help_option = add_help_option - self._help_option = None - self.no_args_is_help = no_args_is_help - self.hidden = hidden - self.deprecated = deprecated - - def to_info_dict(self, ctx: Context) -> dict[str, t.Any]: - return { - "name": self.name, - "params": [param.to_info_dict() for param in self.get_params(ctx)], - "help": self.help, - "epilog": self.epilog, - "short_help": self.short_help, - "hidden": self.hidden, - "deprecated": self.deprecated, - } - - def __repr__(self) -> str: - return f"<{self.__class__.__name__} {self.name}>" - - def get_usage(self, ctx: Context) -> str: - """Formats the usage line into a string and returns it. - - Calls :meth:`format_usage` internally. - """ - formatter = ctx.make_formatter() - self.format_usage(ctx, formatter) - return formatter.getvalue().rstrip("\n") - - def get_params(self, ctx: Context) -> list[Parameter]: - params = self.params - help_option = self.get_help_option(ctx) - - if help_option is not None: - params = [*params, help_option] - - if __debug__: - import warnings - - opts = [opt for param in params for opt in param.opts] - opts_counter = Counter(opts) - duplicate_opts = (opt for opt, count in opts_counter.items() if count > 1) - - for duplicate_opt in duplicate_opts: - warnings.warn( - ( - f"The parameter {duplicate_opt} is used more than once. " - "Remove its duplicate as parameters should be unique." - ), - stacklevel=3, - ) - - return params - - def format_usage(self, ctx: Context, formatter: HelpFormatter) -> None: - """Writes the usage line into the formatter. - - This is a low-level method called by :meth:`get_usage`. - """ - pieces = self.collect_usage_pieces(ctx) - formatter.write_usage(ctx.command_path, " ".join(pieces)) - - def collect_usage_pieces(self, ctx: Context) -> list[str]: - """Returns all the pieces that go into the usage line and returns - it as a list of strings. - """ - rv = [self.options_metavar] if self.options_metavar else [] - - for param in self.get_params(ctx): - rv.extend(param.get_usage_pieces(ctx)) - - return rv - - def get_help_option_names(self, ctx: Context) -> list[str]: - """Returns the names for the help option.""" - all_names = set(ctx.help_option_names) - for param in self.params: - all_names.difference_update(param.opts) - all_names.difference_update(param.secondary_opts) - return list(all_names) - - def get_help_option(self, ctx: Context) -> Option | None: - """Returns the help option object. - - Skipped if :attr:`add_help_option` is ``False``. - - .. versionchanged:: 8.1.8 - The help option is now cached to avoid creating it multiple times. - """ - help_option_names = self.get_help_option_names(ctx) - - if not help_option_names or not self.add_help_option: - return None - - # Cache the help option object in private _help_option attribute to - # avoid creating it multiple times. Not doing this will break the - # callback ordering by iter_params_for_processing(), which relies on - # object comparison. - if self._help_option is None: - # Avoid circular import. - from .decorators import help_option - - # Apply help_option decorator and pop resulting option - help_option(*help_option_names)(self) - self._help_option = self.params.pop() # type: ignore[assignment] - - return self._help_option - - def make_parser(self, ctx: Context) -> _OptionParser: - """Creates the underlying option parser for this command.""" - parser = _OptionParser(ctx) - for param in self.get_params(ctx): - param.add_to_parser(parser, ctx) - return parser - - def get_help(self, ctx: Context) -> str: - """Formats the help into a string and returns it. - - Calls :meth:`format_help` internally. - """ - formatter = ctx.make_formatter() - self.format_help(ctx, formatter) - return formatter.getvalue().rstrip("\n") - - def get_short_help_str(self, limit: int = 45) -> str: - """Gets short help for the command or makes it by shortening the - long help string. - """ - if self.short_help: - text = inspect.cleandoc(self.short_help) - elif self.help: - text = make_default_short_help(self.help, limit) - else: - text = "" - - if self.deprecated: - text = f"{_(text)} {_format_deprecated_label(self.deprecated)}" - - return text.strip() - - def format_help(self, ctx: Context, formatter: HelpFormatter) -> None: - """Writes the help into the formatter if it exists. - - This is a low-level method called by :meth:`get_help`. - - This calls the following methods: - - - :meth:`format_usage` - - :meth:`format_help_text` - - :meth:`format_options` - - :meth:`format_epilog` - """ - self.format_usage(ctx, formatter) - self.format_help_text(ctx, formatter) - self.format_options(ctx, formatter) - self.format_epilog(ctx, formatter) - - def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None: - """Writes the help text to the formatter if it exists.""" - if self.help is not None: - # truncate the help text to the first form feed - text = inspect.cleandoc(self.help).partition("\f")[0] - else: - text = "" - - if self.deprecated: - text = f"{_(text)} {_format_deprecated_label(self.deprecated)}" - - if text: - formatter.write_paragraph() - - with formatter.indentation(): - formatter.write_text(text) - - def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: - """Writes all the options into the formatter if they exist.""" - opts = [] - for param in self.get_params(ctx): - rv = param.get_help_record(ctx) - if rv is not None: - opts.append(rv) - - if opts: - with formatter.section(_("Options")): - formatter.write_dl(opts) - - def format_epilog(self, ctx: Context, formatter: HelpFormatter) -> None: - """Writes the epilog into the formatter if it exists.""" - if self.epilog: - epilog = inspect.cleandoc(self.epilog) - formatter.write_paragraph() - - with formatter.indentation(): - formatter.write_text(epilog) - - def make_context( - self, - info_name: str | None, - args: list[str], - parent: Context | None = None, - **extra: t.Any, - ) -> Context: - """This function when given an info name and arguments will kick - off the parsing and create a new :class:`Context`. It does not - invoke the actual command callback though. - - To quickly customize the context class used without overriding - this method, set the :attr:`context_class` attribute. - - :param info_name: the info name for this invocation. Generally this - is the most descriptive name for the script or - command. For the toplevel script it's usually - the name of the script, for commands below it's - the name of the command. - :param args: the arguments to parse as list of strings. - :param parent: the parent context if available. - :param extra: extra keyword arguments forwarded to the context - constructor. - - .. versionchanged:: 8.0 - Added the :attr:`context_class` attribute. - """ - for key, value in self.context_settings.items(): - if key not in extra: - extra[key] = value - - ctx = self.context_class(self, info_name=info_name, parent=parent, **extra) - - with ctx.scope(cleanup=False): - self.parse_args(ctx, args) - return ctx - - def parse_args(self, ctx: Context, args: list[str]) -> list[str]: - if not args and self.no_args_is_help and not ctx.resilient_parsing: - raise NoArgsIsHelpError(ctx) - - parser = self.make_parser(ctx) - opts, args, param_order = parser.parse_args(args=args) - - for param in iter_params_for_processing(param_order, self.get_params(ctx)): - _, args = param.handle_parse_result(ctx, opts, args) - - # We now have all parameters' values into `ctx.params`, but the data may contain - # the `UNSET` sentinel. - # Convert `UNSET` to `None` to ensure that the user doesn't see `UNSET`. - # - # Waiting until after the initial parse to convert allows us to treat `UNSET` - # more like a missing value when multiple params use the same name. - # Refs: - # https://github.com/pallets/click/issues/3071 - # https://github.com/pallets/click/pull/3079 - for name, value in ctx.params.items(): - if value is UNSET: - ctx.params[name] = None - - if args and not ctx.allow_extra_args and not ctx.resilient_parsing: - ctx.fail( - ngettext( - "Got unexpected extra argument ({args})", - "Got unexpected extra arguments ({args})", - len(args), - ).format(args=" ".join(map(str, args))) - ) - - ctx.args = args - ctx._opt_prefixes.update(parser._opt_prefixes) - return args - - def invoke(self, ctx: Context) -> t.Any: - """Given a context, this invokes the attached callback (if it exists) - in the right way. - """ - if self.deprecated: - message = _( - "DeprecationWarning: The command {name!r} is deprecated.{extra_message}" - ).format( - name=self.name, - extra_message=_format_deprecated_suffix(self.deprecated), - ) - echo(style(message, fg="red"), err=True) - - if self.callback is not None: - return ctx.invoke(self.callback, **ctx.params) - - def shell_complete(self, ctx: Context, incomplete: str) -> list[CompletionItem]: - """Return a list of completions for the incomplete value. Looks - at the names of options and chained multi-commands. - - Any command could be part of a chained multi-command, so sibling - commands are valid at any point during command completion. - - :param ctx: Invocation context for this command. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - from click.shell_completion import CompletionItem - - results: list[CompletionItem] = [] - - if incomplete and not incomplete[0].isalnum(): - for param in self.get_params(ctx): - if ( - not isinstance(param, Option) - or param.hidden - or ( - not param.multiple - and ctx.get_parameter_source(param.name) - is ParameterSource.COMMANDLINE - ) - ): - continue - - results.extend( - CompletionItem(name, help=param.help) - for name in [*param.opts, *param.secondary_opts] - if name.startswith(incomplete) - ) - - while ctx.parent is not None: - ctx = ctx.parent - - if isinstance(ctx.command, Group) and ctx.command.chain: - results.extend( - CompletionItem(name, help=command.get_short_help_str()) - for name, command in _complete_visible_commands(ctx, incomplete) - if name not in ctx._protected_args - ) - - return results - - @t.overload - def main( - self, - args: cabc.Sequence[str] | None = None, - prog_name: str | None = None, - complete_var: str | None = None, - standalone_mode: t.Literal[True] = True, - **extra: t.Any, - ) -> t.NoReturn: ... - - @t.overload - def main( - self, - args: cabc.Sequence[str] | None = None, - prog_name: str | None = None, - complete_var: str | None = None, - standalone_mode: bool = ..., - **extra: t.Any, - ) -> t.Any: ... - - def main( - self, - args: cabc.Sequence[str] | None = None, - prog_name: str | None = None, - complete_var: str | None = None, - standalone_mode: bool = True, - windows_expand_args: bool = True, - **extra: t.Any, - ) -> t.Any: - """This is the way to invoke a script with all the bells and - whistles as a command line application. This will always terminate - the application after a call. If this is not wanted, ``SystemExit`` - needs to be caught. - - This method is also available by directly calling the instance of - a :class:`Command`. - - :param args: the arguments that should be used for parsing. If not - provided, ``sys.argv[1:]`` is used. - :param prog_name: the program name that should be used. By default - the program name is constructed by taking the file - name from ``sys.argv[0]``. - :param complete_var: the environment variable that controls the - bash completion support. The default is - ``"__COMPLETE"`` with prog_name in - uppercase. - :param standalone_mode: the default behavior is to invoke the script - in standalone mode. Click will then - handle exceptions and convert them into - error messages and the function will never - return but shut down the interpreter. If - this is set to `False` they will be - propagated to the caller and the return - value of this function is the return value - of :meth:`invoke`. - :param windows_expand_args: Expand glob patterns, user dir, and - env vars in command line args on Windows. - :param extra: extra keyword arguments are forwarded to the context - constructor. See :class:`Context` for more information. - - .. versionchanged:: 8.0.1 - Added the ``windows_expand_args`` parameter to allow - disabling command line arg expansion on Windows. - - .. versionchanged:: 8.0 - When taking arguments from ``sys.argv`` on Windows, glob - patterns, user dir, and env vars are expanded. - - .. versionchanged:: 3.0 - Added the ``standalone_mode`` parameter. - """ - if args is None: - args = sys.argv[1:] - - if os.name == "nt" and windows_expand_args: - args = _expand_args(args) - else: - args = list(args) - - if prog_name is None: - prog_name = _detect_program_name() - - # Process shell completion requests and exit early. - self._main_shell_completion(extra, prog_name, complete_var) - - try: - try: - with self.make_context(prog_name, args, **extra) as ctx: - rv = self.invoke(ctx) - if not standalone_mode: - return rv - # it's not safe to `ctx.exit(rv)` here! - # note that `rv` may actually contain data like "1" which - # has obvious effects - # more subtle case: `rv=[None, None]` can come out of - # chained commands which all returned `None` -- so it's not - # even always obvious that `rv` indicates success/failure - # by its truthiness/falsiness - ctx.exit() - except (EOFError, KeyboardInterrupt) as e: - echo(file=sys.stderr) - raise Abort() from e - except ClickException as e: - if not standalone_mode: - raise - e.show() - sys.exit(e.exit_code) - except OSError as e: - if e.errno == errno.EPIPE: - sys.stdout = t.cast(t.TextIO, PacifyFlushWrapper(sys.stdout)) - sys.stderr = t.cast(t.TextIO, PacifyFlushWrapper(sys.stderr)) - sys.exit(1) - else: - raise - except Exit as e: - if standalone_mode: - sys.exit(e.exit_code) - else: - # in non-standalone mode, return the exit code - # note that this is only reached if `self.invoke` above raises - # an Exit explicitly -- thus bypassing the check there which - # would return its result - # the results of non-standalone execution may therefore be - # somewhat ambiguous: if there are codepaths which lead to - # `ctx.exit(1)` and to `return 1`, the caller won't be able to - # tell the difference between the two - return e.exit_code - except Abort: - if not standalone_mode: - raise - echo(_("Aborted!"), file=sys.stderr) - sys.exit(1) - - def _main_shell_completion( - self, - ctx_args: cabc.MutableMapping[str, t.Any], - prog_name: str, - complete_var: str | None = None, - ) -> None: - """Check if the shell is asking for tab completion, process - that, then exit early. Called from :meth:`main` before the - program is invoked. - - :param prog_name: Name of the executable in the shell. - :param complete_var: Name of the environment variable that holds - the completion instruction. Defaults to - ``_{PROG_NAME}_COMPLETE``. - - .. versionchanged:: 8.2.0 - Dots (``.``) in ``prog_name`` are replaced with underscores (``_``). - """ - if complete_var is None: - complete_name = prog_name.replace("-", "_").replace(".", "_") - complete_var = f"_{complete_name}_COMPLETE".upper() - - instruction = os.environ.get(complete_var) - - if not instruction: - return - - from .shell_completion import shell_complete - - rv = shell_complete(self, ctx_args, prog_name, complete_var, instruction) - sys.exit(rv) - - def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any: - """Alias for :meth:`main`.""" - return self.main(*args, **kwargs) - - -class _FakeSubclassCheck(type): - def __subclasscheck__(cls, subclass: type) -> bool: - return issubclass(subclass, cls.__bases__[0]) - - def __instancecheck__(cls, instance: t.Any) -> bool: - return isinstance(instance, cls.__bases__[0]) - - -class _BaseCommand(Command, metaclass=_FakeSubclassCheck): - """ - .. deprecated:: 8.2 - Will be removed in Click 9.0. Use ``Command`` instead. - """ - - -class Group(Command): - """A group is a command that nests other commands (or more groups). - - :param name: The name of the group command. - :param commands: Map names to :class:`Command` objects. Can be a list, which - will use :attr:`Command.name` as the keys. - :param invoke_without_command: Invoke the group's callback even if a - subcommand is not given. - :param no_args_is_help: If no arguments are given, show the group's help and - exit. Defaults to the opposite of ``invoke_without_command``. - :param subcommand_metavar: How to represent the subcommand argument in help. - The default will represent whether ``chain`` is set or not. - :param chain: Allow passing more than one subcommand argument. After parsing - a command's arguments, if any arguments remain another command will be - matched, and so on. - :param result_callback: A function to call after the group's and - subcommand's callbacks. The value returned by the subcommand is passed. - If ``chain`` is enabled, the value will be a list of values returned by - all the commands. If ``invoke_without_command`` is enabled, the value - will be the value returned by the group's callback, or an empty list if - ``chain`` is enabled. - :param kwargs: Other arguments passed to :class:`Command`. - - .. versionchanged:: 8.0 - The ``commands`` argument can be a list of command objects. - - .. versionchanged:: 8.2 - Merged with and replaces the ``MultiCommand`` base class. - """ - - allow_extra_args = True - allow_interspersed_args = False - - #: If set, this is used by the group's :meth:`command` decorator - #: as the default :class:`Command` class. This is useful to make all - #: subcommands use a custom command class. - #: - #: .. versionadded:: 8.0 - command_class: type[Command] | None = None - - #: If set, this is used by the group's :meth:`group` decorator - #: as the default :class:`Group` class. This is useful to make all - #: subgroups use a custom group class. - #: - #: If set to the special value :class:`type` (literally - #: ``group_class = type``), this group's class will be used as the - #: default class. This makes a custom group class continue to make - #: custom groups. - #: - #: .. versionadded:: 8.0 - group_class: type[Group] | type[type] | None = None - # Literal[type] isn't valid, so use Type[type] - - def __init__( - self, - name: str | None = None, - commands: cabc.MutableMapping[str, Command] - | cabc.Sequence[Command] - | None = None, - invoke_without_command: bool = False, - no_args_is_help: bool | None = None, - subcommand_metavar: str | None = None, - chain: bool = False, - result_callback: t.Callable[..., t.Any] | None = None, - **kwargs: t.Any, - ) -> None: - super().__init__(name, **kwargs) - - if commands is None: - commands = {} - elif isinstance(commands, abc.Sequence): - commands = {c.name: c for c in commands if c.name is not None} - - #: The registered subcommands by their exported names. - self.commands: cabc.MutableMapping[str, Command] = commands - - if no_args_is_help is None: - no_args_is_help = not invoke_without_command - - self.no_args_is_help = no_args_is_help - self.invoke_without_command = invoke_without_command - - if subcommand_metavar is None: - if chain: - subcommand_metavar = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..." - else: - subcommand_metavar = "COMMAND [ARGS]..." - - self.subcommand_metavar = subcommand_metavar - self.chain = chain - # The result callback that is stored. This can be set or - # overridden with the :func:`result_callback` decorator. - self._result_callback = result_callback - - if self.chain: - for param in self.params: - if isinstance(param, Argument) and not param.required: - raise RuntimeError( - "A group in chain mode cannot have optional arguments." - ) - - def to_info_dict(self, ctx: Context) -> dict[str, t.Any]: - info_dict = super().to_info_dict(ctx) - commands = {} - - for name in self.list_commands(ctx): - command = self.get_command(ctx, name) - - if command is None: - continue - - sub_ctx = ctx._make_sub_context(command) - - with sub_ctx.scope(cleanup=False): - commands[name] = command.to_info_dict(sub_ctx) - - info_dict.update(commands=commands, chain=self.chain) - return info_dict - - def add_command(self, cmd: Command, name: str | None = None) -> None: - """Registers another :class:`Command` with this group. If the name - is not provided, the name of the command is used. - """ - name = name or cmd.name - if name is None: - raise TypeError("Command has no name.") - _check_nested_chain(self, name, cmd, register=True) - self.commands[name] = cmd - - @t.overload - def command(self, __func: t.Callable[..., t.Any]) -> Command: ... - - @t.overload - def command( - self, *args: t.Any, **kwargs: t.Any - ) -> t.Callable[[t.Callable[..., t.Any]], Command]: ... - - def command( - self, *args: t.Any, **kwargs: t.Any - ) -> t.Callable[[t.Callable[..., t.Any]], Command] | Command: - """A shortcut decorator for declaring and attaching a command to - the group. This takes the same arguments as :func:`command` and - immediately registers the created command with this group by - calling :meth:`add_command`. - - To customize the command class used, set the - :attr:`command_class` attribute. - - .. versionchanged:: 8.1 - This decorator can be applied without parentheses. - - .. versionchanged:: 8.0 - Added the :attr:`command_class` attribute. - """ - from .decorators import command - - func: t.Callable[..., t.Any] | None = None - - if args and callable(args[0]): - assert len(args) == 1 and not kwargs, ( - "Use 'command(**kwargs)(callable)' to provide arguments." - ) - (func,) = args - args = () - - if self.command_class and kwargs.get("cls") is None: - kwargs["cls"] = self.command_class - - def decorator(f: t.Callable[..., t.Any]) -> Command: - cmd: Command = command(*args, **kwargs)(f) - self.add_command(cmd) - return cmd - - if func is not None: - return decorator(func) - - return decorator - - @t.overload - def group(self, __func: t.Callable[..., t.Any]) -> Group: ... - - @t.overload - def group( - self, *args: t.Any, **kwargs: t.Any - ) -> t.Callable[[t.Callable[..., t.Any]], Group]: ... - - def group( - self, *args: t.Any, **kwargs: t.Any - ) -> t.Callable[[t.Callable[..., t.Any]], Group] | Group: - """A shortcut decorator for declaring and attaching a group to - the group. This takes the same arguments as :func:`group` and - immediately registers the created group with this group by - calling :meth:`add_command`. - - To customize the group class used, set the :attr:`group_class` - attribute. - - .. versionchanged:: 8.1 - This decorator can be applied without parentheses. - - .. versionchanged:: 8.0 - Added the :attr:`group_class` attribute. - """ - from .decorators import group - - func: t.Callable[..., t.Any] | None = None - - if args and callable(args[0]): - assert len(args) == 1 and not kwargs, ( - "Use 'group(**kwargs)(callable)' to provide arguments." - ) - (func,) = args - args = () - - if self.group_class is not None and kwargs.get("cls") is None: - if self.group_class is type: - kwargs["cls"] = type(self) - else: - kwargs["cls"] = self.group_class - - def decorator(f: t.Callable[..., t.Any]) -> Group: - cmd: Group = group(*args, **kwargs)(f) - self.add_command(cmd) - return cmd - - if func is not None: - return decorator(func) - - return decorator - - def result_callback(self, replace: bool = False) -> t.Callable[[F], F]: - """Adds a result callback to the command. By default if a - result callback is already registered this will chain them but - this can be disabled with the `replace` parameter. The result - callback is invoked with the return value of the subcommand - (or the list of return values from all subcommands if chaining - is enabled) as well as the parameters as they would be passed - to the main callback. - - Example:: - - @click.group() - @click.option('-i', '--input', default=23) - def cli(input): - return 42 - - @cli.result_callback() - def process_result(result, input): - return result + input - - :param replace: if set to `True` an already existing result - callback will be removed. - - .. versionchanged:: 8.0 - Renamed from ``resultcallback``. - - .. versionadded:: 3.0 - """ - - def decorator(f: F) -> F: - old_callback = self._result_callback - - if old_callback is None or replace: - self._result_callback = f - return f - - def function(value: t.Any, /, *args: t.Any, **kwargs: t.Any) -> t.Any: - inner = old_callback(value, *args, **kwargs) - return f(inner, *args, **kwargs) - - self._result_callback = rv = update_wrapper(t.cast(F, function), f) - return rv # type: ignore[return-value] - - return decorator - - def get_command(self, ctx: Context, cmd_name: str) -> Command | None: - """Given a context and a command name, this returns a :class:`Command` - object if it exists or returns ``None``. - """ - return self.commands.get(cmd_name) - - def list_commands(self, ctx: Context) -> list[str]: - """Returns a list of subcommand names in the order they should appear.""" - return sorted(self.commands) - - def collect_usage_pieces(self, ctx: Context) -> list[str]: - rv = super().collect_usage_pieces(ctx) - rv.append(self.subcommand_metavar) - return rv - - def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: - super().format_options(ctx, formatter) - self.format_commands(ctx, formatter) - - def format_commands(self, ctx: Context, formatter: HelpFormatter) -> None: - """Extra format methods for multi methods that adds all the commands - after the options. - """ - commands = [] - for subcommand in self.list_commands(ctx): - cmd = self.get_command(ctx, subcommand) - # What is this, the tool lied about a command. Ignore it - if cmd is None: - continue - if cmd.hidden: - continue - - commands.append((subcommand, cmd)) - - # allow for 3 times the default spacing - if len(commands): - limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands) - - rows = [] - for subcommand, cmd in commands: - help = cmd.get_short_help_str(limit) - rows.append((subcommand, help)) - - if rows: - with formatter.section(_("Commands")): - formatter.write_dl(rows) - - def parse_args(self, ctx: Context, args: list[str]) -> list[str]: - if not args and self.no_args_is_help and not ctx.resilient_parsing: - raise NoArgsIsHelpError(ctx) - - rest = super().parse_args(ctx, args) - - if self.chain: - ctx._protected_args = rest - ctx.args = [] - elif rest: - ctx._protected_args, ctx.args = rest[:1], rest[1:] - - return ctx.args - - def invoke(self, ctx: Context) -> t.Any: - def _process_result(value: t.Any) -> t.Any: - if self._result_callback is not None: - value = ctx.invoke(self._result_callback, value, **ctx.params) - return value - - if not ctx._protected_args: - if self.invoke_without_command: - # No subcommand was invoked, so the result callback is - # invoked with the group return value for regular - # groups, or an empty list for chained groups. - with ctx: - rv = super().invoke(ctx) - return _process_result([] if self.chain else rv) - ctx.fail(_("Missing command.")) - - # Fetch args back out - args = [*ctx._protected_args, *ctx.args] - ctx.args = [] - ctx._protected_args = [] - - # If we're not in chain mode, we only allow the invocation of a - # single command but we also inform the current context about the - # name of the command to invoke. - if not self.chain: - # Make sure the context is entered so we do not clean up - # resources until the result processor has worked. - with ctx: - cmd_name, cmd, args = self.resolve_command(ctx, args) - assert cmd is not None - ctx.invoked_subcommand = cmd_name - super().invoke(ctx) - sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) - with sub_ctx: - return _process_result(sub_ctx.command.invoke(sub_ctx)) - - # In chain mode we create the contexts step by step, but after the - # base command has been invoked. Because at that point we do not - # know the subcommands yet, the invoked subcommand attribute is - # set to ``*`` to inform the command that subcommands are executed - # but nothing else. - with ctx: - ctx.invoked_subcommand = "*" if args else None - super().invoke(ctx) - - # Otherwise we make every single context and invoke them in a - # chain. In that case the return value to the result processor - # is the list of all invoked subcommand's results. - contexts = [] - while args: - cmd_name, cmd, args = self.resolve_command(ctx, args) - assert cmd is not None - sub_ctx = cmd.make_context( - cmd_name, - args, - parent=ctx, - allow_extra_args=True, - allow_interspersed_args=False, - ) - contexts.append(sub_ctx) - args, sub_ctx.args = sub_ctx.args, [] - - rv = [] - for sub_ctx in contexts: - with sub_ctx: - rv.append(sub_ctx.command.invoke(sub_ctx)) - return _process_result(rv) - - def resolve_command( - self, ctx: Context, args: list[str] - ) -> tuple[str | None, Command | None, list[str]]: - cmd_name = make_str(args[0]) - - # Get the command - cmd = self.get_command(ctx, cmd_name) - - # If we can't find the command but there is a normalization - # function available, we try with that one. - if cmd is None and ctx.token_normalize_func is not None: - cmd_name = ctx.token_normalize_func(cmd_name) - cmd = self.get_command(ctx, cmd_name) - - # If we don't find the command we want to show an error message - # to the user that it was not provided. However, there is - # something else we should do: if the first argument looks like - # an option we want to kick off parsing again for arguments to - # resolve things like --help which now should go to the main - # place. - if cmd is None and not ctx.resilient_parsing: - if _split_opt(cmd_name)[0]: - self.parse_args(ctx, args) - raise NoSuchCommand(cmd_name, possibilities=self.commands, ctx=ctx) - return cmd_name if cmd else None, cmd, args[1:] - - def shell_complete(self, ctx: Context, incomplete: str) -> list[CompletionItem]: - """Return a list of completions for the incomplete value. Looks - at the names of options, subcommands, and chained - multi-commands. - - :param ctx: Invocation context for this command. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - from click.shell_completion import CompletionItem - - results = [ - CompletionItem(name, help=command.get_short_help_str()) - for name, command in _complete_visible_commands(ctx, incomplete) - ] - results.extend(super().shell_complete(ctx, incomplete)) - return results - - -class _MultiCommand(Group, metaclass=_FakeSubclassCheck): - """ - .. deprecated:: 8.2 - Will be removed in Click 9.0. Use ``Group`` instead. - """ - - -class CommandCollection(Group): - """A :class:`Group` that looks up subcommands on other groups. If a command - is not found on this group, each registered source is checked in order. - Parameters on a source are not added to this group, and a source's callback - is not invoked when invoking its commands. In other words, this "flattens" - commands in many groups into this one group. - - :param name: The name of the group command. - :param sources: A list of :class:`Group` objects to look up commands from. - :param kwargs: Other arguments passed to :class:`Group`. - - .. versionchanged:: 8.2 - This is a subclass of ``Group``. Commands are looked up first on this - group, then each of its sources. - """ - - def __init__( - self, - name: str | None = None, - sources: list[Group] | None = None, - **kwargs: t.Any, - ) -> None: - super().__init__(name, **kwargs) - #: The list of registered groups. - self.sources: list[Group] = sources or [] - - def add_source(self, group: Group) -> None: - """Add a group as a source of commands.""" - self.sources.append(group) - - def get_command(self, ctx: Context, cmd_name: str) -> Command | None: - rv = super().get_command(ctx, cmd_name) - - if rv is not None: - return rv - - for source in self.sources: - rv = source.get_command(ctx, cmd_name) - - if rv is not None: - if self.chain: - _check_nested_chain(self, cmd_name, rv) - - return rv - - return None - - def list_commands(self, ctx: Context) -> list[str]: - rv: set[str] = set(super().list_commands(ctx)) - - for source in self.sources: - rv.update(source.list_commands(ctx)) - - return sorted(rv) - - -def _check_iter(value: t.Any) -> cabc.Iterator[t.Any]: - """Check if the value is iterable but not a string. Raises a type - error, or return an iterator over the value. - """ - if isinstance(value, str): - raise TypeError - - return iter(value) - - -class Parameter(ABC): - r"""A parameter to a command comes in two versions: they are either - :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently - not supported by design as some of the internals for parsing are - intentionally not finalized. - - Some settings are supported by both options and arguments. - - :param param_decls: the parameter declarations for this option or - argument. This is a list of flags or argument - names. - :param type: the type that should be used. Either a :class:`ParamType` - or a Python type. The latter is converted into the former - automatically if supported. - :param required: controls if this is optional or not. - :param default: the default value if omitted. This can also be a callable, - in which case it's invoked when the default is needed - without any arguments. - :param callback: A function to further process or validate the value - after type conversion. It is called as ``f(ctx, param, value)`` - and must return the value. It is called for all sources, - including prompts. - :param nargs: the number of arguments to match. If not ``1`` the return - value is a tuple instead of single value. The default for - nargs is ``1`` (except if the type is a tuple, then it's - the arity of the tuple). If ``nargs=-1``, all remaining - parameters are collected. - :param metavar: how the value is represented in the help page. - :param expose_value: if this is `True` then the value is passed onwards - to the command callback and stored on the context, - otherwise it's skipped. - :param is_eager: eager values are processed before non eager ones. This - should not be set for arguments or it will inverse the - order of processing. - :param envvar: environment variable(s) that are used to provide a default value for - this parameter. This can be a string or a sequence of strings. If a sequence is - given, only the first non-empty environment variable is used for the parameter. - :param shell_complete: A function that returns custom shell - completions. Used instead of the param's type completion if - given. Takes ``ctx, param, incomplete`` and must return a list - of :class:`~click.shell_completion.CompletionItem` or a list of - strings. - :param deprecated: If ``True`` or non-empty string, issues a message - indicating that the argument is deprecated and highlights - its deprecation in --help. The message can be customized - by using a string as the value. A deprecated parameter - cannot be required, a ValueError will be raised otherwise. - - .. versionchanged:: 8.2.0 - Introduction of ``deprecated``. - - .. versionchanged:: 8.2 - Adding duplicate parameter names to a :class:`~click.core.Command` will - result in a ``UserWarning`` being shown. - - .. versionchanged:: 8.2 - Adding duplicate parameter names to a :class:`~click.core.Command` will - result in a ``UserWarning`` being shown. - - .. versionchanged:: 8.0 - ``process_value`` validates required parameters and bounded - ``nargs``, and invokes the parameter callback before returning - the value. This allows the callback to validate prompts. - ``full_process_value`` is removed. - - .. versionchanged:: 8.0 - ``autocompletion`` is renamed to ``shell_complete`` and has new - semantics described above. The old name is deprecated and will - be removed in 8.1, until then it will be wrapped to match the - new requirements. - - .. versionchanged:: 8.0 - For ``multiple=True, nargs>1``, the default must be a list of - tuples. - - .. versionchanged:: 8.0 - Setting a default is no longer required for ``nargs>1``, it will - default to ``None``. ``multiple=True`` or ``nargs=-1`` will - default to ``()``. - - .. versionchanged:: 7.1 - Empty environment variables are ignored rather than taking the - empty string value. This makes it possible for scripts to clear - variables if they can't unset them. - - .. versionchanged:: 2.0 - Changed signature for parameter callback to also be passed the - parameter. The old callback format will still work, but it will - raise a warning to give you a chance to migrate the code easier. - """ - - param_type_name = "parameter" - - def __init__( - self, - param_decls: cabc.Sequence[str] | None = None, - type: types.ParamType[t.Any] | t.Any | None = None, - required: bool = False, - # XXX The default historically embed two concepts: - # - the declaration of a Parameter object carrying the default (handy to - # arbitrage the default value of coupled Parameters sharing the same - # self.name, like flag options), - # - and the actual value of the default. - # It is confusing and is the source of many issues discussed in: - # https://github.com/pallets/click/pull/3030 - # In the future, we might think of splitting it in two, not unlike - # Option.is_flag and Option.flag_value: we could have something like - # Parameter.is_default and Parameter.default_value. - default: t.Any | t.Callable[[], t.Any] | None = UNSET, - callback: t.Callable[[Context, Parameter, t.Any], t.Any] | None = None, - nargs: int | None = None, - multiple: bool = False, - metavar: str | None = None, - expose_value: bool = True, - is_eager: bool = False, - envvar: str | cabc.Sequence[str] | None = None, - shell_complete: t.Callable[ - [Context, Parameter, str], list[CompletionItem] | list[str] - ] - | None = None, - deprecated: bool | str = False, - ) -> None: - self.name: str - self.opts: list[str] - self.secondary_opts: list[str] - self.name, self.opts, self.secondary_opts = self._parse_decls( - param_decls or (), expose_value - ) - self.type: types.ParamType[t.Any] = types.convert_type(type, default) - - # Default nargs to what the type tells us if we have that - # information available. - if nargs is None: - if self.type.is_composite: - nargs = self.type.arity - else: - nargs = 1 - - self.required = required - self.callback = callback - self.nargs = nargs - self.multiple = multiple - self.expose_value = expose_value - self.default: t.Any | t.Callable[[], t.Any] | None = default - # Whether the user passed ``default`` explicitly to the constructor. - # Captured before any auto-derived default (like ``False`` for boolean - # flags in :class:`Option`) replaces the :data:`UNSET` sentinel, so it - # remains ``False`` when the default was inferred rather than chosen. - # Refs: https://github.com/pallets/click/issues/3403 - self._default_explicit: bool = default is not UNSET - self.is_eager = is_eager - self.metavar = metavar - self.envvar = envvar - self._custom_shell_complete = shell_complete - self.deprecated = deprecated - - if __debug__: - if self.type.is_composite and nargs != self.type.arity: - raise ValueError( - f"'nargs' must be {self.type.arity} (or None) for" - f" type {self.type!r}, but it was {nargs}." - ) - - if required and deprecated: - raise ValueError( - f"The {self.param_type_name} '{self.human_readable_name}' " - "is deprecated and still required. A deprecated " - f"{self.param_type_name} cannot be required." - ) - - def to_info_dict(self) -> dict[str, t.Any]: - """Gather information that could be useful for a tool generating - user-facing documentation. - - Use :meth:`click.Context.to_info_dict` to traverse the entire - CLI structure. - - .. versionchanged:: 8.3.0 - Returns ``None`` for the :attr:`default` if it was not set. - - .. versionadded:: 8.0 - """ - return { - "name": self.name, - "param_type_name": self.param_type_name, - "opts": self.opts, - "secondary_opts": self.secondary_opts, - "type": self.type.to_info_dict(), - "required": self.required, - "nargs": self.nargs, - "multiple": self.multiple, - # We explicitly hide the :attr:`UNSET` value to the user, as we choose to - # make it an implementation detail. And because ``to_info_dict`` has been - # designed for documentation purposes, we return ``None`` instead. - "default": self.default if self.default is not UNSET else None, - "envvar": self.envvar, - } - - def __repr__(self) -> str: - return f"<{self.__class__.__name__} {self.name}>" - - @abstractmethod - def _parse_decls( - self, decls: cabc.Sequence[str], expose_value: bool - ) -> tuple[str, list[str], list[str]]: ... - - @property - def human_readable_name(self) -> str: - """Returns the human readable name of this parameter. This is the - same as the name for options, but the metavar for arguments. - """ - return self.name - - def make_metavar(self, ctx: Context) -> str: - if self.metavar is not None: - return self.metavar - - metavar = self.type.get_metavar(param=self, ctx=ctx) - - if metavar is None: - metavar = self.type.name.upper() - - if self.nargs != 1: - metavar += "..." - - return metavar - - @t.overload - def get_default( - self, ctx: Context, call: t.Literal[True] = True - ) -> t.Any | None: ... - - @t.overload - def get_default( - self, ctx: Context, call: bool = ... - ) -> t.Any | t.Callable[[], t.Any] | None: ... - - def get_default( - self, ctx: Context, call: bool = True - ) -> t.Any | t.Callable[[], t.Any] | None: - """Get the default for the parameter. Tries - :meth:`Context.lookup_default` first, then the local default. - - :param ctx: Current context. - :param call: If the default is a callable, call it. Disable to - return the callable instead. - - .. versionchanged:: 8.0.2 - Type casting is no longer performed when getting a default. - - .. versionchanged:: 8.0.1 - Type casting can fail in resilient parsing mode. Invalid - defaults will not prevent showing help text. - - .. versionchanged:: 8.0 - Looks at ``ctx.default_map`` first. - - .. versionchanged:: 8.0 - Added the ``call`` parameter. - """ - value = ctx.lookup_default(self.name, call=False) - - if value is None and not ctx._default_map_has(self.name): - value = self.default - - if call and callable(value): - value = value() - - return value - - @abstractmethod - def add_to_parser(self, parser: _OptionParser, ctx: Context) -> None: ... - - def consume_value( - self, ctx: Context, opts: cabc.Mapping[str, t.Any] - ) -> tuple[t.Any, ParameterSource]: - """Returns the parameter value produced by the parser. - - If the parser did not produce a value from user input, the value is either - sourced from the environment variable, the default map, or the parameter's - default value. In that order of precedence. - - If no value is found, an internal sentinel value is returned. - - :meta private: - """ - # Collect from the parse the value passed by the user to the CLI. - value = opts.get(self.name, UNSET) - # If the value is set, it means it was sourced from the command line by the - # parser, otherwise it left unset by default. - source = ( - ParameterSource.COMMANDLINE - if value is not UNSET - else ParameterSource.DEFAULT - ) - - if value is UNSET: - envvar_value = self.value_from_envvar(ctx) - if envvar_value is not None: - value = envvar_value - source = ParameterSource.ENVIRONMENT - - if value is UNSET: - default_map_value = ctx.lookup_default(self.name) - if default_map_value is not None or ctx._default_map_has(self.name): - value = default_map_value - source = ParameterSource.DEFAULT_MAP - - # A string from default_map must be split for multi-value - # parameters, matching value_from_envvar behavior. - if isinstance(value, str) and self.nargs != 1: - value = self.type.split_envvar_value(value) - - if value is UNSET: - default_value = self.get_default(ctx) - if default_value is not UNSET: - value = default_value - source = ParameterSource.DEFAULT - - return value, source - - def type_cast_value(self, ctx: Context, value: t.Any) -> t.Any: - """Convert and validate a value against the parameter's - :attr:`type`, :attr:`multiple`, and :attr:`nargs`. - """ - if value is None: - if self.multiple or self.nargs == -1: - return () - else: - return value - - def check_iter(value: t.Any) -> cabc.Iterator[t.Any]: - try: - return _check_iter(value) - except TypeError: - # This should only happen when passing in args manually, - # the parser should construct an iterable when parsing - # the command line. - raise BadParameter( - _("Value must be an iterable."), ctx=ctx, param=self - ) from None - - # Define the conversion function based on nargs and type. - - if self.nargs == 1 or self.type.is_composite: - - def convert(value: t.Any) -> t.Any: - return self.type(value, param=self, ctx=ctx) - - elif self.nargs == -1: - - def convert(value: t.Any) -> t.Any: # tuple[t.Any, ...] - return tuple(self.type(x, self, ctx) for x in check_iter(value)) - - else: # nargs > 1 - - def convert(value: t.Any) -> t.Any: # tuple[t.Any, ...] - value = tuple(check_iter(value)) - - if len(value) != self.nargs: - raise BadParameter( - ngettext( - "Takes {nargs} values but 1 was given.", - "Takes {nargs} values but {len} were given.", - len(value), - ).format(nargs=self.nargs, len=len(value)), - ctx=ctx, - param=self, - ) - - return tuple(self.type(x, self, ctx) for x in value) - - if self.multiple: - return tuple(convert(x) for x in check_iter(value)) - - return convert(value) - - def value_is_missing(self, value: t.Any) -> bool: - """A value is considered missing if: - - - it is :attr:`UNSET`, - - or if it is an empty sequence while the parameter is suppose to have - non-single value (i.e. :attr:`nargs` is not ``1`` or :attr:`multiple` is - set). - - :meta private: - """ - if value is UNSET: - return True - - if (self.nargs != 1 or self.multiple) and value == (): - return True - - return False - - def process_value(self, ctx: Context, value: t.Any) -> t.Any: - """Process the value of this parameter: - - 1. Type cast the value using :meth:`type_cast_value`. - 2. Check if the value is missing (see: :meth:`value_is_missing`), and raise - :exc:`MissingParameter` if it is required. - 3. If a :attr:`callback` is set, call it to have the value replaced by the - result of the callback. If the value was not set, the callback receive - ``None``. This keep the legacy behavior as it was before the introduction of - the :attr:`UNSET` sentinel. - - :meta private: - """ - # shelter `type_cast_value` from ever seeing an `UNSET` value by handling the - # cases in which `UNSET` gets special treatment explicitly at this layer - # - # Refs: - # https://github.com/pallets/click/issues/3069 - if value is UNSET: - if self.multiple or self.nargs == -1: - value = () - else: - value = self.type_cast_value(ctx, value) - - if self.required and self.value_is_missing(value): - raise MissingParameter(ctx=ctx, param=self) - - if self.callback is not None: - # Legacy case: UNSET is not exposed directly to the callback, but converted - # to None. - if value is UNSET: - value = None - - # Search for parameters with UNSET values in the context. - unset_keys = {k: None for k, v in ctx.params.items() if v is UNSET} - # No UNSET values, call the callback as usual. - if not unset_keys: - value = self.callback(ctx, self, value) - - # Legacy case: provide a temporarily manipulated context to the callback - # to hide UNSET values as None. - # - # Refs: - # https://github.com/pallets/click/issues/3136 - # https://github.com/pallets/click/pull/3137 - else: - # Add another layer to the context stack to clearly hint that the - # context is temporarily modified. - with ctx: - # Update the context parameters to replace UNSET with None. - ctx.params.update(unset_keys) - # Feed these fake context parameters to the callback. - value = self.callback(ctx, self, value) - # Restore the UNSET values in the context parameters. - ctx.params.update( - { - k: UNSET - for k in unset_keys - # Only restore keys that are present and still None, in case - # the callback modified other parameters. - if k in ctx.params and ctx.params[k] is None - } - ) - - return value - - def resolve_envvar_value(self, ctx: Context) -> str | None: - """Returns the value found in the environment variable(s) attached to this - parameter. - - Environment variables values are `always returned as strings - `_. - - This method returns ``None`` if: - - - the :attr:`envvar` property is not set on the :class:`Parameter`, - - the environment variable is not found in the environment, - - the variable is found in the environment but its value is empty (i.e. the - environment variable is present but has an empty string). - - If :attr:`envvar` is setup with multiple environment variables, - then only the first non-empty value is returned. - - .. caution:: - - The raw value extracted from the environment is not normalized and is - returned as-is. Any normalization or reconciliation is performed later by - the :class:`Parameter`'s :attr:`type`. - - :meta private: - """ - if not self.envvar: - return None - - if isinstance(self.envvar, str): - rv = os.environ.get(self.envvar) - - if rv: - return rv - else: - for envvar in self.envvar: - rv = os.environ.get(envvar) - - # Return the first non-empty value of the list of environment variables. - if rv: - return rv - # Else, absence of value is interpreted as an environment variable that - # is not set, so proceed to the next one. - - return None - - def value_from_envvar(self, ctx: Context) -> str | cabc.Sequence[str] | None: - """Process the raw environment variable string for this parameter. - - Returns the string as-is or splits it into a sequence of strings if the - parameter is expecting multiple values (i.e. its :attr:`nargs` property is set - to a value other than ``1``). - - :meta private: - """ - rv = self.resolve_envvar_value(ctx) - - if rv is not None and self.nargs != 1: - return self.type.split_envvar_value(rv) - - return rv - - def handle_parse_result( - self, ctx: Context, opts: cabc.Mapping[str, t.Any], args: list[str] - ) -> tuple[t.Any, list[str]]: - """Process the value produced by the parser from user input. - - Always process the value through the Parameter's :attr:`type`, wherever it - comes from. - - If the parameter is deprecated, this method warn the user about it. But only if - the value has been explicitly set by the user (and as such, is not coming from - a default). - - :meta private: - """ - # Capture the slot's existing state before we mutate - # ``_parameter_source`` so the write decision below can compare our - # incoming source against the source of the option that already wrote - # the slot (if any). - existing_value = ctx.params.get(self.name, UNSET) - existing_source = ctx.get_parameter_source(self.name) - existing_default_explicit = ctx._param_default_explicit.get(self.name, False) - - with augment_usage_errors(ctx, param=self): - value, source = self.consume_value(ctx, opts) - - # Record the source before processing so eager callbacks and type - # conversion can inspect it. Restored after arbitration if this - # option loses a feature-switch group. - ctx.set_parameter_source(self.name, source) - - # Display a deprecation warning if necessary. - if ( - self.deprecated - and value is not UNSET - and source < ParameterSource.DEFAULT_MAP - ): - message = _( - "DeprecationWarning: The {param_type} {name!r} is deprecated." - "{extra_message}" - ).format( - param_type=self.param_type_name, - name=self.human_readable_name, - extra_message=_format_deprecated_suffix(self.deprecated), - ) - echo(style(message, fg="red"), err=True) - - # Process the value through the parameter's type. - try: - value = self.process_value(ctx, value) - except Exception: - if not ctx.resilient_parsing: - raise - # In resilient parsing mode, we do not want to fail the command if the - # value is incompatible with the parameter type, so we reset the value - # to UNSET, which will be interpreted as a missing value. - value = UNSET - - # Arbitrate the slot when several parameters target the same variable - # name (feature-switch groups). See: https://github.com/pallets/click/issues/3403 - slot_empty = existing_value is UNSET - more_explicit = existing_source is not None and source < existing_source - same_source = existing_source is not None and source == existing_source - auto_would_downgrade_explicit = ( - same_source - and source == ParameterSource.DEFAULT - and existing_default_explicit - and not self._default_explicit - ) - is_winner = ( - slot_empty - or more_explicit - or (same_source and not auto_would_downgrade_explicit) - ) - - if is_winner: - if self.expose_value: - ctx.params[self.name] = value - ctx._param_default_explicit[self.name] = self._default_explicit - elif existing_source is not None: - # Lost arbitration; restore the winning option's source. - ctx.set_parameter_source(self.name, existing_source) - # else: ctx.params[self.name] was populated by code that bypassed - # handle_parse_result (from another option's callback for example). Keep - # the provisional source recorded before process_value so downstream - # lookups don't return ``None``. - - return value, args - - def get_help_record(self, ctx: Context) -> tuple[str, str] | None: - return None - - def get_usage_pieces(self, ctx: Context) -> list[str]: - return [] - - def get_error_hint(self, ctx: Context | None) -> str: - """Get a stringified version of the param for use in error messages to - indicate which param caused the error. - - .. versionchanged:: 8.4.0 - ``ctx`` can be ``None``. - """ - hint_list = self.opts or [self.human_readable_name] - return " / ".join(f"'{x}'" for x in hint_list) - - def shell_complete(self, ctx: Context, incomplete: str) -> list[CompletionItem]: - """Return a list of completions for the incomplete value. If a - ``shell_complete`` function was given during init, it is used. - Otherwise, the :attr:`type` - :meth:`~click.types.ParamType[t.Any].shell_complete` function is used. - - :param ctx: Invocation context for this command. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - if self._custom_shell_complete is not None: - results = self._custom_shell_complete(ctx, self, incomplete) - - if results and isinstance(results[0], str): - from click.shell_completion import CompletionItem - - results = [CompletionItem(c) for c in results] - - return t.cast("list[CompletionItem]", results) - - return self.type.shell_complete(ctx, self, incomplete) - - -class Option(Parameter): - """Options are usually optional values on the command line and - have some extra features that arguments don't have. - - All other parameters are passed onwards to the parameter constructor. - - :param show_default: Show the default value for this option in its - help text. Values are not shown by default, unless - :attr:`Context.show_default` is ``True``. If this value is a - string, it shows that string in parentheses instead of the - actual value. This is particularly useful for dynamic options. - For single option boolean flags, the default remains hidden if - its value is ``False``. - :param show_envvar: Controls if an environment variable should be - shown on the help page and error messages. - Normally, environment variables are not shown. - :param prompt: If set to ``True`` or a non empty string then the - user will be prompted for input. If set to ``True`` the prompt - will be the option name capitalized. A deprecated option cannot be - prompted. - :param confirmation_prompt: Prompt a second time to confirm the - value if it was prompted for. Can be set to a string instead of - ``True`` to customize the message. - :param prompt_required: If set to ``False``, the user will be - prompted for input only when the option was specified as a flag - without a value. - :param hide_input: If this is ``True`` then the input on the prompt - will be hidden from the user. This is useful for password input. - :param is_flag: forces this option to act as a flag. The default is - auto detection. - :param flag_value: which value should be used for this flag if it's - enabled. This is set to a boolean automatically if - the option string contains a slash to mark two options. - :param multiple: if this is set to `True` then the argument is accepted - multiple times and recorded. This is similar to ``nargs`` - in how it works but supports arbitrary number of - arguments. - :param count: this flag makes an option increment an integer. - :param allow_from_autoenv: if this is enabled then the value of this - parameter will be pulled from an environment - variable in case a prefix is defined on the - context. - :param help: the help string. - :param hidden: hide this option from help outputs. - :param attrs: Other command arguments described in :class:`Parameter`. - - .. versionchanged:: 8.4.0 - Non-basic ``flag_value`` types (not ``str``, ``int``, ``float``, or - ``bool``) are passed through unchanged instead of being stringified. - Previously, ``type=click.UNPROCESSED`` was required to preserve them. - - .. versionchanged:: 8.2 - ``envvar`` used with ``flag_value`` will always use the ``flag_value``, - previously it would use the value of the environment variable. - - .. versionchanged:: 8.1 - Help text indentation is cleaned here instead of only in the - ``@option`` decorator. - - .. versionchanged:: 8.1 - The ``show_default`` parameter overrides - ``Context.show_default``. - - .. versionchanged:: 8.1 - The default of a single option boolean flag is not shown if the - default value is ``False``. - - .. versionchanged:: 8.0.1 - ``type`` is detected from ``flag_value`` if given, for basic Python - types (``str``, ``int``, ``float``, ``bool``). - """ - - param_type_name = "option" - - def __init__( - self, - param_decls: cabc.Sequence[str] | None = None, - show_default: bool | str | None = None, - prompt: bool | str = False, - confirmation_prompt: bool | str = False, - prompt_required: bool = True, - hide_input: bool = False, - is_flag: bool | None = None, - flag_value: t.Any = UNSET, - multiple: bool = False, - count: bool = False, - allow_from_autoenv: bool = True, - type: types.ParamType[t.Any] | t.Any | None = None, - help: str | None = None, - hidden: bool = False, - show_choices: bool = True, - show_envvar: bool = False, - deprecated: bool | str = False, - **attrs: t.Any, - ) -> None: - if help: - help = inspect.cleandoc(help) - - super().__init__( - param_decls, type=type, multiple=multiple, deprecated=deprecated, **attrs - ) - - if prompt is True: - if not self.name: - raise TypeError("'name' is required with 'prompt=True'.") - - prompt_text: str | None = self.name.replace("_", " ").capitalize() - elif prompt is False: - prompt_text = None - else: - prompt_text = prompt - - if deprecated: - label = _format_deprecated_label(deprecated) - help = f"{help} {label}" if help is not None else label - - self.prompt = prompt_text - self.confirmation_prompt = confirmation_prompt - self.prompt_required = prompt_required - self.hide_input = hide_input - self.hidden = hidden - - # The _flag_needs_value property tells the parser that this option is a flag - # that cannot be used standalone and needs a value. With this information, the - # parser can determine whether to consider the next user-provided argument in - # the CLI as a value for this flag or as a new option. - # If prompt is enabled but not required, then it opens the possibility for the - # option to gets its value from the user. - self._flag_needs_value = self.prompt is not None and not self.prompt_required - - # Auto-detect if this is a flag or not. - if is_flag is None: - # Implicitly a flag because flag_value was set. - if flag_value is not UNSET: - is_flag = True - # Not a flag, but when used as a flag it shows a prompt. - elif self._flag_needs_value: - is_flag = False - # Implicitly a flag because secondary options names were given. - elif self.secondary_opts: - is_flag = True - - # The option is explicitly not a flag, but to determine whether or not it needs - # value, we need to check if `flag_value` or `default` was set. Either one is - # sufficient. - # Ref: https://github.com/pallets/click/issues/3084 - elif is_flag is False and not self._flag_needs_value: - self._flag_needs_value = flag_value is not UNSET or self.default is UNSET - - if is_flag: - # Set missing default for flags if not explicitly required or prompted. - if self.default is UNSET and not self.required and not self.prompt: - if multiple: - self.default = () - - # Auto-detect the type of the flag based on the flag_value. - if type is None: - # A flag without a flag_value is a boolean flag. - if flag_value is UNSET: - self.type: types.ParamType[t.Any] = types.BoolParamType() - # If the flag value is a boolean, use BoolParamType. - elif isinstance(flag_value, bool): - self.type = types.BoolParamType() - # Otherwise, guess the type from the flag value. - else: - guessed = types.convert_type(None, flag_value) - if ( - isinstance(guessed, types.StringParamType) - and not isinstance(flag_value, str) - and flag_value is not None - ): - # The flag_value type couldn't be auto-detected - # (not str, int, float, or bool). Since flag_value - # is a programmer-provided Python object, not CLI - # input, pass it through unchanged instead of - # stringifying it. - self.type = types.UNPROCESSED - else: - self.type = guessed - - self.is_flag: bool = bool(is_flag) - self.is_bool_flag: bool = bool( - is_flag and isinstance(self.type, types.BoolParamType) - ) - self.flag_value: t.Any = flag_value - - # Set boolean flag default to False if unset and not required. - if self.is_bool_flag: - if self.default is UNSET and not self.required: - self.default = False - - # The alignment of default to the flag_value is resolved lazily in - # get_default() to prevent callable flag_values (like classes) from - # being instantiated. Refs: - # https://github.com/pallets/click/issues/3121 - # https://github.com/pallets/click/issues/3024#issuecomment-3146199461 - # https://github.com/pallets/click/pull/3030/commits/06847da - - # Set the default flag_value if it is not set. - if self.flag_value is UNSET: - if self.is_flag: - self.flag_value = True - else: - self.flag_value = None - - # Counting. - self.count = count - if count: - if type is None: - self.type = types.IntRange(min=0) - if self.default is UNSET: - self.default = 0 - - self.allow_from_autoenv = allow_from_autoenv - self.help = help - self.show_default = show_default - self.show_choices = show_choices - self.show_envvar = show_envvar - - if __debug__: - if deprecated and prompt: - raise ValueError("`deprecated` options cannot use `prompt`.") - - if self.nargs == -1: - raise TypeError("nargs=-1 is not supported for options.") - - if not self.is_bool_flag and self.secondary_opts: - raise TypeError("Secondary flag is not valid for non-boolean flag.") - - if self.is_bool_flag and self.hide_input and self.prompt is not None: - raise TypeError( - "'prompt' with 'hide_input' is not valid for boolean flag." - ) - - if self.count: - if self.multiple: - raise TypeError("'count' is not valid with 'multiple'.") - - if self.is_flag: - raise TypeError("'count' is not valid with 'is_flag'.") - - def to_info_dict(self) -> dict[str, t.Any]: - """ - .. versionchanged:: 8.3.0 - Returns ``None`` for the :attr:`flag_value` if it was not set. - """ - info_dict = super().to_info_dict() - info_dict.update( - help=self.help, - prompt=self.prompt, - is_flag=self.is_flag, - # We explicitly hide the :attr:`UNSET` value to the user, as we choose to - # make it an implementation detail. And because ``to_info_dict`` has been - # designed for documentation purposes, we return ``None`` instead. - flag_value=self.flag_value if self.flag_value is not UNSET else None, - count=self.count, - hidden=self.hidden, - ) - return info_dict - - def get_default( - self, ctx: Context, call: bool = True - ) -> t.Any | t.Callable[[], t.Any] | None: - """Return the default value for this option. - - For non-boolean flag options, ``default=True`` is treated as a sentinel - meaning "activate this flag by default" and is resolved to - :attr:`flag_value`. For example, with ``--upper/--lower`` feature - switches where ``flag_value="upper"`` and ``default=True``, the default - resolves to ``"upper"``. - - .. caution:: - This substitution only applies to non-boolean flags - (:attr:`is_bool_flag` is ``False``). For boolean flags, ``True`` is - a legitimate Python value and ``default=True`` is returned as-is. - - .. versionchanged:: 8.3.3 - ``default=True`` is no longer substituted with ``flag_value`` for - boolean flags, fixing negative boolean flags like - ``flag_value=False, default=True``. - """ - value = super().get_default(ctx, call=False) - - # Resolve default=True to flag_value lazily (here instead of - # __init__) to prevent callable flag_values (like classes) from - # being instantiated by the callable check below. - if value is True and self.is_flag and not self.is_bool_flag: - value = self.flag_value - elif call and callable(value): - value = value() - - return value - - def get_error_hint(self, ctx: Context | None) -> str: - result = super().get_error_hint(ctx) - if self.show_envvar and self.envvar is not None: - result += f" (env var: '{self.envvar}')" - return result - - def _parse_decls( - self, decls: cabc.Sequence[str], expose_value: bool - ) -> tuple[str, list[str], list[str]]: - opts = [] - secondary_opts = [] - name = None - possible_names = [] - - for decl in decls: - if decl.isidentifier(): - if name is not None: - raise TypeError(_("Name '{name}' defined twice").format(name=name)) - name = decl - else: - split_char = ";" if decl[:1] == "/" else "/" - if split_char in decl: - first, second = decl.split(split_char, 1) - first = first.rstrip() - if first: - possible_names.append(_split_opt(first)) - opts.append(first) - second = second.lstrip() - if second: - secondary_opts.append(second.lstrip()) - if first == second: - raise ValueError( - _( - "Boolean option {decl!r} cannot use the" - " same flag for true/false." - ).format(decl=decl) - ) - else: - possible_names.append(_split_opt(decl)) - opts.append(decl) - - if name is None and possible_names: - possible_names.sort(key=lambda x: -len(x[0])) # group long options first - name = possible_names[0][1].replace("-", "_").lower() - if not name.isidentifier(): - name = None - - if name is None: - if not expose_value: - return "", opts, secondary_opts - raise TypeError( - _( - "Could not determine name for option with declarations {decls!r}" - ).format(decls=decls) - ) - - if not opts and not secondary_opts: - raise TypeError( - _( - "No options defined but a name was passed ({name})." - " Did you mean to declare an argument instead? Did" - " you mean to pass '--{name}'?" - ).format(name=name) - ) - - return name, opts, secondary_opts - - def add_to_parser(self, parser: _OptionParser, ctx: Context) -> None: - if self.multiple: - action = "append" - elif self.count: - action = "count" - else: - action = "store" - - if self.is_flag: - action = f"{action}_const" - - if self.is_bool_flag and self.secondary_opts: - parser.add_option( - obj=self, opts=self.opts, dest=self.name, action=action, const=True - ) - parser.add_option( - obj=self, - opts=self.secondary_opts, - dest=self.name, - action=action, - const=False, - ) - else: - parser.add_option( - obj=self, - opts=self.opts, - dest=self.name, - action=action, - const=self.flag_value, - ) - else: - parser.add_option( - obj=self, - opts=self.opts, - dest=self.name, - action=action, - nargs=self.nargs, - ) - - def get_help_record(self, ctx: Context) -> tuple[str, str] | None: - if self.hidden: - return None - - any_prefix_is_slash = False - - def _write_opts(opts: cabc.Sequence[str]) -> str: - nonlocal any_prefix_is_slash - - rv, any_slashes = join_options(opts) - - if any_slashes: - any_prefix_is_slash = True - - if not self.is_flag and not self.count: - rv += f" {self.make_metavar(ctx=ctx)}" - - return rv - - rv = [_write_opts(self.opts)] - - if self.secondary_opts: - rv.append(_write_opts(self.secondary_opts)) - - help = self.help or "" - - extra = self.get_help_extra(ctx) - extra_items = [] - if "envvars" in extra: - extra_items.append( - _("env var: {var}").format(var=", ".join(extra["envvars"])) - ) - if "default" in extra: - extra_items.append(_("default: {default}").format(default=extra["default"])) - if "range" in extra: - extra_items.append(extra["range"]) - if "required" in extra: - extra_items.append(_(extra["required"])) - - if extra_items: - extra_str = "; ".join(extra_items) - help = f"{help} [{extra_str}]" if help else f"[{extra_str}]" - - return ("; " if any_prefix_is_slash else " / ").join(rv), help - - def get_help_extra(self, ctx: Context) -> types.OptionHelpExtra: - extra: types.OptionHelpExtra = {} - - if self.show_envvar: - envvar = self.envvar - - if envvar is None: - if ( - self.allow_from_autoenv - and ctx.auto_envvar_prefix is not None - and self.name - ): - envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" - - if envvar is not None: - if isinstance(envvar, str): - extra["envvars"] = (envvar,) - else: - extra["envvars"] = tuple(str(d) for d in envvar) - - # Temporarily enable resilient parsing to avoid type casting - # failing for the default. Might be possible to extend this to - # help formatting in general. - resilient = ctx.resilient_parsing - ctx.resilient_parsing = True - - try: - default_value = self.get_default(ctx, call=False) - finally: - ctx.resilient_parsing = resilient - - show_default = False - show_default_is_str = False - - if self.show_default is not None: - if isinstance(self.show_default, str): - show_default_is_str = show_default = True - else: - show_default = self.show_default - elif ctx.show_default is not None: - show_default = ctx.show_default - - if show_default_is_str or ( - show_default and (default_value not in (None, UNSET)) - ): - if show_default_is_str: - default_string = f"({self.show_default})" - elif isinstance(default_value, (list, tuple)): - default_string = ", ".join(str(d) for d in default_value) - elif isinstance(default_value, enum.Enum): - default_string = default_value.name - elif inspect.isfunction(default_value): - default_string = _("(dynamic)") - elif self.is_bool_flag and self.secondary_opts: - # For boolean flags that have distinct True/False opts, - # use the opt without prefix instead of the value. - default_string = _split_opt( - (self.opts if default_value else self.secondary_opts)[0] - )[1] - elif self.is_bool_flag and not self.secondary_opts and not default_value: - default_string = "" - elif isinstance(default_value, str) and default_value == "": - default_string = '""' - else: - default_string = str(default_value) - - if default_string: - extra["default"] = default_string - - if ( - isinstance(self.type, types._NumberRangeBase) - # skip count with default range type - and not (self.count and self.type.min == 0 and self.type.max is None) - ): - range_str = self.type._describe_range() - - if range_str: - extra["range"] = range_str - - if self.required: - extra["required"] = "required" - - return extra - - def prompt_for_value(self, ctx: Context) -> t.Any: - """This is an alternative flow that can be activated in the full - value processing if a value does not exist. It will prompt the - user until a valid value exists and then returns the processed - value as result. - """ - assert self.prompt is not None - - # Calculate the default before prompting anything to lock in the value before - # attempting any user interaction. - default = self.get_default(ctx) - - # A boolean flag can use a simplified [y/n] confirmation prompt. - if self.is_bool_flag: - # If we have no boolean default, we force the user to explicitly provide - # one. - if default in (UNSET, None): - default = None - # Nothing prevent you to declare an option that is simultaneously: - # 1) auto-detected as a boolean flag, - # 2) allowed to prompt, and - # 3) still declare a non-boolean default. - # This forced casting into a boolean is necessary to align any non-boolean - # default to the prompt, which is going to be a [y/n]-style confirmation - # because the option is still a boolean flag. That way, instead of [y/n], - # we get [Y/n] or [y/N] depending on the truthy value of the default. - # Refs: https://github.com/pallets/click/pull/3030#discussion_r2289180249 - else: - default = bool(default) - return confirm(self.prompt, default) - - # If show_default is given, provide this to `prompt` as well, - # otherwise we use `prompt`'s default behavior - prompt_kwargs: t.Any = {} - if self.show_default is not None: - prompt_kwargs["show_default"] = self.show_default - - return prompt( - self.prompt, - # Use ``None`` to inform the prompt() function to reiterate until a valid - # value is provided by the user if we have no default. - default=None if default is UNSET else default, - type=self.type, - hide_input=self.hide_input, - show_choices=self.show_choices, - confirmation_prompt=self.confirmation_prompt, - value_proc=lambda x: self.process_value(ctx, x), - **prompt_kwargs, - ) - - def resolve_envvar_value(self, ctx: Context) -> str | None: - """:class:`Option` resolves its environment variable the same way as - :func:`Parameter.resolve_envvar_value`, but it also supports - :attr:`Context.auto_envvar_prefix`. If we could not find an environment from - the :attr:`envvar` property, we fallback on :attr:`Context.auto_envvar_prefix` - to build dynamiccaly the environment variable name using the - :python:`{ctx.auto_envvar_prefix}_{self.name.upper()}` template. - - :meta private: - """ - rv = super().resolve_envvar_value(ctx) - - if rv is not None: - return rv - - if self.allow_from_autoenv and ctx.auto_envvar_prefix is not None and self.name: - envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" - rv = os.environ.get(envvar) - - if rv: - return rv - - return None - - def value_from_envvar(self, ctx: Context) -> t.Any: - """For :class:`Option`, this method processes the raw environment variable - string the same way as :func:`Parameter.value_from_envvar` does. - - But in the case of non-boolean flags, the value is analyzed to determine if the - flag is activated or not, and returns a boolean of its activation, or the - :attr:`flag_value` if the latter is set. - - This method also takes care of repeated options (i.e. options with - :attr:`multiple` set to ``True``). - - :meta private: - """ - rv = self.resolve_envvar_value(ctx) - - # Absent environment variable or an empty string is interpreted as unset. - if rv is None: - return None - - # Non-boolean flags are more liberal in what they accept. But a flag being a - # flag, its envvar value still needs to be analyzed to determine if the flag is - # activated or not. - if self.is_flag and not self.is_bool_flag: - # If the flag_value is set and match the envvar value, return it - # directly. - if self.flag_value is not UNSET and rv == self.flag_value: - return self.flag_value - # Analyze the envvar value as a boolean to know if the flag is - # activated or not. - return types.BoolParamType.str_to_bool(rv) - - # Split the envvar value if it is allowed to be repeated. - value_depth = (self.nargs != 1) + bool(self.multiple) - if value_depth > 0: - multi_rv = self.type.split_envvar_value(rv) - if self.multiple and self.nargs != 1: - multi_rv = batch(multi_rv, self.nargs) # type: ignore[assignment] - - return multi_rv - - return rv - - def consume_value( - self, ctx: Context, opts: cabc.Mapping[str, Parameter] - ) -> tuple[t.Any, ParameterSource]: - """For :class:`Option`, the value can be collected from an interactive prompt - if the option is a flag that needs a value (and the :attr:`prompt` property is - set). - - Additionally, this method handles flag option that are activated without a - value, in which case the :attr:`flag_value` is returned. - - :meta private: - """ - value, source = super().consume_value(ctx, opts) - - # The parser will emit a sentinel value if the option is allowed to as a flag - # without a value. - if value is FLAG_NEEDS_VALUE: - # If the option allows for a prompt, we start an interaction with the user. - if self.prompt is not None and not ctx.resilient_parsing: - value = self.prompt_for_value(ctx) - source = ParameterSource.PROMPT - # Else the flag takes its flag_value as value. - else: - value = self.flag_value - source = ParameterSource.COMMANDLINE - - # A flag which is activated always returns the flag value, unless the value - # comes from the explicitly sets default. - elif ( - self.is_flag - and value is True - and not self.is_bool_flag - and source < ParameterSource.DEFAULT_MAP - ): - value = self.flag_value - - # Re-interpret a multiple option which has been sent as-is by the parser. - # Here we replace each occurrence of value-less flags (marked by the - # FLAG_NEEDS_VALUE sentinel) with the flag_value. - elif ( - self.multiple - and value is not UNSET - and isinstance(value, cabc.Iterable) - and source < ParameterSource.DEFAULT_MAP - and any(v is FLAG_NEEDS_VALUE for v in value) - ): - value = [self.flag_value if v is FLAG_NEEDS_VALUE else v for v in value] - source = ParameterSource.COMMANDLINE - - # The value wasn't set, or used the param's default, prompt for one to the user - # if prompting is enabled. - elif ( - (value is UNSET or source >= ParameterSource.DEFAULT_MAP) - and self.prompt is not None - and (self.required or self.prompt_required) - and not ctx.resilient_parsing - ): - value = self.prompt_for_value(ctx) - source = ParameterSource.PROMPT - - return value, source - - def process_value(self, ctx: Context, value: t.Any) -> t.Any: - # process_value has to be overridden on Options in order to capture - # `value == UNSET` cases before `type_cast_value()` gets called. - # - # Refs: - # https://github.com/pallets/click/issues/3069 - if self.is_flag and not self.required and self.is_bool_flag and value is UNSET: - value = False - - if self.callback is not None: - value = self.callback(ctx, self, value) - - return value - - # in the normal case, rely on Parameter.process_value - return super().process_value(ctx, value) - - -class Argument(Parameter): - """Arguments are positional parameters to a command. They generally - provide fewer features than options but can have infinite ``nargs`` - and are required by default. - - All parameters are passed onwards to the constructor of :class:`Parameter`. - """ - - param_type_name = "argument" - - def __init__( - self, - param_decls: cabc.Sequence[str], - required: bool | None = None, - **attrs: t.Any, - ) -> None: - # Auto-detect the requirement status of the argument if not explicitly set. - if required is None: - # The argument gets automatically required if it has no explicit default - # value set and is setup to match at least one value. - if attrs.get("default", UNSET) is UNSET: - required = attrs.get("nargs", 1) > 0 - # If the argument has a default value, it is not required. - else: - required = False - - if "multiple" in attrs: - raise TypeError("__init__() got an unexpected keyword argument 'multiple'.") - - super().__init__(param_decls, required=required, **attrs) - - @property - def human_readable_name(self) -> str: - if self.metavar is not None: - return self.metavar - return self.name.upper() - - def make_metavar(self, ctx: Context) -> str: - if self.metavar is not None: - return self.metavar - var = self.type.get_metavar(param=self, ctx=ctx) - if not var: - var = self.name.upper() - if self.deprecated: - var += "!" - if not self.required: - var = f"[{var}]" - if self.nargs != 1: - var += "..." - return var - - def _parse_decls( - self, decls: cabc.Sequence[str], expose_value: bool - ) -> tuple[str, list[str], list[str]]: - if not decls: - if not expose_value: - return "", [], [] - raise TypeError("Argument is marked as exposed, but does not have a name.") - if len(decls) == 1: - name = arg = decls[0] - name = name.replace("-", "_").lower() - else: - raise TypeError( - _( - "Arguments take exactly one parameter declaration, got" - " {length}: {decls}." - ).format(length=len(decls), decls=decls) - ) - return name, [arg], [] - - def get_usage_pieces(self, ctx: Context) -> list[str]: - return [self.make_metavar(ctx)] - - def get_error_hint(self, ctx: Context | None) -> str: - if ctx is not None: - return f"'{self.make_metavar(ctx)}'" - return f"'{self.human_readable_name}'" - - def add_to_parser(self, parser: _OptionParser, ctx: Context) -> None: - parser.add_argument(dest=self.name, nargs=self.nargs, obj=self) - - -def __getattr__(name: str) -> object: - import warnings - - if name == "BaseCommand": - warnings.warn( - "'BaseCommand' is deprecated and will be removed in Click 9.0. Use" - " 'Command' instead.", - DeprecationWarning, - stacklevel=2, - ) - return _BaseCommand - - if name == "MultiCommand": - warnings.warn( - "'MultiCommand' is deprecated and will be removed in Click 9.0. Use" - " 'Group' instead.", - DeprecationWarning, - stacklevel=2, - ) - return _MultiCommand - - raise AttributeError(name) diff --git a/notification-service/venv/Lib/site-packages/click/decorators.py b/notification-service/venv/Lib/site-packages/click/decorators.py deleted file mode 100644 index 14aee42..0000000 --- a/notification-service/venv/Lib/site-packages/click/decorators.py +++ /dev/null @@ -1,551 +0,0 @@ -from __future__ import annotations - -import inspect -import typing as t -from functools import update_wrapper -from gettext import gettext as _ - -from .core import Argument -from .core import Command -from .core import Context -from .core import Group -from .core import Option -from .core import Parameter -from .globals import get_current_context -from .utils import echo - -if t.TYPE_CHECKING: - import typing_extensions as te - - P = te.ParamSpec("P") - -R = t.TypeVar("R") -T = t.TypeVar("T") -_AnyCallable = t.Callable[..., t.Any] -FC = t.TypeVar("FC", bound="_AnyCallable | Command") - - -def pass_context(f: t.Callable[te.Concatenate[Context, P], R]) -> t.Callable[P, R]: - """Marks a callback as wanting to receive the current context - object as first argument. - """ - - def new_func(*args: P.args, **kwargs: P.kwargs) -> R: - return f(get_current_context(), *args, **kwargs) - - return update_wrapper(new_func, f) - - -def pass_obj(f: t.Callable[te.Concatenate[T, P], R]) -> t.Callable[P, R]: - """Similar to :func:`pass_context`, but only pass the object on the - context onwards (:attr:`Context.obj`). This is useful if that object - represents the state of a nested system. - """ - - def new_func(*args: P.args, **kwargs: P.kwargs) -> R: - return f(get_current_context().obj, *args, **kwargs) - - return update_wrapper(new_func, f) - - -def make_pass_decorator( - object_type: type[T], ensure: bool = False -) -> t.Callable[[t.Callable[te.Concatenate[T, P], R]], t.Callable[P, R]]: - """Given an object type this creates a decorator that will work - similar to :func:`pass_obj` but instead of passing the object of the - current context, it will find the innermost context of type - :func:`object_type`. - - This generates a decorator that works roughly like this:: - - from functools import update_wrapper - - def decorator(f): - @pass_context - def new_func(ctx, *args, **kwargs): - obj = ctx.find_object(object_type) - return ctx.invoke(f, obj, *args, **kwargs) - return update_wrapper(new_func, f) - return decorator - - :param object_type: the type of the object to pass. - :param ensure: if set to `True`, a new object will be created and - remembered on the context if it's not there yet. - """ - - def decorator(f: t.Callable[te.Concatenate[T, P], R]) -> t.Callable[P, R]: - def new_func(*args: P.args, **kwargs: P.kwargs) -> R: - ctx = get_current_context() - - obj: T | None - if ensure: - obj = ctx.ensure_object(object_type) - else: - obj = ctx.find_object(object_type) - - if obj is None: - raise RuntimeError( - "Managed to invoke callback without a context" - f" object of type {object_type.__name__!r}" - " existing." - ) - - return ctx.invoke(f, obj, *args, **kwargs) - - return update_wrapper(new_func, f) - - return decorator - - -def pass_meta_key( - key: str, *, doc_description: str | None = None -) -> t.Callable[[t.Callable[te.Concatenate[T, P], R]], t.Callable[P, R]]: - """Create a decorator that passes a key from - :attr:`click.Context.meta` as the first argument to the decorated - function. - - :param key: Key in ``Context.meta`` to pass. - :param doc_description: Description of the object being passed, - inserted into the decorator's docstring. Defaults to "the 'key' - key from Context.meta". - - .. versionadded:: 8.0 - """ - - def decorator(f: t.Callable[te.Concatenate[T, P], R]) -> t.Callable[P, R]: - def new_func(*args: P.args, **kwargs: P.kwargs) -> R: - ctx = get_current_context() - obj = ctx.meta[key] - return ctx.invoke(f, obj, *args, **kwargs) - - return update_wrapper(new_func, f) - - if doc_description is None: - doc_description = f"the {key!r} key from :attr:`click.Context.meta`" - - decorator.__doc__ = ( - f"Decorator that passes {doc_description} as the first argument" - " to the decorated function." - ) - return decorator - - -CmdType = t.TypeVar("CmdType", bound=Command) - - -# variant: no call, directly as decorator for a function. -@t.overload -def command(name: _AnyCallable) -> Command: ... - - -# variant: with positional name and with positional or keyword cls argument: -# @command(namearg, CommandCls, ...) or @command(namearg, cls=CommandCls, ...) -@t.overload -def command( - name: str | None, - cls: type[CmdType], - **attrs: t.Any, -) -> t.Callable[[_AnyCallable], CmdType]: ... - - -# variant: name omitted, cls _must_ be a keyword argument, @command(cls=CommandCls, ...) -@t.overload -def command( - name: None = None, - *, - cls: type[CmdType], - **attrs: t.Any, -) -> t.Callable[[_AnyCallable], CmdType]: ... - - -# variant: with optional string name, no cls argument provided. -@t.overload -def command( - name: str | None = ..., cls: None = None, **attrs: t.Any -) -> t.Callable[[_AnyCallable], Command]: ... - - -def command( - name: str | _AnyCallable | None = None, - cls: type[CmdType] | None = None, - **attrs: t.Any, -) -> Command | t.Callable[[_AnyCallable], Command | CmdType]: - r"""Creates a new :class:`Command` and uses the decorated function as - callback. This will also automatically attach all decorated - :func:`option`\s and :func:`argument`\s as parameters to the command. - - The name of the command defaults to the name of the function, converted to - lowercase, with underscores ``_`` replaced by dashes ``-``, and the suffixes - ``_command``, ``_cmd``, ``_group``, and ``_grp`` are removed. For example, - ``init_data_command`` becomes ``init-data``. - - All keyword arguments are forwarded to the underlying command class. - For the ``params`` argument, any decorated params are appended to - the end of the list. - - Once decorated the function turns into a :class:`Command` instance - that can be invoked as a command line utility or be attached to a - command :class:`Group`. - - :param name: The name of the command. Defaults to modifying the function's - name as described above. - :param cls: The command class to create. Defaults to :class:`Command`. - - .. versionchanged:: 8.2 - The suffixes ``_command``, ``_cmd``, ``_group``, and ``_grp`` are - removed when generating the name. - - .. versionchanged:: 8.1 - This decorator can be applied without parentheses. - - .. versionchanged:: 8.1 - The ``params`` argument can be used. Decorated params are - appended to the end of the list. - """ - - func: t.Callable[[_AnyCallable], t.Any] | None = None - - if callable(name): - func = name - name = None - assert cls is None, "Use 'command(cls=cls)(callable)' to specify a class." - assert not attrs, "Use 'command(**kwargs)(callable)' to provide arguments." - - if cls is None: - cls = t.cast("type[CmdType]", Command) - - def decorator(f: _AnyCallable) -> CmdType: - if isinstance(f, Command): - raise TypeError("Attempted to convert a callback into a command twice.") - - attr_params = attrs.pop("params", None) - params = attr_params if attr_params is not None else [] - - try: - decorator_params = f.__click_params__ # type: ignore - except AttributeError: - pass - else: - del f.__click_params__ # type: ignore - params.extend(reversed(decorator_params)) - - if attrs.get("help") is None: - attrs["help"] = f.__doc__ - - if t.TYPE_CHECKING: - assert cls is not None - assert not callable(name) - - if name is not None: - cmd_name = name - else: - cmd_name = f.__name__.lower().replace("_", "-") - cmd_left, sep, suffix = cmd_name.rpartition("-") - - if sep and suffix in {"command", "cmd", "group", "grp"}: - cmd_name = cmd_left - - cmd = cls(name=cmd_name, callback=f, params=params, **attrs) - cmd.__doc__ = f.__doc__ - return cmd - - if func is not None: - return decorator(func) - - return decorator - - -GrpType = t.TypeVar("GrpType", bound=Group) - - -# variant: no call, directly as decorator for a function. -@t.overload -def group(name: _AnyCallable) -> Group: ... - - -# variant: with positional name and with positional or keyword cls argument: -# @group(namearg, GroupCls, ...) or @group(namearg, cls=GroupCls, ...) -@t.overload -def group( - name: str | None, - cls: type[GrpType], - **attrs: t.Any, -) -> t.Callable[[_AnyCallable], GrpType]: ... - - -# variant: name omitted, cls _must_ be a keyword argument, @group(cmd=GroupCls, ...) -@t.overload -def group( - name: None = None, - *, - cls: type[GrpType], - **attrs: t.Any, -) -> t.Callable[[_AnyCallable], GrpType]: ... - - -# variant: with optional string name, no cls argument provided. -@t.overload -def group( - name: str | None = ..., cls: None = None, **attrs: t.Any -) -> t.Callable[[_AnyCallable], Group]: ... - - -def group( - name: str | _AnyCallable | None = None, - cls: type[GrpType] | None = None, - **attrs: t.Any, -) -> Group | t.Callable[[_AnyCallable], Group | GrpType]: - """Creates a new :class:`Group` with a function as callback. This - works otherwise the same as :func:`command` just that the `cls` - parameter is set to :class:`Group`. - - .. versionchanged:: 8.1 - This decorator can be applied without parentheses. - """ - if cls is None: - cls = t.cast("type[GrpType]", Group) - - if callable(name): - return command(cls=cls, **attrs)(name) - - return command(name, cls, **attrs) - - -def _param_memo(f: t.Callable[..., t.Any], param: Parameter) -> None: - if isinstance(f, Command): - f.params.append(param) - else: - if not hasattr(f, "__click_params__"): - f.__click_params__ = [] # type: ignore - - f.__click_params__.append(param) # type: ignore - - -def argument( - *param_decls: str, cls: type[Argument] | None = None, **attrs: t.Any -) -> t.Callable[[FC], FC]: - """Attaches an argument to the command. All positional arguments are - passed as parameter declarations to :class:`Argument`; all keyword - arguments are forwarded unchanged (except ``cls``). - This is equivalent to creating an :class:`Argument` instance manually - and attaching it to the :attr:`Command.params` list. - - For the default argument class, refer to :class:`Argument` and - :class:`Parameter` for descriptions of parameters. - - :param cls: the argument class to instantiate. This defaults to - :class:`Argument`. - :param param_decls: Passed as positional arguments to the constructor of - ``cls``. - :param attrs: Passed as keyword arguments to the constructor of ``cls``. - """ - if cls is None: - cls = Argument - - def decorator(f: FC) -> FC: - _param_memo(f, cls(param_decls, **attrs)) - return f - - return decorator - - -def option( - *param_decls: str, cls: type[Option] | None = None, **attrs: t.Any -) -> t.Callable[[FC], FC]: - """Attaches an option to the command. All positional arguments are - passed as parameter declarations to :class:`Option`; all keyword - arguments are forwarded unchanged (except ``cls``). - This is equivalent to creating an :class:`Option` instance manually - and attaching it to the :attr:`Command.params` list. - - For the default option class, refer to :class:`Option` and - :class:`Parameter` for descriptions of parameters. - - :param cls: the option class to instantiate. This defaults to - :class:`Option`. - :param param_decls: Passed as positional arguments to the constructor of - ``cls``. - :param attrs: Passed as keyword arguments to the constructor of ``cls``. - """ - if cls is None: - cls = Option - - def decorator(f: FC) -> FC: - _param_memo(f, cls(param_decls, **attrs)) - return f - - return decorator - - -def confirmation_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: - """Add a ``--yes`` option which shows a prompt before continuing if - not passed. If the prompt is declined, the program will exit. - - :param param_decls: One or more option names. Defaults to the single - value ``"--yes"``. - :param kwargs: Extra arguments are passed to :func:`option`. - """ - - def callback(ctx: Context, param: Parameter, value: bool) -> None: - if not value: - ctx.abort() - - if not param_decls: - param_decls = ("--yes",) - - kwargs.setdefault("is_flag", True) - kwargs.setdefault("callback", callback) - kwargs.setdefault("expose_value", False) - kwargs.setdefault("prompt", _("Do you want to continue?")) - kwargs.setdefault("help", _("Confirm the action without prompting.")) - return option(*param_decls, **kwargs) - - -def password_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: - """Add a ``--password`` option which prompts for a password, hiding - input and asking to enter the value again for confirmation. - - :param param_decls: One or more option names. Defaults to the single - value ``"--password"``. - :param kwargs: Extra arguments are passed to :func:`option`. - """ - if not param_decls: - param_decls = ("--password",) - - kwargs.setdefault("prompt", True) - kwargs.setdefault("confirmation_prompt", True) - kwargs.setdefault("hide_input", True) - return option(*param_decls, **kwargs) - - -def version_option( - version: str | None = None, - *param_decls: str, - package_name: str | None = None, - prog_name: str | None = None, - message: str | None = None, - **kwargs: t.Any, -) -> t.Callable[[FC], FC]: - """Add a ``--version`` option which immediately prints the version - number and exits the program. - - If ``version`` is not provided, Click will try to detect it using - :func:`importlib.metadata.version` to get the version for the - ``package_name``. - - If ``package_name`` is not provided, Click will try to detect it by - inspecting the stack frames. This will be used to detect the - version, so it must match the name of the installed package. - - :param version: The version number to show. If not provided, Click - will try to detect it. - :param param_decls: One or more option names. Defaults to the single - value ``"--version"``. - :param package_name: The package name to detect the version from. If - not provided, Click will try to detect it. - :param prog_name: The name of the CLI to show in the message. If not - provided, it will be detected from the command. - :param message: The message to show. The values ``%(prog)s``, - ``%(package)s``, and ``%(version)s`` are available. Defaults to - ``"%(prog)s, version %(version)s"``. - :param kwargs: Extra arguments are passed to :func:`option`. - :raise RuntimeError: ``version`` could not be detected. - - .. versionchanged:: 8.0 - Add the ``package_name`` parameter, and the ``%(package)s`` - value for messages. - - .. versionchanged:: 8.0 - Use :mod:`importlib.metadata` instead of ``pkg_resources``. The - version is detected based on the package name, not the entry - point name. The Python package name must match the installed - package name, or be passed with ``package_name=``. - """ - if message is None: - message = _("%(prog)s, version %(version)s") - - if version is None and package_name is None: - frame = inspect.currentframe() - f_back = frame.f_back if frame is not None else None - f_globals = f_back.f_globals if f_back is not None else None - # break reference cycle - # https://docs.python.org/3/library/inspect.html#the-interpreter-stack - del frame - - if f_globals is not None: - package_name = f_globals.get("__name__") - - if package_name == "__main__": - package_name = f_globals.get("__package__") - - if package_name: - package_name = package_name.partition(".")[0] - - def callback(ctx: Context, param: Parameter, value: bool) -> None: - if not value or ctx.resilient_parsing: - return - - nonlocal prog_name - nonlocal version - - if prog_name is None: - prog_name = ctx.find_root().info_name - - if version is None and package_name is not None: - import importlib.metadata - - try: - version = importlib.metadata.version(package_name) - except importlib.metadata.PackageNotFoundError: - raise RuntimeError( - f"{package_name!r} is not installed. Try passing" - " 'package_name' instead." - ) from None - - if version is None: - raise RuntimeError( - f"Could not determine the version for {package_name!r} automatically." - ) - - echo( - message % {"prog": prog_name, "package": package_name, "version": version}, - color=ctx.color, - ) - ctx.exit() - - if not param_decls: - param_decls = ("--version",) - - kwargs.setdefault("is_flag", True) - kwargs.setdefault("expose_value", False) - kwargs.setdefault("is_eager", True) - kwargs.setdefault("help", _("Show the version and exit.")) - kwargs["callback"] = callback - return option(*param_decls, **kwargs) - - -def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: - """Pre-configured ``--help`` option which immediately prints the help page - and exits the program. - - :param param_decls: One or more option names. Defaults to the single - value ``"--help"``. - :param kwargs: Extra arguments are passed to :func:`option`. - """ - - def show_help(ctx: Context, param: Parameter, value: bool) -> None: - """Callback that print the help page on ```` and exits.""" - if value and not ctx.resilient_parsing: - echo(ctx.get_help(), color=ctx.color) - ctx.exit() - - if not param_decls: - param_decls = ("--help",) - - kwargs.setdefault("is_flag", True) - kwargs.setdefault("expose_value", False) - kwargs.setdefault("is_eager", True) - kwargs.setdefault("help", _("Show this message and exit.")) - kwargs.setdefault("callback", show_help) - - return option(*param_decls, **kwargs) diff --git a/notification-service/venv/Lib/site-packages/click/exceptions.py b/notification-service/venv/Lib/site-packages/click/exceptions.py deleted file mode 100644 index 68c2806..0000000 --- a/notification-service/venv/Lib/site-packages/click/exceptions.py +++ /dev/null @@ -1,347 +0,0 @@ -from __future__ import annotations - -import collections.abc as cabc -import typing as t -from gettext import gettext as _ -from gettext import ngettext - -from ._compat import get_text_stderr -from .globals import resolve_color_default -from .utils import echo -from .utils import format_filename - -if t.TYPE_CHECKING: - from .core import Command - from .core import Context - from .core import Parameter - - -def _join_param_hints(param_hint: cabc.Sequence[str] | str | None) -> str | None: - if param_hint is not None and not isinstance(param_hint, str): - return " / ".join(repr(x) for x in param_hint) - - return param_hint - - -def _format_possibilities(possibilities: list[str]) -> str: - possibility_str = ", ".join(repr(p) for p in sorted(possibilities)) - return ngettext( - "Did you mean {possibility}?", - "(Did you mean one of: {possibilities}?)", - len(possibilities), - ).format(possibility=possibility_str, possibilities=possibility_str) - - -class ClickException(Exception): - """An exception that Click can handle and show to the user.""" - - #: The exit code for this exception. - exit_code = 1 - - def __init__(self, message: str) -> None: - super().__init__(message) - # The context will be removed by the time we print the message, so cache - # the color settings here to be used later on (in `show`) - self.show_color: bool | None = resolve_color_default() - self.message = message - - def format_message(self) -> str: - return self.message - - def __str__(self) -> str: - return self.message - - def show(self, file: t.IO[t.Any] | None = None) -> None: - if file is None: - file = get_text_stderr() - - echo( - _("Error: {message}").format(message=self.format_message()), - file=file, - color=self.show_color, - ) - - -class UsageError(ClickException): - """An internal exception that signals a usage error. This typically - aborts any further handling. - - :param message: the error message to display. - :param ctx: optionally the context that caused this error. Click will - fill in the context automatically in some situations. - """ - - exit_code = 2 - - def __init__(self, message: str, ctx: Context | None = None) -> None: - super().__init__(message) - self.ctx = ctx - self.cmd: Command | None = self.ctx.command if self.ctx else None - - def show(self, file: t.IO[t.Any] | None = None) -> None: - if file is None: - file = get_text_stderr() - color = None - hint = "" - if ( - self.ctx is not None - and self.ctx.command.get_help_option(self.ctx) is not None - ): - help_names = self.ctx.command.get_help_option_names(self.ctx) - # Pick the longest name (like ``--help`` over ``-h``) for - # readability in error messages. - hint = _("Try '{command} {option}' for help.").format( - command=self.ctx.command_path, - option=max(help_names, key=len), - ) - hint = f"{hint}\n" - if self.ctx is not None: - color = self.ctx.color - echo(f"{self.ctx.get_usage()}\n{hint}", file=file, color=color) - echo( - _("Error: {message}").format(message=self.format_message()), - file=file, - color=color, - ) - - -class BadParameter(UsageError): - """An exception that formats out a standardized error message for a - bad parameter. This is useful when thrown from a callback or type as - Click will attach contextual information to it (for instance, which - parameter it is). - - .. versionadded:: 2.0 - - :param param: the parameter object that caused this error. This can - be left out, and Click will attach this info itself - if possible. - :param param_hint: a string that shows up as parameter name. This - can be used as alternative to `param` in cases - where custom validation should happen. If it is - a string it's used as such, if it's a list then - each item is quoted and separated. - """ - - def __init__( - self, - message: str, - ctx: Context | None = None, - param: Parameter | None = None, - param_hint: cabc.Sequence[str] | str | None = None, - ) -> None: - super().__init__(message, ctx) - self.param = param - self.param_hint = param_hint - - def format_message(self) -> str: - if self.param_hint is not None: - param_hint = self.param_hint - elif self.param is not None: - param_hint = self.param.get_error_hint(self.ctx) - else: - return _("Invalid value: {message}").format(message=self.message) - - return _("Invalid value for {param_hint}: {message}").format( - param_hint=_join_param_hints(param_hint), message=self.message - ) - - -class MissingParameter(BadParameter): - """Raised if click required an option or argument but it was not - provided when invoking the script. - - .. versionadded:: 4.0 - - :param param_type: a string that indicates the type of the parameter. - The default is to inherit the parameter type from - the given `param`. Valid values are ``'parameter'``, - ``'option'`` or ``'argument'``. - """ - - def __init__( - self, - message: str | None = None, - ctx: Context | None = None, - param: Parameter | None = None, - param_hint: cabc.Sequence[str] | str | None = None, - param_type: str | None = None, - ) -> None: - super().__init__(message or "", ctx, param, param_hint) - self.param_type = param_type - - def format_message(self) -> str: - if self.param_hint is not None: - param_hint: cabc.Sequence[str] | str | None = self.param_hint - elif self.param is not None: - param_hint = self.param.get_error_hint(self.ctx) - else: - param_hint = None - - param_hint = _join_param_hints(param_hint) - param_hint = f" {param_hint}" if param_hint else "" - - param_type = self.param_type - if param_type is None and self.param is not None: - param_type = self.param.param_type_name - - msg = self.message - if self.param is not None: - msg_extra = self.param.type.get_missing_message( - param=self.param, ctx=self.ctx - ) - if msg_extra: - if msg: - msg += f". {msg_extra}" - else: - msg = msg_extra - - msg = f" {msg}" if msg else "" - - # Translate param_type for known types. - if param_type == "argument": - missing = _("Missing argument") - elif param_type == "option": - missing = _("Missing option") - elif param_type == "parameter": - missing = _("Missing parameter") - else: - missing = _("Missing {param_type}").format(param_type=param_type) - - return f"{missing}{param_hint}.{msg}" - - def __str__(self) -> str: - if not self.message: - param_name = self.param.name if self.param else None - return _("Missing parameter: {param_name}").format(param_name=param_name) - else: - return self.message - - -class NoSuchOption(UsageError): - """Raised if Click attempted to handle an option that does not exist. - - .. versionadded:: 4.0 - """ - - def __init__( - self, - option_name: str, - message: str | None = None, - possibilities: cabc.Iterable[str] | None = None, - ctx: Context | None = None, - ) -> None: - if message is None: - message = _("No such option {name!r}.").format(name=option_name) - - super().__init__(message, ctx) - self.option_name = option_name - self.possibilities: list[str] | None = None - if possibilities: - from difflib import get_close_matches - - self.possibilities = get_close_matches(option_name, possibilities) - - def format_message(self) -> str: - if not self.possibilities: - return self.message - return f"{self.message} {_format_possibilities(self.possibilities)}" - - -class NoSuchCommand(UsageError): - """Raised if Click attempted to handle a command that does not exist. - - .. versionadded:: 8.4.0 - """ - - def __init__( - self, - command_name: str, - message: str | None = None, - possibilities: cabc.Iterable[str] | None = None, - ctx: Context | None = None, - ) -> None: - if message is None: - message = _("No such command {name!r}.").format(name=command_name) - - super().__init__(message, ctx) - self.command_name = command_name - self.possibilities: list[str] | None = None - if possibilities: - from difflib import get_close_matches - - self.possibilities = get_close_matches(command_name, possibilities) - - def format_message(self) -> str: - if not self.possibilities: - return self.message - return f"{self.message} {_format_possibilities(self.possibilities)}" - - -class BadOptionUsage(UsageError): - """Raised if an option is generally supplied but the use of the option - was incorrect. This is for instance raised if the number of arguments - for an option is not correct. - - .. versionadded:: 4.0 - - :param option_name: the name of the option being used incorrectly. - """ - - def __init__( - self, option_name: str, message: str, ctx: Context | None = None - ) -> None: - super().__init__(message, ctx) - self.option_name = option_name - - -class BadArgumentUsage(UsageError): - """Raised if an argument is generally supplied but the use of the argument - was incorrect. This is for instance raised if the number of values - for an argument is not correct. - - .. versionadded:: 6.0 - """ - - -class NoArgsIsHelpError(UsageError): - def __init__(self, ctx: Context) -> None: - self.ctx: Context - super().__init__(ctx.get_help(), ctx=ctx) - - def show(self, file: t.IO[t.Any] | None = None) -> None: - echo(self.format_message(), file=file, err=True, color=self.ctx.color) - - -class FileError(ClickException): - """Raised if a file cannot be opened.""" - - def __init__(self, filename: str, hint: str | None = None) -> None: - if hint is None: - hint = _("unknown error") - - super().__init__(hint) - self.ui_filename: str = format_filename(filename) - self.filename = filename - - def format_message(self) -> str: - return _("Could not open file {filename!r}: {message}").format( - filename=self.ui_filename, message=self.message - ) - - -class Abort(RuntimeError): - """An internal signalling exception that signals Click to abort.""" - - -class Exit(RuntimeError): - """An exception that indicates that the application should exit with some - status code. - - :param code: the status code to exit with. - """ - - __slots__ = ("exit_code",) - - def __init__(self, code: int = 0) -> None: - self.exit_code: int = code diff --git a/notification-service/venv/Lib/site-packages/click/formatting.py b/notification-service/venv/Lib/site-packages/click/formatting.py deleted file mode 100644 index 886a4ad..0000000 --- a/notification-service/venv/Lib/site-packages/click/formatting.py +++ /dev/null @@ -1,315 +0,0 @@ -from __future__ import annotations - -import collections.abc as cabc -from contextlib import contextmanager -from gettext import gettext as _ - -from ._compat import term_len -from .parser import _split_opt - -# Can force a width. This is used by the test system -FORCED_WIDTH: int | None = None - - -def measure_table(rows: cabc.Iterable[tuple[str, str]]) -> tuple[int, ...]: - widths: dict[int, int] = {} - - for row in rows: - for idx, col in enumerate(row): - widths[idx] = max(widths.get(idx, 0), term_len(col)) - - return tuple(y for x, y in sorted(widths.items())) - - -def iter_rows( - rows: cabc.Iterable[tuple[str, str]], col_count: int -) -> cabc.Iterator[tuple[str, ...]]: - for row in rows: - yield row + ("",) * (col_count - len(row)) - - -def wrap_text( - text: str, - width: int = 78, - initial_indent: str = "", - subsequent_indent: str = "", - preserve_paragraphs: bool = False, -) -> str: - """A helper function that intelligently wraps text. By default, it - assumes that it operates on a single paragraph of text but if the - `preserve_paragraphs` parameter is provided it will intelligently - handle paragraphs (defined by two empty lines). - - If paragraphs are handled, a paragraph can be prefixed with an empty - line containing the ``\\b`` character (``\\x08``) to indicate that - no rewrapping should happen in that block. - - :param text: the text that should be rewrapped. - :param width: the maximum width for the text. - :param initial_indent: the initial indent that should be placed on the - first line as a string. - :param subsequent_indent: the indent string that should be placed on - each consecutive line. - :param preserve_paragraphs: if this flag is set then the wrapping will - intelligently handle paragraphs. - - .. versionchanged:: 8.4.0 - Width is measured in visible characters. ANSI escape sequences in - ``text``, ``initial_indent``, or ``subsequent_indent`` no longer - count toward the width budget, so styled input wraps based on what - the user sees instead of raw byte length. - """ - from ._textwrap import TextWrapper - - text = text.expandtabs() - wrapper = TextWrapper( - width, - initial_indent=initial_indent, - subsequent_indent=subsequent_indent, - replace_whitespace=False, - ) - if not preserve_paragraphs: - return wrapper.fill(text) - - p: list[tuple[int, bool, str]] = [] - buf: list[str] = [] - indent = None - - def _flush_par() -> None: - if not buf: - return - if buf[0].strip() == "\b": - p.append((indent or 0, True, "\n".join(buf[1:]))) - else: - p.append((indent or 0, False, " ".join(buf))) - del buf[:] - - for line in text.splitlines(): - if not line: - _flush_par() - indent = None - else: - if indent is None: - orig_len = term_len(line) - line = line.lstrip() - indent = orig_len - term_len(line) - buf.append(line) - _flush_par() - - rv = [] - for indent, raw, text in p: - with wrapper.extra_indent(" " * indent): - if raw: - rv.append(wrapper.indent_only(text)) - else: - rv.append(wrapper.fill(text)) - - return "\n\n".join(rv) - - -class HelpFormatter: - """This class helps with formatting text-based help pages. It's - usually just needed for very special internal cases, but it's also - exposed so that developers can write their own fancy outputs. - - At present, it always writes into memory. - - :param indent_increment: the additional increment for each level. - :param width: the width for the text. This defaults to the terminal - width clamped to a maximum of 78. - """ - - def __init__( - self, - indent_increment: int = 2, - width: int | None = None, - max_width: int | None = None, - ) -> None: - self.indent_increment = indent_increment - if max_width is None: - max_width = 80 - if width is None: - import shutil - - width = FORCED_WIDTH - if width is None: - width = max(min(shutil.get_terminal_size().columns, max_width) - 2, 50) - self.width = width - self.current_indent: int = 0 - self.buffer: list[str] = [] - - def write(self, string: str) -> None: - """Writes a unicode string into the internal buffer.""" - self.buffer.append(string) - - def indent(self) -> None: - """Increases the indentation.""" - self.current_indent += self.indent_increment - - def dedent(self) -> None: - """Decreases the indentation.""" - self.current_indent -= self.indent_increment - - def write_usage(self, prog: str, args: str = "", prefix: str | None = None) -> None: - """Writes a usage line into the buffer. - - :param prog: the program name. - :param args: whitespace separated list of arguments. - :param prefix: The prefix for the first line. Defaults to - ``"Usage: "``. - """ - if prefix is None: - prefix = "{usage} ".format(usage=_("Usage:")) - - usage_prefix = f"{prefix:>{self.current_indent}}{prog} " - text_width = self.width - self.current_indent - - if not args: - # Without args, the prefix's trailing space and the wrap_text - # call that would normally place args on the line are both - # unnecessary. Emit just the prefix line. - self.write(usage_prefix.rstrip(" ")) - self.write("\n") - return - - if text_width >= (term_len(usage_prefix) + 20): - # The arguments will fit to the right of the prefix. - indent = " " * term_len(usage_prefix) - self.write( - wrap_text( - args, - text_width, - initial_indent=usage_prefix, - subsequent_indent=indent, - ) - ) - else: - # The prefix is too long, put the arguments on the next line. - self.write(usage_prefix) - self.write("\n") - indent = " " * (max(self.current_indent, term_len(prefix)) + 4) - self.write( - wrap_text( - args, text_width, initial_indent=indent, subsequent_indent=indent - ) - ) - - self.write("\n") - - def write_heading(self, heading: str) -> None: - """Writes a heading into the buffer.""" - self.write(f"{'':>{self.current_indent}}{heading}:\n") - - def write_paragraph(self) -> None: - """Writes a paragraph into the buffer.""" - if self.buffer: - self.write("\n") - - def write_text(self, text: str) -> None: - """Writes re-indented text into the buffer. This rewraps and - preserves paragraphs. - """ - indent = " " * self.current_indent - self.write( - wrap_text( - text, - self.width, - initial_indent=indent, - subsequent_indent=indent, - preserve_paragraphs=True, - ) - ) - self.write("\n") - - def write_dl( - self, - rows: cabc.Sequence[tuple[str, str]], - col_max: int = 30, - col_spacing: int = 2, - ) -> None: - """Writes a definition list into the buffer. This is how options - and commands are usually formatted. - - :param rows: a list of two item tuples for the terms and values. - :param col_max: the maximum width of the first column. - :param col_spacing: the number of spaces between the first and - second column. - """ - rows = list(rows) - widths = measure_table(rows) - if len(widths) != 2: - raise TypeError("Expected two columns for definition list") - - first_col = min(widths[0], col_max) + col_spacing - - for first, second in iter_rows(rows, len(widths)): - self.write(f"{'':>{self.current_indent}}{first}") - if not second: - self.write("\n") - continue - if term_len(first) <= first_col - col_spacing: - self.write(" " * (first_col - term_len(first))) - else: - self.write("\n") - self.write(" " * (first_col + self.current_indent)) - - text_width = max(self.width - first_col - 2, 10) - wrapped_text = wrap_text(second, text_width, preserve_paragraphs=True) - lines = wrapped_text.splitlines() - - if lines: - self.write(f"{lines[0]}\n") - - for line in lines[1:]: - self.write(f"{'':>{first_col + self.current_indent}}{line}\n") - else: - self.write("\n") - - @contextmanager - def section(self, name: str) -> cabc.Iterator[None]: - """Helpful context manager that writes a paragraph, a heading, - and the indents. - - :param name: the section name that is written as heading. - """ - self.write_paragraph() - self.write_heading(name) - self.indent() - try: - yield - finally: - self.dedent() - - @contextmanager - def indentation(self) -> cabc.Iterator[None]: - """A context manager that increases the indentation.""" - self.indent() - try: - yield - finally: - self.dedent() - - def getvalue(self) -> str: - """Returns the buffer contents.""" - return "".join(self.buffer) - - -def join_options(options: cabc.Sequence[str]) -> tuple[str, bool]: - """Given a list of option strings this joins them in the most appropriate - way and returns them in the form ``(formatted_string, - any_prefix_is_slash)`` where the second item in the tuple is a flag that - indicates if any of the option prefixes was a slash. - """ - rv = [] - any_prefix_is_slash = False - - for opt in options: - prefix = _split_opt(opt)[0] - - if prefix == "/": - any_prefix_is_slash = True - - rv.append((len(prefix), opt)) - - rv.sort(key=lambda x: x[0]) - return ", ".join(x[1] for x in rv), any_prefix_is_slash diff --git a/notification-service/venv/Lib/site-packages/click/globals.py b/notification-service/venv/Lib/site-packages/click/globals.py deleted file mode 100644 index a2f9172..0000000 --- a/notification-service/venv/Lib/site-packages/click/globals.py +++ /dev/null @@ -1,67 +0,0 @@ -from __future__ import annotations - -import typing as t -from threading import local - -if t.TYPE_CHECKING: - from .core import Context - -_local = local() - - -@t.overload -def get_current_context(silent: t.Literal[False] = False) -> Context: ... - - -@t.overload -def get_current_context(silent: bool = ...) -> Context | None: ... - - -def get_current_context(silent: bool = False) -> Context | None: - """Returns the current click context. This can be used as a way to - access the current context object from anywhere. This is a more implicit - alternative to the :func:`pass_context` decorator. This function is - primarily useful for helpers such as :func:`echo` which might be - interested in changing its behavior based on the current context. - - To push the current context, :meth:`Context.scope` can be used. - - .. versionadded:: 5.0 - - :param silent: if set to `True` the return value is `None` if no context - is available. The default behavior is to raise a - :exc:`RuntimeError`. - """ - try: - return t.cast("Context", _local.stack[-1]) - except (AttributeError, IndexError) as e: - if not silent: - raise RuntimeError("There is no active click context.") from e - - return None - - -def push_context(ctx: Context) -> None: - """Pushes a new context to the current stack.""" - _local.__dict__.setdefault("stack", []).append(ctx) - - -def pop_context() -> None: - """Removes the top level from the stack.""" - _local.stack.pop() - - -def resolve_color_default(color: bool | None = None) -> bool | None: - """Internal helper to get the default value of the color flag. If a - value is passed it's returned unchanged, otherwise it's looked up from - the current context. - """ - if color is not None: - return color - - ctx = get_current_context(silent=True) - - if ctx is not None: - return ctx.color - - return None diff --git a/notification-service/venv/Lib/site-packages/click/parser.py b/notification-service/venv/Lib/site-packages/click/parser.py deleted file mode 100644 index 4fcbf7c..0000000 --- a/notification-service/venv/Lib/site-packages/click/parser.py +++ /dev/null @@ -1,533 +0,0 @@ -""" -This module started out as largely a copy paste from the stdlib's -optparse module with the features removed that we do not need from -optparse because we implement them in Click on a higher level (for -instance type handling, help formatting and a lot more). - -The plan is to remove more and more from here over time. - -The reason this is a different module and not optparse from the stdlib -is that there are differences in 2.x and 3.x about the error messages -generated and optparse in the stdlib uses gettext for no good reason -and might cause us issues. - -Click uses parts of optparse written by Gregory P. Ward and maintained -by the Python Software Foundation. This is limited to code in parser.py. - -Copyright 2001-2006 Gregory P. Ward. All rights reserved. -Copyright 2002-2006 Python Software Foundation. All rights reserved. -""" - -# This code uses parts of optparse written by Gregory P. Ward and -# maintained by the Python Software Foundation. -# Copyright 2001-2006 Gregory P. Ward -# Copyright 2002-2006 Python Software Foundation -from __future__ import annotations - -import collections.abc as cabc -import typing as t -from collections import deque -from gettext import gettext as _ -from gettext import ngettext - -from ._utils import FLAG_NEEDS_VALUE -from ._utils import UNSET -from .exceptions import BadArgumentUsage -from .exceptions import BadOptionUsage -from .exceptions import NoSuchOption -from .exceptions import UsageError - -if t.TYPE_CHECKING: - from ._utils import T_FLAG_NEEDS_VALUE - from ._utils import T_UNSET - from .core import Argument as CoreArgument - from .core import Context - from .core import Option as CoreOption - from .core import Parameter as CoreParameter - -V = t.TypeVar("V") - - -def _unpack_args( - args: cabc.Sequence[str], nargs_spec: cabc.Sequence[int] -) -> tuple[cabc.Sequence[str | cabc.Sequence[str | T_UNSET] | T_UNSET], list[str]]: - """Given an iterable of arguments and an iterable of nargs specifications, - it returns a tuple with all the unpacked arguments at the first index - and all remaining arguments as the second. - - The nargs specification is the number of arguments that should be consumed - or `-1` to indicate that this position should eat up all the remainders. - - Missing items are filled with ``UNSET``. - """ - args = deque(args) - nargs_spec = deque(nargs_spec) - rv: list[str | tuple[str | T_UNSET, ...] | T_UNSET] = [] - spos: int | None = None - - def _fetch(c: deque[str]) -> str | T_UNSET: - try: - if spos is None: - return c.popleft() - else: - return c.pop() - except IndexError: - return UNSET - - while nargs_spec: - if spos is None: - nargs = nargs_spec.popleft() - else: - nargs = nargs_spec.pop() - - if nargs == 1: - rv.append(_fetch(args)) - elif nargs > 1: - x: list[str | T_UNSET] = [_fetch(args) for _ in range(nargs)] - - # If we're reversed, we're pulling in the arguments in reverse, - # so we need to turn them around. - if spos is not None: - x.reverse() - - rv.append(tuple(x)) - elif nargs < 0: - if spos is not None: - raise TypeError("Cannot have two nargs < 0") - - spos = len(rv) - rv.append(UNSET) - - # spos is the position of the wildcard (star). If it's not `None`, - # we fill it with the remainder. - if spos is not None: - rv[spos] = tuple(args) - args = [] - rv[spos + 1 :] = reversed(rv[spos + 1 :]) - - return tuple(rv), list(args) - - -def _split_opt(opt: str) -> tuple[str, str]: - first = opt[:1] - if first.isalnum(): - return "", opt - if opt[1:2] == first: - return opt[:2], opt[2:] - return first, opt[1:] - - -def _normalize_opt(opt: str, ctx: Context | None) -> str: - if ctx is None or ctx.token_normalize_func is None: - return opt - prefix, opt = _split_opt(opt) - return f"{prefix}{ctx.token_normalize_func(opt)}" - - -class _Option: - def __init__( - self, - obj: CoreOption, - opts: cabc.Sequence[str], - dest: str | None, - action: str | None = None, - nargs: int = 1, - const: t.Any | None = None, - ): - self._short_opts = [] - self._long_opts = [] - self.prefixes: set[str] = set() - - for opt in opts: - prefix, value = _split_opt(opt) - if not prefix: - raise ValueError( - _("Invalid start character for option ({option})").format( - option=opt - ) - ) - self.prefixes.add(prefix[0]) - if len(prefix) == 1 and len(value) == 1: - self._short_opts.append(opt) - else: - self._long_opts.append(opt) - self.prefixes.add(prefix) - - if action is None: - action = "store" - - self.dest = dest - self.action = action - self.nargs = nargs - self.const = const - self.obj = obj - - @property - def takes_value(self) -> bool: - return self.action in ("store", "append") - - def process(self, value: t.Any, state: _ParsingState) -> None: - if self.action == "store": - state.opts[self.dest] = value # type: ignore - elif self.action == "store_const": - state.opts[self.dest] = self.const # type: ignore - elif self.action == "append": - state.opts.setdefault(self.dest, []).append(value) # type: ignore - elif self.action == "append_const": - state.opts.setdefault(self.dest, []).append(self.const) # type: ignore - elif self.action == "count": - state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 # type: ignore - else: - raise ValueError(f"unknown action '{self.action}'") - state.order.append(self.obj) - - -class _Argument: - def __init__(self, obj: CoreArgument, dest: str | None, nargs: int = 1): - self.dest = dest - self.nargs = nargs - self.obj = obj - - def process( - self, - value: str | cabc.Sequence[str | T_UNSET] | T_UNSET, - state: _ParsingState, - ) -> None: - if self.nargs > 1: - assert isinstance(value, cabc.Sequence) - holes = sum(x is UNSET for x in value) - if holes == len(value): - value = UNSET - elif holes != 0: - raise BadArgumentUsage( - _("Argument {name!r} takes {nargs} values.").format( - name=self.dest, nargs=self.nargs - ) - ) - - # We failed to collect any argument value so we consider the argument as unset. - if value == (): - value = UNSET - - state.opts[self.dest] = value # type: ignore - state.order.append(self.obj) - - -class _ParsingState: - def __init__(self, rargs: list[str]) -> None: - self.opts: dict[str, t.Any] = {} - self.largs: list[str] = [] - self.rargs = rargs - self.order: list[CoreParameter] = [] - - -class _OptionParser: - """The option parser is an internal class that is ultimately used to - parse options and arguments. It's modelled after optparse and brings - a similar but vastly simplified API. It should generally not be used - directly as the high level Click classes wrap it for you. - - It's not nearly as extensible as optparse or argparse as it does not - implement features that are implemented on a higher level (such as - types or defaults). - - :param ctx: optionally the :class:`~click.Context` where this parser - should go with. - - .. deprecated:: 8.2 - Will be removed in Click 9.0. - """ - - def __init__(self, ctx: Context | None = None) -> None: - #: The :class:`~click.Context` for this parser. This might be - #: `None` for some advanced use cases. - self.ctx = ctx - #: This controls how the parser deals with interspersed arguments. - #: If this is set to `False`, the parser will stop on the first - #: non-option. Click uses this to implement nested subcommands - #: safely. - self.allow_interspersed_args: bool = True - #: This tells the parser how to deal with unknown options. By - #: default it will error out (which is sensible), but there is a - #: second mode where it will ignore it and continue processing - #: after shifting all the unknown options into the resulting args. - self.ignore_unknown_options: bool = False - - if ctx is not None: - self.allow_interspersed_args = ctx.allow_interspersed_args - self.ignore_unknown_options = ctx.ignore_unknown_options - - self._short_opt: dict[str, _Option] = {} - self._long_opt: dict[str, _Option] = {} - self._opt_prefixes = {"-", "--"} - self._args: list[_Argument] = [] - - def add_option( - self, - obj: CoreOption, - opts: cabc.Sequence[str], - dest: str | None, - action: str | None = None, - nargs: int = 1, - const: t.Any | None = None, - ) -> None: - """Adds a new option named `dest` to the parser. The destination - is not inferred (unlike with optparse) and needs to be explicitly - provided. Action can be any of ``store``, ``store_const``, - ``append``, ``append_const`` or ``count``. - - The `obj` can be used to identify the option in the order list - that is returned from the parser. - """ - opts = [_normalize_opt(opt, self.ctx) for opt in opts] - option = _Option(obj, opts, dest, action=action, nargs=nargs, const=const) - self._opt_prefixes.update(option.prefixes) - for opt in option._short_opts: - self._short_opt[opt] = option - for opt in option._long_opts: - self._long_opt[opt] = option - - def add_argument(self, obj: CoreArgument, dest: str | None, nargs: int = 1) -> None: - """Adds a positional argument named `dest` to the parser. - - The `obj` can be used to identify the option in the order list - that is returned from the parser. - """ - self._args.append(_Argument(obj, dest=dest, nargs=nargs)) - - def parse_args( - self, args: list[str] - ) -> tuple[dict[str, t.Any], list[str], list[CoreParameter]]: - """Parses positional arguments and returns ``(values, args, order)`` - for the parsed options and arguments as well as the leftover - arguments if there are any. The order is a list of objects as they - appear on the command line. If arguments appear multiple times they - will be memorized multiple times as well. - """ - state = _ParsingState(args) - try: - self._process_args_for_options(state) - self._process_args_for_args(state) - except UsageError: - if self.ctx is None or not self.ctx.resilient_parsing: - raise - return state.opts, state.largs, state.order - - def _process_args_for_args(self, state: _ParsingState) -> None: - pargs, args = _unpack_args( - state.largs + state.rargs, [x.nargs for x in self._args] - ) - - for idx, arg in enumerate(self._args): - arg.process(pargs[idx], state) - - state.largs = args - state.rargs = [] - - def _process_args_for_options(self, state: _ParsingState) -> None: - while state.rargs: - arg = state.rargs.pop(0) - arglen = len(arg) - # Double dashes always handled explicitly regardless of what - # prefixes are valid. - if arg == "--": - return - elif arg[:1] in self._opt_prefixes and arglen > 1: - self._process_opts(arg, state) - elif self.allow_interspersed_args: - state.largs.append(arg) - else: - state.rargs.insert(0, arg) - return - - # Say this is the original argument list: - # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] - # ^ - # (we are about to process arg(i)). - # - # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of - # [arg0, ..., arg(i-1)] (any options and their arguments will have - # been removed from largs). - # - # The while loop will usually consume 1 or more arguments per pass. - # If it consumes 1 (eg. arg is an option that takes no arguments), - # then after _process_arg() is done the situation is: - # - # largs = subset of [arg0, ..., arg(i)] - # rargs = [arg(i+1), ..., arg(N-1)] - # - # If allow_interspersed_args is false, largs will always be - # *empty* -- still a subset of [arg0, ..., arg(i-1)], but - # not a very interesting subset! - - def _match_long_opt( - self, opt: str, explicit_value: str | None, state: _ParsingState - ) -> None: - if opt not in self._long_opt: - raise NoSuchOption(opt, possibilities=self._long_opt, ctx=self.ctx) - - option = self._long_opt[opt] - if option.takes_value: - # At this point it's safe to modify rargs by injecting the - # explicit value, because no exception is raised in this - # branch. This means that the inserted value will be fully - # consumed. - if explicit_value is not None: - state.rargs.insert(0, explicit_value) - - value = self._get_value_from_state(opt, option, state) - - elif explicit_value is not None: - raise BadOptionUsage( - opt, _("Option {name!r} does not take a value.").format(name=opt) - ) - - else: - value = UNSET - - option.process(value, state) - - def _match_short_opt(self, arg: str, state: _ParsingState) -> None: - stop = False - i = 1 - prefix = arg[0] - unknown_options = [] - - for ch in arg[1:]: - opt = _normalize_opt(f"{prefix}{ch}", self.ctx) - option = self._short_opt.get(opt) - i += 1 - - if not option: - if self.ignore_unknown_options: - unknown_options.append(ch) - continue - raise NoSuchOption(opt, ctx=self.ctx) - if option.takes_value: - # Any characters left in arg? Pretend they're the - # next arg, and stop consuming characters of arg. - if i < len(arg): - state.rargs.insert(0, arg[i:]) - stop = True - - value = self._get_value_from_state(opt, option, state) - - else: - value = UNSET - - option.process(value, state) - - if stop: - break - - # If we got any unknown options we recombine the string of the - # remaining options and re-attach the prefix, then report that - # to the state as new large. This way there is basic combinatorics - # that can be achieved while still ignoring unknown arguments. - if self.ignore_unknown_options and unknown_options: - state.largs.append(f"{prefix}{''.join(unknown_options)}") - - def _get_value_from_state( - self, option_name: str, option: _Option, state: _ParsingState - ) -> str | cabc.Sequence[str] | T_UNSET | T_FLAG_NEEDS_VALUE: - nargs = option.nargs - - value: str | cabc.Sequence[str] | T_UNSET | T_FLAG_NEEDS_VALUE - - if len(state.rargs) < nargs: - if option.obj._flag_needs_value: - # Option allows omitting the value. - value = FLAG_NEEDS_VALUE - else: - raise BadOptionUsage( - option_name, - ngettext( - "Option {name!r} requires an argument.", - "Option {name!r} requires {nargs} arguments.", - nargs, - ).format(name=option_name, nargs=nargs), - ) - elif nargs == 1: - next_rarg = state.rargs[0] - - if ( - option.obj._flag_needs_value - and isinstance(next_rarg, str) - and next_rarg[:1] in self._opt_prefixes - and len(next_rarg) > 1 - ): - # The next arg looks like the start of an option, don't - # use it as the value if omitting the value is allowed. - value = FLAG_NEEDS_VALUE - else: - value = state.rargs.pop(0) - else: - value = tuple(state.rargs[:nargs]) - del state.rargs[:nargs] - - return value - - def _process_opts(self, arg: str, state: _ParsingState) -> None: - explicit_value = None - # Long option handling happens in two parts. The first part is - # supporting explicitly attached values. In any case, we will try - # to long match the option first. - if "=" in arg: - long_opt, explicit_value = arg.split("=", 1) - else: - long_opt = arg - norm_long_opt = _normalize_opt(long_opt, self.ctx) - - # At this point we will match the (assumed) long option through - # the long option matching code. Note that this allows options - # like "-foo" to be matched as long options. - try: - self._match_long_opt(norm_long_opt, explicit_value, state) - except NoSuchOption: - # At this point the long option matching failed, and we need - # to try with short options. However there is a special rule - # which says, that if we have a two character options prefix - # (applies to "--foo" for instance), we do not dispatch to the - # short option code and will instead raise the no option - # error. - if arg[:2] not in self._opt_prefixes: - self._match_short_opt(arg, state) - return - - if not self.ignore_unknown_options: - raise - - state.largs.append(arg) - - -def __getattr__(name: str) -> object: - import warnings - - if name in { - "OptionParser", - "Argument", - "Option", - "split_opt", - "normalize_opt", - "ParsingState", - }: - warnings.warn( - f"'parser.{name}' is deprecated and will be removed in Click 9.0." - " The old parser is available in 'optparse'.", - DeprecationWarning, - stacklevel=2, - ) - return globals()[f"_{name}"] - - if name == "split_arg_string": - from .shell_completion import split_arg_string - - warnings.warn( - "Importing 'parser.split_arg_string' is deprecated, it will only be" - " available in 'shell_completion' in Click 9.0.", - DeprecationWarning, - stacklevel=2, - ) - return split_arg_string - - raise AttributeError(name) diff --git a/notification-service/venv/Lib/site-packages/click/py.typed b/notification-service/venv/Lib/site-packages/click/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/click/shell_completion.py b/notification-service/venv/Lib/site-packages/click/shell_completion.py deleted file mode 100644 index b01e290..0000000 --- a/notification-service/venv/Lib/site-packages/click/shell_completion.py +++ /dev/null @@ -1,680 +0,0 @@ -from __future__ import annotations - -import collections.abc as cabc -import os -import re -import typing as t -from gettext import gettext as _ - -from .core import Argument -from .core import Command -from .core import Context -from .core import Group -from .core import Option -from .core import Parameter -from .core import ParameterSource -from .utils import echo - - -def shell_complete( - cli: Command, - ctx_args: cabc.MutableMapping[str, t.Any], - prog_name: str, - complete_var: str, - instruction: str, -) -> int: - """Perform shell completion for the given CLI program. - - :param cli: Command being called. - :param ctx_args: Extra arguments to pass to - ``cli.make_context``. - :param prog_name: Name of the executable in the shell. - :param complete_var: Name of the environment variable that holds - the completion instruction. - :param instruction: Value of ``complete_var`` with the completion - instruction and shell, in the form ``instruction_shell``. - :return: Status code to exit with. - """ - shell, _, instruction = instruction.partition("_") - comp_cls = get_completion_class(shell) - - if comp_cls is None: - return 1 - - comp = comp_cls(cli, ctx_args, prog_name, complete_var) - - # Write bytes, otherwise Windows text stdout translates LF to CRLF and breaks. - if instruction == "source": - echo(comp.source().encode(), nl=False) - return 0 - - if instruction == "complete": - echo(comp.complete().encode()) - return 0 - - return 1 - - -class CompletionItem: - """Represents a completion value and metadata about the value. The - default metadata is ``type`` to indicate special shell handling, - and ``help`` if a shell supports showing a help string next to the - value. - - Arbitrary parameters can be passed when creating the object, and - accessed using ``item.attr``. If an attribute wasn't passed, - accessing it returns ``None``. - - :param value: The completion suggestion. - :param type: Tells the shell script to provide special completion - support for the type. Click uses ``"dir"`` and ``"file"``. - :param help: String shown next to the value if supported. - :param kwargs: Arbitrary metadata. The built-in implementations - don't use this, but custom type completions paired with custom - shell support could use it. - """ - - __slots__ = ("value", "type", "help", "_info") - - def __init__( - self, - value: t.Any, - type: str = "plain", - help: str | None = None, - **kwargs: t.Any, - ) -> None: - self.value: t.Any = value - self.type: str = type - self.help: str | None = help - self._info = kwargs - - def __getattr__(self, name: str) -> t.Any: - return self._info.get(name) - - -# Only Bash >= 4.4 has the nosort option. -_SOURCE_BASH = """\ -%(complete_func)s() { - local IFS=$'\\n' - local response - - response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD \ -%(complete_var)s=bash_complete $1) - - for completion in $response; do - IFS=',' read type value <<< "$completion" - - if [[ $type == 'dir' ]]; then - COMPREPLY=() - compopt -o dirnames - elif [[ $type == 'file' ]]; then - COMPREPLY=() - compopt -o default - elif [[ $type == 'plain' ]]; then - COMPREPLY+=($value) - fi - done - - return 0 -} - -%(complete_func)s_setup() { - complete -o nosort -F %(complete_func)s %(prog_name)s -} - -%(complete_func)s_setup; -""" - -# See ZshComplete.format_completion below, and issue #2703, before -# changing this script. -# -# (TL;DR: _describe is picky about the format, but this Zsh script snippet -# is already widely deployed. So freeze this script, and use clever-ish -# handling of colons in ZshComplet.format_completion.) -_SOURCE_ZSH = """\ -#compdef %(prog_name)s - -%(complete_func)s() { - local -a completions - local -a completions_with_descriptions - local -a response - (( ! $+commands[%(prog_name)s] )) && return 1 - - response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) \ -%(complete_var)s=zsh_complete %(prog_name)s)}") - - for type key descr in ${response}; do - if [[ "$type" == "plain" ]]; then - if [[ "$descr" == "_" ]]; then - completions+=("$key") - else - completions_with_descriptions+=("$key":"$descr") - fi - elif [[ "$type" == "dir" ]]; then - _path_files -/ - elif [[ "$type" == "file" ]]; then - _path_files -f - fi - done - - if [ -n "$completions_with_descriptions" ]; then - _describe -V unsorted completions_with_descriptions -U - fi - - if [ -n "$completions" ]; then - compadd -U -V unsorted -a completions - fi -} - -if [[ $zsh_eval_context[-1] == loadautofunc ]]; then - # autoload from fpath, call function directly - %(complete_func)s "$@" -else - # eval/source/. command, register function for later - compdef %(complete_func)s %(prog_name)s -fi -""" - -_SOURCE_FISH = """\ -function %(complete_func)s; - set -l response (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \ -COMP_CWORD=(commandline -t) %(prog_name)s); - - for completion in $response; - set -l metadata (string split \n $completion); - - if test $metadata[1] = "dir"; - __fish_complete_directories $metadata[2]; - else if test $metadata[1] = "file"; - __fish_complete_path $metadata[2]; - else if test $metadata[1] = "plain"; - if test $metadata[3] != "_"; - echo $metadata[2]\t$metadata[3]; - else; - echo $metadata[2]; - end; - end; - end; -end; - -complete --no-files --command %(prog_name)s --arguments \ -"(%(complete_func)s)"; -""" - - -class ShellComplete: - """Base class for providing shell completion support. A subclass for - a given shell will override attributes and methods to implement the - completion instructions (``source`` and ``complete``). - - :param cli: Command being called. - :param prog_name: Name of the executable in the shell. - :param complete_var: Name of the environment variable that holds - the completion instruction. - - .. versionadded:: 8.0 - """ - - name: t.ClassVar[str] - """Name to register the shell as with :func:`add_completion_class`. - This is used in completion instructions (``{name}_source`` and - ``{name}_complete``). - """ - - source_template: t.ClassVar[str] - """Completion script template formatted by :meth:`source`. This must - be provided by subclasses. - """ - - def __init__( - self, - cli: Command, - ctx_args: cabc.MutableMapping[str, t.Any], - prog_name: str, - complete_var: str, - ) -> None: - self.cli = cli - self.ctx_args = ctx_args - self.prog_name = prog_name - self.complete_var = complete_var - - @property - def func_name(self) -> str: - """The name of the shell function defined by the completion - script. - """ - safe_name = re.sub(r"\W*", "", self.prog_name.replace("-", "_"), flags=re.ASCII) - return f"_{safe_name}_completion" - - def source_vars(self) -> dict[str, t.Any]: - """Vars for formatting :attr:`source_template`. - - By default this provides ``complete_func``, ``complete_var``, - and ``prog_name``. - """ - return { - "complete_func": self.func_name, - "complete_var": self.complete_var, - "prog_name": self.prog_name, - } - - def source(self) -> str: - """Produce the shell script that defines the completion - function. By default this ``%``-style formats - :attr:`source_template` with the dict returned by - :meth:`source_vars`. - """ - return self.source_template % self.source_vars() - - def get_completion_args(self) -> tuple[list[str], str]: - """Use the env vars defined by the shell script to return a - tuple of ``args, incomplete``. This must be implemented by - subclasses. - """ - raise NotImplementedError - - def get_completions(self, args: list[str], incomplete: str) -> list[CompletionItem]: - """Determine the context and last complete command or parameter - from the complete args. Call that object's ``shell_complete`` - method to get the completions for the incomplete value. - - :param args: List of complete args before the incomplete value. - :param incomplete: Value being completed. May be empty. - """ - ctx = _resolve_context(self.cli, self.ctx_args, self.prog_name, args) - obj, incomplete = _resolve_incomplete(ctx, args, incomplete) - return obj.shell_complete(ctx, incomplete) - - def format_completion(self, item: CompletionItem) -> str: - """Format a completion item into the form recognized by the - shell script. This must be implemented by subclasses. - - :param item: Completion item to format. - """ - raise NotImplementedError - - def complete(self) -> str: - """Produce the completion data to send back to the shell. - - By default this calls :meth:`get_completion_args`, gets the - completions, then calls :meth:`format_completion` for each - completion. - """ - args, incomplete = self.get_completion_args() - completions = self.get_completions(args, incomplete) - out = [self.format_completion(item) for item in completions] - return "\n".join(out) - - -class BashComplete(ShellComplete): - """Shell completion for Bash.""" - - name = "bash" - source_template = _SOURCE_BASH - - @staticmethod - def _check_version() -> None: - import shutil - import subprocess - - bash_exe = shutil.which("bash") - - if bash_exe is None: - match = None - else: - output = subprocess.run( - [bash_exe, "--norc", "-c", 'echo "${BASH_VERSION}"'], - stdout=subprocess.PIPE, - ) - match = re.search(r"^(\d+)\.(\d+)\.\d+", output.stdout.decode()) - - if match is not None: - major, minor = match.groups() - - if major < "4" or major == "4" and minor < "4": - echo( - _( - "Shell completion is not supported for Bash" - " versions older than 4.4." - ), - err=True, - ) - else: - echo( - _("Couldn't detect Bash version, shell completion is not supported."), - err=True, - ) - - def source(self) -> str: - self._check_version() - return super().source() - - def get_completion_args(self) -> tuple[list[str], str]: - cwords = split_arg_string(os.environ["COMP_WORDS"]) - cword = int(os.environ["COMP_CWORD"]) - args = cwords[1:cword] - - try: - incomplete = cwords[cword] - except IndexError: - incomplete = "" - - return args, incomplete - - def format_completion(self, item: CompletionItem) -> str: - return f"{item.type},{item.value}" - - -class ZshComplete(ShellComplete): - """Shell completion for Zsh.""" - - name = "zsh" - source_template = _SOURCE_ZSH - - def get_completion_args(self) -> tuple[list[str], str]: - cwords = split_arg_string(os.environ["COMP_WORDS"]) - cword = int(os.environ["COMP_CWORD"]) - args = cwords[1:cword] - - try: - incomplete = cwords[cword] - except IndexError: - incomplete = "" - - return args, incomplete - - def format_completion(self, item: CompletionItem) -> str: - help_ = item.help or "_" - # The zsh completion script uses `_describe` on items with help - # texts (which splits the item help from the item value at the - # first unescaped colon) and `compadd` on items without help - # text (which uses the item value as-is and does not support - # colon escaping). So escape colons in the item value if and - # only if the item help is not the sentinel "_" value, as used - # by the completion script. - # - # (The zsh completion script is potentially widely deployed, and - # thus harder to fix than this method.) - # - # See issue #1812 and issue #2703 for further context. - value = item.value.replace(":", r"\:") if help_ != "_" else item.value - return f"{item.type}\n{value}\n{help_}" - - -class FishComplete(ShellComplete): - """Shell completion for Fish.""" - - name = "fish" - source_template = _SOURCE_FISH - - def get_completion_args(self) -> tuple[list[str], str]: - cwords = split_arg_string(os.environ["COMP_WORDS"]) - incomplete = os.environ["COMP_CWORD"] - if incomplete: - incomplete = split_arg_string(incomplete)[0] - args = cwords[1:] - - # Fish stores the partial word in both COMP_WORDS and - # COMP_CWORD, remove it from complete args. - if incomplete and args and args[-1] == incomplete: - args.pop() - - return args, incomplete - - def format_completion(self, item: CompletionItem) -> str: - """ - .. versionchanged:: 8.4.0 - Escape newlines in value and help to fix completion errors with - multi-line help strings. - """ - # The fish completion script splits each response line on literal - # newlines, so any newline in the value or help would corrupt the - # frame. Replace them with the two-character escape "\n" so the text - # round-trips through fish without breaking the format. The "_" - # sentinel for missing help mirrors :class:`ZshComplete`. - help_ = item.help or "_" - value = item.value.replace("\n", r"\n") - help_escaped = help_.replace("\n", r"\n") - return f"{item.type}\n{value}\n{help_escaped}" - - -ShellCompleteType = t.TypeVar("ShellCompleteType", bound="type[ShellComplete]") - - -_available_shells: dict[str, type[ShellComplete]] = { - "bash": BashComplete, - "fish": FishComplete, - "zsh": ZshComplete, -} - - -def add_completion_class( - cls: ShellCompleteType, name: str | None = None -) -> ShellCompleteType: - """Register a :class:`ShellComplete` subclass under the given name. - The name will be provided by the completion instruction environment - variable during completion. - - :param cls: The completion class that will handle completion for the - shell. - :param name: Name to register the class under. Defaults to the - class's ``name`` attribute. - """ - if name is None: - name = cls.name - - _available_shells[name] = cls - - return cls - - -def get_completion_class(shell: str) -> type[ShellComplete] | None: - """Look up a registered :class:`ShellComplete` subclass by the name - provided by the completion instruction environment variable. If the - name isn't registered, returns ``None``. - - :param shell: Name the class is registered under. - """ - return _available_shells.get(shell) - - -def split_arg_string(string: str) -> list[str]: - """Split an argument string as with :func:`shlex.split`, but don't - fail if the string is incomplete. Ignores a missing closing quote or - incomplete escape sequence and uses the partial token as-is. - - .. code-block:: python - - split_arg_string("example 'my file") - ["example", "my file"] - - split_arg_string("example my\\") - ["example", "my"] - - :param string: String to split. - - .. versionchanged:: 8.2 - Moved to ``shell_completion`` from ``parser``. - """ - import shlex - - lex = shlex.shlex(string, posix=True) - lex.whitespace_split = True - lex.commenters = "" - out = [] - - try: - for token in lex: - out.append(token) - except ValueError: - # Raised when end-of-string is reached in an invalid state. Use - # the partial token as-is. The quote or escape character is in - # lex.state, not lex.token. - out.append(lex.token) - - return out - - -def _is_incomplete_argument(ctx: Context, param: Parameter) -> bool: - """Determine if the given parameter is an argument that can still - accept values. - - :param ctx: Invocation context for the command represented by the - parsed complete args. - :param param: Argument object being checked. - """ - if not isinstance(param, Argument): - return False - - value = ctx.params.get(param.name) - return ( - param.nargs == -1 - or ctx.get_parameter_source(param.name) is not ParameterSource.COMMANDLINE - or ( - param.nargs > 1 - and isinstance(value, (tuple, list)) - and len(value) < param.nargs - ) - ) - - -def _start_of_option(ctx: Context, value: str) -> bool: - """Check if the value looks like the start of an option.""" - if not value: - return False - - c = value[0] - return c in ctx._opt_prefixes - - -def _is_incomplete_option(ctx: Context, args: list[str], param: Parameter) -> bool: - """Determine if the given parameter is an option that needs a value. - - :param args: List of complete args before the incomplete value. - :param param: Option object being checked. - """ - if not isinstance(param, Option): - return False - - if param.is_flag or param.count: - return False - - last_option = None - - for index, arg in enumerate(reversed(args)): - if index + 1 > param.nargs: - break - - if _start_of_option(ctx, arg): - last_option = arg - break - - return last_option is not None and last_option in param.opts - - -def _resolve_context( - cli: Command, - ctx_args: cabc.MutableMapping[str, t.Any], - prog_name: str, - args: list[str], -) -> Context: - """Produce the context hierarchy starting with the command and - traversing the complete arguments. This only follows the commands, - it doesn't trigger input prompts or callbacks. - - :param cli: Command being called. - :param prog_name: Name of the executable in the shell. - :param args: List of complete args before the incomplete value. - """ - ctx_args["resilient_parsing"] = True - with cli.make_context(prog_name, args.copy(), **ctx_args) as ctx: - args = ctx._protected_args + ctx.args - - while args: - command = ctx.command - - if isinstance(command, Group): - if not command.chain: - name, cmd, args = command.resolve_command(ctx, args) - - if cmd is None: - return ctx - - with cmd.make_context( - name, args, parent=ctx, resilient_parsing=True - ) as sub_ctx: - ctx = sub_ctx - args = ctx._protected_args + ctx.args - else: - sub_ctx = ctx - - while args: - name, cmd, args = command.resolve_command(ctx, args) - - if cmd is None: - return ctx - - with cmd.make_context( - name, - args, - parent=ctx, - allow_extra_args=True, - allow_interspersed_args=False, - resilient_parsing=True, - ) as sub_sub_ctx: - sub_ctx = sub_sub_ctx - args = sub_ctx.args - - ctx = sub_ctx - args = [*sub_ctx._protected_args, *sub_ctx.args] - else: - break - - return ctx - - -def _resolve_incomplete( - ctx: Context, args: list[str], incomplete: str -) -> tuple[Command | Parameter, str]: - """Find the Click object that will handle the completion of the - incomplete value. Return the object and the incomplete value. - - :param ctx: Invocation context for the command represented by - the parsed complete args. - :param args: List of complete args before the incomplete value. - :param incomplete: Value being completed. May be empty. - """ - # Different shells treat an "=" between a long option name and - # value differently. Might keep the value joined, return the "=" - # as a separate item, or return the split name and value. Always - # split and discard the "=" to make completion easier. - if incomplete == "=": - incomplete = "" - elif "=" in incomplete and _start_of_option(ctx, incomplete): - name, _, incomplete = incomplete.partition("=") - args.append(name) - - # The "--" marker tells Click to stop treating values as options - # even if they start with the option character. If it hasn't been - # given and the incomplete arg looks like an option, the current - # command will provide option name completions. - if "--" not in args and _start_of_option(ctx, incomplete): - return ctx.command, incomplete - - params = ctx.command.get_params(ctx) - - # If the last complete arg is an option name with an incomplete - # value, the option will provide value completions. - for param in params: - if _is_incomplete_option(ctx, args, param): - return param, incomplete - - # It's not an option name or value. The first argument without a - # parsed value will provide value completions. - for param in params: - if _is_incomplete_argument(ctx, param): - return param, incomplete - - # There were no unparsed arguments, the command may be a group that - # will provide command name completions. - return ctx.command, incomplete diff --git a/notification-service/venv/Lib/site-packages/click/termui.py b/notification-service/venv/Lib/site-packages/click/termui.py deleted file mode 100644 index 91ef6e1..0000000 --- a/notification-service/venv/Lib/site-packages/click/termui.py +++ /dev/null @@ -1,941 +0,0 @@ -from __future__ import annotations - -import collections.abc as cabc -import inspect -import io -import itertools -import re -import sys -import typing as t -from contextlib import AbstractContextManager -from contextlib import redirect_stdout -from gettext import gettext as _ - -from ._compat import isatty -from ._compat import strip_ansi -from ._compat import WIN -from .exceptions import Abort -from .exceptions import UsageError -from .globals import resolve_color_default -from .types import Choice -from .types import convert_type -from .types import ParamType -from .utils import echo -from .utils import LazyFile - -if t.TYPE_CHECKING: - from ._termui_impl import ProgressBar - -V = t.TypeVar("V") - -# The prompt functions to use. The doc tools currently override these -# functions to customize how they work. -visible_prompt_func: t.Callable[[str], str] = input - -_ansi_colors = { - "black": 30, - "red": 31, - "green": 32, - "yellow": 33, - "blue": 34, - "magenta": 35, - "cyan": 36, - "white": 37, - "reset": 39, - "bright_black": 90, - "bright_red": 91, - "bright_green": 92, - "bright_yellow": 93, - "bright_blue": 94, - "bright_magenta": 95, - "bright_cyan": 96, - "bright_white": 97, -} -_ansi_reset_all = "\033[0m" - - -_HIDDEN_INPUT_MASK = "'***'" - - -def _mask_hidden_input(message: str, value: str) -> str: - """Replace occurrences of ``value`` in ``message`` with a fixed mask. - - Both ``repr(value)`` (the form built-in :class:`ParamType` errors use - via ``{value!r}``) and the raw value are masked. The raw-value pass - uses word-boundary lookarounds so a substring like ``"1"`` does not - match inside ``"10"``, and ``"ent"`` does not match inside - ``"Authentication"``. The empty string is skipped to avoid matching - at every boundary. - """ - message = message.replace(repr(value), _HIDDEN_INPUT_MASK) - if value: - message = re.sub( - rf"(? str: - import getpass - - return getpass.getpass(prompt) - - -def _readline_prompt(func: t.Callable[[str], str], text: str, err: bool) -> str: - """Call a prompt function, passing the full prompt on non-Windows so - readline can handle line editing and cursor positioning correctly. - - On Windows the prompt is written separately via :func:`echo` for - colorama support, with only the last character passed to *func*. - """ - if WIN: - # Write the prompt separately so that we get nice coloring - # through colorama on Windows. - echo(text[:-1], nl=False, err=err) - # Echo the last character to stdout to work around an issue - # where readline causes backspace to clear the whole line. - return func(text[-1:]) - if err: - with redirect_stdout(sys.stderr): - return func(text) - return func(text) - - -def _build_prompt( - text: str, - suffix: str, - show_default: bool | str = False, - default: t.Any | None = None, - show_choices: bool = True, - type: ParamType[t.Any] | None = None, -) -> str: - prompt = text - if type is not None and show_choices and isinstance(type, Choice): - prompt += f" ({', '.join(map(str, type.choices))})" - if isinstance(show_default, str): - default = f"({show_default})" - if default is not None and show_default: - prompt = f"{prompt} [{_format_default(default)}]" - return f"{prompt}{suffix}" - - -def _format_default(default: t.Any) -> t.Any: - if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"): - return default.name - - return default - - -def prompt( - text: str, - default: t.Any | None = None, - hide_input: bool = False, - confirmation_prompt: bool | str = False, - type: ParamType[t.Any] | t.Any | None = None, - value_proc: t.Callable[[str], t.Any] | None = None, - prompt_suffix: str = ": ", - show_default: bool | str = True, - err: bool = False, - show_choices: bool = True, -) -> t.Any: - """Prompts a user for input. This is a convenience function that can - be used to prompt a user for input later. - - If the user aborts the input by sending an interrupt signal, this - function will catch it and raise a :exc:`Abort` exception. - - :param text: the text to show for the prompt. - :param default: the default value to use if no input happens. If this - is not given it will prompt until it's aborted. - :param hide_input: if this is set to true then the input value will - be hidden. - :param confirmation_prompt: Prompt a second time to confirm the - value. Can be set to a string instead of ``True`` to customize - the message. - :param type: the type to use to check the value against. - :param value_proc: if this parameter is provided it's a function that - is invoked instead of the type conversion to - convert a value. - :param prompt_suffix: a suffix that should be added to the prompt. - :param show_default: shows or hides the default value in the prompt. - If this value is a string, it shows that string - in parentheses instead of the actual value. - :param err: if set to true the file defaults to ``stderr`` instead of - ``stdout``, the same as with echo. - :param show_choices: Show or hide choices if the passed type is a Choice. - For example if type is a Choice of either day or week, - show_choices is true and text is "Group by" then the - prompt will be "Group by (day, week): ". - - .. versionchanged:: 8.3.3 - ``show_default`` can be a string to show a custom value instead - of the actual default, matching the help text behavior. - - .. versionchanged:: 8.3.1 - A space is no longer appended to the prompt. - - .. versionadded:: 8.0 - ``confirmation_prompt`` can be a custom string. - - .. versionadded:: 7.0 - Added the ``show_choices`` parameter. - - .. versionadded:: 6.0 - Added unicode support for cmd.exe on Windows. - - .. versionadded:: 4.0 - Added the `err` parameter. - - """ - - def prompt_func(text: str) -> str: - f = hidden_prompt_func if hide_input else visible_prompt_func - try: - return _readline_prompt(f, text, err) - except (KeyboardInterrupt, EOFError): - # getpass doesn't print a newline if the user aborts input with ^C. - # Allegedly this behavior is inherited from getpass(3). - # A doc bug has been filed at https://bugs.python.org/issue24711 - if hide_input: - echo(None, err=err) - raise Abort() from None - - if value_proc is None: - value_proc = convert_type(type, default) - - prompt = _build_prompt( - text, prompt_suffix, show_default, default, show_choices, type - ) - - if confirmation_prompt: - if confirmation_prompt is True: - confirmation_prompt = _("Repeat for confirmation") - - confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix) - - while True: - while True: - value = prompt_func(prompt) - if value: - break - elif default is not None: - value = default - break - try: - result = value_proc(value) - except UsageError as e: - message = _mask_hidden_input(e.message, value) if hide_input else e.message - echo(_("Error: {message}").format(message=message), err=err) - continue - if not confirmation_prompt: - return result - while True: - value2 = prompt_func(confirmation_prompt) - is_empty = not value and not value2 - if value2 or is_empty: - break - if value == value2: - return result - echo(_("Error: The two entered values do not match."), err=err) - - -def confirm( - text: str, - default: bool | None = False, - abort: bool = False, - prompt_suffix: str = ": ", - show_default: bool = True, - err: bool = False, -) -> bool: - """Prompts for confirmation (yes/no question). - - If the user aborts the input by sending a interrupt signal this - function will catch it and raise a :exc:`Abort` exception. - - :param text: the question to ask. - :param default: The default value to use when no input is given. If - ``None``, repeat until input is given. - :param abort: if this is set to `True` a negative answer aborts the - exception by raising :exc:`Abort`. - :param prompt_suffix: a suffix that should be added to the prompt. - :param show_default: shows or hides the default value in the prompt. - :param err: if set to true the file defaults to ``stderr`` instead of - ``stdout``, the same as with echo. - - .. versionchanged:: 8.3.1 - A space is no longer appended to the prompt. - - .. versionchanged:: 8.0 - Repeat until input is given if ``default`` is ``None``. - - .. versionadded:: 4.0 - Added the ``err`` parameter. - """ - prompt = _build_prompt( - text, - prompt_suffix, - show_default, - "y/n" if default is None else ("Y/n" if default else "y/N"), - ) - - while True: - try: - value = _readline_prompt(visible_prompt_func, prompt, err).lower().strip() - except (KeyboardInterrupt, EOFError): - raise Abort() from None - if value in ("y", "yes"): - rv = True - elif value in ("n", "no"): - rv = False - elif default is not None and value == "": - rv = default - else: - echo(_("Error: invalid input"), err=err) - continue - break - if abort and not rv: - raise Abort() - return rv - - -def get_pager_file( - color: bool | None = None, -) -> t.ContextManager[t.TextIO]: - """Context manager. - - Yields a writable file-like object which can be used as an output pager. - - .. versionadded:: 8.4.0 - - :param color: controls if the pager supports ANSI colors or not. The - default is autodetection. - """ - from ._termui_impl import get_pager_file - - color = resolve_color_default(color) - - return get_pager_file(color=color) - - -def echo_via_pager( - text_or_generator: cabc.Iterable[str] | t.Callable[[], cabc.Iterable[str]] | str, - color: bool | None = None, -) -> None: - """This function takes a text and shows it via an environment specific - pager on stdout. - - .. versionchanged:: 3.0 - Added the `color` flag. - - :param text_or_generator: the text to page, or alternatively, a - generator emitting the text to page. - :param color: controls if the pager supports ANSI colors or not. The - default is autodetection. - """ - - if inspect.isgeneratorfunction(text_or_generator): - i = t.cast("t.Callable[[], cabc.Iterable[str]]", text_or_generator)() - elif isinstance(text_or_generator, str): - i = [text_or_generator] - else: - i = iter(t.cast("cabc.Iterable[str]", text_or_generator)) - - # convert every element of i to a text type if necessary - text_generator = (el if isinstance(el, str) else str(el) for el in i) - - with get_pager_file(color=color) as pager: - for text in itertools.chain(text_generator, "\n"): - pager.write(text) - - -@t.overload -def progressbar( - *, - length: int, - label: str | None = None, - hidden: bool = False, - show_eta: bool = True, - show_percent: bool | None = None, - show_pos: bool = False, - fill_char: str = "#", - empty_char: str = "-", - bar_template: str = "%(label)s [%(bar)s] %(info)s", - info_sep: str = " ", - width: int = 36, - file: t.TextIO | None = None, - color: bool | None = None, - update_min_steps: int = 1, -) -> ProgressBar[int]: ... - - -@t.overload -def progressbar( - iterable: cabc.Iterable[V] | None = None, - length: int | None = None, - label: str | None = None, - hidden: bool = False, - show_eta: bool = True, - show_percent: bool | None = None, - show_pos: bool = False, - item_show_func: t.Callable[[V | None], str | None] | None = None, - fill_char: str = "#", - empty_char: str = "-", - bar_template: str = "%(label)s [%(bar)s] %(info)s", - info_sep: str = " ", - width: int = 36, - file: t.TextIO | None = None, - color: bool | None = None, - update_min_steps: int = 1, -) -> ProgressBar[V]: ... - - -def progressbar( - iterable: cabc.Iterable[V] | None = None, - length: int | None = None, - label: str | None = None, - hidden: bool = False, - show_eta: bool = True, - show_percent: bool | None = None, - show_pos: bool = False, - item_show_func: t.Callable[[V | None], str | None] | None = None, - fill_char: str = "#", - empty_char: str = "-", - bar_template: str = "%(label)s [%(bar)s] %(info)s", - info_sep: str = " ", - width: int = 36, - file: t.TextIO | None = None, - color: bool | None = None, - update_min_steps: int = 1, -) -> ProgressBar[V]: - """This function creates an iterable context manager that can be used - to iterate over something while showing a progress bar. It will - either iterate over the `iterable` or `length` items (that are counted - up). While iteration happens, this function will print a rendered - progress bar to the given `file` (defaults to stdout) and will attempt - to calculate remaining time and more. By default, this progress bar - will not be rendered if the file is not a terminal. - - The context manager creates the progress bar. When the context - manager is entered the progress bar is already created. With every - iteration over the progress bar, the iterable passed to the bar is - advanced and the bar is updated. When the context manager exits, - a newline is printed and the progress bar is finalized on screen. - - Note: The progress bar is currently designed for use cases where the - total progress can be expected to take at least several seconds. - Because of this, the ProgressBar class object won't display - progress that is considered too fast, and progress where the time - between steps is less than a second. - - No printing must happen or the progress bar will be unintentionally - destroyed. - - Example usage:: - - with progressbar(items) as bar: - for item in bar: - do_something_with(item) - - Alternatively, if no iterable is specified, one can manually update the - progress bar through the `update()` method instead of directly - iterating over the progress bar. The update method accepts the number - of steps to increment the bar with:: - - with progressbar(length=chunks.total_bytes) as bar: - for chunk in chunks: - process_chunk(chunk) - bar.update(chunks.bytes) - - The ``update()`` method also takes an optional value specifying the - ``current_item`` at the new position. This is useful when used - together with ``item_show_func`` to customize the output for each - manual step:: - - with click.progressbar( - length=total_size, - label='Unzipping archive', - item_show_func=lambda a: a.filename - ) as bar: - for archive in zip_file: - archive.extract() - bar.update(archive.size, archive) - - :param iterable: an iterable to iterate over. If not provided the length - is required. - :param length: the number of items to iterate over. By default the - progressbar will attempt to ask the iterator about its - length, which might or might not work. If an iterable is - also provided this parameter can be used to override the - length. If an iterable is not provided the progress bar - will iterate over a range of that length. - :param label: the label to show next to the progress bar. - :param hidden: hide the progressbar. Defaults to ``False``. When no tty is - detected, it will only print the progressbar label. Setting this to - ``False`` also disables that. - :param show_eta: enables or disables the estimated time display. This is - automatically disabled if the length cannot be - determined. - :param show_percent: enables or disables the percentage display. The - default is `True` if the iterable has a length or - `False` if not. - :param show_pos: enables or disables the absolute position display. The - default is `False`. - :param item_show_func: A function called with the current item which - can return a string to show next to the progress bar. If the - function returns ``None`` nothing is shown. The current item can - be ``None``, such as when entering and exiting the bar. - :param fill_char: the character to use to show the filled part of the - progress bar. - :param empty_char: the character to use to show the non-filled part of - the progress bar. - :param bar_template: the format string to use as template for the bar. - The parameters in it are ``label`` for the label, - ``bar`` for the progress bar and ``info`` for the - info section. - :param info_sep: the separator between multiple info items (eta etc.) - :param width: the width of the progress bar in characters, 0 means full - terminal width - :param file: The file to write to. If this is not a terminal then - only the label is printed. - :param color: controls if the terminal supports ANSI colors or not. The - default is autodetection. This is only needed if ANSI - codes are included anywhere in the progress bar output - which is not the case by default. - :param update_min_steps: Render only when this many updates have - completed. This allows tuning for very fast iterators. - - .. versionadded:: 8.2 - The ``hidden`` argument. - - .. versionchanged:: 8.0 - Output is shown even if execution time is less than 0.5 seconds. - - .. versionchanged:: 8.0 - ``item_show_func`` shows the current item, not the previous one. - - .. versionchanged:: 8.0 - Labels are echoed if the output is not a TTY. Reverts a change - in 7.0 that removed all output. - - .. versionadded:: 8.0 - The ``update_min_steps`` parameter. - - .. versionadded:: 4.0 - The ``color`` parameter and ``update`` method. - - .. versionadded:: 2.0 - """ - from ._termui_impl import ProgressBar - - color = resolve_color_default(color) - return ProgressBar( - iterable=iterable, - length=length, - hidden=hidden, - show_eta=show_eta, - show_percent=show_percent, - show_pos=show_pos, - item_show_func=item_show_func, - fill_char=fill_char, - empty_char=empty_char, - bar_template=bar_template, - info_sep=info_sep, - file=file, - label=label, - width=width, - color=color, - update_min_steps=update_min_steps, - ) - - -def clear() -> None: - """Clears the terminal screen. This will have the effect of clearing - the whole visible space of the terminal and moving the cursor to the - top left. This does not do anything if not connected to a terminal. - - .. versionadded:: 2.0 - """ - if not isatty(sys.stdout): - return - - # ANSI escape \033[2J clears the screen, \033[1;1H moves the cursor - echo("\033[2J\033[1;1H", nl=False) - - -def _interpret_color(color: int | tuple[int, int, int] | str, offset: int = 0) -> str: - if isinstance(color, int): - return f"{38 + offset};5;{color:d}" - - if isinstance(color, (tuple, list)): - r, g, b = color - return f"{38 + offset};2;{r:d};{g:d};{b:d}" - - return str(_ansi_colors[color] + offset) - - -def style( - text: t.Any, - fg: int | tuple[int, int, int] | str | None = None, - bg: int | tuple[int, int, int] | str | None = None, - bold: bool | None = None, - dim: bool | None = None, - underline: bool | None = None, - overline: bool | None = None, - italic: bool | None = None, - blink: bool | None = None, - reverse: bool | None = None, - strikethrough: bool | None = None, - reset: bool = True, -) -> str: - """Styles a text with ANSI styles and returns the new string. By - default the styling is self contained which means that at the end - of the string a reset code is issued. This can be prevented by - passing ``reset=False``. - - Examples:: - - click.echo(click.style('Hello World!', fg='green')) - click.echo(click.style('ATTENTION!', blink=True)) - click.echo(click.style('Some things', reverse=True, fg='cyan')) - click.echo(click.style('More colors', fg=(255, 12, 128), bg=117)) - - Supported color names: - - * ``black`` (might be a gray) - * ``red`` - * ``green`` - * ``yellow`` (might be an orange) - * ``blue`` - * ``magenta`` - * ``cyan`` - * ``white`` (might be light gray) - * ``bright_black`` - * ``bright_red`` - * ``bright_green`` - * ``bright_yellow`` - * ``bright_blue`` - * ``bright_magenta`` - * ``bright_cyan`` - * ``bright_white`` - * ``reset`` (reset the color code only) - - If the terminal supports it, color may also be specified as: - - - An integer in the interval [0, 255]. The terminal must support - 8-bit/256-color mode. - - An RGB tuple of three integers in [0, 255]. The terminal must - support 24-bit/true-color mode. - - See https://en.wikipedia.org/wiki/ANSI_color and - https://gist.github.com/XVilka/8346728 for more information. - - :param text: the string to style with ansi codes. - :param fg: if provided this will become the foreground color. - :param bg: if provided this will become the background color. - :param bold: if provided this will enable or disable bold mode. - :param dim: if provided this will enable or disable dim mode. This is - badly supported. - :param underline: if provided this will enable or disable underline. - :param overline: if provided this will enable or disable overline. - :param italic: if provided this will enable or disable italic. - :param blink: if provided this will enable or disable blinking. - :param reverse: if provided this will enable or disable inverse - rendering (foreground becomes background and the - other way round). - :param strikethrough: if provided this will enable or disable - striking through text. - :param reset: by default a reset-all code is added at the end of the - string which means that styles do not carry over. This - can be disabled to compose styles. - - .. versionchanged:: 8.0 - A non-string ``message`` is converted to a string. - - .. versionchanged:: 8.0 - Added support for 256 and RGB color codes. - - .. versionchanged:: 8.0 - Added the ``strikethrough``, ``italic``, and ``overline`` - parameters. - - .. versionchanged:: 7.0 - Added support for bright colors. - - .. versionadded:: 2.0 - """ - if not isinstance(text, str): - text = str(text) - - bits = [] - - if fg: - try: - bits.append(f"\033[{_interpret_color(fg)}m") - except KeyError: - raise TypeError(_("Unknown color {colour!r}").format(colour=fg)) from None - - if bg: - try: - bits.append(f"\033[{_interpret_color(bg, 10)}m") - except KeyError: - raise TypeError(_("Unknown color {colour!r}").format(colour=bg)) from None - - if bold is not None: - bits.append(f"\033[{1 if bold else 22}m") - if dim is not None: - bits.append(f"\033[{2 if dim else 22}m") - if underline is not None: - bits.append(f"\033[{4 if underline else 24}m") - if overline is not None: - bits.append(f"\033[{53 if overline else 55}m") - if italic is not None: - bits.append(f"\033[{3 if italic else 23}m") - if blink is not None: - bits.append(f"\033[{5 if blink else 25}m") - if reverse is not None: - bits.append(f"\033[{7 if reverse else 27}m") - if strikethrough is not None: - bits.append(f"\033[{9 if strikethrough else 29}m") - bits.append(text) - if reset: - bits.append(_ansi_reset_all) - return "".join(bits) - - -def unstyle(text: str) -> str: - """Removes ANSI styling information from a string. Usually it's not - necessary to use this function as Click's echo function will - automatically remove styling if necessary. - - .. versionadded:: 2.0 - - :param text: the text to remove style information from. - """ - return strip_ansi(text) - - -def secho( - message: t.Any | None = None, - file: t.IO[t.AnyStr] | None = None, - nl: bool = True, - err: bool = False, - color: bool | None = None, - **styles: t.Any, -) -> None: - """This function combines :func:`echo` and :func:`style` into one - call. As such the following two calls are the same:: - - click.secho('Hello World!', fg='green') - click.echo(click.style('Hello World!', fg='green')) - - All keyword arguments are forwarded to the underlying functions - depending on which one they go with. - - Non-string types will be converted to :class:`str`. However, - :class:`bytes` are passed directly to :meth:`echo` without applying - style. If you want to style bytes that represent text, call - :meth:`bytes.decode` first. - - .. versionchanged:: 8.0 - A non-string ``message`` is converted to a string. Bytes are - passed through without style applied. - - .. versionadded:: 2.0 - """ - if message is not None and not isinstance(message, (bytes, bytearray)): - message = style(message, **styles) - - return echo(message, file=file, nl=nl, err=err, color=color) - - -@t.overload -def edit( - text: bytes | bytearray, - editor: str | None = None, - env: cabc.Mapping[str, str] | None = None, - require_save: bool = False, - extension: str = ".txt", -) -> bytes | None: ... - - -@t.overload -def edit( - text: str, - editor: str | None = None, - env: cabc.Mapping[str, str] | None = None, - require_save: bool = True, - extension: str = ".txt", -) -> str | None: ... - - -@t.overload -def edit( - text: None = None, - editor: str | None = None, - env: cabc.Mapping[str, str] | None = None, - require_save: bool = True, - extension: str = ".txt", - filename: str | cabc.Iterable[str] | None = None, -) -> None: ... - - -def edit( - text: str | bytes | bytearray | None = None, - editor: str | None = None, - env: cabc.Mapping[str, str] | None = None, - require_save: bool = True, - extension: str = ".txt", - filename: str | cabc.Iterable[str] | None = None, -) -> str | bytes | bytearray | None: - r"""Edits the given text in the defined editor. If an editor is given - (should be the full path to the executable but the regular operating - system search path is used for finding the executable) it overrides - the detected editor. Optionally, some environment variables can be - used. If the editor is closed without changes, `None` is returned. In - case a file is edited directly the return value is always `None` and - `require_save` and `extension` are ignored. - - If the editor cannot be opened a :exc:`UsageError` is raised. - - Note for Windows: to simplify cross-platform usage, the newlines are - automatically converted from POSIX to Windows and vice versa. As such, - the message here will have ``\n`` as newline markers. - - :param text: the text to edit. - :param editor: optionally the editor to use. Defaults to automatic - detection. - :param env: environment variables to forward to the editor. - :param require_save: if this is true, then not saving in the editor - will make the return value become `None`. - :param extension: the extension to tell the editor about. This defaults - to `.txt` but changing this might change syntax - highlighting. - :param filename: if provided it will edit this file instead of the - provided text contents. It will not use a temporary - file as an indirection in that case. If the editor supports - editing multiple files at once, a sequence of files may be - passed as well. Invoke `click.file` once per file instead - if multiple files cannot be managed at once or editing the - files serially is desired. - - .. versionchanged:: 8.2.0 - ``filename`` now accepts any ``Iterable[str]`` in addition to a ``str`` - if the ``editor`` supports editing multiple files at once. - - """ - from ._termui_impl import Editor - - ed = Editor(editor=editor, env=env, require_save=require_save, extension=extension) - - if filename is None: - return ed.edit(text) - - if isinstance(filename, str): - filename = (filename,) - - ed.edit_files(filenames=filename) - return None - - -def launch(url: str, wait: bool = False, locate: bool = False) -> int: - """This function launches the given URL (or filename) in the default - viewer application for this file type. If this is an executable, it - might launch the executable in a new session. The return value is - the exit code of the launched application. Usually, ``0`` indicates - success. - - Examples:: - - click.launch('https://click.palletsprojects.com/') - click.launch('/my/downloaded/file', locate=True) - - .. versionadded:: 2.0 - - :param url: URL or filename of the thing to launch. - :param wait: Wait for the program to exit before returning. This - only works if the launched program blocks. In particular, - ``xdg-open`` on Linux does not block. - :param locate: if this is set to `True` then instead of launching the - application associated with the URL it will attempt to - launch a file manager with the file located. This - might have weird effects if the URL does not point to - the filesystem. - """ - from ._termui_impl import open_url - - return open_url(url, wait=wait, locate=locate) - - -# If this is provided, getchar() calls into this instead. This is used -# for unittesting purposes. -_getchar: t.Callable[[bool], str] | None = None - - -def getchar(echo: bool = False) -> str: - """Fetches a single character from the terminal and returns it. This - will always return a unicode character and under certain rare - circumstances this might return more than one character. The - situations which more than one character is returned is when for - whatever reason multiple characters end up in the terminal buffer or - standard input was not actually a terminal. - - Note that this will always read from the terminal, even if something - is piped into the standard input. - - Note for Windows: in rare cases when typing non-ASCII characters, this - function might wait for a second character and then return both at once. - This is because certain Unicode characters look like special-key markers. - - .. versionadded:: 2.0 - - :param echo: if set to `True`, the character read will also show up on - the terminal. The default is to not show it. - """ - global _getchar - - if _getchar is None: - from ._termui_impl import getchar as f - - _getchar = f - - return _getchar(echo) - - -def raw_terminal() -> AbstractContextManager[int]: - from ._termui_impl import raw_terminal as f - - return f() - - -def pause(info: str | None = None, err: bool = False) -> None: - """This command stops execution and waits for the user to press any - key to continue. This is similar to the Windows batch "pause" - command. If the program is not run through a terminal, this command - will instead do nothing. - - .. versionadded:: 2.0 - - .. versionadded:: 4.0 - Added the `err` parameter. - - :param info: The message to print before pausing. Defaults to - ``"Press any key to continue..."``. - :param err: if set to message goes to ``stderr`` instead of - ``stdout``, the same as with echo. - """ - if not isatty(sys.stdin) or not isatty(sys.stdout): - return - - if info is None: - info = _("Press any key to continue...") - - try: - if info: - echo(info, nl=False, err=err) - try: - getchar() - except (KeyboardInterrupt, EOFError): - pass - finally: - if info: - echo(err=err) diff --git a/notification-service/venv/Lib/site-packages/click/testing.py b/notification-service/venv/Lib/site-packages/click/testing.py deleted file mode 100644 index 1eb81d2..0000000 --- a/notification-service/venv/Lib/site-packages/click/testing.py +++ /dev/null @@ -1,736 +0,0 @@ -from __future__ import annotations - -import collections.abc as cabc -import contextlib -import io -import os -import pdb -import shlex -import sys -import tempfile -import typing as t -from types import TracebackType - -from . import _compat -from . import formatting -from . import termui -from . import utils -from ._compat import _find_binary_reader - -if t.TYPE_CHECKING: - from _typeshed import ReadableBuffer - - from .core import Command - -CaptureMode = t.Literal["sys", "fd"] - - -class EchoingStdin: - def __init__(self, input: t.BinaryIO, output: t.BinaryIO) -> None: - self._input = input - self._output = output - self._paused = False - - def __getattr__(self, x: str) -> t.Any: - return getattr(self._input, x) - - def _echo(self, rv: bytes) -> bytes: - if not self._paused: - self._output.write(rv) - - return rv - - def read(self, n: int = -1) -> bytes: - return self._echo(self._input.read(n)) - - def read1(self, n: int = -1) -> bytes: - return self._echo(self._input.read1(n)) # type: ignore - - def readline(self, n: int = -1) -> bytes: - return self._echo(self._input.readline(n)) - - def readlines(self) -> list[bytes]: - return [self._echo(x) for x in self._input.readlines()] - - def __iter__(self) -> cabc.Iterator[bytes]: - return iter(self._echo(x) for x in self._input) - - def __repr__(self) -> str: - return repr(self._input) - - -@contextlib.contextmanager -def _pause_echo(stream: EchoingStdin | None) -> cabc.Iterator[None]: - if stream is None: - yield - else: - stream._paused = True - yield - stream._paused = False - - -class _FDCapture: - """Redirect a file descriptor to a temporary file for capture. - - Saves the current target of *targetfd* via :func:`os.dup`, then - redirects it to a temporary file via :func:`os.dup2`. On - :meth:`stop`, restores the original ``fd`` and returns the captured - bytes. Inspired by Pytest's ``FDCapture``. - - .. versionadded:: 8.4.0 - """ - - def __init__(self, targetfd: int) -> None: - self._targetfd = targetfd - self.saved_fd: int = -1 - self._tmpfile: t.BinaryIO | None = None - - def start(self) -> None: - self.saved_fd = os.dup(self._targetfd) - self._tmpfile = tempfile.TemporaryFile(buffering=0) - os.dup2(self._tmpfile.fileno(), self._targetfd) - - def stop(self) -> bytes: - assert self._tmpfile is not None, "_FDCapture.start() was not called" - os.dup2(self.saved_fd, self._targetfd) - os.close(self.saved_fd) - self.saved_fd = -1 - self._tmpfile.seek(0) - data = self._tmpfile.read() - self._tmpfile.close() - self._tmpfile = None - return data - - -class BytesIOCopy(io.BytesIO): - """Patch ``io.BytesIO`` to let the written stream be copied to another. - - .. versionadded:: 8.2 - """ - - def __init__(self, copy_to: io.BytesIO) -> None: - super().__init__() - self.copy_to = copy_to - - def flush(self) -> None: - super().flush() - self.copy_to.flush() - - def write(self, b: ReadableBuffer) -> int: - self.copy_to.write(b) - return super().write(b) - - -class StreamMixer: - """Mixes `` and `` streams. - - The result is available in the ``output`` attribute. - - .. versionadded:: 8.2 - """ - - def __init__(self) -> None: - self.output: io.BytesIO = io.BytesIO() - self.stdout: io.BytesIO = BytesIOCopy(copy_to=self.output) - self.stderr: io.BytesIO = BytesIOCopy(copy_to=self.output) - - -class _NamedTextIOWrapper(io.TextIOWrapper): - """A :class:`~io.TextIOWrapper` with custom ``name`` and ``mode`` - that does not close its underlying buffer. - - When ``CliRunner`` runs in ``fd`` mode, ``_original_fd`` is patched to - point at the saved (pre-redirection) ``fd``, so C-level consumers that call - :meth:`fileno` (like ``faulthandler`` or ``subprocess``) keep working. In - the default ``sys`` mode ``_original_fd`` stays at ``-1`` and - :meth:`fileno` raises :exc:`io.UnsupportedOperation`, matching the - pre-``8.3.3`` behavior. - """ - - def __init__( - self, - buffer: t.BinaryIO, - name: str, - mode: str, - **kwargs: t.Any, - ) -> None: - super().__init__(buffer, **kwargs) - self._name = name - self._mode = mode - self._original_fd: int = -1 - - def close(self) -> None: - """The buffer this object contains belongs to some other object, - so prevent the default ``__del__`` implementation from closing - that buffer. - - .. versionadded:: 8.3.2 - """ - - def fileno(self) -> int: - """Return the file descriptor of the saved original stream when - ``CliRunner`` runs in ``fd`` mode. Otherwise delegate to - :class:`~io.TextIOWrapper`, which raises - :exc:`io.UnsupportedOperation` for a ``BytesIO``-backed buffer. - """ - if self._original_fd >= 0: - return self._original_fd - return super().fileno() - - @property - def name(self) -> str: - return self._name - - @property - def mode(self) -> str: - return self._mode - - -def make_input_stream( - input: str | bytes | t.IO[t.Any] | None, charset: str -) -> t.BinaryIO: - # Is already an input stream. - if hasattr(input, "read"): - rv = _find_binary_reader(t.cast("t.IO[t.Any]", input)) - - if rv is not None: - return rv - - raise TypeError("Could not find binary reader for input stream.") - - if input is None: - input = b"" - elif isinstance(input, str): - input = input.encode(charset) - - return io.BytesIO(input) - - -class Result: - """Holds the captured result of an invoked CLI script. - - :param runner: The runner that created the result - :param stdout_bytes: The standard output as bytes. - :param stderr_bytes: The standard error as bytes. - :param output_bytes: A mix of ``stdout_bytes`` and ``stderr_bytes``, as the - user would see it in its terminal. - :param return_value: The value returned from the invoked command. - :param exit_code: The exit code as integer. - :param exception: The exception that happened if one did. - :param exc_info: Exception information (exception type, exception instance, - traceback type). - - .. versionchanged:: 8.2 - ``stderr_bytes`` no longer optional, ``output_bytes`` introduced and - ``mix_stderr`` has been removed. - - .. versionadded:: 8.0 - Added ``return_value``. - """ - - def __init__( - self, - runner: CliRunner, - stdout_bytes: bytes, - stderr_bytes: bytes, - output_bytes: bytes, - return_value: t.Any, - exit_code: int, - exception: BaseException | None, - exc_info: tuple[type[BaseException], BaseException, TracebackType] - | None = None, - ): - self.runner = runner - self.stdout_bytes = stdout_bytes - self.stderr_bytes = stderr_bytes - self.output_bytes = output_bytes - self.return_value = return_value - self.exit_code = exit_code - self.exception = exception - self.exc_info = exc_info - - @property - def output(self) -> str: - """The terminal output as unicode string, as the user would see it. - - .. versionchanged:: 8.2 - No longer a proxy for ``self.stdout``. Now has its own independent stream - that is mixing `` and ``, in the order they were written. - """ - return self.output_bytes.decode(self.runner.charset, "replace").replace( - "\r\n", "\n" - ) - - @property - def stdout(self) -> str: - """The standard output as unicode string.""" - return self.stdout_bytes.decode(self.runner.charset, "replace").replace( - "\r\n", "\n" - ) - - @property - def stderr(self) -> str: - """The standard error as unicode string. - - .. versionchanged:: 8.2 - No longer raise an exception, always returns the `` string. - """ - return self.stderr_bytes.decode(self.runner.charset, "replace").replace( - "\r\n", "\n" - ) - - def __repr__(self) -> str: - exc_str = repr(self.exception) if self.exception else "okay" - return f"<{type(self).__name__} {exc_str}>" - - -class CliRunner: - """The CLI runner provides functionality to invoke a Click command line - script for unittesting purposes in a isolated environment. This only - works in single-threaded systems without any concurrency as it changes the - global interpreter state. - - :param charset: the character set for the input and output data. - :param env: a dictionary with environment variables for overriding. - :param echo_stdin: if this is set to `True`, then reading from `` writes - to ``. This is useful for showing examples in - some circumstances. Note that regular prompts - will automatically echo the input. - :param catch_exceptions: Whether to catch any exceptions other than - ``SystemExit`` when running :meth:`~CliRunner.invoke`. - :param capture: Selects the output capture strategy. ``sys`` (default) - captures Python-level writes only and leaves - :meth:`sys.stdout.fileno` raising :exc:`io.UnsupportedOperation`, so - user code that calls :func:`os.dup2` on ``sys.stdout.fileno()`` cannot - clobber the host runner's stdout. ``fd`` redirects file descriptors - ``1`` and ``2`` via :func:`os.dup2` to a temporary file, also catching - output from stale stream references, C extensions, and subprocesses. - ``fd`` is not supported on Windows. - - .. versionchanged:: 8.4.0 - Added the ``capture`` parameter. The default ``sys`` mode no longer - exposes the original fd through :meth:`fileno`, reverting the change - introduced in ``8.3.3`` that broke Pytest's ``fd``-level capture - teardown. Use ``capture="fd"`` to restore that behavior with proper - isolation. :issue:`3384` - - .. versionchanged:: 8.2 - Added the ``catch_exceptions`` parameter. - - .. versionchanged:: 8.2 - ``mix_stderr`` parameter has been removed. - """ - - def __init__( - self, - charset: str = "utf-8", - env: cabc.Mapping[str, str | None] | None = None, - echo_stdin: bool = False, - catch_exceptions: bool = True, - capture: CaptureMode = "sys", - ) -> None: - if capture not in {"sys", "fd"}: - raise ValueError( - f"capture={capture!r} is not valid. Choose from 'sys' or 'fd'." - ) - if capture == "fd" and sys.platform == "win32": - raise ValueError( - f"capture={capture!r} is not supported on Windows. Use 'sys'." - ) - self.charset = charset - self.env: cabc.Mapping[str, str | None] = env or {} - self.echo_stdin = echo_stdin - self.catch_exceptions = catch_exceptions - self.capture: CaptureMode = capture - - def get_default_prog_name(self, cli: Command) -> str: - """Given a command object it will return the default program name - for it. The default is the `name` attribute or ``"root"`` if not - set. - """ - return cli.name or "root" - - def make_env( - self, overrides: cabc.Mapping[str, str | None] | None = None - ) -> cabc.Mapping[str, str | None]: - """Returns the environment overrides for invoking a script.""" - rv = dict(self.env) - if overrides: - rv.update(overrides) - return rv - - @contextlib.contextmanager - def isolation( - self, - input: str | bytes | t.IO[t.Any] | None = None, - env: cabc.Mapping[str, str | None] | None = None, - color: bool = False, - ) -> cabc.Iterator[tuple[io.BytesIO, io.BytesIO, io.BytesIO]]: - """A context manager that sets up the isolation for invoking of a - command line tool. This sets up `` with the given input data - and `os.environ` with the overrides from the given dictionary. - This also rebinds some internals in Click to be mocked (like the - prompt functionality). - - This is automatically done in the :meth:`invoke` method. - - :param input: the input stream to put into `sys.stdin`. - :param env: the environment overrides as dictionary. - :param color: whether the output should contain color codes. The - application can still override this explicitly. - - .. versionadded:: 8.2 - An additional output stream is returned, which is a mix of - `` and `` streams. - - .. versionchanged:: 8.2 - Always returns the `` stream. - - .. versionchanged:: 8.0 - `` is opened with ``errors="backslashreplace"`` - instead of the default ``"strict"``. - - .. versionchanged:: 4.0 - Added the ``color`` parameter. - """ - bytes_input = make_input_stream(input, self.charset) - echo_input = None - - old_stdin = sys.stdin - old_stdout = sys.stdout - old_stderr = sys.stderr - old_forced_width = formatting.FORCED_WIDTH - formatting.FORCED_WIDTH = 80 - - env = self.make_env(env) - - stream_mixer = StreamMixer() - - if self.echo_stdin: - bytes_input = echo_input = t.cast( - t.BinaryIO, EchoingStdin(bytes_input, stream_mixer.stdout) - ) - - sys.stdin = text_input = _NamedTextIOWrapper( - bytes_input, encoding=self.charset, name="", mode="r" - ) - - if self.echo_stdin: - # Force unbuffered reads, otherwise TextIOWrapper reads a - # large chunk which is echoed early. - text_input._CHUNK_SIZE = 1 # type: ignore - - sys.stdout = _NamedTextIOWrapper( - stream_mixer.stdout, - encoding=self.charset, - name="", - mode="w", - ) - - sys.stderr = _NamedTextIOWrapper( - stream_mixer.stderr, - encoding=self.charset, - name="", - mode="w", - errors="backslashreplace", - ) - - @_pause_echo(echo_input) # type: ignore - def visible_input(prompt: str | None = None) -> str: - sys.stdout.write(prompt or "") - try: - val = next(text_input).rstrip("\r\n") - except StopIteration as e: - raise EOFError() from e - sys.stdout.write(f"{val}\n") - sys.stdout.flush() - return val - - @_pause_echo(echo_input) # type: ignore - def hidden_input(prompt: str | None = None) -> str: - sys.stdout.write(f"{prompt or ''}\n") - sys.stdout.flush() - try: - return next(text_input).rstrip("\r\n") - except StopIteration as e: - raise EOFError() from e - - @_pause_echo(echo_input) # type: ignore - def _getchar(echo: bool) -> str: - char = sys.stdin.read(1) - - if echo: - sys.stdout.write(char) - - sys.stdout.flush() - return char - - default_color = color - - def should_strip_ansi( - stream: t.IO[t.Any] | None = None, color: bool | None = None - ) -> bool: - if color is None: - return not default_color - return not color - - old_visible_prompt_func = termui.visible_prompt_func - old_hidden_prompt_func = termui.hidden_prompt_func - old__getchar_func = termui._getchar - old_should_strip_ansi = utils.should_strip_ansi # type: ignore - old__compat_should_strip_ansi = _compat.should_strip_ansi - old_pdb_init = pdb.Pdb.__init__ - termui.visible_prompt_func = visible_input - termui.hidden_prompt_func = hidden_input - termui._getchar = _getchar - utils.should_strip_ansi = should_strip_ansi # type: ignore - _compat.should_strip_ansi = should_strip_ansi - - def _patched_pdb_init( - self: pdb.Pdb, - completekey: str = "tab", - stdin: t.IO[str] | None = None, - stdout: t.IO[str] | None = None, - **kwargs: t.Any, - ) -> None: - """Default ``pdb.Pdb`` to real terminal streams during - ``CliRunner`` isolation. - - Without this patch, ``pdb.Pdb.__init__`` inherits from - ``cmd.Cmd`` which falls back to ``sys.stdin``/``sys.stdout`` - when no explicit streams are provided. During isolation - those are ``BytesIO``-backed wrappers, so the debugger - reads from an empty buffer and writes to captured output, - making interactive debugging impossible. - - By defaulting to ``sys.__stdin__``/``sys.__stdout__`` (the - original terminal streams Python preserves regardless of - redirection), debuggers can interact with the user while - ``click.echo`` output is still captured normally. - - This covers ``pdb.set_trace()``, ``breakpoint()``, - ``pdb.post_mortem()``, and debuggers that subclass - ``pdb.Pdb`` (ipdb, pdbpp). Explicit ``stdin``/``stdout`` - arguments are honored and not overridden. Debuggers that - do not subclass ``pdb.Pdb`` (pudb, debugpy) are not - covered. - """ - if stdin is None: - stdin = sys.__stdin__ - if stdout is None: - stdout = sys.__stdout__ - old_pdb_init( - self, completekey=completekey, stdin=stdin, stdout=stdout, **kwargs - ) - - pdb.Pdb.__init__ = _patched_pdb_init # type: ignore[assignment] - - old_env = {} - try: - for key, value in env.items(): - old_env[key] = os.environ.get(key) - if value is None: - try: - del os.environ[key] - except Exception: - pass - else: - os.environ[key] = value - yield (stream_mixer.stdout, stream_mixer.stderr, stream_mixer.output) - finally: - for key, value in old_env.items(): - if value is None: - try: - del os.environ[key] - except Exception: - pass - else: - os.environ[key] = value - sys.stdout = old_stdout - sys.stderr = old_stderr - sys.stdin = old_stdin - termui.visible_prompt_func = old_visible_prompt_func - termui.hidden_prompt_func = old_hidden_prompt_func - termui._getchar = old__getchar_func - utils.should_strip_ansi = old_should_strip_ansi # type: ignore - _compat.should_strip_ansi = old__compat_should_strip_ansi - formatting.FORCED_WIDTH = old_forced_width - pdb.Pdb.__init__ = old_pdb_init # type: ignore[method-assign] - - def invoke( - self, - cli: Command, - args: str | cabc.Sequence[str] | None = None, - input: str | bytes | t.IO[t.Any] | None = None, - env: cabc.Mapping[str, str | None] | None = None, - catch_exceptions: bool | None = None, - color: bool = False, - **extra: t.Any, - ) -> Result: - """Invokes a command in an isolated environment. The arguments are - forwarded directly to the command line script, the `extra` keyword - arguments are passed to the :meth:`~clickpkg.Command.main` function of - the command. - - This returns a :class:`Result` object. - - :param cli: the command to invoke - :param args: the arguments to invoke. It may be given as an iterable - or a string. When given as string it will be interpreted - as a Unix shell command. More details at - :func:`shlex.split`. - :param input: the input data for `sys.stdin`. - :param env: the environment overrides. - :param catch_exceptions: Whether to catch any other exceptions than - ``SystemExit``. If :data:`None`, the value - from :class:`CliRunner` is used. - :param extra: the keyword arguments to pass to :meth:`main`. - :param color: whether the output should contain color codes. The - application can still override this explicitly. - - .. versionadded:: 8.2 - The result object has the ``output_bytes`` attribute with - the mix of ``stdout_bytes`` and ``stderr_bytes``, as the user would - see it in its terminal. - - .. versionchanged:: 8.2 - The result object always returns the ``stderr_bytes`` stream. - - .. versionchanged:: 8.0 - The result object has the ``return_value`` attribute with - the value returned from the invoked command. - - .. versionchanged:: 4.0 - Added the ``color`` parameter. - - .. versionchanged:: 3.0 - Added the ``catch_exceptions`` parameter. - - .. versionchanged:: 3.0 - The result object has the ``exc_info`` attribute with the - traceback if available. - """ - exc_info = None - if catch_exceptions is None: - catch_exceptions = self.catch_exceptions - - # Set up fd capture before isolation replaces sys.stdout and sys.stderr. - cap_out: _FDCapture | None = None - cap_err: _FDCapture | None = None - - if self.capture == "fd": - cap_out = _FDCapture(1) - cap_err = _FDCapture(2) - try: - cap_out.start() - cap_err.start() - except OSError: - cap_out = cap_err = None - - with self.isolation(input=input, env=env, color=color) as outstreams: - # Point the captured streams' fileno() at the saved (original) - # fd so that C-level consumers like faulthandler keep working - # while fd 1/2 are redirected to the capture tmpfile. - if cap_out is not None and cap_err is not None: - sys.stdout._original_fd = cap_out.saved_fd # type: ignore[union-attr] - sys.stderr._original_fd = cap_err.saved_fd # type: ignore[union-attr] - - return_value = None - exception: BaseException | None = None - exit_code = 0 - - if isinstance(args, str): - args = shlex.split(args) - - try: - prog_name = extra.pop("prog_name") - except KeyError: - prog_name = self.get_default_prog_name(cli) - - try: - return_value = cli.main(args=args or (), prog_name=prog_name, **extra) - except SystemExit as e: - exc_info = sys.exc_info() - e_code = t.cast("int | t.Any | None", e.code) - - if e_code is None: - e_code = 0 - - if e_code != 0: - exception = e - - if not isinstance(e_code, int): - sys.stdout.write(str(e_code)) - sys.stdout.write("\n") - e_code = 1 - - exit_code = e_code - - except Exception as e: - if not catch_exceptions: - raise - exception = e - exit_code = 1 - exc_info = sys.exc_info() - finally: - sys.stdout.flush() - sys.stderr.flush() - - # Stop fd capture and merge the captured bytes into - # the stdout/stderr BytesIO streams. BytesIOCopy mirrors - # those writes into outstreams[2] automatically. - if cap_out is not None and cap_err is not None: - fd_out = cap_out.stop() - fd_err = cap_err.stop() - if fd_out: - outstreams[0].write(fd_out) - if fd_err: - outstreams[1].write(fd_err) - - stdout = outstreams[0].getvalue() - stderr = outstreams[1].getvalue() - output = outstreams[2].getvalue() - - return Result( - runner=self, - stdout_bytes=stdout, - stderr_bytes=stderr, - output_bytes=output, - return_value=return_value, - exit_code=exit_code, - exception=exception, - exc_info=exc_info, # type: ignore - ) - - @contextlib.contextmanager - def isolated_filesystem( - self, temp_dir: str | os.PathLike[str] | None = None - ) -> cabc.Iterator[str]: - """A context manager that creates a temporary directory and - changes the current working directory to it. This isolates tests - that affect the contents of the CWD to prevent them from - interfering with each other. - - :param temp_dir: Create the temporary directory under this - directory. If given, the created directory is not removed - when exiting. - - .. versionchanged:: 8.0 - Added the ``temp_dir`` parameter. - """ - cwd = os.getcwd() - dt = tempfile.mkdtemp(dir=temp_dir) - os.chdir(dt) - - try: - yield dt - finally: - os.chdir(cwd) - - if temp_dir is None: - import shutil - - try: - shutil.rmtree(dt) - except OSError: - pass diff --git a/notification-service/venv/Lib/site-packages/click/types.py b/notification-service/venv/Lib/site-packages/click/types.py deleted file mode 100644 index 98c2d61..0000000 --- a/notification-service/venv/Lib/site-packages/click/types.py +++ /dev/null @@ -1,1309 +0,0 @@ -from __future__ import annotations - -import abc -import collections.abc as cabc -import enum -import os -import stat -import sys -import typing as t -import uuid -from datetime import datetime -from gettext import gettext as _ -from gettext import ngettext - -from ._compat import _get_argv_encoding -from ._compat import open_stream -from .exceptions import BadParameter -from .utils import format_filename -from .utils import LazyFile -from .utils import safecall - -if t.TYPE_CHECKING: - import typing_extensions as te - - from .core import Context - from .core import Parameter - from .shell_completion import CompletionItem - -ParamTypeValue = t.TypeVar("ParamTypeValue") - - -class ParamTypeInfoDict(t.TypedDict): - param_type: str - name: str - - -class ParamType(t.Generic[ParamTypeValue], abc.ABC): - """Represents the type of a parameter. Validates and converts values - from the command line or Python into the correct type. - - To implement a custom type, subclass and implement at least the - following: - - - The :attr:`name` class attribute must be set. - - Calling an instance of the type with ``None`` must return - ``None``. This is already implemented by default. - - :meth:`convert` must convert string values to the correct type. - - :meth:`convert` must accept values that are already the correct - type. - - It must be able to convert a value if the ``ctx`` and ``param`` - arguments are ``None``. This can occur when converting prompt - input. - - .. versionchanged:: 8.4.0 - Now a generic abstract base class. Parameterize with the - converted value type (``ParamType[int]`` for an integer-returning - type) so that :meth:`convert` and downstream consumers carry the - narrowed return type. - """ - - is_composite: t.ClassVar[bool] = False - arity: t.ClassVar[int] = 1 - - #: the descriptive name of this type - name: str - - #: if a list of this type is expected and the value is pulled from a - #: string environment variable, this is what splits it up. `None` - #: means any whitespace. For all parameters the general rule is that - #: whitespace splits them up. The exception are paths and files which - #: are split by ``os.path.pathsep`` by default (":" on Unix and ";" on - #: Windows). - envvar_list_splitter: t.ClassVar[str | None] = None - - def to_info_dict(self) -> ParamTypeInfoDict: - """Gather information that could be useful for a tool generating - user-facing documentation. - - Use :meth:`click.Context.to_info_dict` to traverse the entire - CLI structure. - - .. versionadded:: 8.0 - """ - # The class name without the "ParamType" suffix. - param_type = type(self).__name__.partition("ParamType")[0] - param_type = param_type.partition("ParameterType")[0] - - # Custom subclasses might not remember to set a name. - if hasattr(self, "name"): - name = self.name - else: - name = param_type - - return {"param_type": param_type, "name": name} - - def __call__( - self, - value: t.Any, - param: Parameter | None = None, - ctx: Context | None = None, - ) -> ParamTypeValue | None: - if value is not None: - return self.convert(value, param, ctx) - return None - - def get_metavar(self, param: Parameter, ctx: Context) -> str | None: - """Returns the metavar default for this param if it provides one.""" - - def get_missing_message(self, param: Parameter, ctx: Context | None) -> str | None: - """Optionally might return extra information about a missing - parameter. - - .. versionadded:: 2.0 - """ - - def convert( - self, value: t.Any, param: Parameter | None, ctx: Context | None - ) -> ParamTypeValue: - """Convert the value to the correct type. This is not called if - the value is ``None`` (the missing value). - - This must accept string values from the command line, as well as - values that are already the correct type. It may also convert - other compatible types. - - The ``param`` and ``ctx`` arguments may be ``None`` in certain - situations, such as when converting prompt input. - - If the value cannot be converted, call :meth:`fail` with a - descriptive message. - - :param value: The value to convert. - :param param: The parameter that is using this type to convert - its value. May be ``None``. - :param ctx: The current context that arrived at this value. May - be ``None``. - """ - # The default returns the value as-is so subclasses that only customize - # metadata are not forced to redeclare ``convert``. - return t.cast("ParamTypeValue", value) - - def split_envvar_value(self, rv: str) -> cabc.Sequence[str]: - """Given a value from an environment variable this splits it up - into small chunks depending on the defined envvar list splitter. - - If the splitter is set to `None`, which means that whitespace splits, - then leading and trailing whitespace is ignored. Otherwise, leading - and trailing splitters usually lead to empty items being included. - """ - return (rv or "").split(self.envvar_list_splitter) - - def fail( - self, - message: str, - param: Parameter | None = None, - ctx: Context | None = None, - ) -> t.NoReturn: - """Helper method to fail with an invalid value message.""" - raise BadParameter(message, ctx=ctx, param=param) - - def shell_complete( - self, ctx: Context, param: Parameter, incomplete: str - ) -> list[CompletionItem]: - """Return a list of - :class:`~click.shell_completion.CompletionItem` objects for the - incomplete value. Most types do not provide completions, but - some do, and this allows custom types to provide custom - completions as well. - - :param ctx: Invocation context for this command. - :param param: The parameter that is requesting completion. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - return [] - - -class CompositeParamType(ParamType[ParamTypeValue]): - is_composite = True - - @property - @abc.abstractmethod - def arity(self) -> int: ... # type: ignore[override] - - -class FuncParamTypeInfoDict(ParamTypeInfoDict): - func: t.Callable[[t.Any], t.Any] - - -class FuncParamType(ParamType[ParamTypeValue]): - def __init__(self, func: t.Callable[[t.Any], ParamTypeValue]) -> None: - self.name: str = func.__name__ - self.func = func - - def to_info_dict(self) -> FuncParamTypeInfoDict: - return {"func": self.func, **super().to_info_dict()} - - def convert( - self, value: t.Any, param: Parameter | None, ctx: Context | None - ) -> ParamTypeValue: - try: - return self.func(value) - except ValueError as exc: - message = str(exc) - - if not message: - try: - message = str(value) - except UnicodeError: - message = value.decode("utf-8", "replace") - - self.fail(message, param, ctx) - - -class UnprocessedParamType(ParamType[t.Any]): - name = "text" - - def convert( - self, value: t.Any, param: Parameter | None, ctx: Context | None - ) -> t.Any: - return value - - def __repr__(self) -> str: - return "UNPROCESSED" - - -class StringParamType(ParamType[str]): - name = "text" - - def convert( - self, value: t.Any, param: Parameter | None, ctx: Context | None - ) -> str: - if isinstance(value, bytes): - enc = _get_argv_encoding() - try: - value = value.decode(enc) - except UnicodeError: - fs_enc = sys.getfilesystemencoding() - if fs_enc != enc: - try: - value = value.decode(fs_enc) - except UnicodeError: - value = value.decode("utf-8", "replace") - else: - value = value.decode("utf-8", "replace") - return value # type: ignore[no-any-return] - return str(value) - - def __repr__(self) -> str: - return "STRING" - - -class ChoiceInfoDict(ParamTypeInfoDict): - choices: cabc.Sequence[t.Any] - case_sensitive: bool - - -class Choice(ParamType[ParamTypeValue], t.Generic[ParamTypeValue]): - """The choice type allows a value to be checked against a fixed set - of supported values. - - You may pass any iterable value which will be converted to a tuple - and thus will only be iterated once. - - The resulting value will always be one of the originally passed choices. - See :meth:`normalize_choice` for more info on the mapping of strings - to choices. See :ref:`choice-opts` for an example. - - :param case_sensitive: Set to false to make choices case - insensitive. Defaults to true. - - .. versionchanged:: 8.4.0 - Now generic in the choice value type. Parameterize with the type of - the choice values (``Choice[HashType]`` for an enum, ``Choice[str]`` - for plain strings) to enable type-checked consumers. - - .. versionchanged:: 8.2.0 - Non-``str`` ``choices`` are now supported. It can additionally be any - iterable. Before you were not recommended to pass anything but a list or - tuple. - - .. versionadded:: 8.2.0 - Choice normalization can be overridden via :meth:`normalize_choice`. - """ - - name = "choice" - - def __init__( - self, choices: cabc.Iterable[ParamTypeValue], case_sensitive: bool = True - ) -> None: - self.choices: cabc.Sequence[ParamTypeValue] = tuple(choices) - self.case_sensitive = case_sensitive - - def to_info_dict(self) -> ChoiceInfoDict: - return { - "choices": self.choices, - "case_sensitive": self.case_sensitive, - **super().to_info_dict(), - } - - def _normalized_mapping( - self, ctx: Context | None = None - ) -> cabc.Mapping[ParamTypeValue, str]: - """ - Returns mapping where keys are the original choices and the values are - the normalized values that are accepted via the command line. - - This is a simple wrapper around :meth:`normalize_choice`, use that - instead which is supported. - """ - return { - choice: self.normalize_choice( - choice=choice, - ctx=ctx, - ) - for choice in self.choices - } - - def normalize_choice(self, choice: ParamTypeValue, ctx: Context | None) -> str: - """ - Normalize a choice value, used to map a passed string to a choice. - Each choice must have a unique normalized value. - - By default uses :meth:`Context.token_normalize_func` and if not case - sensitive, convert it to a casefolded value. - - .. versionadded:: 8.2.0 - """ - normed_value = choice.name if isinstance(choice, enum.Enum) else str(choice) - - if ctx is not None and ctx.token_normalize_func is not None: - normed_value = ctx.token_normalize_func(normed_value) - - if not self.case_sensitive: - normed_value = normed_value.casefold() - - return normed_value - - def get_metavar(self, param: Parameter, ctx: Context) -> str | None: - if param.param_type_name == "option" and not param.show_choices: # type: ignore - choice_metavars = [ - convert_type(type(choice)).name.upper() for choice in self.choices - ] - choices_str = "|".join([*dict.fromkeys(choice_metavars)]) - else: - choices_str = "|".join( - [str(i) for i in self._normalized_mapping(ctx=ctx).values()] - ) - - # Use curly braces to indicate a required argument. - if param.required and param.param_type_name == "argument": - return f"{{{choices_str}}}" - - # Use square braces to indicate an option or optional argument. - return f"[{choices_str}]" - - def get_missing_message(self, param: Parameter, ctx: Context | None) -> str: - """ - Message shown when no choice is passed. - - .. versionchanged:: 8.2.0 Added ``ctx`` argument. - """ - return _("Choose from:\n\t{choices}").format( - choices=",\n\t".join(self._normalized_mapping(ctx=ctx).values()) - ) - - def convert( - self, value: t.Any, param: Parameter | None, ctx: Context | None - ) -> ParamTypeValue: - """ - For a given value from the parser, normalize it and find its - matching normalized value in the list of choices. Then return the - matched "original" choice. - """ - normed_value = self.normalize_choice(choice=value, ctx=ctx) - normalized_mapping = self._normalized_mapping(ctx=ctx) - - try: - return next( - original - for original, normalized in normalized_mapping.items() - if normalized == normed_value - ) - except StopIteration: - self.fail( - self.get_invalid_choice_message(value=value, ctx=ctx), - param=param, - ctx=ctx, - ) - - def get_invalid_choice_message(self, value: t.Any, ctx: Context | None) -> str: - """Get the error message when the given choice is invalid. - - :param value: The invalid value. - - .. versionadded:: 8.2 - """ - choices_str = ", ".join(map(repr, self._normalized_mapping(ctx=ctx).values())) - return ngettext( - "{value!r} is not {choice}.", - "{value!r} is not one of {choices}.", - len(self.choices), - ).format(value=value, choice=choices_str, choices=choices_str) - - def __repr__(self) -> str: - return _("Choice({choices})").format(choices=list(self.choices)) - - def shell_complete( - self, ctx: Context, param: Parameter, incomplete: str - ) -> list[CompletionItem]: - """Complete choices that start with the incomplete value. - - :param ctx: Invocation context for this command. - :param param: The parameter that is requesting completion. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - from click.shell_completion import CompletionItem - - str_choices = [self.normalize_choice(choice, ctx) for choice in self.choices] - if self.case_sensitive: - matched = (c for c in str_choices if c.startswith(incomplete)) - else: - incomplete = incomplete.lower() - matched = (c for c in str_choices if c.lower().startswith(incomplete)) - - return [CompletionItem(c) for c in matched] - - -class DateTimeInfoDict(ParamTypeInfoDict): - formats: cabc.Sequence[str] - - -class DateTime(ParamType[datetime]): - """The DateTime type converts date strings into `datetime` objects. - - The format strings which are checked are configurable, but default to some - common (non-timezone aware) ISO 8601 formats. - - When specifying *DateTime* formats, you should only pass a list or a tuple. - Other iterables, like generators, may lead to surprising results. - - The format strings are processed using ``datetime.strptime``, and this - consequently defines the format strings which are allowed. - - Parsing is tried using each format, in order, and the first format which - parses successfully is used. - - :param formats: A list or tuple of date format strings, in the order in - which they should be tried. Defaults to - ``'%Y-%m-%d'``, ``'%Y-%m-%dT%H:%M:%S'``, - ``'%Y-%m-%d %H:%M:%S'``. - """ - - name = "datetime" - - def __init__(self, formats: cabc.Sequence[str] | None = None): - self.formats: cabc.Sequence[str] = formats or [ - "%Y-%m-%d", - "%Y-%m-%dT%H:%M:%S", - "%Y-%m-%d %H:%M:%S", - ] - - def to_info_dict(self) -> DateTimeInfoDict: - return {"formats": self.formats, **super().to_info_dict()} - - def get_metavar(self, param: Parameter, ctx: Context) -> str | None: - return f"[{'|'.join(self.formats)}]" - - def _try_to_convert_date(self, value: t.Any, format: str) -> datetime | None: - try: - return datetime.strptime(value, format) - except ValueError: - return None - - def convert( - self, value: t.Any, param: Parameter | None, ctx: Context | None - ) -> datetime: - if isinstance(value, datetime): - return value - - for format in self.formats: - converted = self._try_to_convert_date(value, format) - - if converted is not None: - return converted - - formats_str = ", ".join(map(repr, self.formats)) - self.fail( - ngettext( - "{value!r} does not match the format {format}.", - "{value!r} does not match the formats {formats}.", - len(self.formats), - ).format(value=value, format=formats_str, formats=formats_str), - param, - ctx, - ) - - def __repr__(self) -> str: - return "DateTime" - - -class _NumberParamTypeBase(ParamType[ParamTypeValue]): - _number_class: t.Callable[[t.Any], ParamTypeValue] - - def convert( - self, value: t.Any, param: Parameter | None, ctx: Context | None - ) -> ParamTypeValue: - try: - return self._number_class(value) - except ValueError: - self.fail( - _("{value!r} is not a valid {number_type}.").format( - value=value, number_type=self.name - ), - param, - ctx, - ) - - -class NumberRangeInfoDict(ParamTypeInfoDict): - min: float | None - max: float | None - min_open: bool - max_open: bool - clamp: bool - - -class _NumberRangeBase(_NumberParamTypeBase[ParamTypeValue]): - def __init__( - self, - min: float | None = None, - max: float | None = None, - min_open: bool = False, - max_open: bool = False, - clamp: bool = False, - ) -> None: - self.min = min - self.max = max - self.min_open = min_open - self.max_open = max_open - self.clamp = clamp - - def to_info_dict(self) -> NumberRangeInfoDict: - return { - "min": self.min, - "max": self.max, - "min_open": self.min_open, - "max_open": self.max_open, - "clamp": self.clamp, - **super().to_info_dict(), - } - - def convert( - self, value: t.Any, param: Parameter | None, ctx: Context | None - ) -> ParamTypeValue: - import operator - - rv = super().convert(value, param, ctx) - min = self.min - max = self.max - lt_min: bool = min is not None and ( - operator.le if self.min_open else operator.lt - )(rv, min) # type: ignore[arg-type] - gt_max: bool = max is not None and ( - operator.ge if self.max_open else operator.gt - )(rv, max) # type: ignore[arg-type] - - if self.clamp: - if min is not None and lt_min: - return self._clamp(min, 1, self.min_open) # type: ignore[arg-type] - - if max is not None and gt_max: - return self._clamp(max, -1, self.max_open) # type: ignore[arg-type] - - if lt_min or gt_max: - self.fail( - _("{value} is not in the range {range}.").format( - value=rv, range=self._describe_range() - ), - param, - ctx, - ) - - return rv - - @abc.abstractmethod - def _clamp( - self, bound: ParamTypeValue, dir: t.Literal[1, -1], open: bool - ) -> ParamTypeValue: - """Find the valid value to clamp to bound in the given - direction. - - :param bound: The boundary value. - :param dir: 1 or -1 indicating the direction to move. - :param open: If true, the range does not include the bound. - """ - ... - - def _describe_range(self) -> str: - """Describe the range for use in help text.""" - if self.min is None: - op = "<" if self.max_open else "<=" - return f"x{op}{self.max}" - - if self.max is None: - op = ">" if self.min_open else ">=" - return f"x{op}{self.min}" - - lop = "<" if self.min_open else "<=" - rop = "<" if self.max_open else "<=" - return f"{self.min}{lop}x{rop}{self.max}" - - def __repr__(self) -> str: - clamp = " clamped" if self.clamp else "" - return f"<{type(self).__name__} {self._describe_range()}{clamp}>" - - -class IntParamType(_NumberParamTypeBase[int]): - name = "integer" - _number_class = int - - def __repr__(self) -> str: - return "INT" - - -class IntRange(_NumberRangeBase[int], IntParamType): - """Restrict an :data:`click.INT` value to a range of accepted - values. See :ref:`ranges`. - - If ``min`` or ``max`` are not passed, any value is accepted in that - direction. If ``min_open`` or ``max_open`` are enabled, the - corresponding boundary is not included in the range. - - If ``clamp`` is enabled, a value outside the range is clamped to the - boundary instead of failing. - - .. versionchanged:: 8.0 - Added the ``min_open`` and ``max_open`` parameters. - """ - - name = "integer range" - - def _clamp(self, bound: int, dir: t.Literal[1, -1], open: bool) -> int: - if not open: - return bound - - return bound + dir - - -class FloatParamType(_NumberParamTypeBase[float]): - name = "float" - _number_class = float - - def __repr__(self) -> str: - return "FLOAT" - - -class FloatRange(_NumberRangeBase[float], FloatParamType): - """Restrict a :data:`click.FLOAT` value to a range of accepted - values. See :ref:`ranges`. - - If ``min`` or ``max`` are not passed, any value is accepted in that - direction. If ``min_open`` or ``max_open`` are enabled, the - corresponding boundary is not included in the range. - - If ``clamp`` is enabled, a value outside the range is clamped to the - boundary instead of failing. This is not supported if either - boundary is marked ``open``. - - .. versionchanged:: 8.0 - Added the ``min_open`` and ``max_open`` parameters. - """ - - name = "float range" - - def __init__( - self, - min: float | None = None, - max: float | None = None, - min_open: bool = False, - max_open: bool = False, - clamp: bool = False, - ) -> None: - super().__init__( - min=min, max=max, min_open=min_open, max_open=max_open, clamp=clamp - ) - - if (min_open or max_open) and clamp: - raise TypeError("Clamping is not supported for open bounds.") - - def _clamp(self, bound: float, dir: t.Literal[1, -1], open: bool) -> float: - if not open: - return bound - - # Could use math.nextafter here, but clamping an - # open float range doesn't seem to be particularly useful. It's - # left up to the user to write a callback to do it if needed. - raise RuntimeError("Clamping is not supported for open bounds.") - - -class BoolParamType(ParamType[bool]): - name = "boolean" - - bool_states: dict[str, bool] = { - "1": True, - "0": False, - "yes": True, - "no": False, - "true": True, - "false": False, - "on": True, - "off": False, - "t": True, - "f": False, - "y": True, - "n": False, - # Absence of value is considered False. - "": False, - } - """A mapping of string values to boolean states. - - Mapping is inspired by :py:attr:`configparser.ConfigParser.BOOLEAN_STATES` - and extends it. - - .. caution:: - String values are lower-cased, as the ``str_to_bool`` comparison function - below is case-insensitive. - - .. warning:: - The mapping is not exhaustive, and does not cover all possible boolean strings - representations. It will remains as it is to avoid endless bikeshedding. - - Future work my be considered to make this mapping user-configurable from public - API. - """ - - @staticmethod - def str_to_bool(value: str | bool) -> bool | None: - """Convert a string to a boolean value. - - If the value is already a boolean, it is returned as-is. If the value is a - string, it is stripped of whitespaces and lower-cased, then checked against - the known boolean states pre-defined in the `BoolParamType.bool_states` mapping - above. - - Returns `None` if the value does not match any known boolean state. - """ - if isinstance(value, bool): - return value - return BoolParamType.bool_states.get(value.strip().lower()) - - def convert( - self, value: t.Any, param: Parameter | None, ctx: Context | None - ) -> bool: - normalized = self.str_to_bool(value) - if normalized is None: - self.fail( - _( - "{value!r} is not a valid boolean. Recognized values: {states}" - ).format(value=value, states=", ".join(sorted(self.bool_states))), - param, - ctx, - ) - return normalized - - def __repr__(self) -> str: - return "BOOL" - - -class UUIDParameterType(ParamType[uuid.UUID]): - name = "uuid" - - def convert( - self, value: t.Any, param: Parameter | None, ctx: Context | None - ) -> uuid.UUID: - if isinstance(value, uuid.UUID): - return value - - value = value.strip() - - try: - return uuid.UUID(value) - except ValueError: - self.fail( - _("{value!r} is not a valid UUID.").format(value=value), param, ctx - ) - - def __repr__(self) -> str: - return "UUID" - - -class FileInfoDict(ParamTypeInfoDict): - mode: str - encoding: str | None - - -class File(ParamType[t.IO[t.Any]]): - """Declares a parameter to be a file for reading or writing. The file - is automatically closed once the context tears down (after the command - finished working). - - Files can be opened for reading or writing. The special value ``-`` - indicates stdin or stdout depending on the mode. - - By default, the file is opened for reading text data, but it can also be - opened in binary mode or for writing. The encoding parameter can be used - to force a specific encoding. - - The `lazy` flag controls if the file should be opened immediately or upon - first IO. The default is to be non-lazy for standard input and output - streams as well as files opened for reading, `lazy` otherwise. When opening a - file lazily for reading, it is still opened temporarily for validation, but - will not be held open until first IO. lazy is mainly useful when opening - for writing to avoid creating the file until it is needed. - - Files can also be opened atomically in which case all writes go into a - separate file in the same folder and upon completion the file will - be moved over to the original location. This is useful if a file - regularly read by other users is modified. - - See :ref:`file-args` for more information. - - .. versionchanged:: 2.0 - Added the ``atomic`` parameter. - """ - - name = "filename" - envvar_list_splitter: t.ClassVar[str] = os.path.pathsep - - def __init__( - self, - mode: str = "r", - encoding: str | None = None, - errors: str | None = "strict", - lazy: bool | None = None, - atomic: bool = False, - ) -> None: - self.mode = mode - self.encoding = encoding - self.errors = errors - self.lazy = lazy - self.atomic = atomic - - def to_info_dict(self) -> FileInfoDict: - return { - "mode": self.mode, - "encoding": self.encoding, - **super().to_info_dict(), - } - - def resolve_lazy_flag(self, value: str | os.PathLike[str]) -> bool: - if self.lazy is not None: - return self.lazy - if os.fspath(value) == "-": - return False - elif "w" in self.mode: - return True - return False - - def convert( - self, - value: str | os.PathLike[str] | t.IO[t.Any], - param: Parameter | None, - ctx: Context | None, - ) -> t.IO[t.Any]: - if _is_file_like(value): - return value - - value = t.cast("str | os.PathLike[str]", value) - - try: - lazy = self.resolve_lazy_flag(value) - - if lazy: - lf = LazyFile( - value, self.mode, self.encoding, self.errors, atomic=self.atomic - ) - - if ctx is not None: - ctx.call_on_close(lf.close_intelligently) - - return t.cast("t.IO[t.Any]", lf) - - f, should_close = open_stream( - value, self.mode, self.encoding, self.errors, atomic=self.atomic - ) - - # If a context is provided, we automatically close the file - # at the end of the context execution (or flush out). If a - # context does not exist, it's the caller's responsibility to - # properly close the file. This for instance happens when the - # type is used with prompts. - if ctx is not None: - if should_close: - ctx.call_on_close(safecall(f.close)) - else: - ctx.call_on_close(safecall(f.flush)) - - return f - except OSError as e: - self.fail( - f"'{format_filename(value)}': {e.strerror}", - param, - ctx, - ) - - def shell_complete( - self, ctx: Context, param: Parameter, incomplete: str - ) -> list[CompletionItem]: - """Return a special completion marker that tells the completion - system to use the shell to provide file path completions. - - :param ctx: Invocation context for this command. - :param param: The parameter that is requesting completion. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - from click.shell_completion import CompletionItem - - return [CompletionItem(incomplete, type="file")] - - -def _is_file_like(value: t.Any) -> te.TypeGuard[t.IO[t.Any]]: - return hasattr(value, "read") or hasattr(value, "write") - - -class PathInfoDict(ParamTypeInfoDict): - exists: bool - file_okay: bool - dir_okay: bool - writable: bool - readable: bool - allow_dash: bool - - -class Path(ParamType[str | bytes | os.PathLike[str]]): - """The ``Path`` type is similar to the :class:`File` type, but - returns the filename instead of an open file. Various checks can be - enabled to validate the type of file and permissions. - - :param exists: The file or directory needs to exist for the value to - be valid. If this is not set to ``True``, and the file does not - exist, then all further checks are silently skipped. - :param file_okay: Allow a file as a value. - :param dir_okay: Allow a directory as a value. - :param readable: if true, a readable check is performed. - :param writable: if true, a writable check is performed. - :param executable: if true, an executable check is performed. - :param resolve_path: Make the value absolute and resolve any - symlinks. A ``~`` is not expanded, as this is supposed to be - done by the shell only. - :param allow_dash: Allow a single dash as a value, which indicates - a standard stream (but does not open it). Use - :func:`~click.open_file` to handle opening this value. - :param path_type: Convert the incoming path value to this type. If - ``None``, keep Python's default, which is ``str``. Useful to - convert to :class:`pathlib.Path`. - - .. versionchanged:: 8.1 - Added the ``executable`` parameter. - - .. versionchanged:: 8.0 - Allow passing ``path_type=pathlib.Path``. - - .. versionchanged:: 6.0 - Added the ``allow_dash`` parameter. - """ - - envvar_list_splitter: t.ClassVar[str] = os.path.pathsep - - def __init__( - self, - exists: bool = False, - file_okay: bool = True, - dir_okay: bool = True, - writable: bool = False, - readable: bool = True, - resolve_path: bool = False, - allow_dash: bool = False, - path_type: type[t.Any] | None = None, - executable: bool = False, - ): - self.exists = exists - self.file_okay = file_okay - self.dir_okay = dir_okay - self.readable = readable - self.writable = writable - self.executable = executable - self.resolve_path = resolve_path - self.allow_dash = allow_dash - self.type = path_type - - if self.file_okay and not self.dir_okay: - self.name: str = _("file") - elif self.dir_okay and not self.file_okay: - self.name = _("directory") - else: - self.name = _("path") - - def to_info_dict(self) -> PathInfoDict: - return { - "exists": self.exists, - "file_okay": self.file_okay, - "dir_okay": self.dir_okay, - "writable": self.writable, - "readable": self.readable, - "allow_dash": self.allow_dash, - **super().to_info_dict(), - } - - def coerce_path_result( - self, value: str | os.PathLike[str] - ) -> str | bytes | os.PathLike[str]: - if self.type is not None and not isinstance(value, self.type): - if self.type is str: - return os.fsdecode(value) - elif self.type is bytes: - return os.fsencode(value) - else: - return t.cast("os.PathLike[str]", self.type(value)) - - return value - - def convert( - self, - value: str | os.PathLike[str], - param: Parameter | None, - ctx: Context | None, - ) -> str | bytes | os.PathLike[str]: - rv = value - - is_dash = self.file_okay and self.allow_dash and rv in (b"-", "-") - - if not is_dash: - if self.resolve_path: - rv = os.path.realpath(rv) - - try: - st = os.stat(rv) - except OSError: - if not self.exists: - return self.coerce_path_result(rv) - self.fail( - _("{name} {filename!r} does not exist.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - - if not self.file_okay and stat.S_ISREG(st.st_mode): - self.fail( - _("{name} {filename!r} is a file.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - if not self.dir_okay and stat.S_ISDIR(st.st_mode): - self.fail( - _("{name} {filename!r} is a directory.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - - if self.readable and not os.access(rv, os.R_OK): - self.fail( - _("{name} {filename!r} is not readable.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - - if self.writable and not os.access(rv, os.W_OK): - self.fail( - _("{name} {filename!r} is not writable.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - - if self.executable and not os.access(value, os.X_OK): - self.fail( - _("{name} {filename!r} is not executable.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - - return self.coerce_path_result(rv) - - def shell_complete( - self, ctx: Context, param: Parameter, incomplete: str - ) -> list[CompletionItem]: - """Return a special completion marker that tells the completion - system to use the shell to provide path completions for only - directories or any paths. - - :param ctx: Invocation context for this command. - :param param: The parameter that is requesting completion. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - from click.shell_completion import CompletionItem - - type = "dir" if self.dir_okay and not self.file_okay else "file" - return [CompletionItem(incomplete, type=type)] - - -class TupleInfoDict(ParamTypeInfoDict): - types: cabc.Sequence[ParamTypeInfoDict] - - -class Tuple(CompositeParamType[tuple[t.Any, ...]]): - """The default behavior of Click is to apply a type on a value directly. - This works well in most cases, except for when `nargs` is set to a fixed - count and different types should be used for different items. In this - case the :class:`Tuple` type can be used. This type can only be used - if `nargs` is set to a fixed number. - - For more information see :ref:`tuple-type`. - - This can be selected by using a Python tuple literal as a type. - - :param types: a list of types that should be used for the tuple items. - """ - - def __init__(self, types: cabc.Sequence[type[t.Any] | ParamType[t.Any]]) -> None: - self.types: cabc.Sequence[ParamType[t.Any]] = [convert_type(ty) for ty in types] - - def to_info_dict(self) -> TupleInfoDict: - return { - "types": [ty.to_info_dict() for ty in self.types], - **super().to_info_dict(), - } - - @property - def name(self) -> str: # type: ignore[override] - return f"<{' '.join(ty.name for ty in self.types)}>" - - @property - def arity(self) -> int: # type: ignore[override] - return len(self.types) - - def convert( - self, value: t.Any, param: Parameter | None, ctx: Context | None - ) -> tuple[t.Any, ...]: - len_type = len(self.types) - len_value = len(value) - - if len_value != len_type: - self.fail( - ngettext( - "{len_type} values are required, but {len_value} was given.", - "{len_type} values are required, but {len_value} were given.", - len_value, - ).format(len_type=len_type, len_value=len_value), - param=param, - ctx=ctx, - ) - - return tuple( - ty(x, param, ctx) for ty, x in zip(self.types, value, strict=False) - ) - - -def _guess_type( - ty: type[t.Any] | ParamType[t.Any] | None, - default: t.Any | None, -) -> type[t.Any] | tuple[type[t.Any], ...] | ParamType[t.Any] | None: - """Infer a type from *ty* or *default*. - - Returns *ty* unchanged when it is not ``None``. Otherwise inspects - *default* to produce a ``type``, a ``tuple`` of types (for tuple - defaults), or ``None``. - """ - if ty is not None: - return ty - - if default is None: - return None - - if not isinstance(default, (tuple, list)): - return type(default) - - # If the default is empty, return None so convert_type falls - # through to STRING. - if not default: - return None - - item = default[0] - - # A sequence of iterables needs to detect the inner types. - # Can't call convert_type recursively because that would - # incorrectly unwind the tuple to a single type. - if isinstance(item, (tuple, list)): - return tuple(map(type, item)) - - return type(item) - - -@t.overload -def convert_type(ty: None, default: None = None) -> StringParamType: ... - - -@t.overload -def convert_type( - ty: type[t.Any] | ParamType[t.Any], default: t.Any | None = None -) -> ParamType[t.Any]: ... - - -@t.overload -def convert_type( - ty: t.Any | None, default: t.Any | None = None -) -> ParamType[t.Any]: ... - - -def convert_type( - ty: t.Any | None = None, default: t.Any | None = None -) -> ParamType[t.Any]: - """Find the most appropriate :class:`ParamType` for the given Python - type. If the type isn't provided, it can be inferred from a default - value. - """ - guessed = _guess_type(ty, default) - is_guessed = guessed is not ty - - if isinstance(guessed, tuple): - return Tuple(guessed) - - if isinstance(guessed, ParamType): - return guessed - - if guessed is str or guessed is None: - return STRING - - if guessed is int: - return INT - - if guessed is float: - return FLOAT - - if guessed is bool: - return BOOL - - if is_guessed: - return STRING - - if __debug__: - try: - if issubclass(guessed, ParamType): - raise AssertionError( - f"Attempted to use an uninstantiated parameter type ({guessed})." - ) - except TypeError: - # guessed is an instance (correct), so issubclass fails. - pass - - return FuncParamType(guessed) - - -#: A dummy parameter type that just does nothing. From a user's -#: perspective this appears to just be the same as `STRING` but -#: internally no string conversion takes place if the input was bytes. -#: This is usually useful when working with file paths as they can -#: appear in bytes and unicode. -#: -#: For path related uses the :class:`Path` type is a better choice but -#: there are situations where an unprocessed type is useful which is why -#: it is provided. -#: -#: .. versionadded:: 4.0 -UNPROCESSED = UnprocessedParamType() - -#: A unicode string parameter type which is the implicit default. This -#: can also be selected by using ``str`` as type. -STRING = StringParamType() - -#: An integer parameter. This can also be selected by using ``int`` as -#: type. -INT = IntParamType() - -#: A floating point value parameter. This can also be selected by using -#: ``float`` as type. -FLOAT = FloatParamType() - -#: A boolean parameter. This is the default for boolean flags. This can -#: also be selected by using ``bool`` as a type. -BOOL = BoolParamType() - -#: A UUID parameter. -UUID = UUIDParameterType() - - -class OptionHelpExtra(t.TypedDict, total=False): - envvars: tuple[str, ...] - default: str - range: str - required: str diff --git a/notification-service/venv/Lib/site-packages/click/utils.py b/notification-service/venv/Lib/site-packages/click/utils.py deleted file mode 100644 index 67922b8..0000000 --- a/notification-service/venv/Lib/site-packages/click/utils.py +++ /dev/null @@ -1,641 +0,0 @@ -from __future__ import annotations - -import collections.abc as cabc -import os -import re -import sys -import typing as t -from functools import update_wrapper -from gettext import gettext as _ -from types import ModuleType -from types import TracebackType - -from ._compat import _default_text_stderr -from ._compat import _default_text_stdout -from ._compat import _find_binary_writer -from ._compat import auto_wrap_for_ansi -from ._compat import binary_streams -from ._compat import open_stream -from ._compat import should_strip_ansi -from ._compat import strip_ansi -from ._compat import text_streams -from ._compat import WIN -from .globals import resolve_color_default - -if t.TYPE_CHECKING: - import typing_extensions as te - - P = te.ParamSpec("P") - -R = t.TypeVar("R") - - -def _posixify(name: str) -> str: - return "-".join(name.split()).lower() - - -def safecall(func: t.Callable[P, R]) -> t.Callable[P, R | None]: - """Wraps a function so that it swallows exceptions.""" - - def wrapper(*args: P.args, **kwargs: P.kwargs) -> R | None: - try: - return func(*args, **kwargs) - except Exception: - pass - return None - - return update_wrapper(wrapper, func) - - -def make_str(value: t.Any) -> str: - """Converts a value into a valid string.""" - if isinstance(value, bytes): - try: - return value.decode(sys.getfilesystemencoding()) - except UnicodeError: - return value.decode("utf-8", "replace") - return str(value) - - -def make_default_short_help(help: str, max_length: int = 45) -> str: - """Returns a condensed version of help string. - - :meta private: - """ - # Consider only the first paragraph. - paragraph_end = help.find("\n\n") - - if paragraph_end != -1: - help = help[:paragraph_end] - - # Collapse newlines, tabs, and spaces. - words = help.split() - - if not words: - return "" - - # The first paragraph started with a "no rewrap" marker, ignore it. - if words[0] == "\b": - words = words[1:] - - total_length = 0 - last_index = len(words) - 1 - - for i, word in enumerate(words): - total_length += len(word) + (i > 0) - - if total_length > max_length: # too long, truncate - break - - if word[-1] == ".": # sentence end, truncate without "..." - return " ".join(words[: i + 1]) - - if total_length == max_length and i != last_index: - break # not at sentence end, truncate with "..." - else: - return " ".join(words) # no truncation needed - - # Account for the length of the suffix. - total_length += len("...") - - # remove words until the length is short enough - while i > 0: - total_length -= len(words[i]) + (i > 0) - - if total_length <= max_length: - break - - i -= 1 - - return " ".join(words[:i]) + "..." - - -class LazyFile: - """A lazy file works like a regular file but it does not fully open - the file but it does perform some basic checks early to see if the - filename parameter does make sense. This is useful for safely opening - files for writing. - """ - - name: str - mode: str - encoding: str | None - errors: str | None - atomic: bool - _f: t.IO[t.Any] | None - should_close: bool - - def __init__( - self, - filename: str | os.PathLike[str], - mode: str = "r", - encoding: str | None = None, - errors: str | None = "strict", - atomic: bool = False, - ) -> None: - self.name = os.fspath(filename) - self.mode = mode - self.encoding = encoding - self.errors = errors - self.atomic = atomic - - if self.name == "-": - self._f, self.should_close = open_stream(filename, mode, encoding, errors) - else: - if "r" in mode: - # Open and close the file in case we're opening it for - # reading so that we can catch at least some errors in - # some cases early. - open(filename, mode).close() - self._f = None - self.should_close = True - - def __getattr__(self, name: str) -> t.Any: - return getattr(self.open(), name) - - def __repr__(self) -> str: - if self._f is not None: - return repr(self._f) - return f"" - - def open(self) -> t.IO[t.Any]: - """Opens the file if it's not yet open. This call might fail with - a :exc:`FileError`. Not handling this error will produce an error - that Click shows. - """ - if self._f is not None: - return self._f - try: - rv, self.should_close = open_stream( - self.name, self.mode, self.encoding, self.errors, atomic=self.atomic - ) - except OSError as e: - from .exceptions import FileError - - raise FileError(self.name, hint=e.strerror) from e - self._f = rv - return rv - - def close(self) -> None: - """Closes the underlying file, no matter what.""" - if self._f is not None: - self._f.close() - - def close_intelligently(self) -> None: - """This function only closes the file if it was opened by the lazy - file wrapper. For instance this will never close stdin. - """ - if self.should_close: - self.close() - - def __enter__(self) -> LazyFile: - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_value: BaseException | None, - tb: TracebackType | None, - ) -> None: - self.close_intelligently() - - def __iter__(self) -> cabc.Iterator[t.AnyStr]: - self.open() - return iter(self._f) # type: ignore - - -class KeepOpenFile: - _file: t.IO[t.Any] - - def __init__(self, file: t.IO[t.Any]) -> None: - self._file = file - - def __getattr__(self, name: str) -> t.Any: - return getattr(self._file, name) - - def __enter__(self) -> KeepOpenFile: - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_value: BaseException | None, - tb: TracebackType | None, - ) -> None: - pass - - def __repr__(self) -> str: - return repr(self._file) - - def __iter__(self) -> cabc.Iterator[t.AnyStr]: - return iter(self._file) - - -def echo( - message: object = None, - file: t.IO[t.Any] | None = None, - nl: bool = True, - err: bool = False, - color: bool | None = None, -) -> None: - """Print a message and newline to stdout or a file. This should be - used instead of :func:`print` because it provides better support - for different data, files, and environments. - - Compared to :func:`print`, this does the following: - - - Ensures that the output encoding is not misconfigured on Linux. - - Supports Unicode in the Windows console. - - Supports writing to binary outputs, and supports writing bytes - to text outputs. - - Supports colors and styles on Windows. - - Removes ANSI color and style codes if the output does not look - like an interactive terminal. - - Always flushes the output. - - :param message: The string or bytes to output. Other objects are - converted to strings. - :param file: The file to write to. Defaults to ``stdout``. - :param err: Write to ``stderr`` instead of ``stdout``. - :param nl: Print a newline after the message. Enabled by default. - :param color: Force showing or hiding colors and other styles. By - default Click will remove color if the output does not look like - an interactive terminal. - - .. versionchanged:: 6.0 - Support Unicode output on the Windows console. Click does not - modify ``sys.stdout``, so ``sys.stdout.write()`` and ``print()`` - will still not support Unicode. - - .. versionchanged:: 4.0 - Added the ``color`` parameter. - - .. versionadded:: 3.0 - Added the ``err`` parameter. - - .. versionchanged:: 2.0 - Support colors on Windows if colorama is installed. - """ - if file is None: - if err: - file = _default_text_stderr() - else: - file = _default_text_stdout() - - # There are no standard streams attached to write to. For example, - # pythonw on Windows. - if file is None: - return - - match message: - case str() | bytes() | bytearray(): - out = message - case None: - out = "" - case _: - out = str(message) - - if nl: - if isinstance(out, str): - out += "\n" - else: - out += b"\n" - - if not out: - file.flush() - return - - # If there is a message and the value looks like bytes, we manually - # need to find the binary stream and write the message in there. - # This is done separately so that most stream types will work as you - # would expect. Eg: you can write to StringIO for other cases. - if isinstance(out, (bytes, bytearray)): - binary_file = _find_binary_writer(file) - if binary_file is not None: - file.flush() - binary_file.write(out) - binary_file.flush() - return - - # ANSI style code support. For no message or bytes, nothing happens. - # When outputting to a file instead of a terminal, strip codes. - else: - color = resolve_color_default(color) - - if should_strip_ansi(file, color): - out = strip_ansi(out) - elif WIN: - if auto_wrap_for_ansi is not None: - file = auto_wrap_for_ansi(file, color) # type: ignore - elif not color: - out = strip_ansi(out) - - file.write(out) # type: ignore - file.flush() - - -def get_binary_stream(name: t.Literal["stdin", "stdout", "stderr"]) -> t.BinaryIO: - """Returns a system stream for byte processing. - - :param name: the name of the stream to open. Valid names are ``'stdin'``, - ``'stdout'`` and ``'stderr'`` - """ - opener = binary_streams.get(name) - if opener is None: - raise TypeError(_("Unknown standard stream '{name}'").format(name=name)) - return opener() - - -def get_text_stream( - name: t.Literal["stdin", "stdout", "stderr"], - encoding: str | None = None, - errors: str | None = "strict", -) -> t.TextIO: - """Returns a system stream for text processing. This usually returns - a wrapped stream around a binary stream returned from - :func:`get_binary_stream` but it also can take shortcuts for already - correctly configured streams. - - :param name: the name of the stream to open. Valid names are ``'stdin'``, - ``'stdout'`` and ``'stderr'`` - :param encoding: overrides the detected default encoding. - :param errors: overrides the default error mode. - """ - opener = text_streams.get(name) - if opener is None: - raise TypeError(_("Unknown standard stream '{name}'").format(name=name)) - return opener(encoding, errors) - - -def open_file( - filename: str | os.PathLike[str], - mode: str = "r", - encoding: str | None = None, - errors: str | None = "strict", - lazy: bool = False, - atomic: bool = False, -) -> t.IO[t.Any]: - """Open a file, with extra behavior to handle ``'-'`` to indicate - a standard stream, lazy open on write, and atomic write. Similar to - the behavior of the :class:`~click.File` param type. - - If ``'-'`` is given to open ``stdout`` or ``stdin``, the stream is - wrapped so that using it in a context manager will not close it. - This makes it possible to use the function without accidentally - closing a standard stream: - - .. code-block:: python - - with open_file(filename) as f: - ... - - :param filename: The name or Path of the file to open, or ``'-'`` for - ``stdin``/``stdout``. - :param mode: The mode in which to open the file. - :param encoding: The encoding to decode or encode a file opened in - text mode. - :param errors: The error handling mode. - :param lazy: Wait to open the file until it is accessed. For read - mode, the file is temporarily opened to raise access errors - early, then closed until it is read again. - :param atomic: Write to a temporary file and replace the given file - on close. - - .. versionadded:: 3.0 - """ - if lazy: - return t.cast( - "t.IO[t.Any]", LazyFile(filename, mode, encoding, errors, atomic=atomic) - ) - - f, should_close = open_stream(filename, mode, encoding, errors, atomic=atomic) - - if not should_close: - f = t.cast("t.IO[t.Any]", KeepOpenFile(f)) - - return f - - -def format_filename( - filename: str | bytes | os.PathLike[str] | os.PathLike[bytes], - shorten: bool = False, -) -> str: - """Format a filename as a string for display. Ensures the filename can be - displayed by replacing any invalid bytes or surrogate escapes in the name - with the replacement character ``�``. - - Invalid bytes or surrogate escapes will raise an error when written to a - stream with ``errors="strict"``. This will typically happen with ``stdout`` - when the locale is something like ``en_GB.UTF-8``. - - Many scenarios *are* safe to write surrogates though, due to PEP 538 and - PEP 540, including: - - - Writing to ``stderr``, which uses ``errors="backslashreplace"``. - - The system has ``LANG=C.UTF-8``, ``C``, or ``POSIX``. Python opens - stdout and stderr with ``errors="surrogateescape"``. - - None of ``LANG/LC_*`` are set. Python assumes ``LANG=C.UTF-8``. - - Python is started in UTF-8 mode with ``PYTHONUTF8=1`` or ``-X utf8``. - Python opens stdout and stderr with ``errors="surrogateescape"``. - - :param filename: formats a filename for UI display. This will also convert - the filename into unicode without failing. - :param shorten: this optionally shortens the filename to strip of the - path that leads up to it. - """ - if shorten: - filename = os.path.basename(filename) - else: - filename = os.fspath(filename) - - if isinstance(filename, bytes): - filename = filename.decode(sys.getfilesystemencoding(), "replace") - else: - filename = filename.encode("utf-8", "surrogateescape").decode( - "utf-8", "replace" - ) - - return filename - - -def get_app_dir(app_name: str, roaming: bool = True, force_posix: bool = False) -> str: - r"""Returns the config folder for the application. The default behavior - is to return whatever is most appropriate for the operating system. - - To give you an idea, for an app called ``"Foo Bar"``, something like - the following folders could be returned: - - Mac OS X: - ``~/Library/Application Support/Foo Bar`` - Mac OS X (POSIX): - ``~/.foo-bar`` - Unix: - ``~/.config/foo-bar`` - Unix (POSIX): - ``~/.foo-bar`` - Windows (roaming): - ``C:\Users\\AppData\Roaming\Foo Bar`` - Windows (not roaming): - ``C:\Users\\AppData\Local\Foo Bar`` - - .. versionadded:: 2.0 - - :param app_name: the application name. This should be properly capitalized - and can contain whitespace. - :param roaming: controls if the folder should be roaming or not on Windows. - Has no effect otherwise. - :param force_posix: if this is set to `True` then on any POSIX system the - folder will be stored in the home folder with a leading - dot instead of the XDG config home or darwin's - application support folder. - """ - if WIN: - key = "APPDATA" if roaming else "LOCALAPPDATA" - folder = os.environ.get(key) - if folder is None: - folder = os.path.expanduser("~") - return os.path.join(folder, app_name) - if force_posix: - return os.path.join(os.path.expanduser(f"~/.{_posixify(app_name)}")) - if sys.platform == "darwin": - return os.path.join( - os.path.expanduser("~/Library/Application Support"), app_name - ) - return os.path.join( - os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), - _posixify(app_name), - ) - - -class PacifyFlushWrapper: - """This wrapper is used to catch and suppress BrokenPipeErrors resulting - from ``.flush()`` being called on broken pipe during the shutdown/final-GC - of the Python interpreter. Notably ``.flush()`` is always called on - ``sys.stdout`` and ``sys.stderr``. So as to have minimal impact on any - other cleanup code, and the case where the underlying file is not a broken - pipe, all calls and attributes are proxied. - """ - - wrapped: t.IO[t.Any] - - def __init__(self, wrapped: t.IO[t.Any]) -> None: - self.wrapped = wrapped - - def flush(self) -> None: - try: - self.wrapped.flush() - except OSError as e: - import errno - - if e.errno != errno.EPIPE: - raise - - def __getattr__(self, attr: str) -> t.Any: - return getattr(self.wrapped, attr) - - -def _detect_program_name( - path: str | None = None, _main: ModuleType | None = None -) -> str: - """Determine the command used to run the program, for use in help - text. If a file or entry point was executed, the file name is - returned. If ``python -m`` was used to execute a module or package, - ``python -m name`` is returned. - - This doesn't try to be too precise, the goal is to give a concise - name for help text. Files are only shown as their name without the - path. ``python`` is only shown for modules, and the full path to - ``sys.executable`` is not shown. - - :param path: The Python file being executed. Python puts this in - ``sys.argv[0]``, which is used by default. - :param _main: The ``__main__`` module. This should only be passed - during internal testing. - - .. versionadded:: 8.0 - Based on command args detection in the Werkzeug reloader. - - :meta private: - """ - if _main is None: - _main = sys.modules["__main__"] - - if not path: - path = sys.argv[0] - - # The value of __package__ indicates how Python was called. It may - # not exist if a setuptools script is installed as an egg. It may be - # set incorrectly for entry points created with pip on Windows. - # It is set to "" inside a Shiv or PEX zipapp. - if getattr(_main, "__package__", None) in {None, ""} or ( - os.name == "nt" - and _main.__package__ == "" - and not os.path.exists(path) - and os.path.exists(f"{path}.exe") - ): - # Executed a file, like "python app.py". - return os.path.basename(path) - - # Executed a module, like "python -m example". - # Rewritten by Python from "-m script" to "/path/to/script.py". - # Need to look at main module to determine how it was executed. - py_module = t.cast(str, _main.__package__) - name = os.path.splitext(os.path.basename(path))[0] - - # A submodule like "example.cli". - if name != "__main__": - py_module = f"{py_module}.{name}" - - return f"python -m {py_module.lstrip('.')}" - - -def _expand_args( - args: cabc.Iterable[str], - *, - user: bool = True, - env: bool = True, - glob_recursive: bool = True, -) -> list[str]: - """Simulate Unix shell expansion with Python functions. - - See :func:`glob.glob`, :func:`os.path.expanduser`, and - :func:`os.path.expandvars`. - - This is intended for use on Windows, where the shell does not do any - expansion. It may not exactly match what a Unix shell would do. - - :param args: List of command line arguments to expand. - :param user: Expand user home directory. - :param env: Expand environment variables. - :param glob_recursive: ``**`` matches directories recursively. - - .. versionchanged:: 8.1 - Invalid glob patterns are treated as empty expansions rather - than raising an error. - - .. versionadded:: 8.0 - - :meta private: - """ - from glob import glob - - out = [] - - for arg in args: - if user: - arg = os.path.expanduser(arg) - - if env: - arg = os.path.expandvars(arg) - - try: - matches = glob(arg, recursive=glob_recursive) - except re.error: - matches = [] - - if not matches: - out.append(arg) - else: - out.extend(matches) - - return out diff --git a/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER b/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/METADATA b/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/METADATA deleted file mode 100644 index a1b5c57..0000000 --- a/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/METADATA +++ /dev/null @@ -1,441 +0,0 @@ -Metadata-Version: 2.1 -Name: colorama -Version: 0.4.6 -Summary: Cross-platform colored terminal text. -Project-URL: Homepage, https://github.com/tartley/colorama -Author-email: Jonathan Hartley -License-File: LICENSE.txt -Keywords: ansi,color,colour,crossplatform,terminal,text,windows,xplatform -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Console -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Terminals -Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7 -Description-Content-Type: text/x-rst - -.. image:: https://img.shields.io/pypi/v/colorama.svg - :target: https://pypi.org/project/colorama/ - :alt: Latest Version - -.. image:: https://img.shields.io/pypi/pyversions/colorama.svg - :target: https://pypi.org/project/colorama/ - :alt: Supported Python versions - -.. image:: https://github.com/tartley/colorama/actions/workflows/test.yml/badge.svg - :target: https://github.com/tartley/colorama/actions/workflows/test.yml - :alt: Build Status - -Colorama -======== - -Makes ANSI escape character sequences (for producing colored terminal text and -cursor positioning) work under MS Windows. - -.. |donate| image:: https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif - :target: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=2MZ9D2GMLYCUJ&item_name=Colorama¤cy_code=USD - :alt: Donate with Paypal - -`PyPI for releases `_ | -`Github for source `_ | -`Colorama for enterprise on Tidelift `_ - -If you find Colorama useful, please |donate| to the authors. Thank you! - -Installation ------------- - -Tested on CPython 2.7, 3.7, 3.8, 3.9 and 3.10 and Pypy 2.7 and 3.8. - -No requirements other than the standard library. - -.. code-block:: bash - - pip install colorama - # or - conda install -c anaconda colorama - -Description ------------ - -ANSI escape character sequences have long been used to produce colored terminal -text and cursor positioning on Unix and Macs. Colorama makes this work on -Windows, too, by wrapping ``stdout``, stripping ANSI sequences it finds (which -would appear as gobbledygook in the output), and converting them into the -appropriate win32 calls to modify the state of the terminal. On other platforms, -Colorama does nothing. - -This has the upshot of providing a simple cross-platform API for printing -colored terminal text from Python, and has the happy side-effect that existing -applications or libraries which use ANSI sequences to produce colored output on -Linux or Macs can now also work on Windows, simply by calling -``colorama.just_fix_windows_console()`` (since v0.4.6) or ``colorama.init()`` -(all versions, but may have other side-effects – see below). - -An alternative approach is to install ``ansi.sys`` on Windows machines, which -provides the same behaviour for all applications running in terminals. Colorama -is intended for situations where that isn't easy (e.g., maybe your app doesn't -have an installer.) - -Demo scripts in the source code repository print some colored text using -ANSI sequences. Compare their output under Gnome-terminal's built in ANSI -handling, versus on Windows Command-Prompt using Colorama: - -.. image:: https://github.com/tartley/colorama/raw/master/screenshots/ubuntu-demo.png - :width: 661 - :height: 357 - :alt: ANSI sequences on Ubuntu under gnome-terminal. - -.. image:: https://github.com/tartley/colorama/raw/master/screenshots/windows-demo.png - :width: 668 - :height: 325 - :alt: Same ANSI sequences on Windows, using Colorama. - -These screenshots show that, on Windows, Colorama does not support ANSI 'dim -text'; it looks the same as 'normal text'. - -Usage ------ - -Initialisation -.............. - -If the only thing you want from Colorama is to get ANSI escapes to work on -Windows, then run: - -.. code-block:: python - - from colorama import just_fix_windows_console - just_fix_windows_console() - -If you're on a recent version of Windows 10 or better, and your stdout/stderr -are pointing to a Windows console, then this will flip the magic configuration -switch to enable Windows' built-in ANSI support. - -If you're on an older version of Windows, and your stdout/stderr are pointing to -a Windows console, then this will wrap ``sys.stdout`` and/or ``sys.stderr`` in a -magic file object that intercepts ANSI escape sequences and issues the -appropriate Win32 calls to emulate them. - -In all other circumstances, it does nothing whatsoever. Basically the idea is -that this makes Windows act like Unix with respect to ANSI escape handling. - -It's safe to call this function multiple times. It's safe to call this function -on non-Windows platforms, but it won't do anything. It's safe to call this -function when one or both of your stdout/stderr are redirected to a file – it -won't do anything to those streams. - -Alternatively, you can use the older interface with more features (but also more -potential footguns): - -.. code-block:: python - - from colorama import init - init() - -This does the same thing as ``just_fix_windows_console``, except for the -following differences: - -- It's not safe to call ``init`` multiple times; you can end up with multiple - layers of wrapping and broken ANSI support. - -- Colorama will apply a heuristic to guess whether stdout/stderr support ANSI, - and if it thinks they don't, then it will wrap ``sys.stdout`` and - ``sys.stderr`` in a magic file object that strips out ANSI escape sequences - before printing them. This happens on all platforms, and can be convenient if - you want to write your code to emit ANSI escape sequences unconditionally, and - let Colorama decide whether they should actually be output. But note that - Colorama's heuristic is not particularly clever. - -- ``init`` also accepts explicit keyword args to enable/disable various - functionality – see below. - -To stop using Colorama before your program exits, simply call ``deinit()``. -This will restore ``stdout`` and ``stderr`` to their original values, so that -Colorama is disabled. To resume using Colorama again, call ``reinit()``; it is -cheaper than calling ``init()`` again (but does the same thing). - -Most users should depend on ``colorama >= 0.4.6``, and use -``just_fix_windows_console``. The old ``init`` interface will be supported -indefinitely for backwards compatibility, but we don't plan to fix any issues -with it, also for backwards compatibility. - -Colored Output -.............. - -Cross-platform printing of colored text can then be done using Colorama's -constant shorthand for ANSI escape sequences. These are deliberately -rudimentary, see below. - -.. code-block:: python - - from colorama import Fore, Back, Style - print(Fore.RED + 'some red text') - print(Back.GREEN + 'and with a green background') - print(Style.DIM + 'and in dim text') - print(Style.RESET_ALL) - print('back to normal now') - -...or simply by manually printing ANSI sequences from your own code: - -.. code-block:: python - - print('\033[31m' + 'some red text') - print('\033[39m') # and reset to default color - -...or, Colorama can be used in conjunction with existing ANSI libraries -such as the venerable `Termcolor `_ -the fabulous `Blessings `_, -or the incredible `_Rich `_. - -If you wish Colorama's Fore, Back and Style constants were more capable, -then consider using one of the above highly capable libraries to generate -colors, etc, and use Colorama just for its primary purpose: to convert -those ANSI sequences to also work on Windows: - -SIMILARLY, do not send PRs adding the generation of new ANSI types to Colorama. -We are only interested in converting ANSI codes to win32 API calls, not -shortcuts like the above to generate ANSI characters. - -.. code-block:: python - - from colorama import just_fix_windows_console - from termcolor import colored - - # use Colorama to make Termcolor work on Windows too - just_fix_windows_console() - - # then use Termcolor for all colored text output - print(colored('Hello, World!', 'green', 'on_red')) - -Available formatting constants are:: - - Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. - Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. - Style: DIM, NORMAL, BRIGHT, RESET_ALL - -``Style.RESET_ALL`` resets foreground, background, and brightness. Colorama will -perform this reset automatically on program exit. - -These are fairly well supported, but not part of the standard:: - - Fore: LIGHTBLACK_EX, LIGHTRED_EX, LIGHTGREEN_EX, LIGHTYELLOW_EX, LIGHTBLUE_EX, LIGHTMAGENTA_EX, LIGHTCYAN_EX, LIGHTWHITE_EX - Back: LIGHTBLACK_EX, LIGHTRED_EX, LIGHTGREEN_EX, LIGHTYELLOW_EX, LIGHTBLUE_EX, LIGHTMAGENTA_EX, LIGHTCYAN_EX, LIGHTWHITE_EX - -Cursor Positioning -.................. - -ANSI codes to reposition the cursor are supported. See ``demos/demo06.py`` for -an example of how to generate them. - -Init Keyword Args -................. - -``init()`` accepts some ``**kwargs`` to override default behaviour. - -init(autoreset=False): - If you find yourself repeatedly sending reset sequences to turn off color - changes at the end of every print, then ``init(autoreset=True)`` will - automate that: - - .. code-block:: python - - from colorama import init - init(autoreset=True) - print(Fore.RED + 'some red text') - print('automatically back to default color again') - -init(strip=None): - Pass ``True`` or ``False`` to override whether ANSI codes should be - stripped from the output. The default behaviour is to strip if on Windows - or if output is redirected (not a tty). - -init(convert=None): - Pass ``True`` or ``False`` to override whether to convert ANSI codes in the - output into win32 calls. The default behaviour is to convert if on Windows - and output is to a tty (terminal). - -init(wrap=True): - On Windows, Colorama works by replacing ``sys.stdout`` and ``sys.stderr`` - with proxy objects, which override the ``.write()`` method to do their work. - If this wrapping causes you problems, then this can be disabled by passing - ``init(wrap=False)``. The default behaviour is to wrap if ``autoreset`` or - ``strip`` or ``convert`` are True. - - When wrapping is disabled, colored printing on non-Windows platforms will - continue to work as normal. To do cross-platform colored output, you can - use Colorama's ``AnsiToWin32`` proxy directly: - - .. code-block:: python - - import sys - from colorama import init, AnsiToWin32 - init(wrap=False) - stream = AnsiToWin32(sys.stderr).stream - - # Python 2 - print >>stream, Fore.BLUE + 'blue text on stderr' - - # Python 3 - print(Fore.BLUE + 'blue text on stderr', file=stream) - -Recognised ANSI Sequences -......................... - -ANSI sequences generally take the form:: - - ESC [ ; ... - -Where ```` is an integer, and ```` is a single letter. Zero or -more params are passed to a ````. If no params are passed, it is -generally synonymous with passing a single zero. No spaces exist in the -sequence; they have been inserted here simply to read more easily. - -The only ANSI sequences that Colorama converts into win32 calls are:: - - ESC [ 0 m # reset all (colors and brightness) - ESC [ 1 m # bright - ESC [ 2 m # dim (looks same as normal brightness) - ESC [ 22 m # normal brightness - - # FOREGROUND: - ESC [ 30 m # black - ESC [ 31 m # red - ESC [ 32 m # green - ESC [ 33 m # yellow - ESC [ 34 m # blue - ESC [ 35 m # magenta - ESC [ 36 m # cyan - ESC [ 37 m # white - ESC [ 39 m # reset - - # BACKGROUND - ESC [ 40 m # black - ESC [ 41 m # red - ESC [ 42 m # green - ESC [ 43 m # yellow - ESC [ 44 m # blue - ESC [ 45 m # magenta - ESC [ 46 m # cyan - ESC [ 47 m # white - ESC [ 49 m # reset - - # cursor positioning - ESC [ y;x H # position cursor at x across, y down - ESC [ y;x f # position cursor at x across, y down - ESC [ n A # move cursor n lines up - ESC [ n B # move cursor n lines down - ESC [ n C # move cursor n characters forward - ESC [ n D # move cursor n characters backward - - # clear the screen - ESC [ mode J # clear the screen - - # clear the line - ESC [ mode K # clear the line - -Multiple numeric params to the ``'m'`` command can be combined into a single -sequence:: - - ESC [ 36 ; 45 ; 1 m # bright cyan text on magenta background - -All other ANSI sequences of the form ``ESC [ ; ... `` -are silently stripped from the output on Windows. - -Any other form of ANSI sequence, such as single-character codes or alternative -initial characters, are not recognised or stripped. It would be cool to add -them though. Let me know if it would be useful for you, via the Issues on -GitHub. - -Status & Known Problems ------------------------ - -I've personally only tested it on Windows XP (CMD, Console2), Ubuntu -(gnome-terminal, xterm), and OS X. - -Some valid ANSI sequences aren't recognised. - -If you're hacking on the code, see `README-hacking.md`_. ESPECIALLY, see the -explanation there of why we do not want PRs that allow Colorama to generate new -types of ANSI codes. - -See outstanding issues and wish-list: -https://github.com/tartley/colorama/issues - -If anything doesn't work for you, or doesn't do what you expected or hoped for, -I'd love to hear about it on that issues list, would be delighted by patches, -and would be happy to grant commit access to anyone who submits a working patch -or two. - -.. _README-hacking.md: README-hacking.md - -License -------- - -Copyright Jonathan Hartley & Arnon Yaari, 2013-2020. BSD 3-Clause license; see -LICENSE file. - -Professional support --------------------- - -.. |tideliftlogo| image:: https://cdn2.hubspot.net/hubfs/4008838/website/logos/logos_for_download/Tidelift_primary-shorthand-logo.png - :alt: Tidelift - :target: https://tidelift.com/subscription/pkg/pypi-colorama?utm_source=pypi-colorama&utm_medium=referral&utm_campaign=readme - -.. list-table:: - :widths: 10 100 - - * - |tideliftlogo| - - Professional support for colorama is available as part of the - `Tidelift Subscription`_. - Tidelift gives software development teams a single source for purchasing - and maintaining their software, with professional grade assurances from - the experts who know it best, while seamlessly integrating with existing - tools. - -.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-colorama?utm_source=pypi-colorama&utm_medium=referral&utm_campaign=readme - -Thanks ------- - -See the CHANGELOG for more thanks! - -* Marc Schlaich (schlamar) for a ``setup.py`` fix for Python2.5. -* Marc Abramowitz, reported & fixed a crash on exit with closed ``stdout``, - providing a solution to issue #7's setuptools/distutils debate, - and other fixes. -* User 'eryksun', for guidance on correctly instantiating ``ctypes.windll``. -* Matthew McCormick for politely pointing out a longstanding crash on non-Win. -* Ben Hoyt, for a magnificent fix under 64-bit Windows. -* Jesse at Empty Square for submitting a fix for examples in the README. -* User 'jamessp', an observant documentation fix for cursor positioning. -* User 'vaal1239', Dave Mckee & Lackner Kristof for a tiny but much-needed Win7 - fix. -* Julien Stuyck, for wisely suggesting Python3 compatible updates to README. -* Daniel Griffith for multiple fabulous patches. -* Oscar Lesta for a valuable fix to stop ANSI chars being sent to non-tty - output. -* Roger Binns, for many suggestions, valuable feedback, & bug reports. -* Tim Golden for thought and much appreciated feedback on the initial idea. -* User 'Zearin' for updates to the README file. -* John Szakmeister for adding support for light colors -* Charles Merriam for adding documentation to demos -* Jurko for a fix on 64-bit Windows CPython2.5 w/o ctypes -* Florian Bruhin for a fix when stdout or stderr are None -* Thomas Weininger for fixing ValueError on Windows -* Remi Rampin for better Github integration and fixes to the README file -* Simeon Visser for closing a file handle using 'with' and updating classifiers - to include Python 3.3 and 3.4 -* Andy Neff for fixing RESET of LIGHT_EX colors. -* Jonathan Hartley for the initial idea and implementation. diff --git a/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/RECORD b/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/RECORD deleted file mode 100644 index cd6b130..0000000 --- a/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/RECORD +++ /dev/null @@ -1,31 +0,0 @@ -colorama-0.4.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -colorama-0.4.6.dist-info/METADATA,sha256=e67SnrUMOym9sz_4TjF3vxvAV4T3aF7NyqRHHH3YEMw,17158 -colorama-0.4.6.dist-info/RECORD,, -colorama-0.4.6.dist-info/WHEEL,sha256=cdcF4Fbd0FPtw2EMIOwH-3rSOTUdTCeOSXRMD1iLUb8,105 -colorama-0.4.6.dist-info/licenses/LICENSE.txt,sha256=ysNcAmhuXQSlpxQL-zs25zrtSWZW6JEQLkKIhteTAxg,1491 -colorama/__init__.py,sha256=wePQA4U20tKgYARySLEC047ucNX-g8pRLpYBuiHlLb8,266 -colorama/__pycache__/__init__.cpython-312.pyc,, -colorama/__pycache__/ansi.cpython-312.pyc,, -colorama/__pycache__/ansitowin32.cpython-312.pyc,, -colorama/__pycache__/initialise.cpython-312.pyc,, -colorama/__pycache__/win32.cpython-312.pyc,, -colorama/__pycache__/winterm.cpython-312.pyc,, -colorama/ansi.py,sha256=Top4EeEuaQdBWdteKMEcGOTeKeF19Q-Wo_6_Cj5kOzQ,2522 -colorama/ansitowin32.py,sha256=vPNYa3OZbxjbuFyaVo0Tmhmy1FZ1lKMWCnT7odXpItk,11128 -colorama/initialise.py,sha256=-hIny86ClXo39ixh5iSCfUIa2f_h_bgKRDW7gqs-KLU,3325 -colorama/tests/__init__.py,sha256=MkgPAEzGQd-Rq0w0PZXSX2LadRWhUECcisJY8lSrm4Q,75 -colorama/tests/__pycache__/__init__.cpython-312.pyc,, -colorama/tests/__pycache__/ansi_test.cpython-312.pyc,, -colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc,, -colorama/tests/__pycache__/initialise_test.cpython-312.pyc,, -colorama/tests/__pycache__/isatty_test.cpython-312.pyc,, -colorama/tests/__pycache__/utils.cpython-312.pyc,, -colorama/tests/__pycache__/winterm_test.cpython-312.pyc,, -colorama/tests/ansi_test.py,sha256=FeViDrUINIZcr505PAxvU4AjXz1asEiALs9GXMhwRaE,2839 -colorama/tests/ansitowin32_test.py,sha256=RN7AIhMJ5EqDsYaCjVo-o4u8JzDD4ukJbmevWKS70rY,10678 -colorama/tests/initialise_test.py,sha256=BbPy-XfyHwJ6zKozuQOvNvQZzsx9vdb_0bYXn7hsBTc,6741 -colorama/tests/isatty_test.py,sha256=Pg26LRpv0yQDB5Ac-sxgVXG7hsA1NYvapFgApZfYzZg,1866 -colorama/tests/utils.py,sha256=1IIRylG39z5-dzq09R_ngufxyPZxgldNbrxKxUGwGKE,1079 -colorama/tests/winterm_test.py,sha256=qoWFPEjym5gm2RuMwpf3pOis3a5r_PJZFCzK254JL8A,3709 -colorama/win32.py,sha256=YQOKwMTwtGBbsY4dL5HYTvwTeP9wIQra5MvPNddpxZs,6181 -colorama/winterm.py,sha256=XCQFDHjPi6AHYNdZwy0tA02H-Jh48Jp-HvCjeLeLp3U,7134 diff --git a/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL b/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL deleted file mode 100644 index d79189f..0000000 --- a/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: hatchling 1.11.1 -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any diff --git a/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt b/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt deleted file mode 100644 index 3105888..0000000 --- a/notification-service/venv/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2010 Jonathan Hartley -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the copyright holders, nor those of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/notification-service/venv/Lib/site-packages/colorama/__init__.py b/notification-service/venv/Lib/site-packages/colorama/__init__.py deleted file mode 100644 index 383101c..0000000 --- a/notification-service/venv/Lib/site-packages/colorama/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -from .initialise import init, deinit, reinit, colorama_text, just_fix_windows_console -from .ansi import Fore, Back, Style, Cursor -from .ansitowin32 import AnsiToWin32 - -__version__ = '0.4.6' - diff --git a/notification-service/venv/Lib/site-packages/colorama/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/colorama/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index f7b8c3b..0000000 Binary files a/notification-service/venv/Lib/site-packages/colorama/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/colorama/__pycache__/ansi.cpython-312.pyc b/notification-service/venv/Lib/site-packages/colorama/__pycache__/ansi.cpython-312.pyc deleted file mode 100644 index 1ff128e..0000000 Binary files a/notification-service/venv/Lib/site-packages/colorama/__pycache__/ansi.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-312.pyc b/notification-service/venv/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-312.pyc deleted file mode 100644 index 63dd5b6..0000000 Binary files a/notification-service/venv/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/colorama/__pycache__/initialise.cpython-312.pyc b/notification-service/venv/Lib/site-packages/colorama/__pycache__/initialise.cpython-312.pyc deleted file mode 100644 index 67e9cef..0000000 Binary files a/notification-service/venv/Lib/site-packages/colorama/__pycache__/initialise.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/colorama/__pycache__/win32.cpython-312.pyc b/notification-service/venv/Lib/site-packages/colorama/__pycache__/win32.cpython-312.pyc deleted file mode 100644 index ceeb43a..0000000 Binary files a/notification-service/venv/Lib/site-packages/colorama/__pycache__/win32.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/colorama/__pycache__/winterm.cpython-312.pyc b/notification-service/venv/Lib/site-packages/colorama/__pycache__/winterm.cpython-312.pyc deleted file mode 100644 index c01759a..0000000 Binary files a/notification-service/venv/Lib/site-packages/colorama/__pycache__/winterm.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/colorama/ansi.py b/notification-service/venv/Lib/site-packages/colorama/ansi.py deleted file mode 100644 index 11ec695..0000000 --- a/notification-service/venv/Lib/site-packages/colorama/ansi.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -''' -This module generates ANSI character codes to printing colors to terminals. -See: http://en.wikipedia.org/wiki/ANSI_escape_code -''' - -CSI = '\033[' -OSC = '\033]' -BEL = '\a' - - -def code_to_chars(code): - return CSI + str(code) + 'm' - -def set_title(title): - return OSC + '2;' + title + BEL - -def clear_screen(mode=2): - return CSI + str(mode) + 'J' - -def clear_line(mode=2): - return CSI + str(mode) + 'K' - - -class AnsiCodes(object): - def __init__(self): - # the subclasses declare class attributes which are numbers. - # Upon instantiation we define instance attributes, which are the same - # as the class attributes but wrapped with the ANSI escape sequence - for name in dir(self): - if not name.startswith('_'): - value = getattr(self, name) - setattr(self, name, code_to_chars(value)) - - -class AnsiCursor(object): - def UP(self, n=1): - return CSI + str(n) + 'A' - def DOWN(self, n=1): - return CSI + str(n) + 'B' - def FORWARD(self, n=1): - return CSI + str(n) + 'C' - def BACK(self, n=1): - return CSI + str(n) + 'D' - def POS(self, x=1, y=1): - return CSI + str(y) + ';' + str(x) + 'H' - - -class AnsiFore(AnsiCodes): - BLACK = 30 - RED = 31 - GREEN = 32 - YELLOW = 33 - BLUE = 34 - MAGENTA = 35 - CYAN = 36 - WHITE = 37 - RESET = 39 - - # These are fairly well supported, but not part of the standard. - LIGHTBLACK_EX = 90 - LIGHTRED_EX = 91 - LIGHTGREEN_EX = 92 - LIGHTYELLOW_EX = 93 - LIGHTBLUE_EX = 94 - LIGHTMAGENTA_EX = 95 - LIGHTCYAN_EX = 96 - LIGHTWHITE_EX = 97 - - -class AnsiBack(AnsiCodes): - BLACK = 40 - RED = 41 - GREEN = 42 - YELLOW = 43 - BLUE = 44 - MAGENTA = 45 - CYAN = 46 - WHITE = 47 - RESET = 49 - - # These are fairly well supported, but not part of the standard. - LIGHTBLACK_EX = 100 - LIGHTRED_EX = 101 - LIGHTGREEN_EX = 102 - LIGHTYELLOW_EX = 103 - LIGHTBLUE_EX = 104 - LIGHTMAGENTA_EX = 105 - LIGHTCYAN_EX = 106 - LIGHTWHITE_EX = 107 - - -class AnsiStyle(AnsiCodes): - BRIGHT = 1 - DIM = 2 - NORMAL = 22 - RESET_ALL = 0 - -Fore = AnsiFore() -Back = AnsiBack() -Style = AnsiStyle() -Cursor = AnsiCursor() diff --git a/notification-service/venv/Lib/site-packages/colorama/ansitowin32.py b/notification-service/venv/Lib/site-packages/colorama/ansitowin32.py deleted file mode 100644 index abf209e..0000000 --- a/notification-service/venv/Lib/site-packages/colorama/ansitowin32.py +++ /dev/null @@ -1,277 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -import re -import sys -import os - -from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style, BEL -from .winterm import enable_vt_processing, WinTerm, WinColor, WinStyle -from .win32 import windll, winapi_test - - -winterm = None -if windll is not None: - winterm = WinTerm() - - -class StreamWrapper(object): - ''' - Wraps a stream (such as stdout), acting as a transparent proxy for all - attribute access apart from method 'write()', which is delegated to our - Converter instance. - ''' - def __init__(self, wrapped, converter): - # double-underscore everything to prevent clashes with names of - # attributes on the wrapped stream object. - self.__wrapped = wrapped - self.__convertor = converter - - def __getattr__(self, name): - return getattr(self.__wrapped, name) - - def __enter__(self, *args, **kwargs): - # special method lookup bypasses __getattr__/__getattribute__, see - # https://stackoverflow.com/questions/12632894/why-doesnt-getattr-work-with-exit - # thus, contextlib magic methods are not proxied via __getattr__ - return self.__wrapped.__enter__(*args, **kwargs) - - def __exit__(self, *args, **kwargs): - return self.__wrapped.__exit__(*args, **kwargs) - - def __setstate__(self, state): - self.__dict__ = state - - def __getstate__(self): - return self.__dict__ - - def write(self, text): - self.__convertor.write(text) - - def isatty(self): - stream = self.__wrapped - if 'PYCHARM_HOSTED' in os.environ: - if stream is not None and (stream is sys.__stdout__ or stream is sys.__stderr__): - return True - try: - stream_isatty = stream.isatty - except AttributeError: - return False - else: - return stream_isatty() - - @property - def closed(self): - stream = self.__wrapped - try: - return stream.closed - # AttributeError in the case that the stream doesn't support being closed - # ValueError for the case that the stream has already been detached when atexit runs - except (AttributeError, ValueError): - return True - - -class AnsiToWin32(object): - ''' - Implements a 'write()' method which, on Windows, will strip ANSI character - sequences from the text, and if outputting to a tty, will convert them into - win32 function calls. - ''' - ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer - ANSI_OSC_RE = re.compile('\001?\033\\]([^\a]*)(\a)\002?') # Operating System Command - - def __init__(self, wrapped, convert=None, strip=None, autoreset=False): - # The wrapped stream (normally sys.stdout or sys.stderr) - self.wrapped = wrapped - - # should we reset colors to defaults after every .write() - self.autoreset = autoreset - - # create the proxy wrapping our output stream - self.stream = StreamWrapper(wrapped, self) - - on_windows = os.name == 'nt' - # We test if the WinAPI works, because even if we are on Windows - # we may be using a terminal that doesn't support the WinAPI - # (e.g. Cygwin Terminal). In this case it's up to the terminal - # to support the ANSI codes. - conversion_supported = on_windows and winapi_test() - try: - fd = wrapped.fileno() - except Exception: - fd = -1 - system_has_native_ansi = not on_windows or enable_vt_processing(fd) - have_tty = not self.stream.closed and self.stream.isatty() - need_conversion = conversion_supported and not system_has_native_ansi - - # should we strip ANSI sequences from our output? - if strip is None: - strip = need_conversion or not have_tty - self.strip = strip - - # should we should convert ANSI sequences into win32 calls? - if convert is None: - convert = need_conversion and have_tty - self.convert = convert - - # dict of ansi codes to win32 functions and parameters - self.win32_calls = self.get_win32_calls() - - # are we wrapping stderr? - self.on_stderr = self.wrapped is sys.stderr - - def should_wrap(self): - ''' - True if this class is actually needed. If false, then the output - stream will not be affected, nor will win32 calls be issued, so - wrapping stdout is not actually required. This will generally be - False on non-Windows platforms, unless optional functionality like - autoreset has been requested using kwargs to init() - ''' - return self.convert or self.strip or self.autoreset - - def get_win32_calls(self): - if self.convert and winterm: - return { - AnsiStyle.RESET_ALL: (winterm.reset_all, ), - AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), - AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), - AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), - AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), - AnsiFore.RED: (winterm.fore, WinColor.RED), - AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), - AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), - AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), - AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), - AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), - AnsiFore.WHITE: (winterm.fore, WinColor.GREY), - AnsiFore.RESET: (winterm.fore, ), - AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True), - AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True), - AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True), - AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True), - AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True), - AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True), - AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True), - AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True), - AnsiBack.BLACK: (winterm.back, WinColor.BLACK), - AnsiBack.RED: (winterm.back, WinColor.RED), - AnsiBack.GREEN: (winterm.back, WinColor.GREEN), - AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), - AnsiBack.BLUE: (winterm.back, WinColor.BLUE), - AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), - AnsiBack.CYAN: (winterm.back, WinColor.CYAN), - AnsiBack.WHITE: (winterm.back, WinColor.GREY), - AnsiBack.RESET: (winterm.back, ), - AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True), - AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True), - AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True), - AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True), - AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True), - AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True), - AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True), - AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True), - } - return dict() - - def write(self, text): - if self.strip or self.convert: - self.write_and_convert(text) - else: - self.wrapped.write(text) - self.wrapped.flush() - if self.autoreset: - self.reset_all() - - - def reset_all(self): - if self.convert: - self.call_win32('m', (0,)) - elif not self.strip and not self.stream.closed: - self.wrapped.write(Style.RESET_ALL) - - - def write_and_convert(self, text): - ''' - Write the given text to our wrapped stream, stripping any ANSI - sequences from the text, and optionally converting them into win32 - calls. - ''' - cursor = 0 - text = self.convert_osc(text) - for match in self.ANSI_CSI_RE.finditer(text): - start, end = match.span() - self.write_plain_text(text, cursor, start) - self.convert_ansi(*match.groups()) - cursor = end - self.write_plain_text(text, cursor, len(text)) - - - def write_plain_text(self, text, start, end): - if start < end: - self.wrapped.write(text[start:end]) - self.wrapped.flush() - - - def convert_ansi(self, paramstring, command): - if self.convert: - params = self.extract_params(command, paramstring) - self.call_win32(command, params) - - - def extract_params(self, command, paramstring): - if command in 'Hf': - params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';')) - while len(params) < 2: - # defaults: - params = params + (1,) - else: - params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0) - if len(params) == 0: - # defaults: - if command in 'JKm': - params = (0,) - elif command in 'ABCD': - params = (1,) - - return params - - - def call_win32(self, command, params): - if command == 'm': - for param in params: - if param in self.win32_calls: - func_args = self.win32_calls[param] - func = func_args[0] - args = func_args[1:] - kwargs = dict(on_stderr=self.on_stderr) - func(*args, **kwargs) - elif command in 'J': - winterm.erase_screen(params[0], on_stderr=self.on_stderr) - elif command in 'K': - winterm.erase_line(params[0], on_stderr=self.on_stderr) - elif command in 'Hf': # cursor position - absolute - winterm.set_cursor_position(params, on_stderr=self.on_stderr) - elif command in 'ABCD': # cursor position - relative - n = params[0] - # A - up, B - down, C - forward, D - back - x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command] - winterm.cursor_adjust(x, y, on_stderr=self.on_stderr) - - - def convert_osc(self, text): - for match in self.ANSI_OSC_RE.finditer(text): - start, end = match.span() - text = text[:start] + text[end:] - paramstring, command = match.groups() - if command == BEL: - if paramstring.count(";") == 1: - params = paramstring.split(";") - # 0 - change title and icon (we will only change title) - # 1 - change icon (we don't support this) - # 2 - change title - if params[0] in '02': - winterm.set_title(params[1]) - return text - - - def flush(self): - self.wrapped.flush() diff --git a/notification-service/venv/Lib/site-packages/colorama/initialise.py b/notification-service/venv/Lib/site-packages/colorama/initialise.py deleted file mode 100644 index d5fd4b7..0000000 --- a/notification-service/venv/Lib/site-packages/colorama/initialise.py +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -import atexit -import contextlib -import sys - -from .ansitowin32 import AnsiToWin32 - - -def _wipe_internal_state_for_tests(): - global orig_stdout, orig_stderr - orig_stdout = None - orig_stderr = None - - global wrapped_stdout, wrapped_stderr - wrapped_stdout = None - wrapped_stderr = None - - global atexit_done - atexit_done = False - - global fixed_windows_console - fixed_windows_console = False - - try: - # no-op if it wasn't registered - atexit.unregister(reset_all) - except AttributeError: - # python 2: no atexit.unregister. Oh well, we did our best. - pass - - -def reset_all(): - if AnsiToWin32 is not None: # Issue #74: objects might become None at exit - AnsiToWin32(orig_stdout).reset_all() - - -def init(autoreset=False, convert=None, strip=None, wrap=True): - - if not wrap and any([autoreset, convert, strip]): - raise ValueError('wrap=False conflicts with any other arg=True') - - global wrapped_stdout, wrapped_stderr - global orig_stdout, orig_stderr - - orig_stdout = sys.stdout - orig_stderr = sys.stderr - - if sys.stdout is None: - wrapped_stdout = None - else: - sys.stdout = wrapped_stdout = \ - wrap_stream(orig_stdout, convert, strip, autoreset, wrap) - if sys.stderr is None: - wrapped_stderr = None - else: - sys.stderr = wrapped_stderr = \ - wrap_stream(orig_stderr, convert, strip, autoreset, wrap) - - global atexit_done - if not atexit_done: - atexit.register(reset_all) - atexit_done = True - - -def deinit(): - if orig_stdout is not None: - sys.stdout = orig_stdout - if orig_stderr is not None: - sys.stderr = orig_stderr - - -def just_fix_windows_console(): - global fixed_windows_console - - if sys.platform != "win32": - return - if fixed_windows_console: - return - if wrapped_stdout is not None or wrapped_stderr is not None: - # Someone already ran init() and it did stuff, so we won't second-guess them - return - - # On newer versions of Windows, AnsiToWin32.__init__ will implicitly enable the - # native ANSI support in the console as a side-effect. We only need to actually - # replace sys.stdout/stderr if we're in the old-style conversion mode. - new_stdout = AnsiToWin32(sys.stdout, convert=None, strip=None, autoreset=False) - if new_stdout.convert: - sys.stdout = new_stdout - new_stderr = AnsiToWin32(sys.stderr, convert=None, strip=None, autoreset=False) - if new_stderr.convert: - sys.stderr = new_stderr - - fixed_windows_console = True - -@contextlib.contextmanager -def colorama_text(*args, **kwargs): - init(*args, **kwargs) - try: - yield - finally: - deinit() - - -def reinit(): - if wrapped_stdout is not None: - sys.stdout = wrapped_stdout - if wrapped_stderr is not None: - sys.stderr = wrapped_stderr - - -def wrap_stream(stream, convert, strip, autoreset, wrap): - if wrap: - wrapper = AnsiToWin32(stream, - convert=convert, strip=strip, autoreset=autoreset) - if wrapper.should_wrap(): - stream = wrapper.stream - return stream - - -# Use this for initial setup as well, to reduce code duplication -_wipe_internal_state_for_tests() diff --git a/notification-service/venv/Lib/site-packages/colorama/tests/__init__.py b/notification-service/venv/Lib/site-packages/colorama/tests/__init__.py deleted file mode 100644 index 8c5661e..0000000 --- a/notification-service/venv/Lib/site-packages/colorama/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. diff --git a/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index e4005fa..0000000 Binary files a/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-312.pyc b/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-312.pyc deleted file mode 100644 index 39a826d..0000000 Binary files a/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc b/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc deleted file mode 100644 index 861b74f..0000000 Binary files a/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/initialise_test.cpython-312.pyc b/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/initialise_test.cpython-312.pyc deleted file mode 100644 index 053cbe9..0000000 Binary files a/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/initialise_test.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/isatty_test.cpython-312.pyc b/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/isatty_test.cpython-312.pyc deleted file mode 100644 index 8c972b9..0000000 Binary files a/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/isatty_test.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-312.pyc b/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-312.pyc deleted file mode 100644 index 3644150..0000000 Binary files a/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/winterm_test.cpython-312.pyc b/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/winterm_test.cpython-312.pyc deleted file mode 100644 index ef94750..0000000 Binary files a/notification-service/venv/Lib/site-packages/colorama/tests/__pycache__/winterm_test.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/colorama/tests/ansi_test.py b/notification-service/venv/Lib/site-packages/colorama/tests/ansi_test.py deleted file mode 100644 index 0a20c80..0000000 --- a/notification-service/venv/Lib/site-packages/colorama/tests/ansi_test.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -import sys -from unittest import TestCase, main - -from ..ansi import Back, Fore, Style -from ..ansitowin32 import AnsiToWin32 - -stdout_orig = sys.stdout -stderr_orig = sys.stderr - - -class AnsiTest(TestCase): - - def setUp(self): - # sanity check: stdout should be a file or StringIO object. - # It will only be AnsiToWin32 if init() has previously wrapped it - self.assertNotEqual(type(sys.stdout), AnsiToWin32) - self.assertNotEqual(type(sys.stderr), AnsiToWin32) - - def tearDown(self): - sys.stdout = stdout_orig - sys.stderr = stderr_orig - - - def testForeAttributes(self): - self.assertEqual(Fore.BLACK, '\033[30m') - self.assertEqual(Fore.RED, '\033[31m') - self.assertEqual(Fore.GREEN, '\033[32m') - self.assertEqual(Fore.YELLOW, '\033[33m') - self.assertEqual(Fore.BLUE, '\033[34m') - self.assertEqual(Fore.MAGENTA, '\033[35m') - self.assertEqual(Fore.CYAN, '\033[36m') - self.assertEqual(Fore.WHITE, '\033[37m') - self.assertEqual(Fore.RESET, '\033[39m') - - # Check the light, extended versions. - self.assertEqual(Fore.LIGHTBLACK_EX, '\033[90m') - self.assertEqual(Fore.LIGHTRED_EX, '\033[91m') - self.assertEqual(Fore.LIGHTGREEN_EX, '\033[92m') - self.assertEqual(Fore.LIGHTYELLOW_EX, '\033[93m') - self.assertEqual(Fore.LIGHTBLUE_EX, '\033[94m') - self.assertEqual(Fore.LIGHTMAGENTA_EX, '\033[95m') - self.assertEqual(Fore.LIGHTCYAN_EX, '\033[96m') - self.assertEqual(Fore.LIGHTWHITE_EX, '\033[97m') - - - def testBackAttributes(self): - self.assertEqual(Back.BLACK, '\033[40m') - self.assertEqual(Back.RED, '\033[41m') - self.assertEqual(Back.GREEN, '\033[42m') - self.assertEqual(Back.YELLOW, '\033[43m') - self.assertEqual(Back.BLUE, '\033[44m') - self.assertEqual(Back.MAGENTA, '\033[45m') - self.assertEqual(Back.CYAN, '\033[46m') - self.assertEqual(Back.WHITE, '\033[47m') - self.assertEqual(Back.RESET, '\033[49m') - - # Check the light, extended versions. - self.assertEqual(Back.LIGHTBLACK_EX, '\033[100m') - self.assertEqual(Back.LIGHTRED_EX, '\033[101m') - self.assertEqual(Back.LIGHTGREEN_EX, '\033[102m') - self.assertEqual(Back.LIGHTYELLOW_EX, '\033[103m') - self.assertEqual(Back.LIGHTBLUE_EX, '\033[104m') - self.assertEqual(Back.LIGHTMAGENTA_EX, '\033[105m') - self.assertEqual(Back.LIGHTCYAN_EX, '\033[106m') - self.assertEqual(Back.LIGHTWHITE_EX, '\033[107m') - - - def testStyleAttributes(self): - self.assertEqual(Style.DIM, '\033[2m') - self.assertEqual(Style.NORMAL, '\033[22m') - self.assertEqual(Style.BRIGHT, '\033[1m') - - -if __name__ == '__main__': - main() diff --git a/notification-service/venv/Lib/site-packages/colorama/tests/ansitowin32_test.py b/notification-service/venv/Lib/site-packages/colorama/tests/ansitowin32_test.py deleted file mode 100644 index 91ca551..0000000 --- a/notification-service/venv/Lib/site-packages/colorama/tests/ansitowin32_test.py +++ /dev/null @@ -1,294 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -from io import StringIO, TextIOWrapper -from unittest import TestCase, main -try: - from contextlib import ExitStack -except ImportError: - # python 2 - from contextlib2 import ExitStack - -try: - from unittest.mock import MagicMock, Mock, patch -except ImportError: - from mock import MagicMock, Mock, patch - -from ..ansitowin32 import AnsiToWin32, StreamWrapper -from ..win32 import ENABLE_VIRTUAL_TERMINAL_PROCESSING -from .utils import osname - - -class StreamWrapperTest(TestCase): - - def testIsAProxy(self): - mockStream = Mock() - wrapper = StreamWrapper(mockStream, None) - self.assertTrue( wrapper.random_attr is mockStream.random_attr ) - - def testDelegatesWrite(self): - mockStream = Mock() - mockConverter = Mock() - wrapper = StreamWrapper(mockStream, mockConverter) - wrapper.write('hello') - self.assertTrue(mockConverter.write.call_args, (('hello',), {})) - - def testDelegatesContext(self): - mockConverter = Mock() - s = StringIO() - with StreamWrapper(s, mockConverter) as fp: - fp.write(u'hello') - self.assertTrue(s.closed) - - def testProxyNoContextManager(self): - mockStream = MagicMock() - mockStream.__enter__.side_effect = AttributeError() - mockConverter = Mock() - with self.assertRaises(AttributeError) as excinfo: - with StreamWrapper(mockStream, mockConverter) as wrapper: - wrapper.write('hello') - - def test_closed_shouldnt_raise_on_closed_stream(self): - stream = StringIO() - stream.close() - wrapper = StreamWrapper(stream, None) - self.assertEqual(wrapper.closed, True) - - def test_closed_shouldnt_raise_on_detached_stream(self): - stream = TextIOWrapper(StringIO()) - stream.detach() - wrapper = StreamWrapper(stream, None) - self.assertEqual(wrapper.closed, True) - -class AnsiToWin32Test(TestCase): - - def testInit(self): - mockStdout = Mock() - auto = Mock() - stream = AnsiToWin32(mockStdout, autoreset=auto) - self.assertEqual(stream.wrapped, mockStdout) - self.assertEqual(stream.autoreset, auto) - - @patch('colorama.ansitowin32.winterm', None) - @patch('colorama.ansitowin32.winapi_test', lambda *_: True) - def testStripIsTrueOnWindows(self): - with osname('nt'): - mockStdout = Mock() - stream = AnsiToWin32(mockStdout) - self.assertTrue(stream.strip) - - def testStripIsFalseOffWindows(self): - with osname('posix'): - mockStdout = Mock(closed=False) - stream = AnsiToWin32(mockStdout) - self.assertFalse(stream.strip) - - def testWriteStripsAnsi(self): - mockStdout = Mock() - stream = AnsiToWin32(mockStdout) - stream.wrapped = Mock() - stream.write_and_convert = Mock() - stream.strip = True - - stream.write('abc') - - self.assertFalse(stream.wrapped.write.called) - self.assertEqual(stream.write_and_convert.call_args, (('abc',), {})) - - def testWriteDoesNotStripAnsi(self): - mockStdout = Mock() - stream = AnsiToWin32(mockStdout) - stream.wrapped = Mock() - stream.write_and_convert = Mock() - stream.strip = False - stream.convert = False - - stream.write('abc') - - self.assertFalse(stream.write_and_convert.called) - self.assertEqual(stream.wrapped.write.call_args, (('abc',), {})) - - def assert_autoresets(self, convert, autoreset=True): - stream = AnsiToWin32(Mock()) - stream.convert = convert - stream.reset_all = Mock() - stream.autoreset = autoreset - stream.winterm = Mock() - - stream.write('abc') - - self.assertEqual(stream.reset_all.called, autoreset) - - def testWriteAutoresets(self): - self.assert_autoresets(convert=True) - self.assert_autoresets(convert=False) - self.assert_autoresets(convert=True, autoreset=False) - self.assert_autoresets(convert=False, autoreset=False) - - def testWriteAndConvertWritesPlainText(self): - stream = AnsiToWin32(Mock()) - stream.write_and_convert( 'abc' ) - self.assertEqual( stream.wrapped.write.call_args, (('abc',), {}) ) - - def testWriteAndConvertStripsAllValidAnsi(self): - stream = AnsiToWin32(Mock()) - stream.call_win32 = Mock() - data = [ - 'abc\033[mdef', - 'abc\033[0mdef', - 'abc\033[2mdef', - 'abc\033[02mdef', - 'abc\033[002mdef', - 'abc\033[40mdef', - 'abc\033[040mdef', - 'abc\033[0;1mdef', - 'abc\033[40;50mdef', - 'abc\033[50;30;40mdef', - 'abc\033[Adef', - 'abc\033[0Gdef', - 'abc\033[1;20;128Hdef', - ] - for datum in data: - stream.wrapped.write.reset_mock() - stream.write_and_convert( datum ) - self.assertEqual( - [args[0] for args in stream.wrapped.write.call_args_list], - [ ('abc',), ('def',) ] - ) - - def testWriteAndConvertSkipsEmptySnippets(self): - stream = AnsiToWin32(Mock()) - stream.call_win32 = Mock() - stream.write_and_convert( '\033[40m\033[41m' ) - self.assertFalse( stream.wrapped.write.called ) - - def testWriteAndConvertCallsWin32WithParamsAndCommand(self): - stream = AnsiToWin32(Mock()) - stream.convert = True - stream.call_win32 = Mock() - stream.extract_params = Mock(return_value='params') - data = { - 'abc\033[adef': ('a', 'params'), - 'abc\033[;;bdef': ('b', 'params'), - 'abc\033[0cdef': ('c', 'params'), - 'abc\033[;;0;;Gdef': ('G', 'params'), - 'abc\033[1;20;128Hdef': ('H', 'params'), - } - for datum, expected in data.items(): - stream.call_win32.reset_mock() - stream.write_and_convert( datum ) - self.assertEqual( stream.call_win32.call_args[0], expected ) - - def test_reset_all_shouldnt_raise_on_closed_orig_stdout(self): - stream = StringIO() - converter = AnsiToWin32(stream) - stream.close() - - converter.reset_all() - - def test_wrap_shouldnt_raise_on_closed_orig_stdout(self): - stream = StringIO() - stream.close() - with \ - patch("colorama.ansitowin32.os.name", "nt"), \ - patch("colorama.ansitowin32.winapi_test", lambda: True): - converter = AnsiToWin32(stream) - self.assertTrue(converter.strip) - self.assertFalse(converter.convert) - - def test_wrap_shouldnt_raise_on_missing_closed_attr(self): - with \ - patch("colorama.ansitowin32.os.name", "nt"), \ - patch("colorama.ansitowin32.winapi_test", lambda: True): - converter = AnsiToWin32(object()) - self.assertTrue(converter.strip) - self.assertFalse(converter.convert) - - def testExtractParams(self): - stream = AnsiToWin32(Mock()) - data = { - '': (0,), - ';;': (0,), - '2': (2,), - ';;002;;': (2,), - '0;1': (0, 1), - ';;003;;456;;': (3, 456), - '11;22;33;44;55': (11, 22, 33, 44, 55), - } - for datum, expected in data.items(): - self.assertEqual(stream.extract_params('m', datum), expected) - - def testCallWin32UsesLookup(self): - listener = Mock() - stream = AnsiToWin32(listener) - stream.win32_calls = { - 1: (lambda *_, **__: listener(11),), - 2: (lambda *_, **__: listener(22),), - 3: (lambda *_, **__: listener(33),), - } - stream.call_win32('m', (3, 1, 99, 2)) - self.assertEqual( - [a[0][0] for a in listener.call_args_list], - [33, 11, 22] ) - - def test_osc_codes(self): - mockStdout = Mock() - stream = AnsiToWin32(mockStdout, convert=True) - with patch('colorama.ansitowin32.winterm') as winterm: - data = [ - '\033]0\x07', # missing arguments - '\033]0;foo\x08', # wrong OSC command - '\033]0;colorama_test_title\x07', # should work - '\033]1;colorama_test_title\x07', # wrong set command - '\033]2;colorama_test_title\x07', # should work - '\033]' + ';' * 64 + '\x08', # see issue #247 - ] - for code in data: - stream.write(code) - self.assertEqual(winterm.set_title.call_count, 2) - - def test_native_windows_ansi(self): - with ExitStack() as stack: - def p(a, b): - stack.enter_context(patch(a, b, create=True)) - # Pretend to be on Windows - p("colorama.ansitowin32.os.name", "nt") - p("colorama.ansitowin32.winapi_test", lambda: True) - p("colorama.win32.winapi_test", lambda: True) - p("colorama.winterm.win32.windll", "non-None") - p("colorama.winterm.get_osfhandle", lambda _: 1234) - - # Pretend that our mock stream has native ANSI support - p( - "colorama.winterm.win32.GetConsoleMode", - lambda _: ENABLE_VIRTUAL_TERMINAL_PROCESSING, - ) - SetConsoleMode = Mock() - p("colorama.winterm.win32.SetConsoleMode", SetConsoleMode) - - stdout = Mock() - stdout.closed = False - stdout.isatty.return_value = True - stdout.fileno.return_value = 1 - - # Our fake console says it has native vt support, so AnsiToWin32 should - # enable that support and do nothing else. - stream = AnsiToWin32(stdout) - SetConsoleMode.assert_called_with(1234, ENABLE_VIRTUAL_TERMINAL_PROCESSING) - self.assertFalse(stream.strip) - self.assertFalse(stream.convert) - self.assertFalse(stream.should_wrap()) - - # Now let's pretend we're on an old Windows console, that doesn't have - # native ANSI support. - p("colorama.winterm.win32.GetConsoleMode", lambda _: 0) - SetConsoleMode = Mock() - p("colorama.winterm.win32.SetConsoleMode", SetConsoleMode) - - stream = AnsiToWin32(stdout) - SetConsoleMode.assert_called_with(1234, ENABLE_VIRTUAL_TERMINAL_PROCESSING) - self.assertTrue(stream.strip) - self.assertTrue(stream.convert) - self.assertTrue(stream.should_wrap()) - - -if __name__ == '__main__': - main() diff --git a/notification-service/venv/Lib/site-packages/colorama/tests/initialise_test.py b/notification-service/venv/Lib/site-packages/colorama/tests/initialise_test.py deleted file mode 100644 index 89f9b07..0000000 --- a/notification-service/venv/Lib/site-packages/colorama/tests/initialise_test.py +++ /dev/null @@ -1,189 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -import sys -from unittest import TestCase, main, skipUnless - -try: - from unittest.mock import patch, Mock -except ImportError: - from mock import patch, Mock - -from ..ansitowin32 import StreamWrapper -from ..initialise import init, just_fix_windows_console, _wipe_internal_state_for_tests -from .utils import osname, replace_by - -orig_stdout = sys.stdout -orig_stderr = sys.stderr - - -class InitTest(TestCase): - - @skipUnless(sys.stdout.isatty(), "sys.stdout is not a tty") - def setUp(self): - # sanity check - self.assertNotWrapped() - - def tearDown(self): - _wipe_internal_state_for_tests() - sys.stdout = orig_stdout - sys.stderr = orig_stderr - - def assertWrapped(self): - self.assertIsNot(sys.stdout, orig_stdout, 'stdout should be wrapped') - self.assertIsNot(sys.stderr, orig_stderr, 'stderr should be wrapped') - self.assertTrue(isinstance(sys.stdout, StreamWrapper), - 'bad stdout wrapper') - self.assertTrue(isinstance(sys.stderr, StreamWrapper), - 'bad stderr wrapper') - - def assertNotWrapped(self): - self.assertIs(sys.stdout, orig_stdout, 'stdout should not be wrapped') - self.assertIs(sys.stderr, orig_stderr, 'stderr should not be wrapped') - - @patch('colorama.initialise.reset_all') - @patch('colorama.ansitowin32.winapi_test', lambda *_: True) - @patch('colorama.ansitowin32.enable_vt_processing', lambda *_: False) - def testInitWrapsOnWindows(self, _): - with osname("nt"): - init() - self.assertWrapped() - - @patch('colorama.initialise.reset_all') - @patch('colorama.ansitowin32.winapi_test', lambda *_: False) - def testInitDoesntWrapOnEmulatedWindows(self, _): - with osname("nt"): - init() - self.assertNotWrapped() - - def testInitDoesntWrapOnNonWindows(self): - with osname("posix"): - init() - self.assertNotWrapped() - - def testInitDoesntWrapIfNone(self): - with replace_by(None): - init() - # We can't use assertNotWrapped here because replace_by(None) - # changes stdout/stderr already. - self.assertIsNone(sys.stdout) - self.assertIsNone(sys.stderr) - - def testInitAutoresetOnWrapsOnAllPlatforms(self): - with osname("posix"): - init(autoreset=True) - self.assertWrapped() - - def testInitWrapOffDoesntWrapOnWindows(self): - with osname("nt"): - init(wrap=False) - self.assertNotWrapped() - - def testInitWrapOffIncompatibleWithAutoresetOn(self): - self.assertRaises(ValueError, lambda: init(autoreset=True, wrap=False)) - - @patch('colorama.win32.SetConsoleTextAttribute') - @patch('colorama.initialise.AnsiToWin32') - def testAutoResetPassedOn(self, mockATW32, _): - with osname("nt"): - init(autoreset=True) - self.assertEqual(len(mockATW32.call_args_list), 2) - self.assertEqual(mockATW32.call_args_list[1][1]['autoreset'], True) - self.assertEqual(mockATW32.call_args_list[0][1]['autoreset'], True) - - @patch('colorama.initialise.AnsiToWin32') - def testAutoResetChangeable(self, mockATW32): - with osname("nt"): - init() - - init(autoreset=True) - self.assertEqual(len(mockATW32.call_args_list), 4) - self.assertEqual(mockATW32.call_args_list[2][1]['autoreset'], True) - self.assertEqual(mockATW32.call_args_list[3][1]['autoreset'], True) - - init() - self.assertEqual(len(mockATW32.call_args_list), 6) - self.assertEqual( - mockATW32.call_args_list[4][1]['autoreset'], False) - self.assertEqual( - mockATW32.call_args_list[5][1]['autoreset'], False) - - - @patch('colorama.initialise.atexit.register') - def testAtexitRegisteredOnlyOnce(self, mockRegister): - init() - self.assertTrue(mockRegister.called) - mockRegister.reset_mock() - init() - self.assertFalse(mockRegister.called) - - -class JustFixWindowsConsoleTest(TestCase): - def _reset(self): - _wipe_internal_state_for_tests() - sys.stdout = orig_stdout - sys.stderr = orig_stderr - - def tearDown(self): - self._reset() - - @patch("colorama.ansitowin32.winapi_test", lambda: True) - def testJustFixWindowsConsole(self): - if sys.platform != "win32": - # just_fix_windows_console should be a no-op - just_fix_windows_console() - self.assertIs(sys.stdout, orig_stdout) - self.assertIs(sys.stderr, orig_stderr) - else: - def fake_std(): - # Emulate stdout=not a tty, stderr=tty - # to check that we handle both cases correctly - stdout = Mock() - stdout.closed = False - stdout.isatty.return_value = False - stdout.fileno.return_value = 1 - sys.stdout = stdout - - stderr = Mock() - stderr.closed = False - stderr.isatty.return_value = True - stderr.fileno.return_value = 2 - sys.stderr = stderr - - for native_ansi in [False, True]: - with patch( - 'colorama.ansitowin32.enable_vt_processing', - lambda *_: native_ansi - ): - self._reset() - fake_std() - - # Regular single-call test - prev_stdout = sys.stdout - prev_stderr = sys.stderr - just_fix_windows_console() - self.assertIs(sys.stdout, prev_stdout) - if native_ansi: - self.assertIs(sys.stderr, prev_stderr) - else: - self.assertIsNot(sys.stderr, prev_stderr) - - # second call without resetting is always a no-op - prev_stdout = sys.stdout - prev_stderr = sys.stderr - just_fix_windows_console() - self.assertIs(sys.stdout, prev_stdout) - self.assertIs(sys.stderr, prev_stderr) - - self._reset() - fake_std() - - # If init() runs first, just_fix_windows_console should be a no-op - init() - prev_stdout = sys.stdout - prev_stderr = sys.stderr - just_fix_windows_console() - self.assertIs(prev_stdout, sys.stdout) - self.assertIs(prev_stderr, sys.stderr) - - -if __name__ == '__main__': - main() diff --git a/notification-service/venv/Lib/site-packages/colorama/tests/isatty_test.py b/notification-service/venv/Lib/site-packages/colorama/tests/isatty_test.py deleted file mode 100644 index 0f84e4b..0000000 --- a/notification-service/venv/Lib/site-packages/colorama/tests/isatty_test.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -import sys -from unittest import TestCase, main - -from ..ansitowin32 import StreamWrapper, AnsiToWin32 -from .utils import pycharm, replace_by, replace_original_by, StreamTTY, StreamNonTTY - - -def is_a_tty(stream): - return StreamWrapper(stream, None).isatty() - -class IsattyTest(TestCase): - - def test_TTY(self): - tty = StreamTTY() - self.assertTrue(is_a_tty(tty)) - with pycharm(): - self.assertTrue(is_a_tty(tty)) - - def test_nonTTY(self): - non_tty = StreamNonTTY() - self.assertFalse(is_a_tty(non_tty)) - with pycharm(): - self.assertFalse(is_a_tty(non_tty)) - - def test_withPycharm(self): - with pycharm(): - self.assertTrue(is_a_tty(sys.stderr)) - self.assertTrue(is_a_tty(sys.stdout)) - - def test_withPycharmTTYOverride(self): - tty = StreamTTY() - with pycharm(), replace_by(tty): - self.assertTrue(is_a_tty(tty)) - - def test_withPycharmNonTTYOverride(self): - non_tty = StreamNonTTY() - with pycharm(), replace_by(non_tty): - self.assertFalse(is_a_tty(non_tty)) - - def test_withPycharmNoneOverride(self): - with pycharm(): - with replace_by(None), replace_original_by(None): - self.assertFalse(is_a_tty(None)) - self.assertFalse(is_a_tty(StreamNonTTY())) - self.assertTrue(is_a_tty(StreamTTY())) - - def test_withPycharmStreamWrapped(self): - with pycharm(): - self.assertTrue(AnsiToWin32(StreamTTY()).stream.isatty()) - self.assertFalse(AnsiToWin32(StreamNonTTY()).stream.isatty()) - self.assertTrue(AnsiToWin32(sys.stdout).stream.isatty()) - self.assertTrue(AnsiToWin32(sys.stderr).stream.isatty()) - - -if __name__ == '__main__': - main() diff --git a/notification-service/venv/Lib/site-packages/colorama/tests/utils.py b/notification-service/venv/Lib/site-packages/colorama/tests/utils.py deleted file mode 100644 index 472fafb..0000000 --- a/notification-service/venv/Lib/site-packages/colorama/tests/utils.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -from contextlib import contextmanager -from io import StringIO -import sys -import os - - -class StreamTTY(StringIO): - def isatty(self): - return True - -class StreamNonTTY(StringIO): - def isatty(self): - return False - -@contextmanager -def osname(name): - orig = os.name - os.name = name - yield - os.name = orig - -@contextmanager -def replace_by(stream): - orig_stdout = sys.stdout - orig_stderr = sys.stderr - sys.stdout = stream - sys.stderr = stream - yield - sys.stdout = orig_stdout - sys.stderr = orig_stderr - -@contextmanager -def replace_original_by(stream): - orig_stdout = sys.__stdout__ - orig_stderr = sys.__stderr__ - sys.__stdout__ = stream - sys.__stderr__ = stream - yield - sys.__stdout__ = orig_stdout - sys.__stderr__ = orig_stderr - -@contextmanager -def pycharm(): - os.environ["PYCHARM_HOSTED"] = "1" - non_tty = StreamNonTTY() - with replace_by(non_tty), replace_original_by(non_tty): - yield - del os.environ["PYCHARM_HOSTED"] diff --git a/notification-service/venv/Lib/site-packages/colorama/tests/winterm_test.py b/notification-service/venv/Lib/site-packages/colorama/tests/winterm_test.py deleted file mode 100644 index d0955f9..0000000 --- a/notification-service/venv/Lib/site-packages/colorama/tests/winterm_test.py +++ /dev/null @@ -1,131 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -import sys -from unittest import TestCase, main, skipUnless - -try: - from unittest.mock import Mock, patch -except ImportError: - from mock import Mock, patch - -from ..winterm import WinColor, WinStyle, WinTerm - - -class WinTermTest(TestCase): - - @patch('colorama.winterm.win32') - def testInit(self, mockWin32): - mockAttr = Mock() - mockAttr.wAttributes = 7 + 6 * 16 + 8 - mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr - term = WinTerm() - self.assertEqual(term._fore, 7) - self.assertEqual(term._back, 6) - self.assertEqual(term._style, 8) - - @skipUnless(sys.platform.startswith("win"), "requires Windows") - def testGetAttrs(self): - term = WinTerm() - - term._fore = 0 - term._back = 0 - term._style = 0 - self.assertEqual(term.get_attrs(), 0) - - term._fore = WinColor.YELLOW - self.assertEqual(term.get_attrs(), WinColor.YELLOW) - - term._back = WinColor.MAGENTA - self.assertEqual( - term.get_attrs(), - WinColor.YELLOW + WinColor.MAGENTA * 16) - - term._style = WinStyle.BRIGHT - self.assertEqual( - term.get_attrs(), - WinColor.YELLOW + WinColor.MAGENTA * 16 + WinStyle.BRIGHT) - - @patch('colorama.winterm.win32') - def testResetAll(self, mockWin32): - mockAttr = Mock() - mockAttr.wAttributes = 1 + 2 * 16 + 8 - mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr - term = WinTerm() - - term.set_console = Mock() - term._fore = -1 - term._back = -1 - term._style = -1 - - term.reset_all() - - self.assertEqual(term._fore, 1) - self.assertEqual(term._back, 2) - self.assertEqual(term._style, 8) - self.assertEqual(term.set_console.called, True) - - @skipUnless(sys.platform.startswith("win"), "requires Windows") - def testFore(self): - term = WinTerm() - term.set_console = Mock() - term._fore = 0 - - term.fore(5) - - self.assertEqual(term._fore, 5) - self.assertEqual(term.set_console.called, True) - - @skipUnless(sys.platform.startswith("win"), "requires Windows") - def testBack(self): - term = WinTerm() - term.set_console = Mock() - term._back = 0 - - term.back(5) - - self.assertEqual(term._back, 5) - self.assertEqual(term.set_console.called, True) - - @skipUnless(sys.platform.startswith("win"), "requires Windows") - def testStyle(self): - term = WinTerm() - term.set_console = Mock() - term._style = 0 - - term.style(22) - - self.assertEqual(term._style, 22) - self.assertEqual(term.set_console.called, True) - - @patch('colorama.winterm.win32') - def testSetConsole(self, mockWin32): - mockAttr = Mock() - mockAttr.wAttributes = 0 - mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr - term = WinTerm() - term.windll = Mock() - - term.set_console() - - self.assertEqual( - mockWin32.SetConsoleTextAttribute.call_args, - ((mockWin32.STDOUT, term.get_attrs()), {}) - ) - - @patch('colorama.winterm.win32') - def testSetConsoleOnStderr(self, mockWin32): - mockAttr = Mock() - mockAttr.wAttributes = 0 - mockWin32.GetConsoleScreenBufferInfo.return_value = mockAttr - term = WinTerm() - term.windll = Mock() - - term.set_console(on_stderr=True) - - self.assertEqual( - mockWin32.SetConsoleTextAttribute.call_args, - ((mockWin32.STDERR, term.get_attrs()), {}) - ) - - -if __name__ == '__main__': - main() diff --git a/notification-service/venv/Lib/site-packages/colorama/win32.py b/notification-service/venv/Lib/site-packages/colorama/win32.py deleted file mode 100644 index 841b0e2..0000000 --- a/notification-service/venv/Lib/site-packages/colorama/win32.py +++ /dev/null @@ -1,180 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. - -# from winbase.h -STDOUT = -11 -STDERR = -12 - -ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 - -try: - import ctypes - from ctypes import LibraryLoader - windll = LibraryLoader(ctypes.WinDLL) - from ctypes import wintypes -except (AttributeError, ImportError): - windll = None - SetConsoleTextAttribute = lambda *_: None - winapi_test = lambda *_: None -else: - from ctypes import byref, Structure, c_char, POINTER - - COORD = wintypes._COORD - - class CONSOLE_SCREEN_BUFFER_INFO(Structure): - """struct in wincon.h.""" - _fields_ = [ - ("dwSize", COORD), - ("dwCursorPosition", COORD), - ("wAttributes", wintypes.WORD), - ("srWindow", wintypes.SMALL_RECT), - ("dwMaximumWindowSize", COORD), - ] - def __str__(self): - return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( - self.dwSize.Y, self.dwSize.X - , self.dwCursorPosition.Y, self.dwCursorPosition.X - , self.wAttributes - , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right - , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X - ) - - _GetStdHandle = windll.kernel32.GetStdHandle - _GetStdHandle.argtypes = [ - wintypes.DWORD, - ] - _GetStdHandle.restype = wintypes.HANDLE - - _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo - _GetConsoleScreenBufferInfo.argtypes = [ - wintypes.HANDLE, - POINTER(CONSOLE_SCREEN_BUFFER_INFO), - ] - _GetConsoleScreenBufferInfo.restype = wintypes.BOOL - - _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute - _SetConsoleTextAttribute.argtypes = [ - wintypes.HANDLE, - wintypes.WORD, - ] - _SetConsoleTextAttribute.restype = wintypes.BOOL - - _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition - _SetConsoleCursorPosition.argtypes = [ - wintypes.HANDLE, - COORD, - ] - _SetConsoleCursorPosition.restype = wintypes.BOOL - - _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA - _FillConsoleOutputCharacterA.argtypes = [ - wintypes.HANDLE, - c_char, - wintypes.DWORD, - COORD, - POINTER(wintypes.DWORD), - ] - _FillConsoleOutputCharacterA.restype = wintypes.BOOL - - _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute - _FillConsoleOutputAttribute.argtypes = [ - wintypes.HANDLE, - wintypes.WORD, - wintypes.DWORD, - COORD, - POINTER(wintypes.DWORD), - ] - _FillConsoleOutputAttribute.restype = wintypes.BOOL - - _SetConsoleTitleW = windll.kernel32.SetConsoleTitleW - _SetConsoleTitleW.argtypes = [ - wintypes.LPCWSTR - ] - _SetConsoleTitleW.restype = wintypes.BOOL - - _GetConsoleMode = windll.kernel32.GetConsoleMode - _GetConsoleMode.argtypes = [ - wintypes.HANDLE, - POINTER(wintypes.DWORD) - ] - _GetConsoleMode.restype = wintypes.BOOL - - _SetConsoleMode = windll.kernel32.SetConsoleMode - _SetConsoleMode.argtypes = [ - wintypes.HANDLE, - wintypes.DWORD - ] - _SetConsoleMode.restype = wintypes.BOOL - - def _winapi_test(handle): - csbi = CONSOLE_SCREEN_BUFFER_INFO() - success = _GetConsoleScreenBufferInfo( - handle, byref(csbi)) - return bool(success) - - def winapi_test(): - return any(_winapi_test(h) for h in - (_GetStdHandle(STDOUT), _GetStdHandle(STDERR))) - - def GetConsoleScreenBufferInfo(stream_id=STDOUT): - handle = _GetStdHandle(stream_id) - csbi = CONSOLE_SCREEN_BUFFER_INFO() - success = _GetConsoleScreenBufferInfo( - handle, byref(csbi)) - return csbi - - def SetConsoleTextAttribute(stream_id, attrs): - handle = _GetStdHandle(stream_id) - return _SetConsoleTextAttribute(handle, attrs) - - def SetConsoleCursorPosition(stream_id, position, adjust=True): - position = COORD(*position) - # If the position is out of range, do nothing. - if position.Y <= 0 or position.X <= 0: - return - # Adjust for Windows' SetConsoleCursorPosition: - # 1. being 0-based, while ANSI is 1-based. - # 2. expecting (x,y), while ANSI uses (y,x). - adjusted_position = COORD(position.Y - 1, position.X - 1) - if adjust: - # Adjust for viewport's scroll position - sr = GetConsoleScreenBufferInfo(STDOUT).srWindow - adjusted_position.Y += sr.Top - adjusted_position.X += sr.Left - # Resume normal processing - handle = _GetStdHandle(stream_id) - return _SetConsoleCursorPosition(handle, adjusted_position) - - def FillConsoleOutputCharacter(stream_id, char, length, start): - handle = _GetStdHandle(stream_id) - char = c_char(char.encode()) - length = wintypes.DWORD(length) - num_written = wintypes.DWORD(0) - # Note that this is hard-coded for ANSI (vs wide) bytes. - success = _FillConsoleOutputCharacterA( - handle, char, length, start, byref(num_written)) - return num_written.value - - def FillConsoleOutputAttribute(stream_id, attr, length, start): - ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' - handle = _GetStdHandle(stream_id) - attribute = wintypes.WORD(attr) - length = wintypes.DWORD(length) - num_written = wintypes.DWORD(0) - # Note that this is hard-coded for ANSI (vs wide) bytes. - return _FillConsoleOutputAttribute( - handle, attribute, length, start, byref(num_written)) - - def SetConsoleTitle(title): - return _SetConsoleTitleW(title) - - def GetConsoleMode(handle): - mode = wintypes.DWORD() - success = _GetConsoleMode(handle, byref(mode)) - if not success: - raise ctypes.WinError() - return mode.value - - def SetConsoleMode(handle, mode): - success = _SetConsoleMode(handle, mode) - if not success: - raise ctypes.WinError() diff --git a/notification-service/venv/Lib/site-packages/colorama/winterm.py b/notification-service/venv/Lib/site-packages/colorama/winterm.py deleted file mode 100644 index aad867e..0000000 --- a/notification-service/venv/Lib/site-packages/colorama/winterm.py +++ /dev/null @@ -1,195 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -try: - from msvcrt import get_osfhandle -except ImportError: - def get_osfhandle(_): - raise OSError("This isn't windows!") - - -from . import win32 - -# from wincon.h -class WinColor(object): - BLACK = 0 - BLUE = 1 - GREEN = 2 - CYAN = 3 - RED = 4 - MAGENTA = 5 - YELLOW = 6 - GREY = 7 - -# from wincon.h -class WinStyle(object): - NORMAL = 0x00 # dim text, dim background - BRIGHT = 0x08 # bright text, dim background - BRIGHT_BACKGROUND = 0x80 # dim text, bright background - -class WinTerm(object): - - def __init__(self): - self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes - self.set_attrs(self._default) - self._default_fore = self._fore - self._default_back = self._back - self._default_style = self._style - # In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style. - # So that LIGHT_EX colors and BRIGHT style do not clobber each other, - # we track them separately, since LIGHT_EX is overwritten by Fore/Back - # and BRIGHT is overwritten by Style codes. - self._light = 0 - - def get_attrs(self): - return self._fore + self._back * 16 + (self._style | self._light) - - def set_attrs(self, value): - self._fore = value & 7 - self._back = (value >> 4) & 7 - self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND) - - def reset_all(self, on_stderr=None): - self.set_attrs(self._default) - self.set_console(attrs=self._default) - self._light = 0 - - def fore(self, fore=None, light=False, on_stderr=False): - if fore is None: - fore = self._default_fore - self._fore = fore - # Emulate LIGHT_EX with BRIGHT Style - if light: - self._light |= WinStyle.BRIGHT - else: - self._light &= ~WinStyle.BRIGHT - self.set_console(on_stderr=on_stderr) - - def back(self, back=None, light=False, on_stderr=False): - if back is None: - back = self._default_back - self._back = back - # Emulate LIGHT_EX with BRIGHT_BACKGROUND Style - if light: - self._light |= WinStyle.BRIGHT_BACKGROUND - else: - self._light &= ~WinStyle.BRIGHT_BACKGROUND - self.set_console(on_stderr=on_stderr) - - def style(self, style=None, on_stderr=False): - if style is None: - style = self._default_style - self._style = style - self.set_console(on_stderr=on_stderr) - - def set_console(self, attrs=None, on_stderr=False): - if attrs is None: - attrs = self.get_attrs() - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - win32.SetConsoleTextAttribute(handle, attrs) - - def get_position(self, handle): - position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition - # Because Windows coordinates are 0-based, - # and win32.SetConsoleCursorPosition expects 1-based. - position.X += 1 - position.Y += 1 - return position - - def set_cursor_position(self, position=None, on_stderr=False): - if position is None: - # I'm not currently tracking the position, so there is no default. - # position = self.get_position() - return - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - win32.SetConsoleCursorPosition(handle, position) - - def cursor_adjust(self, x, y, on_stderr=False): - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - position = self.get_position(handle) - adjusted_position = (position.Y + y, position.X + x) - win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False) - - def erase_screen(self, mode=0, on_stderr=False): - # 0 should clear from the cursor to the end of the screen. - # 1 should clear from the cursor to the beginning of the screen. - # 2 should clear the entire screen, and move cursor to (1,1) - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - csbi = win32.GetConsoleScreenBufferInfo(handle) - # get the number of character cells in the current buffer - cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y - # get number of character cells before current cursor position - cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X - if mode == 0: - from_coord = csbi.dwCursorPosition - cells_to_erase = cells_in_screen - cells_before_cursor - elif mode == 1: - from_coord = win32.COORD(0, 0) - cells_to_erase = cells_before_cursor - elif mode == 2: - from_coord = win32.COORD(0, 0) - cells_to_erase = cells_in_screen - else: - # invalid mode - return - # fill the entire screen with blanks - win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) - # now set the buffer's attributes accordingly - win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) - if mode == 2: - # put the cursor where needed - win32.SetConsoleCursorPosition(handle, (1, 1)) - - def erase_line(self, mode=0, on_stderr=False): - # 0 should clear from the cursor to the end of the line. - # 1 should clear from the cursor to the beginning of the line. - # 2 should clear the entire line. - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - csbi = win32.GetConsoleScreenBufferInfo(handle) - if mode == 0: - from_coord = csbi.dwCursorPosition - cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X - elif mode == 1: - from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) - cells_to_erase = csbi.dwCursorPosition.X - elif mode == 2: - from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) - cells_to_erase = csbi.dwSize.X - else: - # invalid mode - return - # fill the entire screen with blanks - win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) - # now set the buffer's attributes accordingly - win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) - - def set_title(self, title): - win32.SetConsoleTitle(title) - - -def enable_vt_processing(fd): - if win32.windll is None or not win32.winapi_test(): - return False - - try: - handle = get_osfhandle(fd) - mode = win32.GetConsoleMode(handle) - win32.SetConsoleMode( - handle, - mode | win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING, - ) - - mode = win32.GetConsoleMode(handle) - if mode & win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING: - return True - # Can get TypeError in testsuite where 'fd' is a Mock() - except (OSError, TypeError): - return False diff --git a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/INSTALLER b/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/METADATA b/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/METADATA deleted file mode 100644 index fbea0aa..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/METADATA +++ /dev/null @@ -1,110 +0,0 @@ -Metadata-Version: 2.4 -Name: cryptography -Version: 48.0.0 -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: Natural Language :: English -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Operating System :: POSIX -Classifier: Operating System :: POSIX :: BSD -Classifier: Operating System :: POSIX :: Linux -Classifier: Operating System :: Microsoft :: Windows -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3 :: Only -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 :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Programming Language :: Python :: Free Threading :: 3 - Stable -Classifier: Topic :: Security :: Cryptography -Requires-Dist: cffi>=2.0.0 ; platform_python_implementation != 'PyPy' -Requires-Dist: typing-extensions>=4.13.2 ; python_full_version < '3.11' -Requires-Dist: bcrypt>=3.1.5 ; extra == 'ssh' -Provides-Extra: ssh -License-File: LICENSE -License-File: LICENSE.APACHE -License-File: LICENSE.BSD -Summary: cryptography is a package which provides cryptographic recipes and primitives to Python developers. -Author-email: The Python Cryptographic Authority and individual contributors -License-Expression: Apache-2.0 OR BSD-3-Clause -Requires-Python: >=3.9, !=3.9.0, !=3.9.1 -Description-Content-Type: text/x-rst; charset=UTF-8 -Project-URL: changelog, https://cryptography.io/en/latest/changelog/ -Project-URL: documentation, https://cryptography.io/ -Project-URL: homepage, https://github.com/pyca/cryptography -Project-URL: issues, https://github.com/pyca/cryptography/issues -Project-URL: source, https://github.com/pyca/cryptography/ - -pyca/cryptography -================= - -.. image:: https://img.shields.io/pypi/v/cryptography.svg - :target: https://pypi.org/project/cryptography/ - :alt: Latest Version - -.. image:: https://readthedocs.org/projects/cryptography/badge/?version=latest - :target: https://cryptography.io - :alt: Latest Docs - -.. image:: https://github.com/pyca/cryptography/actions/workflows/ci.yml/badge.svg - :target: https://github.com/pyca/cryptography/actions/workflows/ci.yml?query=branch%3Amain - -``cryptography`` is a package which provides cryptographic recipes and -primitives to Python developers. Our goal is for it to be your "cryptographic -standard library". It supports Python 3.9+ and PyPy3 7.3.11+. - -``cryptography`` includes both high level recipes and low level interfaces to -common cryptographic algorithms such as symmetric ciphers, message digests, and -key derivation functions. For example, to encrypt something with -``cryptography``'s high level symmetric encryption recipe: - -.. code-block:: pycon - - >>> from cryptography.fernet import Fernet - >>> # Put this somewhere safe! - >>> key = Fernet.generate_key() - >>> f = Fernet(key) - >>> token = f.encrypt(b"A really secret message. Not for prying eyes.") - >>> token - b'...' - >>> f.decrypt(token) - b'A really secret message. Not for prying eyes.' - -You can find more information in the `documentation`_. - -You can install ``cryptography`` with: - -.. code-block:: console - - $ pip install cryptography - -For full details see `the installation documentation`_. - -Discussion -~~~~~~~~~~ - -If you run into bugs, you can file them in our `issue tracker`_. - -We maintain a `cryptography-dev`_ mailing list for development discussion. - -You can also join ``#pyca`` on ``irc.libera.chat`` to ask questions or get -involved. - -Security -~~~~~~~~ - -Need to report a security issue? Please consult our `security reporting`_ -documentation. - - -.. _`documentation`: https://cryptography.io/ -.. _`the installation documentation`: https://cryptography.io/en/latest/installation/ -.. _`issue tracker`: https://github.com/pyca/cryptography/issues -.. _`cryptography-dev`: https://mail.python.org/mailman/listinfo/cryptography-dev -.. _`security reporting`: https://cryptography.io/en/latest/security/ - diff --git a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/RECORD b/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/RECORD deleted file mode 100644 index 7eacb8d..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/RECORD +++ /dev/null @@ -1,195 +0,0 @@ -cryptography-48.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -cryptography-48.0.0.dist-info/METADATA,sha256=Q_COX-Utpsgl5e4Ym9mF7hU3hgAgMy3Ly8XaVnneyQY,4343 -cryptography-48.0.0.dist-info/RECORD,, -cryptography-48.0.0.dist-info/WHEEL,sha256=lGUDgbV_nPYOoJsY099H2WbVKMuG8e7U3fBXeO09bHU,96 -cryptography-48.0.0.dist-info/licenses/LICENSE,sha256=Pgx8CRqUi4JTO6mP18u0BDLW8amsv4X1ki0vmak65rs,197 -cryptography-48.0.0.dist-info/licenses/LICENSE.APACHE,sha256=qsc7MUj20dcRHbyjIJn2jSbGRMaBOuHk8F9leaomY_4,11360 -cryptography-48.0.0.dist-info/licenses/LICENSE.BSD,sha256=YCxMdILeZHndLpeTzaJ15eY9dz2s0eymiSMqtwCPtPs,1532 -cryptography-48.0.0.dist-info/sboms/cryptography-rust.cyclonedx.json,sha256=42ZyM2sqoZGpednP_YPuLTjZlQH294uKjxJ5OO9GguM,45557 -cryptography-48.0.0.dist-info/sboms/sbom.json,sha256=5swS0MMKevqcpxG1KQbZAfuiS-pXyBSt8859X-HGxjo,1223 -cryptography/__about__.py,sha256=4Ay52_5LrlJ_oTPcjtV4NXOcNzJhpo6iDZPEYbndzJI,445 -cryptography/__init__.py,sha256=mthuUrTd4FROCpUYrTIqhjz6s6T9djAZrV7nZ1oMm2o,364 -cryptography/__pycache__/__about__.cpython-312.pyc,, -cryptography/__pycache__/__init__.cpython-312.pyc,, -cryptography/__pycache__/exceptions.cpython-312.pyc,, -cryptography/__pycache__/fernet.cpython-312.pyc,, -cryptography/__pycache__/utils.cpython-312.pyc,, -cryptography/exceptions.py,sha256=835EWILc2fwxw-gyFMriciC2SqhViETB10LBSytnDIc,1087 -cryptography/fernet.py,sha256=3Cvxkh0KJSbX8HbnCHu4wfCW7U0GgfUA3v_qQ8a8iWc,6963 -cryptography/hazmat/__init__.py,sha256=5IwrLWrVp0AjEr_4FdWG_V057NSJGY_W4egNNsuct0g,455 -cryptography/hazmat/__pycache__/__init__.cpython-312.pyc,, -cryptography/hazmat/__pycache__/_oid.cpython-312.pyc,, -cryptography/hazmat/_oid.py,sha256=p8ThjwJB56Ci_rAIrjyJ1f8VjgD6e39es2dh8JIUBOw,17240 -cryptography/hazmat/asn1/__init__.py,sha256=AZVmLA09Q9-bq27G8fYr3dof-iRkh5KSX3zEPmNb-9w,744 -cryptography/hazmat/asn1/__pycache__/__init__.cpython-312.pyc,, -cryptography/hazmat/asn1/__pycache__/asn1.cpython-312.pyc,, -cryptography/hazmat/asn1/asn1.py,sha256=FZ6nZr3N1kKqNBQfh0qKtJ0cLUjwtGFemG82KNWOcfk,14724 -cryptography/hazmat/backends/__init__.py,sha256=O5jvKFQdZnXhKeqJ-HtulaEL9Ni7mr1mDzZY5kHlYhI,361 -cryptography/hazmat/backends/__pycache__/__init__.cpython-312.pyc,, -cryptography/hazmat/backends/openssl/__init__.py,sha256=p3jmJfnCag9iE5sdMrN6VvVEu55u46xaS_IjoI0SrmA,305 -cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-312.pyc,, -cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-312.pyc,, -cryptography/hazmat/backends/openssl/backend.py,sha256=7A8JKJlQjG3-Fqdcyat2Eb7kHLYAAtGF0j9ooaWyaE0,10520 -cryptography/hazmat/bindings/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180 -cryptography/hazmat/bindings/__pycache__/__init__.cpython-312.pyc,, -cryptography/hazmat/bindings/_rust.pyd,sha256=BR41VmbY0kKCfHlptw9tprfyeqI_zVw2_LDIG8JaaFY,9903104 -cryptography/hazmat/bindings/_rust/__init__.pyi,sha256=uUnnvOq_uameYnBNpmsv3SRAVO0WQGpjI58aR1lL4Kw,2285 -cryptography/hazmat/bindings/_rust/_openssl.pyi,sha256=T_5TpYO8bghIPjAQ3BtAABqw-CcYskHp92wm5PNY6dc,228 -cryptography/hazmat/bindings/_rust/asn1.pyi,sha256=BrGjC8J6nwuS-r3EVcdXJB8ndotfY9mbQYOfpbPG0HA,354 -cryptography/hazmat/bindings/_rust/declarative_asn1.pyi,sha256=iSeRyyd3hN0VIUKg_p424AzQ-b7hW1b_53Yx50yniYY,3661 -cryptography/hazmat/bindings/_rust/exceptions.pyi,sha256=exXr2xw_0pB1kk93cYbM3MohbzoUkjOms1ZMUi0uQZE,640 -cryptography/hazmat/bindings/_rust/ocsp.pyi,sha256=VPVWuKHI9EMs09ZLRYAGvR0Iz0mCMmEzXAkgJHovpoM,4020 -cryptography/hazmat/bindings/_rust/openssl/__init__.pyi,sha256=JDCef29vXnrEMvF13JH9z1-W9ahiTZQAk5xhu_KH6po,1550 -cryptography/hazmat/bindings/_rust/openssl/aead.pyi,sha256=7d--xdc0vuzRe4S2uuQaGm-9GGKv4NcSLQcLyWcaD6s,4582 -cryptography/hazmat/bindings/_rust/openssl/ciphers.pyi,sha256=LhPzHWSXJq4grAJXn6zSvSSdV-aYIIscHDwIPlJGGPs,1315 -cryptography/hazmat/bindings/_rust/openssl/cmac.pyi,sha256=nPH0X57RYpsAkRowVpjQiHE566ThUTx7YXrsadmrmHk,564 -cryptography/hazmat/bindings/_rust/openssl/dh.pyi,sha256=Z3TC-G04-THtSdAOPLM1h2G7ml5bda1ElZUcn5wpuhk,1564 -cryptography/hazmat/bindings/_rust/openssl/dsa.pyi,sha256=qBtkgj2albt2qFcnZ9UDrhzoNhCVO7HTby5VSf1EXMI,1299 -cryptography/hazmat/bindings/_rust/openssl/ec.pyi,sha256=zJy0pRa5n-_p2dm45PxECB_-B6SVZyNKfjxFDpPqT38,1691 -cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi,sha256=VXfXd5G6hUivg399R1DYdmW3eTb0EebzDTqjRC2gaRw,532 -cryptography/hazmat/bindings/_rust/openssl/ed448.pyi,sha256=Yx49lqdnjsD7bxiDV1kcaMrDktug5evi5a6zerMiy2s,514 -cryptography/hazmat/bindings/_rust/openssl/hashes.pyi,sha256=bFe3T13UeyRInUJMD-R5ArGTGLqWDiWo2Lv2KGzUbf4,1076 -cryptography/hazmat/bindings/_rust/openssl/hmac.pyi,sha256=BXZn7NDjL3JAbYW0SQ8pg1iyC5DbQXVhUAiwsi8DFR8,702 -cryptography/hazmat/bindings/_rust/openssl/hpke.pyi,sha256=wrz8c12gBNBAItz9jorr_W4s8rFYDE1Yel1z2I-Wd2s,2877 -cryptography/hazmat/bindings/_rust/openssl/kdf.pyi,sha256=HiiLdEB9nqMsTvMwiFppQpfPz6fHUz9_gpjEB_XAOXA,6619 -cryptography/hazmat/bindings/_rust/openssl/keys.pyi,sha256=teIt8M6ZEMJrn4s3W0UnW0DZ-30Jd68WnSsKKG124l0,912 -cryptography/hazmat/bindings/_rust/openssl/mldsa.pyi,sha256=HChNsjW0C_vO9OVD4FhEZrXO3_FiEq2ZTF59hlfcEdM,1073 -cryptography/hazmat/bindings/_rust/openssl/mlkem.pyi,sha256=byoeus4-lIOlWlEiRQdCc00qCkXpOB5peBY6yo9ik8s,835 -cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi,sha256=_SW9NtQ5FDlAbdclFtWpT4lGmxKIKHpN-4j8J2BzYfQ,585 -cryptography/hazmat/bindings/_rust/openssl/rsa.pyi,sha256=2OQCNSXkxgc-3uw1xiCCloIQTV6p9_kK79Yu0rhZgPc,1364 -cryptography/hazmat/bindings/_rust/openssl/x25519.pyi,sha256=ewn4GpQyb7zPwE-ni7GtyQgMC0A1mLuqYsSyqv6nI_s,523 -cryptography/hazmat/bindings/_rust/openssl/x448.pyi,sha256=juTZTmli8jO_5Vcufg-vHvx_tCyezmSLIh_9PU3TczI,505 -cryptography/hazmat/bindings/_rust/pkcs12.pyi,sha256=vEEd5wDiZvb8ZGFaziLCaWLzAwoG_tvPUxLQw5_uOl8,1605 -cryptography/hazmat/bindings/_rust/pkcs7.pyi,sha256=txGBJijqZshEcqra6byPNbnisIdlxzOSIHP2hl9arPs,1601 -cryptography/hazmat/bindings/_rust/test_support.pyi,sha256=PPhld-WkO743iXFPebeG0LtgK0aTzGdjcIsay1Gm5GE,757 -cryptography/hazmat/bindings/_rust/x509.pyi,sha256=rmt4enscdvDQ7lBEHb2cASwN0d3TP3ymEVZcEJ-Rf3A,10152 -cryptography/hazmat/bindings/openssl/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180 -cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-312.pyc,, -cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-312.pyc,, -cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-312.pyc,, -cryptography/hazmat/bindings/openssl/_conditional.py,sha256=vfzi-xHdStAcJQjLqqOlSos94L8D_tqFtBe7Ovw-KtY,5611 -cryptography/hazmat/bindings/openssl/binding.py,sha256=GnoZLYvCzXbKf4KldUXec-oz-hdVSa_sinZnqXgdS2s,4096 -cryptography/hazmat/decrepit/__init__.py,sha256=wHCbWfaefa-fk6THSw9th9fJUsStJo7245wfFBqmduA,216 -cryptography/hazmat/decrepit/__pycache__/__init__.cpython-312.pyc,, -cryptography/hazmat/decrepit/ciphers/__init__.py,sha256=wHCbWfaefa-fk6THSw9th9fJUsStJo7245wfFBqmduA,216 -cryptography/hazmat/decrepit/ciphers/__pycache__/__init__.cpython-312.pyc,, -cryptography/hazmat/decrepit/ciphers/__pycache__/algorithms.cpython-312.pyc,, -cryptography/hazmat/decrepit/ciphers/__pycache__/modes.cpython-312.pyc,, -cryptography/hazmat/decrepit/ciphers/algorithms.py,sha256=yqHt7k5OzF_KuvO8M9vTlNLtG7EotbvShyYKIaUJqhg,3566 -cryptography/hazmat/decrepit/ciphers/modes.py,sha256=Oq_PEwCke5OLczOfr_vzAOJ6wPx-rlsvHAXPBuh5b9o,1649 -cryptography/hazmat/primitives/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180 -cryptography/hazmat/primitives/__pycache__/__init__.cpython-312.pyc,, -cryptography/hazmat/primitives/__pycache__/_asymmetric.cpython-312.pyc,, -cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-312.pyc,, -cryptography/hazmat/primitives/__pycache__/_modes.cpython-312.pyc,, -cryptography/hazmat/primitives/__pycache__/_serialization.cpython-312.pyc,, -cryptography/hazmat/primitives/__pycache__/cmac.cpython-312.pyc,, -cryptography/hazmat/primitives/__pycache__/constant_time.cpython-312.pyc,, -cryptography/hazmat/primitives/__pycache__/hashes.cpython-312.pyc,, -cryptography/hazmat/primitives/__pycache__/hmac.cpython-312.pyc,, -cryptography/hazmat/primitives/__pycache__/hpke.cpython-312.pyc,, -cryptography/hazmat/primitives/__pycache__/keywrap.cpython-312.pyc,, -cryptography/hazmat/primitives/__pycache__/padding.cpython-312.pyc,, -cryptography/hazmat/primitives/__pycache__/poly1305.cpython-312.pyc,, -cryptography/hazmat/primitives/_asymmetric.py,sha256=RhgcouUB6HTiFDBrR1LxqkMjpUxIiNvQ1r_zJjRG6qQ,532 -cryptography/hazmat/primitives/_cipheralgorithm.py,sha256=Eh3i7lwedHfi0eLSsH93PZxQKzY9I6lkK67vL4V5tOc,1522 -cryptography/hazmat/primitives/_modes.py,sha256=_EiAOD8Jb6WpFXluwkcUT3ECz_TH8xjGvbQlGkNm59Q,3075 -cryptography/hazmat/primitives/_serialization.py,sha256=hi0xJblBAZ8pmZx2lWa-lruphxvvvG3g9DNK0G8Odfs,4440 -cryptography/hazmat/primitives/asymmetric/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180 -cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-312.pyc,, -cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-312.pyc,, -cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-312.pyc,, -cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-312.pyc,, -cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-312.pyc,, -cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-312.pyc,, -cryptography/hazmat/primitives/asymmetric/__pycache__/mldsa.cpython-312.pyc,, -cryptography/hazmat/primitives/asymmetric/__pycache__/mlkem.cpython-312.pyc,, -cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-312.pyc,, -cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-312.pyc,, -cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-312.pyc,, -cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-312.pyc,, -cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-312.pyc,, -cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-312.pyc,, -cryptography/hazmat/primitives/asymmetric/dh.py,sha256=klvHVaxAFkUyaWXLytqYjBTh81Zx1ByCJNZVRcSDYX8,3912 -cryptography/hazmat/primitives/asymmetric/dsa.py,sha256=kQzTViqAI9PiELNOBco_n6MfP3N9ehIPkSduOpupt0M,4482 -cryptography/hazmat/primitives/asymmetric/ec.py,sha256=LklVCLLxbbQzqiE6HRaYTRauLMphYUw3tE6c8oBIxYQ,10183 -cryptography/hazmat/primitives/asymmetric/ed25519.py,sha256=mbffLvs-3PgCDeg1rQXVXh7GLntlVL4ATjkIEc4pt5M,2998 -cryptography/hazmat/primitives/asymmetric/ed448.py,sha256=n0dK6y-VLxuw-zvrDxuPT4598hymgX-1Ry_jq9aUQhE,4002 -cryptography/hazmat/primitives/asymmetric/mldsa.py,sha256=49DPIhoHEyfGVwL6DRc3WlJ20Rinq-ldtjsp91NpyMM,12226 -cryptography/hazmat/primitives/asymmetric/mlkem.py,sha256=wvVkeFT-4of-VcUAER2-zI_5hXT6rwTJPMCQ8gF9GTA,7901 -cryptography/hazmat/primitives/asymmetric/padding.py,sha256=vQ6l6gOg9HqcbOsvHrSiJRVLdEj9L4m4HkRGYziTyFA,2854 -cryptography/hazmat/primitives/asymmetric/rsa.py,sha256=lIE7lGe449W5URLTKCpvFGerITouKoZV9GwuTzScsSo,8492 -cryptography/hazmat/primitives/asymmetric/types.py,sha256=q3glpax4EHgNpkRSEXlhK43a07F3Dsk-rQ3bbjL9ZnM,3309 -cryptography/hazmat/primitives/asymmetric/utils.py,sha256=Qs8Re9GFPjW_tNp_73IeJEjPCf0slOIsWOxo6qymT6k,821 -cryptography/hazmat/primitives/asymmetric/x25519.py,sha256=lQcgUk-Piubj8ynFNWQeYme3tYZMgHQqkRKkIDOHLzo,3888 -cryptography/hazmat/primitives/asymmetric/x448.py,sha256=b37ig7k7poG6SJDry42j-ElCj5q4eQ0X5CFmN0Sn8z8,3913 -cryptography/hazmat/primitives/ciphers/__init__.py,sha256=eyEXmjk6_CZXaOPYDr7vAYGXr29QvzgWL2-4CSolLFs,680 -cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-312.pyc,, -cryptography/hazmat/primitives/ciphers/__pycache__/aead.cpython-312.pyc,, -cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-312.pyc,, -cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-312.pyc,, -cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-312.pyc,, -cryptography/hazmat/primitives/ciphers/aead.py,sha256=Fzlyx7w8KYQakzDp1zWgJnIr62zgZrgVh1u2h4exB54,634 -cryptography/hazmat/primitives/ciphers/algorithms.py,sha256=IGfCycYJOh1TvoI34rfw8KfJ_xmt1p_DpBht2Fghceo,3496 -cryptography/hazmat/primitives/ciphers/base.py,sha256=aBC7HHBBoixebmparVr0UlODs3VD0A7B6oz_AaRjDv8,4253 -cryptography/hazmat/primitives/ciphers/modes.py,sha256=pNI0cSLCLxr7lz7ApfUpVpFH5q_bzOpKW-QggmgQB74,6007 -cryptography/hazmat/primitives/cmac.py,sha256=sz_s6H_cYnOvx-VNWdIKhRhe3Ymp8z8J0D3CBqOX3gg,338 -cryptography/hazmat/primitives/constant_time.py,sha256=xdunWT0nf8OvKdcqUhhlFKayGp4_PgVJRU2W1wLSr_A,422 -cryptography/hazmat/primitives/hashes.py,sha256=M8BrlKB3U6DEtHvWTV5VRjpteHv1kS3Zxm_Bsk04cr8,5184 -cryptography/hazmat/primitives/hmac.py,sha256=RpB3z9z5skirCQrm7zQbtnp9pLMnAjrlTUvKqF5aDDc,423 -cryptography/hazmat/primitives/hpke.py,sha256=RsHissC5l-dTPn1p2JbcrIrAnDBrLqM5ugBFSGpmKu4,865 -cryptography/hazmat/primitives/kdf/__init__.py,sha256=v3yiYBGU272EojNXbwfYZdbbfI9cVOCCG3nXhTDda3k,1037 -cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-312.pyc,, -cryptography/hazmat/primitives/kdf/__pycache__/argon2.cpython-312.pyc,, -cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-312.pyc,, -cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-312.pyc,, -cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-312.pyc,, -cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-312.pyc,, -cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-312.pyc,, -cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-312.pyc,, -cryptography/hazmat/primitives/kdf/argon2.py,sha256=ZJx-enUlAA4o7b46C1wlzG_XAQQW0wIkFgUKkrM_wA8,632 -cryptography/hazmat/primitives/kdf/concatkdf.py,sha256=BFnOKS72txKF0yQvASr0Na7uhzvLHpUCckK5iNAC_aQ,591 -cryptography/hazmat/primitives/kdf/hkdf.py,sha256=M0lAEfRoc4kpp4-nwDj9yB-vNZukIOYEQrUlWsBNn9o,543 -cryptography/hazmat/primitives/kdf/kbkdf.py,sha256=C3w99vjFqhqzAxzFOH4zzvVoHkb5AC6Lz6AEQGV7d_g,737 -cryptography/hazmat/primitives/kdf/pbkdf2.py,sha256=Xchkk99s-Mk6b6KSCouqdk8FVyiNVOSFIenmnW3tLgQ,468 -cryptography/hazmat/primitives/kdf/scrypt.py,sha256=XyWUdUUmhuI9V6TqAPOvujCSMGv1XQdg0a21IWCmO-U,590 -cryptography/hazmat/primitives/kdf/x963kdf.py,sha256=QKjhRehuTsAstL384bKfvjuv1yfdamAHVhsBRWen2Vw,456 -cryptography/hazmat/primitives/keywrap.py,sha256=UI-0UESQxBXTKU1HrrRoUwDiFsrWif81qyXlV1e7kyY,5776 -cryptography/hazmat/primitives/padding.py,sha256=QT-U-NvV2eQGO1wVPbDiNGNSc9keRDS-ig5cQOrLz0E,1865 -cryptography/hazmat/primitives/poly1305.py,sha256=P5EPQV-RB_FJPahpg01u0Ts4S_PnAmsroxIGXbGeRRo,355 -cryptography/hazmat/primitives/serialization/__init__.py,sha256=Q7uTgDlt7n3WfsMT6jYwutC6DIg_7SEeoAm1GHZ5B5E,1705 -cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-312.pyc,, -cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-312.pyc,, -cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-312.pyc,, -cryptography/hazmat/primitives/serialization/__pycache__/pkcs7.cpython-312.pyc,, -cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-312.pyc,, -cryptography/hazmat/primitives/serialization/base.py,sha256=ikq5MJIwp_oUnjiaBco_PmQwOTYuGi-XkYUYHKy8Vo0,615 -cryptography/hazmat/primitives/serialization/pkcs12.py,sha256=mS9cFNG4afzvseoc5e1MWoY2VskfL8N8Y_OFjl67luY,5104 -cryptography/hazmat/primitives/serialization/pkcs7.py,sha256=mFM7OFuZ8cCxUGUoo4Cof6BnCHc_Ibx1AQjjfxnPlxo,13998 -cryptography/hazmat/primitives/serialization/ssh.py,sha256=HV6ZqIjqNNaNUL6M4gQyNJJtZ75EsiSZs6yxddqBrWI,53789 -cryptography/hazmat/primitives/twofactor/__init__.py,sha256=tmMZGB-g4IU1r7lIFqASU019zr0uPp_wEBYcwdDCKCA,258 -cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-312.pyc,, -cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-312.pyc,, -cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-312.pyc,, -cryptography/hazmat/primitives/twofactor/hotp.py,sha256=ivZo5BrcCGWLsqql4nZV0XXCjyGPi_iHfDFltGlOJwk,3256 -cryptography/hazmat/primitives/twofactor/totp.py,sha256=m5LPpRL00kp4zY8gTjr55Hfz9aMlPS53kHmVkSQCmdY,1652 -cryptography/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -cryptography/utils.py,sha256=wCnykfmWmp6L5zUFou715snYL9_YLLHjpj4_NHmlhwU,4281 -cryptography/x509/__init__.py,sha256=zciyadRgnCp2DNPPm6ujEKd6EX-8_zOnwtCjJbZBatg,8273 -cryptography/x509/__pycache__/__init__.cpython-312.pyc,, -cryptography/x509/__pycache__/base.cpython-312.pyc,, -cryptography/x509/__pycache__/certificate_transparency.cpython-312.pyc,, -cryptography/x509/__pycache__/extensions.cpython-312.pyc,, -cryptography/x509/__pycache__/general_name.cpython-312.pyc,, -cryptography/x509/__pycache__/name.cpython-312.pyc,, -cryptography/x509/__pycache__/ocsp.cpython-312.pyc,, -cryptography/x509/__pycache__/oid.cpython-312.pyc,, -cryptography/x509/__pycache__/verification.cpython-312.pyc,, -cryptography/x509/base.py,sha256=8322G4opJ1a2juXU14Qi2y-G1V-cQHaudo7gAFbTPlM,25998 -cryptography/x509/certificate_transparency.py,sha256=JqoOIDhlwInrYMFW6IFn77WJ0viF-PB_rlZV3vs9MYc,797 -cryptography/x509/extensions.py,sha256=0AUgutLe26SLg1KaxSeo0fG7fUBAyK2tEgJl9c_AQRM,77968 -cryptography/x509/general_name.py,sha256=sP_rV11Qlpsk4x3XXGJY_Mv0Q_s9dtjeLckHsjpLQoQ,7836 -cryptography/x509/name.py,sha256=H0Bix4uAxk5Ndkmee3Lxv3UdXbdph2XBr-nTPxHo54U,15356 -cryptography/x509/ocsp.py,sha256=Yey6NdFV1MPjop24Mj_VenjEpg3kUaMopSWOK0AbeBs,12699 -cryptography/x509/oid.py,sha256=BUzgXXGVWilkBkdKPTm9R4qElE9gAGHgdYPMZAp7PJo,931 -cryptography/x509/verification.py,sha256=gR2C2c-XZQtblZhT5T5vjSKOtCb74ef2alPVmEcwFlM,958 diff --git a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/WHEEL b/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/WHEEL deleted file mode 100644 index 9f0f94d..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: maturin (1.13.1) -Root-Is-Purelib: false -Tag: cp311-abi3-win_amd64 diff --git a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/licenses/LICENSE b/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/licenses/LICENSE deleted file mode 100644 index b11f379..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/licenses/LICENSE +++ /dev/null @@ -1,3 +0,0 @@ -This software is made available under the terms of *either* of the licenses -found in LICENSE.APACHE or LICENSE.BSD. Contributions to cryptography are made -under the terms of *both* these licenses. diff --git a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/licenses/LICENSE.APACHE b/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/licenses/LICENSE.APACHE deleted file mode 100644 index 62589ed..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/licenses/LICENSE.APACHE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/licenses/LICENSE.BSD b/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/licenses/LICENSE.BSD deleted file mode 100644 index ec1a29d..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/licenses/LICENSE.BSD +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) Individual contributors. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of PyCA Cryptography nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/sboms/cryptography-rust.cyclonedx.json b/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/sboms/cryptography-rust.cyclonedx.json deleted file mode 100644 index 799b119..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/sboms/cryptography-rust.cyclonedx.json +++ /dev/null @@ -1,1362 +0,0 @@ -{ - "bomFormat": "CycloneDX", - "specVersion": "1.5", - "version": 1, - "serialNumber": "urn:uuid:9239508a-26c8-47fb-9035-fa65510e2670", - "metadata": { - "timestamp": "2026-05-04T22:45:45.985242700Z", - "tools": [ - { - "vendor": "CycloneDX", - "name": "cargo-cyclonedx", - "version": "0.5.9" - } - ], - "authors": [ - { - "name": "The cryptography developers", - "email": "cryptography-dev@python.org" - } - ], - "component": { - "type": "library", - "bom-ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust#cryptography-rust@0.1.0", - "author": "The cryptography developers ", - "name": "cryptography-rust", - "version": "0.1.0", - "scope": "required", - "licenses": [ - { - "expression": "Apache-2.0 OR BSD-3-Clause" - } - ], - "purl": "pkg:cargo/cryptography-rust@0.1.0?download_url=file://.", - "components": [ - { - "type": "library", - "bom-ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust#cryptography-rust@0.1.0 bin-target-0", - "name": "cryptography_rust", - "version": "0.1.0", - "purl": "pkg:cargo/cryptography-rust@0.1.0?download_url=file://.#src/lib.rs" - } - ] - }, - "properties": [ - { - "name": "cdx:rustc:sbom:target:all_targets", - "value": "true" - } - ] - }, - "components": [ - { - "type": "library", - "bom-ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-cffi#0.1.0", - "author": "The cryptography developers ", - "name": "cryptography-cffi", - "version": "0.1.0", - "scope": "required", - "licenses": [ - { - "expression": "Apache-2.0 OR BSD-3-Clause" - } - ], - "purl": "pkg:cargo/cryptography-cffi@0.1.0?download_url=file://cryptography-cffi" - }, - { - "type": "library", - "bom-ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-crypto#0.1.0", - "author": "The cryptography developers ", - "name": "cryptography-crypto", - "version": "0.1.0", - "scope": "required", - "licenses": [ - { - "expression": "Apache-2.0 OR BSD-3-Clause" - } - ], - "purl": "pkg:cargo/cryptography-crypto@0.1.0?download_url=file://cryptography-crypto" - }, - { - "type": "library", - "bom-ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-keepalive#0.1.0", - "author": "The cryptography developers ", - "name": "cryptography-keepalive", - "version": "0.1.0", - "scope": "required", - "licenses": [ - { - "expression": "Apache-2.0 OR BSD-3-Clause" - } - ], - "purl": "pkg:cargo/cryptography-keepalive@0.1.0?download_url=file://cryptography-keepalive" - }, - { - "type": "library", - "bom-ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-key-parsing#0.1.0", - "author": "The cryptography developers ", - "name": "cryptography-key-parsing", - "version": "0.1.0", - "scope": "required", - "licenses": [ - { - "expression": "Apache-2.0 OR BSD-3-Clause" - } - ], - "purl": "pkg:cargo/cryptography-key-parsing@0.1.0?download_url=file://cryptography-key-parsing" - }, - { - "type": "library", - "bom-ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-openssl#0.1.0", - "author": "The cryptography developers ", - "name": "cryptography-openssl", - "version": "0.1.0", - "scope": "required", - "licenses": [ - { - "expression": "Apache-2.0 OR BSD-3-Clause" - } - ], - "purl": "pkg:cargo/cryptography-openssl@0.1.0?download_url=file://cryptography-openssl" - }, - { - "type": "library", - "bom-ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-x509#0.1.0", - "author": "The cryptography developers ", - "name": "cryptography-x509", - "version": "0.1.0", - "scope": "required", - "licenses": [ - { - "expression": "Apache-2.0 OR BSD-3-Clause" - } - ], - "purl": "pkg:cargo/cryptography-x509@0.1.0?download_url=file://cryptography-x509" - }, - { - "type": "library", - "bom-ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-x509-verification#0.1.0", - "author": "The cryptography developers ", - "name": "cryptography-x509-verification", - "version": "0.1.0", - "scope": "required", - "licenses": [ - { - "expression": "Apache-2.0 OR BSD-3-Clause" - } - ], - "purl": "pkg:cargo/cryptography-x509-verification@0.1.0?download_url=file://cryptography-x509-verification" - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#asn1@0.24.1", - "author": "Alex Gaynor ", - "name": "asn1", - "version": "0.24.1", - "description": "ASN.1 (DER) parser and writer for Rust.", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "c9795210620c0cb3f9a7ce4f882808c38e1ef7b347c90591dceae0886e031fb1" - } - ], - "licenses": [ - { - "expression": "BSD-3-Clause" - } - ], - "purl": "pkg:cargo/asn1@0.24.1", - "externalReferences": [ - { - "type": "vcs", - "url": "https://github.com/alex/rust-asn1" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#asn1_derive@0.24.1", - "author": "Alex Gaynor ", - "name": "asn1_derive", - "version": "0.24.1", - "description": "#[derive] support for asn1", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "909e307f1cc32bb8bccbd98f446e6d1bf03fa30f7b53a4337da7181ad30fa11a" - } - ], - "licenses": [ - { - "expression": "BSD-3-Clause" - } - ], - "purl": "pkg:cargo/asn1_derive@0.24.1", - "externalReferences": [ - { - "type": "vcs", - "url": "https://github.com/alex/rust-asn1" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#base64@0.22.1", - "author": "Marshall Pierce ", - "name": "base64", - "version": "0.22.1", - "description": "encodes and decodes base64 as bytes or utf8", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/base64@0.22.1", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/base64" - }, - { - "type": "vcs", - "url": "https://github.com/marshallpierce/rust-base64" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#bitflags@2.11.1", - "author": "The Rust Project Developers", - "name": "bitflags", - "version": "2.11.1", - "description": "A macro to generate structures which behave like bitflags. ", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/bitflags@2.11.1", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/bitflags" - }, - { - "type": "website", - "url": "https://github.com/bitflags/bitflags" - }, - { - "type": "vcs", - "url": "https://github.com/bitflags/bitflags" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#cc@1.2.61", - "author": "Alex Crichton ", - "name": "cc", - "version": "1.2.61", - "description": "A build-time dependency for Cargo build scripts to assist in invoking the native C compiler to compile native C code into a static archive to be linked into Rust code. ", - "scope": "excluded", - "hashes": [ - { - "alg": "SHA-256", - "content": "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/cc@1.2.61", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/cc" - }, - { - "type": "website", - "url": "https://github.com/rust-lang/cc-rs" - }, - { - "type": "vcs", - "url": "https://github.com/rust-lang/cc-rs" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", - "author": "Alex Crichton ", - "name": "cfg-if", - "version": "1.0.4", - "description": "A macro to ergonomically define an item depending on a large number of #[cfg] parameters. Structured like an if-else chain, the first matching branch is the item that gets emitted. ", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/cfg-if@1.0.4", - "externalReferences": [ - { - "type": "vcs", - "url": "https://github.com/rust-lang/cfg-if" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#find-msvc-tools@0.1.9", - "name": "find-msvc-tools", - "version": "0.1.9", - "description": "Find windows-specific tools, read MSVC versions from the registry and from COM interfaces", - "scope": "excluded", - "hashes": [ - { - "alg": "SHA-256", - "content": "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/find-msvc-tools@0.1.9", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/find-msvc-tools" - }, - { - "type": "vcs", - "url": "https://github.com/rust-lang/cc-rs" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#foreign-types-shared@0.1.1", - "author": "Steven Fackler ", - "name": "foreign-types-shared", - "version": "0.1.1", - "description": "An internal crate used by foreign-types", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/foreign-types-shared@0.1.1", - "externalReferences": [ - { - "type": "vcs", - "url": "https://github.com/sfackler/foreign-types" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#foreign-types@0.3.2", - "author": "Steven Fackler ", - "name": "foreign-types", - "version": "0.3.2", - "description": "A framework for Rust wrappers over C APIs", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/foreign-types@0.3.2", - "externalReferences": [ - { - "type": "vcs", - "url": "https://github.com/sfackler/foreign-types" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#heck@0.5.0", - "name": "heck", - "version": "0.5.0", - "description": "heck is a case conversion library.", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/heck@0.5.0", - "externalReferences": [ - { - "type": "vcs", - "url": "https://github.com/withoutboats/heck" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.18", - "author": "David Tolnay ", - "name": "itoa", - "version": "1.0.18", - "description": "Fast integer primitive to string conversion", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/itoa@1.0.18", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/itoa" - }, - { - "type": "vcs", - "url": "https://github.com/dtolnay/itoa" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.186", - "author": "The Rust Project Developers", - "name": "libc", - "version": "0.2.186", - "description": "Raw FFI bindings to platform libraries like libc.", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/libc@0.2.186", - "externalReferences": [ - { - "type": "vcs", - "url": "https://github.com/rust-lang/libc" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.4", - "author": "Aleksey Kladov ", - "name": "once_cell", - "version": "1.21.4", - "description": "Single assignment cells and lazy values.", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/once_cell@1.21.4", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/once_cell" - }, - { - "type": "vcs", - "url": "https://github.com/matklad/once_cell" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#openssl-macros@0.1.1", - "name": "openssl-macros", - "version": "0.1.1", - "description": "Internal macros used by the openssl crate.", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/openssl-macros@0.1.1" - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#openssl-sys@0.9.115", - "author": "Alex Crichton , Steven Fackler ", - "name": "openssl-sys", - "version": "0.9.115", - "description": "FFI bindings to OpenSSL", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "158fe5b292746440aa6e7a7e690e55aeb72d41505e2804c23c6973ad0e9c9781" - } - ], - "licenses": [ - { - "expression": "MIT" - } - ], - "purl": "pkg:cargo/openssl-sys@0.9.115", - "externalReferences": [ - { - "type": "other", - "url": "openssl" - }, - { - "type": "vcs", - "url": "https://github.com/rust-openssl/rust-openssl" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#openssl@0.10.79", - "author": "Steven Fackler ", - "name": "openssl", - "version": "0.10.79", - "description": "OpenSSL bindings", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "bf0b434746ee2832f4f0baf10137e1cabb18cbe6912c69e2e33263c45250f542" - } - ], - "licenses": [ - { - "expression": "Apache-2.0" - } - ], - "purl": "pkg:cargo/openssl@0.10.79", - "externalReferences": [ - { - "type": "vcs", - "url": "https://github.com/rust-openssl/rust-openssl" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#pem@3.0.6", - "author": "Jonathan Creekmore ", - "name": "pem", - "version": "3.0.6", - "description": "Parse and encode PEM-encoded data.", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" - } - ], - "licenses": [ - { - "expression": "MIT" - } - ], - "purl": "pkg:cargo/pem@3.0.6", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/pem/" - }, - { - "type": "website", - "url": "https://github.com/jcreekmore/pem-rs.git" - }, - { - "type": "vcs", - "url": "https://github.com/jcreekmore/pem-rs.git" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#pkg-config@0.3.33", - "author": "Alex Crichton ", - "name": "pkg-config", - "version": "0.3.33", - "description": "A library to run the pkg-config system tool at build time in order to be used in Cargo build scripts. ", - "scope": "excluded", - "hashes": [ - { - "alg": "SHA-256", - "content": "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/pkg-config@0.3.33", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/pkg-config" - }, - { - "type": "vcs", - "url": "https://github.com/rust-lang/pkg-config-rs" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#portable-atomic@1.13.1", - "name": "portable-atomic", - "version": "1.13.1", - "description": "Portable atomic types including support for 128-bit atomics, atomic float, etc. ", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" - } - ], - "licenses": [ - { - "expression": "Apache-2.0 OR MIT" - } - ], - "purl": "pkg:cargo/portable-atomic@1.13.1", - "externalReferences": [ - { - "type": "vcs", - "url": "https://github.com/taiki-e/portable-atomic" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", - "author": "David Tolnay , Alex Crichton ", - "name": "proc-macro2", - "version": "1.0.106", - "description": "A substitute implementation of the compiler's `proc_macro` API to decouple token-based libraries from the procedural macro use case.", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/proc-macro2@1.0.106", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/proc-macro2" - }, - { - "type": "vcs", - "url": "https://github.com/dtolnay/proc-macro2" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-build-config@0.28.3", - "author": "PyO3 Project and Contributors ", - "name": "pyo3-build-config", - "version": "0.28.3", - "description": "Build configuration for the PyO3 ecosystem", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "e368e7ddfdeb98c9bca7f8383be1648fd84ab466bf2bc015e94008db6d35611e" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/pyo3-build-config@0.28.3", - "externalReferences": [ - { - "type": "website", - "url": "https://github.com/pyo3/pyo3" - }, - { - "type": "vcs", - "url": "https://github.com/pyo3/pyo3" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-ffi@0.28.3", - "author": "PyO3 Project and Contributors ", - "name": "pyo3-ffi", - "version": "0.28.3", - "description": "Python-API bindings for the PyO3 ecosystem", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "7f29e10af80b1f7ccaf7f69eace800a03ecd13e883acfacc1e5d0988605f651e" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/pyo3-ffi@0.28.3", - "externalReferences": [ - { - "type": "website", - "url": "https://github.com/pyo3/pyo3" - }, - { - "type": "other", - "url": "python" - }, - { - "type": "vcs", - "url": "https://github.com/pyo3/pyo3" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-macros-backend@0.28.3", - "author": "PyO3 Project and Contributors ", - "name": "pyo3-macros-backend", - "version": "0.28.3", - "description": "Code generation for PyO3 package", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "c4cdc218d835738f81c2338f822078af45b4afdf8b2e33cbb5916f108b813acb" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/pyo3-macros-backend@0.28.3", - "externalReferences": [ - { - "type": "website", - "url": "https://github.com/pyo3/pyo3" - }, - { - "type": "vcs", - "url": "https://github.com/pyo3/pyo3" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-macros@0.28.3", - "author": "PyO3 Project and Contributors ", - "name": "pyo3-macros", - "version": "0.28.3", - "description": "Proc macros for PyO3 package", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "df6e520eff47c45997d2fc7dd8214b25dd1310918bbb2642156ef66a67f29813" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/pyo3-macros@0.28.3", - "externalReferences": [ - { - "type": "website", - "url": "https://github.com/pyo3/pyo3" - }, - { - "type": "vcs", - "url": "https://github.com/pyo3/pyo3" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3@0.28.3", - "author": "PyO3 Project and Contributors ", - "name": "pyo3", - "version": "0.28.3", - "description": "Bindings to Python interpreter", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "91fd8e38a3b50ed1167fb981cd6fd60147e091784c427b8f7183a7ee32c31c12" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/pyo3@0.28.3", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/crate/pyo3/" - }, - { - "type": "website", - "url": "https://github.com/pyo3/pyo3" - }, - { - "type": "vcs", - "url": "https://github.com/pyo3/pyo3" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45", - "author": "David Tolnay ", - "name": "quote", - "version": "1.0.45", - "description": "Quasi-quoting macro quote!(...)", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/quote@1.0.45", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/quote/" - }, - { - "type": "vcs", - "url": "https://github.com/dtolnay/quote" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#self_cell@1.2.2", - "author": "Lukas Bergdoll ", - "name": "self_cell", - "version": "1.2.2", - "description": "Safe-to-use proc-macro-free self-referential structs in stable Rust.", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" - } - ], - "licenses": [ - { - "expression": "Apache-2.0 OR GPL-2.0-only" - } - ], - "purl": "pkg:cargo/self_cell@1.2.2", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/self_cell" - }, - { - "type": "vcs", - "url": "https://github.com/Voultapher/self_cell" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#shlex@1.3.0", - "author": "comex , Fenhl , Adrian Taylor , Alex Touchet , Daniel Parks , Garrett Berg ", - "name": "shlex", - "version": "1.3.0", - "description": "Split a string into shell words, like Python's shlex.", - "scope": "excluded", - "hashes": [ - { - "alg": "SHA-256", - "content": "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/shlex@1.3.0", - "externalReferences": [ - { - "type": "vcs", - "url": "https://github.com/comex/rust-shlex" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117", - "author": "David Tolnay ", - "name": "syn", - "version": "2.0.117", - "description": "Parser for Rust source code", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/syn@2.0.117", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/syn" - }, - { - "type": "vcs", - "url": "https://github.com/dtolnay/syn" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#target-lexicon@0.13.5", - "author": "Dan Gohman ", - "name": "target-lexicon", - "version": "0.13.5", - "description": "LLVM target triple types", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" - } - ], - "licenses": [ - { - "expression": "Apache-2.0 WITH LLVM-exception" - } - ], - "purl": "pkg:cargo/target-lexicon@0.13.5", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/target-lexicon/" - }, - { - "type": "vcs", - "url": "https://github.com/bytecodealliance/target-lexicon" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24", - "author": "David Tolnay ", - "name": "unicode-ident", - "version": "1.0.24", - "description": "Determine whether characters have the XID_Start or XID_Continue properties according to Unicode Standard Annex #31", - "scope": "required", - "hashes": [ - { - "alg": "SHA-256", - "content": "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" - } - ], - "licenses": [ - { - "expression": "(MIT OR Apache-2.0) AND Unicode-3.0" - } - ], - "purl": "pkg:cargo/unicode-ident@1.0.24", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/unicode-ident" - }, - { - "type": "vcs", - "url": "https://github.com/dtolnay/unicode-ident" - } - ] - }, - { - "type": "library", - "bom-ref": "registry+https://github.com/rust-lang/crates.io-index#vcpkg@0.2.15", - "author": "Jim McGrath ", - "name": "vcpkg", - "version": "0.2.15", - "description": "A library to find native dependencies in a vcpkg tree at build time in order to be used in Cargo build scripts. ", - "scope": "excluded", - "hashes": [ - { - "alg": "SHA-256", - "content": "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - } - ], - "licenses": [ - { - "expression": "MIT OR Apache-2.0" - } - ], - "purl": "pkg:cargo/vcpkg@0.2.15", - "externalReferences": [ - { - "type": "documentation", - "url": "https://docs.rs/vcpkg" - }, - { - "type": "vcs", - "url": "https://github.com/mcgoo/vcpkg-rs" - } - ] - } - ], - "dependencies": [ - { - "ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust#cryptography-rust@0.1.0", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#asn1@0.24.1", - "registry+https://github.com/rust-lang/crates.io-index#base64@0.22.1", - "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", - "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-cffi#0.1.0", - "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-crypto#0.1.0", - "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-keepalive#0.1.0", - "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-key-parsing#0.1.0", - "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-openssl#0.1.0", - "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-x509#0.1.0", - "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-x509-verification#0.1.0", - "registry+https://github.com/rust-lang/crates.io-index#foreign-types-shared@0.1.1", - "registry+https://github.com/rust-lang/crates.io-index#openssl@0.10.79", - "registry+https://github.com/rust-lang/crates.io-index#openssl-sys@0.9.115", - "registry+https://github.com/rust-lang/crates.io-index#pem@3.0.6", - "registry+https://github.com/rust-lang/crates.io-index#pyo3@0.28.3", - "registry+https://github.com/rust-lang/crates.io-index#pyo3-build-config@0.28.3", - "registry+https://github.com/rust-lang/crates.io-index#self_cell@1.2.2" - ] - }, - { - "ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-cffi#0.1.0", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#cc@1.2.61", - "registry+https://github.com/rust-lang/crates.io-index#openssl-sys@0.9.115", - "registry+https://github.com/rust-lang/crates.io-index#pyo3@0.28.3" - ] - }, - { - "ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-crypto#0.1.0", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#openssl@0.10.79" - ] - }, - { - "ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-keepalive#0.1.0", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#pyo3@0.28.3" - ] - }, - { - "ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-key-parsing#0.1.0", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#asn1@0.24.1", - "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", - "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-crypto#0.1.0", - "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-openssl#0.1.0", - "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-x509#0.1.0", - "registry+https://github.com/rust-lang/crates.io-index#openssl@0.10.79", - "registry+https://github.com/rust-lang/crates.io-index#openssl-sys@0.9.115", - "registry+https://github.com/rust-lang/crates.io-index#pem@3.0.6" - ] - }, - { - "ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-openssl#0.1.0", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", - "registry+https://github.com/rust-lang/crates.io-index#foreign-types@0.3.2", - "registry+https://github.com/rust-lang/crates.io-index#foreign-types-shared@0.1.1", - "registry+https://github.com/rust-lang/crates.io-index#openssl@0.10.79", - "registry+https://github.com/rust-lang/crates.io-index#openssl-sys@0.9.115" - ] - }, - { - "ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-x509#0.1.0", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#asn1@0.24.1" - ] - }, - { - "ref": "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-x509-verification#0.1.0", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#asn1@0.24.1", - "path+file:///D:/a/cryptography/cryptography/wheelhouse/.tmpsrzLM5/cryptography-48.0.0/src/rust/cryptography-x509#0.1.0" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#asn1@0.24.1", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#asn1_derive@0.24.1", - "registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.18" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#asn1_derive@0.24.1", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", - "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45", - "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#base64@0.22.1" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#bitflags@2.11.1" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#cc@1.2.61", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#find-msvc-tools@0.1.9", - "registry+https://github.com/rust-lang/crates.io-index#shlex@1.3.0" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#find-msvc-tools@0.1.9" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#foreign-types-shared@0.1.1" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#foreign-types@0.3.2", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#foreign-types-shared@0.1.1" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#heck@0.5.0" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.18" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.186" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.4" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#openssl-macros@0.1.1", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", - "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45", - "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#openssl-sys@0.9.115", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#cc@1.2.61", - "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.186", - "registry+https://github.com/rust-lang/crates.io-index#pkg-config@0.3.33", - "registry+https://github.com/rust-lang/crates.io-index#vcpkg@0.2.15" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#openssl@0.10.79", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#bitflags@2.11.1", - "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", - "registry+https://github.com/rust-lang/crates.io-index#foreign-types@0.3.2", - "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.186", - "registry+https://github.com/rust-lang/crates.io-index#openssl-macros@0.1.1", - "registry+https://github.com/rust-lang/crates.io-index#openssl-sys@0.9.115" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#pem@3.0.6", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#base64@0.22.1" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#pkg-config@0.3.33" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#portable-atomic@1.13.1" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-build-config@0.28.3", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#target-lexicon@0.13.5" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-ffi@0.28.3", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.186", - "registry+https://github.com/rust-lang/crates.io-index#pyo3-build-config@0.28.3" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-macros-backend@0.28.3", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#heck@0.5.0", - "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", - "registry+https://github.com/rust-lang/crates.io-index#pyo3-build-config@0.28.3", - "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45", - "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3-macros@0.28.3", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", - "registry+https://github.com/rust-lang/crates.io-index#pyo3-macros-backend@0.28.3", - "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45", - "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#pyo3@0.28.3", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.186", - "registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.4", - "registry+https://github.com/rust-lang/crates.io-index#portable-atomic@1.13.1", - "registry+https://github.com/rust-lang/crates.io-index#pyo3-build-config@0.28.3", - "registry+https://github.com/rust-lang/crates.io-index#pyo3-ffi@0.28.3", - "registry+https://github.com/rust-lang/crates.io-index#pyo3-macros@0.28.3" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#self_cell@1.2.2" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#shlex@1.3.0" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117", - "dependsOn": [ - "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", - "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45", - "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24" - ] - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#target-lexicon@0.13.5" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24" - }, - { - "ref": "registry+https://github.com/rust-lang/crates.io-index#vcpkg@0.2.15" - } - ] -} \ No newline at end of file diff --git a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/sboms/sbom.json b/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/sboms/sbom.json deleted file mode 100644 index f76bfce..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography-48.0.0.dist-info/sboms/sbom.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "bomFormat": "CycloneDX", - "specVersion": "1.5", - "version": 1, - "serialNumber": "urn:uuid:d28eacb5-bc17-4ccb-953b-1bf4fa4d4845", - "metadata": { - "timestamp": "2026-05-01T00:40:11Z" - }, - "components": [ - { - "type": "library", - "name": "openssl", - "version": "4.0.0", - "purl": "pkg:generic/openssl@4.0.0?download_url=https://github.com/openssl/openssl/releases/download/openssl-4.0.0/openssl-4.0.0.tar.gz", - "hashes": [ - { - "alg": "SHA-256", - "content": "c32cf49a959c4f345f9606982dd36e7d28f7c58b19c2e25d75624d2b3d2f79ac" - } - ], - "externalReferences": [ - { - "type": "distribution", - "url": "https://github.com/openssl/openssl/releases/download/openssl-4.0.0/openssl-4.0.0.tar.gz" - } - ], - "properties": [ - { - "name": "build:operating-system", - "value": "windows" - }, - { - "name": "build:architecture", - "value": "win64" - }, - { - "name": "build:flags", - "value": "no-zlib no-shared no-module no-comp no-apps no-docs no-sm2-precomp no-atexit" - } - ] - } - ] -} diff --git a/notification-service/venv/Lib/site-packages/cryptography/__about__.py b/notification-service/venv/Lib/site-packages/cryptography/__about__.py deleted file mode 100644 index c81901c..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/__about__.py +++ /dev/null @@ -1,17 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -__all__ = [ - "__author__", - "__copyright__", - "__version__", -] - -__version__ = "48.0.0" - - -__author__ = "The Python Cryptographic Authority and individual contributors" -__copyright__ = f"Copyright 2013-2026 {__author__}" diff --git a/notification-service/venv/Lib/site-packages/cryptography/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/__init__.py deleted file mode 100644 index d374f75..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.__about__ import __author__, __copyright__, __version__ - -__all__ = [ - "__author__", - "__copyright__", - "__version__", -] diff --git a/notification-service/venv/Lib/site-packages/cryptography/__pycache__/__about__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/__pycache__/__about__.cpython-312.pyc deleted file mode 100644 index c47fa91..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/__pycache__/__about__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 503a4b3..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/__pycache__/exceptions.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/__pycache__/exceptions.cpython-312.pyc deleted file mode 100644 index 77e83dc..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/__pycache__/exceptions.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/__pycache__/fernet.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/__pycache__/fernet.cpython-312.pyc deleted file mode 100644 index 0f5befc..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/__pycache__/fernet.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/__pycache__/utils.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/__pycache__/utils.cpython-312.pyc deleted file mode 100644 index 2e4b9fa..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/__pycache__/utils.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/exceptions.py b/notification-service/venv/Lib/site-packages/cryptography/exceptions.py deleted file mode 100644 index fe125ea..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/exceptions.py +++ /dev/null @@ -1,52 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import typing - -from cryptography.hazmat.bindings._rust import exceptions as rust_exceptions - -if typing.TYPE_CHECKING: - from cryptography.hazmat.bindings._rust import openssl as rust_openssl - -_Reasons = rust_exceptions._Reasons - - -class UnsupportedAlgorithm(Exception): - def __init__(self, message: str, reason: _Reasons | None = None) -> None: - super().__init__(message) - self._reason = reason - - -class AlreadyFinalized(Exception): - pass - - -class AlreadyUpdated(Exception): - pass - - -class NotYetFinalized(Exception): - pass - - -class InvalidTag(Exception): - pass - - -class InvalidSignature(Exception): - pass - - -class InternalError(Exception): - def __init__( - self, msg: str, err_code: list[rust_openssl.OpenSSLError] - ) -> None: - super().__init__(msg) - self.err_code = err_code - - -class InvalidKey(Exception): - pass diff --git a/notification-service/venv/Lib/site-packages/cryptography/fernet.py b/notification-service/venv/Lib/site-packages/cryptography/fernet.py deleted file mode 100644 index c6744ae..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/fernet.py +++ /dev/null @@ -1,224 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import base64 -import binascii -import os -import time -import typing -from collections.abc import Iterable - -from cryptography import utils -from cryptography.exceptions import InvalidSignature -from cryptography.hazmat.primitives import hashes, padding -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes -from cryptography.hazmat.primitives.hmac import HMAC - - -class InvalidToken(Exception): - pass - - -_MAX_CLOCK_SKEW = 60 - - -class Fernet: - def __init__( - self, - key: bytes | str, - backend: typing.Any = None, - ) -> None: - try: - key = base64.urlsafe_b64decode(key) - except binascii.Error as exc: - raise ValueError( - "Fernet key must be 32 url-safe base64-encoded bytes." - ) from exc - if len(key) != 32: - raise ValueError( - "Fernet key must be 32 url-safe base64-encoded bytes." - ) - - self._signing_key = key[:16] - self._encryption_key = key[16:] - - @classmethod - def generate_key(cls) -> bytes: - return base64.urlsafe_b64encode(os.urandom(32)) - - def encrypt(self, data: bytes) -> bytes: - return self.encrypt_at_time(data, int(time.time())) - - def encrypt_at_time(self, data: bytes, current_time: int) -> bytes: - iv = os.urandom(16) - return self._encrypt_from_parts(data, current_time, iv) - - def _encrypt_from_parts( - self, data: bytes, current_time: int, iv: bytes - ) -> bytes: - utils._check_bytes("data", data) - - padder = padding.PKCS7(algorithms.AES.block_size).padder() - padded_data = padder.update(data) + padder.finalize() - encryptor = Cipher( - algorithms.AES(self._encryption_key), - modes.CBC(iv), - ).encryptor() - ciphertext = encryptor.update(padded_data) + encryptor.finalize() - - basic_parts = ( - b"\x80" - + current_time.to_bytes(length=8, byteorder="big") - + iv - + ciphertext - ) - - h = HMAC(self._signing_key, hashes.SHA256()) - h.update(basic_parts) - hmac = h.finalize() - return base64.urlsafe_b64encode(basic_parts + hmac) - - def decrypt(self, token: bytes | str, ttl: int | None = None) -> bytes: - timestamp, data = Fernet._get_unverified_token_data(token) - if ttl is None: - time_info = None - else: - time_info = (ttl, int(time.time())) - return self._decrypt_data(data, timestamp, time_info) - - def decrypt_at_time( - self, token: bytes | str, ttl: int, current_time: int - ) -> bytes: - if ttl is None: - raise ValueError( - "decrypt_at_time() can only be used with a non-None ttl" - ) - timestamp, data = Fernet._get_unverified_token_data(token) - return self._decrypt_data(data, timestamp, (ttl, current_time)) - - def extract_timestamp(self, token: bytes | str) -> int: - timestamp, data = Fernet._get_unverified_token_data(token) - # Verify the token was not tampered with. - self._verify_signature(data) - return timestamp - - @staticmethod - def _get_unverified_token_data(token: bytes | str) -> tuple[int, bytes]: - if not isinstance(token, (str, bytes)): - raise TypeError("token must be bytes or str") - - try: - data = base64.urlsafe_b64decode(token) - except (TypeError, binascii.Error): - raise InvalidToken - - if not data or data[0] != 0x80: - raise InvalidToken - - if len(data) < 9: - raise InvalidToken - - timestamp = int.from_bytes(data[1:9], byteorder="big") - return timestamp, data - - def _verify_signature(self, data: bytes) -> None: - h = HMAC(self._signing_key, hashes.SHA256()) - h.update(data[:-32]) - try: - h.verify(data[-32:]) - except InvalidSignature: - raise InvalidToken - - def _decrypt_data( - self, - data: bytes, - timestamp: int, - time_info: tuple[int, int] | None, - ) -> bytes: - if time_info is not None: - ttl, current_time = time_info - if timestamp + ttl < current_time: - raise InvalidToken - - if current_time + _MAX_CLOCK_SKEW < timestamp: - raise InvalidToken - - self._verify_signature(data) - - iv = data[9:25] - ciphertext = data[25:-32] - decryptor = Cipher( - algorithms.AES(self._encryption_key), modes.CBC(iv) - ).decryptor() - plaintext_padded = decryptor.update(ciphertext) - try: - plaintext_padded += decryptor.finalize() - except ValueError: - raise InvalidToken - unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() - - unpadded = unpadder.update(plaintext_padded) - try: - unpadded += unpadder.finalize() - except ValueError: - raise InvalidToken - return unpadded - - -class MultiFernet: - def __init__(self, fernets: Iterable[Fernet]): - fernets = list(fernets) - if not fernets: - raise ValueError( - "MultiFernet requires at least one Fernet instance" - ) - self._fernets = fernets - - def encrypt(self, msg: bytes) -> bytes: - return self.encrypt_at_time(msg, int(time.time())) - - def encrypt_at_time(self, msg: bytes, current_time: int) -> bytes: - return self._fernets[0].encrypt_at_time(msg, current_time) - - def rotate(self, msg: bytes | str) -> bytes: - timestamp, data = Fernet._get_unverified_token_data(msg) - for f in self._fernets: - try: - p = f._decrypt_data(data, timestamp, None) - break - except InvalidToken: - pass - else: - raise InvalidToken - - iv = os.urandom(16) - return self._fernets[0]._encrypt_from_parts(p, timestamp, iv) - - def decrypt(self, msg: bytes | str, ttl: int | None = None) -> bytes: - for f in self._fernets: - try: - return f.decrypt(msg, ttl) - except InvalidToken: - pass - raise InvalidToken - - def decrypt_at_time( - self, msg: bytes | str, ttl: int, current_time: int - ) -> bytes: - for f in self._fernets: - try: - return f.decrypt_at_time(msg, ttl, current_time) - except InvalidToken: - pass - raise InvalidToken - - def extract_timestamp(self, msg: bytes | str) -> int: - for f in self._fernets: - try: - return f.extract_timestamp(msg) - except InvalidToken: - pass - raise InvalidToken diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/__init__.py deleted file mode 100644 index b9f1187..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -""" -Hazardous Materials - -This is a "Hazardous Materials" module. You should ONLY use it if you're -100% absolutely sure that you know what you're doing because this module -is full of land mines, dragons, and dinosaurs with laser guns. -""" diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index f0e2118..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/__pycache__/_oid.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/__pycache__/_oid.cpython-312.pyc deleted file mode 100644 index 1df4aba..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/__pycache__/_oid.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/_oid.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/_oid.py deleted file mode 100644 index 4bf138d..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/_oid.py +++ /dev/null @@ -1,356 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.bindings._rust import ( - ObjectIdentifier as ObjectIdentifier, -) -from cryptography.hazmat.primitives import hashes - - -class ExtensionOID: - SUBJECT_DIRECTORY_ATTRIBUTES = ObjectIdentifier("2.5.29.9") - SUBJECT_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.14") - KEY_USAGE = ObjectIdentifier("2.5.29.15") - PRIVATE_KEY_USAGE_PERIOD = ObjectIdentifier("2.5.29.16") - SUBJECT_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.17") - ISSUER_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.18") - BASIC_CONSTRAINTS = ObjectIdentifier("2.5.29.19") - NAME_CONSTRAINTS = ObjectIdentifier("2.5.29.30") - CRL_DISTRIBUTION_POINTS = ObjectIdentifier("2.5.29.31") - CERTIFICATE_POLICIES = ObjectIdentifier("2.5.29.32") - POLICY_MAPPINGS = ObjectIdentifier("2.5.29.33") - AUTHORITY_KEY_IDENTIFIER = ObjectIdentifier("2.5.29.35") - POLICY_CONSTRAINTS = ObjectIdentifier("2.5.29.36") - EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37") - FRESHEST_CRL = ObjectIdentifier("2.5.29.46") - INHIBIT_ANY_POLICY = ObjectIdentifier("2.5.29.54") - ISSUING_DISTRIBUTION_POINT = ObjectIdentifier("2.5.29.28") - AUTHORITY_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.1") - SUBJECT_INFORMATION_ACCESS = ObjectIdentifier("1.3.6.1.5.5.7.1.11") - OCSP_NO_CHECK = ObjectIdentifier("1.3.6.1.5.5.7.48.1.5") - TLS_FEATURE = ObjectIdentifier("1.3.6.1.5.5.7.1.24") - CRL_NUMBER = ObjectIdentifier("2.5.29.20") - DELTA_CRL_INDICATOR = ObjectIdentifier("2.5.29.27") - PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS = ObjectIdentifier( - "1.3.6.1.4.1.11129.2.4.2" - ) - PRECERT_POISON = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3") - SIGNED_CERTIFICATE_TIMESTAMPS = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.5") - MS_CERTIFICATE_TEMPLATE = ObjectIdentifier("1.3.6.1.4.1.311.21.7") - ADMISSIONS = ObjectIdentifier("1.3.36.8.3.3") - - -class OCSPExtensionOID: - NONCE = ObjectIdentifier("1.3.6.1.5.5.7.48.1.2") - ACCEPTABLE_RESPONSES = ObjectIdentifier("1.3.6.1.5.5.7.48.1.4") - - -class CRLEntryExtensionOID: - CERTIFICATE_ISSUER = ObjectIdentifier("2.5.29.29") - CRL_REASON = ObjectIdentifier("2.5.29.21") - INVALIDITY_DATE = ObjectIdentifier("2.5.29.24") - - -class NameOID: - COMMON_NAME = ObjectIdentifier("2.5.4.3") - COUNTRY_NAME = ObjectIdentifier("2.5.4.6") - LOCALITY_NAME = ObjectIdentifier("2.5.4.7") - STATE_OR_PROVINCE_NAME = ObjectIdentifier("2.5.4.8") - STREET_ADDRESS = ObjectIdentifier("2.5.4.9") - ORGANIZATION_IDENTIFIER = ObjectIdentifier("2.5.4.97") - ORGANIZATION_NAME = ObjectIdentifier("2.5.4.10") - ORGANIZATIONAL_UNIT_NAME = ObjectIdentifier("2.5.4.11") - SERIAL_NUMBER = ObjectIdentifier("2.5.4.5") - SURNAME = ObjectIdentifier("2.5.4.4") - GIVEN_NAME = ObjectIdentifier("2.5.4.42") - TITLE = ObjectIdentifier("2.5.4.12") - INITIALS = ObjectIdentifier("2.5.4.43") - GENERATION_QUALIFIER = ObjectIdentifier("2.5.4.44") - X500_UNIQUE_IDENTIFIER = ObjectIdentifier("2.5.4.45") - DN_QUALIFIER = ObjectIdentifier("2.5.4.46") - PSEUDONYM = ObjectIdentifier("2.5.4.65") - USER_ID = ObjectIdentifier("0.9.2342.19200300.100.1.1") - DOMAIN_COMPONENT = ObjectIdentifier("0.9.2342.19200300.100.1.25") - EMAIL_ADDRESS = ObjectIdentifier("1.2.840.113549.1.9.1") - JURISDICTION_COUNTRY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.3") - JURISDICTION_LOCALITY_NAME = ObjectIdentifier("1.3.6.1.4.1.311.60.2.1.1") - JURISDICTION_STATE_OR_PROVINCE_NAME = ObjectIdentifier( - "1.3.6.1.4.1.311.60.2.1.2" - ) - BUSINESS_CATEGORY = ObjectIdentifier("2.5.4.15") - POSTAL_ADDRESS = ObjectIdentifier("2.5.4.16") - POSTAL_CODE = ObjectIdentifier("2.5.4.17") - INN = ObjectIdentifier("1.2.643.3.131.1.1") - OGRN = ObjectIdentifier("1.2.643.100.1") - SNILS = ObjectIdentifier("1.2.643.100.3") - UNSTRUCTURED_NAME = ObjectIdentifier("1.2.840.113549.1.9.2") - - -class SignatureAlgorithmOID: - RSA_WITH_MD5 = ObjectIdentifier("1.2.840.113549.1.1.4") - RSA_WITH_SHA1 = ObjectIdentifier("1.2.840.113549.1.1.5") - # This is an alternate OID for RSA with SHA1 that is occasionally seen - _RSA_WITH_SHA1 = ObjectIdentifier("1.3.14.3.2.29") - RSA_WITH_SHA224 = ObjectIdentifier("1.2.840.113549.1.1.14") - RSA_WITH_SHA256 = ObjectIdentifier("1.2.840.113549.1.1.11") - RSA_WITH_SHA384 = ObjectIdentifier("1.2.840.113549.1.1.12") - RSA_WITH_SHA512 = ObjectIdentifier("1.2.840.113549.1.1.13") - RSA_WITH_SHA3_224 = ObjectIdentifier("2.16.840.1.101.3.4.3.13") - RSA_WITH_SHA3_256 = ObjectIdentifier("2.16.840.1.101.3.4.3.14") - RSA_WITH_SHA3_384 = ObjectIdentifier("2.16.840.1.101.3.4.3.15") - RSA_WITH_SHA3_512 = ObjectIdentifier("2.16.840.1.101.3.4.3.16") - RSASSA_PSS = ObjectIdentifier("1.2.840.113549.1.1.10") - ECDSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10045.4.1") - ECDSA_WITH_SHA224 = ObjectIdentifier("1.2.840.10045.4.3.1") - ECDSA_WITH_SHA256 = ObjectIdentifier("1.2.840.10045.4.3.2") - ECDSA_WITH_SHA384 = ObjectIdentifier("1.2.840.10045.4.3.3") - ECDSA_WITH_SHA512 = ObjectIdentifier("1.2.840.10045.4.3.4") - ECDSA_WITH_SHA3_224 = ObjectIdentifier("2.16.840.1.101.3.4.3.9") - ECDSA_WITH_SHA3_256 = ObjectIdentifier("2.16.840.1.101.3.4.3.10") - ECDSA_WITH_SHA3_384 = ObjectIdentifier("2.16.840.1.101.3.4.3.11") - ECDSA_WITH_SHA3_512 = ObjectIdentifier("2.16.840.1.101.3.4.3.12") - DSA_WITH_SHA1 = ObjectIdentifier("1.2.840.10040.4.3") - DSA_WITH_SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.3.1") - DSA_WITH_SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.3.2") - DSA_WITH_SHA384 = ObjectIdentifier("2.16.840.1.101.3.4.3.3") - DSA_WITH_SHA512 = ObjectIdentifier("2.16.840.1.101.3.4.3.4") - ED25519 = ObjectIdentifier("1.3.101.112") - ED448 = ObjectIdentifier("1.3.101.113") - GOSTR3411_94_WITH_3410_2001 = ObjectIdentifier("1.2.643.2.2.3") - GOSTR3410_2012_WITH_3411_2012_256 = ObjectIdentifier("1.2.643.7.1.1.3.2") - GOSTR3410_2012_WITH_3411_2012_512 = ObjectIdentifier("1.2.643.7.1.1.3.3") - - -_SIG_OIDS_TO_HASH: dict[ObjectIdentifier, hashes.HashAlgorithm | None] = { - SignatureAlgorithmOID.RSA_WITH_MD5: hashes.MD5(), - SignatureAlgorithmOID.RSA_WITH_SHA1: hashes.SHA1(), - SignatureAlgorithmOID._RSA_WITH_SHA1: hashes.SHA1(), - SignatureAlgorithmOID.RSA_WITH_SHA224: hashes.SHA224(), - SignatureAlgorithmOID.RSA_WITH_SHA256: hashes.SHA256(), - SignatureAlgorithmOID.RSA_WITH_SHA384: hashes.SHA384(), - SignatureAlgorithmOID.RSA_WITH_SHA512: hashes.SHA512(), - SignatureAlgorithmOID.RSA_WITH_SHA3_224: hashes.SHA3_224(), - SignatureAlgorithmOID.RSA_WITH_SHA3_256: hashes.SHA3_256(), - SignatureAlgorithmOID.RSA_WITH_SHA3_384: hashes.SHA3_384(), - SignatureAlgorithmOID.RSA_WITH_SHA3_512: hashes.SHA3_512(), - SignatureAlgorithmOID.ECDSA_WITH_SHA1: hashes.SHA1(), - SignatureAlgorithmOID.ECDSA_WITH_SHA224: hashes.SHA224(), - SignatureAlgorithmOID.ECDSA_WITH_SHA256: hashes.SHA256(), - SignatureAlgorithmOID.ECDSA_WITH_SHA384: hashes.SHA384(), - SignatureAlgorithmOID.ECDSA_WITH_SHA512: hashes.SHA512(), - SignatureAlgorithmOID.ECDSA_WITH_SHA3_224: hashes.SHA3_224(), - SignatureAlgorithmOID.ECDSA_WITH_SHA3_256: hashes.SHA3_256(), - SignatureAlgorithmOID.ECDSA_WITH_SHA3_384: hashes.SHA3_384(), - SignatureAlgorithmOID.ECDSA_WITH_SHA3_512: hashes.SHA3_512(), - SignatureAlgorithmOID.DSA_WITH_SHA1: hashes.SHA1(), - SignatureAlgorithmOID.DSA_WITH_SHA224: hashes.SHA224(), - SignatureAlgorithmOID.DSA_WITH_SHA256: hashes.SHA256(), - SignatureAlgorithmOID.ED25519: None, - SignatureAlgorithmOID.ED448: None, - SignatureAlgorithmOID.GOSTR3411_94_WITH_3410_2001: None, - SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_256: None, - SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_512: None, -} - - -class HashAlgorithmOID: - SHA1 = ObjectIdentifier("1.3.14.3.2.26") - SHA224 = ObjectIdentifier("2.16.840.1.101.3.4.2.4") - SHA256 = ObjectIdentifier("2.16.840.1.101.3.4.2.1") - SHA384 = ObjectIdentifier("2.16.840.1.101.3.4.2.2") - SHA512 = ObjectIdentifier("2.16.840.1.101.3.4.2.3") - SHA3_224 = ObjectIdentifier("1.3.6.1.4.1.37476.3.2.1.99.7.224") - SHA3_256 = ObjectIdentifier("1.3.6.1.4.1.37476.3.2.1.99.7.256") - SHA3_384 = ObjectIdentifier("1.3.6.1.4.1.37476.3.2.1.99.7.384") - SHA3_512 = ObjectIdentifier("1.3.6.1.4.1.37476.3.2.1.99.7.512") - SHA3_224_NIST = ObjectIdentifier("2.16.840.1.101.3.4.2.7") - SHA3_256_NIST = ObjectIdentifier("2.16.840.1.101.3.4.2.8") - SHA3_384_NIST = ObjectIdentifier("2.16.840.1.101.3.4.2.9") - SHA3_512_NIST = ObjectIdentifier("2.16.840.1.101.3.4.2.10") - - -class PublicKeyAlgorithmOID: - DSA = ObjectIdentifier("1.2.840.10040.4.1") - EC_PUBLIC_KEY = ObjectIdentifier("1.2.840.10045.2.1") - RSAES_PKCS1_v1_5 = ObjectIdentifier("1.2.840.113549.1.1.1") - RSASSA_PSS = ObjectIdentifier("1.2.840.113549.1.1.10") - X25519 = ObjectIdentifier("1.3.101.110") - X448 = ObjectIdentifier("1.3.101.111") - ED25519 = ObjectIdentifier("1.3.101.112") - ED448 = ObjectIdentifier("1.3.101.113") - - -class ExtendedKeyUsageOID: - SERVER_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.1") - CLIENT_AUTH = ObjectIdentifier("1.3.6.1.5.5.7.3.2") - CODE_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.3") - EMAIL_PROTECTION = ObjectIdentifier("1.3.6.1.5.5.7.3.4") - TIME_STAMPING = ObjectIdentifier("1.3.6.1.5.5.7.3.8") - OCSP_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.9") - ANY_EXTENDED_KEY_USAGE = ObjectIdentifier("2.5.29.37.0") - SMARTCARD_LOGON = ObjectIdentifier("1.3.6.1.4.1.311.20.2.2") - KERBEROS_PKINIT_KDC = ObjectIdentifier("1.3.6.1.5.2.3.5") - IPSEC_IKE = ObjectIdentifier("1.3.6.1.5.5.7.3.17") - BUNDLE_SECURITY = ObjectIdentifier("1.3.6.1.5.5.7.3.35") - CERTIFICATE_TRANSPARENCY = ObjectIdentifier("1.3.6.1.4.1.11129.2.4.4") - - -class OtherNameFormOID: - PERMANENT_IDENTIFIER = ObjectIdentifier("1.3.6.1.5.5.7.8.3") - HW_MODULE_NAME = ObjectIdentifier("1.3.6.1.5.5.7.8.4") - DNS_SRV = ObjectIdentifier("1.3.6.1.5.5.7.8.7") - NAI_REALM = ObjectIdentifier("1.3.6.1.5.5.7.8.8") - SMTP_UTF8_MAILBOX = ObjectIdentifier("1.3.6.1.5.5.7.8.9") - ACP_NODE_NAME = ObjectIdentifier("1.3.6.1.5.5.7.8.10") - BUNDLE_EID = ObjectIdentifier("1.3.6.1.5.5.7.8.11") - - -class AuthorityInformationAccessOID: - CA_ISSUERS = ObjectIdentifier("1.3.6.1.5.5.7.48.2") - OCSP = ObjectIdentifier("1.3.6.1.5.5.7.48.1") - - -class SubjectInformationAccessOID: - CA_REPOSITORY = ObjectIdentifier("1.3.6.1.5.5.7.48.5") - - -class CertificatePoliciesOID: - CPS_QUALIFIER = ObjectIdentifier("1.3.6.1.5.5.7.2.1") - CPS_USER_NOTICE = ObjectIdentifier("1.3.6.1.5.5.7.2.2") - ANY_POLICY = ObjectIdentifier("2.5.29.32.0") - - -class AttributeOID: - CHALLENGE_PASSWORD = ObjectIdentifier("1.2.840.113549.1.9.7") - UNSTRUCTURED_NAME = ObjectIdentifier("1.2.840.113549.1.9.2") - - -_OID_NAMES = { - NameOID.COMMON_NAME: "commonName", - NameOID.COUNTRY_NAME: "countryName", - NameOID.LOCALITY_NAME: "localityName", - NameOID.STATE_OR_PROVINCE_NAME: "stateOrProvinceName", - NameOID.STREET_ADDRESS: "streetAddress", - NameOID.ORGANIZATION_NAME: "organizationName", - NameOID.ORGANIZATIONAL_UNIT_NAME: "organizationalUnitName", - NameOID.SERIAL_NUMBER: "serialNumber", - NameOID.SURNAME: "surname", - NameOID.GIVEN_NAME: "givenName", - NameOID.TITLE: "title", - NameOID.GENERATION_QUALIFIER: "generationQualifier", - NameOID.X500_UNIQUE_IDENTIFIER: "x500UniqueIdentifier", - NameOID.DN_QUALIFIER: "dnQualifier", - NameOID.PSEUDONYM: "pseudonym", - NameOID.USER_ID: "userID", - NameOID.DOMAIN_COMPONENT: "domainComponent", - NameOID.EMAIL_ADDRESS: "emailAddress", - NameOID.JURISDICTION_COUNTRY_NAME: "jurisdictionCountryName", - NameOID.JURISDICTION_LOCALITY_NAME: "jurisdictionLocalityName", - NameOID.JURISDICTION_STATE_OR_PROVINCE_NAME: ( - "jurisdictionStateOrProvinceName" - ), - NameOID.BUSINESS_CATEGORY: "businessCategory", - NameOID.POSTAL_ADDRESS: "postalAddress", - NameOID.POSTAL_CODE: "postalCode", - NameOID.INN: "INN", - NameOID.OGRN: "OGRN", - NameOID.SNILS: "SNILS", - NameOID.UNSTRUCTURED_NAME: "unstructuredName", - SignatureAlgorithmOID.RSA_WITH_MD5: "md5WithRSAEncryption", - SignatureAlgorithmOID.RSA_WITH_SHA1: "sha1WithRSAEncryption", - SignatureAlgorithmOID.RSA_WITH_SHA224: "sha224WithRSAEncryption", - SignatureAlgorithmOID.RSA_WITH_SHA256: "sha256WithRSAEncryption", - SignatureAlgorithmOID.RSA_WITH_SHA384: "sha384WithRSAEncryption", - SignatureAlgorithmOID.RSA_WITH_SHA512: "sha512WithRSAEncryption", - SignatureAlgorithmOID.RSASSA_PSS: "rsassaPss", - SignatureAlgorithmOID.ECDSA_WITH_SHA1: "ecdsa-with-SHA1", - SignatureAlgorithmOID.ECDSA_WITH_SHA224: "ecdsa-with-SHA224", - SignatureAlgorithmOID.ECDSA_WITH_SHA256: "ecdsa-with-SHA256", - SignatureAlgorithmOID.ECDSA_WITH_SHA384: "ecdsa-with-SHA384", - SignatureAlgorithmOID.ECDSA_WITH_SHA512: "ecdsa-with-SHA512", - SignatureAlgorithmOID.DSA_WITH_SHA1: "dsa-with-sha1", - SignatureAlgorithmOID.DSA_WITH_SHA224: "dsa-with-sha224", - SignatureAlgorithmOID.DSA_WITH_SHA256: "dsa-with-sha256", - SignatureAlgorithmOID.ED25519: "ed25519", - SignatureAlgorithmOID.ED448: "ed448", - SignatureAlgorithmOID.GOSTR3411_94_WITH_3410_2001: ( - "GOST R 34.11-94 with GOST R 34.10-2001" - ), - SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_256: ( - "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)" - ), - SignatureAlgorithmOID.GOSTR3410_2012_WITH_3411_2012_512: ( - "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)" - ), - HashAlgorithmOID.SHA1: "sha1", - HashAlgorithmOID.SHA224: "sha224", - HashAlgorithmOID.SHA256: "sha256", - HashAlgorithmOID.SHA384: "sha384", - HashAlgorithmOID.SHA512: "sha512", - HashAlgorithmOID.SHA3_224: "sha3_224", - HashAlgorithmOID.SHA3_256: "sha3_256", - HashAlgorithmOID.SHA3_384: "sha3_384", - HashAlgorithmOID.SHA3_512: "sha3_512", - HashAlgorithmOID.SHA3_224_NIST: "sha3_224", - HashAlgorithmOID.SHA3_256_NIST: "sha3_256", - HashAlgorithmOID.SHA3_384_NIST: "sha3_384", - HashAlgorithmOID.SHA3_512_NIST: "sha3_512", - PublicKeyAlgorithmOID.DSA: "dsaEncryption", - PublicKeyAlgorithmOID.EC_PUBLIC_KEY: "id-ecPublicKey", - PublicKeyAlgorithmOID.RSAES_PKCS1_v1_5: "rsaEncryption", - PublicKeyAlgorithmOID.X25519: "X25519", - PublicKeyAlgorithmOID.X448: "X448", - ExtendedKeyUsageOID.SERVER_AUTH: "serverAuth", - ExtendedKeyUsageOID.CLIENT_AUTH: "clientAuth", - ExtendedKeyUsageOID.CODE_SIGNING: "codeSigning", - ExtendedKeyUsageOID.EMAIL_PROTECTION: "emailProtection", - ExtendedKeyUsageOID.TIME_STAMPING: "timeStamping", - ExtendedKeyUsageOID.OCSP_SIGNING: "OCSPSigning", - ExtendedKeyUsageOID.SMARTCARD_LOGON: "msSmartcardLogin", - ExtendedKeyUsageOID.KERBEROS_PKINIT_KDC: "pkInitKDC", - ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES: "subjectDirectoryAttributes", - ExtensionOID.SUBJECT_KEY_IDENTIFIER: "subjectKeyIdentifier", - ExtensionOID.KEY_USAGE: "keyUsage", - ExtensionOID.PRIVATE_KEY_USAGE_PERIOD: "privateKeyUsagePeriod", - ExtensionOID.SUBJECT_ALTERNATIVE_NAME: "subjectAltName", - ExtensionOID.ISSUER_ALTERNATIVE_NAME: "issuerAltName", - ExtensionOID.BASIC_CONSTRAINTS: "basicConstraints", - ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: ( - "signedCertificateTimestampList" - ), - ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: ( - "signedCertificateTimestampList" - ), - ExtensionOID.PRECERT_POISON: "ctPoison", - ExtensionOID.MS_CERTIFICATE_TEMPLATE: "msCertificateTemplate", - ExtensionOID.ADMISSIONS: "Admissions", - CRLEntryExtensionOID.CRL_REASON: "cRLReason", - CRLEntryExtensionOID.INVALIDITY_DATE: "invalidityDate", - CRLEntryExtensionOID.CERTIFICATE_ISSUER: "certificateIssuer", - ExtensionOID.NAME_CONSTRAINTS: "nameConstraints", - ExtensionOID.CRL_DISTRIBUTION_POINTS: "cRLDistributionPoints", - ExtensionOID.CERTIFICATE_POLICIES: "certificatePolicies", - ExtensionOID.POLICY_MAPPINGS: "policyMappings", - ExtensionOID.AUTHORITY_KEY_IDENTIFIER: "authorityKeyIdentifier", - ExtensionOID.POLICY_CONSTRAINTS: "policyConstraints", - ExtensionOID.EXTENDED_KEY_USAGE: "extendedKeyUsage", - ExtensionOID.FRESHEST_CRL: "freshestCRL", - ExtensionOID.INHIBIT_ANY_POLICY: "inhibitAnyPolicy", - ExtensionOID.ISSUING_DISTRIBUTION_POINT: "issuingDistributionPoint", - ExtensionOID.AUTHORITY_INFORMATION_ACCESS: "authorityInfoAccess", - ExtensionOID.SUBJECT_INFORMATION_ACCESS: "subjectInfoAccess", - ExtensionOID.OCSP_NO_CHECK: "OCSPNoCheck", - ExtensionOID.CRL_NUMBER: "cRLNumber", - ExtensionOID.DELTA_CRL_INDICATOR: "deltaCRLIndicator", - ExtensionOID.TLS_FEATURE: "TLSFeature", - AuthorityInformationAccessOID.OCSP: "OCSP", - AuthorityInformationAccessOID.CA_ISSUERS: "caIssuers", - SubjectInformationAccessOID.CA_REPOSITORY: "caRepository", - CertificatePoliciesOID.CPS_QUALIFIER: "id-qt-cps", - CertificatePoliciesOID.CPS_USER_NOTICE: "id-qt-unotice", - OCSPExtensionOID.NONCE: "OCSPNonce", - AttributeOID.CHALLENGE_PASSWORD: "challengePassword", -} diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/asn1/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/asn1/__init__.py deleted file mode 100644 index ac3d4bd..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/asn1/__init__.py +++ /dev/null @@ -1,43 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from cryptography.hazmat.asn1.asn1 import ( - TLV, - BitString, - Default, - Explicit, - GeneralizedTime, - IA5String, - Implicit, - Null, - PrintableString, - SetOf, - Size, - UTCTime, - Variant, - decode_der, - encode_der, - sequence, - set, -) - -__all__ = [ - "TLV", - "BitString", - "Default", - "Explicit", - "GeneralizedTime", - "IA5String", - "Implicit", - "Null", - "PrintableString", - "SetOf", - "Size", - "UTCTime", - "Variant", - "decode_der", - "encode_der", - "sequence", - "set", -] diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/asn1/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/asn1/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index f5565fb..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/asn1/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/asn1/__pycache__/asn1.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/asn1/__pycache__/asn1.cpython-312.pyc deleted file mode 100644 index fad8107..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/asn1/__pycache__/asn1.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/asn1/asn1.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/asn1/asn1.py deleted file mode 100644 index aa18d7e..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/asn1/asn1.py +++ /dev/null @@ -1,419 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import builtins -import dataclasses -import sys -import types -import typing - -if sys.version_info < (3, 11): - import typing_extensions - - LiteralString = typing_extensions.LiteralString -else: - LiteralString = typing.LiteralString - -from cryptography.hazmat.bindings._rust import declarative_asn1 - -if sys.version_info < (3, 10): - NoneType = type(None) -else: - NoneType = types.NoneType # type: ignore[nonetype-type] - -T = typing.TypeVar("T", covariant=True) -U = typing.TypeVar("U") -Tag = typing.TypeVar("Tag", bound=LiteralString) - - -@dataclasses.dataclass(frozen=True) -class Variant(typing.Generic[U, Tag]): - """ - A tagged variant for CHOICE fields with the same underlying type. - - Use this when you have multiple CHOICE alternatives with the same type - and need to distinguish between them: - - foo: ( - Annotated[Variant[int, typing.Literal["IntA"]], Implicit(0)] - | Annotated[Variant[int, typing.Literal["IntB"]], Implicit(1)] - ) - - Usage: - example = Example(foo=Variant(5, "IntA")) - decoded.foo.value # The int value - decoded.foo.tag # "IntA" or "IntB" - """ - - value: U - tag: str - - -decode_der = declarative_asn1.decode_der -encode_der = declarative_asn1.encode_der - - -def _is_union(field_type: type) -> bool: - # NOTE: types.UnionType for `T | U`, typing.Union for `Union[T, U]`. - # TODO: Drop the `hasattr()` once the minimum supported Python version - # is >= 3.10. - union_types = ( - (types.UnionType, typing.Union) - if hasattr(types, "UnionType") - else (typing.Union,) - ) - return typing.get_origin(field_type) in union_types - - -def _extract_annotation( - metadata: tuple, field_name: str -) -> declarative_asn1.Annotation: - default = None - encoding = None - size = None - for raw_annotation in metadata: - if isinstance(raw_annotation, Default): - if default is not None: - raise TypeError( - f"multiple DEFAULT annotations found in field " - f"'{field_name}'" - ) - default = raw_annotation.value - elif isinstance(raw_annotation, declarative_asn1.Encoding): - if encoding is not None: - raise TypeError( - f"multiple IMPLICIT/EXPLICIT annotations found in field " - f"'{field_name}'" - ) - encoding = raw_annotation - elif isinstance(raw_annotation, declarative_asn1.Size): - if size is not None: - raise TypeError( - f"multiple SIZE annotations found in field '{field_name}'" - ) - size = raw_annotation - else: - raise TypeError(f"unsupported annotation: {raw_annotation}") - - return declarative_asn1.Annotation( - default=default, encoding=encoding, size=size - ) - - -def _normalize_field_type( - field_type: typing.Any, field_name: str -) -> declarative_asn1.AnnotatedType: - # Strip the `Annotated[...]` off, and populate the annotation - # from it if it exists. - if typing.get_origin(field_type) is typing.Annotated: - annotation = _extract_annotation(field_type.__metadata__, field_name) - field_type, *_ = typing.get_args(field_type) - else: - annotation = declarative_asn1.Annotation() - - if annotation.size is not None and ( - typing.get_origin(field_type) not in (builtins.list, SetOf) - and field_type - not in ( - builtins.bytes, - builtins.str, - BitString, - IA5String, - PrintableString, - ) - ): - raise TypeError( - f"field '{field_name}' has a SIZE annotation, but SIZE " - "annotations are only supported for fields of types: " - "[SEQUENCE OF, SET OF, BIT STRING, OCTET STRING, UTF8String, " - "PrintableString, IA5String]" - ) - - if field_type is TLV: - if isinstance(annotation.encoding, Implicit): - raise TypeError( - f"field '{field_name}' has an IMPLICIT annotation, but " - "IMPLICIT annotations are not supported for TLV types." - ) - elif annotation.default is not None: - raise TypeError( - f"field '{field_name}' has a DEFAULT annotation, but " - "DEFAULT annotations are not supported for TLV types." - ) - - if hasattr(field_type, "__asn1_root__"): - root_type = field_type.__asn1_root__ - if not isinstance( - root_type, - (declarative_asn1.Type.Sequence, declarative_asn1.Type.Set), - ): - raise TypeError(f"unsupported root type: {root_type}") - return declarative_asn1.AnnotatedType( - typing.cast(declarative_asn1.Type, root_type), annotation - ) - elif _is_union(field_type): - union_args = typing.get_args(field_type) - if len(union_args) == 2 and NoneType in union_args: - # A Union between a type and None is an OPTIONAL - optional_type = ( - union_args[0] if union_args[1] is type(None) else union_args[1] - ) - if optional_type is TLV: - raise TypeError( - "optional TLV types (`TLV | None`) are not " - "currently supported" - ) - annotated_type = _normalize_field_type(optional_type, field_name) - - if not annotated_type.annotation.is_empty(): - raise TypeError( - "optional (`X | None`) types cannot have `X` " - "annotated: annotations must apply to the union " - "(i.e: `Annotated[X | None, annotation]`)" - ) - - if annotation.default is not None: - raise TypeError( - "optional (`X | None`) types should not have a DEFAULT " - "annotation" - ) - - rust_field_type = declarative_asn1.Type.Option(annotated_type) - - else: - # Otherwise, the Union is a CHOICE - if isinstance(annotation.encoding, Implicit): - # CHOICEs cannot be IMPLICIT. See X.680 section 31.2.9. - raise TypeError( - "CHOICE (`X | Y | ...`) types should not have an IMPLICIT " - "annotation" - ) - variants = [ - _type_to_variant(arg, field_name) - for arg in union_args - if arg is not type(None) - ] - - # Union types should either be all Variants - # (`Variant[..] | Variant[..] | etc`) or all non Variants - are_union_types_tagged = variants[0].tag_name is not None - if any( - (v.tag_name is not None) != are_union_types_tagged - for v in variants - ): - raise TypeError( - "When using `asn1.Variant` in a union, all the other " - "types in the union must also be `asn1.Variant`" - ) - - if are_union_types_tagged: - tags = {v.tag_name for v in variants} - if len(variants) != len(tags): - raise TypeError( - "When using `asn1.Variant` in a union, the tags used " - "must be unique" - ) - - rust_choice_type = declarative_asn1.Type.Choice(variants) - # If None is part of the union types, this is an OPTIONAL CHOICE - rust_field_type = ( - declarative_asn1.Type.Option( - declarative_asn1.AnnotatedType( - rust_choice_type, declarative_asn1.Annotation() - ) - ) - if NoneType in union_args - else rust_choice_type - ) - - elif typing.get_origin(field_type) is builtins.list: - inner_type = _normalize_field_type( - typing.get_args(field_type)[0], field_name - ) - rust_field_type = declarative_asn1.Type.SequenceOf(inner_type) - elif typing.get_origin(field_type) is SetOf: - inner_type = _normalize_field_type( - typing.get_args(field_type)[0], field_name - ) - rust_field_type = declarative_asn1.Type.SetOf(inner_type) - else: - rust_field_type = declarative_asn1.non_root_python_to_rust(field_type) - - return declarative_asn1.AnnotatedType(rust_field_type, annotation) - - -# Convert a type to a Variant. Used with types inside Union -# annotations (T1, T2, etc in `Union[T1, T2, ...]`). -def _type_to_variant( - t: typing.Any, field_name: str -) -> declarative_asn1.Variant: - is_annotated = typing.get_origin(t) is typing.Annotated - inner_type = typing.get_args(t)[0] if is_annotated else t - - # Check if this is a Variant[T, Tag] type - if typing.get_origin(inner_type) is Variant: - value_type, tag_literal = typing.get_args(inner_type) - if typing.get_origin(tag_literal) is not typing.Literal: - raise TypeError( - "When using `asn1.Variant` in a type annotation, the second " - "type parameter must be a `typing.Literal` type. E.g: " - '`Variant[int, typing.Literal["MyInt"]]`.' - ) - tag_name = typing.get_args(tag_literal)[0] - - if hasattr(value_type, "__asn1_root__"): - rust_type = value_type.__asn1_root__ - else: - rust_type = declarative_asn1.non_root_python_to_rust(value_type) - - if is_annotated: - ann_type = declarative_asn1.AnnotatedType( - rust_type, - _extract_annotation(t.__metadata__, field_name), - ) - else: - ann_type = declarative_asn1.AnnotatedType( - rust_type, - declarative_asn1.Annotation(), - ) - - return declarative_asn1.Variant(Variant, ann_type, tag_name) - else: - # Plain type (not a tagged Variant) - return declarative_asn1.Variant( - inner_type, - _normalize_field_type(t, field_name), - None, - ) - - -def _annotate_fields( - raw_fields: dict[str, type], -) -> dict[str, declarative_asn1.AnnotatedType]: - fields = {} - for field_name, field_type in raw_fields.items(): - # Recursively normalize the field type into something that the - # Rust code can understand. - annotated_field_type = _normalize_field_type(field_type, field_name) - fields[field_name] = annotated_field_type - - return fields - - -def _register_asn1_sequence(cls: type[U]) -> None: - raw_fields = typing.get_type_hints(cls, include_extras=True) - root = declarative_asn1.Type.Sequence(cls, _annotate_fields(raw_fields)) - - setattr(cls, "__asn1_root__", root) - - -def _register_asn1_set(cls: type[U]) -> None: - raw_fields = typing.get_type_hints(cls, include_extras=True) - root = declarative_asn1.Type.Set(cls, _annotate_fields(raw_fields)) - - setattr(cls, "__asn1_root__", root) - - -# Due to https://github.com/python/mypy/issues/19731, we can't define an alias -# for `dataclass_transform` that conditionally points to `typing` or -# `typing_extensions` depending on the Python version. We work around it by -# making the whole decorated class conditional on the Python version. -if sys.version_info < (3, 11): - - @typing_extensions.dataclass_transform(kw_only_default=True) - def sequence(cls: type[U]) -> type[U]: - # We use `dataclasses.dataclass` to add an __init__ method - # to the class with keyword-only parameters. - if sys.version_info >= (3, 10): - dataclass_cls = dataclasses.dataclass( - repr=False, - eq=False, - # `match_args` was added in Python 3.10 and defaults - # to True - match_args=False, - # `kw_only` was added in Python 3.10 and defaults to - # False - kw_only=True, - )(cls) - else: - dataclass_cls = dataclasses.dataclass( - repr=False, - eq=False, - )(cls) - _register_asn1_sequence(dataclass_cls) - return dataclass_cls - - @typing_extensions.dataclass_transform(kw_only_default=True) - def set(cls: type[U]) -> type[U]: - # We use `dataclasses.dataclass` to add an __init__ method - # to the class with keyword-only parameters. - if sys.version_info >= (3, 10): - dataclass_cls = dataclasses.dataclass( - repr=False, - eq=False, - # `match_args` was added in Python 3.10 and defaults - # to True - match_args=False, - # `kw_only` was added in Python 3.10 and defaults to - # False - kw_only=True, - )(cls) - else: - dataclass_cls = dataclasses.dataclass( - repr=False, - eq=False, - )(cls) - _register_asn1_set(dataclass_cls) - return dataclass_cls - -else: - - @typing.dataclass_transform(kw_only_default=True) - def sequence(cls: type[U]) -> type[U]: - # Only add an __init__ method, with keyword-only - # parameters. - dataclass_cls = dataclasses.dataclass( - repr=False, - eq=False, - match_args=False, - kw_only=True, - )(cls) - _register_asn1_sequence(dataclass_cls) - return dataclass_cls - - @typing.dataclass_transform(kw_only_default=True) - def set(cls: type[U]) -> type[U]: - # Only add an __init__ method, with keyword-only - # parameters. - dataclass_cls = dataclasses.dataclass( - repr=False, - eq=False, - match_args=False, - kw_only=True, - )(cls) - _register_asn1_set(dataclass_cls) - return dataclass_cls - - -# TODO: replace with `Default[U]` once the min Python version is >= 3.12 -@dataclasses.dataclass(frozen=True) -class Default(typing.Generic[U]): - value: U - - -SetOf = declarative_asn1.SetOf - -Explicit = declarative_asn1.Encoding.Explicit -Implicit = declarative_asn1.Encoding.Implicit -Size = declarative_asn1.Size - -PrintableString = declarative_asn1.PrintableString -IA5String = declarative_asn1.IA5String -UTCTime = declarative_asn1.UTCTime -GeneralizedTime = declarative_asn1.GeneralizedTime -BitString = declarative_asn1.BitString -TLV = declarative_asn1.Tlv -Null = declarative_asn1.Null diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/__init__.py deleted file mode 100644 index b4400aa..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from typing import Any - - -def default_backend() -> Any: - from cryptography.hazmat.backends.openssl.backend import backend - - return backend diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index c0090ff..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__init__.py deleted file mode 100644 index 51b0447..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.backends.openssl.backend import backend - -__all__ = ["backend"] diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 53b5764..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-312.pyc deleted file mode 100644 index 81dbb5c..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/openssl/backend.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/openssl/backend.py deleted file mode 100644 index ad64a2a..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/backends/openssl/backend.py +++ /dev/null @@ -1,312 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.bindings.openssl import binding -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding -from cryptography.hazmat.primitives.asymmetric import ec -from cryptography.hazmat.primitives.asymmetric import utils as asym_utils -from cryptography.hazmat.primitives.asymmetric.padding import ( - MGF1, - OAEP, - PSS, - PKCS1v15, -) -from cryptography.hazmat.primitives.ciphers import ( - CipherAlgorithm, -) -from cryptography.hazmat.primitives.ciphers.algorithms import ( - AES, -) -from cryptography.hazmat.primitives.ciphers.modes import ( - CBC, - Mode, -) - - -class Backend: - """ - OpenSSL API binding interfaces. - """ - - name = "openssl" - - # TripleDES encryption is disallowed/deprecated throughout 2023 in - # FIPS 140-3. To keep it simple we denylist any use of TripleDES (TDEA). - _fips_ciphers = (AES,) - # Sometimes SHA1 is still permissible. That logic is contained - # within the various *_supported methods. - _fips_hashes = ( - hashes.SHA224, - hashes.SHA256, - hashes.SHA384, - hashes.SHA512, - hashes.SHA512_224, - hashes.SHA512_256, - hashes.SHA3_224, - hashes.SHA3_256, - hashes.SHA3_384, - hashes.SHA3_512, - hashes.SHAKE128, - hashes.SHAKE256, - ) - _fips_ecdh_curves = ( - ec.SECP224R1, - ec.SECP256R1, - ec.SECP384R1, - ec.SECP521R1, - ) - _fips_rsa_min_key_size = 2048 - _fips_rsa_min_public_exponent = 65537 - _fips_dsa_min_modulus = 1 << 2048 - _fips_dh_min_key_size = 2048 - _fips_dh_min_modulus = 1 << _fips_dh_min_key_size - - def __init__(self) -> None: - self._binding = binding.Binding() - self._ffi = self._binding.ffi - self._lib = self._binding.lib - self._fips_enabled = rust_openssl.is_fips_enabled() - - def __repr__(self) -> str: - return ( - f"" - ) - - def openssl_assert(self, ok: bool) -> None: - return binding._openssl_assert(ok) - - def _enable_fips(self) -> None: - # This function enables FIPS mode for OpenSSL 3.0.0 on installs that - # have the FIPS provider installed properly. - rust_openssl.enable_fips(rust_openssl._providers) - assert rust_openssl.is_fips_enabled() - self._fips_enabled = rust_openssl.is_fips_enabled() - - def openssl_version_text(self) -> str: - """ - Friendly string name of the loaded OpenSSL library. This is not - necessarily the same version as it was compiled against. - - Example: OpenSSL 3.2.1 30 Jan 2024 - """ - return rust_openssl.openssl_version_text() - - def openssl_version_number(self) -> int: - return rust_openssl.openssl_version() - - def hash_supported(self, algorithm: hashes.HashAlgorithm) -> bool: - if self._fips_enabled and not isinstance(algorithm, self._fips_hashes): - return False - - return rust_openssl.hashes.hash_supported(algorithm) - - def signature_hash_supported( - self, algorithm: hashes.HashAlgorithm - ) -> bool: - # Dedicated check for hashing algorithm use in message digest for - # signatures, e.g. RSA PKCS#1 v1.5 SHA1 (sha1WithRSAEncryption). - if self._fips_enabled and isinstance(algorithm, hashes.SHA1): - return False - return self.hash_supported(algorithm) - - def scrypt_supported(self) -> bool: - if self._fips_enabled: - return False - else: - return hasattr(rust_openssl.kdf.Scrypt, "derive") - - def argon2_supported(self) -> bool: - if self._fips_enabled: - return False - else: - return hasattr(rust_openssl.kdf.Argon2id, "derive") - - def hmac_supported(self, algorithm: hashes.HashAlgorithm) -> bool: - # FIPS mode still allows SHA1 for HMAC - if self._fips_enabled and isinstance(algorithm, hashes.SHA1): - return True - if rust_openssl.CRYPTOGRAPHY_IS_AWSLC: - return isinstance( - algorithm, - ( - hashes.MD5, - hashes.SHA1, - hashes.SHA224, - hashes.SHA256, - hashes.SHA384, - hashes.SHA512, - hashes.SHA512_224, - hashes.SHA512_256, - ), - ) - return self.hash_supported(algorithm) - - def cipher_supported(self, cipher: CipherAlgorithm, mode: Mode) -> bool: - if self._fips_enabled: - # FIPS mode requires AES. TripleDES is disallowed/deprecated in - # FIPS 140-3. - if not isinstance(cipher, self._fips_ciphers): - return False - - return rust_openssl.ciphers.cipher_supported(cipher, mode) - - def pbkdf2_hmac_supported(self, algorithm: hashes.HashAlgorithm) -> bool: - return self.hmac_supported(algorithm) - - def _consume_errors(self) -> list[rust_openssl.OpenSSLError]: - return rust_openssl.capture_error_stack() - - def _oaep_hash_supported(self, algorithm: hashes.HashAlgorithm) -> bool: - if self._fips_enabled and isinstance(algorithm, hashes.SHA1): - return False - - return isinstance( - algorithm, - ( - hashes.SHA1, - hashes.SHA224, - hashes.SHA256, - hashes.SHA384, - hashes.SHA512, - ), - ) - - def rsa_padding_supported(self, padding: AsymmetricPadding) -> bool: - if isinstance(padding, PKCS1v15): - return True - elif isinstance(padding, PSS) and isinstance(padding._mgf, MGF1): - # FIPS 186-4 only allows salt length == digest length for PSS - # It is technically acceptable to set an explicit salt length - # equal to the digest length and this will incorrectly fail, but - # since we don't do that in the tests and this method is - # private, we'll ignore that until we need to do otherwise. - if ( - self._fips_enabled - and padding._salt_length != PSS.DIGEST_LENGTH - ): - return False - return self.hash_supported(padding._mgf._algorithm) - elif isinstance(padding, OAEP) and isinstance(padding._mgf, MGF1): - return self._oaep_hash_supported( - padding._mgf._algorithm - ) and self._oaep_hash_supported(padding._algorithm) - else: - return False - - def rsa_encryption_supported(self, padding: AsymmetricPadding) -> bool: - if self._fips_enabled and isinstance(padding, PKCS1v15): - return False - else: - return self.rsa_padding_supported(padding) - - def dsa_supported(self) -> bool: - return ( - not rust_openssl.CRYPTOGRAPHY_IS_BORINGSSL - and not self._fips_enabled - ) - - def dsa_hash_supported(self, algorithm: hashes.HashAlgorithm) -> bool: - if not self.dsa_supported(): - return False - return self.signature_hash_supported(algorithm) - - def cmac_algorithm_supported(self, algorithm) -> bool: - return self.cipher_supported( - algorithm, CBC(b"\x00" * algorithm.block_size) - ) - - def elliptic_curve_supported(self, curve: ec.EllipticCurve) -> bool: - if self._fips_enabled and not isinstance( - curve, self._fips_ecdh_curves - ): - return False - - return rust_openssl.ec.curve_supported(curve) - - def elliptic_curve_signature_algorithm_supported( - self, - signature_algorithm: ec.EllipticCurveSignatureAlgorithm, - curve: ec.EllipticCurve, - ) -> bool: - # We only support ECDSA right now. - if not isinstance(signature_algorithm, ec.ECDSA): - return False - - return self.elliptic_curve_supported(curve) and ( - isinstance(signature_algorithm.algorithm, asym_utils.Prehashed) - or self.hash_supported(signature_algorithm.algorithm) - ) - - def elliptic_curve_exchange_algorithm_supported( - self, algorithm: ec.ECDH, curve: ec.EllipticCurve - ) -> bool: - return self.elliptic_curve_supported(curve) and isinstance( - algorithm, ec.ECDH - ) - - def dh_supported(self) -> bool: - return ( - not rust_openssl.CRYPTOGRAPHY_IS_BORINGSSL - and not rust_openssl.CRYPTOGRAPHY_IS_AWSLC - ) - - def dh_x942_serialization_supported(self) -> bool: - return self._lib.Cryptography_HAS_EVP_PKEY_DHX == 1 - - def x25519_supported(self) -> bool: - return not self._fips_enabled - - def x448_supported(self) -> bool: - if self._fips_enabled: - return False - return ( - not rust_openssl.CRYPTOGRAPHY_IS_LIBRESSL - and not rust_openssl.CRYPTOGRAPHY_IS_BORINGSSL - and not rust_openssl.CRYPTOGRAPHY_IS_AWSLC - ) - - def mlkem_supported(self) -> bool: - return ( - rust_openssl.CRYPTOGRAPHY_IS_AWSLC - or rust_openssl.CRYPTOGRAPHY_IS_BORINGSSL - or rust_openssl.CRYPTOGRAPHY_OPENSSL_350_OR_GREATER - ) - - def mldsa_supported(self) -> bool: - return ( - rust_openssl.CRYPTOGRAPHY_IS_AWSLC - or rust_openssl.CRYPTOGRAPHY_IS_BORINGSSL - or rust_openssl.CRYPTOGRAPHY_OPENSSL_350_OR_GREATER - ) - - def ed25519_supported(self) -> bool: - return True - - def ed448_supported(self) -> bool: - return ( - not rust_openssl.CRYPTOGRAPHY_IS_LIBRESSL - and not rust_openssl.CRYPTOGRAPHY_IS_BORINGSSL - and not rust_openssl.CRYPTOGRAPHY_IS_AWSLC - ) - - def ecdsa_deterministic_supported(self) -> bool: - return ( - rust_openssl.CRYPTOGRAPHY_OPENSSL_320_OR_GREATER - and not self._fips_enabled - ) - - def poly1305_supported(self) -> bool: - return not self._fips_enabled - - def pkcs7_supported(self) -> bool: - return True - - -backend = Backend() diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/__init__.py deleted file mode 100644 index b509336..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 064a6b3..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust.pyd b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust.pyd deleted file mode 100644 index 6fdb43b..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust.pyd and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/__init__.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/__init__.pyi deleted file mode 100644 index c3148f1..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/__init__.pyi +++ /dev/null @@ -1,67 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing - -from cryptography.hazmat.primitives import padding -from cryptography.hazmat.primitives._serialization import ( - KeySerializationEncryptionBuilder, -) -from cryptography.utils import Buffer - -class PKCS7PaddingContext(padding.PaddingContext): - def __init__(self, block_size: int) -> None: ... - def update(self, data: Buffer) -> bytes: ... - def finalize(self) -> bytes: ... - -class ANSIX923PaddingContext(padding.PaddingContext): - def __init__(self, block_size: int) -> None: ... - def update(self, data: Buffer) -> bytes: ... - def finalize(self) -> bytes: ... - -class PKCS7UnpaddingContext(padding.PaddingContext): - def __init__(self, block_size: int) -> None: ... - def update(self, data: Buffer) -> bytes: ... - def finalize(self) -> bytes: ... - -class ANSIX923UnpaddingContext(padding.PaddingContext): - def __init__(self, block_size: int) -> None: ... - def update(self, data: Buffer) -> bytes: ... - def finalize(self) -> bytes: ... - -class Encoding: - PEM: typing.ClassVar[Encoding] - DER: typing.ClassVar[Encoding] - OpenSSH: typing.ClassVar[Encoding] - Raw: typing.ClassVar[Encoding] - X962: typing.ClassVar[Encoding] - SMIME: typing.ClassVar[Encoding] - -class PrivateFormat: - PKCS8: typing.ClassVar[PrivateFormat] - TraditionalOpenSSL: typing.ClassVar[PrivateFormat] - Raw: typing.ClassVar[PrivateFormat] - OpenSSH: typing.ClassVar[PrivateFormat] - PKCS12: typing.ClassVar[PrivateFormat] - def encryption_builder(self) -> KeySerializationEncryptionBuilder: ... - -class PublicFormat: - SubjectPublicKeyInfo: typing.ClassVar[PublicFormat] - PKCS1: typing.ClassVar[PublicFormat] - OpenSSH: typing.ClassVar[PublicFormat] - Raw: typing.ClassVar[PublicFormat] - CompressedPoint: typing.ClassVar[PublicFormat] - UncompressedPoint: typing.ClassVar[PublicFormat] - -class ParameterFormat: - PKCS3: typing.ClassVar[ParameterFormat] - -class ObjectIdentifier: - def __init__(self, value: str) -> None: ... - @property - def dotted_string(self) -> str: ... - @property - def _name(self) -> str: ... - -T = typing.TypeVar("T") diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/_openssl.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/_openssl.pyi deleted file mode 100644 index 3d4ea4e..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/_openssl.pyi +++ /dev/null @@ -1,8 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing - -lib: typing.Any -ffi: typing.Any diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/asn1.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/asn1.pyi deleted file mode 100644 index 3b5f208..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/asn1.pyi +++ /dev/null @@ -1,7 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -def decode_dss_signature(signature: bytes) -> tuple[int, int]: ... -def encode_dss_signature(r: int, s: int) -> bytes: ... -def parse_spki_for_data(data: bytes) -> bytes: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/declarative_asn1.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/declarative_asn1.pyi deleted file mode 100644 index a4c0cb6..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/declarative_asn1.pyi +++ /dev/null @@ -1,127 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import datetime -import typing - -def decode_der(cls: type, value: bytes) -> typing.Any: ... -def encode_der(value: typing.Any) -> bytes: ... -def non_root_python_to_rust(cls: type) -> Type: ... - -# Type is a Rust enum with tuple variants. For now, we express the type -# annotations like this: -class Type: - Sequence: typing.ClassVar[type] - SequenceOf: typing.ClassVar[type] - Set: typing.ClassVar[type] - SetOf: typing.ClassVar[type] - Option: typing.ClassVar[type] - Choice: typing.ClassVar[type] - PyBool: typing.ClassVar[type] - PyInt: typing.ClassVar[type] - PyBytes: typing.ClassVar[type] - PyStr: typing.ClassVar[type] - -class Annotation: - default: typing.Any | None - encoding: Encoding | None - size: Size | None - def __new__( - cls, - default: typing.Any | None = None, - encoding: Encoding | None = None, - size: Size | None = None, - ) -> Annotation: ... - def is_empty(self) -> bool: ... - -# Encoding is a Rust enum with tuple variants. For now, we express the type -# annotations like this: -class Encoding: - Implicit: typing.ClassVar[type] - Explicit: typing.ClassVar[type] - -class Size: - min: int - max: int | None - - def __new__(cls, min: int, max: int | None) -> Size: ... - @staticmethod - def exact(n: int) -> Size: ... - -class AnnotatedType: - inner: Type - annotation: Annotation - - def __new__(cls, inner: Type, annotation: Annotation) -> AnnotatedType: ... - -class AnnotatedTypeObject: - annotated_type: AnnotatedType - value: typing.Any - - def __new__( - cls, annotated_type: AnnotatedType, value: typing.Any - ) -> AnnotatedTypeObject: ... - -class Variant: - python_class: type - ann_type: AnnotatedType - tag_name: str | None - - def __new__( - cls, - python_class: type, - ann_type: AnnotatedType, - tag_name: str | None, - ) -> Variant: ... - -class PrintableString: - def __new__(cls, inner: str) -> PrintableString: ... - def __repr__(self) -> str: ... - def __eq__(self, other: object) -> bool: ... - def as_str(self) -> str: ... - -class IA5String: - def __new__(cls, inner: str) -> IA5String: ... - def __repr__(self) -> str: ... - def __eq__(self, other: object) -> bool: ... - def as_str(self) -> str: ... - -class UTCTime: - def __new__(cls, inner: datetime.datetime) -> UTCTime: ... - def __repr__(self) -> str: ... - def __eq__(self, other: object) -> bool: ... - def as_datetime(self) -> datetime.datetime: ... - -class GeneralizedTime: - def __new__(cls, inner: datetime.datetime) -> GeneralizedTime: ... - def __repr__(self) -> str: ... - def __eq__(self, other: object) -> bool: ... - def as_datetime(self) -> datetime.datetime: ... - -class BitString: - def __new__(cls, data: bytes, padding_bits: int) -> BitString: ... - def __repr__(self) -> str: ... - def __eq__(self, other: object) -> bool: ... - def as_bytes(self) -> bytes: ... - def padding_bits(self) -> int: ... - -class Tlv: - @property - def tag_bytes(self) -> bytes: ... - @property - def data(self) -> memoryview: ... - def parse(self, cls: type): ... - -T = typing.TypeVar("T") - -class SetOf(typing.Generic[T]): - def __new__(cls, inner: list[T]) -> SetOf[T]: ... - def as_list(self) -> list[T]: ... - def __eq__(self, other: object) -> bool: ... - def __repr__(self) -> str: ... - -class Null: - def __new__(cls) -> Null: ... - def __repr__(self) -> str: ... - def __eq__(self, other: object) -> bool: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/exceptions.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/exceptions.pyi deleted file mode 100644 index 09f46b1..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/exceptions.pyi +++ /dev/null @@ -1,17 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -class _Reasons: - BACKEND_MISSING_INTERFACE: _Reasons - UNSUPPORTED_HASH: _Reasons - UNSUPPORTED_CIPHER: _Reasons - UNSUPPORTED_PADDING: _Reasons - UNSUPPORTED_MGF: _Reasons - UNSUPPORTED_PUBLIC_KEY_ALGORITHM: _Reasons - UNSUPPORTED_ELLIPTIC_CURVE: _Reasons - UNSUPPORTED_SERIALIZATION: _Reasons - UNSUPPORTED_X509: _Reasons - UNSUPPORTED_EXCHANGE_ALGORITHM: _Reasons - UNSUPPORTED_DIFFIE_HELLMAN: _Reasons - UNSUPPORTED_MAC: _Reasons diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/ocsp.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/ocsp.pyi deleted file mode 100644 index 103e96c..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/ocsp.pyi +++ /dev/null @@ -1,117 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import datetime -from collections.abc import Iterator - -from cryptography import x509 -from cryptography.hazmat.primitives import hashes, serialization -from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes -from cryptography.x509 import ocsp - -class OCSPRequest: - @property - def issuer_key_hash(self) -> bytes: ... - @property - def issuer_name_hash(self) -> bytes: ... - @property - def hash_algorithm(self) -> hashes.HashAlgorithm: ... - @property - def serial_number(self) -> int: ... - def public_bytes(self, encoding: serialization.Encoding) -> bytes: ... - @property - def extensions(self) -> x509.Extensions: ... - -class OCSPResponse: - @property - def responses(self) -> Iterator[OCSPSingleResponse]: ... - @property - def response_status(self) -> ocsp.OCSPResponseStatus: ... - @property - def signature_algorithm_oid(self) -> x509.ObjectIdentifier: ... - @property - def signature_hash_algorithm( - self, - ) -> hashes.HashAlgorithm | None: ... - @property - def signature(self) -> bytes: ... - @property - def tbs_response_bytes(self) -> bytes: ... - @property - def certificates(self) -> list[x509.Certificate]: ... - @property - def responder_key_hash(self) -> bytes | None: ... - @property - def responder_name(self) -> x509.Name | None: ... - @property - def produced_at(self) -> datetime.datetime: ... - @property - def produced_at_utc(self) -> datetime.datetime: ... - @property - def certificate_status(self) -> ocsp.OCSPCertStatus: ... - @property - def revocation_time(self) -> datetime.datetime | None: ... - @property - def revocation_time_utc(self) -> datetime.datetime | None: ... - @property - def revocation_reason(self) -> x509.ReasonFlags | None: ... - @property - def this_update(self) -> datetime.datetime: ... - @property - def this_update_utc(self) -> datetime.datetime: ... - @property - def next_update(self) -> datetime.datetime | None: ... - @property - def next_update_utc(self) -> datetime.datetime | None: ... - @property - def issuer_key_hash(self) -> bytes: ... - @property - def issuer_name_hash(self) -> bytes: ... - @property - def hash_algorithm(self) -> hashes.HashAlgorithm: ... - @property - def serial_number(self) -> int: ... - @property - def extensions(self) -> x509.Extensions: ... - @property - def single_extensions(self) -> x509.Extensions: ... - def public_bytes(self, encoding: serialization.Encoding) -> bytes: ... - -class OCSPSingleResponse: - @property - def certificate_status(self) -> ocsp.OCSPCertStatus: ... - @property - def revocation_time(self) -> datetime.datetime | None: ... - @property - def revocation_time_utc(self) -> datetime.datetime | None: ... - @property - def revocation_reason(self) -> x509.ReasonFlags | None: ... - @property - def this_update(self) -> datetime.datetime: ... - @property - def this_update_utc(self) -> datetime.datetime: ... - @property - def next_update(self) -> datetime.datetime | None: ... - @property - def next_update_utc(self) -> datetime.datetime | None: ... - @property - def issuer_key_hash(self) -> bytes: ... - @property - def issuer_name_hash(self) -> bytes: ... - @property - def hash_algorithm(self) -> hashes.HashAlgorithm: ... - @property - def serial_number(self) -> int: ... - -def load_der_ocsp_request(data: bytes) -> ocsp.OCSPRequest: ... -def load_der_ocsp_response(data: bytes) -> ocsp.OCSPResponse: ... -def create_ocsp_request( - builder: ocsp.OCSPRequestBuilder, -) -> ocsp.OCSPRequest: ... -def create_ocsp_response( - status: ocsp.OCSPResponseStatus, - builder: ocsp.OCSPResponseBuilder | None, - private_key: PrivateKeyTypes | None, - hash_algorithm: hashes.HashAlgorithm | None, -) -> ocsp.OCSPResponse: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi deleted file mode 100644 index 404a300..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi +++ /dev/null @@ -1,80 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing - -from cryptography.hazmat.bindings._rust.openssl import ( - aead, - ciphers, - cmac, - dh, - dsa, - ec, - ed448, - ed25519, - hashes, - hmac, - hpke, - kdf, - keys, - mldsa, - mlkem, - poly1305, - rsa, - x448, - x25519, -) - -__all__ = [ - "aead", - "ciphers", - "cmac", - "dh", - "dsa", - "ec", - "ed448", - "ed25519", - "hashes", - "hmac", - "hpke", - "kdf", - "keys", - "mldsa", - "mlkem", - "openssl_version", - "openssl_version_text", - "poly1305", - "raise_openssl_error", - "rsa", - "x448", - "x25519", -] - -CRYPTOGRAPHY_IS_LIBRESSL: bool -CRYPTOGRAPHY_IS_BORINGSSL: bool -CRYPTOGRAPHY_IS_AWSLC: bool -CRYPTOGRAPHY_OPENSSL_309_OR_GREATER: bool -CRYPTOGRAPHY_OPENSSL_320_OR_GREATER: bool -CRYPTOGRAPHY_OPENSSL_330_OR_GREATER: bool -CRYPTOGRAPHY_OPENSSL_350_OR_GREATER: bool - -class Providers: ... - -_legacy_provider_loaded: bool -_providers: Providers - -def openssl_version() -> int: ... -def openssl_version_text() -> str: ... -def raise_openssl_error() -> typing.NoReturn: ... -def capture_error_stack() -> list[OpenSSLError]: ... -def is_fips_enabled() -> bool: ... -def enable_fips(providers: Providers) -> None: ... - -class OpenSSLError: - @property - def lib(self) -> int: ... - @property - def reason(self) -> int: ... - @property - def reason_text(self) -> bytes: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/aead.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/aead.pyi deleted file mode 100644 index eb44608..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/aead.pyi +++ /dev/null @@ -1,189 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from collections.abc import Sequence - -from cryptography.utils import Buffer - -class AESGCM: - def __init__(self, key: Buffer) -> None: ... - @staticmethod - def generate_key(bit_length: int) -> bytes: ... - def encrypt( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - ) -> bytes: ... - def decrypt( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - ) -> bytes: ... - def encrypt_into( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - buf: Buffer, - ) -> int: ... - def decrypt_into( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - buf: Buffer, - ) -> int: ... - -class ChaCha20Poly1305: - def __init__(self, key: Buffer) -> None: ... - @staticmethod - def generate_key() -> bytes: ... - def encrypt( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - ) -> bytes: ... - def encrypt_into( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - buf: Buffer, - ) -> int: ... - def decrypt( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - ) -> bytes: ... - def decrypt_into( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - buf: Buffer, - ) -> int: ... - -class AESCCM: - def __init__(self, key: Buffer, tag_length: int = 16) -> None: ... - @staticmethod - def generate_key(bit_length: int) -> bytes: ... - def encrypt( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - ) -> bytes: ... - def encrypt_into( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - buf: Buffer, - ) -> int: ... - def decrypt( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - ) -> bytes: ... - def decrypt_into( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - buf: Buffer, - ) -> int: ... - -class AESSIV: - def __init__(self, key: Buffer) -> None: ... - @staticmethod - def generate_key(bit_length: int) -> bytes: ... - def encrypt( - self, - data: Buffer, - associated_data: Sequence[Buffer] | None, - ) -> bytes: ... - def encrypt_into( - self, - data: Buffer, - associated_data: Sequence[Buffer] | None, - buf: Buffer, - ) -> int: ... - def decrypt( - self, - data: Buffer, - associated_data: Sequence[Buffer] | None, - ) -> bytes: ... - def decrypt_into( - self, - data: Buffer, - associated_data: Sequence[Buffer] | None, - buf: Buffer, - ) -> int: ... - -class AESOCB3: - def __init__(self, key: Buffer) -> None: ... - @staticmethod - def generate_key(bit_length: int) -> bytes: ... - def encrypt( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - ) -> bytes: ... - def encrypt_into( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - buf: Buffer, - ) -> int: ... - def decrypt( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - ) -> bytes: ... - def decrypt_into( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - buf: Buffer, - ) -> int: ... - -class AESGCMSIV: - def __init__(self, key: Buffer) -> None: ... - @staticmethod - def generate_key(bit_length: int) -> bytes: ... - def encrypt( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - ) -> bytes: ... - def encrypt_into( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - buf: Buffer, - ) -> int: ... - def decrypt( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - ) -> bytes: ... - def decrypt_into( - self, - nonce: Buffer, - data: Buffer, - associated_data: Buffer | None, - buf: Buffer, - ) -> int: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ciphers.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ciphers.pyi deleted file mode 100644 index a48fb01..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ciphers.pyi +++ /dev/null @@ -1,38 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing - -from cryptography.hazmat.primitives import ciphers -from cryptography.hazmat.primitives.ciphers import modes - -@typing.overload -def create_encryption_ctx( - algorithm: ciphers.CipherAlgorithm, mode: modes.ModeWithAuthenticationTag -) -> ciphers.AEADEncryptionContext: ... -@typing.overload -def create_encryption_ctx( - algorithm: ciphers.CipherAlgorithm, mode: modes.Mode | None -) -> ciphers.CipherContext: ... -@typing.overload -def create_decryption_ctx( - algorithm: ciphers.CipherAlgorithm, mode: modes.ModeWithAuthenticationTag -) -> ciphers.AEADDecryptionContext: ... -@typing.overload -def create_decryption_ctx( - algorithm: ciphers.CipherAlgorithm, mode: modes.Mode | None -) -> ciphers.CipherContext: ... -def cipher_supported( - algorithm: ciphers.CipherAlgorithm, mode: modes.Mode -) -> bool: ... -def _advance( - ctx: ciphers.AEADEncryptionContext | ciphers.AEADDecryptionContext, n: int -) -> None: ... -def _advance_aad( - ctx: ciphers.AEADEncryptionContext | ciphers.AEADDecryptionContext, n: int -) -> None: ... - -class CipherContext: ... -class AEADEncryptionContext: ... -class AEADDecryptionContext: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/cmac.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/cmac.pyi deleted file mode 100644 index 9c03508..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/cmac.pyi +++ /dev/null @@ -1,18 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing - -from cryptography.hazmat.primitives import ciphers - -class CMAC: - def __init__( - self, - algorithm: ciphers.BlockCipherAlgorithm, - backend: typing.Any = None, - ) -> None: ... - def update(self, data: bytes) -> None: ... - def finalize(self) -> bytes: ... - def verify(self, signature: bytes) -> None: ... - def copy(self) -> CMAC: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/dh.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/dh.pyi deleted file mode 100644 index 08733d7..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/dh.pyi +++ /dev/null @@ -1,51 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing - -from cryptography.hazmat.primitives.asymmetric import dh - -MIN_MODULUS_SIZE: int - -class DHPrivateKey: ... -class DHPublicKey: ... -class DHParameters: ... - -class DHPrivateNumbers: - def __init__(self, x: int, public_numbers: DHPublicNumbers) -> None: ... - def private_key(self, backend: typing.Any = None) -> dh.DHPrivateKey: ... - @property - def x(self) -> int: ... - @property - def public_numbers(self) -> DHPublicNumbers: ... - -class DHPublicNumbers: - def __init__( - self, y: int, parameter_numbers: DHParameterNumbers - ) -> None: ... - def public_key(self, backend: typing.Any = None) -> dh.DHPublicKey: ... - @property - def y(self) -> int: ... - @property - def parameter_numbers(self) -> DHParameterNumbers: ... - -class DHParameterNumbers: - def __init__(self, p: int, g: int, q: int | None = None) -> None: ... - def parameters(self, backend: typing.Any = None) -> dh.DHParameters: ... - @property - def p(self) -> int: ... - @property - def g(self) -> int: ... - @property - def q(self) -> int | None: ... - -def generate_parameters( - generator: int, key_size: int, backend: typing.Any = None -) -> dh.DHParameters: ... -def from_pem_parameters( - data: bytes, backend: typing.Any = None -) -> dh.DHParameters: ... -def from_der_parameters( - data: bytes, backend: typing.Any = None -) -> dh.DHParameters: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/dsa.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/dsa.pyi deleted file mode 100644 index 0922a4c..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/dsa.pyi +++ /dev/null @@ -1,41 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing - -from cryptography.hazmat.primitives.asymmetric import dsa - -class DSAPrivateKey: ... -class DSAPublicKey: ... -class DSAParameters: ... - -class DSAPrivateNumbers: - def __init__(self, x: int, public_numbers: DSAPublicNumbers) -> None: ... - @property - def x(self) -> int: ... - @property - def public_numbers(self) -> DSAPublicNumbers: ... - def private_key(self, backend: typing.Any = None) -> dsa.DSAPrivateKey: ... - -class DSAPublicNumbers: - def __init__( - self, y: int, parameter_numbers: DSAParameterNumbers - ) -> None: ... - @property - def y(self) -> int: ... - @property - def parameter_numbers(self) -> DSAParameterNumbers: ... - def public_key(self, backend: typing.Any = None) -> dsa.DSAPublicKey: ... - -class DSAParameterNumbers: - def __init__(self, p: int, q: int, g: int) -> None: ... - @property - def p(self) -> int: ... - @property - def q(self) -> int: ... - @property - def g(self) -> int: ... - def parameters(self, backend: typing.Any = None) -> dsa.DSAParameters: ... - -def generate_parameters(key_size: int) -> dsa.DSAParameters: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ec.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ec.pyi deleted file mode 100644 index 5c3b7bf..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ec.pyi +++ /dev/null @@ -1,52 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing - -from cryptography.hazmat.primitives.asymmetric import ec - -class ECPrivateKey: ... -class ECPublicKey: ... - -class EllipticCurvePrivateNumbers: - def __init__( - self, private_value: int, public_numbers: EllipticCurvePublicNumbers - ) -> None: ... - def private_key( - self, backend: typing.Any = None - ) -> ec.EllipticCurvePrivateKey: ... - @property - def private_value(self) -> int: ... - @property - def public_numbers(self) -> EllipticCurvePublicNumbers: ... - -class EllipticCurvePublicNumbers: - def __init__(self, x: int, y: int, curve: ec.EllipticCurve) -> None: ... - def public_key( - self, backend: typing.Any = None - ) -> ec.EllipticCurvePublicKey: ... - @property - def x(self) -> int: ... - @property - def y(self) -> int: ... - @property - def curve(self) -> ec.EllipticCurve: ... - def __eq__(self, other: object) -> bool: ... - -def curve_supported(curve: ec.EllipticCurve) -> bool: ... -def generate_private_key( - curve: ec.EllipticCurve, backend: typing.Any = None -) -> ec.EllipticCurvePrivateKey: ... -def from_private_numbers( - numbers: ec.EllipticCurvePrivateNumbers, -) -> ec.EllipticCurvePrivateKey: ... -def from_public_numbers( - numbers: ec.EllipticCurvePublicNumbers, -) -> ec.EllipticCurvePublicKey: ... -def from_public_bytes( - curve: ec.EllipticCurve, data: bytes -) -> ec.EllipticCurvePublicKey: ... -def derive_private_key( - private_value: int, curve: ec.EllipticCurve -) -> ec.EllipticCurvePrivateKey: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi deleted file mode 100644 index f85b3d1..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed25519.pyi +++ /dev/null @@ -1,13 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from cryptography.hazmat.primitives.asymmetric import ed25519 -from cryptography.utils import Buffer - -class Ed25519PrivateKey: ... -class Ed25519PublicKey: ... - -def generate_key() -> ed25519.Ed25519PrivateKey: ... -def from_private_bytes(data: Buffer) -> ed25519.Ed25519PrivateKey: ... -def from_public_bytes(data: bytes) -> ed25519.Ed25519PublicKey: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed448.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed448.pyi deleted file mode 100644 index c8ca0ec..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/ed448.pyi +++ /dev/null @@ -1,13 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from cryptography.hazmat.primitives.asymmetric import ed448 -from cryptography.utils import Buffer - -class Ed448PrivateKey: ... -class Ed448PublicKey: ... - -def generate_key() -> ed448.Ed448PrivateKey: ... -def from_private_bytes(data: Buffer) -> ed448.Ed448PrivateKey: ... -def from_public_bytes(data: bytes) -> ed448.Ed448PublicKey: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hashes.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hashes.pyi deleted file mode 100644 index 106b531..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hashes.pyi +++ /dev/null @@ -1,30 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing - -from cryptography.hazmat.primitives import hashes -from cryptography.utils import Buffer - -class Hash(hashes.HashContext): - def __init__( - self, algorithm: hashes.HashAlgorithm, backend: typing.Any = None - ) -> None: ... - @property - def algorithm(self) -> hashes.HashAlgorithm: ... - def update(self, data: Buffer) -> None: ... - def finalize(self) -> bytes: ... - def copy(self) -> Hash: ... - @staticmethod - def hash(algorithm: hashes.HashAlgorithm, data: Buffer) -> bytes: ... - -def hash_supported(algorithm: hashes.HashAlgorithm) -> bool: ... - -class XOFHash: - def __init__(self, algorithm: hashes.ExtendableOutputFunction) -> None: ... - @property - def algorithm(self) -> hashes.ExtendableOutputFunction: ... - def update(self, data: Buffer) -> None: ... - def squeeze(self, length: int) -> bytes: ... - def copy(self) -> XOFHash: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hmac.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hmac.pyi deleted file mode 100644 index 3883d1b..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hmac.pyi +++ /dev/null @@ -1,22 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing - -from cryptography.hazmat.primitives import hashes -from cryptography.utils import Buffer - -class HMAC(hashes.HashContext): - def __init__( - self, - key: Buffer, - algorithm: hashes.HashAlgorithm, - backend: typing.Any = None, - ) -> None: ... - @property - def algorithm(self) -> hashes.HashAlgorithm: ... - def update(self, data: Buffer) -> None: ... - def finalize(self) -> bytes: ... - def verify(self, signature: bytes) -> None: ... - def copy(self) -> HMAC: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hpke.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hpke.pyi deleted file mode 100644 index a9d8a11..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/hpke.pyi +++ /dev/null @@ -1,108 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from cryptography.hazmat.primitives.asymmetric import ec, mlkem, x25519 -from cryptography.utils import Buffer - -class KEM: - X25519: KEM - P256: KEM - P384: KEM - P521: KEM - MLKEM768: KEM - MLKEM1024: KEM - MLKEM768_X25519: KEM - MLKEM1024_P384: KEM - -class KDF: - HKDF_SHA256: KDF - HKDF_SHA384: KDF - HKDF_SHA512: KDF - SHAKE128: KDF - SHAKE256: KDF - -class AEAD: - AES_128_GCM: AEAD - AES_256_GCM: AEAD - CHACHA20_POLY1305: AEAD - -class MLKEM768X25519PrivateKey: - def __init__( - self, - mlkem_key: mlkem.MLKEM768PrivateKey, - x25519_key: x25519.X25519PrivateKey, - ) -> None: ... - def public_key(self) -> MLKEM768X25519PublicKey: ... - -class MLKEM768X25519PublicKey: - def __init__( - self, - mlkem_key: mlkem.MLKEM768PublicKey, - x25519_key: x25519.X25519PublicKey, - ) -> None: ... - -class MLKEM1024P384PrivateKey: - def __init__( - self, - mlkem_key: mlkem.MLKEM1024PrivateKey, - p384_key: ec.EllipticCurvePrivateKey, - ) -> None: ... - def public_key(self) -> MLKEM1024P384PublicKey: ... - -class MLKEM1024P384PublicKey: - def __init__( - self, - mlkem_key: mlkem.MLKEM1024PublicKey, - p384_key: ec.EllipticCurvePublicKey, - ) -> None: ... - -class Suite: - def __init__(self, kem: KEM, kdf: KDF, aead: AEAD) -> None: ... - def encrypt( - self, - plaintext: Buffer, - public_key: x25519.X25519PublicKey - | ec.EllipticCurvePublicKey - | mlkem.MLKEM768PublicKey - | mlkem.MLKEM1024PublicKey - | MLKEM768X25519PublicKey - | MLKEM1024P384PublicKey, - info: Buffer | None = None, - ) -> bytes: ... - def decrypt( - self, - ciphertext: Buffer, - private_key: x25519.X25519PrivateKey - | ec.EllipticCurvePrivateKey - | mlkem.MLKEM768PrivateKey - | mlkem.MLKEM1024PrivateKey - | MLKEM768X25519PrivateKey - | MLKEM1024P384PrivateKey, - info: Buffer | None = None, - ) -> bytes: ... - -def _encrypt_with_aad( - suite: Suite, - plaintext: Buffer, - public_key: x25519.X25519PublicKey - | ec.EllipticCurvePublicKey - | mlkem.MLKEM768PublicKey - | mlkem.MLKEM1024PublicKey - | MLKEM768X25519PublicKey - | MLKEM1024P384PublicKey, - info: Buffer | None = None, - aad: Buffer | None = None, -) -> bytes: ... -def _decrypt_with_aad( - suite: Suite, - ciphertext: Buffer, - private_key: x25519.X25519PrivateKey - | ec.EllipticCurvePrivateKey - | mlkem.MLKEM768PrivateKey - | mlkem.MLKEM1024PrivateKey - | MLKEM768X25519PrivateKey - | MLKEM1024P384PrivateKey, - info: Buffer | None = None, - aad: Buffer | None = None, -) -> bytes: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/kdf.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/kdf.pyi deleted file mode 100644 index bb37b96..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/kdf.pyi +++ /dev/null @@ -1,205 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing - -from cryptography.hazmat.primitives.hashes import HashAlgorithm -from cryptography.hazmat.primitives.kdf.kbkdf import CounterLocation, Mode -from cryptography.utils import Buffer - -class PBKDF2HMAC: - def __init__( - self, - algorithm: HashAlgorithm, - length: int, - salt: bytes, - iterations: int, - backend: typing.Any = None, - ) -> None: ... - def derive(self, key_material: Buffer) -> bytes: ... - def derive_into(self, key_material: Buffer, buffer: Buffer) -> int: ... - def verify(self, key_material: bytes, expected_key: bytes) -> None: ... - -class Scrypt: - def __init__( - self, - salt: bytes, - length: int, - n: int, - r: int, - p: int, - backend: typing.Any = None, - ) -> None: ... - def derive(self, key_material: Buffer) -> bytes: ... - def derive_into(self, key_material: Buffer, buffer: Buffer) -> int: ... - def verify(self, key_material: bytes, expected_key: bytes) -> None: ... - -class Argon2d: - def __init__( - self, - *, - salt: bytes, - length: int, - iterations: int, - lanes: int, - memory_cost: int, - ad: bytes | None = None, - secret: bytes | None = None, - ) -> None: ... - def derive(self, key_material: bytes) -> bytes: ... - def derive_into(self, key_material: bytes, buffer: Buffer) -> int: ... - def verify(self, key_material: bytes, expected_key: bytes) -> None: ... - def derive_phc_encoded(self, key_material: bytes) -> str: ... - @classmethod - def verify_phc_encoded( - cls, key_material: bytes, phc_encoded: str, secret: bytes | None = None - ) -> None: ... - -class Argon2i: - def __init__( - self, - *, - salt: bytes, - length: int, - iterations: int, - lanes: int, - memory_cost: int, - ad: bytes | None = None, - secret: bytes | None = None, - ) -> None: ... - def derive(self, key_material: bytes) -> bytes: ... - def derive_into(self, key_material: bytes, buffer: Buffer) -> int: ... - def verify(self, key_material: bytes, expected_key: bytes) -> None: ... - def derive_phc_encoded(self, key_material: bytes) -> str: ... - @classmethod - def verify_phc_encoded( - cls, key_material: bytes, phc_encoded: str, secret: bytes | None = None - ) -> None: ... - -class Argon2id: - def __init__( - self, - *, - salt: bytes, - length: int, - iterations: int, - lanes: int, - memory_cost: int, - ad: bytes | None = None, - secret: bytes | None = None, - ) -> None: ... - def derive(self, key_material: bytes) -> bytes: ... - def derive_into(self, key_material: bytes, buffer: Buffer) -> int: ... - def verify(self, key_material: bytes, expected_key: bytes) -> None: ... - def derive_phc_encoded(self, key_material: bytes) -> str: ... - @classmethod - def verify_phc_encoded( - cls, key_material: bytes, phc_encoded: str, secret: bytes | None = None - ) -> None: ... - -class HKDF: - def __init__( - self, - algorithm: HashAlgorithm, - length: int, - salt: bytes | None, - info: bytes | None, - backend: typing.Any = None, - ): ... - @staticmethod - def extract( - algorithm: HashAlgorithm, salt: bytes | None, key_material: Buffer - ) -> bytes: ... - def derive(self, key_material: Buffer) -> bytes: ... - def derive_into(self, key_material: Buffer, buffer: Buffer) -> int: ... - def verify(self, key_material: bytes, expected_key: bytes) -> None: ... - -class HKDFExpand: - def __init__( - self, - algorithm: HashAlgorithm, - length: int, - info: bytes | None, - backend: typing.Any = None, - ): ... - def derive(self, key_material: Buffer) -> bytes: ... - def derive_into(self, key_material: Buffer, buffer: Buffer) -> int: ... - def verify(self, key_material: bytes, expected_key: bytes) -> None: ... - -class X963KDF: - def __init__( - self, - algorithm: HashAlgorithm, - length: int, - sharedinfo: bytes | None, - backend: typing.Any = None, - ) -> None: ... - def derive(self, key_material: Buffer) -> bytes: ... - def derive_into(self, key_material: Buffer, buffer: Buffer) -> int: ... - def verify(self, key_material: bytes, expected_key: bytes) -> None: ... - -class ConcatKDFHash: - def __init__( - self, - algorithm: HashAlgorithm, - length: int, - otherinfo: bytes | None, - backend: typing.Any = None, - ) -> None: ... - def derive(self, key_material: Buffer) -> bytes: ... - def derive_into(self, key_material: Buffer, buffer: Buffer) -> int: ... - def verify(self, key_material: bytes, expected_key: bytes) -> None: ... - -class ConcatKDFHMAC: - def __init__( - self, - algorithm: HashAlgorithm, - length: int, - salt: bytes | None, - otherinfo: bytes | None, - backend: typing.Any = None, - ) -> None: ... - def derive(self, key_material: Buffer) -> bytes: ... - def derive_into(self, key_material: Buffer, buffer: Buffer) -> int: ... - def verify(self, key_material: bytes, expected_key: bytes) -> None: ... - -class KBKDFHMAC: - def __init__( - self, - algorithm: HashAlgorithm, - mode: Mode, - length: int, - rlen: int, - llen: int | None, - location: CounterLocation, - label: bytes | None, - context: bytes | None, - fixed: bytes | None, - backend: typing.Any = None, - *, - break_location: int | None = None, - ) -> None: ... - def derive(self, key_material: Buffer) -> bytes: ... - def derive_into(self, key_material: Buffer, buffer: Buffer) -> int: ... - def verify(self, key_material: bytes, expected_key: bytes) -> None: ... - -class KBKDFCMAC: - def __init__( - self, - algorithm: typing.Any, - mode: Mode, - length: int, - rlen: int, - llen: int | None, - location: CounterLocation, - label: bytes | None, - context: bytes | None, - fixed: bytes | None, - backend: typing.Any = None, - *, - break_location: int | None = None, - ) -> None: ... - def derive(self, key_material: Buffer) -> bytes: ... - def derive_into(self, key_material: Buffer, buffer: Buffer) -> int: ... - def verify(self, key_material: bytes, expected_key: bytes) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/keys.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/keys.pyi deleted file mode 100644 index 404057e..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/keys.pyi +++ /dev/null @@ -1,34 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing - -from cryptography.hazmat.primitives.asymmetric.types import ( - PrivateKeyTypes, - PublicKeyTypes, -) -from cryptography.utils import Buffer - -def load_der_private_key( - data: Buffer, - password: bytes | None, - backend: typing.Any = None, - *, - unsafe_skip_rsa_key_validation: bool = False, -) -> PrivateKeyTypes: ... -def load_pem_private_key( - data: Buffer, - password: bytes | None, - backend: typing.Any = None, - *, - unsafe_skip_rsa_key_validation: bool = False, -) -> PrivateKeyTypes: ... -def load_der_public_key( - data: bytes, - backend: typing.Any = None, -) -> PublicKeyTypes: ... -def load_pem_public_key( - data: bytes, - backend: typing.Any = None, -) -> PublicKeyTypes: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/mldsa.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/mldsa.pyi deleted file mode 100644 index 232469a..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/mldsa.pyi +++ /dev/null @@ -1,23 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from cryptography.hazmat.primitives.asymmetric import mldsa -from cryptography.utils import Buffer - -class MLDSA44PrivateKey: ... -class MLDSA44PublicKey: ... -class MLDSA65PrivateKey: ... -class MLDSA65PublicKey: ... -class MLDSA87PrivateKey: ... -class MLDSA87PublicKey: ... - -def generate_mldsa44_key() -> mldsa.MLDSA44PrivateKey: ... -def from_mldsa44_public_bytes(data: bytes) -> mldsa.MLDSA44PublicKey: ... -def from_mldsa44_seed_bytes(data: Buffer) -> mldsa.MLDSA44PrivateKey: ... -def generate_mldsa65_key() -> mldsa.MLDSA65PrivateKey: ... -def from_mldsa65_public_bytes(data: bytes) -> mldsa.MLDSA65PublicKey: ... -def from_mldsa65_seed_bytes(data: Buffer) -> mldsa.MLDSA65PrivateKey: ... -def generate_mldsa87_key() -> mldsa.MLDSA87PrivateKey: ... -def from_mldsa87_public_bytes(data: bytes) -> mldsa.MLDSA87PublicKey: ... -def from_mldsa87_seed_bytes(data: Buffer) -> mldsa.MLDSA87PrivateKey: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/mlkem.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/mlkem.pyi deleted file mode 100644 index 768a340..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/mlkem.pyi +++ /dev/null @@ -1,18 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from cryptography.hazmat.primitives.asymmetric import mlkem -from cryptography.utils import Buffer - -class MLKEM768PrivateKey: ... -class MLKEM768PublicKey: ... -class MLKEM1024PrivateKey: ... -class MLKEM1024PublicKey: ... - -def generate_mlkem768_key() -> mlkem.MLKEM768PrivateKey: ... -def from_mlkem768_seed_bytes(data: Buffer) -> mlkem.MLKEM768PrivateKey: ... -def from_mlkem768_public_bytes(data: Buffer) -> mlkem.MLKEM768PublicKey: ... -def generate_mlkem1024_key() -> mlkem.MLKEM1024PrivateKey: ... -def from_mlkem1024_seed_bytes(data: Buffer) -> mlkem.MLKEM1024PrivateKey: ... -def from_mlkem1024_public_bytes(data: Buffer) -> mlkem.MLKEM1024PublicKey: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi deleted file mode 100644 index 45a2a39..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/poly1305.pyi +++ /dev/null @@ -1,15 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from cryptography.utils import Buffer - -class Poly1305: - def __init__(self, key: Buffer) -> None: ... - @staticmethod - def generate_tag(key: Buffer, data: Buffer) -> bytes: ... - @staticmethod - def verify_tag(key: Buffer, data: Buffer, tag: bytes) -> None: ... - def update(self, data: Buffer) -> None: ... - def finalize(self) -> bytes: ... - def verify(self, tag: bytes) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/rsa.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/rsa.pyi deleted file mode 100644 index ef7752d..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/rsa.pyi +++ /dev/null @@ -1,55 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing - -from cryptography.hazmat.primitives.asymmetric import rsa - -class RSAPrivateKey: ... -class RSAPublicKey: ... - -class RSAPrivateNumbers: - def __init__( - self, - p: int, - q: int, - d: int, - dmp1: int, - dmq1: int, - iqmp: int, - public_numbers: RSAPublicNumbers, - ) -> None: ... - @property - def p(self) -> int: ... - @property - def q(self) -> int: ... - @property - def d(self) -> int: ... - @property - def dmp1(self) -> int: ... - @property - def dmq1(self) -> int: ... - @property - def iqmp(self) -> int: ... - @property - def public_numbers(self) -> RSAPublicNumbers: ... - def private_key( - self, - backend: typing.Any = None, - *, - unsafe_skip_rsa_key_validation: bool = False, - ) -> rsa.RSAPrivateKey: ... - -class RSAPublicNumbers: - def __init__(self, e: int, n: int) -> None: ... - @property - def n(self) -> int: ... - @property - def e(self) -> int: ... - def public_key(self, backend: typing.Any = None) -> rsa.RSAPublicKey: ... - -def generate_private_key( - public_exponent: int, - key_size: int, -) -> rsa.RSAPrivateKey: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/x25519.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/x25519.pyi deleted file mode 100644 index 38d2add..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/x25519.pyi +++ /dev/null @@ -1,13 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from cryptography.hazmat.primitives.asymmetric import x25519 -from cryptography.utils import Buffer - -class X25519PrivateKey: ... -class X25519PublicKey: ... - -def generate_key() -> x25519.X25519PrivateKey: ... -def from_private_bytes(data: Buffer) -> x25519.X25519PrivateKey: ... -def from_public_bytes(data: bytes) -> x25519.X25519PublicKey: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/x448.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/x448.pyi deleted file mode 100644 index 3ac0980..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/openssl/x448.pyi +++ /dev/null @@ -1,13 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from cryptography.hazmat.primitives.asymmetric import x448 -from cryptography.utils import Buffer - -class X448PrivateKey: ... -class X448PublicKey: ... - -def generate_key() -> x448.X448PrivateKey: ... -def from_private_bytes(data: Buffer) -> x448.X448PrivateKey: ... -def from_public_bytes(data: bytes) -> x448.X448PublicKey: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/pkcs12.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/pkcs12.pyi deleted file mode 100644 index b25becb..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/pkcs12.pyi +++ /dev/null @@ -1,52 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import typing -from collections.abc import Iterable - -from cryptography import x509 -from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes -from cryptography.hazmat.primitives.serialization import ( - KeySerializationEncryption, -) -from cryptography.hazmat.primitives.serialization.pkcs12 import ( - PKCS12KeyAndCertificates, - PKCS12PrivateKeyTypes, -) -from cryptography.utils import Buffer - -class PKCS12Certificate: - def __init__( - self, cert: x509.Certificate, friendly_name: bytes | None - ) -> None: ... - @property - def friendly_name(self) -> bytes | None: ... - @property - def certificate(self) -> x509.Certificate: ... - -def load_key_and_certificates( - data: Buffer, - password: Buffer | None, - backend: typing.Any = None, -) -> tuple[ - PrivateKeyTypes | None, - x509.Certificate | None, - list[x509.Certificate], -]: ... -def load_pkcs12( - data: bytes, - password: bytes | None, - backend: typing.Any = None, -) -> PKCS12KeyAndCertificates: ... -def serialize_java_truststore( - certs: Iterable[PKCS12Certificate], - encryption_algorithm: KeySerializationEncryption, -) -> bytes: ... -def serialize_key_and_certificates( - name: bytes | None, - key: PKCS12PrivateKeyTypes | None, - cert: x509.Certificate | None, - cas: Iterable[x509.Certificate | PKCS12Certificate] | None, - encryption_algorithm: KeySerializationEncryption, -) -> bytes: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/pkcs7.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/pkcs7.pyi deleted file mode 100644 index 358b135..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/pkcs7.pyi +++ /dev/null @@ -1,50 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from collections.abc import Iterable - -from cryptography import x509 -from cryptography.hazmat.primitives import serialization -from cryptography.hazmat.primitives.asymmetric import rsa -from cryptography.hazmat.primitives.serialization import pkcs7 - -def serialize_certificates( - certs: list[x509.Certificate], - encoding: serialization.Encoding, -) -> bytes: ... -def encrypt_and_serialize( - builder: pkcs7.PKCS7EnvelopeBuilder, - content_encryption_algorithm: pkcs7.ContentEncryptionAlgorithm, - encoding: serialization.Encoding, - options: Iterable[pkcs7.PKCS7Options], -) -> bytes: ... -def sign_and_serialize( - builder: pkcs7.PKCS7SignatureBuilder, - encoding: serialization.Encoding, - options: Iterable[pkcs7.PKCS7Options], -) -> bytes: ... -def decrypt_der( - data: bytes, - certificate: x509.Certificate, - private_key: rsa.RSAPrivateKey, - options: Iterable[pkcs7.PKCS7Options], -) -> bytes: ... -def decrypt_pem( - data: bytes, - certificate: x509.Certificate, - private_key: rsa.RSAPrivateKey, - options: Iterable[pkcs7.PKCS7Options], -) -> bytes: ... -def decrypt_smime( - data: bytes, - certificate: x509.Certificate, - private_key: rsa.RSAPrivateKey, - options: Iterable[pkcs7.PKCS7Options], -) -> bytes: ... -def load_pem_pkcs7_certificates( - data: bytes, -) -> list[x509.Certificate]: ... -def load_der_pkcs7_certificates( - data: bytes, -) -> list[x509.Certificate]: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/test_support.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/test_support.pyi deleted file mode 100644 index c6c6d0b..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/test_support.pyi +++ /dev/null @@ -1,23 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from cryptography import x509 -from cryptography.hazmat.primitives import serialization -from cryptography.hazmat.primitives.serialization import pkcs7 -from cryptography.utils import Buffer - -class TestCertificate: - not_after_tag: int - not_before_tag: int - issuer_value_tags: list[int] - subject_value_tags: list[int] - -def test_parse_certificate(data: bytes) -> TestCertificate: ... -def pkcs7_verify( - encoding: serialization.Encoding, - sig: bytes, - msg: Buffer | None, - certs: list[x509.Certificate], - options: list[pkcs7.PKCS7Options], -) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/x509.pyi b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/x509.pyi deleted file mode 100644 index 196a3c6..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/_rust/x509.pyi +++ /dev/null @@ -1,312 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -import datetime -import typing -from collections.abc import Iterator - -from cryptography import x509 -from cryptography.hazmat.primitives import hashes, serialization -from cryptography.hazmat.primitives.asymmetric.ec import ECDSA -from cryptography.hazmat.primitives.asymmetric.padding import PSS, PKCS1v15 -from cryptography.hazmat.primitives.asymmetric.types import ( - CertificateIssuerPublicKeyTypes, - CertificatePublicKeyTypes, - PrivateKeyTypes, -) -from cryptography.x509 import certificate_transparency - -def load_pem_x509_certificate( - data: bytes, backend: typing.Any = None -) -> x509.Certificate: ... -def load_der_x509_certificate( - data: bytes, backend: typing.Any = None -) -> x509.Certificate: ... -def load_pem_x509_certificates( - data: bytes, -) -> list[x509.Certificate]: ... -def load_pem_x509_crl( - data: bytes, backend: typing.Any = None -) -> x509.CertificateRevocationList: ... -def load_der_x509_crl( - data: bytes, backend: typing.Any = None -) -> x509.CertificateRevocationList: ... -def load_pem_x509_csr( - data: bytes, backend: typing.Any = None -) -> x509.CertificateSigningRequest: ... -def load_der_x509_csr( - data: bytes, backend: typing.Any = None -) -> x509.CertificateSigningRequest: ... -def encode_name_bytes(name: x509.Name) -> bytes: ... -def encode_extension_value(extension: x509.ExtensionType) -> bytes: ... -def create_x509_certificate( - builder: x509.CertificateBuilder, - private_key: PrivateKeyTypes, - hash_algorithm: hashes.HashAlgorithm | None, - rsa_padding: PKCS1v15 | PSS | None, - ecdsa_deterministic: bool | None, -) -> x509.Certificate: ... -def create_x509_csr( - builder: x509.CertificateSigningRequestBuilder, - private_key: PrivateKeyTypes, - hash_algorithm: hashes.HashAlgorithm | None, - rsa_padding: PKCS1v15 | PSS | None, - ecdsa_deterministic: bool | None, -) -> x509.CertificateSigningRequest: ... -def create_revoked_certificate( - builder: x509.RevokedCertificateBuilder, -) -> x509.RevokedCertificate: ... -def create_x509_crl( - builder: x509.CertificateRevocationListBuilder, - private_key: PrivateKeyTypes, - hash_algorithm: hashes.HashAlgorithm | None, - rsa_padding: PKCS1v15 | PSS | None, - ecdsa_deterministic: bool | None, -) -> x509.CertificateRevocationList: ... - -class Sct: - @property - def version(self) -> certificate_transparency.Version: ... - @property - def log_id(self) -> bytes: ... - @property - def timestamp(self) -> datetime.datetime: ... - @property - def entry_type(self) -> certificate_transparency.LogEntryType: ... - @property - def signature_hash_algorithm(self) -> hashes.HashAlgorithm: ... - @property - def signature_algorithm( - self, - ) -> certificate_transparency.SignatureAlgorithm: ... - @property - def signature(self) -> bytes: ... - @property - def extension_bytes(self) -> bytes: ... - -class Certificate: - def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes: ... - @property - def serial_number(self) -> int: ... - @property - def version(self) -> x509.Version: ... - def public_key(self) -> CertificatePublicKeyTypes: ... - @property - def public_key_algorithm_oid(self) -> x509.ObjectIdentifier: ... - @property - def not_valid_before(self) -> datetime.datetime: ... - @property - def not_valid_before_utc(self) -> datetime.datetime: ... - @property - def not_valid_after(self) -> datetime.datetime: ... - @property - def not_valid_after_utc(self) -> datetime.datetime: ... - @property - def issuer(self) -> x509.Name: ... - @property - def subject(self) -> x509.Name: ... - @property - def signature_hash_algorithm( - self, - ) -> hashes.HashAlgorithm | None: ... - @property - def signature_algorithm_oid(self) -> x509.ObjectIdentifier: ... - @property - def signature_algorithm_parameters( - self, - ) -> PSS | PKCS1v15 | ECDSA | None: ... - @property - def extensions(self) -> x509.Extensions: ... - @property - def signature(self) -> bytes: ... - @property - def tbs_certificate_bytes(self) -> bytes: ... - @property - def tbs_precertificate_bytes(self) -> bytes: ... - def __eq__(self, other: object) -> bool: ... - def __hash__(self) -> int: ... - def public_bytes(self, encoding: serialization.Encoding) -> bytes: ... - def verify_directly_issued_by(self, issuer: Certificate) -> None: ... - -class RevokedCertificate: - @property - def serial_number(self) -> int: ... - @property - def revocation_date(self) -> datetime.datetime: ... - @property - def revocation_date_utc(self) -> datetime.datetime: ... - @property - def extensions(self) -> x509.Extensions: ... - -class CertificateRevocationList: - def public_bytes(self, encoding: serialization.Encoding) -> bytes: ... - def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes: ... - def get_revoked_certificate_by_serial_number( - self, serial_number: int - ) -> x509.RevokedCertificate | None: ... - @property - def signature_hash_algorithm( - self, - ) -> hashes.HashAlgorithm | None: ... - @property - def signature_algorithm_oid(self) -> x509.ObjectIdentifier: ... - @property - def signature_algorithm_parameters( - self, - ) -> PSS | PKCS1v15 | ECDSA | None: ... - @property - def issuer(self) -> x509.Name: ... - @property - def next_update(self) -> datetime.datetime | None: ... - @property - def next_update_utc(self) -> datetime.datetime | None: ... - @property - def last_update(self) -> datetime.datetime: ... - @property - def last_update_utc(self) -> datetime.datetime: ... - @property - def extensions(self) -> x509.Extensions: ... - @property - def signature(self) -> bytes: ... - @property - def tbs_certlist_bytes(self) -> bytes: ... - def __eq__(self, other: object) -> bool: ... - def __len__(self) -> int: ... - @typing.overload - def __getitem__(self, idx: int) -> x509.RevokedCertificate: ... - @typing.overload - def __getitem__(self, idx: slice) -> list[x509.RevokedCertificate]: ... - def __iter__(self) -> Iterator[x509.RevokedCertificate]: ... - def is_signature_valid( - self, public_key: CertificateIssuerPublicKeyTypes - ) -> bool: ... - -class CertificateSigningRequest: - def __eq__(self, other: object) -> bool: ... - def __hash__(self) -> int: ... - def public_key(self) -> CertificatePublicKeyTypes: ... - @property - def subject(self) -> x509.Name: ... - @property - def signature_hash_algorithm( - self, - ) -> hashes.HashAlgorithm | None: ... - @property - def signature_algorithm_oid(self) -> x509.ObjectIdentifier: ... - @property - def signature_algorithm_parameters( - self, - ) -> PSS | PKCS1v15 | ECDSA | None: ... - @property - def extensions(self) -> x509.Extensions: ... - @property - def attributes(self) -> x509.Attributes: ... - def public_bytes(self, encoding: serialization.Encoding) -> bytes: ... - @property - def signature(self) -> bytes: ... - @property - def tbs_certrequest_bytes(self) -> bytes: ... - @property - def is_signature_valid(self) -> bool: ... - -class PolicyBuilder: - def time(self, time: datetime.datetime) -> PolicyBuilder: ... - def store(self, store: Store) -> PolicyBuilder: ... - def max_chain_depth(self, max_chain_depth: int) -> PolicyBuilder: ... - def extension_policies( - self, *, ca_policy: ExtensionPolicy, ee_policy: ExtensionPolicy - ) -> PolicyBuilder: ... - def build_client_verifier(self) -> ClientVerifier: ... - def build_server_verifier( - self, subject: x509.verification.Subject - ) -> ServerVerifier: ... - -class Policy: - @property - def max_chain_depth(self) -> int: ... - @property - def subject(self) -> x509.verification.Subject | None: ... - @property - def validation_time(self) -> datetime.datetime: ... - @property - def extended_key_usage(self) -> x509.ObjectIdentifier: ... - @property - def minimum_rsa_modulus(self) -> int: ... - -class Criticality: - CRITICAL: Criticality - AGNOSTIC: Criticality - NON_CRITICAL: Criticality - -T = typing.TypeVar("T", contravariant=True, bound=x509.ExtensionType) - -MaybeExtensionValidatorCallback = typing.Callable[ - [ - Policy, - x509.Certificate, - T | None, - ], - None, -] - -PresentExtensionValidatorCallback = typing.Callable[ - [Policy, x509.Certificate, T], - None, -] - -class ExtensionPolicy: - @staticmethod - def permit_all() -> ExtensionPolicy: ... - @staticmethod - def webpki_defaults_ca() -> ExtensionPolicy: ... - @staticmethod - def webpki_defaults_ee() -> ExtensionPolicy: ... - def require_not_present( - self, extension_type: type[x509.ExtensionType] - ) -> ExtensionPolicy: ... - def may_be_present( - self, - extension_type: type[T], - criticality: Criticality, - validator: MaybeExtensionValidatorCallback[T] | None, - ) -> ExtensionPolicy: ... - def require_present( - self, - extension_type: type[T], - criticality: Criticality, - validator: PresentExtensionValidatorCallback[T] | None, - ) -> ExtensionPolicy: ... - -class VerifiedClient: - @property - def subjects(self) -> list[x509.GeneralName] | None: ... - @property - def chain(self) -> list[x509.Certificate]: ... - -class ClientVerifier: - @property - def policy(self) -> Policy: ... - @property - def store(self) -> Store: ... - def verify( - self, - leaf: x509.Certificate, - intermediates: list[x509.Certificate], - ) -> VerifiedClient: ... - -class ServerVerifier: - @property - def policy(self) -> Policy: ... - @property - def store(self) -> Store: ... - def verify( - self, - leaf: x509.Certificate, - intermediates: list[x509.Certificate], - ) -> list[x509.Certificate]: ... - -class Store: - def __init__(self, certs: list[x509.Certificate]) -> None: ... - -class VerificationError(Exception): ... diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__init__.py deleted file mode 100644 index b509336..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 2982a53..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-312.pyc deleted file mode 100644 index 9fa9d91..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-312.pyc deleted file mode 100644 index 6b94911..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py deleted file mode 100644 index 1e447a5..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/_conditional.py +++ /dev/null @@ -1,199 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - - -def cryptography_has_set_cert_cb() -> list[str]: - return [ - "SSL_CTX_set_cert_cb", - "SSL_set_cert_cb", - ] - - -def cryptography_has_ssl_st() -> list[str]: - return [ - "SSL_ST_BEFORE", - "SSL_ST_OK", - "SSL_ST_INIT", - "SSL_ST_RENEGOTIATE", - ] - - -def cryptography_has_tls_st() -> list[str]: - return [ - "TLS_ST_BEFORE", - "TLS_ST_OK", - ] - - -def cryptography_has_ssl_sigalgs() -> list[str]: - return [ - "SSL_CTX_set1_sigalgs_list", - ] - - -def cryptography_has_psk() -> list[str]: - return [ - "SSL_CTX_use_psk_identity_hint", - "SSL_CTX_set_psk_server_callback", - "SSL_CTX_set_psk_client_callback", - ] - - -def cryptography_has_psk_tlsv13() -> list[str]: - return [ - "SSL_CTX_set_psk_find_session_callback", - "SSL_CTX_set_psk_use_session_callback", - "Cryptography_SSL_SESSION_new", - "SSL_CIPHER_find", - "SSL_SESSION_set1_master_key", - "SSL_SESSION_set_cipher", - "SSL_SESSION_set_protocol_version", - ] - - -def cryptography_has_custom_ext() -> list[str]: - return [ - "SSL_CTX_add_client_custom_ext", - "SSL_CTX_add_server_custom_ext", - "SSL_extension_supported", - ] - - -def cryptography_has_tlsv13_functions() -> list[str]: - return [ - "SSL_CTX_set_ciphersuites", - ] - - -def cryptography_has_tlsv13_hs_functions() -> list[str]: - return [ - "SSL_VERIFY_POST_HANDSHAKE", - "SSL_verify_client_post_handshake", - "SSL_CTX_set_post_handshake_auth", - "SSL_set_post_handshake_auth", - "SSL_SESSION_get_max_early_data", - "SSL_write_early_data", - "SSL_read_early_data", - "SSL_CTX_set_max_early_data", - ] - - -def cryptography_has_ssl_verify_client_post_handshake() -> list[str]: - return [ - "SSL_verify_client_post_handshake", - ] - - -def cryptography_has_engine() -> list[str]: - return [ - "ENGINE_by_id", - "ENGINE_init", - "ENGINE_finish", - "ENGINE_get_default_RAND", - "ENGINE_set_default_RAND", - "ENGINE_unregister_RAND", - "ENGINE_ctrl_cmd", - "ENGINE_free", - "ENGINE_get_name", - "ENGINE_ctrl_cmd_string", - "ENGINE_load_builtin_engines", - "ENGINE_load_private_key", - "ENGINE_load_public_key", - "SSL_CTX_set_client_cert_engine", - ] - - -def cryptography_has_verified_chain() -> list[str]: - return [ - "SSL_get0_verified_chain", - ] - - -def cryptography_has_srtp() -> list[str]: - return [ - "SSL_CTX_set_tlsext_use_srtp", - "SSL_set_tlsext_use_srtp", - "SSL_get_selected_srtp_profile", - ] - - -def cryptography_has_dtls_get_data_mtu() -> list[str]: - return [ - "DTLS_get_data_mtu", - ] - - -def cryptography_has_ssl_cookie() -> list[str]: - return [ - "SSL_OP_COOKIE_EXCHANGE", - "DTLS1_COOKIE_LENGTH", - "DTLSv1_listen", - "SSL_CTX_set_cookie_generate_cb", - "SSL_CTX_set_cookie_verify_cb", - ] - - -def cryptography_has_prime_checks() -> list[str]: - return [ - "BN_prime_checks_for_size", - ] - - -def cryptography_has_unexpected_eof_while_reading() -> list[str]: - return ["SSL_R_UNEXPECTED_EOF_WHILE_READING"] - - -def cryptography_has_ssl_op_ignore_unexpected_eof() -> list[str]: - return [ - "SSL_OP_IGNORE_UNEXPECTED_EOF", - ] - - -def cryptography_has_get_extms_support() -> list[str]: - return ["SSL_get_extms_support"] - - -def cryptography_has_ssl_get0_group_name() -> list[str]: - return ["SSL_get0_group_name"] - - -# This is a mapping of -# {condition: function-returning-names-dependent-on-that-condition} so we can -# loop over them and delete unsupported names at runtime. It will be removed -# when cffi supports #if in cdef. We use functions instead of just a dict of -# lists so we can use coverage to measure which are used. -CONDITIONAL_NAMES = { - "Cryptography_HAS_SET_CERT_CB": cryptography_has_set_cert_cb, - "Cryptography_HAS_SSL_ST": cryptography_has_ssl_st, - "Cryptography_HAS_TLS_ST": cryptography_has_tls_st, - "Cryptography_HAS_SIGALGS": cryptography_has_ssl_sigalgs, - "Cryptography_HAS_PSK": cryptography_has_psk, - "Cryptography_HAS_PSK_TLSv1_3": cryptography_has_psk_tlsv13, - "Cryptography_HAS_CUSTOM_EXT": cryptography_has_custom_ext, - "Cryptography_HAS_TLSv1_3_FUNCTIONS": cryptography_has_tlsv13_functions, - "Cryptography_HAS_TLSv1_3_HS_FUNCTIONS": ( - cryptography_has_tlsv13_hs_functions - ), - "Cryptography_HAS_SSL_VERIFY_CLIENT_POST_HANDSHAKE": ( - cryptography_has_ssl_verify_client_post_handshake - ), - "Cryptography_HAS_ENGINE": cryptography_has_engine, - "Cryptography_HAS_VERIFIED_CHAIN": cryptography_has_verified_chain, - "Cryptography_HAS_SRTP": cryptography_has_srtp, - "Cryptography_HAS_DTLS_GET_DATA_MTU": cryptography_has_dtls_get_data_mtu, - "Cryptography_HAS_SSL_COOKIE": cryptography_has_ssl_cookie, - "Cryptography_HAS_PRIME_CHECKS": cryptography_has_prime_checks, - "Cryptography_HAS_UNEXPECTED_EOF_WHILE_READING": ( - cryptography_has_unexpected_eof_while_reading - ), - "Cryptography_HAS_SSL_OP_IGNORE_UNEXPECTED_EOF": ( - cryptography_has_ssl_op_ignore_unexpected_eof - ), - "Cryptography_HAS_GET_EXTMS_SUPPORT": cryptography_has_get_extms_support, - "Cryptography_HAS_SSL_GET0_GROUP_NAME": ( - cryptography_has_ssl_get0_group_name - ), -} diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/binding.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/binding.py deleted file mode 100644 index 6a0cafd..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/bindings/openssl/binding.py +++ /dev/null @@ -1,122 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import os -import sys -import threading -import types -import typing -import warnings -from collections.abc import Callable - -import cryptography -from cryptography.exceptions import InternalError -from cryptography.hazmat.bindings._rust import _openssl, openssl -from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES - - -def _openssl_assert(ok: bool) -> None: - if not ok: - errors = openssl.capture_error_stack() - - raise InternalError( - "Unknown OpenSSL error. This error is commonly encountered when " - "another library is not cleaning up the OpenSSL error stack. If " - "you are using cryptography with another library that uses " - "OpenSSL try disabling it before reporting a bug. Otherwise " - "please file an issue at https://github.com/pyca/cryptography/" - "issues with information on how to reproduce " - f"this. ({errors!r})", - errors, - ) - - -def build_conditional_library( - lib: typing.Any, - conditional_names: dict[str, Callable[[], list[str]]], -) -> typing.Any: - conditional_lib = types.ModuleType("lib") - conditional_lib._original_lib = lib # type: ignore[attr-defined] - excluded_names = set() - for condition, names_cb in conditional_names.items(): - if not getattr(lib, condition): - excluded_names.update(names_cb()) - - for attr in dir(lib): - if attr not in excluded_names: - setattr(conditional_lib, attr, getattr(lib, attr)) - - return conditional_lib - - -class Binding: - """ - OpenSSL API wrapper. - """ - - lib: typing.ClassVar[typing.Any] = None - ffi: typing.Any = _openssl.ffi - _lib_loaded = False - _init_lock = threading.Lock() - - def __init__(self) -> None: - self._ensure_ffi_initialized() - - @classmethod - def _ensure_ffi_initialized(cls) -> None: - with cls._init_lock: - if not cls._lib_loaded: - cls.lib = build_conditional_library( - _openssl.lib, CONDITIONAL_NAMES - ) - cls._lib_loaded = True - - @classmethod - def init_static_locks(cls) -> None: - cls._ensure_ffi_initialized() - - -def _verify_package_version(version: str) -> None: - # Occasionally we run into situations where the version of the Python - # package does not match the version of the shared object that is loaded. - # This may occur in environments where multiple versions of cryptography - # are installed and available in the python path. To avoid errors cropping - # up later this code checks that the currently imported package and the - # shared object that were loaded have the same version and raise an - # ImportError if they do not - so_package_version = _openssl.ffi.string( - _openssl.lib.CRYPTOGRAPHY_PACKAGE_VERSION - ) - if version.encode("ascii") != so_package_version: - raise ImportError( - "The version of cryptography does not match the loaded " - "shared object. This can happen if you have multiple copies of " - "cryptography installed in your Python path. Please try creating " - "a new virtual environment to resolve this issue. " - f"Loaded python version: {version}, " - f"shared object version: {so_package_version}" - ) - - _openssl_assert( - _openssl.lib.OpenSSL_version_num() == openssl.openssl_version(), - ) - - -_verify_package_version(cryptography.__version__) - -Binding.init_static_locks() - -if ( - sys.platform == "win32" - and os.environ.get("PROCESSOR_ARCHITEW6432") is not None -): - warnings.warn( - "You are using cryptography on a 32-bit Python on a 64-bit Windows " - "Operating System. Cryptography will be significantly faster if you " - "switch to using a 64-bit Python.", - UserWarning, - stacklevel=2, - ) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/__init__.py deleted file mode 100644 index 41d7318..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 2544892..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/__init__.py deleted file mode 100644 index 41d7318..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index b255f1a..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/__pycache__/algorithms.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/__pycache__/algorithms.cpython-312.pyc deleted file mode 100644 index 9733c09..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/__pycache__/algorithms.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/__pycache__/modes.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/__pycache__/modes.cpython-312.pyc deleted file mode 100644 index 45a6d03..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/__pycache__/modes.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/algorithms.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/algorithms.py deleted file mode 100644 index 703c8e4..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/algorithms.py +++ /dev/null @@ -1,142 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import warnings - -from cryptography import utils -from cryptography.hazmat.primitives._cipheralgorithm import ( - BlockCipherAlgorithm, - CipherAlgorithm, - _verify_key_size, -) - - -class ARC4(CipherAlgorithm): - name = "RC4" - key_sizes = frozenset([40, 56, 64, 80, 128, 160, 192, 256]) - - def __init__(self, key: bytes): - self.key = _verify_key_size(self, key) - - @property - def key_size(self) -> int: - return len(self.key) * 8 - - -class TripleDES(BlockCipherAlgorithm): - name = "3DES" - block_size = 64 - key_sizes = frozenset([64, 128, 192]) - - def __init__(self, key: bytes): - if len(key) == 8: - warnings.warn( - "Single-key TripleDES (8-byte keys) is deprecated and " - "support will be removed in a future release. Use 24-byte " - "keys instead (e.g., key + key + key).", - utils.DeprecatedIn47, - stacklevel=2, - ) - key = key + key + key - elif len(key) == 16: - warnings.warn( - "Two-key TripleDES (16-byte keys) is deprecated and " - "support will be removed in a future release. Use 24-byte " - "keys instead (e.g., key + key[:8]).", - utils.DeprecatedIn47, - stacklevel=2, - ) - key = key + key[:8] - self.key = _verify_key_size(self, key) - - @property - def key_size(self) -> int: - return len(self.key) * 8 - - -# Not actually supported, marker for tests -class _DES: - key_size = 64 - - -class Blowfish(BlockCipherAlgorithm): - name = "Blowfish" - block_size = 64 - key_sizes = frozenset(range(32, 449, 8)) - - def __init__(self, key: bytes): - self.key = _verify_key_size(self, key) - - @property - def key_size(self) -> int: - return len(self.key) * 8 - - -class CAST5(BlockCipherAlgorithm): - name = "CAST5" - block_size = 64 - key_sizes = frozenset(range(40, 129, 8)) - - def __init__(self, key: bytes): - self.key = _verify_key_size(self, key) - - @property - def key_size(self) -> int: - return len(self.key) * 8 - - -class SEED(BlockCipherAlgorithm): - name = "SEED" - block_size = 128 - key_sizes = frozenset([128]) - - def __init__(self, key: bytes): - self.key = _verify_key_size(self, key) - - @property - def key_size(self) -> int: - return len(self.key) * 8 - - -class IDEA(BlockCipherAlgorithm): - name = "IDEA" - block_size = 64 - key_sizes = frozenset([128]) - - def __init__(self, key: bytes): - self.key = _verify_key_size(self, key) - - @property - def key_size(self) -> int: - return len(self.key) * 8 - - -class Camellia(BlockCipherAlgorithm): - name = "camellia" - block_size = 128 - key_sizes = frozenset([128, 192, 256]) - - def __init__(self, key: bytes): - self.key = _verify_key_size(self, key) - - @property - def key_size(self) -> int: - return len(self.key) * 8 - - -# This class only allows RC2 with a 128-bit key. No support for -# effective key bits or other key sizes is provided. -class RC2(BlockCipherAlgorithm): - name = "RC2" - block_size = 64 - key_sizes = frozenset([128]) - - def __init__(self, key: bytes): - self.key = _verify_key_size(self, key) - - @property - def key_size(self) -> int: - return len(self.key) * 8 diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/modes.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/modes.py deleted file mode 100644 index 1786bb0..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/decrepit/ciphers/modes.py +++ /dev/null @@ -1,53 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography import utils -from cryptography.hazmat.primitives._modes import ( - ModeWithInitializationVector, - _check_iv_and_key_length, -) - - -class OFB(ModeWithInitializationVector): - name = "OFB" - - def __init__(self, initialization_vector: utils.Buffer): - utils._check_byteslike("initialization_vector", initialization_vector) - self._initialization_vector = initialization_vector - - @property - def initialization_vector(self) -> utils.Buffer: - return self._initialization_vector - - validate_for_algorithm = _check_iv_and_key_length - - -class CFB(ModeWithInitializationVector): - name = "CFB" - - def __init__(self, initialization_vector: utils.Buffer): - utils._check_byteslike("initialization_vector", initialization_vector) - self._initialization_vector = initialization_vector - - @property - def initialization_vector(self) -> utils.Buffer: - return self._initialization_vector - - validate_for_algorithm = _check_iv_and_key_length - - -class CFB8(ModeWithInitializationVector): - name = "CFB8" - - def __init__(self, initialization_vector: utils.Buffer): - utils._check_byteslike("initialization_vector", initialization_vector) - self._initialization_vector = initialization_vector - - @property - def initialization_vector(self) -> utils.Buffer: - return self._initialization_vector - - validate_for_algorithm = _check_iv_and_key_length diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__init__.py deleted file mode 100644 index b509336..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index f3cc30c..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_asymmetric.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_asymmetric.cpython-312.pyc deleted file mode 100644 index d1ed772..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_asymmetric.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-312.pyc deleted file mode 100644 index 49053c5..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_modes.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_modes.cpython-312.pyc deleted file mode 100644 index 482ca36..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_modes.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_serialization.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_serialization.cpython-312.pyc deleted file mode 100644 index e3cfb5f..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/_serialization.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/cmac.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/cmac.cpython-312.pyc deleted file mode 100644 index cad5da7..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/cmac.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/constant_time.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/constant_time.cpython-312.pyc deleted file mode 100644 index 35ba74b..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/constant_time.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/hashes.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/hashes.cpython-312.pyc deleted file mode 100644 index d07567d..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/hashes.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/hmac.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/hmac.cpython-312.pyc deleted file mode 100644 index 9edfd6c..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/hmac.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/hpke.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/hpke.cpython-312.pyc deleted file mode 100644 index 74e3220..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/hpke.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/keywrap.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/keywrap.cpython-312.pyc deleted file mode 100644 index db3e3ec..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/keywrap.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/padding.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/padding.cpython-312.pyc deleted file mode 100644 index eb26ece..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/padding.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/poly1305.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/poly1305.cpython-312.pyc deleted file mode 100644 index 1c2e1e5..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/__pycache__/poly1305.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/_asymmetric.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/_asymmetric.py deleted file mode 100644 index ea55ffd..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/_asymmetric.py +++ /dev/null @@ -1,19 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -# This exists to break an import cycle. It is normally accessible from the -# asymmetric padding module. - - -class AsymmetricPadding(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def name(self) -> str: - """ - A string naming this padding (e.g. "PSS", "PKCS1"). - """ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/_cipheralgorithm.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/_cipheralgorithm.py deleted file mode 100644 index 305a9fd..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/_cipheralgorithm.py +++ /dev/null @@ -1,60 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -from cryptography import utils - -# This exists to break an import cycle. It is normally accessible from the -# ciphers module. - - -class CipherAlgorithm(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def name(self) -> str: - """ - A string naming this mode (e.g. "AES", "Camellia"). - """ - - @property - @abc.abstractmethod - def key_sizes(self) -> frozenset[int]: - """ - Valid key sizes for this algorithm in bits - """ - - @property - @abc.abstractmethod - def key_size(self) -> int: - """ - The size of the key being used as an integer in bits (e.g. 128, 256). - """ - - -class BlockCipherAlgorithm(CipherAlgorithm): - key: utils.Buffer - - @property - @abc.abstractmethod - def block_size(self) -> int: - """ - The size of a block as an integer in bits (e.g. 64, 128). - """ - - -def _verify_key_size( - algorithm: CipherAlgorithm, key: utils.Buffer -) -> utils.Buffer: - # Verify that the key is instance of bytes - utils._check_byteslike("key", key) - - # Verify that the key size matches the expected key size - if len(key) * 8 not in algorithm.key_sizes: - raise ValueError( - f"Invalid key size ({len(key) * 8}) for {algorithm.name}." - ) - return key diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/_modes.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/_modes.py deleted file mode 100644 index deae8bc..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/_modes.py +++ /dev/null @@ -1,105 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -from cryptography import utils -from cryptography.exceptions import UnsupportedAlgorithm, _Reasons -from cryptography.hazmat.primitives._cipheralgorithm import ( - BlockCipherAlgorithm, - CipherAlgorithm, -) - - -class Mode(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def name(self) -> str: - """ - A string naming this mode (e.g. "ECB", "CBC"). - """ - - @abc.abstractmethod - def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: - """ - Checks that all the necessary invariants of this (mode, algorithm) - combination are met. - """ - - -class ModeWithInitializationVector(Mode, metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def initialization_vector(self) -> utils.Buffer: - """ - The value of the initialization vector for this mode as bytes. - """ - - -class ModeWithTweak(Mode, metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def tweak(self) -> utils.Buffer: - """ - The value of the tweak for this mode as bytes. - """ - - -class ModeWithNonce(Mode, metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def nonce(self) -> utils.Buffer: - """ - The value of the nonce for this mode as bytes. - """ - - -class ModeWithAuthenticationTag(Mode, metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def tag(self) -> bytes | None: - """ - The value of the tag supplied to the constructor of this mode. - """ - - -def _check_aes_key_length(self: Mode, algorithm: CipherAlgorithm) -> None: - if algorithm.key_size > 256 and algorithm.name == "AES": - raise ValueError( - "Only 128, 192, and 256 bit keys are allowed for this AES mode" - ) - - -def _check_iv_length( - self: ModeWithInitializationVector, algorithm: BlockCipherAlgorithm -) -> None: - iv_len = len(self.initialization_vector) - if iv_len * 8 != algorithm.block_size: - raise ValueError(f"Invalid IV size ({iv_len}) for {self.name}.") - - -def _check_nonce_length( - nonce: utils.Buffer, name: str, algorithm: CipherAlgorithm -) -> None: - if not isinstance(algorithm, BlockCipherAlgorithm): - raise UnsupportedAlgorithm( - f"{name} requires a block cipher algorithm", - _Reasons.UNSUPPORTED_CIPHER, - ) - if len(nonce) * 8 != algorithm.block_size: - raise ValueError(f"Invalid nonce size ({len(nonce)}) for {name}.") - - -def _check_iv_and_key_length( - self: ModeWithInitializationVector, algorithm: CipherAlgorithm -) -> None: - if not isinstance(algorithm, BlockCipherAlgorithm): - raise UnsupportedAlgorithm( - f"{self} requires a block cipher algorithm", - _Reasons.UNSUPPORTED_CIPHER, - ) - _check_aes_key_length(self, algorithm) - _check_iv_length(self, algorithm) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/_serialization.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/_serialization.py deleted file mode 100644 index 9c3c474..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/_serialization.py +++ /dev/null @@ -1,136 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -from cryptography import utils -from cryptography.hazmat.bindings._rust import Encoding as Encoding -from cryptography.hazmat.bindings._rust import ( - ParameterFormat as ParameterFormat, -) -from cryptography.hazmat.bindings._rust import PrivateFormat as PrivateFormat -from cryptography.hazmat.bindings._rust import PublicFormat as PublicFormat -from cryptography.hazmat.primitives.hashes import HashAlgorithm - -# This exists to break an import cycle. These classes are normally accessible -# from the serialization module. - - -class PBES(utils.Enum): - PBESv1SHA1And3KeyTripleDESCBC = "PBESv1 using SHA1 and 3-Key TripleDES" - PBESv2SHA256AndAES256CBC = "PBESv2 using SHA256 PBKDF2 and AES256 CBC" - - -class KeySerializationEncryption(metaclass=abc.ABCMeta): - pass - - -class BestAvailableEncryption(KeySerializationEncryption): - def __init__(self, password: bytes): - if not isinstance(password, bytes) or len(password) == 0: - raise ValueError("Password must be 1 or more bytes.") - - self.password = password - - -class NoEncryption(KeySerializationEncryption): - pass - - -class KeySerializationEncryptionBuilder: - def __init__( - self, - format: PrivateFormat, - *, - _kdf_rounds: int | None = None, - _hmac_hash: HashAlgorithm | None = None, - _key_cert_algorithm: PBES | None = None, - ) -> None: - self._format = format - - self._kdf_rounds = _kdf_rounds - self._hmac_hash = _hmac_hash - self._key_cert_algorithm = _key_cert_algorithm - - def kdf_rounds(self, rounds: int) -> KeySerializationEncryptionBuilder: - if self._kdf_rounds is not None: - raise ValueError("kdf_rounds already set") - - if not isinstance(rounds, int): - raise TypeError("kdf_rounds must be an integer") - - if rounds < 1: - raise ValueError("kdf_rounds must be a positive integer") - - return KeySerializationEncryptionBuilder( - self._format, - _kdf_rounds=rounds, - _hmac_hash=self._hmac_hash, - _key_cert_algorithm=self._key_cert_algorithm, - ) - - def hmac_hash( - self, algorithm: HashAlgorithm - ) -> KeySerializationEncryptionBuilder: - if self._format is not PrivateFormat.PKCS12: - raise TypeError( - "hmac_hash only supported with PrivateFormat.PKCS12" - ) - - if self._hmac_hash is not None: - raise ValueError("hmac_hash already set") - return KeySerializationEncryptionBuilder( - self._format, - _kdf_rounds=self._kdf_rounds, - _hmac_hash=algorithm, - _key_cert_algorithm=self._key_cert_algorithm, - ) - - def key_cert_algorithm( - self, algorithm: PBES - ) -> KeySerializationEncryptionBuilder: - if self._format is not PrivateFormat.PKCS12: - raise TypeError( - "key_cert_algorithm only supported with PrivateFormat.PKCS12" - ) - if self._key_cert_algorithm is not None: - raise ValueError("key_cert_algorithm already set") - return KeySerializationEncryptionBuilder( - self._format, - _kdf_rounds=self._kdf_rounds, - _hmac_hash=self._hmac_hash, - _key_cert_algorithm=algorithm, - ) - - def build(self, password: bytes) -> KeySerializationEncryption: - if not isinstance(password, bytes) or len(password) == 0: - raise ValueError("Password must be 1 or more bytes.") - - return _KeySerializationEncryption( - self._format, - password, - kdf_rounds=self._kdf_rounds, - hmac_hash=self._hmac_hash, - key_cert_algorithm=self._key_cert_algorithm, - ) - - -class _KeySerializationEncryption(KeySerializationEncryption): - def __init__( - self, - format: PrivateFormat, - password: bytes, - *, - kdf_rounds: int | None, - hmac_hash: HashAlgorithm | None, - key_cert_algorithm: PBES | None, - ): - self._format = format - self.password = password - - self._kdf_rounds = kdf_rounds - self._hmac_hash = hmac_hash - self._key_cert_algorithm = key_cert_algorithm diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__init__.py deleted file mode 100644 index b509336..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 47f926f..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-312.pyc deleted file mode 100644 index cca06e3..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-312.pyc deleted file mode 100644 index 017e014..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-312.pyc deleted file mode 100644 index 1bb3783..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-312.pyc deleted file mode 100644 index 3c63218..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-312.pyc deleted file mode 100644 index c4b53d1..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/mldsa.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/mldsa.cpython-312.pyc deleted file mode 100644 index 834d71b..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/mldsa.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/mlkem.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/mlkem.cpython-312.pyc deleted file mode 100644 index 96f0e2d..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/mlkem.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-312.pyc deleted file mode 100644 index e3e07c7..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-312.pyc deleted file mode 100644 index 46d4dbd..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-312.pyc deleted file mode 100644 index 3dcc1fe..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-312.pyc deleted file mode 100644 index 9141871..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-312.pyc deleted file mode 100644 index 09c8b90..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-312.pyc deleted file mode 100644 index 586ecc7..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/dh.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/dh.py deleted file mode 100644 index 2f6b834..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/dh.py +++ /dev/null @@ -1,159 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives import _serialization - -generate_parameters = rust_openssl.dh.generate_parameters - - -DHPrivateNumbers = rust_openssl.dh.DHPrivateNumbers -DHPublicNumbers = rust_openssl.dh.DHPublicNumbers -DHParameterNumbers = rust_openssl.dh.DHParameterNumbers - - -class DHParameters(metaclass=abc.ABCMeta): - @abc.abstractmethod - def generate_private_key(self) -> DHPrivateKey: - """ - Generates and returns a DHPrivateKey. - """ - - @abc.abstractmethod - def parameter_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.ParameterFormat, - ) -> bytes: - """ - Returns the parameters serialized as bytes. - """ - - @abc.abstractmethod - def parameter_numbers(self) -> DHParameterNumbers: - """ - Returns a DHParameterNumbers. - """ - - -DHParametersWithSerialization = DHParameters -DHParameters.register(rust_openssl.dh.DHParameters) - - -class DHPublicKey(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def key_size(self) -> int: - """ - The bit length of the prime modulus. - """ - - @abc.abstractmethod - def parameters(self) -> DHParameters: - """ - The DHParameters object associated with this public key. - """ - - @abc.abstractmethod - def public_numbers(self) -> DHPublicNumbers: - """ - Returns a DHPublicNumbers. - """ - - @abc.abstractmethod - def public_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PublicFormat, - ) -> bytes: - """ - Returns the key serialized as bytes. - """ - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Checks equality. - """ - - @abc.abstractmethod - def __copy__(self) -> DHPublicKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> DHPublicKey: - """ - Returns a deep copy. - """ - - -DHPublicKeyWithSerialization = DHPublicKey -DHPublicKey.register(rust_openssl.dh.DHPublicKey) - - -class DHPrivateKey(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def key_size(self) -> int: - """ - The bit length of the prime modulus. - """ - - @abc.abstractmethod - def public_key(self) -> DHPublicKey: - """ - The DHPublicKey associated with this private key. - """ - - @abc.abstractmethod - def parameters(self) -> DHParameters: - """ - The DHParameters object associated with this private key. - """ - - @abc.abstractmethod - def exchange(self, peer_public_key: DHPublicKey) -> bytes: - """ - Given peer's DHPublicKey, carry out the key exchange and - return shared key as bytes. - """ - - @abc.abstractmethod - def private_numbers(self) -> DHPrivateNumbers: - """ - Returns a DHPrivateNumbers. - """ - - @abc.abstractmethod - def private_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PrivateFormat, - encryption_algorithm: _serialization.KeySerializationEncryption, - ) -> bytes: - """ - Returns the key serialized as bytes. - """ - - @abc.abstractmethod - def __copy__(self) -> DHPrivateKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> DHPrivateKey: - """ - Returns a deep copy. - """ - - -DHPrivateKeyWithSerialization = DHPrivateKey -DHPrivateKey.register(rust_openssl.dh.DHPrivateKey) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py deleted file mode 100644 index f245557..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py +++ /dev/null @@ -1,179 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc -import typing - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives import _serialization, hashes -from cryptography.hazmat.primitives.asymmetric import utils as asym_utils -from cryptography.utils import Buffer - - -class DSAParameters(metaclass=abc.ABCMeta): - @abc.abstractmethod - def generate_private_key(self) -> DSAPrivateKey: - """ - Generates and returns a DSAPrivateKey. - """ - - @abc.abstractmethod - def parameter_numbers(self) -> DSAParameterNumbers: - """ - Returns a DSAParameterNumbers. - """ - - -DSAParametersWithNumbers = DSAParameters -DSAParameters.register(rust_openssl.dsa.DSAParameters) - - -class DSAPrivateKey(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def key_size(self) -> int: - """ - The bit length of the prime modulus. - """ - - @abc.abstractmethod - def public_key(self) -> DSAPublicKey: - """ - The DSAPublicKey associated with this private key. - """ - - @abc.abstractmethod - def parameters(self) -> DSAParameters: - """ - The DSAParameters object associated with this private key. - """ - - @abc.abstractmethod - def sign( - self, - data: Buffer, - algorithm: asym_utils.Prehashed | hashes.HashAlgorithm, - ) -> bytes: - """ - Signs the data - """ - - @abc.abstractmethod - def private_numbers(self) -> DSAPrivateNumbers: - """ - Returns a DSAPrivateNumbers. - """ - - @abc.abstractmethod - def private_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PrivateFormat, - encryption_algorithm: _serialization.KeySerializationEncryption, - ) -> bytes: - """ - Returns the key serialized as bytes. - """ - - @abc.abstractmethod - def __copy__(self) -> DSAPrivateKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> DSAPrivateKey: - """ - Returns a deep copy. - """ - - -DSAPrivateKeyWithSerialization = DSAPrivateKey -DSAPrivateKey.register(rust_openssl.dsa.DSAPrivateKey) - - -class DSAPublicKey(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def key_size(self) -> int: - """ - The bit length of the prime modulus. - """ - - @abc.abstractmethod - def parameters(self) -> DSAParameters: - """ - The DSAParameters object associated with this public key. - """ - - @abc.abstractmethod - def public_numbers(self) -> DSAPublicNumbers: - """ - Returns a DSAPublicNumbers. - """ - - @abc.abstractmethod - def public_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PublicFormat, - ) -> bytes: - """ - Returns the key serialized as bytes. - """ - - @abc.abstractmethod - def verify( - self, - signature: Buffer, - data: Buffer, - algorithm: asym_utils.Prehashed | hashes.HashAlgorithm, - ) -> None: - """ - Verifies the signature of the data. - """ - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Checks equality. - """ - - @abc.abstractmethod - def __copy__(self) -> DSAPublicKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> DSAPublicKey: - """ - Returns a deep copy. - """ - - -DSAPublicKeyWithSerialization = DSAPublicKey -DSAPublicKey.register(rust_openssl.dsa.DSAPublicKey) - -DSAPrivateNumbers = rust_openssl.dsa.DSAPrivateNumbers -DSAPublicNumbers = rust_openssl.dsa.DSAPublicNumbers -DSAParameterNumbers = rust_openssl.dsa.DSAParameterNumbers - - -def generate_parameters( - key_size: int, backend: typing.Any = None -) -> DSAParameters: - if key_size not in (1024, 2048, 3072, 4096): - raise ValueError("Key size must be 1024, 2048, 3072, or 4096 bits.") - - return rust_openssl.dsa.generate_parameters(key_size) - - -def generate_private_key( - key_size: int, backend: typing.Any = None -) -> DSAPrivateKey: - parameters = generate_parameters(key_size) - return parameters.generate_private_key() diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py deleted file mode 100644 index 39e6751..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py +++ /dev/null @@ -1,369 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc -import typing - -from cryptography import utils -from cryptography.exceptions import UnsupportedAlgorithm, _Reasons -from cryptography.hazmat._oid import ObjectIdentifier -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives import _serialization, hashes -from cryptography.hazmat.primitives.asymmetric import utils as asym_utils - - -class EllipticCurveOID: - SECP192R1 = ObjectIdentifier("1.2.840.10045.3.1.1") - SECP224R1 = ObjectIdentifier("1.3.132.0.33") - SECP256K1 = ObjectIdentifier("1.3.132.0.10") - SECP256R1 = ObjectIdentifier("1.2.840.10045.3.1.7") - SECP384R1 = ObjectIdentifier("1.3.132.0.34") - SECP521R1 = ObjectIdentifier("1.3.132.0.35") - BRAINPOOLP256R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.7") - BRAINPOOLP384R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.11") - BRAINPOOLP512R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.13") - - -class EllipticCurve(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def name(self) -> str: - """ - The name of the curve. e.g. secp256r1. - """ - - @property - @abc.abstractmethod - def key_size(self) -> int: - """ - Bit size of a secret scalar for the curve. - """ - - @property - @abc.abstractmethod - def group_order(self) -> int: - """ - The order of the curve's group. - """ - - -class EllipticCurveSignatureAlgorithm(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def algorithm( - self, - ) -> asym_utils.Prehashed | hashes.HashAlgorithm: - """ - The digest algorithm used with this signature. - """ - - -class EllipticCurvePrivateKey(metaclass=abc.ABCMeta): - @abc.abstractmethod - def exchange( - self, algorithm: ECDH, peer_public_key: EllipticCurvePublicKey - ) -> bytes: - """ - Performs a key exchange operation using the provided algorithm with the - provided peer's public key. - """ - - @abc.abstractmethod - def public_key(self) -> EllipticCurvePublicKey: - """ - The EllipticCurvePublicKey for this private key. - """ - - @property - @abc.abstractmethod - def curve(self) -> EllipticCurve: - """ - The EllipticCurve that this key is on. - """ - - @property - @abc.abstractmethod - def key_size(self) -> int: - """ - Bit size of a secret scalar for the curve. - """ - - @abc.abstractmethod - def sign( - self, - data: utils.Buffer, - signature_algorithm: EllipticCurveSignatureAlgorithm, - ) -> bytes: - """ - Signs the data - """ - - @abc.abstractmethod - def private_numbers(self) -> EllipticCurvePrivateNumbers: - """ - Returns an EllipticCurvePrivateNumbers. - """ - - @abc.abstractmethod - def private_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PrivateFormat, - encryption_algorithm: _serialization.KeySerializationEncryption, - ) -> bytes: - """ - Returns the key serialized as bytes. - """ - - @abc.abstractmethod - def __copy__(self) -> EllipticCurvePrivateKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> EllipticCurvePrivateKey: - """ - Returns a deep copy. - """ - - -EllipticCurvePrivateKeyWithSerialization = EllipticCurvePrivateKey -EllipticCurvePrivateKey.register(rust_openssl.ec.ECPrivateKey) - - -class EllipticCurvePublicKey(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def curve(self) -> EllipticCurve: - """ - The EllipticCurve that this key is on. - """ - - @property - @abc.abstractmethod - def key_size(self) -> int: - """ - Bit size of a secret scalar for the curve. - """ - - @abc.abstractmethod - def public_numbers(self) -> EllipticCurvePublicNumbers: - """ - Returns an EllipticCurvePublicNumbers. - """ - - @abc.abstractmethod - def public_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PublicFormat, - ) -> bytes: - """ - Returns the key serialized as bytes. - """ - - @abc.abstractmethod - def verify( - self, - signature: utils.Buffer, - data: utils.Buffer, - signature_algorithm: EllipticCurveSignatureAlgorithm, - ) -> None: - """ - Verifies the signature of the data. - """ - - @classmethod - def from_encoded_point( - cls, curve: EllipticCurve, data: bytes - ) -> EllipticCurvePublicKey: - utils._check_bytes("data", data) - - if len(data) == 0: - raise ValueError("data must not be an empty byte string") - - if data[0] not in [0x02, 0x03, 0x04]: - raise ValueError("Unsupported elliptic curve point type") - - return rust_openssl.ec.from_public_bytes(curve, data) - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Checks equality. - """ - - @abc.abstractmethod - def __copy__(self) -> EllipticCurvePublicKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> EllipticCurvePublicKey: - """ - Returns a deep copy. - """ - - -EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey -EllipticCurvePublicKey.register(rust_openssl.ec.ECPublicKey) - -EllipticCurvePrivateNumbers = rust_openssl.ec.EllipticCurvePrivateNumbers -EllipticCurvePublicNumbers = rust_openssl.ec.EllipticCurvePublicNumbers - - -class SECP521R1(EllipticCurve): - name = "secp521r1" - key_size = 521 - group_order = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409 # noqa: E501 - - -class SECP384R1(EllipticCurve): - name = "secp384r1" - key_size = 384 - group_order = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973 # noqa: E501 - - -class SECP256R1(EllipticCurve): - name = "secp256r1" - key_size = 256 - group_order = ( - 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 - ) - - -class SECP256K1(EllipticCurve): - name = "secp256k1" - key_size = 256 - group_order = ( - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - ) - - -class SECP224R1(EllipticCurve): - name = "secp224r1" - key_size = 224 - group_order = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D - - -class SECP192R1(EllipticCurve): - name = "secp192r1" - key_size = 192 - group_order = 0xFFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831 - - -class BrainpoolP256R1(EllipticCurve): - name = "brainpoolP256r1" - key_size = 256 - group_order = ( - 0xA9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7 - ) - - -class BrainpoolP384R1(EllipticCurve): - name = "brainpoolP384r1" - key_size = 384 - group_order = 0x8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565 # noqa: E501 - - -class BrainpoolP512R1(EllipticCurve): - name = "brainpoolP512r1" - key_size = 512 - group_order = 0xAADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069 # noqa: E501 - - -_CURVE_TYPES: dict[str, EllipticCurve] = { - "prime192v1": SECP192R1(), - "prime256v1": SECP256R1(), - "secp192r1": SECP192R1(), - "secp224r1": SECP224R1(), - "secp256r1": SECP256R1(), - "secp384r1": SECP384R1(), - "secp521r1": SECP521R1(), - "secp256k1": SECP256K1(), - "brainpoolP256r1": BrainpoolP256R1(), - "brainpoolP384r1": BrainpoolP384R1(), - "brainpoolP512r1": BrainpoolP512R1(), -} - - -class ECDSA(EllipticCurveSignatureAlgorithm): - def __init__( - self, - algorithm: asym_utils.Prehashed | hashes.HashAlgorithm, - deterministic_signing: bool = False, - ): - from cryptography.hazmat.backends.openssl.backend import backend - - if ( - deterministic_signing - and not backend.ecdsa_deterministic_supported() - ): - raise UnsupportedAlgorithm( - "ECDSA with deterministic signature (RFC 6979) is not " - "supported by this version of OpenSSL.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - self._algorithm = algorithm - self._deterministic_signing = deterministic_signing - - @property - def algorithm( - self, - ) -> asym_utils.Prehashed | hashes.HashAlgorithm: - return self._algorithm - - @property - def deterministic_signing( - self, - ) -> bool: - return self._deterministic_signing - - -generate_private_key = rust_openssl.ec.generate_private_key - - -def derive_private_key( - private_value: int, - curve: EllipticCurve, - backend: typing.Any = None, -) -> EllipticCurvePrivateKey: - if not isinstance(private_value, int): - raise TypeError("private_value must be an integer type.") - - if private_value <= 0: - raise ValueError("private_value must be a positive integer.") - - return rust_openssl.ec.derive_private_key(private_value, curve) - - -class ECDH: - pass - - -_OID_TO_CURVE = { - EllipticCurveOID.SECP192R1: SECP192R1, - EllipticCurveOID.SECP224R1: SECP224R1, - EllipticCurveOID.SECP256K1: SECP256K1, - EllipticCurveOID.SECP256R1: SECP256R1, - EllipticCurveOID.SECP384R1: SECP384R1, - EllipticCurveOID.SECP521R1: SECP521R1, - EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1, - EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1, - EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1, -} - - -def get_curve_for_oid(oid: ObjectIdentifier) -> type[EllipticCurve]: - try: - return _OID_TO_CURVE[oid] - except KeyError: - raise LookupError( - "The provided object identifier has no matching elliptic " - "curve class" - ) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ed25519.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ed25519.py deleted file mode 100644 index 70aec5b..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ed25519.py +++ /dev/null @@ -1,116 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives import _serialization -from cryptography.utils import Buffer - - -class Ed25519PublicKey(metaclass=abc.ABCMeta): - @classmethod - def from_public_bytes(cls, data: bytes) -> Ed25519PublicKey: - return rust_openssl.ed25519.from_public_bytes(data) - - @abc.abstractmethod - def public_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PublicFormat, - ) -> bytes: - """ - The serialized bytes of the public key. - """ - - @abc.abstractmethod - def public_bytes_raw(self) -> bytes: - """ - The raw bytes of the public key. - Equivalent to public_bytes(Raw, Raw). - """ - - @abc.abstractmethod - def verify(self, signature: Buffer, data: Buffer) -> None: - """ - Verify the signature. - """ - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Checks equality. - """ - - @abc.abstractmethod - def __copy__(self) -> Ed25519PublicKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> Ed25519PublicKey: - """ - Returns a deep copy. - """ - - -Ed25519PublicKey.register(rust_openssl.ed25519.Ed25519PublicKey) - - -class Ed25519PrivateKey(metaclass=abc.ABCMeta): - @classmethod - def generate(cls) -> Ed25519PrivateKey: - return rust_openssl.ed25519.generate_key() - - @classmethod - def from_private_bytes(cls, data: Buffer) -> Ed25519PrivateKey: - return rust_openssl.ed25519.from_private_bytes(data) - - @abc.abstractmethod - def public_key(self) -> Ed25519PublicKey: - """ - The Ed25519PublicKey derived from the private key. - """ - - @abc.abstractmethod - def private_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PrivateFormat, - encryption_algorithm: _serialization.KeySerializationEncryption, - ) -> bytes: - """ - The serialized bytes of the private key. - """ - - @abc.abstractmethod - def private_bytes_raw(self) -> bytes: - """ - The raw bytes of the private key. - Equivalent to private_bytes(Raw, Raw, NoEncryption()). - """ - - @abc.abstractmethod - def sign(self, data: Buffer) -> bytes: - """ - Signs the data. - """ - - @abc.abstractmethod - def __copy__(self) -> Ed25519PrivateKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> Ed25519PrivateKey: - """ - Returns a deep copy. - """ - - -Ed25519PrivateKey.register(rust_openssl.ed25519.Ed25519PrivateKey) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ed448.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ed448.py deleted file mode 100644 index 9ecb478..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/ed448.py +++ /dev/null @@ -1,143 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -from cryptography.exceptions import UnsupportedAlgorithm, _Reasons -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives import _serialization -from cryptography.utils import Buffer - - -class Ed448PublicKey(metaclass=abc.ABCMeta): - @classmethod - def from_public_bytes(cls, data: bytes) -> Ed448PublicKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.ed448_supported(): - raise UnsupportedAlgorithm( - "ed448 is not supported by this version of OpenSSL.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.ed448.from_public_bytes(data) - - @abc.abstractmethod - def public_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PublicFormat, - ) -> bytes: - """ - The serialized bytes of the public key. - """ - - @abc.abstractmethod - def public_bytes_raw(self) -> bytes: - """ - The raw bytes of the public key. - Equivalent to public_bytes(Raw, Raw). - """ - - @abc.abstractmethod - def verify(self, signature: Buffer, data: Buffer) -> None: - """ - Verify the signature. - """ - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Checks equality. - """ - - @abc.abstractmethod - def __copy__(self) -> Ed448PublicKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> Ed448PublicKey: - """ - Returns a deep copy. - """ - - -if hasattr(rust_openssl, "ed448"): - Ed448PublicKey.register(rust_openssl.ed448.Ed448PublicKey) - - -class Ed448PrivateKey(metaclass=abc.ABCMeta): - @classmethod - def generate(cls) -> Ed448PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.ed448_supported(): - raise UnsupportedAlgorithm( - "ed448 is not supported by this version of OpenSSL.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.ed448.generate_key() - - @classmethod - def from_private_bytes(cls, data: Buffer) -> Ed448PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.ed448_supported(): - raise UnsupportedAlgorithm( - "ed448 is not supported by this version of OpenSSL.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.ed448.from_private_bytes(data) - - @abc.abstractmethod - def public_key(self) -> Ed448PublicKey: - """ - The Ed448PublicKey derived from the private key. - """ - - @abc.abstractmethod - def sign(self, data: Buffer) -> bytes: - """ - Signs the data. - """ - - @abc.abstractmethod - def private_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PrivateFormat, - encryption_algorithm: _serialization.KeySerializationEncryption, - ) -> bytes: - """ - The serialized bytes of the private key. - """ - - @abc.abstractmethod - def private_bytes_raw(self) -> bytes: - """ - The raw bytes of the private key. - Equivalent to private_bytes(Raw, Raw, NoEncryption()). - """ - - @abc.abstractmethod - def __copy__(self) -> Ed448PrivateKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> Ed448PrivateKey: - """ - Returns a deep copy. - """ - - -if hasattr(rust_openssl, "x448"): - Ed448PrivateKey.register(rust_openssl.ed448.Ed448PrivateKey) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/mldsa.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/mldsa.py deleted file mode 100644 index 0bd9684..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/mldsa.py +++ /dev/null @@ -1,441 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -from cryptography.exceptions import UnsupportedAlgorithm, _Reasons -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives import _serialization -from cryptography.utils import Buffer - - -class MLDSA44PublicKey(metaclass=abc.ABCMeta): - @classmethod - def from_public_bytes(cls, data: bytes) -> MLDSA44PublicKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mldsa_supported(): - raise UnsupportedAlgorithm( - "ML-DSA-44 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mldsa.from_mldsa44_public_bytes(data) - - @abc.abstractmethod - def public_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PublicFormat, - ) -> bytes: - """ - The serialized bytes of the public key. - """ - - @abc.abstractmethod - def public_bytes_raw(self) -> bytes: - """ - The raw bytes of the public key. - Equivalent to public_bytes(Raw, Raw). - - The public key is 1,312 bytes for MLDSA-44. - """ - - @abc.abstractmethod - def verify( - self, - signature: Buffer, - data: Buffer, - context: Buffer | None = None, - ) -> None: - """ - Verify the signature. - """ - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Checks equality. - """ - - @abc.abstractmethod - def __copy__(self) -> MLDSA44PublicKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> MLDSA44PublicKey: - """ - Returns a deep copy. - """ - - -if hasattr(rust_openssl, "mldsa"): - MLDSA44PublicKey.register(rust_openssl.mldsa.MLDSA44PublicKey) - - -class MLDSA44PrivateKey(metaclass=abc.ABCMeta): - @classmethod - def generate(cls) -> MLDSA44PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mldsa_supported(): - raise UnsupportedAlgorithm( - "ML-DSA-44 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mldsa.generate_mldsa44_key() - - @classmethod - def from_seed_bytes(cls, data: Buffer) -> MLDSA44PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mldsa_supported(): - raise UnsupportedAlgorithm( - "ML-DSA-44 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mldsa.from_mldsa44_seed_bytes(data) - - @abc.abstractmethod - def public_key(self) -> MLDSA44PublicKey: - """ - The MLDSA44PublicKey derived from the private key. - """ - - @abc.abstractmethod - def private_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PrivateFormat, - encryption_algorithm: _serialization.KeySerializationEncryption, - ) -> bytes: - """ - The serialized bytes of the private key. - - This method only returns the serialization of the seed form of the - private key, never the expanded one. - """ - - @abc.abstractmethod - def private_bytes_raw(self) -> bytes: - """ - The raw bytes of the private key. - Equivalent to private_bytes(Raw, Raw, NoEncryption()). - - This method only returns the seed form of the private key (32 bytes). - """ - - @abc.abstractmethod - def sign(self, data: Buffer, context: Buffer | None = None) -> bytes: - """ - Signs the data. - """ - - @abc.abstractmethod - def __copy__(self) -> MLDSA44PrivateKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> MLDSA44PrivateKey: - """ - Returns a deep copy. - """ - - -if hasattr(rust_openssl, "mldsa"): - MLDSA44PrivateKey.register(rust_openssl.mldsa.MLDSA44PrivateKey) - - -class MLDSA65PublicKey(metaclass=abc.ABCMeta): - @classmethod - def from_public_bytes(cls, data: bytes) -> MLDSA65PublicKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mldsa_supported(): - raise UnsupportedAlgorithm( - "ML-DSA-65 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mldsa.from_mldsa65_public_bytes(data) - - @abc.abstractmethod - def public_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PublicFormat, - ) -> bytes: - """ - The serialized bytes of the public key. - """ - - @abc.abstractmethod - def public_bytes_raw(self) -> bytes: - """ - The raw bytes of the public key. - Equivalent to public_bytes(Raw, Raw). - - The public key is 1,952 bytes for MLDSA-65. - """ - - @abc.abstractmethod - def verify( - self, - signature: Buffer, - data: Buffer, - context: Buffer | None = None, - ) -> None: - """ - Verify the signature. - """ - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Checks equality. - """ - - @abc.abstractmethod - def __copy__(self) -> MLDSA65PublicKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> MLDSA65PublicKey: - """ - Returns a deep copy. - """ - - -if hasattr(rust_openssl, "mldsa"): - MLDSA65PublicKey.register(rust_openssl.mldsa.MLDSA65PublicKey) - - -class MLDSA65PrivateKey(metaclass=abc.ABCMeta): - @classmethod - def generate(cls) -> MLDSA65PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mldsa_supported(): - raise UnsupportedAlgorithm( - "ML-DSA-65 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mldsa.generate_mldsa65_key() - - @classmethod - def from_seed_bytes(cls, data: Buffer) -> MLDSA65PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mldsa_supported(): - raise UnsupportedAlgorithm( - "ML-DSA-65 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mldsa.from_mldsa65_seed_bytes(data) - - @abc.abstractmethod - def public_key(self) -> MLDSA65PublicKey: - """ - The MLDSA65PublicKey derived from the private key. - """ - - @abc.abstractmethod - def private_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PrivateFormat, - encryption_algorithm: _serialization.KeySerializationEncryption, - ) -> bytes: - """ - The serialized bytes of the private key. - - This method only returns the serialization of the seed form of the - private key, never the expanded one. - """ - - @abc.abstractmethod - def private_bytes_raw(self) -> bytes: - """ - The raw bytes of the private key. - Equivalent to private_bytes(Raw, Raw, NoEncryption()). - - This method only returns the seed form of the private key (32 bytes). - """ - - @abc.abstractmethod - def sign(self, data: Buffer, context: Buffer | None = None) -> bytes: - """ - Signs the data. - """ - - @abc.abstractmethod - def __copy__(self) -> MLDSA65PrivateKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> MLDSA65PrivateKey: - """ - Returns a deep copy. - """ - - -if hasattr(rust_openssl, "mldsa"): - MLDSA65PrivateKey.register(rust_openssl.mldsa.MLDSA65PrivateKey) - - -class MLDSA87PublicKey(metaclass=abc.ABCMeta): - @classmethod - def from_public_bytes(cls, data: bytes) -> MLDSA87PublicKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mldsa_supported(): - raise UnsupportedAlgorithm( - "ML-DSA-87 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mldsa.from_mldsa87_public_bytes(data) - - @abc.abstractmethod - def public_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PublicFormat, - ) -> bytes: - """ - The serialized bytes of the public key. - """ - - @abc.abstractmethod - def public_bytes_raw(self) -> bytes: - """ - The raw bytes of the public key. - Equivalent to public_bytes(Raw, Raw). - - The public key is 2,592 bytes for MLDSA-87. - """ - - @abc.abstractmethod - def verify( - self, - signature: Buffer, - data: Buffer, - context: Buffer | None = None, - ) -> None: - """ - Verify the signature. - """ - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Checks equality. - """ - - @abc.abstractmethod - def __copy__(self) -> MLDSA87PublicKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> MLDSA87PublicKey: - """ - Returns a deep copy. - """ - - -if hasattr(rust_openssl, "mldsa"): - MLDSA87PublicKey.register(rust_openssl.mldsa.MLDSA87PublicKey) - - -class MLDSA87PrivateKey(metaclass=abc.ABCMeta): - @classmethod - def generate(cls) -> MLDSA87PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mldsa_supported(): - raise UnsupportedAlgorithm( - "ML-DSA-87 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mldsa.generate_mldsa87_key() - - @classmethod - def from_seed_bytes(cls, data: Buffer) -> MLDSA87PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mldsa_supported(): - raise UnsupportedAlgorithm( - "ML-DSA-87 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mldsa.from_mldsa87_seed_bytes(data) - - @abc.abstractmethod - def public_key(self) -> MLDSA87PublicKey: - """ - The MLDSA87PublicKey derived from the private key. - """ - - @abc.abstractmethod - def private_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PrivateFormat, - encryption_algorithm: _serialization.KeySerializationEncryption, - ) -> bytes: - """ - The serialized bytes of the private key. - - This method only returns the serialization of the seed form of the - private key, never the expanded one. - """ - - @abc.abstractmethod - def private_bytes_raw(self) -> bytes: - """ - The raw bytes of the private key. - Equivalent to private_bytes(Raw, Raw, NoEncryption()). - - This method only returns the seed form of the private key (32 bytes). - """ - - @abc.abstractmethod - def sign(self, data: Buffer, context: Buffer | None = None) -> bytes: - """ - Signs the data. - """ - - @abc.abstractmethod - def __copy__(self) -> MLDSA87PrivateKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> MLDSA87PrivateKey: - """ - Returns a deep copy. - """ - - -if hasattr(rust_openssl, "mldsa"): - MLDSA87PrivateKey.register(rust_openssl.mldsa.MLDSA87PrivateKey) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/mlkem.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/mlkem.py deleted file mode 100644 index 64bca11..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/mlkem.py +++ /dev/null @@ -1,278 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -from cryptography.exceptions import UnsupportedAlgorithm, _Reasons -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives import _serialization -from cryptography.utils import Buffer - - -class MLKEM768PublicKey(metaclass=abc.ABCMeta): - @classmethod - def from_public_bytes(cls, data: Buffer) -> MLKEM768PublicKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mlkem_supported(): - raise UnsupportedAlgorithm( - "ML-KEM-768 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mlkem.from_mlkem768_public_bytes(data) - - @abc.abstractmethod - def encapsulate(self) -> tuple[bytes, bytes]: - """ - Encapsulate: returns (shared_secret, ciphertext). - """ - - @abc.abstractmethod - def public_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PublicFormat, - ) -> bytes: - """ - The serialized bytes of the public key. - """ - - @abc.abstractmethod - def public_bytes_raw(self) -> bytes: - """ - The raw bytes of the public key. - Equivalent to public_bytes(Raw, Raw). - - The public key is 1,184 bytes for ML-KEM-768. - """ - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Checks equality. - """ - - @abc.abstractmethod - def __copy__(self) -> MLKEM768PublicKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> MLKEM768PublicKey: - """ - Returns a deep copy. - """ - - -if hasattr(rust_openssl, "mlkem"): - MLKEM768PublicKey.register(rust_openssl.mlkem.MLKEM768PublicKey) - - -class MLKEM768PrivateKey(metaclass=abc.ABCMeta): - @classmethod - def generate(cls) -> MLKEM768PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mlkem_supported(): - raise UnsupportedAlgorithm( - "ML-KEM-768 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mlkem.generate_mlkem768_key() - - @classmethod - def from_seed_bytes(cls, data: Buffer) -> MLKEM768PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mlkem_supported(): - raise UnsupportedAlgorithm( - "ML-KEM-768 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mlkem.from_mlkem768_seed_bytes(data) - - @abc.abstractmethod - def decapsulate(self, ciphertext: Buffer) -> bytes: - """ - Decapsulate: returns shared_secret. - """ - - @abc.abstractmethod - def public_key(self) -> MLKEM768PublicKey: - """ - The MLKEM768PublicKey derived from this private key. - """ - - @abc.abstractmethod - def private_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PrivateFormat, - encryption_algorithm: _serialization.KeySerializationEncryption, - ) -> bytes: - """ - The serialized bytes of the private key. - """ - - @abc.abstractmethod - def private_bytes_raw(self) -> bytes: - """ - The raw bytes of the private key (64-byte seed). - Equivalent to private_bytes(Raw, Raw, NoEncryption()). - """ - - @abc.abstractmethod - def __copy__(self) -> MLKEM768PrivateKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> MLKEM768PrivateKey: - """ - Returns a deep copy. - """ - - -if hasattr(rust_openssl, "mlkem"): - MLKEM768PrivateKey.register(rust_openssl.mlkem.MLKEM768PrivateKey) - - -class MLKEM1024PublicKey(metaclass=abc.ABCMeta): - @classmethod - def from_public_bytes(cls, data: Buffer) -> MLKEM1024PublicKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mlkem_supported(): - raise UnsupportedAlgorithm( - "ML-KEM-1024 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mlkem.from_mlkem1024_public_bytes(data) - - @abc.abstractmethod - def encapsulate(self) -> tuple[bytes, bytes]: - """ - Encapsulate: returns (shared_secret, ciphertext). - """ - - @abc.abstractmethod - def public_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PublicFormat, - ) -> bytes: - """ - The serialized bytes of the public key. - """ - - @abc.abstractmethod - def public_bytes_raw(self) -> bytes: - """ - The raw bytes of the public key. - Equivalent to public_bytes(Raw, Raw). - - The public key is 1,568 bytes for ML-KEM-1024. - """ - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Checks equality. - """ - - @abc.abstractmethod - def __copy__(self) -> MLKEM1024PublicKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> MLKEM1024PublicKey: - """ - Returns a deep copy. - """ - - -if hasattr(rust_openssl, "mlkem"): - MLKEM1024PublicKey.register(rust_openssl.mlkem.MLKEM1024PublicKey) - - -class MLKEM1024PrivateKey(metaclass=abc.ABCMeta): - @classmethod - def generate(cls) -> MLKEM1024PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mlkem_supported(): - raise UnsupportedAlgorithm( - "ML-KEM-1024 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mlkem.generate_mlkem1024_key() - - @classmethod - def from_seed_bytes(cls, data: Buffer) -> MLKEM1024PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.mlkem_supported(): - raise UnsupportedAlgorithm( - "ML-KEM-1024 is not supported by this backend.", - _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM, - ) - - return rust_openssl.mlkem.from_mlkem1024_seed_bytes(data) - - @abc.abstractmethod - def decapsulate(self, ciphertext: Buffer) -> bytes: - """ - Decapsulate: returns shared_secret. - """ - - @abc.abstractmethod - def public_key(self) -> MLKEM1024PublicKey: - """ - The MLKEM1024PublicKey derived from this private key. - """ - - @abc.abstractmethod - def private_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PrivateFormat, - encryption_algorithm: _serialization.KeySerializationEncryption, - ) -> bytes: - """ - The serialized bytes of the private key. - """ - - @abc.abstractmethod - def private_bytes_raw(self) -> bytes: - """ - The raw bytes of the private key (64-byte seed). - Equivalent to private_bytes(Raw, Raw, NoEncryption()). - """ - - @abc.abstractmethod - def __copy__(self) -> MLKEM1024PrivateKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> MLKEM1024PrivateKey: - """ - Returns a deep copy. - """ - - -if hasattr(rust_openssl, "mlkem"): - MLKEM1024PrivateKey.register(rust_openssl.mlkem.MLKEM1024PrivateKey) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py deleted file mode 100644 index 5121a28..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/padding.py +++ /dev/null @@ -1,111 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives._asymmetric import ( - AsymmetricPadding as AsymmetricPadding, -) -from cryptography.hazmat.primitives.asymmetric import rsa - - -class PKCS1v15(AsymmetricPadding): - name = "EMSA-PKCS1-v1_5" - - -class _MaxLength: - "Sentinel value for `MAX_LENGTH`." - - -class _Auto: - "Sentinel value for `AUTO`." - - -class _DigestLength: - "Sentinel value for `DIGEST_LENGTH`." - - -class PSS(AsymmetricPadding): - MAX_LENGTH = _MaxLength() - AUTO = _Auto() - DIGEST_LENGTH = _DigestLength() - name = "EMSA-PSS" - _salt_length: int | _MaxLength | _Auto | _DigestLength - - def __init__( - self, - mgf: MGF, - salt_length: int | _MaxLength | _Auto | _DigestLength, - ) -> None: - self._mgf = mgf - - if not isinstance( - salt_length, (int, _MaxLength, _Auto, _DigestLength) - ): - raise TypeError( - "salt_length must be an integer, MAX_LENGTH, " - "DIGEST_LENGTH, or AUTO" - ) - - if isinstance(salt_length, int) and salt_length < 0: - raise ValueError("salt_length must be zero or greater.") - - self._salt_length = salt_length - - @property - def mgf(self) -> MGF: - return self._mgf - - -class OAEP(AsymmetricPadding): - name = "EME-OAEP" - - def __init__( - self, - mgf: MGF, - algorithm: hashes.HashAlgorithm, - label: bytes | None, - ): - if not isinstance(algorithm, hashes.HashAlgorithm): - raise TypeError("Expected instance of hashes.HashAlgorithm.") - - self._mgf = mgf - self._algorithm = algorithm - self._label = label - - @property - def algorithm(self) -> hashes.HashAlgorithm: - return self._algorithm - - @property - def mgf(self) -> MGF: - return self._mgf - - -class MGF(metaclass=abc.ABCMeta): - _algorithm: hashes.HashAlgorithm - - -class MGF1(MGF): - def __init__(self, algorithm: hashes.HashAlgorithm): - if not isinstance(algorithm, hashes.HashAlgorithm): - raise TypeError("Expected instance of hashes.HashAlgorithm.") - - self._algorithm = algorithm - - -def calculate_max_pss_salt_length( - key: rsa.RSAPrivateKey | rsa.RSAPublicKey, - hash_algorithm: hashes.HashAlgorithm, -) -> int: - if not isinstance(key, (rsa.RSAPrivateKey, rsa.RSAPublicKey)): - raise TypeError("key must be an RSA public or private key") - # bit length - 1 per RFC 3447 - emlen = (key.key_size + 6) // 8 - salt_length = emlen - hash_algorithm.digest_size - 2 - assert salt_length >= 0 - return salt_length diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py deleted file mode 100644 index d730ceb..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py +++ /dev/null @@ -1,295 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc -import random -import typing -from math import gcd, lcm - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives import _serialization, hashes -from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding -from cryptography.hazmat.primitives.asymmetric import utils as asym_utils - - -class RSAPrivateKey(metaclass=abc.ABCMeta): - @abc.abstractmethod - def decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes: - """ - Decrypts the provided ciphertext. - """ - - @property - @abc.abstractmethod - def key_size(self) -> int: - """ - The bit length of the public modulus. - """ - - @abc.abstractmethod - def public_key(self) -> RSAPublicKey: - """ - The RSAPublicKey associated with this private key. - """ - - @abc.abstractmethod - def sign( - self, - data: bytes, - padding: AsymmetricPadding, - algorithm: asym_utils.Prehashed - | hashes.HashAlgorithm - | asym_utils.NoDigestInfo, - ) -> bytes: - """ - Signs the data. - """ - - @abc.abstractmethod - def private_numbers(self) -> RSAPrivateNumbers: - """ - Returns an RSAPrivateNumbers. - """ - - @abc.abstractmethod - def private_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PrivateFormat, - encryption_algorithm: _serialization.KeySerializationEncryption, - ) -> bytes: - """ - Returns the key serialized as bytes. - """ - - @abc.abstractmethod - def __copy__(self) -> RSAPrivateKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> RSAPrivateKey: - """ - Returns a deep copy. - """ - - -RSAPrivateKeyWithSerialization = RSAPrivateKey -RSAPrivateKey.register(rust_openssl.rsa.RSAPrivateKey) - - -class RSAPublicKey(metaclass=abc.ABCMeta): - @abc.abstractmethod - def encrypt(self, plaintext: bytes, padding: AsymmetricPadding) -> bytes: - """ - Encrypts the given plaintext. - """ - - @property - @abc.abstractmethod - def key_size(self) -> int: - """ - The bit length of the public modulus. - """ - - @abc.abstractmethod - def public_numbers(self) -> RSAPublicNumbers: - """ - Returns an RSAPublicNumbers - """ - - @abc.abstractmethod - def public_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PublicFormat, - ) -> bytes: - """ - Returns the key serialized as bytes. - """ - - @abc.abstractmethod - def verify( - self, - signature: bytes, - data: bytes, - padding: AsymmetricPadding, - algorithm: asym_utils.Prehashed | hashes.HashAlgorithm, - ) -> None: - """ - Verifies the signature of the data. - """ - - @abc.abstractmethod - def recover_data_from_signature( - self, - signature: bytes, - padding: AsymmetricPadding, - algorithm: hashes.HashAlgorithm | asym_utils.NoDigestInfo | None, - ) -> bytes: - """ - Recovers the original data from the signature. - """ - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Checks equality. - """ - - @abc.abstractmethod - def __copy__(self) -> RSAPublicKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> RSAPublicKey: - """ - Returns a deep copy. - """ - - -RSAPublicKeyWithSerialization = RSAPublicKey -RSAPublicKey.register(rust_openssl.rsa.RSAPublicKey) - -RSAPrivateNumbers = rust_openssl.rsa.RSAPrivateNumbers -RSAPublicNumbers = rust_openssl.rsa.RSAPublicNumbers - - -def generate_private_key( - public_exponent: int, - key_size: int, - backend: typing.Any = None, -) -> RSAPrivateKey: - _verify_rsa_parameters(public_exponent, key_size) - return rust_openssl.rsa.generate_private_key(public_exponent, key_size) - - -def _verify_rsa_parameters(public_exponent: int, key_size: int) -> None: - if public_exponent not in (3, 65537): - raise ValueError( - "public_exponent must be either 3 (for legacy compatibility) or " - "65537. Almost everyone should choose 65537 here!" - ) - - if key_size < 1024: - raise ValueError("key_size must be at least 1024-bits.") - - -def _modinv(e: int, m: int) -> int: - """ - Modular Multiplicative Inverse. Returns x such that: (x*e) mod m == 1 - """ - x1, x2 = 1, 0 - a, b = e, m - while b > 0: - q, r = divmod(a, b) - xn = x1 - q * x2 - a, b, x1, x2 = b, r, x2, xn - return x1 % m - - -def rsa_crt_iqmp(p: int, q: int) -> int: - """ - Compute the CRT (q ** -1) % p value from RSA primes p and q. - """ - if p <= 1 or q <= 1: - raise ValueError("Values can't be <= 1") - return _modinv(q, p) - - -def rsa_crt_dmp1(private_exponent: int, p: int) -> int: - """ - Compute the CRT private_exponent % (p - 1) value from the RSA - private_exponent (d) and p. - """ - if private_exponent <= 1 or p <= 1: - raise ValueError("Values can't be <= 1") - return private_exponent % (p - 1) - - -def rsa_crt_dmq1(private_exponent: int, q: int) -> int: - """ - Compute the CRT private_exponent % (q - 1) value from the RSA - private_exponent (d) and q. - """ - if private_exponent <= 1 or q <= 1: - raise ValueError("Values can't be <= 1") - return private_exponent % (q - 1) - - -def rsa_recover_private_exponent(e: int, p: int, q: int) -> int: - """ - Compute the RSA private_exponent (d) given the public exponent (e) - and the RSA primes p and q. - - This uses the Carmichael totient function to generate the - smallest possible working value of the private exponent. - """ - # This lambda_n is the Carmichael totient function. - # The original RSA paper uses the Euler totient function - # here: phi_n = (p - 1) * (q - 1) - # Either version of the private exponent will work, but the - # one generated by the older formulation may be larger - # than necessary. (lambda_n always divides phi_n) - if e <= 1 or p <= 1 or q <= 1: - raise ValueError("Values can't be <= 1") - return _modinv(e, lcm(p - 1, q - 1)) - - -# Controls the number of iterations rsa_recover_prime_factors will perform -# to obtain the prime factors. -_MAX_RECOVERY_ATTEMPTS = 500 - - -def rsa_recover_prime_factors(n: int, e: int, d: int) -> tuple[int, int]: - """ - Compute factors p and q from the private exponent d. We assume that n has - no more than two factors. This function is adapted from code in PyCrypto. - """ - # reject invalid values early - if d <= 1 or e <= 1: - raise ValueError("d, e can't be <= 1") - if 17 != pow(17, e * d, n): - raise ValueError("n, d, e don't match") - # See 8.2.2(i) in Handbook of Applied Cryptography. - ktot = d * e - 1 - # The quantity d*e-1 is a multiple of phi(n), even, - # and can be represented as t*2^s. - t = ktot - while t % 2 == 0: - t = t // 2 - # Cycle through all multiplicative inverses in Zn. - # The algorithm is non-deterministic, but there is a 50% chance - # any candidate a leads to successful factoring. - # See "Digitalized Signatures and Public Key Functions as Intractable - # as Factorization", M. Rabin, 1979 - spotted = False - tries = 0 - while not spotted and tries < _MAX_RECOVERY_ATTEMPTS: - a = random.randint(2, n - 1) - tries += 1 - k = t - # Cycle through all values a^{t*2^i}=a^k - while k < ktot: - cand = pow(a, k, n) - # Check if a^k is a non-trivial root of unity (mod n) - if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1: - # We have found a number such that (cand-1)(cand+1)=0 (mod n). - # Either of the terms divides n. - p = gcd(cand + 1, n) - spotted = True - break - k *= 2 - if not spotted: - raise ValueError("Unable to compute factors p and q from exponent d.") - # Found ! - q, r = divmod(n, p) - assert r == 0 - p, q = sorted((p, q), reverse=True) - return (p, q) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/types.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/types.py deleted file mode 100644 index dfd12ce..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/types.py +++ /dev/null @@ -1,123 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import typing - -from cryptography import utils -from cryptography.hazmat.primitives.asymmetric import ( - dh, - dsa, - ec, - ed448, - ed25519, - mldsa, - mlkem, - rsa, - x448, - x25519, -) - -# Every asymmetric key type -PublicKeyTypes = typing.Union[ - dh.DHPublicKey, - dsa.DSAPublicKey, - rsa.RSAPublicKey, - ec.EllipticCurvePublicKey, - ed25519.Ed25519PublicKey, - ed448.Ed448PublicKey, - mldsa.MLDSA44PublicKey, - mldsa.MLDSA65PublicKey, - mldsa.MLDSA87PublicKey, - mlkem.MLKEM768PublicKey, - mlkem.MLKEM1024PublicKey, - x25519.X25519PublicKey, - x448.X448PublicKey, -] -PUBLIC_KEY_TYPES = PublicKeyTypes -utils.deprecated( - PUBLIC_KEY_TYPES, - __name__, - "Use PublicKeyTypes instead", - utils.DeprecatedIn40, - name="PUBLIC_KEY_TYPES", -) -# Every asymmetric key type -PrivateKeyTypes = typing.Union[ - dh.DHPrivateKey, - ed25519.Ed25519PrivateKey, - ed448.Ed448PrivateKey, - mldsa.MLDSA44PrivateKey, - mldsa.MLDSA65PrivateKey, - mldsa.MLDSA87PrivateKey, - mlkem.MLKEM768PrivateKey, - mlkem.MLKEM1024PrivateKey, - rsa.RSAPrivateKey, - dsa.DSAPrivateKey, - ec.EllipticCurvePrivateKey, - x25519.X25519PrivateKey, - x448.X448PrivateKey, -] -PRIVATE_KEY_TYPES = PrivateKeyTypes -utils.deprecated( - PRIVATE_KEY_TYPES, - __name__, - "Use PrivateKeyTypes instead", - utils.DeprecatedIn40, - name="PRIVATE_KEY_TYPES", -) -# Just the key types we allow to be used for x509 signing. This mirrors -# the certificate public key types -CertificateIssuerPrivateKeyTypes = typing.Union[ - ed25519.Ed25519PrivateKey, - ed448.Ed448PrivateKey, - rsa.RSAPrivateKey, - dsa.DSAPrivateKey, - ec.EllipticCurvePrivateKey, -] -CERTIFICATE_PRIVATE_KEY_TYPES = CertificateIssuerPrivateKeyTypes -utils.deprecated( - CERTIFICATE_PRIVATE_KEY_TYPES, - __name__, - "Use CertificateIssuerPrivateKeyTypes instead", - utils.DeprecatedIn40, - name="CERTIFICATE_PRIVATE_KEY_TYPES", -) -# Just the key types we allow to be used for x509 signing. This mirrors -# the certificate private key types -CertificateIssuerPublicKeyTypes = typing.Union[ - dsa.DSAPublicKey, - rsa.RSAPublicKey, - ec.EllipticCurvePublicKey, - ed25519.Ed25519PublicKey, - ed448.Ed448PublicKey, -] -CERTIFICATE_ISSUER_PUBLIC_KEY_TYPES = CertificateIssuerPublicKeyTypes -utils.deprecated( - CERTIFICATE_ISSUER_PUBLIC_KEY_TYPES, - __name__, - "Use CertificateIssuerPublicKeyTypes instead", - utils.DeprecatedIn40, - name="CERTIFICATE_ISSUER_PUBLIC_KEY_TYPES", -) -# This type removes DHPublicKey. x448/x25519 can be a public key -# but cannot be used in signing so they are allowed here. -CertificatePublicKeyTypes = typing.Union[ - dsa.DSAPublicKey, - rsa.RSAPublicKey, - ec.EllipticCurvePublicKey, - ed25519.Ed25519PublicKey, - ed448.Ed448PublicKey, - x25519.X25519PublicKey, - x448.X448PublicKey, -] -CERTIFICATE_PUBLIC_KEY_TYPES = CertificatePublicKeyTypes -utils.deprecated( - CERTIFICATE_PUBLIC_KEY_TYPES, - __name__, - "Use CertificatePublicKeyTypes instead", - utils.DeprecatedIn40, - name="CERTIFICATE_PUBLIC_KEY_TYPES", -) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/utils.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/utils.py deleted file mode 100644 index c01c342..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/utils.py +++ /dev/null @@ -1,28 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.bindings._rust import asn1 -from cryptography.hazmat.primitives import hashes - -decode_dss_signature = asn1.decode_dss_signature -encode_dss_signature = asn1.encode_dss_signature - - -class NoDigestInfo: - pass - - -class Prehashed: - def __init__(self, algorithm: hashes.HashAlgorithm): - if not isinstance(algorithm, hashes.HashAlgorithm): - raise TypeError("Expected instance of HashAlgorithm.") - - self._algorithm = algorithm - self._digest_size = algorithm.digest_size - - @property - def digest_size(self) -> int: - return self._digest_size diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/x25519.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/x25519.py deleted file mode 100644 index 7498998..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/x25519.py +++ /dev/null @@ -1,134 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -from cryptography.exceptions import UnsupportedAlgorithm, _Reasons -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives import _serialization -from cryptography.utils import Buffer - - -class X25519PublicKey(metaclass=abc.ABCMeta): - @classmethod - def from_public_bytes(cls, data: bytes) -> X25519PublicKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.x25519_supported(): - raise UnsupportedAlgorithm( - "X25519 is not supported by this version of OpenSSL.", - _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, - ) - - return rust_openssl.x25519.from_public_bytes(data) - - @abc.abstractmethod - def public_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PublicFormat, - ) -> bytes: - """ - The serialized bytes of the public key. - """ - - @abc.abstractmethod - def public_bytes_raw(self) -> bytes: - """ - The raw bytes of the public key. - Equivalent to public_bytes(Raw, Raw). - """ - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Checks equality. - """ - - @abc.abstractmethod - def __copy__(self) -> X25519PublicKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> X25519PublicKey: - """ - Returns a deep copy. - """ - - -X25519PublicKey.register(rust_openssl.x25519.X25519PublicKey) - - -class X25519PrivateKey(metaclass=abc.ABCMeta): - @classmethod - def generate(cls) -> X25519PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.x25519_supported(): - raise UnsupportedAlgorithm( - "X25519 is not supported by this version of OpenSSL.", - _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, - ) - return rust_openssl.x25519.generate_key() - - @classmethod - def from_private_bytes(cls, data: Buffer) -> X25519PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.x25519_supported(): - raise UnsupportedAlgorithm( - "X25519 is not supported by this version of OpenSSL.", - _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, - ) - - return rust_openssl.x25519.from_private_bytes(data) - - @abc.abstractmethod - def public_key(self) -> X25519PublicKey: - """ - Returns the public key associated with this private key - """ - - @abc.abstractmethod - def private_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PrivateFormat, - encryption_algorithm: _serialization.KeySerializationEncryption, - ) -> bytes: - """ - The serialized bytes of the private key. - """ - - @abc.abstractmethod - def private_bytes_raw(self) -> bytes: - """ - The raw bytes of the private key. - Equivalent to private_bytes(Raw, Raw, NoEncryption()). - """ - - @abc.abstractmethod - def exchange(self, peer_public_key: X25519PublicKey) -> bytes: - """ - Performs a key exchange operation using the provided peer's public key. - """ - - @abc.abstractmethod - def __copy__(self) -> X25519PrivateKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> X25519PrivateKey: - """ - Returns a deep copy. - """ - - -X25519PrivateKey.register(rust_openssl.x25519.X25519PrivateKey) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/x448.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/x448.py deleted file mode 100644 index b9dc826..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/asymmetric/x448.py +++ /dev/null @@ -1,137 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -from cryptography.exceptions import UnsupportedAlgorithm, _Reasons -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives import _serialization -from cryptography.utils import Buffer - - -class X448PublicKey(metaclass=abc.ABCMeta): - @classmethod - def from_public_bytes(cls, data: bytes) -> X448PublicKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.x448_supported(): - raise UnsupportedAlgorithm( - "X448 is not supported by this version of OpenSSL.", - _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, - ) - - return rust_openssl.x448.from_public_bytes(data) - - @abc.abstractmethod - def public_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PublicFormat, - ) -> bytes: - """ - The serialized bytes of the public key. - """ - - @abc.abstractmethod - def public_bytes_raw(self) -> bytes: - """ - The raw bytes of the public key. - Equivalent to public_bytes(Raw, Raw). - """ - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Checks equality. - """ - - @abc.abstractmethod - def __copy__(self) -> X448PublicKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> X448PublicKey: - """ - Returns a deep copy. - """ - - -if hasattr(rust_openssl, "x448"): - X448PublicKey.register(rust_openssl.x448.X448PublicKey) - - -class X448PrivateKey(metaclass=abc.ABCMeta): - @classmethod - def generate(cls) -> X448PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.x448_supported(): - raise UnsupportedAlgorithm( - "X448 is not supported by this version of OpenSSL.", - _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, - ) - - return rust_openssl.x448.generate_key() - - @classmethod - def from_private_bytes(cls, data: Buffer) -> X448PrivateKey: - from cryptography.hazmat.backends.openssl.backend import backend - - if not backend.x448_supported(): - raise UnsupportedAlgorithm( - "X448 is not supported by this version of OpenSSL.", - _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM, - ) - - return rust_openssl.x448.from_private_bytes(data) - - @abc.abstractmethod - def public_key(self) -> X448PublicKey: - """ - Returns the public key associated with this private key - """ - - @abc.abstractmethod - def private_bytes( - self, - encoding: _serialization.Encoding, - format: _serialization.PrivateFormat, - encryption_algorithm: _serialization.KeySerializationEncryption, - ) -> bytes: - """ - The serialized bytes of the private key. - """ - - @abc.abstractmethod - def private_bytes_raw(self) -> bytes: - """ - The raw bytes of the private key. - Equivalent to private_bytes(Raw, Raw, NoEncryption()). - """ - - @abc.abstractmethod - def exchange(self, peer_public_key: X448PublicKey) -> bytes: - """ - Performs a key exchange operation using the provided peer's public key. - """ - - @abc.abstractmethod - def __copy__(self) -> X448PrivateKey: - """ - Returns a copy. - """ - - @abc.abstractmethod - def __deepcopy__(self, memo: dict) -> X448PrivateKey: - """ - Returns a deep copy. - """ - - -if hasattr(rust_openssl, "x448"): - X448PrivateKey.register(rust_openssl.x448.X448PrivateKey) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__init__.py deleted file mode 100644 index 10c15d0..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.primitives._cipheralgorithm import ( - BlockCipherAlgorithm, - CipherAlgorithm, -) -from cryptography.hazmat.primitives.ciphers.base import ( - AEADCipherContext, - AEADDecryptionContext, - AEADEncryptionContext, - Cipher, - CipherContext, -) - -__all__ = [ - "AEADCipherContext", - "AEADDecryptionContext", - "AEADEncryptionContext", - "BlockCipherAlgorithm", - "Cipher", - "CipherAlgorithm", - "CipherContext", -] diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 419f4cd..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/aead.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/aead.cpython-312.pyc deleted file mode 100644 index 8f3941a..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/aead.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-312.pyc deleted file mode 100644 index d46ed51..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-312.pyc deleted file mode 100644 index 2f5348c..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-312.pyc deleted file mode 100644 index 1491390..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/aead.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/aead.py deleted file mode 100644 index c8a582d..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/aead.py +++ /dev/null @@ -1,23 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl - -__all__ = [ - "AESCCM", - "AESGCM", - "AESGCMSIV", - "AESOCB3", - "AESSIV", - "ChaCha20Poly1305", -] - -AESGCM = rust_openssl.aead.AESGCM -ChaCha20Poly1305 = rust_openssl.aead.ChaCha20Poly1305 -AESCCM = rust_openssl.aead.AESCCM -AESSIV = rust_openssl.aead.AESSIV -AESOCB3 = rust_openssl.aead.AESOCB3 -AESGCMSIV = rust_openssl.aead.AESGCMSIV diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py deleted file mode 100644 index 6b20dd5..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/algorithms.py +++ /dev/null @@ -1,138 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography import utils -from cryptography.hazmat.decrepit.ciphers.algorithms import ( - ARC4 as ARC4, -) -from cryptography.hazmat.decrepit.ciphers.algorithms import ( - CAST5 as CAST5, -) -from cryptography.hazmat.decrepit.ciphers.algorithms import ( - IDEA as IDEA, -) -from cryptography.hazmat.decrepit.ciphers.algorithms import ( - SEED as SEED, -) -from cryptography.hazmat.decrepit.ciphers.algorithms import ( - Blowfish as Blowfish, -) -from cryptography.hazmat.decrepit.ciphers.algorithms import ( - Camellia as Camellia, -) -from cryptography.hazmat.decrepit.ciphers.algorithms import ( - TripleDES as TripleDES, -) -from cryptography.hazmat.primitives._cipheralgorithm import _verify_key_size -from cryptography.hazmat.primitives.ciphers import ( - BlockCipherAlgorithm, - CipherAlgorithm, -) - - -class AES(BlockCipherAlgorithm): - name = "AES" - block_size = 128 - # 512 added to support AES-256-XTS, which uses 512-bit keys - key_sizes = frozenset([128, 192, 256, 512]) - - def __init__(self, key: utils.Buffer): - self.key = _verify_key_size(self, key) - - @property - def key_size(self) -> int: - return len(self.key) * 8 - - -class AES128(BlockCipherAlgorithm): - name = "AES" - block_size = 128 - key_sizes = frozenset([128]) - key_size = 128 - - def __init__(self, key: utils.Buffer): - self.key = _verify_key_size(self, key) - - -class AES256(BlockCipherAlgorithm): - name = "AES" - block_size = 128 - key_sizes = frozenset([256]) - key_size = 256 - - def __init__(self, key: utils.Buffer): - self.key = _verify_key_size(self, key) - - -utils.deprecated( - Camellia, - __name__, - "Camellia has been moved to " - "cryptography.hazmat.decrepit.ciphers.algorithms.Camellia and " - "will be removed from " - "cryptography.hazmat.primitives.ciphers.algorithms in 49.0.0.", - utils.DeprecatedIn43, - name="Camellia", -) - - -utils.deprecated( - ARC4, - __name__, - "ARC4 has been moved to " - "cryptography.hazmat.decrepit.ciphers.algorithms.ARC4 and " - "will be removed from " - "cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.", - utils.DeprecatedIn43, - name="ARC4", -) - - -utils.deprecated( - TripleDES, - __name__, - "TripleDES has been moved to " - "cryptography.hazmat.decrepit.ciphers.algorithms.TripleDES and " - "will be removed from " - "cryptography.hazmat.primitives.ciphers.algorithms in 48.0.0.", - utils.DeprecatedIn43, - name="TripleDES", -) - - -class ChaCha20(CipherAlgorithm): - name = "ChaCha20" - key_sizes = frozenset([256]) - - def __init__(self, key: utils.Buffer, nonce: utils.Buffer): - self.key = _verify_key_size(self, key) - utils._check_byteslike("nonce", nonce) - - if len(nonce) != 16: - raise ValueError("nonce must be 128-bits (16 bytes)") - - self._nonce = nonce - - @property - def nonce(self) -> utils.Buffer: - return self._nonce - - @property - def key_size(self) -> int: - return len(self.key) * 8 - - -class SM4(BlockCipherAlgorithm): - name = "SM4" - block_size = 128 - key_sizes = frozenset([128]) - - def __init__(self, key: bytes): - self.key = _verify_key_size(self, key) - - @property - def key_size(self) -> int: - return len(self.key) * 8 diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/base.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/base.py deleted file mode 100644 index 24fceea..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/base.py +++ /dev/null @@ -1,146 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc -import typing - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives._cipheralgorithm import CipherAlgorithm -from cryptography.hazmat.primitives.ciphers import modes -from cryptography.utils import Buffer - - -class CipherContext(metaclass=abc.ABCMeta): - @abc.abstractmethod - def update(self, data: Buffer) -> bytes: - """ - Processes the provided bytes through the cipher and returns the results - as bytes. - """ - - @abc.abstractmethod - def update_into(self, data: Buffer, buf: Buffer) -> int: - """ - Processes the provided bytes and writes the resulting data into the - provided buffer. Returns the number of bytes written. - """ - - @abc.abstractmethod - def finalize(self) -> bytes: - """ - Returns the results of processing the final block as bytes. - """ - - @abc.abstractmethod - def reset_nonce(self, nonce: bytes) -> None: - """ - Resets the nonce for the cipher context to the provided value. - Raises an exception if it does not support reset or if the - provided nonce does not have a valid length. - """ - - -class AEADCipherContext(CipherContext, metaclass=abc.ABCMeta): - @abc.abstractmethod - def authenticate_additional_data(self, data: Buffer) -> None: - """ - Authenticates the provided bytes. - """ - - -class AEADDecryptionContext(AEADCipherContext, metaclass=abc.ABCMeta): - @abc.abstractmethod - def finalize_with_tag(self, tag: bytes) -> bytes: - """ - Returns the results of processing the final block as bytes and allows - delayed passing of the authentication tag. - """ - - -class AEADEncryptionContext(AEADCipherContext, metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def tag(self) -> bytes: - """ - Returns tag bytes. This is only available after encryption is - finalized. - """ - - -Mode = typing.TypeVar( - "Mode", bound=typing.Optional[modes.Mode], covariant=True -) - - -class Cipher(typing.Generic[Mode]): - def __init__( - self, - algorithm: CipherAlgorithm, - mode: Mode, - backend: typing.Any = None, - ) -> None: - if not isinstance(algorithm, CipherAlgorithm): - raise TypeError("Expected interface of CipherAlgorithm.") - - if mode is not None: - # mypy needs this assert to narrow the type from our generic - # type. Maybe it won't some time in the future. - assert isinstance(mode, modes.Mode) - mode.validate_for_algorithm(algorithm) - - self.algorithm = algorithm - self.mode = mode - - @typing.overload - def encryptor( - self: Cipher[modes.ModeWithAuthenticationTag], - ) -> AEADEncryptionContext: ... - - @typing.overload - def encryptor( - self: _CIPHER_TYPE, - ) -> CipherContext: ... - - def encryptor(self): - if isinstance(self.mode, modes.ModeWithAuthenticationTag): - if self.mode.tag is not None: - raise ValueError( - "Authentication tag must be None when encrypting." - ) - - return rust_openssl.ciphers.create_encryption_ctx( - self.algorithm, self.mode - ) - - @typing.overload - def decryptor( - self: Cipher[modes.ModeWithAuthenticationTag], - ) -> AEADDecryptionContext: ... - - @typing.overload - def decryptor( - self: _CIPHER_TYPE, - ) -> CipherContext: ... - - def decryptor(self): - return rust_openssl.ciphers.create_decryption_ctx( - self.algorithm, self.mode - ) - - -_CIPHER_TYPE = Cipher[ - typing.Union[ - modes.ModeWithNonce, - modes.ModeWithTweak, - modes.ECB, - modes.ModeWithInitializationVector, - None, - ] -] - -CipherContext.register(rust_openssl.ciphers.CipherContext) -AEADEncryptionContext.register(rust_openssl.ciphers.AEADEncryptionContext) -AEADDecryptionContext.register(rust_openssl.ciphers.AEADDecryptionContext) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/modes.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/modes.py deleted file mode 100644 index 0f1c217..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/ciphers/modes.py +++ /dev/null @@ -1,192 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography import utils -from cryptography.exceptions import UnsupportedAlgorithm, _Reasons -from cryptography.hazmat.decrepit.ciphers.modes import CFB as CFB -from cryptography.hazmat.decrepit.ciphers.modes import CFB8 as CFB8 -from cryptography.hazmat.decrepit.ciphers.modes import OFB as OFB -from cryptography.hazmat.primitives._cipheralgorithm import ( - BlockCipherAlgorithm, - CipherAlgorithm, -) -from cryptography.hazmat.primitives._modes import ( - Mode as Mode, -) -from cryptography.hazmat.primitives._modes import ( - ModeWithAuthenticationTag as ModeWithAuthenticationTag, -) -from cryptography.hazmat.primitives._modes import ( - ModeWithInitializationVector as ModeWithInitializationVector, -) -from cryptography.hazmat.primitives._modes import ( - ModeWithNonce as ModeWithNonce, -) -from cryptography.hazmat.primitives._modes import ( - ModeWithTweak as ModeWithTweak, -) -from cryptography.hazmat.primitives._modes import ( - _check_aes_key_length, - _check_iv_and_key_length, - _check_nonce_length, -) -from cryptography.hazmat.primitives.ciphers import algorithms - - -class CBC(ModeWithInitializationVector): - name = "CBC" - - def __init__(self, initialization_vector: utils.Buffer): - utils._check_byteslike("initialization_vector", initialization_vector) - self._initialization_vector = initialization_vector - - @property - def initialization_vector(self) -> utils.Buffer: - return self._initialization_vector - - validate_for_algorithm = _check_iv_and_key_length - - -class XTS(ModeWithTweak): - name = "XTS" - - def __init__(self, tweak: utils.Buffer): - utils._check_byteslike("tweak", tweak) - - if len(tweak) != 16: - raise ValueError("tweak must be 128-bits (16 bytes)") - - self._tweak = tweak - - @property - def tweak(self) -> utils.Buffer: - return self._tweak - - def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: - if isinstance(algorithm, (algorithms.AES128, algorithms.AES256)): - raise TypeError( - "The AES128 and AES256 classes do not support XTS, please use " - "the standard AES class instead." - ) - - if algorithm.key_size not in (256, 512): - raise ValueError( - "The XTS specification requires a 256-bit key for AES-128-XTS" - " and 512-bit key for AES-256-XTS" - ) - - -class ECB(Mode): - name = "ECB" - - validate_for_algorithm = _check_aes_key_length - - -class CTR(ModeWithNonce): - name = "CTR" - - def __init__(self, nonce: utils.Buffer): - utils._check_byteslike("nonce", nonce) - self._nonce = nonce - - @property - def nonce(self) -> utils.Buffer: - return self._nonce - - def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: - _check_aes_key_length(self, algorithm) - _check_nonce_length(self.nonce, self.name, algorithm) - - -class GCM(ModeWithInitializationVector, ModeWithAuthenticationTag): - name = "GCM" - _MAX_ENCRYPTED_BYTES = (2**39 - 256) // 8 - _MAX_AAD_BYTES = (2**64) // 8 - - def __init__( - self, - initialization_vector: utils.Buffer, - tag: bytes | None = None, - min_tag_length: int = 16, - ): - # OpenSSL 3.0.0 constrains GCM IVs to [64, 1024] bits inclusive - # This is a sane limit anyway so we'll enforce it here. - utils._check_byteslike("initialization_vector", initialization_vector) - if len(initialization_vector) < 8 or len(initialization_vector) > 128: - raise ValueError( - "initialization_vector must be between 8 and 128 bytes (64 " - "and 1024 bits)." - ) - self._initialization_vector = initialization_vector - if tag is not None: - utils._check_bytes("tag", tag) - if min_tag_length < 4: - raise ValueError("min_tag_length must be >= 4") - if len(tag) < min_tag_length: - raise ValueError( - f"Authentication tag must be {min_tag_length} bytes or " - "longer." - ) - self._tag = tag - self._min_tag_length = min_tag_length - - @property - def tag(self) -> bytes | None: - return self._tag - - @property - def initialization_vector(self) -> utils.Buffer: - return self._initialization_vector - - def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: - _check_aes_key_length(self, algorithm) - if not isinstance(algorithm, BlockCipherAlgorithm): - raise UnsupportedAlgorithm( - "GCM requires a block cipher algorithm", - _Reasons.UNSUPPORTED_CIPHER, - ) - block_size_bytes = algorithm.block_size // 8 - if self._tag is not None and len(self._tag) > block_size_bytes: - raise ValueError( - f"Authentication tag cannot be more than {block_size_bytes} " - "bytes." - ) - - -utils.deprecated( - OFB, - __name__, - "OFB has been moved to " - "cryptography.hazmat.decrepit.ciphers.modes.OFB and " - "will be removed from " - "cryptography.hazmat.primitives.ciphers.modes in 49.0.0.", - utils.DeprecatedIn47, - name="OFB", -) - - -utils.deprecated( - CFB, - __name__, - "CFB has been moved to " - "cryptography.hazmat.decrepit.ciphers.modes.CFB and " - "will be removed from " - "cryptography.hazmat.primitives.ciphers.modes in 49.0.0.", - utils.DeprecatedIn47, - name="CFB", -) - - -utils.deprecated( - CFB8, - __name__, - "CFB8 has been moved to " - "cryptography.hazmat.decrepit.ciphers.modes.CFB8 and " - "will be removed from " - "cryptography.hazmat.primitives.ciphers.modes in 49.0.0.", - utils.DeprecatedIn47, - name="CFB8", -) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/cmac.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/cmac.py deleted file mode 100644 index 2c67ce2..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/cmac.py +++ /dev/null @@ -1,10 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl - -__all__ = ["CMAC"] -CMAC = rust_openssl.cmac.CMAC diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/constant_time.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/constant_time.py deleted file mode 100644 index 3975c71..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/constant_time.py +++ /dev/null @@ -1,14 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import hmac - - -def bytes_eq(a: bytes, b: bytes) -> bool: - if not isinstance(a, bytes) or not isinstance(b, bytes): - raise TypeError("a and b must be bytes.") - - return hmac.compare_digest(a, b) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/hashes.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/hashes.py deleted file mode 100644 index 4b55ec3..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/hashes.py +++ /dev/null @@ -1,246 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.utils import Buffer - -__all__ = [ - "MD5", - "SHA1", - "SHA3_224", - "SHA3_256", - "SHA3_384", - "SHA3_512", - "SHA224", - "SHA256", - "SHA384", - "SHA512", - "SHA512_224", - "SHA512_256", - "SHAKE128", - "SHAKE256", - "SM3", - "BLAKE2b", - "BLAKE2s", - "ExtendableOutputFunction", - "Hash", - "HashAlgorithm", - "HashContext", - "XOFHash", -] - - -class HashAlgorithm(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def name(self) -> str: - """ - A string naming this algorithm (e.g. "sha256", "md5"). - """ - - @property - @abc.abstractmethod - def digest_size(self) -> int: - """ - The size of the resulting digest in bytes. - """ - - @property - @abc.abstractmethod - def block_size(self) -> int | None: - """ - The internal block size of the hash function, or None if the hash - function does not use blocks internally (e.g. SHA3). - """ - - -class HashContext(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def algorithm(self) -> HashAlgorithm: - """ - A HashAlgorithm that will be used by this context. - """ - - @abc.abstractmethod - def update(self, data: Buffer) -> None: - """ - Processes the provided bytes through the hash. - """ - - @abc.abstractmethod - def finalize(self) -> bytes: - """ - Finalizes the hash context and returns the hash digest as bytes. - """ - - @abc.abstractmethod - def copy(self) -> HashContext: - """ - Return a HashContext that is a copy of the current context. - """ - - -Hash = rust_openssl.hashes.Hash -HashContext.register(Hash) - -XOFHash = rust_openssl.hashes.XOFHash - - -class ExtendableOutputFunction(metaclass=abc.ABCMeta): - """ - An interface for extendable output functions. - """ - - -class SHA1(HashAlgorithm): - name = "sha1" - digest_size = 20 - block_size = 64 - - -class SHA512_224(HashAlgorithm): # noqa: N801 - name = "sha512-224" - digest_size = 28 - block_size = 128 - - -class SHA512_256(HashAlgorithm): # noqa: N801 - name = "sha512-256" - digest_size = 32 - block_size = 128 - - -class SHA224(HashAlgorithm): - name = "sha224" - digest_size = 28 - block_size = 64 - - -class SHA256(HashAlgorithm): - name = "sha256" - digest_size = 32 - block_size = 64 - - -class SHA384(HashAlgorithm): - name = "sha384" - digest_size = 48 - block_size = 128 - - -class SHA512(HashAlgorithm): - name = "sha512" - digest_size = 64 - block_size = 128 - - -class SHA3_224(HashAlgorithm): # noqa: N801 - name = "sha3-224" - digest_size = 28 - block_size = None - - -class SHA3_256(HashAlgorithm): # noqa: N801 - name = "sha3-256" - digest_size = 32 - block_size = None - - -class SHA3_384(HashAlgorithm): # noqa: N801 - name = "sha3-384" - digest_size = 48 - block_size = None - - -class SHA3_512(HashAlgorithm): # noqa: N801 - name = "sha3-512" - digest_size = 64 - block_size = None - - -class SHAKE128(HashAlgorithm, ExtendableOutputFunction): - name = "shake128" - block_size = None - - def __init__(self, digest_size: int): - if not isinstance(digest_size, int): - raise TypeError("digest_size must be an integer") - - if digest_size < 1: - raise ValueError("digest_size must be a positive integer") - - self._digest_size = digest_size - - @property - def digest_size(self) -> int: - return self._digest_size - - -class SHAKE256(HashAlgorithm, ExtendableOutputFunction): - name = "shake256" - block_size = None - - def __init__(self, digest_size: int): - if not isinstance(digest_size, int): - raise TypeError("digest_size must be an integer") - - if digest_size < 1: - raise ValueError("digest_size must be a positive integer") - - self._digest_size = digest_size - - @property - def digest_size(self) -> int: - return self._digest_size - - -class MD5(HashAlgorithm): - name = "md5" - digest_size = 16 - block_size = 64 - - -class BLAKE2b(HashAlgorithm): - name = "blake2b" - _max_digest_size = 64 - _min_digest_size = 1 - block_size = 128 - - def __init__(self, digest_size: int): - if digest_size != 64: - raise ValueError("Digest size must be 64") - - self._digest_size = digest_size - - @property - def digest_size(self) -> int: - return self._digest_size - - -class BLAKE2s(HashAlgorithm): - name = "blake2s" - block_size = 64 - _max_digest_size = 32 - _min_digest_size = 1 - - def __init__(self, digest_size: int): - if digest_size != 32: - raise ValueError("Digest size must be 32") - - self._digest_size = digest_size - - @property - def digest_size(self) -> int: - return self._digest_size - - -class SM3(HashAlgorithm): - name = "sm3" - digest_size = 32 - block_size = 64 diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/hmac.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/hmac.py deleted file mode 100644 index a9442d5..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/hmac.py +++ /dev/null @@ -1,13 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives import hashes - -__all__ = ["HMAC"] - -HMAC = rust_openssl.hmac.HMAC -hashes.HashContext.register(HMAC) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/hpke.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/hpke.py deleted file mode 100644 index c802808..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/hpke.py +++ /dev/null @@ -1,27 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl - -AEAD = rust_openssl.hpke.AEAD -KDF = rust_openssl.hpke.KDF -KEM = rust_openssl.hpke.KEM -MLKEM768X25519PrivateKey = rust_openssl.hpke.MLKEM768X25519PrivateKey -MLKEM768X25519PublicKey = rust_openssl.hpke.MLKEM768X25519PublicKey -MLKEM1024P384PrivateKey = rust_openssl.hpke.MLKEM1024P384PrivateKey -MLKEM1024P384PublicKey = rust_openssl.hpke.MLKEM1024P384PublicKey -Suite = rust_openssl.hpke.Suite - -__all__ = [ - "AEAD", - "KDF", - "KEM", - "MLKEM768X25519PrivateKey", - "MLKEM768X25519PublicKey", - "MLKEM1024P384PrivateKey", - "MLKEM1024P384PublicKey", - "Suite", -] diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__init__.py deleted file mode 100644 index 26c45bd..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__init__.py +++ /dev/null @@ -1,32 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -from cryptography.utils import Buffer - - -class KeyDerivationFunction(metaclass=abc.ABCMeta): - @abc.abstractmethod - def derive(self, key_material: bytes) -> bytes: - """ - Deterministically generates and returns a new key based on the existing - key material. - """ - - @abc.abstractmethod - def derive_into(self, key_material: bytes, buffer: Buffer) -> None: - """ - Deterministically generates a new key based on the existing key - material and stores it in the provided buffer. - """ - - @abc.abstractmethod - def verify(self, key_material: bytes, expected_key: bytes) -> None: - """ - Checks whether the key generated by the key material matches the - expected derived key. Raises an exception if they do not match. - """ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index f57074e..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/argon2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/argon2.cpython-312.pyc deleted file mode 100644 index 68d7ac2..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/argon2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-312.pyc deleted file mode 100644 index 70ec09b..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-312.pyc deleted file mode 100644 index 9416271..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-312.pyc deleted file mode 100644 index 4a0962a..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-312.pyc deleted file mode 100644 index 1255da2..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-312.pyc deleted file mode 100644 index 9902153..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-312.pyc deleted file mode 100644 index abff2e2..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/argon2.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/argon2.py deleted file mode 100644 index 03e84d4..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/argon2.py +++ /dev/null @@ -1,17 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives.kdf import KeyDerivationFunction - -Argon2d = rust_openssl.kdf.Argon2d -Argon2i = rust_openssl.kdf.Argon2i -Argon2id = rust_openssl.kdf.Argon2id -KeyDerivationFunction.register(Argon2d) -KeyDerivationFunction.register(Argon2i) -KeyDerivationFunction.register(Argon2id) - -__all__ = ["Argon2d", "Argon2i", "Argon2id"] diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/concatkdf.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/concatkdf.py deleted file mode 100644 index 398dc5d..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/concatkdf.py +++ /dev/null @@ -1,16 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives.kdf import KeyDerivationFunction - -ConcatKDFHash = rust_openssl.kdf.ConcatKDFHash -ConcatKDFHMAC = rust_openssl.kdf.ConcatKDFHMAC - -KeyDerivationFunction.register(ConcatKDFHash) -KeyDerivationFunction.register(ConcatKDFHMAC) - -__all__ = ["ConcatKDFHMAC", "ConcatKDFHash"] diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py deleted file mode 100644 index 1e162d9..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/hkdf.py +++ /dev/null @@ -1,16 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives.kdf import KeyDerivationFunction - -HKDF = rust_openssl.kdf.HKDF -HKDFExpand = rust_openssl.kdf.HKDFExpand - -KeyDerivationFunction.register(HKDF) -KeyDerivationFunction.register(HKDFExpand) - -__all__ = ["HKDF", "HKDFExpand"] diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py deleted file mode 100644 index e559df8..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/kbkdf.py +++ /dev/null @@ -1,26 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography import utils -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives.kdf import KeyDerivationFunction - - -class Mode(utils.Enum): - CounterMode = "ctr" - - -class CounterLocation(utils.Enum): - BeforeFixed = "before_fixed" - AfterFixed = "after_fixed" - MiddleFixed = "middle_fixed" - - -KBKDFHMAC = rust_openssl.kdf.KBKDFHMAC -KeyDerivationFunction.register(KBKDFHMAC) - -KBKDFCMAC = rust_openssl.kdf.KBKDFCMAC -KeyDerivationFunction.register(KBKDFCMAC) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/pbkdf2.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/pbkdf2.py deleted file mode 100644 index 771d80d..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/pbkdf2.py +++ /dev/null @@ -1,13 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives.kdf import KeyDerivationFunction - -PBKDF2HMAC = rust_openssl.kdf.PBKDF2HMAC -KeyDerivationFunction.register(PBKDF2HMAC) - -__all__ = ["PBKDF2HMAC"] diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/scrypt.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/scrypt.py deleted file mode 100644 index f791cee..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/scrypt.py +++ /dev/null @@ -1,19 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import sys - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives.kdf import KeyDerivationFunction - -# This is used by the scrypt tests to skip tests that require more memory -# than the MEM_LIMIT -_MEM_LIMIT = sys.maxsize // 2 - -Scrypt = rust_openssl.kdf.Scrypt -KeyDerivationFunction.register(Scrypt) - -__all__ = ["Scrypt"] diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/x963kdf.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/x963kdf.py deleted file mode 100644 index 8c4e2d3..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/kdf/x963kdf.py +++ /dev/null @@ -1,13 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl -from cryptography.hazmat.primitives.kdf import KeyDerivationFunction - -X963KDF = rust_openssl.kdf.X963KDF -KeyDerivationFunction.register(X963KDF) - -__all__ = ["X963KDF"] diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/keywrap.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/keywrap.py deleted file mode 100644 index a3e56b9..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/keywrap.py +++ /dev/null @@ -1,180 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import typing - -from cryptography.hazmat.primitives.ciphers import Cipher -from cryptography.hazmat.primitives.ciphers.algorithms import AES -from cryptography.hazmat.primitives.ciphers.modes import ECB -from cryptography.hazmat.primitives.constant_time import bytes_eq - - -def _wrap_core( - wrapping_key: bytes, - a: bytes, - r: list[bytes], -) -> bytes: - # RFC 3394 Key Wrap - 2.2.1 (index method) - encryptor = Cipher(AES(wrapping_key), ECB()).encryptor() - n = len(r) - for j in range(6): - for i in range(n): - # every encryption operation is a discrete 16 byte chunk (because - # AES has a 128-bit block size) and since we're using ECB it is - # safe to reuse the encryptor for the entire operation - b = encryptor.update(a + r[i]) - a = ( - int.from_bytes(b[:8], byteorder="big") ^ ((n * j) + i + 1) - ).to_bytes(length=8, byteorder="big") - r[i] = b[-8:] - - assert encryptor.finalize() == b"" - - return a + b"".join(r) - - -def aes_key_wrap( - wrapping_key: bytes, - key_to_wrap: bytes, - backend: typing.Any = None, -) -> bytes: - if len(wrapping_key) not in [16, 24, 32]: - raise ValueError("The wrapping key must be a valid AES key length") - - if len(key_to_wrap) < 16: - raise ValueError("The key to wrap must be at least 16 bytes") - - if len(key_to_wrap) % 8 != 0: - raise ValueError("The key to wrap must be a multiple of 8 bytes") - - a = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" - r = [key_to_wrap[i : i + 8] for i in range(0, len(key_to_wrap), 8)] - return _wrap_core(wrapping_key, a, r) - - -def _unwrap_core( - wrapping_key: bytes, - a: bytes, - r: list[bytes], -) -> tuple[bytes, list[bytes]]: - # Implement RFC 3394 Key Unwrap - 2.2.2 (index method) - decryptor = Cipher(AES(wrapping_key), ECB()).decryptor() - n = len(r) - for j in reversed(range(6)): - for i in reversed(range(n)): - atr = ( - int.from_bytes(a, byteorder="big") ^ ((n * j) + i + 1) - ).to_bytes(length=8, byteorder="big") + r[i] - # every decryption operation is a discrete 16 byte chunk so - # it is safe to reuse the decryptor for the entire operation - b = decryptor.update(atr) - a = b[:8] - r[i] = b[-8:] - - assert decryptor.finalize() == b"" - return a, r - - -def aes_key_wrap_with_padding( - wrapping_key: bytes, - key_to_wrap: bytes, - backend: typing.Any = None, -) -> bytes: - if len(wrapping_key) not in [16, 24, 32]: - raise ValueError("The wrapping key must be a valid AES key length") - - if not key_to_wrap or len(key_to_wrap) > 2**32: - raise ValueError("key_to_wrap must be between 1 and 2^32 bytes") - - aiv = b"\xa6\x59\x59\xa6" + len(key_to_wrap).to_bytes( - length=4, byteorder="big" - ) - # pad the key to wrap if necessary - pad = (8 - (len(key_to_wrap) % 8)) % 8 - key_to_wrap = key_to_wrap + b"\x00" * pad - if len(key_to_wrap) == 8: - # RFC 5649 - 4.1 - exactly 8 octets after padding - encryptor = Cipher(AES(wrapping_key), ECB()).encryptor() - b = encryptor.update(aiv + key_to_wrap) - assert encryptor.finalize() == b"" - return b - else: - r = [key_to_wrap[i : i + 8] for i in range(0, len(key_to_wrap), 8)] - return _wrap_core(wrapping_key, aiv, r) - - -def aes_key_unwrap_with_padding( - wrapping_key: bytes, - wrapped_key: bytes, - backend: typing.Any = None, -) -> bytes: - if len(wrapped_key) < 16: - raise InvalidUnwrap("Must be at least 16 bytes") - - if len(wrapping_key) not in [16, 24, 32]: - raise ValueError("The wrapping key must be a valid AES key length") - - if len(wrapped_key) == 16: - # RFC 5649 - 4.2 - exactly two 64-bit blocks - decryptor = Cipher(AES(wrapping_key), ECB()).decryptor() - out = decryptor.update(wrapped_key) - assert decryptor.finalize() == b"" - a = out[:8] - data = out[8:] - n = 1 - else: - r = [wrapped_key[i : i + 8] for i in range(0, len(wrapped_key), 8)] - encrypted_aiv = r.pop(0) - n = len(r) - a, r = _unwrap_core(wrapping_key, encrypted_aiv, r) - data = b"".join(r) - - # 1) Check that MSB(32,A) = A65959A6. - # 2) Check that 8*(n-1) < LSB(32,A) <= 8*n. If so, let - # MLI = LSB(32,A). - # 3) Let b = (8*n)-MLI, and then check that the rightmost b octets of - # the output data are zero. - mli = int.from_bytes(a[4:], byteorder="big") - b = (8 * n) - mli - if ( - not bytes_eq(a[:4], b"\xa6\x59\x59\xa6") - or not 8 * (n - 1) < mli <= 8 * n - or (b != 0 and not bytes_eq(data[-b:], b"\x00" * b)) - ): - raise InvalidUnwrap() - - if b == 0: - return data - else: - return data[:-b] - - -def aes_key_unwrap( - wrapping_key: bytes, - wrapped_key: bytes, - backend: typing.Any = None, -) -> bytes: - if len(wrapped_key) < 24: - raise InvalidUnwrap("Must be at least 24 bytes") - - if len(wrapped_key) % 8 != 0: - raise InvalidUnwrap("The wrapped key must be a multiple of 8 bytes") - - if len(wrapping_key) not in [16, 24, 32]: - raise ValueError("The wrapping key must be a valid AES key length") - - aiv = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" - r = [wrapped_key[i : i + 8] for i in range(0, len(wrapped_key), 8)] - a = r.pop(0) - a, r = _unwrap_core(wrapping_key, a, r) - if not bytes_eq(a, aiv): - raise InvalidUnwrap() - - return b"".join(r) - - -class InvalidUnwrap(Exception): - pass diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/padding.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/padding.py deleted file mode 100644 index f9cd1f1..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/padding.py +++ /dev/null @@ -1,69 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc - -from cryptography import utils -from cryptography.hazmat.bindings._rust import ( - ANSIX923PaddingContext, - ANSIX923UnpaddingContext, - PKCS7PaddingContext, - PKCS7UnpaddingContext, -) - - -class PaddingContext(metaclass=abc.ABCMeta): - @abc.abstractmethod - def update(self, data: utils.Buffer) -> bytes: - """ - Pads the provided bytes and returns any available data as bytes. - """ - - @abc.abstractmethod - def finalize(self) -> bytes: - """ - Finalize the padding, returns bytes. - """ - - -def _byte_padding_check(block_size: int) -> None: - if not (0 <= block_size <= 2040): - raise ValueError("block_size must be in range(0, 2041).") - - if block_size % 8 != 0: - raise ValueError("block_size must be a multiple of 8.") - - -class PKCS7: - def __init__(self, block_size: int): - _byte_padding_check(block_size) - self.block_size = block_size - - def padder(self) -> PaddingContext: - return PKCS7PaddingContext(self.block_size) - - def unpadder(self) -> PaddingContext: - return PKCS7UnpaddingContext(self.block_size) - - -PaddingContext.register(PKCS7PaddingContext) -PaddingContext.register(PKCS7UnpaddingContext) - - -class ANSIX923: - def __init__(self, block_size: int): - _byte_padding_check(block_size) - self.block_size = block_size - - def padder(self) -> PaddingContext: - return ANSIX923PaddingContext(self.block_size) - - def unpadder(self) -> PaddingContext: - return ANSIX923UnpaddingContext(self.block_size) - - -PaddingContext.register(ANSIX923PaddingContext) -PaddingContext.register(ANSIX923UnpaddingContext) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/poly1305.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/poly1305.py deleted file mode 100644 index 7f5a77a..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/poly1305.py +++ /dev/null @@ -1,11 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl - -__all__ = ["Poly1305"] - -Poly1305 = rust_openssl.poly1305.Poly1305 diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__init__.py deleted file mode 100644 index 62283cc..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__init__.py +++ /dev/null @@ -1,65 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat.primitives._serialization import ( - BestAvailableEncryption, - Encoding, - KeySerializationEncryption, - NoEncryption, - ParameterFormat, - PrivateFormat, - PublicFormat, - _KeySerializationEncryption, -) -from cryptography.hazmat.primitives.serialization.base import ( - load_der_parameters, - load_der_private_key, - load_der_public_key, - load_pem_parameters, - load_pem_private_key, - load_pem_public_key, -) -from cryptography.hazmat.primitives.serialization.ssh import ( - SSHCertificate, - SSHCertificateBuilder, - SSHCertificateType, - SSHCertPrivateKeyTypes, - SSHCertPublicKeyTypes, - SSHPrivateKeyTypes, - SSHPublicKeyTypes, - load_ssh_private_key, - load_ssh_public_identity, - load_ssh_public_key, - ssh_key_fingerprint, -) - -__all__ = [ - "BestAvailableEncryption", - "Encoding", - "KeySerializationEncryption", - "NoEncryption", - "ParameterFormat", - "PrivateFormat", - "PublicFormat", - "SSHCertPrivateKeyTypes", - "SSHCertPublicKeyTypes", - "SSHCertificate", - "SSHCertificateBuilder", - "SSHCertificateType", - "SSHPrivateKeyTypes", - "SSHPublicKeyTypes", - "_KeySerializationEncryption", - "load_der_parameters", - "load_der_private_key", - "load_der_public_key", - "load_pem_parameters", - "load_pem_private_key", - "load_pem_public_key", - "load_ssh_private_key", - "load_ssh_public_identity", - "load_ssh_public_key", - "ssh_key_fingerprint", -] diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 083eac4..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-312.pyc deleted file mode 100644 index d0dadd0..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-312.pyc deleted file mode 100644 index eb8a06a..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs7.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs7.cpython-312.pyc deleted file mode 100644 index 4668af5..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs7.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-312.pyc deleted file mode 100644 index 4fa9bee..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/base.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/base.py deleted file mode 100644 index e7c998b..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/base.py +++ /dev/null @@ -1,14 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from cryptography.hazmat.bindings._rust import openssl as rust_openssl - -load_pem_private_key = rust_openssl.keys.load_pem_private_key -load_der_private_key = rust_openssl.keys.load_der_private_key - -load_pem_public_key = rust_openssl.keys.load_pem_public_key -load_der_public_key = rust_openssl.keys.load_der_public_key - -load_pem_parameters = rust_openssl.dh.from_pem_parameters -load_der_parameters = rust_openssl.dh.from_der_parameters diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs12.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs12.py deleted file mode 100644 index 58884ff..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs12.py +++ /dev/null @@ -1,176 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import typing -from collections.abc import Iterable - -from cryptography import x509 -from cryptography.hazmat.bindings._rust import pkcs12 as rust_pkcs12 -from cryptography.hazmat.primitives import serialization -from cryptography.hazmat.primitives._serialization import PBES as PBES -from cryptography.hazmat.primitives.asymmetric import ( - dsa, - ec, - ed448, - ed25519, - rsa, -) -from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes - -__all__ = [ - "PBES", - "PKCS12Certificate", - "PKCS12KeyAndCertificates", - "PKCS12PrivateKeyTypes", - "load_key_and_certificates", - "load_pkcs12", - "serialize_java_truststore", - "serialize_key_and_certificates", -] - -PKCS12PrivateKeyTypes = typing.Union[ - rsa.RSAPrivateKey, - dsa.DSAPrivateKey, - ec.EllipticCurvePrivateKey, - ed25519.Ed25519PrivateKey, - ed448.Ed448PrivateKey, -] - - -PKCS12Certificate = rust_pkcs12.PKCS12Certificate - - -class PKCS12KeyAndCertificates: - def __init__( - self, - key: PrivateKeyTypes | None, - cert: PKCS12Certificate | None, - additional_certs: list[PKCS12Certificate], - ): - if key is not None and not isinstance( - key, - ( - rsa.RSAPrivateKey, - dsa.DSAPrivateKey, - ec.EllipticCurvePrivateKey, - ed25519.Ed25519PrivateKey, - ed448.Ed448PrivateKey, - ), - ): - raise TypeError( - "Key must be RSA, DSA, EllipticCurve, ED25519, or ED448" - " private key, or None." - ) - if cert is not None and not isinstance(cert, PKCS12Certificate): - raise TypeError("cert must be a PKCS12Certificate object or None") - if not all( - isinstance(add_cert, PKCS12Certificate) - for add_cert in additional_certs - ): - raise TypeError( - "all values in additional_certs must be PKCS12Certificate" - " objects" - ) - self._key = key - self._cert = cert - self._additional_certs = additional_certs - - @property - def key(self) -> PrivateKeyTypes | None: - return self._key - - @property - def cert(self) -> PKCS12Certificate | None: - return self._cert - - @property - def additional_certs(self) -> list[PKCS12Certificate]: - return self._additional_certs - - def __eq__(self, other: object) -> bool: - if not isinstance(other, PKCS12KeyAndCertificates): - return NotImplemented - - return ( - self.key == other.key - and self.cert == other.cert - and self.additional_certs == other.additional_certs - ) - - def __hash__(self) -> int: - return hash((self.key, self.cert, tuple(self.additional_certs))) - - def __repr__(self) -> str: - fmt = ( - "" - ) - return fmt.format(self.key, self.cert, self.additional_certs) - - -load_key_and_certificates = rust_pkcs12.load_key_and_certificates -load_pkcs12 = rust_pkcs12.load_pkcs12 - - -_PKCS12CATypes = typing.Union[ - x509.Certificate, - PKCS12Certificate, -] - - -def serialize_java_truststore( - certs: Iterable[PKCS12Certificate], - encryption_algorithm: serialization.KeySerializationEncryption, -) -> bytes: - if not certs: - raise ValueError("You must supply at least one cert") - - if not isinstance( - encryption_algorithm, serialization.KeySerializationEncryption - ): - raise TypeError( - "Key encryption algorithm must be a " - "KeySerializationEncryption instance" - ) - - return rust_pkcs12.serialize_java_truststore(certs, encryption_algorithm) - - -def serialize_key_and_certificates( - name: bytes | None, - key: PKCS12PrivateKeyTypes | None, - cert: x509.Certificate | None, - cas: Iterable[_PKCS12CATypes] | None, - encryption_algorithm: serialization.KeySerializationEncryption, -) -> bytes: - if key is not None and not isinstance( - key, - ( - rsa.RSAPrivateKey, - dsa.DSAPrivateKey, - ec.EllipticCurvePrivateKey, - ed25519.Ed25519PrivateKey, - ed448.Ed448PrivateKey, - ), - ): - raise TypeError( - "Key must be RSA, DSA, EllipticCurve, ED25519, or ED448" - " private key, or None." - ) - - if not isinstance( - encryption_algorithm, serialization.KeySerializationEncryption - ): - raise TypeError( - "Key encryption algorithm must be a " - "KeySerializationEncryption instance" - ) - - if key is None and cert is None and not cas: - raise ValueError("You must supply at least one of key, cert, or cas") - - return rust_pkcs12.serialize_key_and_certificates( - name, key, cert, cas, encryption_algorithm - ) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs7.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs7.py deleted file mode 100644 index 76b667a..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/pkcs7.py +++ /dev/null @@ -1,412 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import email.base64mime -import email.generator -import email.message -import email.policy -import io -import typing -from collections.abc import Iterable - -from cryptography import utils, x509 -from cryptography.exceptions import UnsupportedAlgorithm, _Reasons -from cryptography.hazmat.bindings._rust import pkcs7 as rust_pkcs7 -from cryptography.hazmat.primitives import hashes, serialization -from cryptography.hazmat.primitives.asymmetric import ec, padding, rsa -from cryptography.hazmat.primitives.ciphers import ( - algorithms, -) -from cryptography.utils import _check_byteslike - -load_pem_pkcs7_certificates = rust_pkcs7.load_pem_pkcs7_certificates - -load_der_pkcs7_certificates = rust_pkcs7.load_der_pkcs7_certificates - -serialize_certificates = rust_pkcs7.serialize_certificates - -PKCS7HashTypes = typing.Union[ - hashes.SHA224, - hashes.SHA256, - hashes.SHA384, - hashes.SHA512, -] - -PKCS7PrivateKeyTypes = typing.Union[ - rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey -] - -ContentEncryptionAlgorithm = typing.Union[ - type[algorithms.AES128], type[algorithms.AES256] -] - - -class PKCS7Options(utils.Enum): - Text = "Add text/plain MIME type" - Binary = "Don't translate input data into canonical MIME format" - DetachedSignature = "Don't embed data in the PKCS7 structure" - NoCapabilities = "Don't embed SMIME capabilities" - NoAttributes = "Don't embed authenticatedAttributes" - NoCerts = "Don't embed signer certificate" - - -class PKCS7SignatureBuilder: - def __init__( - self, - data: utils.Buffer | None = None, - signers: list[ - tuple[ - x509.Certificate, - PKCS7PrivateKeyTypes, - PKCS7HashTypes, - padding.PSS | padding.PKCS1v15 | None, - ] - ] = [], - additional_certs: list[x509.Certificate] = [], - ): - self._data = data - self._signers = signers - self._additional_certs = additional_certs - - def set_data(self, data: utils.Buffer) -> PKCS7SignatureBuilder: - _check_byteslike("data", data) - if self._data is not None: - raise ValueError("data may only be set once") - - return PKCS7SignatureBuilder(data, self._signers) - - def add_signer( - self, - certificate: x509.Certificate, - private_key: PKCS7PrivateKeyTypes, - hash_algorithm: PKCS7HashTypes, - *, - rsa_padding: padding.PSS | padding.PKCS1v15 | None = None, - ) -> PKCS7SignatureBuilder: - if not isinstance( - hash_algorithm, - ( - hashes.SHA224, - hashes.SHA256, - hashes.SHA384, - hashes.SHA512, - ), - ): - raise TypeError( - "hash_algorithm must be one of hashes.SHA224, " - "SHA256, SHA384, or SHA512" - ) - if not isinstance(certificate, x509.Certificate): - raise TypeError("certificate must be a x509.Certificate") - - if not isinstance( - private_key, (rsa.RSAPrivateKey, ec.EllipticCurvePrivateKey) - ): - raise TypeError("Only RSA & EC keys are supported at this time.") - - if rsa_padding is not None: - if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)): - raise TypeError("Padding must be PSS or PKCS1v15") - if not isinstance(private_key, rsa.RSAPrivateKey): - raise TypeError("Padding is only supported for RSA keys") - - return PKCS7SignatureBuilder( - self._data, - [ - *self._signers, - (certificate, private_key, hash_algorithm, rsa_padding), - ], - ) - - def add_certificate( - self, certificate: x509.Certificate - ) -> PKCS7SignatureBuilder: - if not isinstance(certificate, x509.Certificate): - raise TypeError("certificate must be a x509.Certificate") - - return PKCS7SignatureBuilder( - self._data, self._signers, [*self._additional_certs, certificate] - ) - - def sign( - self, - encoding: serialization.Encoding, - options: Iterable[PKCS7Options], - backend: typing.Any = None, - ) -> bytes: - if len(self._signers) == 0: - raise ValueError("Must have at least one signer") - if self._data is None: - raise ValueError("You must add data to sign") - options = list(options) - if not all(isinstance(x, PKCS7Options) for x in options): - raise ValueError("options must be from the PKCS7Options enum") - if encoding not in ( - serialization.Encoding.PEM, - serialization.Encoding.DER, - serialization.Encoding.SMIME, - ): - raise ValueError( - "Must be PEM, DER, or SMIME from the Encoding enum" - ) - - # Text is a meaningless option unless it is accompanied by - # DetachedSignature - if ( - PKCS7Options.Text in options - and PKCS7Options.DetachedSignature not in options - ): - raise ValueError( - "When passing the Text option you must also pass " - "DetachedSignature" - ) - - if PKCS7Options.Text in options and encoding in ( - serialization.Encoding.DER, - serialization.Encoding.PEM, - ): - raise ValueError( - "The Text option is only available for SMIME serialization" - ) - - # No attributes implies no capabilities so we'll error if you try to - # pass both. - if ( - PKCS7Options.NoAttributes in options - and PKCS7Options.NoCapabilities in options - ): - raise ValueError( - "NoAttributes is a superset of NoCapabilities. Do not pass " - "both values." - ) - - return rust_pkcs7.sign_and_serialize(self, encoding, options) - - -class PKCS7EnvelopeBuilder: - def __init__( - self, - *, - _data: bytes | None = None, - _recipients: list[x509.Certificate] | None = None, - _content_encryption_algorithm: ContentEncryptionAlgorithm - | None = None, - ): - from cryptography.hazmat.backends.openssl.backend import ( - backend as ossl, - ) - - if not ossl.rsa_encryption_supported(padding=padding.PKCS1v15()): - raise UnsupportedAlgorithm( - "RSA with PKCS1 v1.5 padding is not supported by this version" - " of OpenSSL.", - _Reasons.UNSUPPORTED_PADDING, - ) - self._data = _data - self._recipients = _recipients if _recipients is not None else [] - self._content_encryption_algorithm = _content_encryption_algorithm - - def set_data(self, data: bytes) -> PKCS7EnvelopeBuilder: - _check_byteslike("data", data) - if self._data is not None: - raise ValueError("data may only be set once") - - return PKCS7EnvelopeBuilder( - _data=data, - _recipients=self._recipients, - _content_encryption_algorithm=self._content_encryption_algorithm, - ) - - def add_recipient( - self, - certificate: x509.Certificate, - ) -> PKCS7EnvelopeBuilder: - if not isinstance(certificate, x509.Certificate): - raise TypeError("certificate must be a x509.Certificate") - - if not isinstance(certificate.public_key(), rsa.RSAPublicKey): - raise TypeError("Only RSA keys are supported at this time.") - - return PKCS7EnvelopeBuilder( - _data=self._data, - _recipients=[ - *self._recipients, - certificate, - ], - _content_encryption_algorithm=self._content_encryption_algorithm, - ) - - def set_content_encryption_algorithm( - self, content_encryption_algorithm: ContentEncryptionAlgorithm - ) -> PKCS7EnvelopeBuilder: - if self._content_encryption_algorithm is not None: - raise ValueError("Content encryption algo may only be set once") - if content_encryption_algorithm not in { - algorithms.AES128, - algorithms.AES256, - }: - raise TypeError("Only AES128 and AES256 are supported") - - return PKCS7EnvelopeBuilder( - _data=self._data, - _recipients=self._recipients, - _content_encryption_algorithm=content_encryption_algorithm, - ) - - def encrypt( - self, - encoding: serialization.Encoding, - options: Iterable[PKCS7Options], - ) -> bytes: - if len(self._recipients) == 0: - raise ValueError("Must have at least one recipient") - if self._data is None: - raise ValueError("You must add data to encrypt") - - # The default content encryption algorithm is AES-128-CBC, which the - # S/MIME v3.2 RFC specifies as MUST support (https://datatracker.ietf.org/doc/html/rfc5751#section-2.7) - # however rest of S/MIME v3.2 is not currently supported - content_encryption_algorithm = ( - self._content_encryption_algorithm or algorithms.AES128 - ) - - options = list(options) - if not all(isinstance(x, PKCS7Options) for x in options): - raise ValueError("options must be from the PKCS7Options enum") - if encoding not in ( - serialization.Encoding.PEM, - serialization.Encoding.DER, - serialization.Encoding.SMIME, - ): - raise ValueError( - "Must be PEM, DER, or SMIME from the Encoding enum" - ) - - # Only allow options that make sense for encryption - if any( - opt not in [PKCS7Options.Text, PKCS7Options.Binary] - for opt in options - ): - raise ValueError( - "Only the following options are supported for encryption: " - "Text, Binary" - ) - elif PKCS7Options.Text in options and PKCS7Options.Binary in options: - # OpenSSL accepts both options at the same time, but ignores Text. - # We fail defensively to avoid unexpected outputs. - raise ValueError( - "Cannot use Binary and Text options at the same time" - ) - - return rust_pkcs7.encrypt_and_serialize( - self, content_encryption_algorithm, encoding, options - ) - - -pkcs7_decrypt_der = rust_pkcs7.decrypt_der -pkcs7_decrypt_pem = rust_pkcs7.decrypt_pem -pkcs7_decrypt_smime = rust_pkcs7.decrypt_smime - - -def _smime_signed_encode( - data: bytes, signature: bytes, micalg: str, text_mode: bool -) -> bytes: - # This function works pretty hard to replicate what OpenSSL does - # precisely. For good and for ill. - - m = email.message.Message() - m.add_header("MIME-Version", "1.0") - m.add_header( - "Content-Type", - "multipart/signed", - protocol="application/x-pkcs7-signature", - micalg=micalg, - ) - - m.preamble = "This is an S/MIME signed message\n" - - msg_part = OpenSSLMimePart() - msg_part.set_payload(data) - if text_mode: - msg_part.add_header("Content-Type", "text/plain") - m.attach(msg_part) - - sig_part = email.message.MIMEPart() - sig_part.add_header( - "Content-Type", "application/x-pkcs7-signature", name="smime.p7s" - ) - sig_part.add_header("Content-Transfer-Encoding", "base64") - sig_part.add_header( - "Content-Disposition", "attachment", filename="smime.p7s" - ) - sig_part.set_payload( - email.base64mime.body_encode(signature, maxlinelen=65) - ) - del sig_part["MIME-Version"] - m.attach(sig_part) - - fp = io.BytesIO() - g = email.generator.BytesGenerator( - fp, - maxheaderlen=0, - mangle_from_=False, - policy=m.policy.clone(linesep="\r\n"), - ) - g.flatten(m) - return fp.getvalue() - - -def _smime_enveloped_encode(data: bytes) -> bytes: - m = email.message.Message() - m.add_header("MIME-Version", "1.0") - m.add_header("Content-Disposition", "attachment", filename="smime.p7m") - m.add_header( - "Content-Type", - "application/pkcs7-mime", - smime_type="enveloped-data", - name="smime.p7m", - ) - m.add_header("Content-Transfer-Encoding", "base64") - - m.set_payload(email.base64mime.body_encode(data, maxlinelen=65)) - - return m.as_bytes(policy=m.policy.clone(linesep="\n", max_line_length=0)) - - -def _smime_enveloped_decode(data: bytes) -> bytes: - m = email.message_from_bytes(data) - if m.get_content_type() not in { - "application/x-pkcs7-mime", - "application/pkcs7-mime", - }: - raise ValueError("Not an S/MIME enveloped message") - return bytes(m.get_payload(decode=True)) - - -def _smime_remove_text_headers(data: bytes) -> bytes: - m = email.message_from_bytes(data) - # Using get() instead of get_content_type() since it has None as default, - # where the latter has "text/plain". Both methods are case-insensitive. - content_type = m.get("content-type") - if content_type is None: - raise ValueError( - "Decrypted MIME data has no 'Content-Type' header. " - "Please remove the 'Text' option to parse it manually." - ) - if "text/plain" not in content_type: - raise ValueError( - f"Decrypted MIME data content type is '{content_type}', not " - "'text/plain'. Remove the 'Text' option to parse it manually." - ) - return bytes(m.get_payload(decode=True)) - - -class OpenSSLMimePart(email.message.MIMEPart): - # A MIMEPart subclass that replicates OpenSSL's behavior of not including - # a newline if there are no headers. - def _write_headers(self, generator) -> None: - if list(self.raw_items()): - generator._write_headers(self) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/ssh.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/ssh.py deleted file mode 100644 index 411113b..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/serialization/ssh.py +++ /dev/null @@ -1,1621 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import binascii -import enum -import os -import re -import typing -import warnings -from base64 import encodebytes as _base64_encode -from dataclasses import dataclass - -from cryptography import utils -from cryptography.exceptions import UnsupportedAlgorithm -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.asymmetric import ( - dsa, - ec, - ed25519, - padding, - rsa, -) -from cryptography.hazmat.primitives.asymmetric import utils as asym_utils -from cryptography.hazmat.primitives.ciphers import ( - AEADDecryptionContext, - Cipher, - algorithms, - modes, -) -from cryptography.hazmat.primitives.serialization import ( - Encoding, - KeySerializationEncryption, - NoEncryption, - PrivateFormat, - PublicFormat, - _KeySerializationEncryption, -) - -try: - from bcrypt import kdf as _bcrypt_kdf - - _bcrypt_supported = True -except ImportError: - _bcrypt_supported = False - - def _bcrypt_kdf( - password: bytes, - salt: bytes, - desired_key_bytes: int, - rounds: int, - ignore_few_rounds: bool = False, - ) -> bytes: - raise UnsupportedAlgorithm("Need bcrypt module") - - -_SSH_ED25519 = b"ssh-ed25519" -_SSH_RSA = b"ssh-rsa" -_SSH_DSA = b"ssh-dss" -_ECDSA_NISTP256 = b"ecdsa-sha2-nistp256" -_ECDSA_NISTP384 = b"ecdsa-sha2-nistp384" -_ECDSA_NISTP521 = b"ecdsa-sha2-nistp521" -_CERT_SUFFIX = b"-cert-v01@openssh.com" - -# U2F application string suffixed pubkey -_SK_SSH_ED25519 = b"sk-ssh-ed25519@openssh.com" -_SK_SSH_ECDSA_NISTP256 = b"sk-ecdsa-sha2-nistp256@openssh.com" - -# These are not key types, only algorithms, so they cannot appear -# as a public key type -_SSH_RSA_SHA256 = b"rsa-sha2-256" -_SSH_RSA_SHA512 = b"rsa-sha2-512" - -_SSH_PUBKEY_RC = re.compile(rb"\A(\S+)[ \t]+(\S+)") -_SK_MAGIC = b"openssh-key-v1\0" -_SK_START = b"-----BEGIN OPENSSH PRIVATE KEY-----" -_SK_END = b"-----END OPENSSH PRIVATE KEY-----" -_BCRYPT = b"bcrypt" -_NONE = b"none" -_DEFAULT_CIPHER = b"aes256-ctr" -_DEFAULT_ROUNDS = 16 - -# re is only way to work on bytes-like data -_PEM_RC = re.compile(_SK_START + b"(.*?)" + _SK_END, re.DOTALL) - -# padding for max blocksize -_PADDING = memoryview(bytearray(range(1, 1 + 16))) - - -@dataclass -class _SSHCipher: - alg: type[algorithms.AES] - key_len: int - mode: type[modes.CTR] | type[modes.CBC] | type[modes.GCM] - block_len: int - iv_len: int - tag_len: int | None - is_aead: bool - - -# ciphers that are actually used in key wrapping -_SSH_CIPHERS: dict[bytes, _SSHCipher] = { - b"aes256-ctr": _SSHCipher( - alg=algorithms.AES, - key_len=32, - mode=modes.CTR, - block_len=16, - iv_len=16, - tag_len=None, - is_aead=False, - ), - b"aes256-cbc": _SSHCipher( - alg=algorithms.AES, - key_len=32, - mode=modes.CBC, - block_len=16, - iv_len=16, - tag_len=None, - is_aead=False, - ), - b"aes256-gcm@openssh.com": _SSHCipher( - alg=algorithms.AES, - key_len=32, - mode=modes.GCM, - block_len=16, - iv_len=12, - tag_len=16, - is_aead=True, - ), -} - -# map local curve name to key type -_ECDSA_KEY_TYPE = { - "secp256r1": _ECDSA_NISTP256, - "secp384r1": _ECDSA_NISTP384, - "secp521r1": _ECDSA_NISTP521, -} - - -def _get_ssh_key_type(key: SSHPrivateKeyTypes | SSHPublicKeyTypes) -> bytes: - if isinstance(key, ec.EllipticCurvePrivateKey): - key_type = _ecdsa_key_type(key.public_key()) - elif isinstance(key, ec.EllipticCurvePublicKey): - key_type = _ecdsa_key_type(key) - elif isinstance(key, (rsa.RSAPrivateKey, rsa.RSAPublicKey)): - key_type = _SSH_RSA - elif isinstance(key, (dsa.DSAPrivateKey, dsa.DSAPublicKey)): - key_type = _SSH_DSA - elif isinstance( - key, (ed25519.Ed25519PrivateKey, ed25519.Ed25519PublicKey) - ): - key_type = _SSH_ED25519 - else: - raise ValueError("Unsupported key type") - - return key_type - - -def _ecdsa_key_type(public_key: ec.EllipticCurvePublicKey) -> bytes: - """Return SSH key_type and curve_name for private key.""" - curve = public_key.curve - if curve.name not in _ECDSA_KEY_TYPE: - raise ValueError( - f"Unsupported curve for ssh private key: {curve.name!r}" - ) - return _ECDSA_KEY_TYPE[curve.name] - - -def _ssh_pem_encode( - data: utils.Buffer, - prefix: bytes = _SK_START + b"\n", - suffix: bytes = _SK_END + b"\n", -) -> bytes: - return b"".join([prefix, _base64_encode(data), suffix]) - - -def _check_block_size(data: utils.Buffer, block_len: int) -> None: - """Require data to be full blocks""" - if not data or len(data) % block_len != 0: - raise ValueError("Corrupt data: missing padding") - - -def _check_empty(data: utils.Buffer) -> None: - """All data should have been parsed.""" - if data: - raise ValueError("Corrupt data: unparsed data") - - -def _init_cipher( - ciphername: bytes, - password: bytes | None, - salt: bytes, - rounds: int, -) -> Cipher[modes.CBC | modes.CTR | modes.GCM]: - """Generate key + iv and return cipher.""" - if not password: - raise TypeError( - "Key is password-protected, but password was not provided." - ) - - ciph = _SSH_CIPHERS[ciphername] - seed = _bcrypt_kdf( - password, salt, ciph.key_len + ciph.iv_len, rounds, True - ) - return Cipher( - ciph.alg(seed[: ciph.key_len]), - ciph.mode(seed[ciph.key_len :]), - ) - - -def _get_u32(data: memoryview) -> tuple[int, memoryview]: - """Uint32""" - if len(data) < 4: - raise ValueError("Invalid data") - return int.from_bytes(data[:4], byteorder="big"), data[4:] - - -def _get_u64(data: memoryview) -> tuple[int, memoryview]: - """Uint64""" - if len(data) < 8: - raise ValueError("Invalid data") - return int.from_bytes(data[:8], byteorder="big"), data[8:] - - -def _get_sshstr(data: memoryview) -> tuple[memoryview, memoryview]: - """Bytes with u32 length prefix""" - n, data = _get_u32(data) - if n > len(data): - raise ValueError("Invalid data") - return data[:n], data[n:] - - -def _get_mpint(data: memoryview) -> tuple[int, memoryview]: - """Big integer.""" - val, data = _get_sshstr(data) - if val and val[0] > 0x7F: - raise ValueError("Invalid data") - return int.from_bytes(val, "big"), data - - -def _to_mpint(val: int) -> bytes: - """Storage format for signed bigint.""" - if val < 0: - raise ValueError("negative mpint not allowed") - if not val: - return b"" - nbytes = (val.bit_length() + 8) // 8 - return utils.int_to_bytes(val, nbytes) - - -class _FragList: - """Build recursive structure without data copy.""" - - flist: list[utils.Buffer] - - def __init__(self, init: list[utils.Buffer] | None = None) -> None: - self.flist = [] - if init: - self.flist.extend(init) - - def put_raw(self, val: utils.Buffer) -> None: - """Add plain bytes""" - self.flist.append(val) - - def put_u32(self, val: int) -> None: - """Big-endian uint32""" - self.flist.append(val.to_bytes(length=4, byteorder="big")) - - def put_u64(self, val: int) -> None: - """Big-endian uint64""" - self.flist.append(val.to_bytes(length=8, byteorder="big")) - - def put_sshstr(self, val: bytes | _FragList) -> None: - """Bytes prefixed with u32 length""" - if isinstance(val, (bytes, memoryview, bytearray)): - self.put_u32(len(val)) - self.flist.append(val) - else: - self.put_u32(val.size()) - self.flist.extend(val.flist) - - def put_mpint(self, val: int) -> None: - """Big-endian bigint prefixed with u32 length""" - self.put_sshstr(_to_mpint(val)) - - def size(self) -> int: - """Current number of bytes""" - return sum(map(len, self.flist)) - - def render(self, dstbuf: memoryview, pos: int = 0) -> int: - """Write into bytearray""" - for frag in self.flist: - flen = len(frag) - start, pos = pos, pos + flen - dstbuf[start:pos] = frag - return pos - - def tobytes(self) -> bytes: - """Return as bytes""" - buf = memoryview(bytearray(self.size())) - self.render(buf) - return buf.tobytes() - - -class _SSHFormatRSA: - """Format for RSA keys. - - Public: - mpint e, n - Private: - mpint n, e, d, iqmp, p, q - """ - - def get_public( - self, data: memoryview - ) -> tuple[tuple[int, int], memoryview]: - """RSA public fields""" - e, data = _get_mpint(data) - n, data = _get_mpint(data) - return (e, n), data - - def load_public( - self, data: memoryview - ) -> tuple[rsa.RSAPublicKey, memoryview]: - """Make RSA public key from data.""" - (e, n), data = self.get_public(data) - public_numbers = rsa.RSAPublicNumbers(e, n) - public_key = public_numbers.public_key() - return public_key, data - - def load_private( - self, data: memoryview, pubfields, unsafe_skip_rsa_key_validation: bool - ) -> tuple[rsa.RSAPrivateKey, memoryview]: - """Make RSA private key from data.""" - n, data = _get_mpint(data) - e, data = _get_mpint(data) - d, data = _get_mpint(data) - iqmp, data = _get_mpint(data) - p, data = _get_mpint(data) - q, data = _get_mpint(data) - - if (e, n) != pubfields: - raise ValueError("Corrupt data: rsa field mismatch") - dmp1 = rsa.rsa_crt_dmp1(d, p) - dmq1 = rsa.rsa_crt_dmq1(d, q) - public_numbers = rsa.RSAPublicNumbers(e, n) - private_numbers = rsa.RSAPrivateNumbers( - p, q, d, dmp1, dmq1, iqmp, public_numbers - ) - private_key = private_numbers.private_key( - unsafe_skip_rsa_key_validation=unsafe_skip_rsa_key_validation - ) - return private_key, data - - def encode_public( - self, public_key: rsa.RSAPublicKey, f_pub: _FragList - ) -> None: - """Write RSA public key""" - pubn = public_key.public_numbers() - f_pub.put_mpint(pubn.e) - f_pub.put_mpint(pubn.n) - - def encode_private( - self, private_key: rsa.RSAPrivateKey, f_priv: _FragList - ) -> None: - """Write RSA private key""" - private_numbers = private_key.private_numbers() - public_numbers = private_numbers.public_numbers - - f_priv.put_mpint(public_numbers.n) - f_priv.put_mpint(public_numbers.e) - - f_priv.put_mpint(private_numbers.d) - f_priv.put_mpint(private_numbers.iqmp) - f_priv.put_mpint(private_numbers.p) - f_priv.put_mpint(private_numbers.q) - - -class _SSHFormatDSA: - """Format for DSA keys. - - Public: - mpint p, q, g, y - Private: - mpint p, q, g, y, x - """ - - def get_public(self, data: memoryview) -> tuple[tuple, memoryview]: - """DSA public fields""" - p, data = _get_mpint(data) - q, data = _get_mpint(data) - g, data = _get_mpint(data) - y, data = _get_mpint(data) - return (p, q, g, y), data - - def load_public( - self, data: memoryview - ) -> tuple[dsa.DSAPublicKey, memoryview]: - """Make DSA public key from data.""" - (p, q, g, y), data = self.get_public(data) - parameter_numbers = dsa.DSAParameterNumbers(p, q, g) - public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers) - self._validate(public_numbers) - public_key = public_numbers.public_key() - return public_key, data - - def load_private( - self, data: memoryview, pubfields, unsafe_skip_rsa_key_validation: bool - ) -> tuple[dsa.DSAPrivateKey, memoryview]: - """Make DSA private key from data.""" - (p, q, g, y), data = self.get_public(data) - x, data = _get_mpint(data) - - if (p, q, g, y) != pubfields: - raise ValueError("Corrupt data: dsa field mismatch") - parameter_numbers = dsa.DSAParameterNumbers(p, q, g) - public_numbers = dsa.DSAPublicNumbers(y, parameter_numbers) - self._validate(public_numbers) - private_numbers = dsa.DSAPrivateNumbers(x, public_numbers) - private_key = private_numbers.private_key() - return private_key, data - - def encode_public( - self, public_key: dsa.DSAPublicKey, f_pub: _FragList - ) -> None: - """Write DSA public key""" - public_numbers = public_key.public_numbers() - parameter_numbers = public_numbers.parameter_numbers - self._validate(public_numbers) - - f_pub.put_mpint(parameter_numbers.p) - f_pub.put_mpint(parameter_numbers.q) - f_pub.put_mpint(parameter_numbers.g) - f_pub.put_mpint(public_numbers.y) - - def encode_private( - self, private_key: dsa.DSAPrivateKey, f_priv: _FragList - ) -> None: - """Write DSA private key""" - self.encode_public(private_key.public_key(), f_priv) - f_priv.put_mpint(private_key.private_numbers().x) - - def _validate(self, public_numbers: dsa.DSAPublicNumbers) -> None: - parameter_numbers = public_numbers.parameter_numbers - if parameter_numbers.p.bit_length() != 1024: - raise ValueError("SSH supports only 1024 bit DSA keys") - - -class _SSHFormatECDSA: - """Format for ECDSA keys. - - Public: - str curve - bytes point - Private: - str curve - bytes point - mpint secret - """ - - def __init__(self, ssh_curve_name: bytes, curve: ec.EllipticCurve): - self.ssh_curve_name = ssh_curve_name - self.curve = curve - - def get_public( - self, data: memoryview - ) -> tuple[tuple[memoryview, memoryview], memoryview]: - """ECDSA public fields""" - curve, data = _get_sshstr(data) - point, data = _get_sshstr(data) - if curve != self.ssh_curve_name: - raise ValueError("Curve name mismatch") - if len(point) == 0: - raise ValueError("Invalid EC point: empty data") - if point[0] != 4: - raise NotImplementedError("Need uncompressed point") - return (curve, point), data - - def load_public( - self, data: memoryview - ) -> tuple[ec.EllipticCurvePublicKey, memoryview]: - """Make ECDSA public key from data.""" - (_, point), data = self.get_public(data) - public_key = ec.EllipticCurvePublicKey.from_encoded_point( - self.curve, point.tobytes() - ) - return public_key, data - - def load_private( - self, data: memoryview, pubfields, unsafe_skip_rsa_key_validation: bool - ) -> tuple[ec.EllipticCurvePrivateKey, memoryview]: - """Make ECDSA private key from data.""" - (curve_name, point), data = self.get_public(data) - secret, data = _get_mpint(data) - - if (curve_name, point) != pubfields: - raise ValueError("Corrupt data: ecdsa field mismatch") - private_key = ec.derive_private_key(secret, self.curve) - return private_key, data - - def encode_public( - self, public_key: ec.EllipticCurvePublicKey, f_pub: _FragList - ) -> None: - """Write ECDSA public key""" - point = public_key.public_bytes( - Encoding.X962, PublicFormat.UncompressedPoint - ) - f_pub.put_sshstr(self.ssh_curve_name) - f_pub.put_sshstr(point) - - def encode_private( - self, private_key: ec.EllipticCurvePrivateKey, f_priv: _FragList - ) -> None: - """Write ECDSA private key""" - public_key = private_key.public_key() - private_numbers = private_key.private_numbers() - - self.encode_public(public_key, f_priv) - f_priv.put_mpint(private_numbers.private_value) - - -class _SSHFormatEd25519: - """Format for Ed25519 keys. - - Public: - bytes point - Private: - bytes point - bytes secret_and_point - """ - - def get_public( - self, data: memoryview - ) -> tuple[tuple[memoryview], memoryview]: - """Ed25519 public fields""" - point, data = _get_sshstr(data) - return (point,), data - - def load_public( - self, data: memoryview - ) -> tuple[ed25519.Ed25519PublicKey, memoryview]: - """Make Ed25519 public key from data.""" - (point,), data = self.get_public(data) - public_key = ed25519.Ed25519PublicKey.from_public_bytes( - point.tobytes() - ) - return public_key, data - - def load_private( - self, data: memoryview, pubfields, unsafe_skip_rsa_key_validation: bool - ) -> tuple[ed25519.Ed25519PrivateKey, memoryview]: - """Make Ed25519 private key from data.""" - (point,), data = self.get_public(data) - keypair, data = _get_sshstr(data) - - secret = keypair[:32] - point2 = keypair[32:] - if point != point2 or (point,) != pubfields: - raise ValueError("Corrupt data: ed25519 field mismatch") - private_key = ed25519.Ed25519PrivateKey.from_private_bytes(secret) - return private_key, data - - def encode_public( - self, public_key: ed25519.Ed25519PublicKey, f_pub: _FragList - ) -> None: - """Write Ed25519 public key""" - raw_public_key = public_key.public_bytes( - Encoding.Raw, PublicFormat.Raw - ) - f_pub.put_sshstr(raw_public_key) - - def encode_private( - self, private_key: ed25519.Ed25519PrivateKey, f_priv: _FragList - ) -> None: - """Write Ed25519 private key""" - public_key = private_key.public_key() - raw_private_key = private_key.private_bytes( - Encoding.Raw, PrivateFormat.Raw, NoEncryption() - ) - raw_public_key = public_key.public_bytes( - Encoding.Raw, PublicFormat.Raw - ) - f_keypair = _FragList([raw_private_key, raw_public_key]) - - self.encode_public(public_key, f_priv) - f_priv.put_sshstr(f_keypair) - - -def load_application(data) -> tuple[memoryview, memoryview]: - """ - U2F application strings - """ - application, data = _get_sshstr(data) - if not application.tobytes().startswith(b"ssh:"): - raise ValueError( - "U2F application string does not start with b'ssh:' " - f"({application})" - ) - return application, data - - -class _SSHFormatSKEd25519: - """ - The format of a sk-ssh-ed25519@openssh.com public key is: - - string "sk-ssh-ed25519@openssh.com" - string public key - string application (user-specified, but typically "ssh:") - """ - - def load_public( - self, data: memoryview - ) -> tuple[ed25519.Ed25519PublicKey, memoryview]: - """Make Ed25519 public key from data.""" - public_key, data = _lookup_kformat(_SSH_ED25519).load_public(data) - _, data = load_application(data) - return public_key, data - - def get_public(self, data: memoryview) -> typing.NoReturn: - # Confusingly `get_public` is an entry point used by private key - # loading. - raise UnsupportedAlgorithm( - "sk-ssh-ed25519 private keys cannot be loaded" - ) - - -class _SSHFormatSKECDSA: - """ - The format of a sk-ecdsa-sha2-nistp256@openssh.com public key is: - - string "sk-ecdsa-sha2-nistp256@openssh.com" - string curve name - ec_point Q - string application (user-specified, but typically "ssh:") - """ - - def load_public( - self, data: memoryview - ) -> tuple[ec.EllipticCurvePublicKey, memoryview]: - """Make ECDSA public key from data.""" - public_key, data = _lookup_kformat(_ECDSA_NISTP256).load_public(data) - _, data = load_application(data) - return public_key, data - - def get_public(self, data: memoryview) -> typing.NoReturn: - # Confusingly `get_public` is an entry point used by private key - # loading. - raise UnsupportedAlgorithm( - "sk-ecdsa-sha2-nistp256 private keys cannot be loaded" - ) - - -_KEY_FORMATS = { - _SSH_RSA: _SSHFormatRSA(), - _SSH_DSA: _SSHFormatDSA(), - _SSH_ED25519: _SSHFormatEd25519(), - _ECDSA_NISTP256: _SSHFormatECDSA(b"nistp256", ec.SECP256R1()), - _ECDSA_NISTP384: _SSHFormatECDSA(b"nistp384", ec.SECP384R1()), - _ECDSA_NISTP521: _SSHFormatECDSA(b"nistp521", ec.SECP521R1()), - _SK_SSH_ED25519: _SSHFormatSKEd25519(), - _SK_SSH_ECDSA_NISTP256: _SSHFormatSKECDSA(), -} - - -def _lookup_kformat(key_type: utils.Buffer): - """Return valid format or throw error""" - if not isinstance(key_type, bytes): - key_type = memoryview(key_type).tobytes() - if key_type in _KEY_FORMATS: - return _KEY_FORMATS[key_type] - raise UnsupportedAlgorithm(f"Unsupported key type: {key_type!r}") - - -SSHPrivateKeyTypes = typing.Union[ - ec.EllipticCurvePrivateKey, - rsa.RSAPrivateKey, - dsa.DSAPrivateKey, - ed25519.Ed25519PrivateKey, -] - - -def load_ssh_private_key( - data: utils.Buffer, - password: bytes | None, - backend: typing.Any = None, - *, - unsafe_skip_rsa_key_validation: bool = False, -) -> SSHPrivateKeyTypes: - """Load private key from OpenSSH custom encoding.""" - utils._check_byteslike("data", data) - if password is not None: - utils._check_bytes("password", password) - - m = _PEM_RC.search(data) - if not m: - raise ValueError("Not OpenSSH private key format") - p1 = m.start(1) - p2 = m.end(1) - data = binascii.a2b_base64(memoryview(data)[p1:p2]) - if not data.startswith(_SK_MAGIC): - raise ValueError("Not OpenSSH private key format") - data = memoryview(data)[len(_SK_MAGIC) :] - - # parse header - ciphername, data = _get_sshstr(data) - kdfname, data = _get_sshstr(data) - kdfoptions, data = _get_sshstr(data) - nkeys, data = _get_u32(data) - if nkeys != 1: - raise ValueError("Only one key supported") - - # load public key data - pubdata, data = _get_sshstr(data) - pub_key_type, pubdata = _get_sshstr(pubdata) - kformat = _lookup_kformat(pub_key_type) - pubfields, pubdata = kformat.get_public(pubdata) - _check_empty(pubdata) - - if ciphername != _NONE or kdfname != _NONE: - ciphername_bytes = ciphername.tobytes() - if ciphername_bytes not in _SSH_CIPHERS: - raise UnsupportedAlgorithm( - f"Unsupported cipher: {ciphername_bytes!r}" - ) - if kdfname != _BCRYPT: - raise UnsupportedAlgorithm(f"Unsupported KDF: {kdfname!r}") - blklen = _SSH_CIPHERS[ciphername_bytes].block_len - tag_len = _SSH_CIPHERS[ciphername_bytes].tag_len - # load secret data - edata, data = _get_sshstr(data) - # see https://bugzilla.mindrot.org/show_bug.cgi?id=3553 for - # information about how OpenSSH handles AEAD tags - if _SSH_CIPHERS[ciphername_bytes].is_aead: - tag = bytes(data) - if len(tag) != tag_len: - raise ValueError("Corrupt data: invalid tag length for cipher") - else: - _check_empty(data) - _check_block_size(edata, blklen) - salt, kbuf = _get_sshstr(kdfoptions) - rounds, kbuf = _get_u32(kbuf) - _check_empty(kbuf) - ciph = _init_cipher(ciphername_bytes, password, salt.tobytes(), rounds) - dec = ciph.decryptor() - edata = memoryview(dec.update(edata)) - if _SSH_CIPHERS[ciphername_bytes].is_aead: - assert isinstance(dec, AEADDecryptionContext) - _check_empty(dec.finalize_with_tag(tag)) - else: - # _check_block_size requires data to be a full block so there - # should be no output from finalize - _check_empty(dec.finalize()) - else: - if password: - raise TypeError( - "Password was given but private key is not encrypted." - ) - # load secret data - edata, data = _get_sshstr(data) - _check_empty(data) - blklen = 8 - _check_block_size(edata, blklen) - ck1, edata = _get_u32(edata) - ck2, edata = _get_u32(edata) - if ck1 != ck2: - raise ValueError("Corrupt data: broken checksum") - - # load per-key struct - key_type, edata = _get_sshstr(edata) - if key_type != pub_key_type: - raise ValueError("Corrupt data: key type mismatch") - private_key, edata = kformat.load_private( - edata, - pubfields, - unsafe_skip_rsa_key_validation=unsafe_skip_rsa_key_validation, - ) - # We don't use the comment - _, edata = _get_sshstr(edata) - - # yes, SSH does padding check *after* all other parsing is done. - # need to follow as it writes zero-byte padding too. - if edata != _PADDING[: len(edata)]: - raise ValueError("Corrupt data: invalid padding") - - if isinstance(private_key, dsa.DSAPrivateKey): - warnings.warn( - "SSH DSA keys are deprecated and will be removed in a future " - "release.", - utils.DeprecatedIn40, - stacklevel=2, - ) - - return private_key - - -def _serialize_ssh_private_key( - private_key: SSHPrivateKeyTypes, - password: bytes, - encryption_algorithm: KeySerializationEncryption, -) -> bytes: - """Serialize private key with OpenSSH custom encoding.""" - utils._check_bytes("password", password) - if isinstance(private_key, dsa.DSAPrivateKey): - warnings.warn( - "SSH DSA key support is deprecated and will be " - "removed in a future release", - utils.DeprecatedIn40, - stacklevel=4, - ) - - key_type = _get_ssh_key_type(private_key) - kformat = _lookup_kformat(key_type) - - # setup parameters - f_kdfoptions = _FragList() - if password: - ciphername = _DEFAULT_CIPHER - blklen = _SSH_CIPHERS[ciphername].block_len - kdfname = _BCRYPT - rounds = _DEFAULT_ROUNDS - if ( - isinstance(encryption_algorithm, _KeySerializationEncryption) - and encryption_algorithm._kdf_rounds is not None - ): - rounds = encryption_algorithm._kdf_rounds - salt = os.urandom(16) - f_kdfoptions.put_sshstr(salt) - f_kdfoptions.put_u32(rounds) - ciph = _init_cipher(ciphername, password, salt, rounds) - else: - ciphername = kdfname = _NONE - blklen = 8 - ciph = None - nkeys = 1 - checkval = os.urandom(4) - comment = b"" - - # encode public and private parts together - f_public_key = _FragList() - f_public_key.put_sshstr(key_type) - kformat.encode_public(private_key.public_key(), f_public_key) - - f_secrets = _FragList([checkval, checkval]) - f_secrets.put_sshstr(key_type) - kformat.encode_private(private_key, f_secrets) - f_secrets.put_sshstr(comment) - f_secrets.put_raw(_PADDING[: blklen - (f_secrets.size() % blklen)]) - - # top-level structure - f_main = _FragList() - f_main.put_raw(_SK_MAGIC) - f_main.put_sshstr(ciphername) - f_main.put_sshstr(kdfname) - f_main.put_sshstr(f_kdfoptions) - f_main.put_u32(nkeys) - f_main.put_sshstr(f_public_key) - f_main.put_sshstr(f_secrets) - - # copy result info bytearray - slen = f_secrets.size() - mlen = f_main.size() - buf = memoryview(bytearray(mlen + blklen)) - f_main.render(buf) - ofs = mlen - slen - - # encrypt in-place - if ciph is not None: - ciph.encryptor().update_into(buf[ofs:mlen], buf[ofs:]) - - return _ssh_pem_encode(buf[:mlen]) - - -SSHPublicKeyTypes = typing.Union[ - ec.EllipticCurvePublicKey, - rsa.RSAPublicKey, - dsa.DSAPublicKey, - ed25519.Ed25519PublicKey, -] - -SSHCertPublicKeyTypes = typing.Union[ - ec.EllipticCurvePublicKey, - rsa.RSAPublicKey, - ed25519.Ed25519PublicKey, -] - - -class SSHCertificateType(enum.Enum): - USER = 1 - HOST = 2 - - -class SSHCertificate: - def __init__( - self, - _nonce: memoryview, - _public_key: SSHPublicKeyTypes, - _serial: int, - _cctype: int, - _key_id: memoryview, - _valid_principals: list[bytes], - _valid_after: int, - _valid_before: int, - _critical_options: dict[bytes, bytes], - _extensions: dict[bytes, bytes], - _sig_type: memoryview, - _sig_key: memoryview, - _inner_sig_type: memoryview, - _signature: memoryview, - _tbs_cert_body: memoryview, - _cert_key_type: bytes, - _cert_body: memoryview, - ): - self._nonce = _nonce - self._public_key = _public_key - self._serial = _serial - try: - self._type = SSHCertificateType(_cctype) - except ValueError: - raise ValueError("Invalid certificate type") - self._key_id = _key_id - self._valid_principals = _valid_principals - self._valid_after = _valid_after - self._valid_before = _valid_before - self._critical_options = _critical_options - self._extensions = _extensions - self._sig_type = _sig_type - self._sig_key = _sig_key - self._inner_sig_type = _inner_sig_type - self._signature = _signature - self._cert_key_type = _cert_key_type - self._cert_body = _cert_body - self._tbs_cert_body = _tbs_cert_body - - @property - def nonce(self) -> bytes: - return bytes(self._nonce) - - def public_key(self) -> SSHCertPublicKeyTypes: - # make mypy happy until we remove DSA support entirely and - # the underlying union won't have a disallowed type - return typing.cast(SSHCertPublicKeyTypes, self._public_key) - - @property - def serial(self) -> int: - return self._serial - - @property - def type(self) -> SSHCertificateType: - return self._type - - @property - def key_id(self) -> bytes: - return bytes(self._key_id) - - @property - def valid_principals(self) -> list[bytes]: - return self._valid_principals - - @property - def valid_before(self) -> int: - return self._valid_before - - @property - def valid_after(self) -> int: - return self._valid_after - - @property - def critical_options(self) -> dict[bytes, bytes]: - return self._critical_options - - @property - def extensions(self) -> dict[bytes, bytes]: - return self._extensions - - def signature_key(self) -> SSHCertPublicKeyTypes: - sigformat = _lookup_kformat(self._sig_type) - signature_key, sigkey_rest = sigformat.load_public(self._sig_key) - _check_empty(sigkey_rest) - return signature_key - - def public_bytes(self) -> bytes: - return ( - bytes(self._cert_key_type) - + b" " - + binascii.b2a_base64(bytes(self._cert_body), newline=False) - ) - - def verify_cert_signature(self) -> None: - signature_key = self.signature_key() - if isinstance(signature_key, ed25519.Ed25519PublicKey): - signature_key.verify( - bytes(self._signature), bytes(self._tbs_cert_body) - ) - elif isinstance(signature_key, ec.EllipticCurvePublicKey): - # The signature is encoded as a pair of big-endian integers - r, data = _get_mpint(self._signature) - s, data = _get_mpint(data) - _check_empty(data) - computed_sig = asym_utils.encode_dss_signature(r, s) - hash_alg = _get_ec_hash_alg(signature_key.curve) - signature_key.verify( - computed_sig, bytes(self._tbs_cert_body), ec.ECDSA(hash_alg) - ) - else: - assert isinstance(signature_key, rsa.RSAPublicKey) - if self._inner_sig_type == _SSH_RSA: - hash_alg = hashes.SHA1() - elif self._inner_sig_type == _SSH_RSA_SHA256: - hash_alg = hashes.SHA256() - else: - assert self._inner_sig_type == _SSH_RSA_SHA512 - hash_alg = hashes.SHA512() - signature_key.verify( - bytes(self._signature), - bytes(self._tbs_cert_body), - padding.PKCS1v15(), - hash_alg, - ) - - -def _get_ec_hash_alg(curve: ec.EllipticCurve) -> hashes.HashAlgorithm: - if isinstance(curve, ec.SECP256R1): - return hashes.SHA256() - elif isinstance(curve, ec.SECP384R1): - return hashes.SHA384() - else: - assert isinstance(curve, ec.SECP521R1) - return hashes.SHA512() - - -def _load_ssh_public_identity( - data: utils.Buffer, - _legacy_dsa_allowed=False, -) -> SSHCertificate | SSHPublicKeyTypes: - utils._check_byteslike("data", data) - - m = _SSH_PUBKEY_RC.match(data) - if not m: - raise ValueError("Invalid line format") - key_type = orig_key_type = m.group(1) - key_body = m.group(2) - with_cert = False - if key_type.endswith(_CERT_SUFFIX): - with_cert = True - key_type = key_type[: -len(_CERT_SUFFIX)] - if key_type == _SSH_DSA and not _legacy_dsa_allowed: - raise UnsupportedAlgorithm( - "DSA keys aren't supported in SSH certificates" - ) - kformat = _lookup_kformat(key_type) - - try: - rest = memoryview(binascii.a2b_base64(key_body)) - except (TypeError, binascii.Error): - raise ValueError("Invalid format") - - if with_cert: - cert_body = rest - inner_key_type, rest = _get_sshstr(rest) - if inner_key_type != orig_key_type: - raise ValueError("Invalid key format") - if with_cert: - nonce, rest = _get_sshstr(rest) - public_key, rest = kformat.load_public(rest) - if with_cert: - serial, rest = _get_u64(rest) - cctype, rest = _get_u32(rest) - key_id, rest = _get_sshstr(rest) - principals, rest = _get_sshstr(rest) - valid_principals = [] - while principals: - principal, principals = _get_sshstr(principals) - valid_principals.append(bytes(principal)) - valid_after, rest = _get_u64(rest) - valid_before, rest = _get_u64(rest) - crit_options, rest = _get_sshstr(rest) - critical_options = _parse_exts_opts(crit_options) - exts, rest = _get_sshstr(rest) - extensions = _parse_exts_opts(exts) - # Get the reserved field, which is unused. - _, rest = _get_sshstr(rest) - sig_key_raw, rest = _get_sshstr(rest) - sig_type, sig_key = _get_sshstr(sig_key_raw) - if sig_type == _SSH_DSA and not _legacy_dsa_allowed: - raise UnsupportedAlgorithm( - "DSA signatures aren't supported in SSH certificates" - ) - # Get the entire cert body and subtract the signature - tbs_cert_body = cert_body[: -len(rest)] - signature_raw, rest = _get_sshstr(rest) - _check_empty(rest) - inner_sig_type, sig_rest = _get_sshstr(signature_raw) - # RSA certs can have multiple algorithm types - if ( - sig_type == _SSH_RSA - and inner_sig_type - not in [_SSH_RSA_SHA256, _SSH_RSA_SHA512, _SSH_RSA] - ) or (sig_type != _SSH_RSA and inner_sig_type != sig_type): - raise ValueError("Signature key type does not match") - signature, sig_rest = _get_sshstr(sig_rest) - _check_empty(sig_rest) - return SSHCertificate( - nonce, - public_key, - serial, - cctype, - key_id, - valid_principals, - valid_after, - valid_before, - critical_options, - extensions, - sig_type, - sig_key, - inner_sig_type, - signature, - tbs_cert_body, - orig_key_type, - cert_body, - ) - else: - _check_empty(rest) - return public_key - - -def load_ssh_public_identity( - data: utils.Buffer, -) -> SSHCertificate | SSHPublicKeyTypes: - return _load_ssh_public_identity(data) - - -def _parse_exts_opts(exts_opts: memoryview) -> dict[bytes, bytes]: - result: dict[bytes, bytes] = {} - last_name = None - while exts_opts: - name, exts_opts = _get_sshstr(exts_opts) - bname: bytes = bytes(name) - if bname in result: - raise ValueError("Duplicate name") - if last_name is not None and bname < last_name: - raise ValueError("Fields not lexically sorted") - value, exts_opts = _get_sshstr(exts_opts) - if len(value) > 0: - value, extra = _get_sshstr(value) - if len(extra) > 0: - raise ValueError("Unexpected extra data after value") - result[bname] = bytes(value) - last_name = bname - return result - - -def ssh_key_fingerprint( - key: SSHPublicKeyTypes, - hash_algorithm: hashes.MD5 | hashes.SHA256, -) -> bytes: - if not isinstance(hash_algorithm, (hashes.MD5, hashes.SHA256)): - raise TypeError("hash_algorithm must be either MD5 or SHA256") - - key_type = _get_ssh_key_type(key) - kformat = _lookup_kformat(key_type) - - f_pub = _FragList() - f_pub.put_sshstr(key_type) - kformat.encode_public(key, f_pub) - - ssh_binary_data = f_pub.tobytes() - - # Hash the binary data - hash_obj = hashes.Hash(hash_algorithm) - hash_obj.update(ssh_binary_data) - return hash_obj.finalize() - - -def load_ssh_public_key( - data: utils.Buffer, backend: typing.Any = None -) -> SSHPublicKeyTypes: - cert_or_key = _load_ssh_public_identity(data, _legacy_dsa_allowed=True) - public_key: SSHPublicKeyTypes - if isinstance(cert_or_key, SSHCertificate): - public_key = cert_or_key.public_key() - else: - public_key = cert_or_key - - if isinstance(public_key, dsa.DSAPublicKey): - warnings.warn( - "SSH DSA keys are deprecated and will be removed in a future " - "release.", - utils.DeprecatedIn40, - stacklevel=2, - ) - return public_key - - -def serialize_ssh_public_key(public_key: SSHPublicKeyTypes) -> bytes: - """One-line public key format for OpenSSH""" - if isinstance(public_key, dsa.DSAPublicKey): - warnings.warn( - "SSH DSA key support is deprecated and will be " - "removed in a future release", - utils.DeprecatedIn40, - stacklevel=4, - ) - key_type = _get_ssh_key_type(public_key) - kformat = _lookup_kformat(key_type) - - f_pub = _FragList() - f_pub.put_sshstr(key_type) - kformat.encode_public(public_key, f_pub) - - pub = binascii.b2a_base64(f_pub.tobytes()).strip() - return b"".join([key_type, b" ", pub]) - - -SSHCertPrivateKeyTypes = typing.Union[ - ec.EllipticCurvePrivateKey, - rsa.RSAPrivateKey, - ed25519.Ed25519PrivateKey, -] - - -# This is an undocumented limit enforced in the openssh codebase for sshd and -# ssh-keygen, but it is undefined in the ssh certificates spec. -_SSHKEY_CERT_MAX_PRINCIPALS = 256 - - -class SSHCertificateBuilder: - def __init__( - self, - _public_key: SSHCertPublicKeyTypes | None = None, - _serial: int | None = None, - _type: SSHCertificateType | None = None, - _key_id: bytes | None = None, - _valid_principals: list[bytes] = [], - _valid_for_all_principals: bool = False, - _valid_before: int | None = None, - _valid_after: int | None = None, - _critical_options: list[tuple[bytes, bytes]] = [], - _extensions: list[tuple[bytes, bytes]] = [], - ): - self._public_key = _public_key - self._serial = _serial - self._type = _type - self._key_id = _key_id - self._valid_principals = _valid_principals - self._valid_for_all_principals = _valid_for_all_principals - self._valid_before = _valid_before - self._valid_after = _valid_after - self._critical_options = _critical_options - self._extensions = _extensions - - def public_key( - self, public_key: SSHCertPublicKeyTypes - ) -> SSHCertificateBuilder: - if not isinstance( - public_key, - ( - ec.EllipticCurvePublicKey, - rsa.RSAPublicKey, - ed25519.Ed25519PublicKey, - ), - ): - raise TypeError("Unsupported key type") - if self._public_key is not None: - raise ValueError("public_key already set") - - return SSHCertificateBuilder( - _public_key=public_key, - _serial=self._serial, - _type=self._type, - _key_id=self._key_id, - _valid_principals=self._valid_principals, - _valid_for_all_principals=self._valid_for_all_principals, - _valid_before=self._valid_before, - _valid_after=self._valid_after, - _critical_options=self._critical_options, - _extensions=self._extensions, - ) - - def serial(self, serial: int) -> SSHCertificateBuilder: - if not isinstance(serial, int): - raise TypeError("serial must be an integer") - if not 0 <= serial < 2**64: - raise ValueError("serial must be between 0 and 2**64") - if self._serial is not None: - raise ValueError("serial already set") - - return SSHCertificateBuilder( - _public_key=self._public_key, - _serial=serial, - _type=self._type, - _key_id=self._key_id, - _valid_principals=self._valid_principals, - _valid_for_all_principals=self._valid_for_all_principals, - _valid_before=self._valid_before, - _valid_after=self._valid_after, - _critical_options=self._critical_options, - _extensions=self._extensions, - ) - - def type(self, type: SSHCertificateType) -> SSHCertificateBuilder: - if not isinstance(type, SSHCertificateType): - raise TypeError("type must be an SSHCertificateType") - if self._type is not None: - raise ValueError("type already set") - - return SSHCertificateBuilder( - _public_key=self._public_key, - _serial=self._serial, - _type=type, - _key_id=self._key_id, - _valid_principals=self._valid_principals, - _valid_for_all_principals=self._valid_for_all_principals, - _valid_before=self._valid_before, - _valid_after=self._valid_after, - _critical_options=self._critical_options, - _extensions=self._extensions, - ) - - def key_id(self, key_id: bytes) -> SSHCertificateBuilder: - if not isinstance(key_id, bytes): - raise TypeError("key_id must be bytes") - if self._key_id is not None: - raise ValueError("key_id already set") - - return SSHCertificateBuilder( - _public_key=self._public_key, - _serial=self._serial, - _type=self._type, - _key_id=key_id, - _valid_principals=self._valid_principals, - _valid_for_all_principals=self._valid_for_all_principals, - _valid_before=self._valid_before, - _valid_after=self._valid_after, - _critical_options=self._critical_options, - _extensions=self._extensions, - ) - - def valid_principals( - self, valid_principals: list[bytes] - ) -> SSHCertificateBuilder: - if self._valid_for_all_principals: - raise ValueError( - "Principals can't be set because the cert is valid " - "for all principals" - ) - if ( - not all(isinstance(x, bytes) for x in valid_principals) - or not valid_principals - ): - raise TypeError( - "principals must be a list of bytes and can't be empty" - ) - if self._valid_principals: - raise ValueError("valid_principals already set") - - if len(valid_principals) > _SSHKEY_CERT_MAX_PRINCIPALS: - raise ValueError( - "Reached or exceeded the maximum number of valid_principals" - ) - - return SSHCertificateBuilder( - _public_key=self._public_key, - _serial=self._serial, - _type=self._type, - _key_id=self._key_id, - _valid_principals=valid_principals, - _valid_for_all_principals=self._valid_for_all_principals, - _valid_before=self._valid_before, - _valid_after=self._valid_after, - _critical_options=self._critical_options, - _extensions=self._extensions, - ) - - def valid_for_all_principals(self): - if self._valid_principals: - raise ValueError( - "valid_principals already set, can't set " - "valid_for_all_principals" - ) - if self._valid_for_all_principals: - raise ValueError("valid_for_all_principals already set") - - return SSHCertificateBuilder( - _public_key=self._public_key, - _serial=self._serial, - _type=self._type, - _key_id=self._key_id, - _valid_principals=self._valid_principals, - _valid_for_all_principals=True, - _valid_before=self._valid_before, - _valid_after=self._valid_after, - _critical_options=self._critical_options, - _extensions=self._extensions, - ) - - def valid_before(self, valid_before: int | float) -> SSHCertificateBuilder: - if not isinstance(valid_before, (int, float)): - raise TypeError("valid_before must be an int or float") - valid_before = int(valid_before) - if valid_before < 0 or valid_before >= 2**64: - raise ValueError("valid_before must [0, 2**64)") - if self._valid_before is not None: - raise ValueError("valid_before already set") - - return SSHCertificateBuilder( - _public_key=self._public_key, - _serial=self._serial, - _type=self._type, - _key_id=self._key_id, - _valid_principals=self._valid_principals, - _valid_for_all_principals=self._valid_for_all_principals, - _valid_before=valid_before, - _valid_after=self._valid_after, - _critical_options=self._critical_options, - _extensions=self._extensions, - ) - - def valid_after(self, valid_after: int | float) -> SSHCertificateBuilder: - if not isinstance(valid_after, (int, float)): - raise TypeError("valid_after must be an int or float") - valid_after = int(valid_after) - if valid_after < 0 or valid_after >= 2**64: - raise ValueError("valid_after must [0, 2**64)") - if self._valid_after is not None: - raise ValueError("valid_after already set") - - return SSHCertificateBuilder( - _public_key=self._public_key, - _serial=self._serial, - _type=self._type, - _key_id=self._key_id, - _valid_principals=self._valid_principals, - _valid_for_all_principals=self._valid_for_all_principals, - _valid_before=self._valid_before, - _valid_after=valid_after, - _critical_options=self._critical_options, - _extensions=self._extensions, - ) - - def add_critical_option( - self, name: bytes, value: bytes - ) -> SSHCertificateBuilder: - if not isinstance(name, bytes) or not isinstance(value, bytes): - raise TypeError("name and value must be bytes") - # This is O(n**2) - if name in [name for name, _ in self._critical_options]: - raise ValueError("Duplicate critical option name") - - return SSHCertificateBuilder( - _public_key=self._public_key, - _serial=self._serial, - _type=self._type, - _key_id=self._key_id, - _valid_principals=self._valid_principals, - _valid_for_all_principals=self._valid_for_all_principals, - _valid_before=self._valid_before, - _valid_after=self._valid_after, - _critical_options=[*self._critical_options, (name, value)], - _extensions=self._extensions, - ) - - def add_extension( - self, name: bytes, value: bytes - ) -> SSHCertificateBuilder: - if not isinstance(name, bytes) or not isinstance(value, bytes): - raise TypeError("name and value must be bytes") - # This is O(n**2) - if name in [name for name, _ in self._extensions]: - raise ValueError("Duplicate extension name") - - return SSHCertificateBuilder( - _public_key=self._public_key, - _serial=self._serial, - _type=self._type, - _key_id=self._key_id, - _valid_principals=self._valid_principals, - _valid_for_all_principals=self._valid_for_all_principals, - _valid_before=self._valid_before, - _valid_after=self._valid_after, - _critical_options=self._critical_options, - _extensions=[*self._extensions, (name, value)], - ) - - def sign(self, private_key: SSHCertPrivateKeyTypes) -> SSHCertificate: - if not isinstance( - private_key, - ( - ec.EllipticCurvePrivateKey, - rsa.RSAPrivateKey, - ed25519.Ed25519PrivateKey, - ), - ): - raise TypeError("Unsupported private key type") - - if self._public_key is None: - raise ValueError("public_key must be set") - - # Not required - serial = 0 if self._serial is None else self._serial - - if self._type is None: - raise ValueError("type must be set") - - # Not required - key_id = b"" if self._key_id is None else self._key_id - - # A zero length list is valid, but means the certificate - # is valid for any principal of the specified type. We require - # the user to explicitly set valid_for_all_principals to get - # that behavior. - if not self._valid_principals and not self._valid_for_all_principals: - raise ValueError( - "valid_principals must be set if valid_for_all_principals " - "is False" - ) - - if self._valid_before is None: - raise ValueError("valid_before must be set") - - if self._valid_after is None: - raise ValueError("valid_after must be set") - - if self._valid_after > self._valid_before: - raise ValueError("valid_after must be earlier than valid_before") - - # lexically sort our byte strings - self._critical_options.sort(key=lambda x: x[0]) - self._extensions.sort(key=lambda x: x[0]) - - key_type = _get_ssh_key_type(self._public_key) - cert_prefix = key_type + _CERT_SUFFIX - - # Marshal the bytes to be signed - nonce = os.urandom(32) - kformat = _lookup_kformat(key_type) - f = _FragList() - f.put_sshstr(cert_prefix) - f.put_sshstr(nonce) - kformat.encode_public(self._public_key, f) - f.put_u64(serial) - f.put_u32(self._type.value) - f.put_sshstr(key_id) - fprincipals = _FragList() - for p in self._valid_principals: - fprincipals.put_sshstr(p) - f.put_sshstr(fprincipals.tobytes()) - f.put_u64(self._valid_after) - f.put_u64(self._valid_before) - fcrit = _FragList() - for name, value in self._critical_options: - fcrit.put_sshstr(name) - if len(value) > 0: - foptval = _FragList() - foptval.put_sshstr(value) - fcrit.put_sshstr(foptval.tobytes()) - else: - fcrit.put_sshstr(value) - f.put_sshstr(fcrit.tobytes()) - fext = _FragList() - for name, value in self._extensions: - fext.put_sshstr(name) - if len(value) > 0: - fextval = _FragList() - fextval.put_sshstr(value) - fext.put_sshstr(fextval.tobytes()) - else: - fext.put_sshstr(value) - f.put_sshstr(fext.tobytes()) - f.put_sshstr(b"") # RESERVED FIELD - # encode CA public key - ca_type = _get_ssh_key_type(private_key) - caformat = _lookup_kformat(ca_type) - caf = _FragList() - caf.put_sshstr(ca_type) - caformat.encode_public(private_key.public_key(), caf) - f.put_sshstr(caf.tobytes()) - # Sigs according to the rules defined for the CA's public key - # (RFC4253 section 6.6 for ssh-rsa, RFC5656 for ECDSA, - # and RFC8032 for Ed25519). - if isinstance(private_key, ed25519.Ed25519PrivateKey): - signature = private_key.sign(f.tobytes()) - fsig = _FragList() - fsig.put_sshstr(ca_type) - fsig.put_sshstr(signature) - f.put_sshstr(fsig.tobytes()) - elif isinstance(private_key, ec.EllipticCurvePrivateKey): - hash_alg = _get_ec_hash_alg(private_key.curve) - signature = private_key.sign(f.tobytes(), ec.ECDSA(hash_alg)) - r, s = asym_utils.decode_dss_signature(signature) - fsig = _FragList() - fsig.put_sshstr(ca_type) - fsigblob = _FragList() - fsigblob.put_mpint(r) - fsigblob.put_mpint(s) - fsig.put_sshstr(fsigblob.tobytes()) - f.put_sshstr(fsig.tobytes()) - - else: - assert isinstance(private_key, rsa.RSAPrivateKey) - # Just like Golang, we're going to use SHA512 for RSA - # https://cs.opensource.google/go/x/crypto/+/refs/tags/ - # v0.4.0:ssh/certs.go;l=445 - # RFC 8332 defines SHA256 and 512 as options - fsig = _FragList() - fsig.put_sshstr(_SSH_RSA_SHA512) - signature = private_key.sign( - f.tobytes(), padding.PKCS1v15(), hashes.SHA512() - ) - fsig.put_sshstr(signature) - f.put_sshstr(fsig.tobytes()) - - cert_data = binascii.b2a_base64(f.tobytes()).strip() - # load_ssh_public_identity returns a union, but this is - # guaranteed to be an SSHCertificate, so we cast to make - # mypy happy. - return typing.cast( - SSHCertificate, - load_ssh_public_identity(b"".join([cert_prefix, b" ", cert_data])), - ) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__init__.py deleted file mode 100644 index c1af423..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - - -class InvalidToken(Exception): - pass diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 7d7d7c7..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-312.pyc deleted file mode 100644 index d3e07a0..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-312.pyc deleted file mode 100644 index 3001baa..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/hotp.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/hotp.py deleted file mode 100644 index 21fb000..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/hotp.py +++ /dev/null @@ -1,101 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import base64 -import typing -from urllib.parse import quote, urlencode - -from cryptography.hazmat.primitives import constant_time, hmac -from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512 -from cryptography.hazmat.primitives.twofactor import InvalidToken -from cryptography.utils import Buffer - -HOTPHashTypes = typing.Union[SHA1, SHA256, SHA512] - - -def _generate_uri( - hotp: HOTP, - type_name: str, - account_name: str, - issuer: str | None, - extra_parameters: list[tuple[str, int]], -) -> str: - parameters = [ - ("digits", hotp._length), - ("secret", base64.b32encode(hotp._key)), - ("algorithm", hotp._algorithm.name.upper()), - ] - - if issuer is not None: - parameters.append(("issuer", issuer)) - - parameters.extend(extra_parameters) - - label = ( - f"{quote(issuer)}:{quote(account_name)}" - if issuer - else quote(account_name) - ) - return f"otpauth://{type_name}/{label}?{urlencode(parameters)}" - - -class HOTP: - def __init__( - self, - key: Buffer, - length: int, - algorithm: HOTPHashTypes, - backend: typing.Any = None, - enforce_key_length: bool = True, - ) -> None: - if len(key) < 16 and enforce_key_length is True: - raise ValueError("Key length has to be at least 128 bits.") - - if not isinstance(length, int): - raise TypeError("Length parameter must be an integer type.") - - if length < 6 or length > 8: - raise ValueError("Length of HOTP has to be between 6 and 8.") - - if not isinstance(algorithm, (SHA1, SHA256, SHA512)): - raise TypeError("Algorithm must be SHA1, SHA256 or SHA512.") - - self._key = key - self._length = length - self._algorithm = algorithm - - def generate(self, counter: int) -> bytes: - if not isinstance(counter, int): - raise TypeError("Counter parameter must be an integer type.") - - truncated_value = self._dynamic_truncate(counter) - hotp = truncated_value % (10**self._length) - return "{0:0{1}}".format(hotp, self._length).encode() - - def verify(self, hotp: bytes, counter: int) -> None: - if not constant_time.bytes_eq(self.generate(counter), hotp): - raise InvalidToken("Supplied HOTP value does not match.") - - def _dynamic_truncate(self, counter: int) -> int: - ctx = hmac.HMAC(self._key, self._algorithm) - - try: - ctx.update(counter.to_bytes(length=8, byteorder="big")) - except OverflowError: - raise ValueError(f"Counter must be between 0 and {2**64 - 1}.") - - hmac_value = ctx.finalize() - - offset = hmac_value[len(hmac_value) - 1] & 0b1111 - p = hmac_value[offset : offset + 4] - return int.from_bytes(p, byteorder="big") & 0x7FFFFFFF - - def get_provisioning_uri( - self, account_name: str, counter: int, issuer: str | None - ) -> str: - return _generate_uri( - self, "hotp", account_name, issuer, [("counter", int(counter))] - ) diff --git a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/totp.py b/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/totp.py deleted file mode 100644 index 10c725c..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/hazmat/primitives/twofactor/totp.py +++ /dev/null @@ -1,56 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import typing - -from cryptography.hazmat.primitives import constant_time -from cryptography.hazmat.primitives.twofactor import InvalidToken -from cryptography.hazmat.primitives.twofactor.hotp import ( - HOTP, - HOTPHashTypes, - _generate_uri, -) -from cryptography.utils import Buffer - - -class TOTP: - def __init__( - self, - key: Buffer, - length: int, - algorithm: HOTPHashTypes, - time_step: int, - backend: typing.Any = None, - enforce_key_length: bool = True, - ): - self._time_step = time_step - self._hotp = HOTP( - key, length, algorithm, enforce_key_length=enforce_key_length - ) - - def generate(self, time: int | float) -> bytes: - if not isinstance(time, (int, float)): - raise TypeError( - "Time parameter must be an integer type or float type." - ) - - counter = int(time / self._time_step) - return self._hotp.generate(counter) - - def verify(self, totp: bytes, time: int) -> None: - if not constant_time.bytes_eq(self.generate(time), totp): - raise InvalidToken("Supplied TOTP value does not match.") - - def get_provisioning_uri( - self, account_name: str, issuer: str | None - ) -> str: - return _generate_uri( - self._hotp, - "totp", - account_name, - issuer, - [("period", int(self._time_step))], - ) diff --git a/notification-service/venv/Lib/site-packages/cryptography/py.typed b/notification-service/venv/Lib/site-packages/cryptography/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/cryptography/utils.py b/notification-service/venv/Lib/site-packages/cryptography/utils.py deleted file mode 100644 index 9cfc992..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/utils.py +++ /dev/null @@ -1,135 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import enum -import sys -import types -import typing -import warnings -from collections.abc import Callable, Sequence - - -# We use a UserWarning subclass, instead of DeprecationWarning, because CPython -# decided deprecation warnings should be invisible by default. -class CryptographyDeprecationWarning(UserWarning): - pass - - -# Several APIs were deprecated with no specific end-of-life date because of the -# ubiquity of their use. They should not be removed until we agree on when that -# cycle ends. -DeprecatedIn36 = CryptographyDeprecationWarning -DeprecatedIn40 = CryptographyDeprecationWarning -DeprecatedIn41 = CryptographyDeprecationWarning -DeprecatedIn42 = CryptographyDeprecationWarning -DeprecatedIn43 = CryptographyDeprecationWarning -DeprecatedIn47 = CryptographyDeprecationWarning - - -# If you're wondering why we don't use `Buffer`, it's because `Buffer` would -# be more accurately named: Bufferable. It means something which has an -# `__buffer__`. Which means you can't actually treat the result as a buffer -# (and do things like take a `len()`). -Buffer = typing.Union[bytes, bytearray, memoryview] - - -def _check_bytes(name: str, value: bytes) -> None: - if not isinstance(value, bytes): - raise TypeError(f"{name} must be bytes") - - -def _check_byteslike(name: str, value: Buffer) -> None: - try: - memoryview(value) - except TypeError: - raise TypeError(f"{name} must be bytes-like") - - -def int_to_bytes(integer: int, length: int | None = None) -> bytes: - if length == 0: - raise ValueError("length argument can't be 0") - return integer.to_bytes( - length or (integer.bit_length() + 7) // 8 or 1, "big" - ) - - -class InterfaceNotImplemented(Exception): - pass - - -class _DeprecatedValue: - def __init__(self, value: object, message: str, warning_class): - self.value = value - self.message = message - self.warning_class = warning_class - - -class _ModuleWithDeprecations(types.ModuleType): - def __init__(self, module: types.ModuleType): - super().__init__(module.__name__) - self.__dict__["_module"] = module - - def __getattr__(self, name: str) -> typing.Any: - obj = getattr(self._module, name) - if isinstance(obj, _DeprecatedValue): - warnings.warn(obj.message, obj.warning_class, stacklevel=2) - obj = obj.value - return obj - - def __setattr__(self, attr: str, value: object) -> None: - setattr(self._module, attr, value) - - def __delattr__(self, attr: str) -> None: - obj = getattr(self._module, attr) - if isinstance(obj, _DeprecatedValue): - warnings.warn(obj.message, obj.warning_class, stacklevel=2) - - delattr(self._module, attr) - - def __dir__(self) -> Sequence[str]: - return ["_module", *dir(self._module)] - - -def deprecated( - value: object, - module_name: str, - message: str, - warning_class: type[Warning], - name: str | None = None, -) -> _DeprecatedValue: - module = sys.modules[module_name] - if not isinstance(module, _ModuleWithDeprecations): - sys.modules[module_name] = module = _ModuleWithDeprecations(module) - dv = _DeprecatedValue(value, message, warning_class) - # Maintain backwards compatibility with `name is None` for pyOpenSSL. - if name is not None: - setattr(module, name, dv) - return dv - - -def cached_property(func: Callable) -> property: - cached_name = f"_cached_{func}" - sentinel = object() - - def inner(instance: object): - cache = getattr(instance, cached_name, sentinel) - if cache is not sentinel: - return cache - result = func(instance) - setattr(instance, cached_name, result) - return result - - return property(inner) - - -# Python 3.10 changed representation of enums. We use well-defined object -# representation and string representation from Python 3.9. -class Enum(enum.Enum): - def __repr__(self) -> str: - return f"<{self.__class__.__name__}.{self._name_}: {self._value_!r}>" - - def __str__(self) -> str: - return f"{self.__class__.__name__}.{self._name_}" diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/__init__.py b/notification-service/venv/Lib/site-packages/cryptography/x509/__init__.py deleted file mode 100644 index cb34833..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/x509/__init__.py +++ /dev/null @@ -1,271 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.x509 import certificate_transparency, oid, verification -from cryptography.x509.base import ( - Attribute, - AttributeNotFound, - Attributes, - Certificate, - CertificateBuilder, - CertificateRevocationList, - CertificateRevocationListBuilder, - CertificateSigningRequest, - CertificateSigningRequestBuilder, - InvalidVersion, - RevokedCertificate, - RevokedCertificateBuilder, - Version, - load_der_x509_certificate, - load_der_x509_crl, - load_der_x509_csr, - load_pem_x509_certificate, - load_pem_x509_certificates, - load_pem_x509_crl, - load_pem_x509_csr, - random_serial_number, -) -from cryptography.x509.extensions import ( - AccessDescription, - Admission, - Admissions, - AuthorityInformationAccess, - AuthorityKeyIdentifier, - BasicConstraints, - CertificateIssuer, - CertificatePolicies, - CRLDistributionPoints, - CRLNumber, - CRLReason, - DeltaCRLIndicator, - DistributionPoint, - DuplicateExtension, - ExtendedKeyUsage, - Extension, - ExtensionNotFound, - Extensions, - ExtensionType, - FreshestCRL, - GeneralNames, - InhibitAnyPolicy, - InvalidityDate, - IssuerAlternativeName, - IssuingDistributionPoint, - KeyUsage, - MSCertificateTemplate, - NameConstraints, - NamingAuthority, - NoticeReference, - OCSPAcceptableResponses, - OCSPNoCheck, - OCSPNonce, - PolicyConstraints, - PolicyInformation, - PrecertificateSignedCertificateTimestamps, - PrecertPoison, - PrivateKeyUsagePeriod, - ProfessionInfo, - ReasonFlags, - SignedCertificateTimestamps, - SubjectAlternativeName, - SubjectInformationAccess, - SubjectKeyIdentifier, - TLSFeature, - TLSFeatureType, - UnrecognizedExtension, - UserNotice, -) -from cryptography.x509.general_name import ( - DirectoryName, - DNSName, - GeneralName, - IPAddress, - OtherName, - RegisteredID, - RFC822Name, - UniformResourceIdentifier, - UnsupportedGeneralNameType, -) -from cryptography.x509.name import ( - Name, - NameAttribute, - RelativeDistinguishedName, -) -from cryptography.x509.oid import ( - AuthorityInformationAccessOID, - CertificatePoliciesOID, - CRLEntryExtensionOID, - ExtendedKeyUsageOID, - ExtensionOID, - NameOID, - ObjectIdentifier, - PublicKeyAlgorithmOID, - SignatureAlgorithmOID, -) - -OID_AUTHORITY_INFORMATION_ACCESS = ExtensionOID.AUTHORITY_INFORMATION_ACCESS -OID_AUTHORITY_KEY_IDENTIFIER = ExtensionOID.AUTHORITY_KEY_IDENTIFIER -OID_BASIC_CONSTRAINTS = ExtensionOID.BASIC_CONSTRAINTS -OID_CERTIFICATE_POLICIES = ExtensionOID.CERTIFICATE_POLICIES -OID_CRL_DISTRIBUTION_POINTS = ExtensionOID.CRL_DISTRIBUTION_POINTS -OID_EXTENDED_KEY_USAGE = ExtensionOID.EXTENDED_KEY_USAGE -OID_FRESHEST_CRL = ExtensionOID.FRESHEST_CRL -OID_INHIBIT_ANY_POLICY = ExtensionOID.INHIBIT_ANY_POLICY -OID_ISSUER_ALTERNATIVE_NAME = ExtensionOID.ISSUER_ALTERNATIVE_NAME -OID_KEY_USAGE = ExtensionOID.KEY_USAGE -OID_PRIVATE_KEY_USAGE_PERIOD = ExtensionOID.PRIVATE_KEY_USAGE_PERIOD -OID_NAME_CONSTRAINTS = ExtensionOID.NAME_CONSTRAINTS -OID_OCSP_NO_CHECK = ExtensionOID.OCSP_NO_CHECK -OID_POLICY_CONSTRAINTS = ExtensionOID.POLICY_CONSTRAINTS -OID_POLICY_MAPPINGS = ExtensionOID.POLICY_MAPPINGS -OID_SUBJECT_ALTERNATIVE_NAME = ExtensionOID.SUBJECT_ALTERNATIVE_NAME -OID_SUBJECT_DIRECTORY_ATTRIBUTES = ExtensionOID.SUBJECT_DIRECTORY_ATTRIBUTES -OID_SUBJECT_INFORMATION_ACCESS = ExtensionOID.SUBJECT_INFORMATION_ACCESS -OID_SUBJECT_KEY_IDENTIFIER = ExtensionOID.SUBJECT_KEY_IDENTIFIER - -OID_DSA_WITH_SHA1 = SignatureAlgorithmOID.DSA_WITH_SHA1 -OID_DSA_WITH_SHA224 = SignatureAlgorithmOID.DSA_WITH_SHA224 -OID_DSA_WITH_SHA256 = SignatureAlgorithmOID.DSA_WITH_SHA256 -OID_ECDSA_WITH_SHA1 = SignatureAlgorithmOID.ECDSA_WITH_SHA1 -OID_ECDSA_WITH_SHA224 = SignatureAlgorithmOID.ECDSA_WITH_SHA224 -OID_ECDSA_WITH_SHA256 = SignatureAlgorithmOID.ECDSA_WITH_SHA256 -OID_ECDSA_WITH_SHA384 = SignatureAlgorithmOID.ECDSA_WITH_SHA384 -OID_ECDSA_WITH_SHA512 = SignatureAlgorithmOID.ECDSA_WITH_SHA512 -OID_RSA_WITH_MD5 = SignatureAlgorithmOID.RSA_WITH_MD5 -OID_RSA_WITH_SHA1 = SignatureAlgorithmOID.RSA_WITH_SHA1 -OID_RSA_WITH_SHA224 = SignatureAlgorithmOID.RSA_WITH_SHA224 -OID_RSA_WITH_SHA256 = SignatureAlgorithmOID.RSA_WITH_SHA256 -OID_RSA_WITH_SHA384 = SignatureAlgorithmOID.RSA_WITH_SHA384 -OID_RSA_WITH_SHA512 = SignatureAlgorithmOID.RSA_WITH_SHA512 -OID_RSASSA_PSS = SignatureAlgorithmOID.RSASSA_PSS - -OID_COMMON_NAME = NameOID.COMMON_NAME -OID_COUNTRY_NAME = NameOID.COUNTRY_NAME -OID_DOMAIN_COMPONENT = NameOID.DOMAIN_COMPONENT -OID_DN_QUALIFIER = NameOID.DN_QUALIFIER -OID_EMAIL_ADDRESS = NameOID.EMAIL_ADDRESS -OID_GENERATION_QUALIFIER = NameOID.GENERATION_QUALIFIER -OID_GIVEN_NAME = NameOID.GIVEN_NAME -OID_LOCALITY_NAME = NameOID.LOCALITY_NAME -OID_ORGANIZATIONAL_UNIT_NAME = NameOID.ORGANIZATIONAL_UNIT_NAME -OID_ORGANIZATION_NAME = NameOID.ORGANIZATION_NAME -OID_PSEUDONYM = NameOID.PSEUDONYM -OID_SERIAL_NUMBER = NameOID.SERIAL_NUMBER -OID_STATE_OR_PROVINCE_NAME = NameOID.STATE_OR_PROVINCE_NAME -OID_SURNAME = NameOID.SURNAME -OID_TITLE = NameOID.TITLE - -OID_CLIENT_AUTH = ExtendedKeyUsageOID.CLIENT_AUTH -OID_CODE_SIGNING = ExtendedKeyUsageOID.CODE_SIGNING -OID_EMAIL_PROTECTION = ExtendedKeyUsageOID.EMAIL_PROTECTION -OID_OCSP_SIGNING = ExtendedKeyUsageOID.OCSP_SIGNING -OID_SERVER_AUTH = ExtendedKeyUsageOID.SERVER_AUTH -OID_TIME_STAMPING = ExtendedKeyUsageOID.TIME_STAMPING - -OID_ANY_POLICY = CertificatePoliciesOID.ANY_POLICY -OID_CPS_QUALIFIER = CertificatePoliciesOID.CPS_QUALIFIER -OID_CPS_USER_NOTICE = CertificatePoliciesOID.CPS_USER_NOTICE - -OID_CERTIFICATE_ISSUER = CRLEntryExtensionOID.CERTIFICATE_ISSUER -OID_CRL_REASON = CRLEntryExtensionOID.CRL_REASON -OID_INVALIDITY_DATE = CRLEntryExtensionOID.INVALIDITY_DATE - -OID_CA_ISSUERS = AuthorityInformationAccessOID.CA_ISSUERS -OID_OCSP = AuthorityInformationAccessOID.OCSP - -__all__ = [ - "OID_CA_ISSUERS", - "OID_OCSP", - "AccessDescription", - "Admission", - "Admissions", - "Attribute", - "AttributeNotFound", - "Attributes", - "AuthorityInformationAccess", - "AuthorityKeyIdentifier", - "BasicConstraints", - "CRLDistributionPoints", - "CRLNumber", - "CRLReason", - "Certificate", - "CertificateBuilder", - "CertificateIssuer", - "CertificatePolicies", - "CertificateRevocationList", - "CertificateRevocationListBuilder", - "CertificateSigningRequest", - "CertificateSigningRequestBuilder", - "DNSName", - "DeltaCRLIndicator", - "DirectoryName", - "DistributionPoint", - "DuplicateExtension", - "ExtendedKeyUsage", - "Extension", - "ExtensionNotFound", - "ExtensionType", - "Extensions", - "FreshestCRL", - "GeneralName", - "GeneralNames", - "IPAddress", - "InhibitAnyPolicy", - "InvalidVersion", - "InvalidityDate", - "IssuerAlternativeName", - "IssuingDistributionPoint", - "KeyUsage", - "MSCertificateTemplate", - "Name", - "NameAttribute", - "NameConstraints", - "NameOID", - "NamingAuthority", - "NoticeReference", - "OCSPAcceptableResponses", - "OCSPNoCheck", - "OCSPNonce", - "ObjectIdentifier", - "OtherName", - "PolicyConstraints", - "PolicyInformation", - "PrecertPoison", - "PrecertificateSignedCertificateTimestamps", - "PrivateKeyUsagePeriod", - "ProfessionInfo", - "PublicKeyAlgorithmOID", - "RFC822Name", - "ReasonFlags", - "RegisteredID", - "RelativeDistinguishedName", - "RevokedCertificate", - "RevokedCertificateBuilder", - "SignatureAlgorithmOID", - "SignedCertificateTimestamps", - "SubjectAlternativeName", - "SubjectInformationAccess", - "SubjectKeyIdentifier", - "TLSFeature", - "TLSFeatureType", - "UniformResourceIdentifier", - "UnrecognizedExtension", - "UnsupportedGeneralNameType", - "UserNotice", - "Version", - "certificate_transparency", - "load_der_x509_certificate", - "load_der_x509_crl", - "load_der_x509_csr", - "load_pem_x509_certificate", - "load_pem_x509_certificates", - "load_pem_x509_crl", - "load_pem_x509_csr", - "oid", - "random_serial_number", - "verification", - "verification", -] diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index fd9ad8b..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/base.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/base.cpython-312.pyc deleted file mode 100644 index d2df06d..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/base.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/certificate_transparency.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/certificate_transparency.cpython-312.pyc deleted file mode 100644 index ed9dccd..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/certificate_transparency.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/extensions.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/extensions.cpython-312.pyc deleted file mode 100644 index 30b8066..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/extensions.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/general_name.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/general_name.cpython-312.pyc deleted file mode 100644 index 75257c0..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/general_name.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/name.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/name.cpython-312.pyc deleted file mode 100644 index b4c46a7..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/name.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/ocsp.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/ocsp.cpython-312.pyc deleted file mode 100644 index 36be28d..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/ocsp.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/oid.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/oid.cpython-312.pyc deleted file mode 100644 index be4eb48..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/oid.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/verification.cpython-312.pyc b/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/verification.cpython-312.pyc deleted file mode 100644 index e2a9405..0000000 Binary files a/notification-service/venv/Lib/site-packages/cryptography/x509/__pycache__/verification.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/base.py b/notification-service/venv/Lib/site-packages/cryptography/x509/base.py deleted file mode 100644 index a11b8fe..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/x509/base.py +++ /dev/null @@ -1,773 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import datetime -import os -import typing -from collections.abc import Iterable - -from cryptography import utils -from cryptography.hazmat.bindings._rust import x509 as rust_x509 -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.asymmetric import ( - dsa, - ec, - ed448, - ed25519, - padding, - rsa, - x448, - x25519, -) -from cryptography.hazmat.primitives.asymmetric.types import ( - CertificateIssuerPrivateKeyTypes, - CertificatePublicKeyTypes, -) -from cryptography.x509.extensions import ( - Extension, - ExtensionType, - _make_sequence_methods, -) -from cryptography.x509.name import Name, _ASN1Type -from cryptography.x509.oid import ObjectIdentifier - -_EARLIEST_UTC_TIME = datetime.datetime(1950, 1, 1) - -# This must be kept in sync with sign.rs's list of allowable types in -# identify_hash_type -_AllowedHashTypes = typing.Union[ - hashes.SHA224, - hashes.SHA256, - hashes.SHA384, - hashes.SHA512, - hashes.SHA3_224, - hashes.SHA3_256, - hashes.SHA3_384, - hashes.SHA3_512, -] - - -class AttributeNotFound(Exception): - def __init__(self, msg: str, oid: ObjectIdentifier) -> None: - super().__init__(msg) - self.oid = oid - - -def _reject_duplicate_extension( - extension: Extension[ExtensionType], - extensions: list[Extension[ExtensionType]], -) -> None: - # This is quadratic in the number of extensions - for e in extensions: - if e.oid == extension.oid: - raise ValueError("This extension has already been set.") - - -def _reject_duplicate_attribute( - oid: ObjectIdentifier, - attributes: list[tuple[ObjectIdentifier, bytes, int | None]], -) -> None: - # This is quadratic in the number of attributes - for attr_oid, _, _ in attributes: - if attr_oid == oid: - raise ValueError("This attribute has already been set.") - - -def _convert_to_naive_utc_time(time: datetime.datetime) -> datetime.datetime: - """Normalizes a datetime to a naive datetime in UTC. - - time -- datetime to normalize. Assumed to be in UTC if not timezone - aware. - """ - if time.tzinfo is not None: - offset = time.utcoffset() - offset = offset if offset else datetime.timedelta() - return time.replace(tzinfo=None) - offset - else: - return time - - -class Attribute: - def __init__( - self, - oid: ObjectIdentifier, - value: bytes, - _type: int = _ASN1Type.UTF8String.value, - ) -> None: - self._oid = oid - self._value = value - self._type = _type - - @property - def oid(self) -> ObjectIdentifier: - return self._oid - - @property - def value(self) -> bytes: - return self._value - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, Attribute): - return NotImplemented - - return ( - self.oid == other.oid - and self.value == other.value - and self._type == other._type - ) - - def __hash__(self) -> int: - return hash((self.oid, self.value, self._type)) - - -class Attributes: - def __init__( - self, - attributes: Iterable[Attribute], - ) -> None: - self._attributes = list(attributes) - - __len__, __iter__, __getitem__ = _make_sequence_methods("_attributes") - - def __repr__(self) -> str: - return f"" - - def get_attribute_for_oid(self, oid: ObjectIdentifier) -> Attribute: - for attr in self: - if attr.oid == oid: - return attr - - raise AttributeNotFound(f"No {oid} attribute was found", oid) - - -class Version(utils.Enum): - v1 = 0 - v3 = 2 - - -class InvalidVersion(Exception): - def __init__(self, msg: str, parsed_version: int) -> None: - super().__init__(msg) - self.parsed_version = parsed_version - - -Certificate = rust_x509.Certificate -RevokedCertificate = rust_x509.RevokedCertificate - - -CertificateRevocationList = rust_x509.CertificateRevocationList -CertificateSigningRequest = rust_x509.CertificateSigningRequest - - -load_pem_x509_certificate = rust_x509.load_pem_x509_certificate -load_der_x509_certificate = rust_x509.load_der_x509_certificate - -load_pem_x509_certificates = rust_x509.load_pem_x509_certificates - -load_pem_x509_csr = rust_x509.load_pem_x509_csr -load_der_x509_csr = rust_x509.load_der_x509_csr - -load_pem_x509_crl = rust_x509.load_pem_x509_crl -load_der_x509_crl = rust_x509.load_der_x509_crl - - -class CertificateSigningRequestBuilder: - def __init__( - self, - subject_name: Name | None = None, - extensions: list[Extension[ExtensionType]] = [], - attributes: list[tuple[ObjectIdentifier, bytes, int | None]] = [], - ): - """ - Creates an empty X.509 certificate request (v1). - """ - self._subject_name = subject_name - self._extensions = extensions - self._attributes = attributes - - def subject_name(self, name: Name) -> CertificateSigningRequestBuilder: - """ - Sets the certificate requestor's distinguished name. - """ - if not isinstance(name, Name): - raise TypeError("Expecting x509.Name object.") - if self._subject_name is not None: - raise ValueError("The subject name may only be set once.") - return CertificateSigningRequestBuilder( - name, self._extensions, self._attributes - ) - - def add_extension( - self, extval: ExtensionType, critical: bool - ) -> CertificateSigningRequestBuilder: - """ - Adds an X.509 extension to the certificate request. - """ - if not isinstance(extval, ExtensionType): - raise TypeError("extension must be an ExtensionType") - - extension = Extension(extval.oid, critical, extval) - _reject_duplicate_extension(extension, self._extensions) - - return CertificateSigningRequestBuilder( - self._subject_name, - [*self._extensions, extension], - self._attributes, - ) - - def add_attribute( - self, - oid: ObjectIdentifier, - value: bytes, - *, - _tag: _ASN1Type | None = None, - ) -> CertificateSigningRequestBuilder: - """ - Adds an X.509 attribute with an OID and associated value. - """ - if not isinstance(oid, ObjectIdentifier): - raise TypeError("oid must be an ObjectIdentifier") - - if not isinstance(value, bytes): - raise TypeError("value must be bytes") - - if _tag is not None and not isinstance(_tag, _ASN1Type): - raise TypeError("tag must be _ASN1Type") - - _reject_duplicate_attribute(oid, self._attributes) - - if _tag is not None: - tag = _tag.value - else: - tag = None - - return CertificateSigningRequestBuilder( - self._subject_name, - self._extensions, - [*self._attributes, (oid, value, tag)], - ) - - def sign( - self, - private_key: CertificateIssuerPrivateKeyTypes, - algorithm: _AllowedHashTypes | None, - backend: typing.Any = None, - *, - rsa_padding: padding.PSS | padding.PKCS1v15 | None = None, - ecdsa_deterministic: bool | None = None, - ) -> CertificateSigningRequest: - """ - Signs the request using the requestor's private key. - """ - if self._subject_name is None: - raise ValueError("A CertificateSigningRequest must have a subject") - - if rsa_padding is not None: - if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)): - raise TypeError("Padding must be PSS or PKCS1v15") - if not isinstance(private_key, rsa.RSAPrivateKey): - raise TypeError("Padding is only supported for RSA keys") - - if ecdsa_deterministic is not None: - if not isinstance(private_key, ec.EllipticCurvePrivateKey): - raise TypeError( - "Deterministic ECDSA is only supported for EC keys" - ) - - return rust_x509.create_x509_csr( - self, - private_key, - algorithm, - rsa_padding, - ecdsa_deterministic, - ) - - -class CertificateBuilder: - _extensions: list[Extension[ExtensionType]] - - def __init__( - self, - issuer_name: Name | None = None, - subject_name: Name | None = None, - public_key: CertificatePublicKeyTypes | None = None, - serial_number: int | None = None, - not_valid_before: datetime.datetime | None = None, - not_valid_after: datetime.datetime | None = None, - extensions: list[Extension[ExtensionType]] = [], - ) -> None: - self._version = Version.v3 - self._issuer_name = issuer_name - self._subject_name = subject_name - self._public_key = public_key - self._serial_number = serial_number - self._not_valid_before = not_valid_before - self._not_valid_after = not_valid_after - self._extensions = extensions - - def issuer_name(self, name: Name) -> CertificateBuilder: - """ - Sets the CA's distinguished name. - """ - if not isinstance(name, Name): - raise TypeError("Expecting x509.Name object.") - if self._issuer_name is not None: - raise ValueError("The issuer name may only be set once.") - return CertificateBuilder( - name, - self._subject_name, - self._public_key, - self._serial_number, - self._not_valid_before, - self._not_valid_after, - self._extensions, - ) - - def subject_name(self, name: Name) -> CertificateBuilder: - """ - Sets the requestor's distinguished name. - """ - if not isinstance(name, Name): - raise TypeError("Expecting x509.Name object.") - if self._subject_name is not None: - raise ValueError("The subject name may only be set once.") - return CertificateBuilder( - self._issuer_name, - name, - self._public_key, - self._serial_number, - self._not_valid_before, - self._not_valid_after, - self._extensions, - ) - - def public_key( - self, - key: CertificatePublicKeyTypes, - ) -> CertificateBuilder: - """ - Sets the requestor's public key (as found in the signing request). - """ - if not isinstance( - key, - ( - dsa.DSAPublicKey, - rsa.RSAPublicKey, - ec.EllipticCurvePublicKey, - ed25519.Ed25519PublicKey, - ed448.Ed448PublicKey, - x25519.X25519PublicKey, - x448.X448PublicKey, - ), - ): - raise TypeError( - "Expecting one of DSAPublicKey, RSAPublicKey," - " EllipticCurvePublicKey, Ed25519PublicKey," - " Ed448PublicKey, X25519PublicKey, or " - "X448PublicKey." - ) - if self._public_key is not None: - raise ValueError("The public key may only be set once.") - return CertificateBuilder( - self._issuer_name, - self._subject_name, - key, - self._serial_number, - self._not_valid_before, - self._not_valid_after, - self._extensions, - ) - - def serial_number(self, number: int) -> CertificateBuilder: - """ - Sets the certificate serial number. - """ - if not isinstance(number, int): - raise TypeError("Serial number must be of integral type.") - if self._serial_number is not None: - raise ValueError("The serial number may only be set once.") - if number <= 0: - raise ValueError("The serial number should be positive.") - - # ASN.1 integers are always signed, so most significant bit must be - # zero. - if number.bit_length() >= 160: # As defined in RFC 5280 - raise ValueError( - "The serial number should not be more than 159 bits." - ) - return CertificateBuilder( - self._issuer_name, - self._subject_name, - self._public_key, - number, - self._not_valid_before, - self._not_valid_after, - self._extensions, - ) - - def not_valid_before(self, time: datetime.datetime) -> CertificateBuilder: - """ - Sets the certificate activation time. - """ - if not isinstance(time, datetime.datetime): - raise TypeError("Expecting datetime object.") - if self._not_valid_before is not None: - raise ValueError("The not valid before may only be set once.") - time = _convert_to_naive_utc_time(time) - if time < _EARLIEST_UTC_TIME: - raise ValueError( - "The not valid before date must be on or after" - " 1950 January 1)." - ) - if self._not_valid_after is not None and time > self._not_valid_after: - raise ValueError( - "The not valid before date must be before the not valid after " - "date." - ) - return CertificateBuilder( - self._issuer_name, - self._subject_name, - self._public_key, - self._serial_number, - time, - self._not_valid_after, - self._extensions, - ) - - def not_valid_after(self, time: datetime.datetime) -> CertificateBuilder: - """ - Sets the certificate expiration time. - """ - if not isinstance(time, datetime.datetime): - raise TypeError("Expecting datetime object.") - if self._not_valid_after is not None: - raise ValueError("The not valid after may only be set once.") - time = _convert_to_naive_utc_time(time) - if time < _EARLIEST_UTC_TIME: - raise ValueError( - "The not valid after date must be on or after 1950 January 1." - ) - if ( - self._not_valid_before is not None - and time < self._not_valid_before - ): - raise ValueError( - "The not valid after date must be after the not valid before " - "date." - ) - return CertificateBuilder( - self._issuer_name, - self._subject_name, - self._public_key, - self._serial_number, - self._not_valid_before, - time, - self._extensions, - ) - - def add_extension( - self, extval: ExtensionType, critical: bool - ) -> CertificateBuilder: - """ - Adds an X.509 extension to the certificate. - """ - if not isinstance(extval, ExtensionType): - raise TypeError("extension must be an ExtensionType") - - extension = Extension(extval.oid, critical, extval) - _reject_duplicate_extension(extension, self._extensions) - - return CertificateBuilder( - self._issuer_name, - self._subject_name, - self._public_key, - self._serial_number, - self._not_valid_before, - self._not_valid_after, - [*self._extensions, extension], - ) - - def sign( - self, - private_key: CertificateIssuerPrivateKeyTypes, - algorithm: _AllowedHashTypes | None, - backend: typing.Any = None, - *, - rsa_padding: padding.PSS | padding.PKCS1v15 | None = None, - ecdsa_deterministic: bool | None = None, - ) -> Certificate: - """ - Signs the certificate using the CA's private key. - """ - if self._subject_name is None: - raise ValueError("A certificate must have a subject name") - - if self._issuer_name is None: - raise ValueError("A certificate must have an issuer name") - - if self._serial_number is None: - raise ValueError("A certificate must have a serial number") - - if self._not_valid_before is None: - raise ValueError("A certificate must have a not valid before time") - - if self._not_valid_after is None: - raise ValueError("A certificate must have a not valid after time") - - if self._public_key is None: - raise ValueError("A certificate must have a public key") - - if rsa_padding is not None: - if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)): - raise TypeError("Padding must be PSS or PKCS1v15") - if not isinstance(private_key, rsa.RSAPrivateKey): - raise TypeError("Padding is only supported for RSA keys") - - if ecdsa_deterministic is not None: - if not isinstance(private_key, ec.EllipticCurvePrivateKey): - raise TypeError( - "Deterministic ECDSA is only supported for EC keys" - ) - - return rust_x509.create_x509_certificate( - self, - private_key, - algorithm, - rsa_padding, - ecdsa_deterministic, - ) - - -class CertificateRevocationListBuilder: - _extensions: list[Extension[ExtensionType]] - _revoked_certificates: list[RevokedCertificate] - - def __init__( - self, - issuer_name: Name | None = None, - last_update: datetime.datetime | None = None, - next_update: datetime.datetime | None = None, - extensions: list[Extension[ExtensionType]] = [], - revoked_certificates: list[RevokedCertificate] = [], - ): - self._issuer_name = issuer_name - self._last_update = last_update - self._next_update = next_update - self._extensions = extensions - self._revoked_certificates = revoked_certificates - - def issuer_name( - self, issuer_name: Name - ) -> CertificateRevocationListBuilder: - if not isinstance(issuer_name, Name): - raise TypeError("Expecting x509.Name object.") - if self._issuer_name is not None: - raise ValueError("The issuer name may only be set once.") - return CertificateRevocationListBuilder( - issuer_name, - self._last_update, - self._next_update, - self._extensions, - self._revoked_certificates, - ) - - def last_update( - self, last_update: datetime.datetime - ) -> CertificateRevocationListBuilder: - if not isinstance(last_update, datetime.datetime): - raise TypeError("Expecting datetime object.") - if self._last_update is not None: - raise ValueError("Last update may only be set once.") - last_update = _convert_to_naive_utc_time(last_update) - if last_update < _EARLIEST_UTC_TIME: - raise ValueError( - "The last update date must be on or after 1950 January 1." - ) - if self._next_update is not None and last_update > self._next_update: - raise ValueError( - "The last update date must be before the next update date." - ) - return CertificateRevocationListBuilder( - self._issuer_name, - last_update, - self._next_update, - self._extensions, - self._revoked_certificates, - ) - - def next_update( - self, next_update: datetime.datetime - ) -> CertificateRevocationListBuilder: - if not isinstance(next_update, datetime.datetime): - raise TypeError("Expecting datetime object.") - if self._next_update is not None: - raise ValueError("Last update may only be set once.") - next_update = _convert_to_naive_utc_time(next_update) - if next_update < _EARLIEST_UTC_TIME: - raise ValueError( - "The last update date must be on or after 1950 January 1." - ) - if self._last_update is not None and next_update < self._last_update: - raise ValueError( - "The next update date must be after the last update date." - ) - return CertificateRevocationListBuilder( - self._issuer_name, - self._last_update, - next_update, - self._extensions, - self._revoked_certificates, - ) - - def add_extension( - self, extval: ExtensionType, critical: bool - ) -> CertificateRevocationListBuilder: - """ - Adds an X.509 extension to the certificate revocation list. - """ - if not isinstance(extval, ExtensionType): - raise TypeError("extension must be an ExtensionType") - - extension = Extension(extval.oid, critical, extval) - _reject_duplicate_extension(extension, self._extensions) - return CertificateRevocationListBuilder( - self._issuer_name, - self._last_update, - self._next_update, - [*self._extensions, extension], - self._revoked_certificates, - ) - - def add_revoked_certificate( - self, revoked_certificate: RevokedCertificate - ) -> CertificateRevocationListBuilder: - """ - Adds a revoked certificate to the CRL. - """ - if not isinstance(revoked_certificate, RevokedCertificate): - raise TypeError("Must be an instance of RevokedCertificate") - - return CertificateRevocationListBuilder( - self._issuer_name, - self._last_update, - self._next_update, - self._extensions, - [*self._revoked_certificates, revoked_certificate], - ) - - def sign( - self, - private_key: CertificateIssuerPrivateKeyTypes, - algorithm: _AllowedHashTypes | None, - backend: typing.Any = None, - *, - rsa_padding: padding.PSS | padding.PKCS1v15 | None = None, - ecdsa_deterministic: bool | None = None, - ) -> CertificateRevocationList: - if self._issuer_name is None: - raise ValueError("A CRL must have an issuer name") - - if self._last_update is None: - raise ValueError("A CRL must have a last update time") - - if self._next_update is None: - raise ValueError("A CRL must have a next update time") - - if rsa_padding is not None: - if not isinstance(rsa_padding, (padding.PSS, padding.PKCS1v15)): - raise TypeError("Padding must be PSS or PKCS1v15") - if not isinstance(private_key, rsa.RSAPrivateKey): - raise TypeError("Padding is only supported for RSA keys") - - if ecdsa_deterministic is not None: - if not isinstance(private_key, ec.EllipticCurvePrivateKey): - raise TypeError( - "Deterministic ECDSA is only supported for EC keys" - ) - - return rust_x509.create_x509_crl( - self, - private_key, - algorithm, - rsa_padding, - ecdsa_deterministic, - ) - - -class RevokedCertificateBuilder: - def __init__( - self, - serial_number: int | None = None, - revocation_date: datetime.datetime | None = None, - extensions: list[Extension[ExtensionType]] = [], - ): - self._serial_number = serial_number - self._revocation_date = revocation_date - self._extensions = extensions - - def serial_number(self, number: int) -> RevokedCertificateBuilder: - if not isinstance(number, int): - raise TypeError("Serial number must be of integral type.") - if self._serial_number is not None: - raise ValueError("The serial number may only be set once.") - if number <= 0: - raise ValueError("The serial number should be positive") - - # ASN.1 integers are always signed, so most significant bit must be - # zero. - if number.bit_length() >= 160: # As defined in RFC 5280 - raise ValueError( - "The serial number should not be more than 159 bits." - ) - return RevokedCertificateBuilder( - number, self._revocation_date, self._extensions - ) - - def revocation_date( - self, time: datetime.datetime - ) -> RevokedCertificateBuilder: - if not isinstance(time, datetime.datetime): - raise TypeError("Expecting datetime object.") - if self._revocation_date is not None: - raise ValueError("The revocation date may only be set once.") - time = _convert_to_naive_utc_time(time) - if time < _EARLIEST_UTC_TIME: - raise ValueError( - "The revocation date must be on or after 1950 January 1." - ) - return RevokedCertificateBuilder( - self._serial_number, time, self._extensions - ) - - def add_extension( - self, extval: ExtensionType, critical: bool - ) -> RevokedCertificateBuilder: - if not isinstance(extval, ExtensionType): - raise TypeError("extension must be an ExtensionType") - - extension = Extension(extval.oid, critical, extval) - _reject_duplicate_extension(extension, self._extensions) - return RevokedCertificateBuilder( - self._serial_number, - self._revocation_date, - [*self._extensions, extension], - ) - - def build(self, backend: typing.Any = None) -> RevokedCertificate: - if self._serial_number is None: - raise ValueError("A revoked certificate must have a serial number") - if self._revocation_date is None: - raise ValueError( - "A revoked certificate must have a revocation date" - ) - return rust_x509.create_revoked_certificate(self) - - -def random_serial_number() -> int: - return int.from_bytes(os.urandom(20), "big") >> 1 diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/certificate_transparency.py b/notification-service/venv/Lib/site-packages/cryptography/x509/certificate_transparency.py deleted file mode 100644 index fb66cc6..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/x509/certificate_transparency.py +++ /dev/null @@ -1,35 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography import utils -from cryptography.hazmat.bindings._rust import x509 as rust_x509 - - -class LogEntryType(utils.Enum): - X509_CERTIFICATE = 0 - PRE_CERTIFICATE = 1 - - -class Version(utils.Enum): - v1 = 0 - - -class SignatureAlgorithm(utils.Enum): - """ - Signature algorithms that are valid for SCTs. - - These are exactly the same as SignatureAlgorithm in RFC 5246 (TLS 1.2). - - See: - """ - - ANONYMOUS = 0 - RSA = 1 - DSA = 2 - ECDSA = 3 - - -SignedCertificateTimestamp = rust_x509.Sct diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/extensions.py b/notification-service/venv/Lib/site-packages/cryptography/x509/extensions.py deleted file mode 100644 index 7b78e9e..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/x509/extensions.py +++ /dev/null @@ -1,2533 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc -import datetime -import hashlib -import ipaddress -import typing -from collections.abc import Iterable, Iterator - -from cryptography import utils -from cryptography.hazmat.bindings._rust import asn1 -from cryptography.hazmat.bindings._rust import x509 as rust_x509 -from cryptography.hazmat.primitives import constant_time, serialization -from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey -from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey -from cryptography.hazmat.primitives.asymmetric.types import ( - CertificateIssuerPublicKeyTypes, - CertificatePublicKeyTypes, -) -from cryptography.x509.certificate_transparency import ( - SignedCertificateTimestamp, -) -from cryptography.x509.general_name import ( - DirectoryName, - DNSName, - GeneralName, - IPAddress, - OtherName, - RegisteredID, - RFC822Name, - UniformResourceIdentifier, - _IPAddressTypes, -) -from cryptography.x509.name import Name, RelativeDistinguishedName -from cryptography.x509.oid import ( - CRLEntryExtensionOID, - ExtensionOID, - ObjectIdentifier, - OCSPExtensionOID, -) - -ExtensionTypeVar = typing.TypeVar( - "ExtensionTypeVar", bound="ExtensionType", covariant=True -) - - -def _key_identifier_from_public_key( - public_key: CertificatePublicKeyTypes, -) -> bytes: - if isinstance(public_key, RSAPublicKey): - data = public_key.public_bytes( - serialization.Encoding.DER, - serialization.PublicFormat.PKCS1, - ) - elif isinstance(public_key, EllipticCurvePublicKey): - data = public_key.public_bytes( - serialization.Encoding.X962, - serialization.PublicFormat.UncompressedPoint, - ) - else: - # This is a very slow way to do this. - serialized = public_key.public_bytes( - serialization.Encoding.DER, - serialization.PublicFormat.SubjectPublicKeyInfo, - ) - data = asn1.parse_spki_for_data(serialized) - - return hashlib.sha1(data).digest() - - -def _make_sequence_methods(field_name: str): - def len_method(self) -> int: - return len(getattr(self, field_name)) - - def iter_method(self): - return iter(getattr(self, field_name)) - - def getitem_method(self, idx): - return getattr(self, field_name)[idx] - - return len_method, iter_method, getitem_method - - -class DuplicateExtension(Exception): - def __init__(self, msg: str, oid: ObjectIdentifier) -> None: - super().__init__(msg) - self.oid = oid - - -class ExtensionNotFound(Exception): - def __init__(self, msg: str, oid: ObjectIdentifier) -> None: - super().__init__(msg) - self.oid = oid - - -class ExtensionType(metaclass=abc.ABCMeta): - oid: typing.ClassVar[ObjectIdentifier] - - def public_bytes(self) -> bytes: - """ - Serializes the extension type to DER. - """ - raise NotImplementedError( - f"public_bytes is not implemented for extension type {self!r}" - ) - - -class Extensions: - def __init__(self, extensions: Iterable[Extension[ExtensionType]]) -> None: - self._extensions = list(extensions) - - def get_extension_for_oid( - self, oid: ObjectIdentifier - ) -> Extension[ExtensionType]: - for ext in self: - if ext.oid == oid: - return ext - - raise ExtensionNotFound(f"No {oid} extension was found", oid) - - def get_extension_for_class( - self, extclass: type[ExtensionTypeVar] - ) -> Extension[ExtensionTypeVar]: - if extclass is UnrecognizedExtension: - raise TypeError( - "UnrecognizedExtension can't be used with " - "get_extension_for_class because more than one instance of the" - " class may be present." - ) - - for ext in self: - if isinstance(ext.value, extclass): - return ext - - raise ExtensionNotFound( - f"No {extclass} extension was found", extclass.oid - ) - - __len__, __iter__, __getitem__ = _make_sequence_methods("_extensions") - - def __repr__(self) -> str: - return f"" - - -class CRLNumber(ExtensionType): - oid = ExtensionOID.CRL_NUMBER - - def __init__(self, crl_number: int) -> None: - if not isinstance(crl_number, int): - raise TypeError("crl_number must be an integer") - - self._crl_number = crl_number - - def __eq__(self, other: object) -> bool: - if not isinstance(other, CRLNumber): - return NotImplemented - - return self.crl_number == other.crl_number - - def __hash__(self) -> int: - return hash(self.crl_number) - - def __repr__(self) -> str: - return f"" - - @property - def crl_number(self) -> int: - return self._crl_number - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class AuthorityKeyIdentifier(ExtensionType): - oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER - - def __init__( - self, - key_identifier: bytes | None, - authority_cert_issuer: Iterable[GeneralName] | None, - authority_cert_serial_number: int | None, - ) -> None: - if (authority_cert_issuer is None) != ( - authority_cert_serial_number is None - ): - raise ValueError( - "authority_cert_issuer and authority_cert_serial_number " - "must both be present or both None" - ) - - if authority_cert_issuer is not None: - authority_cert_issuer = list(authority_cert_issuer) - if not all( - isinstance(x, GeneralName) for x in authority_cert_issuer - ): - raise TypeError( - "authority_cert_issuer must be a list of GeneralName " - "objects" - ) - - if authority_cert_serial_number is not None and not isinstance( - authority_cert_serial_number, int - ): - raise TypeError("authority_cert_serial_number must be an integer") - - self._key_identifier = key_identifier - self._authority_cert_issuer = authority_cert_issuer - self._authority_cert_serial_number = authority_cert_serial_number - - # This takes a subset of CertificatePublicKeyTypes because an issuer - # cannot have an X25519/X448 key. This introduces some unfortunate - # asymmetry that requires typing users to explicitly - # narrow their type, but we should make this accurate and not just - # convenient. - @classmethod - def from_issuer_public_key( - cls, public_key: CertificateIssuerPublicKeyTypes - ) -> AuthorityKeyIdentifier: - digest = _key_identifier_from_public_key(public_key) - return cls( - key_identifier=digest, - authority_cert_issuer=None, - authority_cert_serial_number=None, - ) - - @classmethod - def from_issuer_subject_key_identifier( - cls, ski: SubjectKeyIdentifier - ) -> AuthorityKeyIdentifier: - return cls( - key_identifier=ski.digest, - authority_cert_issuer=None, - authority_cert_serial_number=None, - ) - - def __repr__(self) -> str: - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, AuthorityKeyIdentifier): - return NotImplemented - - return ( - self.key_identifier == other.key_identifier - and self.authority_cert_issuer == other.authority_cert_issuer - and self.authority_cert_serial_number - == other.authority_cert_serial_number - ) - - def __hash__(self) -> int: - if self.authority_cert_issuer is None: - aci = None - else: - aci = tuple(self.authority_cert_issuer) - return hash( - (self.key_identifier, aci, self.authority_cert_serial_number) - ) - - @property - def key_identifier(self) -> bytes | None: - return self._key_identifier - - @property - def authority_cert_issuer( - self, - ) -> list[GeneralName] | None: - return self._authority_cert_issuer - - @property - def authority_cert_serial_number(self) -> int | None: - return self._authority_cert_serial_number - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class SubjectKeyIdentifier(ExtensionType): - oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER - - def __init__(self, digest: bytes) -> None: - self._digest = digest - - @classmethod - def from_public_key( - cls, public_key: CertificatePublicKeyTypes - ) -> SubjectKeyIdentifier: - return cls(_key_identifier_from_public_key(public_key)) - - @property - def digest(self) -> bytes: - return self._digest - - @property - def key_identifier(self) -> bytes: - return self._digest - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, SubjectKeyIdentifier): - return NotImplemented - - return constant_time.bytes_eq(self.digest, other.digest) - - def __hash__(self) -> int: - return hash(self.digest) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class AuthorityInformationAccess(ExtensionType): - oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS - - def __init__(self, descriptions: Iterable[AccessDescription]) -> None: - descriptions = list(descriptions) - if not all(isinstance(x, AccessDescription) for x in descriptions): - raise TypeError( - "Every item in the descriptions list must be an " - "AccessDescription" - ) - - self._descriptions = descriptions - - __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions") - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, AuthorityInformationAccess): - return NotImplemented - - return self._descriptions == other._descriptions - - def __hash__(self) -> int: - return hash(tuple(self._descriptions)) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class SubjectInformationAccess(ExtensionType): - oid = ExtensionOID.SUBJECT_INFORMATION_ACCESS - - def __init__(self, descriptions: Iterable[AccessDescription]) -> None: - descriptions = list(descriptions) - if not all(isinstance(x, AccessDescription) for x in descriptions): - raise TypeError( - "Every item in the descriptions list must be an " - "AccessDescription" - ) - - self._descriptions = descriptions - - __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions") - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, SubjectInformationAccess): - return NotImplemented - - return self._descriptions == other._descriptions - - def __hash__(self) -> int: - return hash(tuple(self._descriptions)) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class AccessDescription: - def __init__( - self, access_method: ObjectIdentifier, access_location: GeneralName - ) -> None: - if not isinstance(access_method, ObjectIdentifier): - raise TypeError("access_method must be an ObjectIdentifier") - - if not isinstance(access_location, GeneralName): - raise TypeError("access_location must be a GeneralName") - - self._access_method = access_method - self._access_location = access_location - - def __repr__(self) -> str: - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, AccessDescription): - return NotImplemented - - return ( - self.access_method == other.access_method - and self.access_location == other.access_location - ) - - def __hash__(self) -> int: - return hash((self.access_method, self.access_location)) - - @property - def access_method(self) -> ObjectIdentifier: - return self._access_method - - @property - def access_location(self) -> GeneralName: - return self._access_location - - -class BasicConstraints(ExtensionType): - oid = ExtensionOID.BASIC_CONSTRAINTS - - def __init__(self, ca: bool, path_length: int | None) -> None: - if not isinstance(ca, bool): - raise TypeError("ca must be a boolean value") - - if path_length is not None and not ca: - raise ValueError("path_length must be None when ca is False") - - if path_length is not None and ( - not isinstance(path_length, int) or path_length < 0 - ): - raise TypeError( - "path_length must be a non-negative integer or None" - ) - - self._ca = ca - self._path_length = path_length - - @property - def ca(self) -> bool: - return self._ca - - @property - def path_length(self) -> int | None: - return self._path_length - - def __repr__(self) -> str: - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, BasicConstraints): - return NotImplemented - - return self.ca == other.ca and self.path_length == other.path_length - - def __hash__(self) -> int: - return hash((self.ca, self.path_length)) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class DeltaCRLIndicator(ExtensionType): - oid = ExtensionOID.DELTA_CRL_INDICATOR - - def __init__(self, crl_number: int) -> None: - if not isinstance(crl_number, int): - raise TypeError("crl_number must be an integer") - - self._crl_number = crl_number - - @property - def crl_number(self) -> int: - return self._crl_number - - def __eq__(self, other: object) -> bool: - if not isinstance(other, DeltaCRLIndicator): - return NotImplemented - - return self.crl_number == other.crl_number - - def __hash__(self) -> int: - return hash(self.crl_number) - - def __repr__(self) -> str: - return f"" - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class CRLDistributionPoints(ExtensionType): - oid = ExtensionOID.CRL_DISTRIBUTION_POINTS - - def __init__( - self, distribution_points: Iterable[DistributionPoint] - ) -> None: - distribution_points = list(distribution_points) - if not all( - isinstance(x, DistributionPoint) for x in distribution_points - ): - raise TypeError( - "distribution_points must be a list of DistributionPoint " - "objects" - ) - - self._distribution_points = distribution_points - - __len__, __iter__, __getitem__ = _make_sequence_methods( - "_distribution_points" - ) - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, CRLDistributionPoints): - return NotImplemented - - return self._distribution_points == other._distribution_points - - def __hash__(self) -> int: - return hash(tuple(self._distribution_points)) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class FreshestCRL(ExtensionType): - oid = ExtensionOID.FRESHEST_CRL - - def __init__( - self, distribution_points: Iterable[DistributionPoint] - ) -> None: - distribution_points = list(distribution_points) - if not all( - isinstance(x, DistributionPoint) for x in distribution_points - ): - raise TypeError( - "distribution_points must be a list of DistributionPoint " - "objects" - ) - - self._distribution_points = distribution_points - - __len__, __iter__, __getitem__ = _make_sequence_methods( - "_distribution_points" - ) - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, FreshestCRL): - return NotImplemented - - return self._distribution_points == other._distribution_points - - def __hash__(self) -> int: - return hash(tuple(self._distribution_points)) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class DistributionPoint: - def __init__( - self, - full_name: Iterable[GeneralName] | None, - relative_name: RelativeDistinguishedName | None, - reasons: frozenset[ReasonFlags] | None, - crl_issuer: Iterable[GeneralName] | None, - ) -> None: - if full_name and relative_name: - raise ValueError( - "You cannot provide both full_name and relative_name, at " - "least one must be None." - ) - if not full_name and not relative_name and not crl_issuer: - raise ValueError( - "Either full_name, relative_name or crl_issuer must be " - "provided." - ) - - if full_name is not None: - full_name = list(full_name) - if not all(isinstance(x, GeneralName) for x in full_name): - raise TypeError( - "full_name must be a list of GeneralName objects" - ) - - if relative_name: - if not isinstance(relative_name, RelativeDistinguishedName): - raise TypeError( - "relative_name must be a RelativeDistinguishedName" - ) - - if crl_issuer is not None: - crl_issuer = list(crl_issuer) - if not all(isinstance(x, GeneralName) for x in crl_issuer): - raise TypeError( - "crl_issuer must be None or a list of general names" - ) - - if reasons and ( - not isinstance(reasons, frozenset) - or not all(isinstance(x, ReasonFlags) for x in reasons) - ): - raise TypeError("reasons must be None or frozenset of ReasonFlags") - - if reasons and ( - ReasonFlags.unspecified in reasons - or ReasonFlags.remove_from_crl in reasons - ): - raise ValueError( - "unspecified and remove_from_crl are not valid reasons in a " - "DistributionPoint" - ) - - self._full_name = full_name - self._relative_name = relative_name - self._reasons = reasons - self._crl_issuer = crl_issuer - - def __repr__(self) -> str: - return ( - "".format(self) - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, DistributionPoint): - return NotImplemented - - return ( - self.full_name == other.full_name - and self.relative_name == other.relative_name - and self.reasons == other.reasons - and self.crl_issuer == other.crl_issuer - ) - - def __hash__(self) -> int: - if self.full_name is not None: - fn: tuple[GeneralName, ...] | None = tuple(self.full_name) - else: - fn = None - - if self.crl_issuer is not None: - crl_issuer: tuple[GeneralName, ...] | None = tuple(self.crl_issuer) - else: - crl_issuer = None - - return hash((fn, self.relative_name, self.reasons, crl_issuer)) - - @property - def full_name(self) -> list[GeneralName] | None: - return self._full_name - - @property - def relative_name(self) -> RelativeDistinguishedName | None: - return self._relative_name - - @property - def reasons(self) -> frozenset[ReasonFlags] | None: - return self._reasons - - @property - def crl_issuer(self) -> list[GeneralName] | None: - return self._crl_issuer - - -class ReasonFlags(utils.Enum): - unspecified = "unspecified" - key_compromise = "keyCompromise" - ca_compromise = "cACompromise" - affiliation_changed = "affiliationChanged" - superseded = "superseded" - cessation_of_operation = "cessationOfOperation" - certificate_hold = "certificateHold" - privilege_withdrawn = "privilegeWithdrawn" - aa_compromise = "aACompromise" - remove_from_crl = "removeFromCRL" - - -# These are distribution point bit string mappings. Not to be confused with -# CRLReason reason flags bit string mappings. -# ReasonFlags ::= BIT STRING { -# unused (0), -# keyCompromise (1), -# cACompromise (2), -# affiliationChanged (3), -# superseded (4), -# cessationOfOperation (5), -# certificateHold (6), -# privilegeWithdrawn (7), -# aACompromise (8) } -_REASON_BIT_MAPPING = { - 1: ReasonFlags.key_compromise, - 2: ReasonFlags.ca_compromise, - 3: ReasonFlags.affiliation_changed, - 4: ReasonFlags.superseded, - 5: ReasonFlags.cessation_of_operation, - 6: ReasonFlags.certificate_hold, - 7: ReasonFlags.privilege_withdrawn, - 8: ReasonFlags.aa_compromise, -} - -_CRLREASONFLAGS = { - ReasonFlags.key_compromise: 1, - ReasonFlags.ca_compromise: 2, - ReasonFlags.affiliation_changed: 3, - ReasonFlags.superseded: 4, - ReasonFlags.cessation_of_operation: 5, - ReasonFlags.certificate_hold: 6, - ReasonFlags.privilege_withdrawn: 7, - ReasonFlags.aa_compromise: 8, -} - -# CRLReason ::= ENUMERATED { -# unspecified (0), -# keyCompromise (1), -# cACompromise (2), -# affiliationChanged (3), -# superseded (4), -# cessationOfOperation (5), -# certificateHold (6), -# -- value 7 is not used -# removeFromCRL (8), -# privilegeWithdrawn (9), -# aACompromise (10) } -_CRL_ENTRY_REASON_ENUM_TO_CODE = { - ReasonFlags.unspecified: 0, - ReasonFlags.key_compromise: 1, - ReasonFlags.ca_compromise: 2, - ReasonFlags.affiliation_changed: 3, - ReasonFlags.superseded: 4, - ReasonFlags.cessation_of_operation: 5, - ReasonFlags.certificate_hold: 6, - ReasonFlags.remove_from_crl: 8, - ReasonFlags.privilege_withdrawn: 9, - ReasonFlags.aa_compromise: 10, -} - - -class PolicyConstraints(ExtensionType): - oid = ExtensionOID.POLICY_CONSTRAINTS - - def __init__( - self, - require_explicit_policy: int | None, - inhibit_policy_mapping: int | None, - ) -> None: - if require_explicit_policy is not None and not isinstance( - require_explicit_policy, int - ): - raise TypeError( - "require_explicit_policy must be a non-negative integer or " - "None" - ) - - if inhibit_policy_mapping is not None and not isinstance( - inhibit_policy_mapping, int - ): - raise TypeError( - "inhibit_policy_mapping must be a non-negative integer or None" - ) - - if inhibit_policy_mapping is None and require_explicit_policy is None: - raise ValueError( - "At least one of require_explicit_policy and " - "inhibit_policy_mapping must not be None" - ) - - self._require_explicit_policy = require_explicit_policy - self._inhibit_policy_mapping = inhibit_policy_mapping - - def __repr__(self) -> str: - return ( - "".format(self) - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, PolicyConstraints): - return NotImplemented - - return ( - self.require_explicit_policy == other.require_explicit_policy - and self.inhibit_policy_mapping == other.inhibit_policy_mapping - ) - - def __hash__(self) -> int: - return hash( - (self.require_explicit_policy, self.inhibit_policy_mapping) - ) - - @property - def require_explicit_policy(self) -> int | None: - return self._require_explicit_policy - - @property - def inhibit_policy_mapping(self) -> int | None: - return self._inhibit_policy_mapping - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class CertificatePolicies(ExtensionType): - oid = ExtensionOID.CERTIFICATE_POLICIES - - def __init__(self, policies: Iterable[PolicyInformation]) -> None: - policies = list(policies) - if not all(isinstance(x, PolicyInformation) for x in policies): - raise TypeError( - "Every item in the policies list must be a PolicyInformation" - ) - - self._policies = policies - - __len__, __iter__, __getitem__ = _make_sequence_methods("_policies") - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, CertificatePolicies): - return NotImplemented - - return self._policies == other._policies - - def __hash__(self) -> int: - return hash(tuple(self._policies)) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class PolicyInformation: - def __init__( - self, - policy_identifier: ObjectIdentifier, - policy_qualifiers: Iterable[str | UserNotice] | None, - ) -> None: - if not isinstance(policy_identifier, ObjectIdentifier): - raise TypeError("policy_identifier must be an ObjectIdentifier") - - self._policy_identifier = policy_identifier - - if policy_qualifiers is not None: - policy_qualifiers = list(policy_qualifiers) - if not all( - isinstance(x, (str, UserNotice)) for x in policy_qualifiers - ): - raise TypeError( - "policy_qualifiers must be a list of strings and/or " - "UserNotice objects or None" - ) - - self._policy_qualifiers = policy_qualifiers - - def __repr__(self) -> str: - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, PolicyInformation): - return NotImplemented - - return ( - self.policy_identifier == other.policy_identifier - and self.policy_qualifiers == other.policy_qualifiers - ) - - def __hash__(self) -> int: - if self.policy_qualifiers is not None: - pq = tuple(self.policy_qualifiers) - else: - pq = None - - return hash((self.policy_identifier, pq)) - - @property - def policy_identifier(self) -> ObjectIdentifier: - return self._policy_identifier - - @property - def policy_qualifiers( - self, - ) -> list[str | UserNotice] | None: - return self._policy_qualifiers - - -class UserNotice: - def __init__( - self, - notice_reference: NoticeReference | None, - explicit_text: str | None, - ) -> None: - if notice_reference and not isinstance( - notice_reference, NoticeReference - ): - raise TypeError( - "notice_reference must be None or a NoticeReference" - ) - - self._notice_reference = notice_reference - self._explicit_text = explicit_text - - def __repr__(self) -> str: - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, UserNotice): - return NotImplemented - - return ( - self.notice_reference == other.notice_reference - and self.explicit_text == other.explicit_text - ) - - def __hash__(self) -> int: - return hash((self.notice_reference, self.explicit_text)) - - @property - def notice_reference(self) -> NoticeReference | None: - return self._notice_reference - - @property - def explicit_text(self) -> str | None: - return self._explicit_text - - -class NoticeReference: - def __init__( - self, - organization: str | None, - notice_numbers: Iterable[int], - ) -> None: - self._organization = organization - notice_numbers = list(notice_numbers) - if not all(isinstance(x, int) for x in notice_numbers): - raise TypeError("notice_numbers must be a list of integers") - - self._notice_numbers = notice_numbers - - def __repr__(self) -> str: - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, NoticeReference): - return NotImplemented - - return ( - self.organization == other.organization - and self.notice_numbers == other.notice_numbers - ) - - def __hash__(self) -> int: - return hash((self.organization, tuple(self.notice_numbers))) - - @property - def organization(self) -> str | None: - return self._organization - - @property - def notice_numbers(self) -> list[int]: - return self._notice_numbers - - -class ExtendedKeyUsage(ExtensionType): - oid = ExtensionOID.EXTENDED_KEY_USAGE - - def __init__(self, usages: Iterable[ObjectIdentifier]) -> None: - usages = list(usages) - if not all(isinstance(x, ObjectIdentifier) for x in usages): - raise TypeError( - "Every item in the usages list must be an ObjectIdentifier" - ) - - self._usages = usages - - __len__, __iter__, __getitem__ = _make_sequence_methods("_usages") - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, ExtendedKeyUsage): - return NotImplemented - - return self._usages == other._usages - - def __hash__(self) -> int: - return hash(tuple(self._usages)) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class OCSPNoCheck(ExtensionType): - oid = ExtensionOID.OCSP_NO_CHECK - - def __eq__(self, other: object) -> bool: - if not isinstance(other, OCSPNoCheck): - return NotImplemented - - return True - - def __hash__(self) -> int: - return hash(OCSPNoCheck) - - def __repr__(self) -> str: - return "" - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class PrecertPoison(ExtensionType): - oid = ExtensionOID.PRECERT_POISON - - def __eq__(self, other: object) -> bool: - if not isinstance(other, PrecertPoison): - return NotImplemented - - return True - - def __hash__(self) -> int: - return hash(PrecertPoison) - - def __repr__(self) -> str: - return "" - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class TLSFeature(ExtensionType): - oid = ExtensionOID.TLS_FEATURE - - def __init__(self, features: Iterable[TLSFeatureType]) -> None: - features = list(features) - if ( - not all(isinstance(x, TLSFeatureType) for x in features) - or len(features) == 0 - ): - raise TypeError( - "features must be a list of elements from the TLSFeatureType " - "enum" - ) - - self._features = features - - __len__, __iter__, __getitem__ = _make_sequence_methods("_features") - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, TLSFeature): - return NotImplemented - - return self._features == other._features - - def __hash__(self) -> int: - return hash(tuple(self._features)) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class TLSFeatureType(utils.Enum): - # status_request is defined in RFC 6066 and is used for what is commonly - # called OCSP Must-Staple when present in the TLS Feature extension in an - # X.509 certificate. - status_request = 5 - # status_request_v2 is defined in RFC 6961 and allows multiple OCSP - # responses to be provided. It is not currently in use by clients or - # servers. - status_request_v2 = 17 - - -_TLS_FEATURE_TYPE_TO_ENUM = {x.value: x for x in TLSFeatureType} - - -class InhibitAnyPolicy(ExtensionType): - oid = ExtensionOID.INHIBIT_ANY_POLICY - - def __init__(self, skip_certs: int) -> None: - if not isinstance(skip_certs, int): - raise TypeError("skip_certs must be an integer") - - if skip_certs < 0: - raise ValueError("skip_certs must be a non-negative integer") - - self._skip_certs = skip_certs - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, InhibitAnyPolicy): - return NotImplemented - - return self.skip_certs == other.skip_certs - - def __hash__(self) -> int: - return hash(self.skip_certs) - - @property - def skip_certs(self) -> int: - return self._skip_certs - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class KeyUsage(ExtensionType): - oid = ExtensionOID.KEY_USAGE - - def __init__( - self, - digital_signature: bool, - content_commitment: bool, - key_encipherment: bool, - data_encipherment: bool, - key_agreement: bool, - key_cert_sign: bool, - crl_sign: bool, - encipher_only: bool, - decipher_only: bool, - ) -> None: - if not key_agreement and (encipher_only or decipher_only): - raise ValueError( - "encipher_only and decipher_only can only be true when " - "key_agreement is true" - ) - - self._digital_signature = digital_signature - self._content_commitment = content_commitment - self._key_encipherment = key_encipherment - self._data_encipherment = data_encipherment - self._key_agreement = key_agreement - self._key_cert_sign = key_cert_sign - self._crl_sign = crl_sign - self._encipher_only = encipher_only - self._decipher_only = decipher_only - - @property - def digital_signature(self) -> bool: - return self._digital_signature - - @property - def content_commitment(self) -> bool: - return self._content_commitment - - @property - def key_encipherment(self) -> bool: - return self._key_encipherment - - @property - def data_encipherment(self) -> bool: - return self._data_encipherment - - @property - def key_agreement(self) -> bool: - return self._key_agreement - - @property - def key_cert_sign(self) -> bool: - return self._key_cert_sign - - @property - def crl_sign(self) -> bool: - return self._crl_sign - - @property - def encipher_only(self) -> bool: - if not self.key_agreement: - raise ValueError( - "encipher_only is undefined unless key_agreement is true" - ) - else: - return self._encipher_only - - @property - def decipher_only(self) -> bool: - if not self.key_agreement: - raise ValueError( - "decipher_only is undefined unless key_agreement is true" - ) - else: - return self._decipher_only - - def __repr__(self) -> str: - try: - encipher_only = self.encipher_only - decipher_only = self.decipher_only - except ValueError: - # Users found None confusing because even though encipher/decipher - # have no meaning unless key_agreement is true, to construct an - # instance of the class you still need to pass False. - encipher_only = False - decipher_only = False - - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, KeyUsage): - return NotImplemented - - return ( - self.digital_signature == other.digital_signature - and self.content_commitment == other.content_commitment - and self.key_encipherment == other.key_encipherment - and self.data_encipherment == other.data_encipherment - and self.key_agreement == other.key_agreement - and self.key_cert_sign == other.key_cert_sign - and self.crl_sign == other.crl_sign - and self._encipher_only == other._encipher_only - and self._decipher_only == other._decipher_only - ) - - def __hash__(self) -> int: - return hash( - ( - self.digital_signature, - self.content_commitment, - self.key_encipherment, - self.data_encipherment, - self.key_agreement, - self.key_cert_sign, - self.crl_sign, - self._encipher_only, - self._decipher_only, - ) - ) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class PrivateKeyUsagePeriod(ExtensionType): - oid = ExtensionOID.PRIVATE_KEY_USAGE_PERIOD - - def __init__( - self, - not_before: datetime.datetime | None, - not_after: datetime.datetime | None, - ) -> None: - if ( - not isinstance(not_before, datetime.datetime) - and not_before is not None - ): - raise TypeError("not_before must be a datetime.datetime or None") - - if ( - not isinstance(not_after, datetime.datetime) - and not_after is not None - ): - raise TypeError("not_after must be a datetime.datetime or None") - - if not_before is None and not_after is None: - raise ValueError( - "At least one of not_before and not_after must not be None" - ) - - if ( - not_before is not None - and not_after is not None - and not_before > not_after - ): - raise ValueError("not_before must be before not_after") - - self._not_before = not_before - self._not_after = not_after - - @property - def not_before(self) -> datetime.datetime | None: - return self._not_before - - @property - def not_after(self) -> datetime.datetime | None: - return self._not_after - - def __repr__(self) -> str: - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, PrivateKeyUsagePeriod): - return NotImplemented - - return ( - self.not_before == other.not_before - and self.not_after == other.not_after - ) - - def __hash__(self) -> int: - return hash((self.not_before, self.not_after)) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class NameConstraints(ExtensionType): - oid = ExtensionOID.NAME_CONSTRAINTS - - def __init__( - self, - permitted_subtrees: Iterable[GeneralName] | None, - excluded_subtrees: Iterable[GeneralName] | None, - ) -> None: - if permitted_subtrees is not None: - permitted_subtrees = list(permitted_subtrees) - if not permitted_subtrees: - raise ValueError( - "permitted_subtrees must be a non-empty list or None" - ) - if not all(isinstance(x, GeneralName) for x in permitted_subtrees): - raise TypeError( - "permitted_subtrees must be a list of GeneralName objects " - "or None" - ) - - self._validate_tree(permitted_subtrees) - - if excluded_subtrees is not None: - excluded_subtrees = list(excluded_subtrees) - if not excluded_subtrees: - raise ValueError( - "excluded_subtrees must be a non-empty list or None" - ) - if not all(isinstance(x, GeneralName) for x in excluded_subtrees): - raise TypeError( - "excluded_subtrees must be a list of GeneralName objects " - "or None" - ) - - self._validate_tree(excluded_subtrees) - - if permitted_subtrees is None and excluded_subtrees is None: - raise ValueError( - "At least one of permitted_subtrees and excluded_subtrees " - "must not be None" - ) - - self._permitted_subtrees = permitted_subtrees - self._excluded_subtrees = excluded_subtrees - - def __eq__(self, other: object) -> bool: - if not isinstance(other, NameConstraints): - return NotImplemented - - return ( - self.excluded_subtrees == other.excluded_subtrees - and self.permitted_subtrees == other.permitted_subtrees - ) - - def _validate_tree(self, tree: Iterable[GeneralName]) -> None: - self._validate_ip_name(tree) - self._validate_dns_name(tree) - - def _validate_ip_name(self, tree: Iterable[GeneralName]) -> None: - if any( - isinstance(name, IPAddress) - and not isinstance( - name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network) - ) - for name in tree - ): - raise TypeError( - "IPAddress name constraints must be an IPv4Network or" - " IPv6Network object" - ) - - def _validate_dns_name(self, tree: Iterable[GeneralName]) -> None: - if any( - isinstance(name, DNSName) and "*" in name.value for name in tree - ): - raise ValueError( - "DNSName name constraints must not contain the '*' wildcard" - " character" - ) - - def __repr__(self) -> str: - return ( - f"" - ) - - def __hash__(self) -> int: - if self.permitted_subtrees is not None: - ps: tuple[GeneralName, ...] | None = tuple(self.permitted_subtrees) - else: - ps = None - - if self.excluded_subtrees is not None: - es: tuple[GeneralName, ...] | None = tuple(self.excluded_subtrees) - else: - es = None - - return hash((ps, es)) - - @property - def permitted_subtrees( - self, - ) -> list[GeneralName] | None: - return self._permitted_subtrees - - @property - def excluded_subtrees( - self, - ) -> list[GeneralName] | None: - return self._excluded_subtrees - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class Extension(typing.Generic[ExtensionTypeVar]): - def __init__( - self, oid: ObjectIdentifier, critical: bool, value: ExtensionTypeVar - ) -> None: - if not isinstance(oid, ObjectIdentifier): - raise TypeError( - "oid argument must be an ObjectIdentifier instance." - ) - - if not isinstance(critical, bool): - raise TypeError("critical must be a boolean value") - - self._oid = oid - self._critical = critical - self._value = value - - @property - def oid(self) -> ObjectIdentifier: - return self._oid - - @property - def critical(self) -> bool: - return self._critical - - @property - def value(self) -> ExtensionTypeVar: - return self._value - - def __repr__(self) -> str: - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, Extension): - return NotImplemented - - return ( - self.oid == other.oid - and self.critical == other.critical - and self.value == other.value - ) - - def __hash__(self) -> int: - return hash((self.oid, self.critical, self.value)) - - -class GeneralNames: - def __init__(self, general_names: Iterable[GeneralName]) -> None: - general_names = list(general_names) - if not all(isinstance(x, GeneralName) for x in general_names): - raise TypeError( - "Every item in the general_names list must be an " - "object conforming to the GeneralName interface" - ) - - self._general_names = general_names - - __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") - - @typing.overload - def get_values_for_type( - self, - type: type[DNSName] - | type[UniformResourceIdentifier] - | type[RFC822Name], - ) -> list[str]: ... - - @typing.overload - def get_values_for_type( - self, - type: type[DirectoryName], - ) -> list[Name]: ... - - @typing.overload - def get_values_for_type( - self, - type: type[RegisteredID], - ) -> list[ObjectIdentifier]: ... - - @typing.overload - def get_values_for_type( - self, type: type[IPAddress] - ) -> list[_IPAddressTypes]: ... - - @typing.overload - def get_values_for_type( - self, type: type[OtherName] - ) -> list[OtherName]: ... - - def get_values_for_type( - self, - type: type[DNSName] - | type[DirectoryName] - | type[IPAddress] - | type[OtherName] - | type[RFC822Name] - | type[RegisteredID] - | type[UniformResourceIdentifier], - ) -> ( - list[_IPAddressTypes] - | list[str] - | list[OtherName] - | list[Name] - | list[ObjectIdentifier] - ): - # Return the value of each GeneralName, except for OtherName instances - # which we return directly because it has two important properties not - # just one value. - objs = (i for i in self if isinstance(i, type)) - if type != OtherName: - return [i.value for i in objs] # type: ignore[return-value,unused-ignore] - return list(objs) # type: ignore[return-value,unused-ignore] - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, GeneralNames): - return NotImplemented - - return self._general_names == other._general_names - - def __hash__(self) -> int: - return hash(tuple(self._general_names)) - - -class SubjectAlternativeName(ExtensionType): - oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME - - def __init__(self, general_names: Iterable[GeneralName]) -> None: - self._general_names = GeneralNames(general_names) - - __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") - - @typing.overload - def get_values_for_type( - self, - type: type[DNSName] - | type[UniformResourceIdentifier] - | type[RFC822Name], - ) -> list[str]: ... - - @typing.overload - def get_values_for_type( - self, - type: type[DirectoryName], - ) -> list[Name]: ... - - @typing.overload - def get_values_for_type( - self, - type: type[RegisteredID], - ) -> list[ObjectIdentifier]: ... - - @typing.overload - def get_values_for_type( - self, type: type[IPAddress] - ) -> list[_IPAddressTypes]: ... - - @typing.overload - def get_values_for_type( - self, type: type[OtherName] - ) -> list[OtherName]: ... - - def get_values_for_type( - self, - type: type[DNSName] - | type[DirectoryName] - | type[IPAddress] - | type[OtherName] - | type[RFC822Name] - | type[RegisteredID] - | type[UniformResourceIdentifier], - ) -> ( - list[_IPAddressTypes] - | list[str] - | list[OtherName] - | list[Name] - | list[ObjectIdentifier] - ): - return self._general_names.get_values_for_type(type) - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, SubjectAlternativeName): - return NotImplemented - - return self._general_names == other._general_names - - def __hash__(self) -> int: - return hash(self._general_names) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class IssuerAlternativeName(ExtensionType): - oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME - - def __init__(self, general_names: Iterable[GeneralName]) -> None: - self._general_names = GeneralNames(general_names) - - __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") - - @typing.overload - def get_values_for_type( - self, - type: type[DNSName] - | type[UniformResourceIdentifier] - | type[RFC822Name], - ) -> list[str]: ... - - @typing.overload - def get_values_for_type( - self, - type: type[DirectoryName], - ) -> list[Name]: ... - - @typing.overload - def get_values_for_type( - self, - type: type[RegisteredID], - ) -> list[ObjectIdentifier]: ... - - @typing.overload - def get_values_for_type( - self, type: type[IPAddress] - ) -> list[_IPAddressTypes]: ... - - @typing.overload - def get_values_for_type( - self, type: type[OtherName] - ) -> list[OtherName]: ... - - def get_values_for_type( - self, - type: type[DNSName] - | type[DirectoryName] - | type[IPAddress] - | type[OtherName] - | type[RFC822Name] - | type[RegisteredID] - | type[UniformResourceIdentifier], - ) -> ( - list[_IPAddressTypes] - | list[str] - | list[OtherName] - | list[Name] - | list[ObjectIdentifier] - ): - return self._general_names.get_values_for_type(type) - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, IssuerAlternativeName): - return NotImplemented - - return self._general_names == other._general_names - - def __hash__(self) -> int: - return hash(self._general_names) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class CertificateIssuer(ExtensionType): - oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER - - def __init__(self, general_names: Iterable[GeneralName]) -> None: - self._general_names = GeneralNames(general_names) - - __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names") - - @typing.overload - def get_values_for_type( - self, - type: type[DNSName] - | type[UniformResourceIdentifier] - | type[RFC822Name], - ) -> list[str]: ... - - @typing.overload - def get_values_for_type( - self, - type: type[DirectoryName], - ) -> list[Name]: ... - - @typing.overload - def get_values_for_type( - self, - type: type[RegisteredID], - ) -> list[ObjectIdentifier]: ... - - @typing.overload - def get_values_for_type( - self, type: type[IPAddress] - ) -> list[_IPAddressTypes]: ... - - @typing.overload - def get_values_for_type( - self, type: type[OtherName] - ) -> list[OtherName]: ... - - def get_values_for_type( - self, - type: type[DNSName] - | type[DirectoryName] - | type[IPAddress] - | type[OtherName] - | type[RFC822Name] - | type[RegisteredID] - | type[UniformResourceIdentifier], - ) -> ( - list[_IPAddressTypes] - | list[str] - | list[OtherName] - | list[Name] - | list[ObjectIdentifier] - ): - return self._general_names.get_values_for_type(type) - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, CertificateIssuer): - return NotImplemented - - return self._general_names == other._general_names - - def __hash__(self) -> int: - return hash(self._general_names) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class CRLReason(ExtensionType): - oid = CRLEntryExtensionOID.CRL_REASON - - def __init__(self, reason: ReasonFlags) -> None: - if not isinstance(reason, ReasonFlags): - raise TypeError("reason must be an element from ReasonFlags") - - self._reason = reason - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, CRLReason): - return NotImplemented - - return self.reason == other.reason - - def __hash__(self) -> int: - return hash(self.reason) - - @property - def reason(self) -> ReasonFlags: - return self._reason - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class InvalidityDate(ExtensionType): - oid = CRLEntryExtensionOID.INVALIDITY_DATE - - def __init__(self, invalidity_date: datetime.datetime) -> None: - if not isinstance(invalidity_date, datetime.datetime): - raise TypeError("invalidity_date must be a datetime.datetime") - - self._invalidity_date = invalidity_date - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, InvalidityDate): - return NotImplemented - - return self.invalidity_date == other.invalidity_date - - def __hash__(self) -> int: - return hash(self.invalidity_date) - - @property - def invalidity_date(self) -> datetime.datetime: - return self._invalidity_date - - @property - def invalidity_date_utc(self) -> datetime.datetime: - if self._invalidity_date.tzinfo is None: - return self._invalidity_date.replace(tzinfo=datetime.timezone.utc) - else: - return self._invalidity_date.astimezone(tz=datetime.timezone.utc) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class PrecertificateSignedCertificateTimestamps(ExtensionType): - oid = ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS - - def __init__( - self, - signed_certificate_timestamps: Iterable[SignedCertificateTimestamp], - ) -> None: - signed_certificate_timestamps = list(signed_certificate_timestamps) - if not all( - isinstance(sct, SignedCertificateTimestamp) - for sct in signed_certificate_timestamps - ): - raise TypeError( - "Every item in the signed_certificate_timestamps list must be " - "a SignedCertificateTimestamp" - ) - self._signed_certificate_timestamps = signed_certificate_timestamps - - __len__, __iter__, __getitem__ = _make_sequence_methods( - "_signed_certificate_timestamps" - ) - - def __repr__(self) -> str: - return f"" - - def __hash__(self) -> int: - return hash(tuple(self._signed_certificate_timestamps)) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, PrecertificateSignedCertificateTimestamps): - return NotImplemented - - return ( - self._signed_certificate_timestamps - == other._signed_certificate_timestamps - ) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class SignedCertificateTimestamps(ExtensionType): - oid = ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS - - def __init__( - self, - signed_certificate_timestamps: Iterable[SignedCertificateTimestamp], - ) -> None: - signed_certificate_timestamps = list(signed_certificate_timestamps) - if not all( - isinstance(sct, SignedCertificateTimestamp) - for sct in signed_certificate_timestamps - ): - raise TypeError( - "Every item in the signed_certificate_timestamps list must be " - "a SignedCertificateTimestamp" - ) - self._signed_certificate_timestamps = signed_certificate_timestamps - - __len__, __iter__, __getitem__ = _make_sequence_methods( - "_signed_certificate_timestamps" - ) - - def __repr__(self) -> str: - return f"" - - def __hash__(self) -> int: - return hash(tuple(self._signed_certificate_timestamps)) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, SignedCertificateTimestamps): - return NotImplemented - - return ( - self._signed_certificate_timestamps - == other._signed_certificate_timestamps - ) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class OCSPNonce(ExtensionType): - oid = OCSPExtensionOID.NONCE - - def __init__(self, nonce: bytes) -> None: - if not isinstance(nonce, bytes): - raise TypeError("nonce must be bytes") - - self._nonce = nonce - - def __eq__(self, other: object) -> bool: - if not isinstance(other, OCSPNonce): - return NotImplemented - - return self.nonce == other.nonce - - def __hash__(self) -> int: - return hash(self.nonce) - - def __repr__(self) -> str: - return f"" - - @property - def nonce(self) -> bytes: - return self._nonce - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class OCSPAcceptableResponses(ExtensionType): - oid = OCSPExtensionOID.ACCEPTABLE_RESPONSES - - def __init__(self, responses: Iterable[ObjectIdentifier]) -> None: - responses = list(responses) - if any(not isinstance(r, ObjectIdentifier) for r in responses): - raise TypeError("All responses must be ObjectIdentifiers") - - self._responses = responses - - def __eq__(self, other: object) -> bool: - if not isinstance(other, OCSPAcceptableResponses): - return NotImplemented - - return self._responses == other._responses - - def __hash__(self) -> int: - return hash(tuple(self._responses)) - - def __repr__(self) -> str: - return f"" - - def __iter__(self) -> Iterator[ObjectIdentifier]: - return iter(self._responses) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class IssuingDistributionPoint(ExtensionType): - oid = ExtensionOID.ISSUING_DISTRIBUTION_POINT - - def __init__( - self, - full_name: Iterable[GeneralName] | None, - relative_name: RelativeDistinguishedName | None, - only_contains_user_certs: bool, - only_contains_ca_certs: bool, - only_some_reasons: frozenset[ReasonFlags] | None, - indirect_crl: bool, - only_contains_attribute_certs: bool, - ) -> None: - if full_name is not None: - full_name = list(full_name) - - if only_some_reasons and ( - not isinstance(only_some_reasons, frozenset) - or not all(isinstance(x, ReasonFlags) for x in only_some_reasons) - ): - raise TypeError( - "only_some_reasons must be None or frozenset of ReasonFlags" - ) - - if only_some_reasons and ( - ReasonFlags.unspecified in only_some_reasons - or ReasonFlags.remove_from_crl in only_some_reasons - ): - raise ValueError( - "unspecified and remove_from_crl are not valid reasons in an " - "IssuingDistributionPoint" - ) - - if not ( - isinstance(only_contains_user_certs, bool) - and isinstance(only_contains_ca_certs, bool) - and isinstance(indirect_crl, bool) - and isinstance(only_contains_attribute_certs, bool) - ): - raise TypeError( - "only_contains_user_certs, only_contains_ca_certs, " - "indirect_crl and only_contains_attribute_certs " - "must all be boolean." - ) - - # Per RFC5280 Section 5.2.5, the Issuing Distribution Point extension - # in a CRL can have only one of onlyContainsUserCerts, - # onlyContainsCACerts, onlyContainsAttributeCerts set to TRUE. - crl_constraints = [ - only_contains_user_certs, - only_contains_ca_certs, - only_contains_attribute_certs, - ] - - if len([x for x in crl_constraints if x]) > 1: - raise ValueError( - "Only one of the following can be set to True: " - "only_contains_user_certs, only_contains_ca_certs, " - "only_contains_attribute_certs" - ) - - if not any( - [ - only_contains_user_certs, - only_contains_ca_certs, - indirect_crl, - only_contains_attribute_certs, - full_name, - relative_name, - only_some_reasons, - ] - ): - raise ValueError( - "Cannot create empty extension: " - "if only_contains_user_certs, only_contains_ca_certs, " - "indirect_crl, and only_contains_attribute_certs are all False" - ", then either full_name, relative_name, or only_some_reasons " - "must have a value." - ) - - self._only_contains_user_certs = only_contains_user_certs - self._only_contains_ca_certs = only_contains_ca_certs - self._indirect_crl = indirect_crl - self._only_contains_attribute_certs = only_contains_attribute_certs - self._only_some_reasons = only_some_reasons - self._full_name = full_name - self._relative_name = relative_name - - def __repr__(self) -> str: - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, IssuingDistributionPoint): - return NotImplemented - - return ( - self.full_name == other.full_name - and self.relative_name == other.relative_name - and self.only_contains_user_certs == other.only_contains_user_certs - and self.only_contains_ca_certs == other.only_contains_ca_certs - and self.only_some_reasons == other.only_some_reasons - and self.indirect_crl == other.indirect_crl - and self.only_contains_attribute_certs - == other.only_contains_attribute_certs - ) - - def __hash__(self) -> int: - if self.full_name is not None: - full_name: tuple[GeneralName, ...] | None = tuple(self.full_name) - else: - full_name = None - - return hash( - ( - full_name, - self.relative_name, - self.only_contains_user_certs, - self.only_contains_ca_certs, - self.only_some_reasons, - self.indirect_crl, - self.only_contains_attribute_certs, - ) - ) - - @property - def full_name(self) -> list[GeneralName] | None: - return self._full_name - - @property - def relative_name(self) -> RelativeDistinguishedName | None: - return self._relative_name - - @property - def only_contains_user_certs(self) -> bool: - return self._only_contains_user_certs - - @property - def only_contains_ca_certs(self) -> bool: - return self._only_contains_ca_certs - - @property - def only_some_reasons( - self, - ) -> frozenset[ReasonFlags] | None: - return self._only_some_reasons - - @property - def indirect_crl(self) -> bool: - return self._indirect_crl - - @property - def only_contains_attribute_certs(self) -> bool: - return self._only_contains_attribute_certs - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class MSCertificateTemplate(ExtensionType): - oid = ExtensionOID.MS_CERTIFICATE_TEMPLATE - - def __init__( - self, - template_id: ObjectIdentifier, - major_version: int | None, - minor_version: int | None, - ) -> None: - if not isinstance(template_id, ObjectIdentifier): - raise TypeError("oid must be an ObjectIdentifier") - self._template_id = template_id - if ( - major_version is not None and not isinstance(major_version, int) - ) or ( - minor_version is not None and not isinstance(minor_version, int) - ): - raise TypeError( - "major_version and minor_version must be integers or None" - ) - self._major_version = major_version - self._minor_version = minor_version - - @property - def template_id(self) -> ObjectIdentifier: - return self._template_id - - @property - def major_version(self) -> int | None: - return self._major_version - - @property - def minor_version(self) -> int | None: - return self._minor_version - - def __repr__(self) -> str: - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, MSCertificateTemplate): - return NotImplemented - - return ( - self.template_id == other.template_id - and self.major_version == other.major_version - and self.minor_version == other.minor_version - ) - - def __hash__(self) -> int: - return hash((self.template_id, self.major_version, self.minor_version)) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class NamingAuthority: - def __init__( - self, - id: ObjectIdentifier | None, - url: str | None, - text: str | None, - ) -> None: - if id is not None and not isinstance(id, ObjectIdentifier): - raise TypeError("id must be an ObjectIdentifier") - - if url is not None and not isinstance(url, str): - raise TypeError("url must be a str") - - if text is not None and not isinstance(text, str): - raise TypeError("text must be a str") - - self._id = id - self._url = url - self._text = text - - @property - def id(self) -> ObjectIdentifier | None: - return self._id - - @property - def url(self) -> str | None: - return self._url - - @property - def text(self) -> str | None: - return self._text - - def __repr__(self) -> str: - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, NamingAuthority): - return NotImplemented - - return ( - self.id == other.id - and self.url == other.url - and self.text == other.text - ) - - def __hash__(self) -> int: - return hash( - ( - self.id, - self.url, - self.text, - ) - ) - - -class ProfessionInfo: - def __init__( - self, - naming_authority: NamingAuthority | None, - profession_items: Iterable[str], - profession_oids: Iterable[ObjectIdentifier] | None, - registration_number: str | None, - add_profession_info: bytes | None, - ) -> None: - if naming_authority is not None and not isinstance( - naming_authority, NamingAuthority - ): - raise TypeError("naming_authority must be a NamingAuthority") - - profession_items = list(profession_items) - if not all(isinstance(item, str) for item in profession_items): - raise TypeError( - "Every item in the profession_items list must be a str" - ) - - if profession_oids is not None: - profession_oids = list(profession_oids) - if not all( - isinstance(oid, ObjectIdentifier) for oid in profession_oids - ): - raise TypeError( - "Every item in the profession_oids list must be an " - "ObjectIdentifier" - ) - - if registration_number is not None and not isinstance( - registration_number, str - ): - raise TypeError("registration_number must be a str") - - if add_profession_info is not None and not isinstance( - add_profession_info, bytes - ): - raise TypeError("add_profession_info must be bytes") - - self._naming_authority = naming_authority - self._profession_items = profession_items - self._profession_oids = profession_oids - self._registration_number = registration_number - self._add_profession_info = add_profession_info - - @property - def naming_authority(self) -> NamingAuthority | None: - return self._naming_authority - - @property - def profession_items(self) -> list[str]: - return self._profession_items - - @property - def profession_oids(self) -> list[ObjectIdentifier] | None: - return self._profession_oids - - @property - def registration_number(self) -> str | None: - return self._registration_number - - @property - def add_profession_info(self) -> bytes | None: - return self._add_profession_info - - def __repr__(self) -> str: - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, ProfessionInfo): - return NotImplemented - - return ( - self.naming_authority == other.naming_authority - and self.profession_items == other.profession_items - and self.profession_oids == other.profession_oids - and self.registration_number == other.registration_number - and self.add_profession_info == other.add_profession_info - ) - - def __hash__(self) -> int: - if self.profession_oids is not None: - profession_oids = tuple(self.profession_oids) - else: - profession_oids = None - return hash( - ( - self.naming_authority, - tuple(self.profession_items), - profession_oids, - self.registration_number, - self.add_profession_info, - ) - ) - - -class Admission: - def __init__( - self, - admission_authority: GeneralName | None, - naming_authority: NamingAuthority | None, - profession_infos: Iterable[ProfessionInfo], - ) -> None: - if admission_authority is not None and not isinstance( - admission_authority, GeneralName - ): - raise TypeError("admission_authority must be a GeneralName") - - if naming_authority is not None and not isinstance( - naming_authority, NamingAuthority - ): - raise TypeError("naming_authority must be a NamingAuthority") - - profession_infos = list(profession_infos) - if not all( - isinstance(info, ProfessionInfo) for info in profession_infos - ): - raise TypeError( - "Every item in the profession_infos list must be a " - "ProfessionInfo" - ) - - self._admission_authority = admission_authority - self._naming_authority = naming_authority - self._profession_infos = profession_infos - - @property - def admission_authority(self) -> GeneralName | None: - return self._admission_authority - - @property - def naming_authority(self) -> NamingAuthority | None: - return self._naming_authority - - @property - def profession_infos(self) -> list[ProfessionInfo]: - return self._profession_infos - - def __repr__(self) -> str: - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, Admission): - return NotImplemented - - return ( - self.admission_authority == other.admission_authority - and self.naming_authority == other.naming_authority - and self.profession_infos == other.profession_infos - ) - - def __hash__(self) -> int: - return hash( - ( - self.admission_authority, - self.naming_authority, - tuple(self.profession_infos), - ) - ) - - -class Admissions(ExtensionType): - oid = ExtensionOID.ADMISSIONS - - def __init__( - self, - authority: GeneralName | None, - admissions: Iterable[Admission], - ) -> None: - if authority is not None and not isinstance(authority, GeneralName): - raise TypeError("authority must be a GeneralName") - - admissions = list(admissions) - if not all( - isinstance(admission, Admission) for admission in admissions - ): - raise TypeError( - "Every item in the contents_of_admissions list must be an " - "Admission" - ) - - self._authority = authority - self._admissions = admissions - - __len__, __iter__, __getitem__ = _make_sequence_methods("_admissions") - - @property - def authority(self) -> GeneralName | None: - return self._authority - - def __repr__(self) -> str: - return ( - f"" - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, Admissions): - return NotImplemented - - return ( - self.authority == other.authority - and self._admissions == other._admissions - ) - - def __hash__(self) -> int: - return hash((self.authority, tuple(self._admissions))) - - def public_bytes(self) -> bytes: - return rust_x509.encode_extension_value(self) - - -class UnrecognizedExtension(ExtensionType): - def __init__(self, oid: ObjectIdentifier, value: bytes) -> None: - if not isinstance(oid, ObjectIdentifier): - raise TypeError("oid must be an ObjectIdentifier") - self._oid = oid - self._value = value - - @property - def oid(self) -> ObjectIdentifier: # type: ignore[override] - return self._oid - - @property - def value(self) -> bytes: - return self._value - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, UnrecognizedExtension): - return NotImplemented - - return self.oid == other.oid and self.value == other.value - - def __hash__(self) -> int: - return hash((self.oid, self.value)) - - def public_bytes(self) -> bytes: - return self.value diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/general_name.py b/notification-service/venv/Lib/site-packages/cryptography/x509/general_name.py deleted file mode 100644 index 672f287..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/x509/general_name.py +++ /dev/null @@ -1,281 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import abc -import ipaddress -import typing -from email.utils import parseaddr - -from cryptography.x509.name import Name -from cryptography.x509.oid import ObjectIdentifier - -_IPAddressTypes = typing.Union[ - ipaddress.IPv4Address, - ipaddress.IPv6Address, - ipaddress.IPv4Network, - ipaddress.IPv6Network, -] - - -class UnsupportedGeneralNameType(Exception): - pass - - -class GeneralName(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def value(self) -> typing.Any: - """ - Return the value of the object - """ - - -class RFC822Name(GeneralName): - def __init__(self, value: str) -> None: - if isinstance(value, str): - try: - value.encode("ascii") - except UnicodeEncodeError: - raise ValueError( - "RFC822Name values should be passed as an A-label string. " - "This means unicode characters should be encoded via " - "a library like idna." - ) - else: - raise TypeError("value must be string") - - name, address = parseaddr(value) - if name or not address: - # parseaddr has found a name (e.g. Name ) or the entire - # value is an empty string. - raise ValueError("Invalid rfc822name value") - - self._value = value - - @property - def value(self) -> str: - return self._value - - @classmethod - def _init_without_validation(cls, value: str) -> RFC822Name: - instance = cls.__new__(cls) - instance._value = value - return instance - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, RFC822Name): - return NotImplemented - - return self.value == other.value - - def __hash__(self) -> int: - return hash(self.value) - - -class DNSName(GeneralName): - def __init__(self, value: str) -> None: - if isinstance(value, str): - try: - value.encode("ascii") - except UnicodeEncodeError: - raise ValueError( - "DNSName values should be passed as an A-label string. " - "This means unicode characters should be encoded via " - "a library like idna." - ) - else: - raise TypeError("value must be string") - - self._value = value - - @property - def value(self) -> str: - return self._value - - @classmethod - def _init_without_validation(cls, value: str) -> DNSName: - instance = cls.__new__(cls) - instance._value = value - return instance - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, DNSName): - return NotImplemented - - return self.value == other.value - - def __hash__(self) -> int: - return hash(self.value) - - -class UniformResourceIdentifier(GeneralName): - def __init__(self, value: str) -> None: - if isinstance(value, str): - try: - value.encode("ascii") - except UnicodeEncodeError: - raise ValueError( - "URI values should be passed as an A-label string. " - "This means unicode characters should be encoded via " - "a library like idna." - ) - else: - raise TypeError("value must be string") - - self._value = value - - @property - def value(self) -> str: - return self._value - - @classmethod - def _init_without_validation(cls, value: str) -> UniformResourceIdentifier: - instance = cls.__new__(cls) - instance._value = value - return instance - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, UniformResourceIdentifier): - return NotImplemented - - return self.value == other.value - - def __hash__(self) -> int: - return hash(self.value) - - -class DirectoryName(GeneralName): - def __init__(self, value: Name) -> None: - if not isinstance(value, Name): - raise TypeError("value must be a Name") - - self._value = value - - @property - def value(self) -> Name: - return self._value - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, DirectoryName): - return NotImplemented - - return self.value == other.value - - def __hash__(self) -> int: - return hash(self.value) - - -class RegisteredID(GeneralName): - def __init__(self, value: ObjectIdentifier) -> None: - if not isinstance(value, ObjectIdentifier): - raise TypeError("value must be an ObjectIdentifier") - - self._value = value - - @property - def value(self) -> ObjectIdentifier: - return self._value - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, RegisteredID): - return NotImplemented - - return self.value == other.value - - def __hash__(self) -> int: - return hash(self.value) - - -class IPAddress(GeneralName): - def __init__(self, value: _IPAddressTypes) -> None: - if not isinstance( - value, - ( - ipaddress.IPv4Address, - ipaddress.IPv6Address, - ipaddress.IPv4Network, - ipaddress.IPv6Network, - ), - ): - raise TypeError( - "value must be an instance of ipaddress.IPv4Address, " - "ipaddress.IPv6Address, ipaddress.IPv4Network, or " - "ipaddress.IPv6Network" - ) - - self._value = value - - @property - def value(self) -> _IPAddressTypes: - return self._value - - def _packed(self) -> bytes: - if isinstance( - self.value, (ipaddress.IPv4Address, ipaddress.IPv6Address) - ): - return self.value.packed - else: - return ( - self.value.network_address.packed + self.value.netmask.packed - ) - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, IPAddress): - return NotImplemented - - return self.value == other.value - - def __hash__(self) -> int: - return hash(self.value) - - -class OtherName(GeneralName): - def __init__(self, type_id: ObjectIdentifier, value: bytes) -> None: - if not isinstance(type_id, ObjectIdentifier): - raise TypeError("type_id must be an ObjectIdentifier") - if not isinstance(value, bytes): - raise TypeError("value must be a binary string") - - self._type_id = type_id - self._value = value - - @property - def type_id(self) -> ObjectIdentifier: - return self._type_id - - @property - def value(self) -> bytes: - return self._value - - def __repr__(self) -> str: - return f"" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, OtherName): - return NotImplemented - - return self.type_id == other.type_id and self.value == other.value - - def __hash__(self) -> int: - return hash((self.type_id, self.value)) diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/name.py b/notification-service/venv/Lib/site-packages/cryptography/x509/name.py deleted file mode 100644 index 57f3d56..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/x509/name.py +++ /dev/null @@ -1,482 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import binascii -import re -import sys -import typing -import warnings -from collections.abc import Iterable, Iterator - -from cryptography import utils -from cryptography.hazmat.bindings._rust import x509 as rust_x509 -from cryptography.x509.oid import NameOID, ObjectIdentifier - - -class _ASN1Type(utils.Enum): - BitString = 3 - OctetString = 4 - UTF8String = 12 - NumericString = 18 - PrintableString = 19 - T61String = 20 - IA5String = 22 - UTCTime = 23 - GeneralizedTime = 24 - VisibleString = 26 - UniversalString = 28 - BMPString = 30 - - -_ASN1_TYPE_TO_ENUM = {i.value: i for i in _ASN1Type} -_NAMEOID_DEFAULT_TYPE: dict[ObjectIdentifier, _ASN1Type] = { - NameOID.COUNTRY_NAME: _ASN1Type.PrintableString, - NameOID.JURISDICTION_COUNTRY_NAME: _ASN1Type.PrintableString, - NameOID.SERIAL_NUMBER: _ASN1Type.PrintableString, - NameOID.DN_QUALIFIER: _ASN1Type.PrintableString, - NameOID.EMAIL_ADDRESS: _ASN1Type.IA5String, - NameOID.DOMAIN_COMPONENT: _ASN1Type.IA5String, -} - -# Type alias -_OidNameMap = typing.Mapping[ObjectIdentifier, str] -_NameOidMap = typing.Mapping[str, ObjectIdentifier] - -#: Short attribute names from RFC 4514: -#: https://tools.ietf.org/html/rfc4514#page-7 -_NAMEOID_TO_NAME: _OidNameMap = { - NameOID.COMMON_NAME: "CN", - NameOID.LOCALITY_NAME: "L", - NameOID.STATE_OR_PROVINCE_NAME: "ST", - NameOID.ORGANIZATION_NAME: "O", - NameOID.ORGANIZATIONAL_UNIT_NAME: "OU", - NameOID.COUNTRY_NAME: "C", - NameOID.STREET_ADDRESS: "STREET", - NameOID.DOMAIN_COMPONENT: "DC", - NameOID.USER_ID: "UID", -} -_NAME_TO_NAMEOID = {v: k for k, v in _NAMEOID_TO_NAME.items()} - -_NAMEOID_LENGTH_LIMIT = { - NameOID.COUNTRY_NAME: (2, 2), - NameOID.JURISDICTION_COUNTRY_NAME: (2, 2), - NameOID.COMMON_NAME: (1, 64), -} - - -def _escape_dn_value(val: str | bytes) -> str: - """Escape special characters in RFC4514 Distinguished Name value.""" - - if not val: - return "" - - # RFC 4514 Section 2.4 defines the value as being the # (U+0023) character - # followed by the hexadecimal encoding of the octets. - if isinstance(val, bytes): - return "#" + binascii.hexlify(val).decode("utf8") - - # See https://tools.ietf.org/html/rfc4514#section-2.4 - val = val.replace("\\", "\\\\") - val = val.replace('"', '\\"') - val = val.replace("+", "\\+") - val = val.replace(",", "\\,") - val = val.replace(";", "\\;") - val = val.replace("<", "\\<") - val = val.replace(">", "\\>") - val = val.replace("\0", "\\00") - - if val[0] == "#" or (val[0] == " " and len(val) > 1): - val = "\\" + val - if val[-1] == " ": - val = val[:-1] + "\\ " - - return val - - -def _unescape_dn_value(val: str) -> str: - if not val: - return "" - - # See https://tools.ietf.org/html/rfc4514#section-3 - - # special = escaped / SPACE / SHARP / EQUALS - # escaped = DQUOTE / PLUS / COMMA / SEMI / LANGLE / RANGLE - def sub(m): - val = m.group(0) - # Special character escape - if len(val) == 2: - return val[1:] - - # Unicode string of hex - return binascii.unhexlify(val.replace("\\", "")).decode() - - return _RFC4514NameParser._PAIR_MULTI_RE.sub(sub, val) - - -NameAttributeValueType = typing.TypeVar( - "NameAttributeValueType", - typing.Union[str, bytes], - str, - bytes, - covariant=True, -) - - -class NameAttribute(typing.Generic[NameAttributeValueType]): - def __init__( - self, - oid: ObjectIdentifier, - value: NameAttributeValueType, - _type: _ASN1Type | None = None, - *, - _validate: bool = True, - ) -> None: - if not isinstance(oid, ObjectIdentifier): - raise TypeError( - "oid argument must be an ObjectIdentifier instance." - ) - if _type == _ASN1Type.BitString: - if oid != NameOID.X500_UNIQUE_IDENTIFIER: - raise TypeError( - "oid must be X500_UNIQUE_IDENTIFIER for BitString type." - ) - if not isinstance(value, bytes): - raise TypeError("value must be bytes for BitString") - elif not isinstance(value, str): - raise TypeError("value argument must be a str") - - length_limits = _NAMEOID_LENGTH_LIMIT.get(oid) - if length_limits is not None: - min_length, max_length = length_limits - assert isinstance(value, str) - c_len = len(value.encode("utf8")) - if c_len < min_length or c_len > max_length: - msg = ( - f"Attribute's length must be >= {min_length} and " - f"<= {max_length}, but it was {c_len}" - ) - if _validate is True: - raise ValueError(msg) - else: - warnings.warn(msg, stacklevel=2) - - # The appropriate ASN1 string type varies by OID and is defined across - # multiple RFCs including 2459, 3280, and 5280. In general UTF8String - # is preferred (2459), but 3280 and 5280 specify several OIDs with - # alternate types. This means when we see the sentinel value we need - # to look up whether the OID has a non-UTF8 type. If it does, set it - # to that. Otherwise, UTF8! - if _type is None: - _type = _NAMEOID_DEFAULT_TYPE.get(oid, _ASN1Type.UTF8String) - - if not isinstance(_type, _ASN1Type): - raise TypeError("_type must be from the _ASN1Type enum") - - self._oid = oid - self._value: NameAttributeValueType = value - self._type: _ASN1Type = _type - - @property - def oid(self) -> ObjectIdentifier: - return self._oid - - @property - def value(self) -> NameAttributeValueType: - return self._value - - @property - def rfc4514_attribute_name(self) -> str: - """ - The short attribute name (for example "CN") if available, - otherwise the OID dotted string. - """ - return _NAMEOID_TO_NAME.get(self.oid, self.oid.dotted_string) - - def rfc4514_string( - self, attr_name_overrides: _OidNameMap | None = None - ) -> str: - """ - Format as RFC4514 Distinguished Name string. - - Use short attribute name if available, otherwise fall back to OID - dotted string. - """ - attr_name = ( - attr_name_overrides.get(self.oid) if attr_name_overrides else None - ) - if attr_name is None: - attr_name = self.rfc4514_attribute_name - - return f"{attr_name}={_escape_dn_value(self.value)}" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, NameAttribute): - return NotImplemented - - return self.oid == other.oid and self.value == other.value - - def __hash__(self) -> int: - return hash((self.oid, self.value)) - - def __repr__(self) -> str: - return f"" - - -class RelativeDistinguishedName: - def __init__(self, attributes: Iterable[NameAttribute[str | bytes]]): - attributes = list(attributes) - if not attributes: - raise ValueError("a relative distinguished name cannot be empty") - if not all(isinstance(x, NameAttribute) for x in attributes): - raise TypeError("attributes must be an iterable of NameAttribute") - - # Keep list and frozenset to preserve attribute order where it matters - self._attributes = attributes - self._attribute_set = frozenset(attributes) - - if len(self._attribute_set) != len(attributes): - raise ValueError("duplicate attributes are not allowed") - - def get_attributes_for_oid( - self, - oid: ObjectIdentifier, - ) -> list[NameAttribute[str | bytes]]: - return [i for i in self if i.oid == oid] - - def rfc4514_string( - self, attr_name_overrides: _OidNameMap | None = None - ) -> str: - """ - Format as RFC4514 Distinguished Name string. - - Within each RDN, attributes are joined by '+', although that is rarely - used in certificates. - """ - return "+".join( - attr.rfc4514_string(attr_name_overrides) - for attr in self._attributes - ) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, RelativeDistinguishedName): - return NotImplemented - - return self._attribute_set == other._attribute_set - - def __hash__(self) -> int: - return hash(self._attribute_set) - - def __iter__(self) -> Iterator[NameAttribute[str | bytes]]: - return iter(self._attributes) - - def __len__(self) -> int: - return len(self._attributes) - - def __repr__(self) -> str: - return f"" - - -class Name: - @typing.overload - def __init__( - self, attributes: Iterable[NameAttribute[str | bytes]] - ) -> None: ... - - @typing.overload - def __init__( - self, attributes: Iterable[RelativeDistinguishedName] - ) -> None: ... - - def __init__( - self, - attributes: Iterable[ - NameAttribute[str | bytes] | RelativeDistinguishedName - ], - ) -> None: - attributes = list(attributes) - if all(isinstance(x, NameAttribute) for x in attributes): - self._attributes = [ - RelativeDistinguishedName([typing.cast(NameAttribute, x)]) - for x in attributes - ] - elif all(isinstance(x, RelativeDistinguishedName) for x in attributes): - self._attributes = typing.cast( - list[RelativeDistinguishedName], attributes - ) - else: - raise TypeError( - "attributes must be a list of NameAttribute" - " or a list RelativeDistinguishedName" - ) - - @classmethod - def from_rfc4514_string( - cls, - data: str, - attr_name_overrides: _NameOidMap | None = None, - ) -> Name: - return _RFC4514NameParser(data, attr_name_overrides or {}).parse() - - def rfc4514_string( - self, attr_name_overrides: _OidNameMap | None = None - ) -> str: - """ - Format as RFC4514 Distinguished Name string. - For example 'CN=foobar.com,O=Foo Corp,C=US' - - An X.509 name is a two-level structure: a list of sets of attributes. - Each list element is separated by ',' and within each list element, set - elements are separated by '+'. The latter is almost never used in - real world certificates. According to RFC4514 section 2.1 the - RDNSequence must be reversed when converting to string representation. - """ - return ",".join( - attr.rfc4514_string(attr_name_overrides) - for attr in reversed(self._attributes) - ) - - def get_attributes_for_oid( - self, - oid: ObjectIdentifier, - ) -> list[NameAttribute[str | bytes]]: - return [i for i in self if i.oid == oid] - - @property - def rdns(self) -> list[RelativeDistinguishedName]: - return self._attributes - - def public_bytes(self, backend: typing.Any = None) -> bytes: - return rust_x509.encode_name_bytes(self) - - def __eq__(self, other: object) -> bool: - if not isinstance(other, Name): - return NotImplemented - - return self._attributes == other._attributes - - def __hash__(self) -> int: - # TODO: this is relatively expensive, if this looks like a bottleneck - # for you, consider optimizing! - return hash(tuple(self._attributes)) - - def __iter__(self) -> Iterator[NameAttribute[str | bytes]]: - for rdn in self._attributes: - yield from rdn - - def __len__(self) -> int: - return sum(len(rdn) for rdn in self._attributes) - - def __repr__(self) -> str: - return f"" - - -class _RFC4514NameParser: - _OID_RE = re.compile(r"(0|([1-9]\d*))(\.(0|([1-9]\d*)))+") - _DESCR_RE = re.compile(r"[a-zA-Z][a-zA-Z\d-]*") - - _ESCAPE_SPECIAL = r"[\\ #=\"\+,;<>]" - _ESCAPE_HEX = r"[\da-zA-Z]{2}" - _PAIR = rf"\\({_ESCAPE_SPECIAL}|{_ESCAPE_HEX})" - _PAIR_MULTI_RE = re.compile(rf"(\\{_ESCAPE_SPECIAL})|((\\{_ESCAPE_HEX})+)") - _LUTF1 = r"[\x01-\x1f\x21\x24-\x2A\x2D-\x3A\x3D\x3F-\x5B\x5D-\x7F]" - _SUTF1 = r"[\x01-\x21\x23-\x2A\x2D-\x3A\x3D\x3F-\x5B\x5D-\x7F]" - _TUTF1 = r"[\x01-\x1F\x21\x23-\x2A\x2D-\x3A\x3D\x3F-\x5B\x5D-\x7F]" - _UTFMB = rf"[\x80-{chr(sys.maxunicode)}]" - _LEADCHAR = rf"{_LUTF1}|{_UTFMB}" - _STRINGCHAR = rf"{_SUTF1}|{_UTFMB}" - _TRAILCHAR = rf"{_TUTF1}|{_UTFMB}" - _STRING_RE = re.compile( - rf""" - ( - ({_LEADCHAR}|{_PAIR}) - ( - ({_STRINGCHAR}|{_PAIR})* - ({_TRAILCHAR}|{_PAIR}) - )? - )? - """, - re.VERBOSE, - ) - _HEXSTRING_RE = re.compile(r"#([\da-zA-Z]{2})+") - - def __init__(self, data: str, attr_name_overrides: _NameOidMap) -> None: - self._data = data - self._idx = 0 - - self._attr_name_overrides = attr_name_overrides - - def _has_data(self) -> bool: - return self._idx < len(self._data) - - def _peek(self) -> str | None: - if self._has_data(): - return self._data[self._idx] - return None - - def _read_char(self, ch: str) -> None: - if self._peek() != ch: - raise ValueError - self._idx += 1 - - def _read_re(self, pat) -> str: - match = pat.match(self._data, pos=self._idx) - if match is None: - raise ValueError - val = match.group() - self._idx += len(val) - return val - - def parse(self) -> Name: - """ - Parses the `data` string and converts it to a Name. - - According to RFC4514 section 2.1 the RDNSequence must be - reversed when converting to string representation. So, when - we parse it, we need to reverse again to get the RDNs on the - correct order. - """ - - if not self._has_data(): - return Name([]) - - rdns = [self._parse_rdn()] - - while self._has_data(): - self._read_char(",") - rdns.append(self._parse_rdn()) - - return Name(reversed(rdns)) - - def _parse_rdn(self) -> RelativeDistinguishedName: - nas = [self._parse_na()] - while self._peek() == "+": - self._read_char("+") - nas.append(self._parse_na()) - - return RelativeDistinguishedName(nas) - - def _parse_na(self) -> NameAttribute[str]: - try: - oid_value = self._read_re(self._OID_RE) - except ValueError: - name = self._read_re(self._DESCR_RE) - oid = self._attr_name_overrides.get( - name, _NAME_TO_NAMEOID.get(name) - ) - if oid is None: - raise ValueError - else: - oid = ObjectIdentifier(oid_value) - - self._read_char("=") - if self._peek() == "#": - value = self._read_re(self._HEXSTRING_RE) - value = binascii.unhexlify(value[1:]).decode() - else: - raw_value = self._read_re(self._STRING_RE) - value = _unescape_dn_value(raw_value) - - return NameAttribute(oid, value) diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/ocsp.py b/notification-service/venv/Lib/site-packages/cryptography/x509/ocsp.py deleted file mode 100644 index f61ed80..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/x509/ocsp.py +++ /dev/null @@ -1,379 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import datetime -from collections.abc import Iterable - -from cryptography import utils, x509 -from cryptography.hazmat.bindings._rust import ocsp -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.asymmetric.types import ( - CertificateIssuerPrivateKeyTypes, -) -from cryptography.x509.base import _reject_duplicate_extension - - -class OCSPResponderEncoding(utils.Enum): - HASH = "By Hash" - NAME = "By Name" - - -class OCSPResponseStatus(utils.Enum): - SUCCESSFUL = 0 - MALFORMED_REQUEST = 1 - INTERNAL_ERROR = 2 - TRY_LATER = 3 - SIG_REQUIRED = 5 - UNAUTHORIZED = 6 - - -_ALLOWED_HASHES = ( - hashes.SHA1, - hashes.SHA224, - hashes.SHA256, - hashes.SHA384, - hashes.SHA512, -) - - -def _verify_algorithm(algorithm: hashes.HashAlgorithm) -> None: - if not isinstance(algorithm, _ALLOWED_HASHES): - raise ValueError( - "Algorithm must be SHA1, SHA224, SHA256, SHA384, or SHA512" - ) - - -class OCSPCertStatus(utils.Enum): - GOOD = 0 - REVOKED = 1 - UNKNOWN = 2 - - -class _SingleResponse: - def __init__( - self, - resp: tuple[x509.Certificate, x509.Certificate] | None, - resp_hash: tuple[bytes, bytes, int] | None, - algorithm: hashes.HashAlgorithm, - cert_status: OCSPCertStatus, - this_update: datetime.datetime, - next_update: datetime.datetime | None, - revocation_time: datetime.datetime | None, - revocation_reason: x509.ReasonFlags | None, - ): - _verify_algorithm(algorithm) - if not isinstance(this_update, datetime.datetime): - raise TypeError("this_update must be a datetime object") - if next_update is not None and not isinstance( - next_update, datetime.datetime - ): - raise TypeError("next_update must be a datetime object or None") - - self._resp = resp - self._resp_hash = resp_hash - self._algorithm = algorithm - self._this_update = this_update - self._next_update = next_update - - if not isinstance(cert_status, OCSPCertStatus): - raise TypeError( - "cert_status must be an item from the OCSPCertStatus enum" - ) - if cert_status is not OCSPCertStatus.REVOKED: - if revocation_time is not None: - raise ValueError( - "revocation_time can only be provided if the certificate " - "is revoked" - ) - if revocation_reason is not None: - raise ValueError( - "revocation_reason can only be provided if the certificate" - " is revoked" - ) - else: - if not isinstance(revocation_time, datetime.datetime): - raise TypeError("revocation_time must be a datetime object") - - if revocation_reason is not None and not isinstance( - revocation_reason, x509.ReasonFlags - ): - raise TypeError( - "revocation_reason must be an item from the ReasonFlags " - "enum or None" - ) - - self._cert_status = cert_status - self._revocation_time = revocation_time - self._revocation_reason = revocation_reason - - -OCSPRequest = ocsp.OCSPRequest -OCSPResponse = ocsp.OCSPResponse -OCSPSingleResponse = ocsp.OCSPSingleResponse - - -class OCSPRequestBuilder: - def __init__( - self, - request: tuple[ - x509.Certificate, x509.Certificate, hashes.HashAlgorithm - ] - | None = None, - request_hash: tuple[bytes, bytes, int, hashes.HashAlgorithm] - | None = None, - extensions: list[x509.Extension[x509.ExtensionType]] = [], - ) -> None: - self._request = request - self._request_hash = request_hash - self._extensions = extensions - - def add_certificate( - self, - cert: x509.Certificate, - issuer: x509.Certificate, - algorithm: hashes.HashAlgorithm, - ) -> OCSPRequestBuilder: - if self._request is not None or self._request_hash is not None: - raise ValueError("Only one certificate can be added to a request") - - _verify_algorithm(algorithm) - if not isinstance(cert, x509.Certificate) or not isinstance( - issuer, x509.Certificate - ): - raise TypeError("cert and issuer must be a Certificate") - - return OCSPRequestBuilder( - (cert, issuer, algorithm), self._request_hash, self._extensions - ) - - def add_certificate_by_hash( - self, - issuer_name_hash: bytes, - issuer_key_hash: bytes, - serial_number: int, - algorithm: hashes.HashAlgorithm, - ) -> OCSPRequestBuilder: - if self._request is not None or self._request_hash is not None: - raise ValueError("Only one certificate can be added to a request") - - if not isinstance(serial_number, int): - raise TypeError("serial_number must be an integer") - - _verify_algorithm(algorithm) - utils._check_bytes("issuer_name_hash", issuer_name_hash) - utils._check_bytes("issuer_key_hash", issuer_key_hash) - if algorithm.digest_size != len( - issuer_name_hash - ) or algorithm.digest_size != len(issuer_key_hash): - raise ValueError( - "issuer_name_hash and issuer_key_hash must be the same length " - "as the digest size of the algorithm" - ) - - return OCSPRequestBuilder( - self._request, - (issuer_name_hash, issuer_key_hash, serial_number, algorithm), - self._extensions, - ) - - def add_extension( - self, extval: x509.ExtensionType, critical: bool - ) -> OCSPRequestBuilder: - if not isinstance(extval, x509.ExtensionType): - raise TypeError("extension must be an ExtensionType") - - extension = x509.Extension(extval.oid, critical, extval) - _reject_duplicate_extension(extension, self._extensions) - - return OCSPRequestBuilder( - self._request, self._request_hash, [*self._extensions, extension] - ) - - def build(self) -> OCSPRequest: - if self._request is None and self._request_hash is None: - raise ValueError("You must add a certificate before building") - - return ocsp.create_ocsp_request(self) - - -class OCSPResponseBuilder: - def __init__( - self, - response: _SingleResponse | None = None, - responder_id: tuple[x509.Certificate, OCSPResponderEncoding] - | None = None, - certs: list[x509.Certificate] | None = None, - extensions: list[x509.Extension[x509.ExtensionType]] = [], - ): - self._response = response - self._responder_id = responder_id - self._certs = certs - self._extensions = extensions - - def add_response( - self, - cert: x509.Certificate, - issuer: x509.Certificate, - algorithm: hashes.HashAlgorithm, - cert_status: OCSPCertStatus, - this_update: datetime.datetime, - next_update: datetime.datetime | None, - revocation_time: datetime.datetime | None, - revocation_reason: x509.ReasonFlags | None, - ) -> OCSPResponseBuilder: - if self._response is not None: - raise ValueError("Only one response per OCSPResponse.") - - if not isinstance(cert, x509.Certificate) or not isinstance( - issuer, x509.Certificate - ): - raise TypeError("cert and issuer must be a Certificate") - - singleresp = _SingleResponse( - (cert, issuer), - None, - algorithm, - cert_status, - this_update, - next_update, - revocation_time, - revocation_reason, - ) - return OCSPResponseBuilder( - singleresp, - self._responder_id, - self._certs, - self._extensions, - ) - - def add_response_by_hash( - self, - issuer_name_hash: bytes, - issuer_key_hash: bytes, - serial_number: int, - algorithm: hashes.HashAlgorithm, - cert_status: OCSPCertStatus, - this_update: datetime.datetime, - next_update: datetime.datetime | None, - revocation_time: datetime.datetime | None, - revocation_reason: x509.ReasonFlags | None, - ) -> OCSPResponseBuilder: - if self._response is not None: - raise ValueError("Only one response per OCSPResponse.") - - if not isinstance(serial_number, int): - raise TypeError("serial_number must be an integer") - - utils._check_bytes("issuer_name_hash", issuer_name_hash) - utils._check_bytes("issuer_key_hash", issuer_key_hash) - _verify_algorithm(algorithm) - if algorithm.digest_size != len( - issuer_name_hash - ) or algorithm.digest_size != len(issuer_key_hash): - raise ValueError( - "issuer_name_hash and issuer_key_hash must be the same length " - "as the digest size of the algorithm" - ) - - singleresp = _SingleResponse( - None, - (issuer_name_hash, issuer_key_hash, serial_number), - algorithm, - cert_status, - this_update, - next_update, - revocation_time, - revocation_reason, - ) - return OCSPResponseBuilder( - singleresp, - self._responder_id, - self._certs, - self._extensions, - ) - - def responder_id( - self, encoding: OCSPResponderEncoding, responder_cert: x509.Certificate - ) -> OCSPResponseBuilder: - if self._responder_id is not None: - raise ValueError("responder_id can only be set once") - if not isinstance(responder_cert, x509.Certificate): - raise TypeError("responder_cert must be a Certificate") - if not isinstance(encoding, OCSPResponderEncoding): - raise TypeError( - "encoding must be an element from OCSPResponderEncoding" - ) - - return OCSPResponseBuilder( - self._response, - (responder_cert, encoding), - self._certs, - self._extensions, - ) - - def certificates( - self, certs: Iterable[x509.Certificate] - ) -> OCSPResponseBuilder: - if self._certs is not None: - raise ValueError("certificates may only be set once") - certs = list(certs) - if len(certs) == 0: - raise ValueError("certs must not be an empty list") - if not all(isinstance(x, x509.Certificate) for x in certs): - raise TypeError("certs must be a list of Certificates") - return OCSPResponseBuilder( - self._response, - self._responder_id, - certs, - self._extensions, - ) - - def add_extension( - self, extval: x509.ExtensionType, critical: bool - ) -> OCSPResponseBuilder: - if not isinstance(extval, x509.ExtensionType): - raise TypeError("extension must be an ExtensionType") - - extension = x509.Extension(extval.oid, critical, extval) - _reject_duplicate_extension(extension, self._extensions) - - return OCSPResponseBuilder( - self._response, - self._responder_id, - self._certs, - [*self._extensions, extension], - ) - - def sign( - self, - private_key: CertificateIssuerPrivateKeyTypes, - algorithm: hashes.HashAlgorithm | None, - ) -> OCSPResponse: - if self._response is None: - raise ValueError("You must add a response before signing") - if self._responder_id is None: - raise ValueError("You must add a responder_id before signing") - - return ocsp.create_ocsp_response( - OCSPResponseStatus.SUCCESSFUL, self, private_key, algorithm - ) - - @classmethod - def build_unsuccessful( - cls, response_status: OCSPResponseStatus - ) -> OCSPResponse: - if not isinstance(response_status, OCSPResponseStatus): - raise TypeError( - "response_status must be an item from OCSPResponseStatus" - ) - if response_status is OCSPResponseStatus.SUCCESSFUL: - raise ValueError("response_status cannot be SUCCESSFUL") - - return ocsp.create_ocsp_response(response_status, None, None, None) - - -load_der_ocsp_request = ocsp.load_der_ocsp_request -load_der_ocsp_response = ocsp.load_der_ocsp_response diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/oid.py b/notification-service/venv/Lib/site-packages/cryptography/x509/oid.py deleted file mode 100644 index 520fc7a..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/x509/oid.py +++ /dev/null @@ -1,37 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -from cryptography.hazmat._oid import ( - AttributeOID, - AuthorityInformationAccessOID, - CertificatePoliciesOID, - CRLEntryExtensionOID, - ExtendedKeyUsageOID, - ExtensionOID, - NameOID, - ObjectIdentifier, - OCSPExtensionOID, - OtherNameFormOID, - PublicKeyAlgorithmOID, - SignatureAlgorithmOID, - SubjectInformationAccessOID, -) - -__all__ = [ - "AttributeOID", - "AuthorityInformationAccessOID", - "CRLEntryExtensionOID", - "CertificatePoliciesOID", - "ExtendedKeyUsageOID", - "ExtensionOID", - "NameOID", - "OCSPExtensionOID", - "ObjectIdentifier", - "OtherNameFormOID", - "PublicKeyAlgorithmOID", - "SignatureAlgorithmOID", - "SubjectInformationAccessOID", -] diff --git a/notification-service/venv/Lib/site-packages/cryptography/x509/verification.py b/notification-service/venv/Lib/site-packages/cryptography/x509/verification.py deleted file mode 100644 index 2db4324..0000000 --- a/notification-service/venv/Lib/site-packages/cryptography/x509/verification.py +++ /dev/null @@ -1,34 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - -from __future__ import annotations - -import typing - -from cryptography.hazmat.bindings._rust import x509 as rust_x509 -from cryptography.x509.general_name import DNSName, IPAddress - -__all__ = [ - "ClientVerifier", - "Criticality", - "ExtensionPolicy", - "Policy", - "PolicyBuilder", - "ServerVerifier", - "Store", - "Subject", - "VerificationError", - "VerifiedClient", -] - -Store = rust_x509.Store -Subject = typing.Union[DNSName, IPAddress] -VerifiedClient = rust_x509.VerifiedClient -ClientVerifier = rust_x509.ClientVerifier -ServerVerifier = rust_x509.ServerVerifier -PolicyBuilder = rust_x509.PolicyBuilder -Policy = rust_x509.Policy -ExtensionPolicy = rust_x509.ExtensionPolicy -Criticality = rust_x509.Criticality -VerificationError = rust_x509.VerificationError diff --git a/notification-service/venv/Lib/site-packages/dotenv/__init__.py b/notification-service/venv/Lib/site-packages/dotenv/__init__.py deleted file mode 100644 index dde24a0..0000000 --- a/notification-service/venv/Lib/site-packages/dotenv/__init__.py +++ /dev/null @@ -1,51 +0,0 @@ -from typing import Any, Optional - -from .main import dotenv_values, find_dotenv, get_key, load_dotenv, set_key, unset_key - - -def load_ipython_extension(ipython: Any) -> None: - from .ipython import load_ipython_extension - - load_ipython_extension(ipython) - - -def get_cli_string( - path: Optional[str] = None, - action: Optional[str] = None, - key: Optional[str] = None, - value: Optional[str] = None, - quote: Optional[str] = None, -): - """Returns a string suitable for running as a shell script. - - Useful for converting a arguments passed to a fabric task - to be passed to a `local` or `run` command. - """ - command = ["dotenv"] - if quote: - command.append(f"-q {quote}") - if path: - command.append(f"-f {path}") - if action: - command.append(action) - if key: - command.append(key) - if value: - if " " in value: - command.append(f'"{value}"') - else: - command.append(value) - - return " ".join(command).strip() - - -__all__ = [ - "get_cli_string", - "load_dotenv", - "dotenv_values", - "get_key", - "set_key", - "unset_key", - "find_dotenv", - "load_ipython_extension", -] diff --git a/notification-service/venv/Lib/site-packages/dotenv/__main__.py b/notification-service/venv/Lib/site-packages/dotenv/__main__.py deleted file mode 100644 index 3977f55..0000000 --- a/notification-service/venv/Lib/site-packages/dotenv/__main__.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Entry point for cli, enables execution with `python -m dotenv`""" - -from .cli import cli - -if __name__ == "__main__": - cli() diff --git a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/dotenv/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index a3604ba..0000000 Binary files a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/__main__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/dotenv/__pycache__/__main__.cpython-312.pyc deleted file mode 100644 index 370d583..0000000 Binary files a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/__main__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/cli.cpython-312.pyc b/notification-service/venv/Lib/site-packages/dotenv/__pycache__/cli.cpython-312.pyc deleted file mode 100644 index a8c4098..0000000 Binary files a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/cli.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/ipython.cpython-312.pyc b/notification-service/venv/Lib/site-packages/dotenv/__pycache__/ipython.cpython-312.pyc deleted file mode 100644 index cbf0345..0000000 Binary files a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/ipython.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/main.cpython-312.pyc b/notification-service/venv/Lib/site-packages/dotenv/__pycache__/main.cpython-312.pyc deleted file mode 100644 index e1618a6..0000000 Binary files a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/main.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/parser.cpython-312.pyc b/notification-service/venv/Lib/site-packages/dotenv/__pycache__/parser.cpython-312.pyc deleted file mode 100644 index 612b706..0000000 Binary files a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/parser.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/variables.cpython-312.pyc b/notification-service/venv/Lib/site-packages/dotenv/__pycache__/variables.cpython-312.pyc deleted file mode 100644 index 2a5e8be..0000000 Binary files a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/variables.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/version.cpython-312.pyc b/notification-service/venv/Lib/site-packages/dotenv/__pycache__/version.cpython-312.pyc deleted file mode 100644 index f068b1f..0000000 Binary files a/notification-service/venv/Lib/site-packages/dotenv/__pycache__/version.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/dotenv/cli.py b/notification-service/venv/Lib/site-packages/dotenv/cli.py deleted file mode 100644 index 47eec04..0000000 --- a/notification-service/venv/Lib/site-packages/dotenv/cli.py +++ /dev/null @@ -1,236 +0,0 @@ -import json -import os -import shlex -import sys -from contextlib import contextmanager -from typing import IO, Any, Dict, Iterator, List, Optional - -if sys.platform == "win32": - from subprocess import Popen - -try: - import click -except ImportError: - sys.stderr.write( - "It seems python-dotenv is not installed with cli option. \n" - 'Run pip install "python-dotenv[cli]" to fix this.' - ) - sys.exit(1) - -from .main import dotenv_values, set_key, unset_key -from .version import __version__ - - -def enumerate_env() -> Optional[str]: - """ - Return a path for the ${pwd}/.env file. - - If pwd does not exist, return None. - """ - try: - cwd = os.getcwd() - except FileNotFoundError: - return None - path = os.path.join(cwd, ".env") - return path - - -@click.group() -@click.option( - "-f", - "--file", - default=enumerate_env(), - type=click.Path(file_okay=True), - help="Location of the .env file, defaults to .env file in current working directory.", -) -@click.option( - "-q", - "--quote", - default="always", - type=click.Choice(["always", "never", "auto"]), - help="Whether to quote or not the variable values. Default mode is always. This does not affect parsing.", -) -@click.option( - "-e", - "--export", - default=False, - type=click.BOOL, - help="Whether to write the dot file as an executable bash script.", -) -@click.version_option(version=__version__) -@click.pass_context -def cli(ctx: click.Context, file: Any, quote: Any, export: Any) -> None: - """This script is used to set, get or unset values from a .env file.""" - ctx.obj = {"QUOTE": quote, "EXPORT": export, "FILE": file} - - -@contextmanager -def stream_file(path: os.PathLike) -> Iterator[IO[str]]: - """ - Open a file and yield the corresponding (decoded) stream. - - Exits with error code 2 if the file cannot be opened. - """ - - try: - with open(path) as stream: - yield stream - except OSError as exc: - print(f"Error opening env file: {exc}", file=sys.stderr) - sys.exit(2) - - -@cli.command(name="list") -@click.pass_context -@click.option( - "--format", - "output_format", - default="simple", - type=click.Choice(["simple", "json", "shell", "export"]), - help="The format in which to display the list. Default format is simple, " - "which displays name=value without quotes.", -) -def list_values(ctx: click.Context, output_format: str) -> None: - """Display all the stored key/value.""" - file = ctx.obj["FILE"] - - with stream_file(file) as stream: - values = dotenv_values(stream=stream) - - if output_format == "json": - click.echo(json.dumps(values, indent=2, sort_keys=True)) - else: - prefix = "export " if output_format == "export" else "" - for k in sorted(values): - v = values[k] - if v is not None: - if output_format in ("export", "shell"): - v = shlex.quote(v) - click.echo(f"{prefix}{k}={v}") - - -@cli.command(name="set") -@click.pass_context -@click.argument("key", required=True) -@click.argument("value", required=True) -def set_value(ctx: click.Context, key: Any, value: Any) -> None: - """ - Store the given key/value. - - This doesn't follow symlinks, to avoid accidentally modifying a file at a - potentially untrusted path. - """ - - file = ctx.obj["FILE"] - quote = ctx.obj["QUOTE"] - export = ctx.obj["EXPORT"] - success, key, value = set_key(file, key, value, quote, export) - if success: - click.echo(f"{key}={value}") - else: - sys.exit(1) - - -@cli.command() -@click.pass_context -@click.argument("key", required=True) -def get(ctx: click.Context, key: Any) -> None: - """Retrieve the value for the given key.""" - file = ctx.obj["FILE"] - - with stream_file(file) as stream: - values = dotenv_values(stream=stream) - - stored_value = values.get(key) - if stored_value: - click.echo(stored_value) - else: - sys.exit(1) - - -@cli.command() -@click.pass_context -@click.argument("key", required=True) -def unset(ctx: click.Context, key: Any) -> None: - """ - Removes the given key. - - This doesn't follow symlinks, to avoid accidentally modifying a file at a - potentially untrusted path. - """ - file = ctx.obj["FILE"] - quote = ctx.obj["QUOTE"] - success, key = unset_key(file, key, quote) - if success: - click.echo(f"Successfully removed {key}") - else: - sys.exit(1) - - -@cli.command( - context_settings={ - "allow_extra_args": True, - "allow_interspersed_args": False, - "ignore_unknown_options": True, - } -) -@click.pass_context -@click.option( - "--override/--no-override", - default=True, - help="Override variables from the environment file with those from the .env file.", -) -@click.argument("commandline", nargs=-1, type=click.UNPROCESSED) -def run(ctx: click.Context, override: bool, commandline: tuple[str, ...]) -> None: - """Run command with environment variables present.""" - file = ctx.obj["FILE"] - if not os.path.isfile(file): - raise click.BadParameter( - f"Invalid value for '-f' \"{file}\" does not exist.", ctx=ctx - ) - dotenv_as_dict = { - k: v - for (k, v) in dotenv_values(file).items() - if v is not None and (override or k not in os.environ) - } - - if not commandline: - click.echo("No command given.") - sys.exit(1) - - run_command([*commandline, *ctx.args], dotenv_as_dict) - - -def run_command(command: List[str], env: Dict[str, str]) -> None: - """Replace the current process with the specified command. - - Replaces the current process with the specified command and the variables from `env` - added in the current environment variables. - - Parameters - ---------- - command: List[str] - The command and it's parameters - env: Dict - The additional environment variables - - Returns - ------- - None - This function does not return any value. It replaces the current process with the new one. - - """ - # copy the current environment variables and add the vales from - # `env` - cmd_env = os.environ.copy() - cmd_env.update(env) - - if sys.platform == "win32": - # execvpe on Windows returns control immediately - # rather than once the command has finished. - p = Popen(command, universal_newlines=True, bufsize=0, shell=False, env=cmd_env) - _, _ = p.communicate() - - sys.exit(p.returncode) - else: - os.execvpe(command[0], args=command, env=cmd_env) diff --git a/notification-service/venv/Lib/site-packages/dotenv/ipython.py b/notification-service/venv/Lib/site-packages/dotenv/ipython.py deleted file mode 100644 index 4e7edbb..0000000 --- a/notification-service/venv/Lib/site-packages/dotenv/ipython.py +++ /dev/null @@ -1,50 +0,0 @@ -from IPython.core.magic import Magics, line_magic, magics_class # type: ignore -from IPython.core.magic_arguments import ( - argument, - magic_arguments, - parse_argstring, -) # type: ignore - -from .main import find_dotenv, load_dotenv - - -@magics_class -class IPythonDotEnv(Magics): - @magic_arguments() - @argument( - "-o", - "--override", - action="store_true", - help="Indicate to override existing variables", - ) - @argument( - "-v", - "--verbose", - action="store_true", - help="Indicate function calls to be verbose", - ) - @argument( - "dotenv_path", - nargs="?", - type=str, - default=".env", - help="Search in increasingly higher folders for the `dotenv_path`", - ) - @line_magic - def dotenv(self, line): - args = parse_argstring(self.dotenv, line) - # Locate the .env file - dotenv_path = args.dotenv_path - try: - dotenv_path = find_dotenv(dotenv_path, True, True) - except IOError: - print("cannot find .env file") - return - - # Load the .env file - load_dotenv(dotenv_path, verbose=args.verbose, override=args.override) - - -def load_ipython_extension(ipython): - """Register the %dotenv magic.""" - ipython.register_magics(IPythonDotEnv) diff --git a/notification-service/venv/Lib/site-packages/dotenv/main.py b/notification-service/venv/Lib/site-packages/dotenv/main.py deleted file mode 100644 index 48e5245..0000000 --- a/notification-service/venv/Lib/site-packages/dotenv/main.py +++ /dev/null @@ -1,480 +0,0 @@ -import io -import logging -import os -import pathlib -import stat -import sys -import tempfile -from collections import OrderedDict -from contextlib import contextmanager -from typing import IO, Dict, Iterable, Iterator, Mapping, Optional, Tuple, Union - -from .parser import Binding, parse_stream -from .variables import parse_variables - -# A type alias for a string path to be used for the paths in this file. -# These paths may flow to `open()` and `os.replace()`. -StrPath = Union[str, "os.PathLike[str]"] - -logger = logging.getLogger(__name__) - - -def _load_dotenv_disabled() -> bool: - """ - Determine if dotenv loading has been disabled. - """ - if "PYTHON_DOTENV_DISABLED" not in os.environ: - return False - value = os.environ["PYTHON_DOTENV_DISABLED"].casefold() - return value in {"1", "true", "t", "yes", "y"} - - -def with_warn_for_invalid_lines(mappings: Iterator[Binding]) -> Iterator[Binding]: - for mapping in mappings: - if mapping.error: - logger.warning( - "python-dotenv could not parse statement starting at line %s", - mapping.original.line, - ) - yield mapping - - -class DotEnv: - def __init__( - self, - dotenv_path: Optional[StrPath], - stream: Optional[IO[str]] = None, - verbose: bool = False, - encoding: Optional[str] = None, - interpolate: bool = True, - override: bool = True, - ) -> None: - self.dotenv_path: Optional[StrPath] = dotenv_path - self.stream: Optional[IO[str]] = stream - self._dict: Optional[Dict[str, Optional[str]]] = None - self.verbose: bool = verbose - self.encoding: Optional[str] = encoding - self.interpolate: bool = interpolate - self.override: bool = override - - @contextmanager - def _get_stream(self) -> Iterator[IO[str]]: - if self.dotenv_path and _is_file_or_fifo(self.dotenv_path): - with open(self.dotenv_path, encoding=self.encoding) as stream: - yield stream - elif self.stream is not None: - yield self.stream - else: - if self.verbose: - logger.info( - "python-dotenv could not find configuration file %s.", - self.dotenv_path or ".env", - ) - yield io.StringIO("") - - def dict(self) -> Dict[str, Optional[str]]: - """Return dotenv as dict""" - if self._dict: - return self._dict - - raw_values = self.parse() - - if self.interpolate: - self._dict = OrderedDict( - resolve_variables(raw_values, override=self.override) - ) - else: - self._dict = OrderedDict(raw_values) - - return self._dict - - def parse(self) -> Iterator[Tuple[str, Optional[str]]]: - with self._get_stream() as stream: - for mapping in with_warn_for_invalid_lines(parse_stream(stream)): - if mapping.key is not None: - yield mapping.key, mapping.value - - def set_as_environment_variables(self) -> bool: - """ - Load the current dotenv as system environment variable. - """ - if not self.dict(): - return False - - for k, v in self.dict().items(): - if k in os.environ and not self.override: - continue - if v is not None: - os.environ[k] = v - - return True - - def get(self, key: str) -> Optional[str]: - """ """ - data = self.dict() - - if key in data: - return data[key] - - if self.verbose: - logger.warning("Key %s not found in %s.", key, self.dotenv_path) - - return None - - -def get_key( - dotenv_path: StrPath, - key_to_get: str, - encoding: Optional[str] = "utf-8", -) -> Optional[str]: - """ - Get the value of a given key from the given .env. - - Returns `None` if the key isn't found or doesn't have a value. - """ - return DotEnv(dotenv_path, verbose=True, encoding=encoding).get(key_to_get) - - -@contextmanager -def rewrite( - path: StrPath, - encoding: Optional[str], - follow_symlinks: bool = False, -) -> Iterator[Tuple[IO[str], IO[str]]]: - if follow_symlinks: - path = os.path.realpath(path) - - try: - source: IO[str] = open(path, encoding=encoding) - try: - path_stat = os.lstat(path) - original_mode: Optional[int] = ( - stat.S_IMODE(path_stat.st_mode) - if stat.S_ISREG(path_stat.st_mode) - else None - ) - except BaseException: - source.close() - raise - except FileNotFoundError: - source = io.StringIO("") - original_mode = None - - with tempfile.NamedTemporaryFile( - mode="w", - encoding=encoding, - delete=False, - prefix=".tmp_", - dir=os.path.dirname(os.path.abspath(path)), - ) as dest: - dest_path = pathlib.Path(dest.name) - error = None - - try: - with source: - yield (source, dest) - except BaseException as err: - error = err - - if error is None: - try: - if original_mode is not None: - os.chmod(dest_path, original_mode) - - os.replace(dest_path, path) - except BaseException: - dest_path.unlink(missing_ok=True) - raise - else: - dest_path.unlink(missing_ok=True) - raise error from None - - -def set_key( - dotenv_path: StrPath, - key_to_set: str, - value_to_set: str, - quote_mode: str = "always", - export: bool = False, - encoding: Optional[str] = "utf-8", - follow_symlinks: bool = False, -) -> Tuple[Optional[bool], str, str]: - """ - Adds or Updates a key/value to the given .env - - The target .env file is created if it doesn't exist. - - This function doesn't follow symlinks by default, to avoid accidentally - modifying a file at a potentially untrusted path. If you don't need this - protection and need symlinks to be followed, use `follow_symlinks`. - """ - if quote_mode not in ("always", "auto", "never"): - raise ValueError(f"Unknown quote_mode: {quote_mode}") - - quote = quote_mode == "always" or ( - quote_mode == "auto" and not value_to_set.isalnum() - ) - - if quote: - value_out = "'{}'".format(value_to_set.replace("'", "\\'")) - else: - value_out = value_to_set - if export: - line_out = f"export {key_to_set}={value_out}\n" - else: - line_out = f"{key_to_set}={value_out}\n" - - with rewrite(dotenv_path, encoding=encoding, follow_symlinks=follow_symlinks) as ( - source, - dest, - ): - replaced = False - missing_newline = False - for mapping in with_warn_for_invalid_lines(parse_stream(source)): - if mapping.key == key_to_set: - dest.write(line_out) - replaced = True - else: - dest.write(mapping.original.string) - missing_newline = not mapping.original.string.endswith("\n") - if not replaced: - if missing_newline: - dest.write("\n") - dest.write(line_out) - - return True, key_to_set, value_to_set - - -def unset_key( - dotenv_path: StrPath, - key_to_unset: str, - quote_mode: str = "always", - encoding: Optional[str] = "utf-8", - follow_symlinks: bool = False, -) -> Tuple[Optional[bool], str]: - """ - Removes a given key from the given `.env` file. - - If the .env path given doesn't exist, fails. - If the given key doesn't exist in the .env, fails. - - This function doesn't follow symlinks by default, to avoid accidentally - modifying a file at a potentially untrusted path. If you don't need this - protection and need symlinks to be followed, use `follow_symlinks`. - """ - if not os.path.exists(dotenv_path): - logger.warning("Can't delete from %s - it doesn't exist.", dotenv_path) - return None, key_to_unset - - removed = False - with rewrite(dotenv_path, encoding=encoding, follow_symlinks=follow_symlinks) as ( - source, - dest, - ): - for mapping in with_warn_for_invalid_lines(parse_stream(source)): - if mapping.key == key_to_unset: - removed = True - else: - dest.write(mapping.original.string) - - if not removed: - logger.warning( - "Key %s not removed from %s - key doesn't exist.", key_to_unset, dotenv_path - ) - return None, key_to_unset - - return removed, key_to_unset - - -def resolve_variables( - values: Iterable[Tuple[str, Optional[str]]], - override: bool, -) -> Mapping[str, Optional[str]]: - new_values: Dict[str, Optional[str]] = {} - - for name, value in values: - if value is None: - result = None - else: - atoms = parse_variables(value) - env: Dict[str, Optional[str]] = {} - if override: - env.update(os.environ) # type: ignore - env.update(new_values) - else: - env.update(new_values) - env.update(os.environ) # type: ignore - result = "".join(atom.resolve(env) for atom in atoms) - - new_values[name] = result - - return new_values - - -def _walk_to_root(path: str) -> Iterator[str]: - """ - Yield directories starting from the given directory up to the root - """ - if not os.path.exists(path): - raise IOError("Starting path not found") - - if os.path.isfile(path): - path = os.path.dirname(path) - - last_dir = None - current_dir = os.path.abspath(path) - while last_dir != current_dir: - yield current_dir - parent_dir = os.path.abspath(os.path.join(current_dir, os.path.pardir)) - last_dir, current_dir = current_dir, parent_dir - - -def find_dotenv( - filename: str = ".env", - raise_error_if_not_found: bool = False, - usecwd: bool = False, -) -> str: - """ - Search in increasingly higher folders for the given file - - Returns path to the file if found, or an empty string otherwise - """ - - def _is_interactive(): - """Decide whether this is running in a REPL or IPython notebook""" - if hasattr(sys, "ps1") or hasattr(sys, "ps2"): - return True - try: - main = __import__("__main__", None, None, fromlist=["__file__"]) - except ModuleNotFoundError: - return False - return not hasattr(main, "__file__") - - def _is_debugger(): - return sys.gettrace() is not None - - if usecwd or _is_interactive() or _is_debugger() or getattr(sys, "frozen", False): - # Should work without __file__, e.g. in REPL or IPython notebook. - path = os.getcwd() - else: - # will work for .py files - frame = sys._getframe() - current_file = __file__ - - while frame.f_code.co_filename == current_file or not os.path.exists( - frame.f_code.co_filename - ): - assert frame.f_back is not None - frame = frame.f_back - frame_filename = frame.f_code.co_filename - path = os.path.dirname(os.path.abspath(frame_filename)) - - for dirname in _walk_to_root(path): - check_path = os.path.join(dirname, filename) - if _is_file_or_fifo(check_path): - return check_path - - if raise_error_if_not_found: - raise IOError("File not found") - - return "" - - -def load_dotenv( - dotenv_path: Optional[StrPath] = None, - stream: Optional[IO[str]] = None, - verbose: bool = False, - override: bool = False, - interpolate: bool = True, - encoding: Optional[str] = "utf-8", -) -> bool: - """Parse a .env file and then load all the variables found as environment variables. - - Parameters: - dotenv_path: Absolute or relative path to .env file. - stream: Text stream (such as `io.StringIO`) with .env content, used if - `dotenv_path` is `None`. - verbose: Whether to output a warning the .env file is missing. - override: Whether to override the system environment variables with the variables - from the `.env` file. - encoding: Encoding to be used to read the file. - Returns: - Bool: True if at least one environment variable is set else False - - If both `dotenv_path` and `stream` are `None`, `find_dotenv()` is used to find the - .env file with it's default parameters. If you need to change the default parameters - of `find_dotenv()`, you can explicitly call `find_dotenv()` and pass the result - to this function as `dotenv_path`. - - If the environment variable `PYTHON_DOTENV_DISABLED` is set to a truthy value, - .env loading is disabled. - """ - if _load_dotenv_disabled(): - logger.debug( - "python-dotenv: .env loading disabled by PYTHON_DOTENV_DISABLED environment variable" - ) - return False - - if dotenv_path is None and stream is None: - dotenv_path = find_dotenv() - - dotenv = DotEnv( - dotenv_path=dotenv_path, - stream=stream, - verbose=verbose, - interpolate=interpolate, - override=override, - encoding=encoding, - ) - return dotenv.set_as_environment_variables() - - -def dotenv_values( - dotenv_path: Optional[StrPath] = None, - stream: Optional[IO[str]] = None, - verbose: bool = False, - interpolate: bool = True, - encoding: Optional[str] = "utf-8", -) -> Dict[str, Optional[str]]: - """ - Parse a .env file and return its content as a dict. - - The returned dict will have `None` values for keys without values in the .env file. - For example, `foo=bar` results in `{"foo": "bar"}` whereas `foo` alone results in - `{"foo": None}` - - Parameters: - dotenv_path: Absolute or relative path to the .env file. - stream: `StringIO` object with .env content, used if `dotenv_path` is `None`. - verbose: Whether to output a warning if the .env file is missing. - encoding: Encoding to be used to read the file. - - If both `dotenv_path` and `stream` are `None`, `find_dotenv()` is used to find the - .env file. - """ - if dotenv_path is None and stream is None: - dotenv_path = find_dotenv() - - return DotEnv( - dotenv_path=dotenv_path, - stream=stream, - verbose=verbose, - interpolate=interpolate, - override=True, - encoding=encoding, - ).dict() - - -def _is_file_or_fifo(path: StrPath) -> bool: - """ - Return True if `path` exists and is either a regular file or a FIFO. - """ - if os.path.isfile(path): - return True - - try: - st = os.stat(path) - except (FileNotFoundError, OSError): - return False - - return stat.S_ISFIFO(st.st_mode) diff --git a/notification-service/venv/Lib/site-packages/dotenv/parser.py b/notification-service/venv/Lib/site-packages/dotenv/parser.py deleted file mode 100644 index eb100b4..0000000 --- a/notification-service/venv/Lib/site-packages/dotenv/parser.py +++ /dev/null @@ -1,182 +0,0 @@ -import codecs -import re -from typing import ( - IO, - Iterator, - Match, - NamedTuple, - Optional, - Pattern, - Sequence, -) - - -def make_regex(string: str, extra_flags: int = 0) -> Pattern[str]: - return re.compile(string, re.UNICODE | extra_flags) - - -_newline = make_regex(r"(\r\n|\n|\r)") -_multiline_whitespace = make_regex(r"\s*", extra_flags=re.MULTILINE) -_whitespace = make_regex(r"[^\S\r\n]*") -_export = make_regex(r"(?:export[^\S\r\n]+)?") -_single_quoted_key = make_regex(r"'([^']+)'") -_unquoted_key = make_regex(r"([^=\#\s]+)") -_equal_sign = make_regex(r"(=[^\S\r\n]*)") -_single_quoted_value = make_regex(r"'((?:\\'|[^'])*)'") -_double_quoted_value = make_regex(r'"((?:\\"|[^"])*)"') -_unquoted_value = make_regex(r"([^\r\n]*)") -_comment = make_regex(r"(?:[^\S\r\n]*#[^\r\n]*)?") -_end_of_line = make_regex(r"[^\S\r\n]*(?:\r\n|\n|\r|$)") -_rest_of_line = make_regex(r"[^\r\n]*(?:\r|\n|\r\n)?") -_double_quote_escapes = make_regex(r"\\[\\'\"abfnrtv]") -_single_quote_escapes = make_regex(r"\\[\\']") - - -class Original(NamedTuple): - string: str - line: int - - -class Binding(NamedTuple): - key: Optional[str] - value: Optional[str] - original: Original - error: bool - - -class Position: - def __init__(self, chars: int, line: int) -> None: - self.chars = chars - self.line = line - - @classmethod - def start(cls) -> "Position": - return cls(chars=0, line=1) - - def set(self, other: "Position") -> None: - self.chars = other.chars - self.line = other.line - - def advance(self, string: str) -> None: - self.chars += len(string) - self.line += len(re.findall(_newline, string)) - - -class Error(Exception): - pass - - -class Reader: - def __init__(self, stream: IO[str]) -> None: - self.string = stream.read() - self.position = Position.start() - self.mark = Position.start() - - def has_next(self) -> bool: - return self.position.chars < len(self.string) - - def set_mark(self) -> None: - self.mark.set(self.position) - - def get_marked(self) -> Original: - return Original( - string=self.string[self.mark.chars : self.position.chars], - line=self.mark.line, - ) - - def peek(self, count: int) -> str: - return self.string[self.position.chars : self.position.chars + count] - - def read(self, count: int) -> str: - result = self.string[self.position.chars : self.position.chars + count] - if len(result) < count: - raise Error("read: End of string") - self.position.advance(result) - return result - - def read_regex(self, regex: Pattern[str]) -> Sequence[str]: - match = regex.match(self.string, self.position.chars) - if match is None: - raise Error("read_regex: Pattern not found") - self.position.advance(self.string[match.start() : match.end()]) - return match.groups() - - -def decode_escapes(regex: Pattern[str], string: str) -> str: - def decode_match(match: Match[str]) -> str: - return codecs.decode(match.group(0), "unicode-escape") # type: ignore - - return regex.sub(decode_match, string) - - -def parse_key(reader: Reader) -> Optional[str]: - char = reader.peek(1) - if char == "#": - return None - elif char == "'": - (key,) = reader.read_regex(_single_quoted_key) - else: - (key,) = reader.read_regex(_unquoted_key) - return key - - -def parse_unquoted_value(reader: Reader) -> str: - (part,) = reader.read_regex(_unquoted_value) - return re.sub(r"\s+#.*", "", part).rstrip() - - -def parse_value(reader: Reader) -> str: - char = reader.peek(1) - if char == "'": - (value,) = reader.read_regex(_single_quoted_value) - return decode_escapes(_single_quote_escapes, value) - elif char == '"': - (value,) = reader.read_regex(_double_quoted_value) - return decode_escapes(_double_quote_escapes, value) - elif char in ("", "\n", "\r"): - return "" - else: - return parse_unquoted_value(reader) - - -def parse_binding(reader: Reader) -> Binding: - reader.set_mark() - try: - reader.read_regex(_multiline_whitespace) - if not reader.has_next(): - return Binding( - key=None, - value=None, - original=reader.get_marked(), - error=False, - ) - reader.read_regex(_export) - key = parse_key(reader) - reader.read_regex(_whitespace) - if reader.peek(1) == "=": - reader.read_regex(_equal_sign) - value: Optional[str] = parse_value(reader) - else: - value = None - reader.read_regex(_comment) - reader.read_regex(_end_of_line) - return Binding( - key=key, - value=value, - original=reader.get_marked(), - error=False, - ) - except Error: - reader.read_regex(_rest_of_line) - return Binding( - key=None, - value=None, - original=reader.get_marked(), - error=True, - ) - - -def parse_stream(stream: IO[str]) -> Iterator[Binding]: - reader = Reader(stream) - while reader.has_next(): - yield parse_binding(reader) diff --git a/notification-service/venv/Lib/site-packages/dotenv/py.typed b/notification-service/venv/Lib/site-packages/dotenv/py.typed deleted file mode 100644 index 7632ecf..0000000 --- a/notification-service/venv/Lib/site-packages/dotenv/py.typed +++ /dev/null @@ -1 +0,0 @@ -# Marker file for PEP 561 diff --git a/notification-service/venv/Lib/site-packages/dotenv/variables.py b/notification-service/venv/Lib/site-packages/dotenv/variables.py deleted file mode 100644 index 667f2f2..0000000 --- a/notification-service/venv/Lib/site-packages/dotenv/variables.py +++ /dev/null @@ -1,86 +0,0 @@ -import re -from abc import ABCMeta, abstractmethod -from typing import Iterator, Mapping, Optional, Pattern - -_posix_variable: Pattern[str] = re.compile( - r""" - \$\{ - (?P[^\}:]*) - (?::- - (?P[^\}]*) - )? - \} - """, - re.VERBOSE, -) - - -class Atom(metaclass=ABCMeta): - def __ne__(self, other: object) -> bool: - result = self.__eq__(other) - if result is NotImplemented: - return NotImplemented - return not result - - @abstractmethod - def resolve(self, env: Mapping[str, Optional[str]]) -> str: ... - - -class Literal(Atom): - def __init__(self, value: str) -> None: - self.value = value - - def __repr__(self) -> str: - return f"Literal(value={self.value})" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, self.__class__): - return NotImplemented - return self.value == other.value - - def __hash__(self) -> int: - return hash((self.__class__, self.value)) - - def resolve(self, env: Mapping[str, Optional[str]]) -> str: - return self.value - - -class Variable(Atom): - def __init__(self, name: str, default: Optional[str]) -> None: - self.name = name - self.default = default - - def __repr__(self) -> str: - return f"Variable(name={self.name}, default={self.default})" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, self.__class__): - return NotImplemented - return (self.name, self.default) == (other.name, other.default) - - def __hash__(self) -> int: - return hash((self.__class__, self.name, self.default)) - - def resolve(self, env: Mapping[str, Optional[str]]) -> str: - default = self.default if self.default is not None else "" - result = env.get(self.name, default) - return result if result is not None else "" - - -def parse_variables(value: str) -> Iterator[Atom]: - cursor = 0 - - for match in _posix_variable.finditer(value): - (start, end) = match.span() - name = match["name"] - default = match["default"] - - if start > cursor: - yield Literal(value=value[cursor:start]) - - yield Variable(name=name, default=default) - cursor = end - - length = len(value) - if cursor < length: - yield Literal(value=value[cursor:length]) diff --git a/notification-service/venv/Lib/site-packages/dotenv/version.py b/notification-service/venv/Lib/site-packages/dotenv/version.py deleted file mode 100644 index bc86c94..0000000 --- a/notification-service/venv/Lib/site-packages/dotenv/version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "1.2.2" diff --git a/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/INSTALLER b/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/METADATA b/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/METADATA deleted file mode 100644 index 149c90c..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/METADATA +++ /dev/null @@ -1,622 +0,0 @@ -Metadata-Version: 2.4 -Name: fastapi -Version: 0.136.1 -Summary: FastAPI framework, high performance, easy to learn, fast to code, ready for production -Author-Email: =?utf-8?q?Sebasti=C3=A1n_Ram=C3=ADrez?= -License-Expression: MIT -License-File: LICENSE -Classifier: Intended Audience :: Information Technology -Classifier: Intended Audience :: System Administrators -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python -Classifier: Topic :: Internet -Classifier: Topic :: Software Development :: Libraries :: Application Frameworks -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Software Development :: Libraries -Classifier: Topic :: Software Development -Classifier: Typing :: Typed -Classifier: Development Status :: 4 - Beta -Classifier: Environment :: Web Environment -Classifier: Framework :: AsyncIO -Classifier: Framework :: FastAPI -Classifier: Framework :: Pydantic -Classifier: Framework :: Pydantic :: 2 -Classifier: Intended Audience :: Developers -Classifier: Programming Language :: Python :: 3 :: Only -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: Topic :: Internet :: WWW/HTTP :: HTTP Servers -Classifier: Topic :: Internet :: WWW/HTTP -Project-URL: Homepage, https://github.com/fastapi/fastapi -Project-URL: Documentation, https://fastapi.tiangolo.com/ -Project-URL: Repository, https://github.com/fastapi/fastapi -Project-URL: Issues, https://github.com/fastapi/fastapi/issues -Project-URL: Changelog, https://fastapi.tiangolo.com/release-notes/ -Requires-Python: >=3.10 -Requires-Dist: starlette>=0.46.0 -Requires-Dist: pydantic>=2.9.0 -Requires-Dist: typing-extensions>=4.8.0 -Requires-Dist: typing-inspection>=0.4.2 -Requires-Dist: annotated-doc>=0.0.2 -Provides-Extra: standard -Requires-Dist: fastapi-cli[standard]>=0.0.8; extra == "standard" -Requires-Dist: fastar>=0.9.0; extra == "standard" -Requires-Dist: httpx<1.0.0,>=0.23.0; extra == "standard" -Requires-Dist: jinja2>=3.1.5; extra == "standard" -Requires-Dist: python-multipart>=0.0.18; extra == "standard" -Requires-Dist: email-validator>=2.0.0; extra == "standard" -Requires-Dist: uvicorn[standard]>=0.12.0; extra == "standard" -Requires-Dist: pydantic-settings>=2.0.0; extra == "standard" -Requires-Dist: pydantic-extra-types>=2.0.0; extra == "standard" -Provides-Extra: standard-no-fastapi-cloud-cli -Requires-Dist: fastapi-cli[standard-no-fastapi-cloud-cli]>=0.0.8; extra == "standard-no-fastapi-cloud-cli" -Requires-Dist: httpx<1.0.0,>=0.23.0; extra == "standard-no-fastapi-cloud-cli" -Requires-Dist: jinja2>=3.1.5; extra == "standard-no-fastapi-cloud-cli" -Requires-Dist: python-multipart>=0.0.18; extra == "standard-no-fastapi-cloud-cli" -Requires-Dist: email-validator>=2.0.0; extra == "standard-no-fastapi-cloud-cli" -Requires-Dist: uvicorn[standard]>=0.12.0; extra == "standard-no-fastapi-cloud-cli" -Requires-Dist: pydantic-settings>=2.0.0; extra == "standard-no-fastapi-cloud-cli" -Requires-Dist: pydantic-extra-types>=2.0.0; extra == "standard-no-fastapi-cloud-cli" -Provides-Extra: all -Requires-Dist: fastapi-cli[standard]>=0.0.8; extra == "all" -Requires-Dist: httpx<1.0.0,>=0.23.0; extra == "all" -Requires-Dist: jinja2>=3.1.5; extra == "all" -Requires-Dist: python-multipart>=0.0.18; extra == "all" -Requires-Dist: itsdangerous>=1.1.0; extra == "all" -Requires-Dist: pyyaml>=5.3.1; extra == "all" -Requires-Dist: email-validator>=2.0.0; extra == "all" -Requires-Dist: uvicorn[standard]>=0.12.0; extra == "all" -Requires-Dist: pydantic-settings>=2.0.0; extra == "all" -Requires-Dist: pydantic-extra-types>=2.0.0; extra == "all" -Description-Content-Type: text/markdown - -

- FastAPI -

-

- FastAPI framework, high performance, easy to learn, fast to code, ready for production -

-

- - Test - - - Coverage - - - Package version - - - Supported Python versions - -

- ---- - -**Documentation**: [https://fastapi.tiangolo.com](https://fastapi.tiangolo.com) - -**Source Code**: [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi) - ---- - -FastAPI is a modern, fast (high-performance), web framework for building APIs with Python based on standard Python type hints. - -The key features are: - -* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance). -* **Fast to code**: Increase the speed to develop features by about 200% to 300%. * -* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. * -* **Intuitive**: Great editor support. Completion everywhere. Less time debugging. -* **Easy**: Designed to be easy to use and learn. Less time reading docs. -* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. -* **Robust**: Get production-ready code. With automatic interactive documentation. -* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (previously known as Swagger) and [JSON Schema](https://json-schema.org/). - -* estimation based on tests conducted by an internal development team, building production applications. - -## Sponsors - - -### Keystone Sponsor - - - -### Gold and Silver Sponsors - - - - - - - - - - - - - - - - - - - - -[Other sponsors](https://fastapi.tiangolo.com/fastapi-people/#sponsors) - -## Opinions - -"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" - -
Kabir Khan - Microsoft (ref)
- ---- - -"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_" - -
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
- ---- - -"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_" - -
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
- ---- - -"_I’m over the moon excited about **FastAPI**. It’s so fun!_" - -
Brian Okken - [Python Bytes](https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855) podcast host (ref)
- ---- - -"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._" - -
Timothy Crosley - [Hug](https://github.com/hugapi/hug) creator (ref)
- ---- - -"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_" - -"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_" - -
Ines Montani - Matthew Honnibal - [Explosion AI](https://explosion.ai) founders - [spaCy](https://spacy.io) creators (ref) - (ref)
- ---- - -"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._" - -
Deon Pillsbury - Cisco (ref)
- ---- - -## FastAPI mini documentary - -There's a [FastAPI mini documentary](https://www.youtube.com/watch?v=mpR8ngthqiE) released at the end of 2025, you can watch it online: - -FastAPI Mini Documentary - -## **Typer**, the FastAPI of CLIs - - - -If you are building a CLI app to be used in the terminal instead of a web API, check out [**Typer**](https://typer.tiangolo.com/). - -**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀 - -## Requirements - -FastAPI stands on the shoulders of giants: - -* [Starlette](https://www.starlette.dev/) for the web parts. -* [Pydantic](https://docs.pydantic.dev/) for the data parts. - -## Installation - -Create and activate a [virtual environment](https://fastapi.tiangolo.com/virtual-environments/) and then install FastAPI: - -
- -```console -$ pip install "fastapi[standard]" - ----> 100% -``` - -
- -**Note**: Make sure you put `"fastapi[standard]"` in quotes to ensure it works in all terminals. - -## Example - -### Create it - -Create a file `main.py` with: - -```Python -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/") -def read_root(): - return {"Hello": "World"} - - -@app.get("/items/{item_id}") -def read_item(item_id: int, q: str | None = None): - return {"item_id": item_id, "q": q} -``` - -
-Or use async def... - -If your code uses `async` / `await`, use `async def`: - -```Python hl_lines="7 12" -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/") -async def read_root(): - return {"Hello": "World"} - - -@app.get("/items/{item_id}") -async def read_item(item_id: int, q: str | None = None): - return {"item_id": item_id, "q": q} -``` - -**Note**: - -If you don't know, check the _"In a hurry?"_ section about [`async` and `await` in the docs](https://fastapi.tiangolo.com/async/#in-a-hurry). - -
- -### Run it - -Run the server with: - -
- -```console -$ fastapi dev - - ╭────────── FastAPI CLI - Development mode ───────────╮ - │ │ - │ Serving at: http://127.0.0.1:8000 │ - │ │ - │ API docs: http://127.0.0.1:8000/docs │ - │ │ - │ Running in development mode, for production use: │ - │ │ - │ fastapi run │ - │ │ - ╰─────────────────────────────────────────────────────╯ - -INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [2248755] using WatchFiles -INFO: Started server process [2248757] -INFO: Waiting for application startup. -INFO: Application startup complete. -``` - -
- -
-About the command fastapi dev... - -The command `fastapi dev` reads your `main.py` file automatically, detects the **FastAPI** app in it, and starts a server using [Uvicorn](https://www.uvicorn.dev). - -By default, `fastapi dev` will start with auto-reload enabled for local development. - -You can read more about it in the [FastAPI CLI docs](https://fastapi.tiangolo.com/fastapi-cli/). - -
- -### Check it - -Open your browser at [http://127.0.0.1:8000/items/5?q=somequery](http://127.0.0.1:8000/items/5?q=somequery). - -You will see the JSON response as: - -```JSON -{"item_id": 5, "q": "somequery"} -``` - -You already created an API that: - -* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`. -* Both _paths_ take `GET` operations (also known as HTTP _methods_). -* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`. -* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`. - -### Interactive API docs - -Now go to [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). - -You will see the automatic interactive API documentation (provided by [Swagger UI](https://github.com/swagger-api/swagger-ui)): - -![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) - -### Alternative API docs - -And now, go to [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc). - -You will see the alternative automatic documentation (provided by [ReDoc](https://github.com/Rebilly/ReDoc)): - -![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) - -## Example upgrade - -Now modify the file `main.py` to receive a body from a `PUT` request. - -Declare the body using standard Python types, thanks to Pydantic. - -```Python hl_lines="2 7-10 23-25" -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - price: float - is_offer: bool | None = None - - -@app.get("/") -def read_root(): - return {"Hello": "World"} - - -@app.get("/items/{item_id}") -def read_item(item_id: int, q: str | None = None): - return {"item_id": item_id, "q": q} - - -@app.put("/items/{item_id}") -def update_item(item_id: int, item: Item): - return {"item_name": item.name, "item_id": item_id} -``` - -The `fastapi dev` server should reload automatically. - -### Interactive API docs upgrade - -Now go to [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). - -* The interactive API documentation will be automatically updated, including the new body: - -![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) - -* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API: - -![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) - -* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen: - -![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) - -### Alternative API docs upgrade - -And now, go to [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc). - -* The alternative documentation will also reflect the new query parameter and body: - -![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) - -### Recap - -In summary, you declare **once** the types of parameters, body, etc. as function parameters. - -You do that with standard modern Python types. - -You don't have to learn a new syntax, the methods or classes of a specific library, etc. - -Just standard **Python**. - -For example, for an `int`: - -```Python -item_id: int -``` - -or for a more complex `Item` model: - -```Python -item: Item -``` - -...and with that single declaration you get: - -* Editor support, including: - * Completion. - * Type checks. -* Validation of data: - * Automatic and clear errors when the data is invalid. - * Validation even for deeply nested JSON objects. -* Conversion of input data: coming from the network to Python data and types. Reading from: - * JSON. - * Path parameters. - * Query parameters. - * Cookies. - * Headers. - * Forms. - * Files. -* Conversion of output data: converting from Python data and types to network data (as JSON): - * Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc). - * `datetime` objects. - * `UUID` objects. - * Database models. - * ...and many more. -* Automatic interactive API documentation, including 2 alternative user interfaces: - * Swagger UI. - * ReDoc. - ---- - -Coming back to the previous code example, **FastAPI** will: - -* Validate that there is an `item_id` in the path for `GET` and `PUT` requests. -* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests. - * If it is not, the client will see a useful, clear error. -* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests. - * As the `q` parameter is declared with `= None`, it is optional. - * Without the `None` it would be required (as is the body in the case with `PUT`). -* For `PUT` requests to `/items/{item_id}`, read the body as JSON: - * Check that it has a required attribute `name` that should be a `str`. - * Check that it has a required attribute `price` that has to be a `float`. - * Check that it has an optional attribute `is_offer`, that should be a `bool`, if present. - * All this would also work for deeply nested JSON objects. -* Convert from and to JSON automatically. -* Document everything with OpenAPI, that can be used by: - * Interactive documentation systems. - * Automatic client code generation systems, for many languages. -* Provide 2 interactive documentation web interfaces directly. - ---- - -We just scratched the surface, but you already get the idea of how it all works. - -Try changing the line with: - -```Python - return {"item_name": item.name, "item_id": item_id} -``` - -...from: - -```Python - ... "item_name": item.name ... -``` - -...to: - -```Python - ... "item_price": item.price ... -``` - -...and see how your editor will auto-complete the attributes and know their types: - -![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) - -For a more complete example including more features, see the Tutorial - User Guide. - -**Spoiler alert**: the tutorial - user guide includes: - -* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**. -* How to set **validation constraints** as `maximum_length` or `regex`. -* A very powerful and easy to use **Dependency Injection** system. -* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth. -* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic). -* **GraphQL** integration with [Strawberry](https://strawberry.rocks) and other libraries. -* Many extra features (thanks to Starlette) as: - * **WebSockets** - * extremely easy tests based on HTTPX and `pytest` - * **CORS** - * **Cookie Sessions** - * ...and more. - -### Deploy your app (optional) - -You can optionally deploy your FastAPI app to [FastAPI Cloud](https://fastapicloud.com), go and join the waiting list if you haven't. 🚀 - -If you already have a **FastAPI Cloud** account (we invited you from the waiting list 😉), you can deploy your application with one command. - -
- -```console -$ fastapi deploy - -Deploying to FastAPI Cloud... - -✅ Deployment successful! - -🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev -``` - -
- -That's it! Now you can access your app at that URL. ✨ - -#### About FastAPI Cloud - -**[FastAPI Cloud](https://fastapicloud.com)** is built by the same author and team behind **FastAPI**. - -It streamlines the process of **building**, **deploying**, and **accessing** an API with minimal effort. - -It brings the same **developer experience** of building apps with FastAPI to **deploying** them to the cloud. 🎉 - -FastAPI Cloud is the primary sponsor and funding provider for the *FastAPI and friends* open source projects. ✨ - -#### Deploy to other cloud providers - -FastAPI is open source and based on standards. You can deploy FastAPI apps to any cloud provider you choose. - -Follow your cloud provider's guides to deploy FastAPI apps with them. 🤓 - -## Performance - -Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as [one of the fastest Python frameworks available](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7), only below Starlette and Uvicorn themselves (used internally by FastAPI). (*) - -To understand more about it, see the section [Benchmarks](https://fastapi.tiangolo.com/benchmarks/). - -## Dependencies - -FastAPI depends on Pydantic and Starlette. - -### `standard` Dependencies - -When you install FastAPI with `pip install "fastapi[standard]"` it comes with the `standard` group of optional dependencies: - -Used by Pydantic: - -* [`email-validator`](https://github.com/JoshData/python-email-validator) - for email validation. - -Used by Starlette: - -* [`httpx`](https://www.python-httpx.org) - Required if you want to use the `TestClient`. -* [`jinja2`](https://jinja.palletsprojects.com) - Required if you want to use the default template configuration. -* [`python-multipart`](https://github.com/Kludex/python-multipart) - Required if you want to support form "parsing", with `request.form()`. - -Used by FastAPI: - -* [`uvicorn`](https://www.uvicorn.dev) - for the server that loads and serves your application. This includes `uvicorn[standard]`, which includes some dependencies (e.g. `uvloop`) needed for high performance serving. -* `fastapi-cli[standard]` - to provide the `fastapi` command. - * This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to [FastAPI Cloud](https://fastapicloud.com). - -### Without `standard` Dependencies - -If you don't want to include the `standard` optional dependencies, you can install with `pip install fastapi` instead of `pip install "fastapi[standard]"`. - -### Without `fastapi-cloud-cli` - -If you want to install FastAPI with the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`. - -### Additional Optional Dependencies - -There are some additional dependencies you might want to install. - -Additional optional Pydantic dependencies: - -* [`pydantic-settings`](https://docs.pydantic.dev/latest/usage/pydantic_settings/) - for settings management. -* [`pydantic-extra-types`](https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/) - for extra types to be used with Pydantic. - -Additional optional FastAPI dependencies: - -* [`orjson`](https://github.com/ijl/orjson) - Required if you want to use `ORJSONResponse`. -* [`ujson`](https://github.com/esnme/ultrajson) - Required if you want to use `UJSONResponse`. - -## License - -This project is licensed under the terms of the MIT license. diff --git a/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/RECORD b/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/RECORD deleted file mode 100644 index efc7438..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/RECORD +++ /dev/null @@ -1,109 +0,0 @@ -../../Scripts/fastapi.exe,sha256=sGm1VGqFWBush-gHZa3u59sk8zuac1hwPV5KOWgCxtQ,108489 -fastapi-0.136.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -fastapi-0.136.1.dist-info/METADATA,sha256=4umh1Y9ITXdaOwMz5l38WTyjm34eH9lXPS1bGOoHvqw,28315 -fastapi-0.136.1.dist-info/RECORD,, -fastapi-0.136.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -fastapi-0.136.1.dist-info/WHEEL,sha256=Z36eTX6lG3PITRleSd5hAZHCcz52yg3c0JQVxKBbLW0,90 -fastapi-0.136.1.dist-info/entry_points.txt,sha256=GCf-WbIZxyGT4MUmrPGj1cOHYZoGsNPHAvNkT6hnGeA,61 -fastapi-0.136.1.dist-info/licenses/LICENSE,sha256=Tsif_IFIW5f-xYSy1KlhAy7v_oNEU4lP2cEnSQbMdE4,1086 -fastapi/.agents/skills/fastapi/SKILL.md,sha256=PIsrztMiIFHK1gMtBsrkrEDooTdiVeMI0sb0Bc8uo1U,10388 -fastapi/.agents/skills/fastapi/references/dependencies.md,sha256=KiNTXAVU6AAirx6kI0iF6Wf265hjUvDGMiIlRPvjcVc,3263 -fastapi/.agents/skills/fastapi/references/other-tools.md,sha256=EbpvhDr9TUuRmQHqaD7vflRIkmfVhHbygTpwC2mREj4,1526 -fastapi/.agents/skills/fastapi/references/streaming.md,sha256=bHaIKnwbTkd7TUVQm_uxapUnAlEG4rdvALV9koD5ypI,2581 -fastapi/__init__.py,sha256=j2bEQ82f1rv9mJqFQX0YVKVCb0v0lyu46J7CXYCCxh8,1081 -fastapi/__main__.py,sha256=bKePXLdO4SsVSM6r9SVoLickJDcR2c0cTOxZRKq26YQ,37 -fastapi/__pycache__/__init__.cpython-312.pyc,, -fastapi/__pycache__/__main__.cpython-312.pyc,, -fastapi/__pycache__/applications.cpython-312.pyc,, -fastapi/__pycache__/background.cpython-312.pyc,, -fastapi/__pycache__/cli.cpython-312.pyc,, -fastapi/__pycache__/concurrency.cpython-312.pyc,, -fastapi/__pycache__/datastructures.cpython-312.pyc,, -fastapi/__pycache__/encoders.cpython-312.pyc,, -fastapi/__pycache__/exception_handlers.cpython-312.pyc,, -fastapi/__pycache__/exceptions.cpython-312.pyc,, -fastapi/__pycache__/logger.cpython-312.pyc,, -fastapi/__pycache__/param_functions.cpython-312.pyc,, -fastapi/__pycache__/params.cpython-312.pyc,, -fastapi/__pycache__/requests.cpython-312.pyc,, -fastapi/__pycache__/responses.cpython-312.pyc,, -fastapi/__pycache__/routing.cpython-312.pyc,, -fastapi/__pycache__/sse.cpython-312.pyc,, -fastapi/__pycache__/staticfiles.cpython-312.pyc,, -fastapi/__pycache__/templating.cpython-312.pyc,, -fastapi/__pycache__/testclient.cpython-312.pyc,, -fastapi/__pycache__/types.cpython-312.pyc,, -fastapi/__pycache__/utils.cpython-312.pyc,, -fastapi/__pycache__/websockets.cpython-312.pyc,, -fastapi/_compat/__init__.py,sha256=PYOR-8vJ5va4Qjl810FcQmJbqmpyyeQMoZ9R86CeE2U,2095 -fastapi/_compat/__pycache__/__init__.cpython-312.pyc,, -fastapi/_compat/__pycache__/shared.cpython-312.pyc,, -fastapi/_compat/__pycache__/v2.cpython-312.pyc,, -fastapi/_compat/shared.py,sha256=9Jgi16IkiwhXdnIgAw325qOSaSkYE_u3o33uEUeWLPE,7045 -fastapi/_compat/v2.py,sha256=eP8dE-dYtAnnFp8FpFoa46lbfhM4XGu8OtXZn_Q2G_k,17532 -fastapi/applications.py,sha256=1XJE5LqWILmKF4IN0CnaNNAq2vR7yYhAG1JBukbGcDs,181470 -fastapi/background.py,sha256=TADzAethOAaqpVvckYuTT3c4O9N1HaFQysFCPt0MsgU,1820 -fastapi/cli.py,sha256=dhiBcPAS4lR0UQHV5eAe8S3p60KJGD-bCZC4fpliBfc,455 -fastapi/concurrency.py,sha256=xHGDEOQAA6cvFEDX46oq3r2t1Zd4sVvreaRgdIE4juM,1489 -fastapi/datastructures.py,sha256=XPugnojHc4N07eF5Xp1TTndP2gMv1fG4k-0L4Vdr7Kc,5321 -fastapi/dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -fastapi/dependencies/__pycache__/__init__.cpython-312.pyc,, -fastapi/dependencies/__pycache__/models.cpython-312.pyc,, -fastapi/dependencies/__pycache__/utils.cpython-312.pyc,, -fastapi/dependencies/models.py,sha256=XPIkEaukHaTaFz9LoeI9f_T-3otOAVkoOC113TpFbWI,7250 -fastapi/dependencies/utils.py,sha256=AhbEjTKNhVmDBqW_gWViOsrvXDO6jhebDHi-LnN_7sk,39574 -fastapi/encoders.py,sha256=5t0-MdMkNUCoGRsxjnZ9E1XRHVGBPX0f4DZRC-FSsYc,11683 -fastapi/exception_handlers.py,sha256=YVcT8Zy021VYYeecgdyh5YEUjEIHKcLspbkSf4OfbJI,1275 -fastapi/exceptions.py,sha256=fUNOBRdIsULU0TnO8aNBg3HoJeyJxXp9UV6D8wYu9lI,7453 -fastapi/logger.py,sha256=I9NNi3ov8AcqbsbC9wl1X-hdItKgYt2XTrx1f99Zpl4,54 -fastapi/middleware/__init__.py,sha256=oQDxiFVcc1fYJUOIFvphnK7pTT5kktmfL32QXpBFvvo,58 -fastapi/middleware/__pycache__/__init__.cpython-312.pyc,, -fastapi/middleware/__pycache__/asyncexitstack.cpython-312.pyc,, -fastapi/middleware/__pycache__/cors.cpython-312.pyc,, -fastapi/middleware/__pycache__/gzip.cpython-312.pyc,, -fastapi/middleware/__pycache__/httpsredirect.cpython-312.pyc,, -fastapi/middleware/__pycache__/trustedhost.cpython-312.pyc,, -fastapi/middleware/__pycache__/wsgi.cpython-312.pyc,, -fastapi/middleware/asyncexitstack.py,sha256=RKGlQpGzg3GLosqVhrxBy_NCZ9qJS7zQeNHt5Y3x-00,637 -fastapi/middleware/cors.py,sha256=ynwjWQZoc_vbhzZ3_ZXceoaSrslHFHPdoM52rXr0WUU,79 -fastapi/middleware/gzip.py,sha256=xM5PcsH8QlAimZw4VDvcmTnqQamslThsfe3CVN2voa0,79 -fastapi/middleware/httpsredirect.py,sha256=rL8eXMnmLijwVkH7_400zHri1AekfeBd6D6qs8ix950,115 -fastapi/middleware/trustedhost.py,sha256=eE5XGRxGa7c5zPnMJDGp3BxaL25k5iVQlhnv-Pk0Pss,109 -fastapi/middleware/wsgi.py,sha256=a_FMDoeTwcdig9wdAGumIH82oDFfuj4pxtQxLbAw2Ns,107 -fastapi/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -fastapi/openapi/__pycache__/__init__.cpython-312.pyc,, -fastapi/openapi/__pycache__/constants.cpython-312.pyc,, -fastapi/openapi/__pycache__/docs.cpython-312.pyc,, -fastapi/openapi/__pycache__/models.cpython-312.pyc,, -fastapi/openapi/__pycache__/utils.cpython-312.pyc,, -fastapi/openapi/constants.py,sha256=adGzmis1L1HJRTE3kJ5fmHS_Noq6tIY6pWv_SFzoFDU,153 -fastapi/openapi/docs.py,sha256=PcjH0Sn-yp97O0exXincG8epsY7ATyJC5662bK1DRao,12425 -fastapi/openapi/models.py,sha256=0RCAgM78AjuHwR0Iq3fT0HcElYf2s7lOusCFUP6S6iQ,14591 -fastapi/openapi/utils.py,sha256=1oJHBj73ORe7hpNmw5xnxiS4BqfQIHGb_Ue4VyKXFJ0,26262 -fastapi/param_functions.py,sha256=4fTCVlvEDbAQr7gvWYkOX8hktdl2Iwk-kv4FaTz7P8w,69596 -fastapi/params.py,sha256=ONyxTvnFNVrJ_mCAeq_WRYoqIpj37az8xgGwcjO1O9E,26275 -fastapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -fastapi/requests.py,sha256=zayepKFcienBllv3snmWI20Gk0oHNVLU4DDhqXBb4LU,142 -fastapi/responses.py,sha256=_9XSuCgO4Jufo2bm0WtTXrYlzH9Bcjr_SWftISCxvcc,4194 -fastapi/routing.py,sha256=es9Ba1E1jHUh9E0k18trmj-ya1IkfLpTr96qagEP2QE,197632 -fastapi/security/__init__.py,sha256=bO8pNmxqVRXUjfl2mOKiVZLn0FpBQ61VUYVjmppnbJw,881 -fastapi/security/__pycache__/__init__.cpython-312.pyc,, -fastapi/security/__pycache__/api_key.cpython-312.pyc,, -fastapi/security/__pycache__/base.cpython-312.pyc,, -fastapi/security/__pycache__/http.cpython-312.pyc,, -fastapi/security/__pycache__/oauth2.cpython-312.pyc,, -fastapi/security/__pycache__/open_id_connect_url.cpython-312.pyc,, -fastapi/security/__pycache__/utils.cpython-312.pyc,, -fastapi/security/api_key.py,sha256=4CNLNVAStOsMhytH9C5EOUEOZrtLg_IpMQS_HcRDP4M,9793 -fastapi/security/base.py,sha256=dl4pvbC-RxjfbWgPtCWd8MVU-7CB2SZ22rJDXVCXO6c,141 -fastapi/security/http.py,sha256=Z0xALDqwgJZRAaDs40Sa68rAnjFzEL99UEmO5PJzTKA,13410 -fastapi/security/oauth2.py,sha256=sSqW4tbvoHaWNld46TYatta5rgFfjod4LhxmedXzkI8,24178 -fastapi/security/open_id_connect_url.py,sha256=V8WLPEsEq_WJlIjPwJO2vCoJWGLu-VTt1-N2H7aV-D4,3136 -fastapi/security/utils.py,sha256=E9YIoez-H2k1oBLEdxqJEi8sV1umunJYKjQHvZG3FRY,261 -fastapi/sse.py,sha256=VXJU0RtvW26JDKaeQwz3wUA2rwj50Vos6l1VJ04AihM,6394 -fastapi/staticfiles.py,sha256=iirGIt3sdY2QZXd36ijs3Cj-T0FuGFda3cd90kM9Ikw,69 -fastapi/templating.py,sha256=4zsuTWgcjcEainMJFAlW6-gnslm6AgOS1SiiDWfmQxk,76 -fastapi/testclient.py,sha256=nBvaAmX66YldReJNZXPOk1sfuo2Q6hs8bOvIaCep6LQ,66 -fastapi/types.py,sha256=g2tD842BUHC2C3_P8P06albQ4MhCb9RybrSmp5rODgU,438 -fastapi/utils.py,sha256=DX0VrnMwfVsZxRz8IitQ42c2---fDzmFZkeRMZR2UMo,4341 -fastapi/websockets.py,sha256=419uncYObEKZG0YcrXscfQQYLSWoE10jqxVMetGdR98,222 diff --git a/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/REQUESTED b/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/REQUESTED deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/WHEEL b/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/WHEEL deleted file mode 100644 index 82d3df6..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: pdm-backend (2.4.8) -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/entry_points.txt b/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/entry_points.txt deleted file mode 100644 index b81849e..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/entry_points.txt +++ /dev/null @@ -1,5 +0,0 @@ -[console_scripts] -fastapi = fastapi.cli:main - -[gui_scripts] - diff --git a/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/licenses/LICENSE b/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/licenses/LICENSE deleted file mode 100644 index 3e92463..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi-0.136.1.dist-info/licenses/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2018 Sebastián Ramírez - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/notification-service/venv/Lib/site-packages/fastapi/.agents/skills/fastapi/SKILL.md b/notification-service/venv/Lib/site-packages/fastapi/.agents/skills/fastapi/SKILL.md deleted file mode 100644 index 48cfdab..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/.agents/skills/fastapi/SKILL.md +++ /dev/null @@ -1,436 +0,0 @@ ---- -name: fastapi -description: FastAPI best practices and conventions. Use when working with FastAPI APIs and Pydantic models for them. Keeps FastAPI code clean and up to date with the latest features and patterns, updated with new versions. Write new code or refactor and update old code. ---- - -# FastAPI - -Official FastAPI skill to write code with best practices, keeping up to date with new versions and features. - -## Use the `fastapi` CLI - -Run the development server on localhost with reload: - -```bash -fastapi dev -``` - - -Run the production server: - -```bash -fastapi run -``` - -### Add an entrypoint in `pyproject.toml` - -FastAPI CLI will read the entrypoint in `pyproject.toml` to know where the FastAPI app is declared. - -```toml -[tool.fastapi] -entrypoint = "my_app.main:app" -``` - -### Use `fastapi` with a path - -When adding the entrypoint to `pyproject.toml` is not possible, or the user explicitly asks not to, or it's running an independent small app, you can pass the app file path to the `fastapi` command: - -```bash -fastapi dev my_app/main.py -``` - -Prefer to set the entrypoint in `pyproject.toml` when possible. - -## Use `Annotated` - -Always prefer the `Annotated` style for parameter and dependency declarations. - -It keeps the function signatures working in other contexts, respects the types, allows reusability. - -### In Parameter Declarations - -Use `Annotated` for parameter declarations, including `Path`, `Query`, `Header`, etc.: - -```python -from typing import Annotated - -from fastapi import FastAPI, Path, Query - -app = FastAPI() - - -@app.get("/items/{item_id}") -async def read_item( - item_id: Annotated[int, Path(ge=1, description="The item ID")], - q: Annotated[str | None, Query(max_length=50)] = None, -): - return {"message": "Hello World"} -``` - -instead of: - -```python -# DO NOT DO THIS -@app.get("/items/{item_id}") -async def read_item( - item_id: int = Path(ge=1, description="The item ID"), - q: str | None = Query(default=None, max_length=50), -): - return {"message": "Hello World"} -``` - -### For Dependencies - -Use `Annotated` for dependencies with `Depends()`. - -Unless asked not to, create a new type alias for the dependency to allow re-using it. - -```python -from typing import Annotated - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -def get_current_user(): - return {"username": "johndoe"} - - -CurrentUserDep = Annotated[dict, Depends(get_current_user)] - - -@app.get("/items/") -async def read_item(current_user: CurrentUserDep): - return {"message": "Hello World"} -``` - -instead of: - -```python -# DO NOT DO THIS -@app.get("/items/") -async def read_item(current_user: dict = Depends(get_current_user)): - return {"message": "Hello World"} -``` - -## Do not use Ellipsis for *path operations* or Pydantic models - -Do not use `...` as a default value for required parameters, it's not needed and not recommended. - -Do this, without Ellipsis (`...`): - -```python -from typing import Annotated - -from fastapi import FastAPI, Query -from pydantic import BaseModel, Field - - -class Item(BaseModel): - name: str - description: str | None = None - price: float = Field(gt=0) - - -app = FastAPI() - - -@app.post("/items/") -async def create_item(item: Item, project_id: Annotated[int, Query()]): ... -``` - -instead of this: - -```python -# DO NOT DO THIS -class Item(BaseModel): - name: str = ... - description: str | None = None - price: float = Field(..., gt=0) - - -app = FastAPI() - - -@app.post("/items/") -async def create_item(item: Item, project_id: Annotated[int, Query(...)]): ... -``` - -## Return Type or Response Model - -When possible, include a return type. It will be used to validate, filter, document, and serialize the response. - -```python -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: str | None = None - - -@app.get("/items/me") -async def get_item() -> Item: - return Item(name="Plumbus", description="All-purpose home device") -``` - -**Important**: Return types or response models are what filter data ensuring no sensitive information is exposed. And they are used to serialize data with Pydantic (in Rust), this is the main idea that can increase response performance. - -The return type doesn't have to be a Pydantic model, it could be a different type, like a list of integers, or a dict, etc. - -### When to use `response_model` instead - -If the return type is not the same as the type that you want to use to validate, filter, or serialize, use the `response_model` parameter on the decorator instead. - -```python -from typing import Any - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: str | None = None - - -@app.get("/items/me", response_model=Item) -async def get_item() -> Any: - return {"name": "Foo", "description": "A very nice Item"} -``` - -This can be particularly useful when filtering data to expose only the public fields and avoid exposing sensitive information. - -```python -from typing import Any - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class InternalItem(BaseModel): - name: str - description: str | None = None - secret_key: str - - -class Item(BaseModel): - name: str - description: str | None = None - - -@app.get("/items/me", response_model=Item) -async def get_item() -> Any: - item = InternalItem( - name="Foo", description="A very nice Item", secret_key="supersecret" - ) - return item -``` - -## Performance - -Do not use `ORJSONResponse` or `UJSONResponse`, they are deprecated. - -Instead, declare a return type or response model. Pydantic will handle the data serialization on the Rust side. - -## Including Routers - -When declaring routers, prefer to add router level parameters like prefix, tags, etc. to the router itself, instead of in `include_router()`. - -Do this: - -```python -from fastapi import APIRouter, FastAPI - -app = FastAPI() - -router = APIRouter(prefix="/items", tags=["items"]) - - -@router.get("/") -async def list_items(): - return [] - - -# In main.py -app.include_router(router) -``` - -instead of this: - -```python -# DO NOT DO THIS -from fastapi import APIRouter, FastAPI - -app = FastAPI() - -router = APIRouter() - - -@router.get("/") -async def list_items(): - return [] - - -# In main.py -app.include_router(router, prefix="/items", tags=["items"]) -``` - -There could be exceptions, but try to follow this convention. - -Apply shared dependencies at the router level via `dependencies=[Depends(...)]`. - -## Dependency Injection - -See [the dependency injection reference](references/dependencies.md) for detailed patterns including `yield` with `scope`, and class dependencies. - -Use dependencies when the logic can't be declared in Pydantic validation, depends on external resources, needs cleanup (with `yield`), or is shared across endpoints. - -Apply shared dependencies at the router level via `dependencies=[Depends(...)]`. - -## Async vs Sync *path operations* - -Use `async` *path operations* only when fully certain that the logic called inside is compatible with async and await (it's called with `await`) or that doesn't block. - -```python -from fastapi import FastAPI - -app = FastAPI() - - -# Use async def when calling async code -@app.get("/async-items/") -async def read_async_items(): - data = await some_async_library.fetch_items() - return data - - -# Use plain def when calling blocking/sync code or when in doubt -@app.get("/items/") -def read_items(): - data = some_blocking_library.fetch_items() - return data -``` - -In case of doubt, or by default, use regular `def` functions, those will be run in a threadpool so they don't block the event loop. - -The same rules apply to dependencies. - -Make sure blocking code is not run inside of `async` functions. The logic will work, but will damage the performance heavily. - -When needing to mix blocking and async code, see Asyncer in [the other tools reference](references/other-tools.md). - -## Streaming (JSON Lines, SSE, bytes) - -See [the streaming reference](references/streaming.md) for JSON Lines, Server-Sent Events (`EventSourceResponse`, `ServerSentEvent`), and byte streaming (`StreamingResponse`) patterns. - -## Tooling - -See [the other tools reference](references/other-tools.md) for details on uv, Ruff, ty for package management, linting, type checking, formatting, etc. - -## Other Libraries - -See [the other tools reference](references/other-tools.md) for details on other libraries: - -* Asyncer for handling async and await, concurrency, mixing async and blocking code, prefer it over AnyIO or asyncio. -* SQLModel for working with SQL databases, prefer it over SQLAlchemy. -* HTTPX for interacting with HTTP (other APIs), prefer it over Requests. - -## Do not use Pydantic RootModels - -Do not use Pydantic `RootModel`, instead use regular type annotations with `Annotated` and Pydantic validation utilities. - -For example, for a list with validations you could do: - -```python -from typing import Annotated - -from fastapi import Body, FastAPI -from pydantic import Field - -app = FastAPI() - - -@app.post("/items/") -async def create_items(items: Annotated[list[int], Field(min_length=1), Body()]): - return items -``` - -instead of: - -```python -# DO NOT DO THIS -from typing import Annotated - -from fastapi import FastAPI -from pydantic import Field, RootModel - -app = FastAPI() - - -class ItemList(RootModel[Annotated[list[int], Field(min_length=1)]]): - pass - - -@app.post("/items/") -async def create_items(items: ItemList): - return items - -``` - -FastAPI supports these type annotations and will create a Pydantic `TypeAdapter` for them, so that types can work as normally and there's no need for the custom logic and types in RootModels. - -## Use one HTTP operation per function - -Don't mix HTTP operations in a single function, having one function per HTTP operation helps separate concerns and organize the code. - -Do this: - -```python -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - - -@app.get("/items/") -async def list_items(): - return [] - - -@app.post("/items/") -async def create_item(item: Item): - return item -``` - -instead of this: - -```python -# DO NOT DO THIS -from fastapi import FastAPI, Request -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - - -@app.api_route("/items/", methods=["GET", "POST"]) -async def handle_items(request: Request): - if request.method == "GET": - return [] -``` diff --git a/notification-service/venv/Lib/site-packages/fastapi/.agents/skills/fastapi/references/dependencies.md b/notification-service/venv/Lib/site-packages/fastapi/.agents/skills/fastapi/references/dependencies.md deleted file mode 100644 index ca70909..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/.agents/skills/fastapi/references/dependencies.md +++ /dev/null @@ -1,142 +0,0 @@ -# Dependency Injection - -Use dependencies when: - -* They can't be declared in Pydantic validation and require additional logic -* The logic depends on external resources or could block in any other way -* Other dependencies need their results (it's a sub-dependency) -* The logic can be shared by multiple endpoints to do things like error early, authentication, etc. -* They need to handle cleanup (e.g., DB sessions, file handles), using dependencies with `yield` -* Their logic needs input data from the request, like headers, query parameters, etc. - -## Dependencies with `yield` and `scope` - -When using dependencies with `yield`, they can have a `scope` that defines when the exit code is run. - -Use the default scope `"request"` to run the exit code after the response is sent back. - -```python -from typing import Annotated - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -def get_db(): - db = DBSession() - try: - yield db - finally: - db.close() - - -DBDep = Annotated[DBSession, Depends(get_db)] - - -@app.get("/items/") -async def read_items(db: DBDep): - return db.query(Item).all() -``` - -Use the scope `"function"` when they should run the exit code after the response data is generated but before the response is sent back to the client. - -```python -from typing import Annotated - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -def get_username(): - try: - yield "Rick" - finally: - print("Cleanup up before response is sent") - -UserNameDep = Annotated[str, Depends(get_username, scope="function")] - -@app.get("/users/me") -def get_user_me(username: UserNameDep): - return username -``` - -## Class Dependencies - -Avoid creating class dependencies when possible. - -If a class is needed, instead create a regular function dependency that returns a class instance. - -Do this: - -```python -from dataclasses import dataclass -from typing import Annotated - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -@dataclass -class DatabasePaginator: - offset: int = 0 - limit: int = 100 - q: str | None = None - - def get_page(self) -> dict: - # Simulate a page of data - return { - "offset": self.offset, - "limit": self.limit, - "q": self.q, - "items": [], - } - - -def get_db_paginator( - offset: int = 0, limit: int = 100, q: str | None = None -) -> DatabasePaginator: - return DatabasePaginator(offset=offset, limit=limit, q=q) - - -PaginatorDep = Annotated[DatabasePaginator, Depends(get_db_paginator)] - - -@app.get("/items/") -async def read_items(paginator: PaginatorDep): - return paginator.get_page() -``` - -instead of this: - -```python -# DO NOT DO THIS -from typing import Annotated - -from fastapi import Depends, FastAPI - -app = FastAPI() - - -class DatabasePaginator: - def __init__(self, offset: int = 0, limit: int = 100, q: str | None = None): - self.offset = offset - self.limit = limit - self.q = q - - def get_page(self) -> dict: - # Simulate a page of data - return { - "offset": self.offset, - "limit": self.limit, - "q": self.q, - "items": [], - } - - -@app.get("/items/") -async def read_items(paginator: Annotated[DatabasePaginator, Depends()]): - return paginator.get_page() -``` diff --git a/notification-service/venv/Lib/site-packages/fastapi/.agents/skills/fastapi/references/other-tools.md b/notification-service/venv/Lib/site-packages/fastapi/.agents/skills/fastapi/references/other-tools.md deleted file mode 100644 index 58b19d0..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/.agents/skills/fastapi/references/other-tools.md +++ /dev/null @@ -1,76 +0,0 @@ -# Other Tools - -## uv - -If uv is available, use it to manage dependencies. - -## Ruff - -If Ruff is available, use it to lint and format the code. Consider enabling the FastAPI rules. - -## ty - -If ty is available, use it to check types. - -## Asyncer - -When needing to run blocking code inside of async functions, or async code inside of blocking functions, suggest using Asyncer. - -Prefer it over AnyIO or asyncio. - -Install: - -```bash -uv add asyncer -``` - -Run blocking sync code inside of async with `asyncify()`: - -```python -from asyncer import asyncify -from fastapi import FastAPI - -app = FastAPI() - - -def do_blocking_work(name: str) -> str: - # Some blocking I/O operation - return f"Hello {name}" - - -@app.get("/items/") -async def read_items(): - result = await asyncify(do_blocking_work)(name="World") - return {"message": result} -``` - -And run async code inside of blocking sync code with `syncify()`: - -```python -from asyncer import syncify -from fastapi import FastAPI - -app = FastAPI() - - -async def do_async_work(name: str) -> str: - return f"Hello {name}" - - -@app.get("/items/") -def read_items(): - result = syncify(do_async_work)(name="World") - return {"message": result} -``` - -## SQLModel for SQL databases - -When working with SQL databases, prefer using SQLModel as it is integrated with Pydantic and will allow declaring data validation with the same models. - -Prefer it over SQLAlchemy. - -## HTTPX - -Use HTTPX for handling HTTP communication (e.g. with other APIs). It support sync and async usage. - -Prefer it over Requests. diff --git a/notification-service/venv/Lib/site-packages/fastapi/.agents/skills/fastapi/references/streaming.md b/notification-service/venv/Lib/site-packages/fastapi/.agents/skills/fastapi/references/streaming.md deleted file mode 100644 index 0832eed..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/.agents/skills/fastapi/references/streaming.md +++ /dev/null @@ -1,105 +0,0 @@ -# Streaming - -## Stream JSON Lines - -To stream JSON Lines, declare the return type and use `yield` to return the data. - -```python -@app.get("/items/stream") -async def stream_items() -> AsyncIterable[Item]: - for item in items: - yield item -``` - -## Server-Sent Events (SSE) - -To stream Server-Sent Events, use `response_class=EventSourceResponse` and `yield` items from the endpoint. - -Plain objects are automatically JSON-serialized as `data:` fields, declare the return type so the serialization is done by Pydantic: - -```python -from collections.abc import AsyncIterable - -from fastapi import FastAPI -from fastapi.sse import EventSourceResponse -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - price: float - - -@app.get("/items/stream", response_class=EventSourceResponse) -async def stream_items() -> AsyncIterable[Item]: - yield Item(name="Plumbus", price=32.99) - yield Item(name="Portal Gun", price=999.99) -``` - -For full control over SSE fields (`event`, `id`, `retry`, `comment`), yield `ServerSentEvent` instances: - -```python -from collections.abc import AsyncIterable - -from fastapi import FastAPI -from fastapi.sse import EventSourceResponse, ServerSentEvent - -app = FastAPI() - - -@app.get("/events", response_class=EventSourceResponse) -async def stream_events() -> AsyncIterable[ServerSentEvent]: - yield ServerSentEvent(data={"status": "started"}, event="status", id="1") - yield ServerSentEvent(data={"progress": 50}, event="progress", id="2") -``` - -Use `raw_data` instead of `data` to send pre-formatted strings without JSON encoding: - -```python -yield ServerSentEvent(raw_data="plain text line", event="log") -``` - -## Stream bytes - -To stream bytes, declare a `response_class=` of `StreamingResponse` or a sub-class, and use `yield` to return the data. - -```python -from fastapi import FastAPI -from fastapi.responses import StreamingResponse -from app.utils import read_image - -app = FastAPI() - - -class PNGStreamingResponse(StreamingResponse): - media_type = "image/png" - -@app.get("/image", response_class=PNGStreamingResponse) -def stream_image_no_async_no_annotation(): - with read_image() as image_file: - yield from image_file -``` - -prefer this over returning a `StreamingResponse` directly: - -```python -# DO NOT DO THIS - -import anyio -from fastapi import FastAPI -from fastapi.responses import StreamingResponse -from app.utils import read_image - -app = FastAPI() - - -class PNGStreamingResponse(StreamingResponse): - media_type = "image/png" - - -@app.get("/") -async def main(): - return PNGStreamingResponse(read_image()) -``` diff --git a/notification-service/venv/Lib/site-packages/fastapi/__init__.py b/notification-service/venv/Lib/site-packages/fastapi/__init__.py deleted file mode 100644 index f07511a..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -"""FastAPI framework, high performance, easy to learn, fast to code, ready for production""" - -__version__ = "0.136.1" - -from starlette import status as status - -from .applications import FastAPI as FastAPI -from .background import BackgroundTasks as BackgroundTasks -from .datastructures import UploadFile as UploadFile -from .exceptions import HTTPException as HTTPException -from .exceptions import WebSocketException as WebSocketException -from .param_functions import Body as Body -from .param_functions import Cookie as Cookie -from .param_functions import Depends as Depends -from .param_functions import File as File -from .param_functions import Form as Form -from .param_functions import Header as Header -from .param_functions import Path as Path -from .param_functions import Query as Query -from .param_functions import Security as Security -from .requests import Request as Request -from .responses import Response as Response -from .routing import APIRouter as APIRouter -from .websockets import WebSocket as WebSocket -from .websockets import WebSocketDisconnect as WebSocketDisconnect diff --git a/notification-service/venv/Lib/site-packages/fastapi/__main__.py b/notification-service/venv/Lib/site-packages/fastapi/__main__.py deleted file mode 100644 index fc36465..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/__main__.py +++ /dev/null @@ -1,3 +0,0 @@ -from fastapi.cli import main - -main() diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 4b2eca5..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/__main__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/__main__.cpython-312.pyc deleted file mode 100644 index 50a86b6..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/__main__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/applications.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/applications.cpython-312.pyc deleted file mode 100644 index dea77a3..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/applications.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/background.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/background.cpython-312.pyc deleted file mode 100644 index 615b78e..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/background.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/cli.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/cli.cpython-312.pyc deleted file mode 100644 index b43e13c..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/cli.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/concurrency.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/concurrency.cpython-312.pyc deleted file mode 100644 index 4df8435..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/concurrency.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/datastructures.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/datastructures.cpython-312.pyc deleted file mode 100644 index 2c7e857..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/datastructures.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/encoders.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/encoders.cpython-312.pyc deleted file mode 100644 index 43f2d5a..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/encoders.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/exception_handlers.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/exception_handlers.cpython-312.pyc deleted file mode 100644 index 20c3f24..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/exception_handlers.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/exceptions.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/exceptions.cpython-312.pyc deleted file mode 100644 index a3a35a0..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/exceptions.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/logger.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/logger.cpython-312.pyc deleted file mode 100644 index 09167ad..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/logger.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/param_functions.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/param_functions.cpython-312.pyc deleted file mode 100644 index e4eeb2f..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/param_functions.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/params.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/params.cpython-312.pyc deleted file mode 100644 index b0f37ed..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/params.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/requests.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/requests.cpython-312.pyc deleted file mode 100644 index dea7771..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/requests.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/responses.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/responses.cpython-312.pyc deleted file mode 100644 index 8638073..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/responses.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/routing.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/routing.cpython-312.pyc deleted file mode 100644 index 37d7442..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/routing.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/sse.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/sse.cpython-312.pyc deleted file mode 100644 index 3dc642c..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/sse.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/staticfiles.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/staticfiles.cpython-312.pyc deleted file mode 100644 index b119c4b..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/staticfiles.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/templating.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/templating.cpython-312.pyc deleted file mode 100644 index f189597..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/templating.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/testclient.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/testclient.cpython-312.pyc deleted file mode 100644 index 27db9e9..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/testclient.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/types.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/types.cpython-312.pyc deleted file mode 100644 index defa0b6..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/types.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/utils.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/utils.cpython-312.pyc deleted file mode 100644 index 5560ded..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/utils.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/websockets.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/__pycache__/websockets.cpython-312.pyc deleted file mode 100644 index daeeb72..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/__pycache__/websockets.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/_compat/__init__.py b/notification-service/venv/Lib/site-packages/fastapi/_compat/__init__.py deleted file mode 100644 index 4581c38..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/_compat/__init__.py +++ /dev/null @@ -1,40 +0,0 @@ -from .shared import PYDANTIC_VERSION_MINOR_TUPLE as PYDANTIC_VERSION_MINOR_TUPLE -from .shared import annotation_is_pydantic_v1 as annotation_is_pydantic_v1 -from .shared import field_annotation_is_scalar as field_annotation_is_scalar -from .shared import ( - field_annotation_is_scalar_sequence as field_annotation_is_scalar_sequence, -) -from .shared import field_annotation_is_sequence as field_annotation_is_sequence -from .shared import ( - is_bytes_or_nonable_bytes_annotation as is_bytes_or_nonable_bytes_annotation, -) -from .shared import is_bytes_sequence_annotation as is_bytes_sequence_annotation -from .shared import is_pydantic_v1_model_instance as is_pydantic_v1_model_instance -from .shared import ( - is_uploadfile_or_nonable_uploadfile_annotation as is_uploadfile_or_nonable_uploadfile_annotation, -) -from .shared import ( - is_uploadfile_sequence_annotation as is_uploadfile_sequence_annotation, -) -from .shared import lenient_issubclass as lenient_issubclass -from .shared import sequence_types as sequence_types -from .shared import value_is_sequence as value_is_sequence -from .v2 import ModelField as ModelField -from .v2 import PydanticSchemaGenerationError as PydanticSchemaGenerationError -from .v2 import RequiredParam as RequiredParam -from .v2 import Undefined as Undefined -from .v2 import Url as Url -from .v2 import copy_field_info as copy_field_info -from .v2 import create_body_model as create_body_model -from .v2 import evaluate_forwardref as evaluate_forwardref -from .v2 import get_cached_model_fields as get_cached_model_fields -from .v2 import get_definitions as get_definitions -from .v2 import get_flat_models_from_fields as get_flat_models_from_fields -from .v2 import get_missing_field_error as get_missing_field_error -from .v2 import get_model_name_map as get_model_name_map -from .v2 import get_schema_from_model_field as get_schema_from_model_field -from .v2 import is_scalar_field as is_scalar_field -from .v2 import serialize_sequence_value as serialize_sequence_value -from .v2 import ( - with_info_plain_validator_function as with_info_plain_validator_function, -) diff --git a/notification-service/venv/Lib/site-packages/fastapi/_compat/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/_compat/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 558b3ab..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/_compat/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/_compat/__pycache__/shared.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/_compat/__pycache__/shared.cpython-312.pyc deleted file mode 100644 index 37f5830..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/_compat/__pycache__/shared.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/_compat/__pycache__/v2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/_compat/__pycache__/v2.cpython-312.pyc deleted file mode 100644 index 2656542..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/_compat/__pycache__/v2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/_compat/shared.py b/notification-service/venv/Lib/site-packages/fastapi/_compat/shared.py deleted file mode 100644 index 9d76dab..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/_compat/shared.py +++ /dev/null @@ -1,214 +0,0 @@ -import types -import typing -import warnings -from collections import deque -from collections.abc import Mapping, Sequence -from dataclasses import is_dataclass -from typing import ( - Annotated, - Any, - TypeGuard, - TypeVar, - Union, - get_args, - get_origin, -) - -from fastapi.types import UnionType -from pydantic import BaseModel -from pydantic.version import VERSION as PYDANTIC_VERSION -from starlette.datastructures import UploadFile - -_T = TypeVar("_T") - -# Copy from Pydantic: pydantic/_internal/_typing_extra.py -WithArgsTypes: tuple[Any, ...] = ( - typing._GenericAlias, # type: ignore[attr-defined] - types.GenericAlias, - types.UnionType, -) # pyright: ignore[reportAttributeAccessIssue] - -PYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(".")[:2]) - - -sequence_annotation_to_type = { - Sequence: list, - list: list, - tuple: tuple, - set: set, - frozenset: frozenset, - deque: deque, -} - -sequence_types: tuple[type[Any], ...] = tuple(sequence_annotation_to_type.keys()) - - -# Copy of Pydantic: pydantic/_internal/_utils.py with added TypeGuard -def lenient_issubclass( - cls: Any, class_or_tuple: type[_T] | tuple[type[_T], ...] | None -) -> TypeGuard[type[_T]]: - try: - return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type] - except TypeError: # pragma: no cover - if isinstance(cls, WithArgsTypes): - return False - raise # pragma: no cover - - -def _annotation_is_sequence(annotation: type[Any] | None) -> bool: - if lenient_issubclass(annotation, (str, bytes)): - return False - return lenient_issubclass(annotation, sequence_types) - - -def field_annotation_is_sequence(annotation: type[Any] | None) -> bool: - origin = get_origin(annotation) - if origin is Union or origin is UnionType: - for arg in get_args(annotation): - if field_annotation_is_sequence(arg): - return True - return False - return _annotation_is_sequence(annotation) or _annotation_is_sequence( - get_origin(annotation) - ) - - -def value_is_sequence(value: Any) -> bool: - return isinstance(value, sequence_types) and not isinstance(value, (str, bytes)) - - -def _annotation_is_complex(annotation: type[Any] | None) -> bool: - return ( - lenient_issubclass(annotation, (BaseModel, Mapping, UploadFile)) - or _annotation_is_sequence(annotation) - or is_dataclass(annotation) - ) - - -def field_annotation_is_complex(annotation: type[Any] | None) -> bool: - origin = get_origin(annotation) - if origin is Union or origin is UnionType: - return any(field_annotation_is_complex(arg) for arg in get_args(annotation)) - - if origin is Annotated: - return field_annotation_is_complex(get_args(annotation)[0]) - - return ( - _annotation_is_complex(annotation) - or _annotation_is_complex(origin) - or hasattr(origin, "__pydantic_core_schema__") - or hasattr(origin, "__get_pydantic_core_schema__") - ) - - -def field_annotation_is_scalar(annotation: Any) -> bool: - # handle Ellipsis here to make tuple[int, ...] work nicely - return annotation is Ellipsis or not field_annotation_is_complex(annotation) - - -def field_annotation_is_scalar_sequence(annotation: type[Any] | None) -> bool: - origin = get_origin(annotation) - if origin is Union or origin is UnionType: - at_least_one_scalar_sequence = False - for arg in get_args(annotation): - if field_annotation_is_scalar_sequence(arg): - at_least_one_scalar_sequence = True - continue - elif not field_annotation_is_scalar(arg): - return False - return at_least_one_scalar_sequence - return field_annotation_is_sequence(annotation) and all( - field_annotation_is_scalar(sub_annotation) - for sub_annotation in get_args(annotation) - ) - - -def is_bytes_or_nonable_bytes_annotation(annotation: Any) -> bool: - if lenient_issubclass(annotation, bytes): - return True - origin = get_origin(annotation) - if origin is Union or origin is UnionType: - for arg in get_args(annotation): - if lenient_issubclass(arg, bytes): - return True - return False - - -def is_uploadfile_or_nonable_uploadfile_annotation(annotation: Any) -> bool: - if lenient_issubclass(annotation, UploadFile): - return True - origin = get_origin(annotation) - if origin is Union or origin is UnionType: - for arg in get_args(annotation): - if lenient_issubclass(arg, UploadFile): - return True - return False - - -def is_bytes_sequence_annotation(annotation: Any) -> bool: - origin = get_origin(annotation) - if origin is Union or origin is UnionType: - at_least_one = False - for arg in get_args(annotation): - if is_bytes_sequence_annotation(arg): - at_least_one = True - continue - return at_least_one - return field_annotation_is_sequence(annotation) and all( - is_bytes_or_nonable_bytes_annotation(sub_annotation) - for sub_annotation in get_args(annotation) - ) - - -def is_uploadfile_sequence_annotation(annotation: Any) -> bool: - origin = get_origin(annotation) - if origin is Union or origin is UnionType: - at_least_one = False - for arg in get_args(annotation): - if is_uploadfile_sequence_annotation(arg): - at_least_one = True - continue - return at_least_one - return field_annotation_is_sequence(annotation) and all( - is_uploadfile_or_nonable_uploadfile_annotation(sub_annotation) - for sub_annotation in get_args(annotation) - ) - - -def is_pydantic_v1_model_instance(obj: Any) -> bool: - # TODO: remove this function once the required version of Pydantic fully - # removes pydantic.v1 - try: - with warnings.catch_warnings(): - warnings.simplefilter("ignore", UserWarning) - from pydantic import v1 - except ImportError: # pragma: no cover - return False - return isinstance(obj, v1.BaseModel) - - -def is_pydantic_v1_model_class(cls: Any) -> bool: - # TODO: remove this function once the required version of Pydantic fully - # removes pydantic.v1 - try: - with warnings.catch_warnings(): - warnings.simplefilter("ignore", UserWarning) - from pydantic import v1 - except ImportError: # pragma: no cover - return False - return lenient_issubclass(cls, v1.BaseModel) - - -def annotation_is_pydantic_v1(annotation: Any) -> bool: - if is_pydantic_v1_model_class(annotation): - return True - origin = get_origin(annotation) - if origin is Union or origin is UnionType: - for arg in get_args(annotation): - if is_pydantic_v1_model_class(arg): - return True - if field_annotation_is_sequence(annotation): - for sub_annotation in get_args(annotation): - if annotation_is_pydantic_v1(sub_annotation): - return True - return False diff --git a/notification-service/venv/Lib/site-packages/fastapi/_compat/v2.py b/notification-service/venv/Lib/site-packages/fastapi/_compat/v2.py deleted file mode 100644 index 3b64fba..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/_compat/v2.py +++ /dev/null @@ -1,493 +0,0 @@ -import re -import warnings -from collections.abc import Sequence -from copy import copy -from dataclasses import dataclass, is_dataclass -from enum import Enum -from functools import lru_cache -from typing import ( - Annotated, - Any, - Literal, - Union, - cast, - get_args, - get_origin, -) - -from fastapi._compat import lenient_issubclass, shared -from fastapi.openapi.constants import REF_TEMPLATE -from fastapi.types import IncEx, ModelNameMap, UnionType -from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, create_model -from pydantic import PydanticSchemaGenerationError as PydanticSchemaGenerationError -from pydantic import PydanticUndefinedAnnotation as PydanticUndefinedAnnotation -from pydantic import ValidationError as ValidationError -from pydantic._internal import _typing_extra as _pydantic_typing_extra -from pydantic._internal._schema_generation_shared import ( # type: ignore[attr-defined] # ty: ignore[unused-ignore-comment] - GetJsonSchemaHandler as GetJsonSchemaHandler, -) -from pydantic.fields import FieldInfo as FieldInfo -from pydantic.json_schema import GenerateJsonSchema as _GenerateJsonSchema -from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue -from pydantic_core import CoreSchema as CoreSchema -from pydantic_core import PydanticUndefined -from pydantic_core import Url as Url -from pydantic_core.core_schema import ( - with_info_plain_validator_function as with_info_plain_validator_function, -) - -RequiredParam = PydanticUndefined -Undefined = PydanticUndefined - - -def evaluate_forwardref( - value: Any, - globalns: dict[str, Any] | None = None, - localns: dict[str, Any] | None = None, -) -> Any: - # eval_type_lenient has been deprecated since Pydantic v2.10.0b1 (PR #10530) - try_eval_type = getattr(_pydantic_typing_extra, "try_eval_type", None) - if try_eval_type is not None: - return try_eval_type(value, globalns, localns)[0] - return _pydantic_typing_extra.eval_type_lenient( # ty: ignore[deprecated] - value, globalns, localns - ) - - -class GenerateJsonSchema(_GenerateJsonSchema): - # TODO: remove when this is merged (or equivalent): https://github.com/pydantic/pydantic/pull/12841 - # and dropping support for any version of Pydantic before that one (so, in a very long time) - def bytes_schema(self, schema: CoreSchema) -> JsonSchemaValue: - json_schema = {"type": "string", "contentMediaType": "application/octet-stream"} - bytes_mode = ( - self._config.ser_json_bytes - if self.mode == "serialization" - else self._config.val_json_bytes - ) - if bytes_mode == "base64": - json_schema["contentEncoding"] = "base64" - self.update_with_validations(json_schema, schema, self.ValidationsMapping.bytes) - return json_schema - - -# TODO: remove when dropping support for Pydantic < v2.12.3 -_Attrs = { - "default": ..., - "default_factory": None, - "alias": None, - "alias_priority": None, - "validation_alias": None, - "serialization_alias": None, - "title": None, - "field_title_generator": None, - "description": None, - "examples": None, - "exclude": None, - "exclude_if": None, - "discriminator": None, - "deprecated": None, - "json_schema_extra": None, - "frozen": None, - "validate_default": None, - "repr": True, - "init": None, - "init_var": None, - "kw_only": None, -} - - -# TODO: remove when dropping support for Pydantic < v2.12.3 -def asdict(field_info: FieldInfo) -> dict[str, Any]: - attributes = {} - for attr in _Attrs: - value = getattr(field_info, attr, Undefined) - if value is not Undefined: - attributes[attr] = value - return { - "annotation": field_info.annotation, - "metadata": field_info.metadata, - "attributes": attributes, - } - - -@dataclass -class ModelField: - field_info: FieldInfo - name: str - mode: Literal["validation", "serialization"] = "validation" - config: ConfigDict | None = None - - @property - def alias(self) -> str: - a = self.field_info.alias - return a if a is not None else self.name - - @property - def validation_alias(self) -> str | None: - va = self.field_info.validation_alias - if isinstance(va, str) and va: - return va - return None - - @property - def serialization_alias(self) -> str | None: - sa = self.field_info.serialization_alias - return sa or None - - @property - def default(self) -> Any: - return self.get_default() - - def __post_init__(self) -> None: - with warnings.catch_warnings(): - # Pydantic >= 2.12.0 warns about field specific metadata that is unused - # (e.g. `TypeAdapter(Annotated[int, Field(alias='b')])`). In some cases, we - # end up building the type adapter from a model field annotation so we - # need to ignore the warning: - if shared.PYDANTIC_VERSION_MINOR_TUPLE >= (2, 12): - from pydantic.warnings import UnsupportedFieldAttributeWarning - - warnings.simplefilter( - "ignore", category=UnsupportedFieldAttributeWarning - ) - # TODO: remove after setting the min Pydantic to v2.12.3 - # that adds asdict(), and use self.field_info.asdict() instead - field_dict = asdict(self.field_info) - annotated_args = ( - field_dict["annotation"], - *field_dict["metadata"], - # this FieldInfo needs to be created again so that it doesn't include - # the old field info metadata and only the rest of the attributes - Field(**field_dict["attributes"]), - ) - self._type_adapter: TypeAdapter[Any] = TypeAdapter( - Annotated[annotated_args], # ty: ignore[invalid-type-form] - config=self.config, - ) - - def get_default(self) -> Any: - if self.field_info.is_required(): - return Undefined - return self.field_info.get_default(call_default_factory=True) - - def validate( - self, - value: Any, - values: dict[str, Any] = {}, # noqa: B006 - *, - loc: tuple[int | str, ...] = (), - ) -> tuple[Any, list[dict[str, Any]]]: - try: - return ( - self._type_adapter.validate_python(value, from_attributes=True), - [], - ) - except ValidationError as exc: - return None, _regenerate_error_with_loc( - errors=exc.errors(include_url=False), loc_prefix=loc - ) - - def serialize( - self, - value: Any, - *, - mode: Literal["json", "python"] = "json", - include: IncEx | None = None, - exclude: IncEx | None = None, - by_alias: bool = True, - exclude_unset: bool = False, - exclude_defaults: bool = False, - exclude_none: bool = False, - ) -> Any: - # What calls this code passes a value that already called - # self._type_adapter.validate_python(value) - return self._type_adapter.dump_python( - value, - mode=mode, - include=include, - exclude=exclude, - by_alias=by_alias, - exclude_unset=exclude_unset, - exclude_defaults=exclude_defaults, - exclude_none=exclude_none, - ) - - def serialize_json( - self, - value: Any, - *, - include: IncEx | None = None, - exclude: IncEx | None = None, - by_alias: bool = True, - exclude_unset: bool = False, - exclude_defaults: bool = False, - exclude_none: bool = False, - ) -> bytes: - # What calls this code passes a value that already called - # self._type_adapter.validate_python(value) - # This uses Pydantic's dump_json() which serializes directly to JSON - # bytes in one pass (via Rust), avoiding the intermediate Python dict - # step of dump_python(mode="json") + json.dumps(). - return self._type_adapter.dump_json( - value, - include=include, - exclude=exclude, - by_alias=by_alias, - exclude_unset=exclude_unset, - exclude_defaults=exclude_defaults, - exclude_none=exclude_none, - ) - - def __hash__(self) -> int: - # Each ModelField is unique for our purposes, to allow making a dict from - # ModelField to its JSON Schema. - return id(self) - - -def _has_computed_fields(field: ModelField) -> bool: - computed_fields = field._type_adapter.core_schema.get("schema", {}).get( - "computed_fields", [] - ) - return len(computed_fields) > 0 - - -def get_schema_from_model_field( - *, - field: ModelField, - model_name_map: ModelNameMap, - field_mapping: dict[ - tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue - ], - separate_input_output_schemas: bool = True, -) -> dict[str, Any]: - override_mode: Literal["validation"] | None = ( - None - if (separate_input_output_schemas or _has_computed_fields(field)) - else "validation" - ) - field_alias = ( - (field.validation_alias or field.alias) - if field.mode == "validation" - else (field.serialization_alias or field.alias) - ) - - # This expects that GenerateJsonSchema was already used to generate the definitions - json_schema = field_mapping[(field, override_mode or field.mode)] - if "$ref" not in json_schema: - # TODO remove when deprecating Pydantic v1 - # Ref: https://github.com/pydantic/pydantic/blob/d61792cc42c80b13b23e3ffa74bc37ec7c77f7d1/pydantic/schema.py#L207 - json_schema["title"] = field.field_info.title or field_alias.title().replace( - "_", " " - ) - return json_schema - - -def get_definitions( - *, - fields: Sequence[ModelField], - model_name_map: ModelNameMap, - separate_input_output_schemas: bool = True, -) -> tuple[ - dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue], - dict[str, dict[str, Any]], -]: - schema_generator = GenerateJsonSchema(ref_template=REF_TEMPLATE) - validation_fields = [field for field in fields if field.mode == "validation"] - serialization_fields = [field for field in fields if field.mode == "serialization"] - flat_validation_models = get_flat_models_from_fields( - validation_fields, known_models=set() - ) - flat_serialization_models = get_flat_models_from_fields( - serialization_fields, known_models=set() - ) - flat_validation_model_fields = [ - ModelField( - field_info=FieldInfo(annotation=model), - name=model.__name__, - mode="validation", - ) - for model in flat_validation_models - ] - flat_serialization_model_fields = [ - ModelField( - field_info=FieldInfo(annotation=model), - name=model.__name__, - mode="serialization", - ) - for model in flat_serialization_models - ] - flat_model_fields = flat_validation_model_fields + flat_serialization_model_fields - input_types = {f.field_info.annotation for f in fields} - unique_flat_model_fields = { - f for f in flat_model_fields if f.field_info.annotation not in input_types - } - inputs = [ - ( - field, - ( - field.mode - if (separate_input_output_schemas or _has_computed_fields(field)) - else "validation" - ), - field._type_adapter.core_schema, - ) - for field in list(fields) + list(unique_flat_model_fields) - ] - field_mapping, definitions = schema_generator.generate_definitions(inputs=inputs) - for item_def in cast(dict[str, dict[str, Any]], definitions).values(): - if "description" in item_def: - item_description = cast(str, item_def["description"]).split("\f")[0] - item_def["description"] = item_description - # definitions: dict[DefsRef, dict[str, Any]] - # but mypy complains about general str in other places that are not declared as - # DefsRef, although DefsRef is just str: - # DefsRef = NewType('DefsRef', str) - # So, a cast to simplify the types here - return field_mapping, cast(dict[str, dict[str, Any]], definitions) - - -def is_scalar_field(field: ModelField) -> bool: - from fastapi import params - - return shared.field_annotation_is_scalar( - field.field_info.annotation - ) and not isinstance(field.field_info, params.Body) - - -def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo: - cls = type(field_info) - merged_field_info = cls.from_annotation(annotation) - new_field_info = copy(field_info) - new_field_info.metadata = merged_field_info.metadata - new_field_info.annotation = merged_field_info.annotation - return new_field_info - - -def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]: - origin_type = get_origin(field.field_info.annotation) or field.field_info.annotation - if origin_type is Union or origin_type is UnionType: # Handle optional sequences - union_args = get_args(field.field_info.annotation) - for union_arg in union_args: - if union_arg is type(None): - continue - origin_type = get_origin(union_arg) or union_arg - break - assert issubclass(origin_type, shared.sequence_types) # type: ignore[arg-type] - return shared.sequence_annotation_to_type[origin_type](value) # type: ignore[no-any-return,index] - - -def get_missing_field_error(loc: tuple[int | str, ...]) -> dict[str, Any]: - error = ValidationError.from_exception_data( - "Field required", [{"type": "missing", "loc": loc, "input": {}}] - ).errors(include_url=False)[0] - error["input"] = None - return error # type: ignore[return-value] - - -def create_body_model( - *, fields: Sequence[ModelField], model_name: str -) -> type[BaseModel]: - field_params = {f.name: (f.field_info.annotation, f.field_info) for f in fields} - BodyModel: type[BaseModel] = create_model(model_name, **field_params) # type: ignore[call-overload] - return BodyModel - - -def get_model_fields(model: type[BaseModel]) -> list[ModelField]: - model_fields: list[ModelField] = [] - for name, field_info in model.model_fields.items(): - type_ = field_info.annotation - if lenient_issubclass(type_, (BaseModel, dict)) or is_dataclass(type_): - model_config = None - else: - model_config = model.model_config - model_fields.append( - ModelField( - field_info=field_info, - name=name, - config=model_config, - ) - ) - return model_fields - - -@lru_cache -def get_cached_model_fields(model: type[BaseModel]) -> list[ModelField]: - return get_model_fields(model) - - -# Duplicate of several schema functions from Pydantic v1 to make them compatible with -# Pydantic v2 and allow mixing the models - -TypeModelOrEnum = type["BaseModel"] | type[Enum] -TypeModelSet = set[TypeModelOrEnum] - - -def normalize_name(name: str) -> str: - return re.sub(r"[^a-zA-Z0-9.\-_]", "_", name) - - -def get_model_name_map(unique_models: TypeModelSet) -> dict[TypeModelOrEnum, str]: - name_model_map = {} - for model in unique_models: - model_name = normalize_name(model.__name__) - name_model_map[model_name] = model - return {v: k for k, v in name_model_map.items()} - - -def get_flat_models_from_model( - model: type["BaseModel"], known_models: TypeModelSet | None = None -) -> TypeModelSet: - known_models = known_models or set() - fields = get_model_fields(model) - get_flat_models_from_fields(fields, known_models=known_models) - return known_models - - -def get_flat_models_from_annotation( - annotation: Any, known_models: TypeModelSet -) -> TypeModelSet: - origin = get_origin(annotation) - if origin is not None: - for arg in get_args(annotation): - if lenient_issubclass(arg, (BaseModel, Enum)): - if arg not in known_models: - known_models.add(arg) # type: ignore[arg-type] # ty: ignore[unused-ignore-comment] - if lenient_issubclass(arg, BaseModel): - get_flat_models_from_model(arg, known_models=known_models) - else: - get_flat_models_from_annotation(arg, known_models=known_models) - return known_models - - -def get_flat_models_from_field( - field: ModelField, known_models: TypeModelSet -) -> TypeModelSet: - field_type = field.field_info.annotation - if lenient_issubclass(field_type, BaseModel): - if field_type in known_models: - return known_models - known_models.add(field_type) - get_flat_models_from_model(field_type, known_models=known_models) - elif lenient_issubclass(field_type, Enum): - known_models.add(field_type) - else: - get_flat_models_from_annotation(field_type, known_models=known_models) - return known_models - - -def get_flat_models_from_fields( - fields: Sequence[ModelField], known_models: TypeModelSet -) -> TypeModelSet: - for field in fields: - get_flat_models_from_field(field, known_models=known_models) - return known_models - - -def _regenerate_error_with_loc( - *, errors: Sequence[Any], loc_prefix: tuple[str | int, ...] -) -> list[dict[str, Any]]: - updated_loc_errors: list[Any] = [ - {**err, "loc": loc_prefix + err.get("loc", ())} for err in errors - ] - - return updated_loc_errors diff --git a/notification-service/venv/Lib/site-packages/fastapi/applications.py b/notification-service/venv/Lib/site-packages/fastapi/applications.py deleted file mode 100644 index 4af1146..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/applications.py +++ /dev/null @@ -1,4691 +0,0 @@ -from collections.abc import Awaitable, Callable, Coroutine, Sequence -from enum import Enum -from typing import Annotated, Any, TypeVar - -from annotated_doc import Doc -from fastapi import routing -from fastapi.datastructures import Default, DefaultPlaceholder -from fastapi.exception_handlers import ( - http_exception_handler, - request_validation_exception_handler, - websocket_request_validation_exception_handler, -) -from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError -from fastapi.logger import logger -from fastapi.middleware.asyncexitstack import AsyncExitStackMiddleware -from fastapi.openapi.docs import ( - get_redoc_html, - get_swagger_ui_html, - get_swagger_ui_oauth2_redirect_html, -) -from fastapi.openapi.utils import get_openapi -from fastapi.params import Depends -from fastapi.types import DecoratedCallable, IncEx -from fastapi.utils import generate_unique_id -from starlette.applications import Starlette -from starlette.datastructures import State -from starlette.exceptions import HTTPException -from starlette.middleware import Middleware -from starlette.middleware.base import BaseHTTPMiddleware -from starlette.middleware.errors import ServerErrorMiddleware -from starlette.middleware.exceptions import ExceptionMiddleware -from starlette.requests import Request -from starlette.responses import HTMLResponse, JSONResponse, Response -from starlette.routing import BaseRoute -from starlette.types import ASGIApp, ExceptionHandler, Lifespan, Receive, Scope, Send -from typing_extensions import deprecated - -AppType = TypeVar("AppType", bound="FastAPI") - - -class FastAPI(Starlette): - """ - `FastAPI` app class, the main entrypoint to use FastAPI. - - Read more in the - [FastAPI docs for First Steps](https://fastapi.tiangolo.com/tutorial/first-steps/). - - ## Example - - ```python - from fastapi import FastAPI - - app = FastAPI() - ``` - """ - - def __init__( - self: AppType, - *, - debug: Annotated[ - bool, - Doc( - """ - Boolean indicating if debug tracebacks should be returned on server - errors. - - Read more in the - [Starlette docs for Applications](https://www.starlette.dev/applications/#instantiating-the-application). - """ - ), - ] = False, - routes: Annotated[ - list[BaseRoute] | None, - Doc( - """ - **Note**: you probably shouldn't use this parameter, it is inherited - from Starlette and supported for compatibility. - - --- - - A list of routes to serve incoming HTTP and WebSocket requests. - """ - ), - deprecated( - """ - You normally wouldn't use this parameter with FastAPI, it is inherited - from Starlette and supported for compatibility. - - In FastAPI, you normally would use the *path operation methods*, - like `app.get()`, `app.post()`, etc. - """ - ), - ] = None, - title: Annotated[ - str, - Doc( - """ - The title of the API. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more in the - [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-api). - - **Example** - - ```python - from fastapi import FastAPI - - app = FastAPI(title="ChimichangApp") - ``` - """ - ), - ] = "FastAPI", - summary: Annotated[ - str | None, - Doc( - """ - A short summary of the API. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more in the - [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-api). - - **Example** - - ```python - from fastapi import FastAPI - - app = FastAPI(summary="Deadpond's favorite app. Nuff said.") - ``` - """ - ), - ] = None, - description: Annotated[ - str, - Doc( - ''' - A description of the API. Supports Markdown (using - [CommonMark syntax](https://commonmark.org/)). - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more in the - [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-api). - - **Example** - - ```python - from fastapi import FastAPI - - app = FastAPI( - description=""" - ChimichangApp API helps you do awesome stuff. 🚀 - - ## Items - - You can **read items**. - - ## Users - - You will be able to: - - * **Create users** (_not implemented_). - * **Read users** (_not implemented_). - - """ - ) - ``` - ''' - ), - ] = "", - version: Annotated[ - str, - Doc( - """ - The version of the API. - - **Note** This is the version of your application, not the version of - the OpenAPI specification nor the version of FastAPI being used. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more in the - [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-api). - - **Example** - - ```python - from fastapi import FastAPI - - app = FastAPI(version="0.0.1") - ``` - """ - ), - ] = "0.1.0", - openapi_url: Annotated[ - str | None, - Doc( - """ - The URL where the OpenAPI schema will be served from. - - If you set it to `None`, no OpenAPI schema will be served publicly, and - the default automatic endpoints `/docs` and `/redoc` will also be - disabled. - - Read more in the - [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#openapi-url). - - **Example** - - ```python - from fastapi import FastAPI - - app = FastAPI(openapi_url="/api/v1/openapi.json") - ``` - """ - ), - ] = "/openapi.json", - openapi_tags: Annotated[ - list[dict[str, Any]] | None, - Doc( - """ - A list of tags used by OpenAPI, these are the same `tags` you can set - in the *path operations*, like: - - * `@app.get("/users/", tags=["users"])` - * `@app.get("/items/", tags=["items"])` - - The order of the tags can be used to specify the order shown in - tools like Swagger UI, used in the automatic path `/docs`. - - It's not required to specify all the tags used. - - The tags that are not declared MAY be organized randomly or based - on the tools' logic. Each tag name in the list MUST be unique. - - The value of each item is a `dict` containing: - - * `name`: The name of the tag. - * `description`: A short description of the tag. - [CommonMark syntax](https://commonmark.org/) MAY be used for rich - text representation. - * `externalDocs`: Additional external documentation for this tag. If - provided, it would contain a `dict` with: - * `description`: A short description of the target documentation. - [CommonMark syntax](https://commonmark.org/) MAY be used for - rich text representation. - * `url`: The URL for the target documentation. Value MUST be in - the form of a URL. - - Read more in the - [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-tags). - - **Example** - - ```python - from fastapi import FastAPI - - tags_metadata = [ - { - "name": "users", - "description": "Operations with users. The **login** logic is also here.", - }, - { - "name": "items", - "description": "Manage items. So _fancy_ they have their own docs.", - "externalDocs": { - "description": "Items external docs", - "url": "https://fastapi.tiangolo.com/", - }, - }, - ] - - app = FastAPI(openapi_tags=tags_metadata) - ``` - """ - ), - ] = None, - servers: Annotated[ - list[dict[str, str | Any]] | None, - Doc( - """ - A `list` of `dict`s with connectivity information to a target server. - - You would use it, for example, if your application is served from - different domains and you want to use the same Swagger UI in the - browser to interact with each of them (instead of having multiple - browser tabs open). Or if you want to leave fixed the possible URLs. - - If the servers `list` is not provided, or is an empty `list`, the - `servers` property in the generated OpenAPI will be: - - * a `dict` with a `url` value of the application's mounting point - (`root_path`) if it's different from `/`. - * otherwise, the `servers` property will be omitted from the OpenAPI - schema. - - Each item in the `list` is a `dict` containing: - - * `url`: A URL to the target host. This URL supports Server Variables - and MAY be relative, to indicate that the host location is relative - to the location where the OpenAPI document is being served. Variable - substitutions will be made when a variable is named in `{`brackets`}`. - * `description`: An optional string describing the host designated by - the URL. [CommonMark syntax](https://commonmark.org/) MAY be used for - rich text representation. - * `variables`: A `dict` between a variable name and its value. The value - is used for substitution in the server's URL template. - - Read more in the - [FastAPI docs for Behind a Proxy](https://fastapi.tiangolo.com/advanced/behind-a-proxy/#additional-servers). - - **Example** - - ```python - from fastapi import FastAPI - - app = FastAPI( - servers=[ - {"url": "https://stag.example.com", "description": "Staging environment"}, - {"url": "https://prod.example.com", "description": "Production environment"}, - ] - ) - ``` - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[Depends] | None, - Doc( - """ - A list of global dependencies, they will be applied to each - *path operation*, including in sub-routers. - - Read more about it in the - [FastAPI docs for Global Dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/global-dependencies/). - - **Example** - - ```python - from fastapi import Depends, FastAPI - - from .dependencies import func_dep_1, func_dep_2 - - app = FastAPI(dependencies=[Depends(func_dep_1), Depends(func_dep_2)]) - ``` - """ - ), - ] = None, - default_response_class: Annotated[ - type[Response], - Doc( - """ - The default response class to be used. - - Read more in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#default-response-class). - - **Example** - - ```python - from fastapi import FastAPI - from fastapi.responses import ORJSONResponse - - app = FastAPI(default_response_class=ORJSONResponse) - ``` - """ - ), - ] = Default(JSONResponse), - redirect_slashes: Annotated[ - bool, - Doc( - """ - Whether to detect and redirect slashes in URLs when the client doesn't - use the same format. - - **Example** - - ```python - from fastapi import FastAPI - - app = FastAPI(redirect_slashes=True) # the default - - @app.get("/items/") - async def read_items(): - return [{"item_id": "Foo"}] - ``` - - With this app, if a client goes to `/items` (without a trailing slash), - they will be automatically redirected with an HTTP status code of 307 - to `/items/`. - """ - ), - ] = True, - docs_url: Annotated[ - str | None, - Doc( - """ - The path to the automatic interactive API documentation. - It is handled in the browser by Swagger UI. - - The default URL is `/docs`. You can disable it by setting it to `None`. - - If `openapi_url` is set to `None`, this will be automatically disabled. - - Read more in the - [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#docs-urls). - - **Example** - - ```python - from fastapi import FastAPI - - app = FastAPI(docs_url="/documentation", redoc_url=None) - ``` - """ - ), - ] = "/docs", - redoc_url: Annotated[ - str | None, - Doc( - """ - The path to the alternative automatic interactive API documentation - provided by ReDoc. - - The default URL is `/redoc`. You can disable it by setting it to `None`. - - If `openapi_url` is set to `None`, this will be automatically disabled. - - Read more in the - [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#docs-urls). - - **Example** - - ```python - from fastapi import FastAPI - - app = FastAPI(docs_url="/documentation", redoc_url="redocumentation") - ``` - """ - ), - ] = "/redoc", - swagger_ui_oauth2_redirect_url: Annotated[ - str | None, - Doc( - """ - The OAuth2 redirect endpoint for the Swagger UI. - - By default it is `/docs/oauth2-redirect`. - - This is only used if you use OAuth2 (with the "Authorize" button) - with Swagger UI. - """ - ), - ] = "/docs/oauth2-redirect", - swagger_ui_init_oauth: Annotated[ - dict[str, Any] | None, - Doc( - """ - OAuth2 configuration for the Swagger UI, by default shown at `/docs`. - - Read more about the available configuration options in the - [Swagger UI docs](https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/). - """ - ), - ] = None, - middleware: Annotated[ - Sequence[Middleware] | None, - Doc( - """ - List of middleware to be added when creating the application. - - In FastAPI you would normally do this with `app.add_middleware()` - instead. - - Read more in the - [FastAPI docs for Middleware](https://fastapi.tiangolo.com/tutorial/middleware/). - """ - ), - ] = None, - exception_handlers: Annotated[ - dict[ - int | type[Exception], - Callable[[Request, Any], Coroutine[Any, Any, Response]], - ] - | None, - Doc( - """ - A dictionary with handlers for exceptions. - - In FastAPI, you would normally use the decorator - `@app.exception_handler()`. - - Read more in the - [FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/). - """ - ), - ] = None, - on_startup: Annotated[ - Sequence[Callable[[], Any]] | None, - Doc( - """ - A list of startup event handler functions. - - You should instead use the `lifespan` handlers. - - Read more in the [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). - """ - ), - ] = None, - on_shutdown: Annotated[ - Sequence[Callable[[], Any]] | None, - Doc( - """ - A list of shutdown event handler functions. - - You should instead use the `lifespan` handlers. - - Read more in the - [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). - """ - ), - ] = None, - lifespan: Annotated[ - Lifespan[AppType] | None, - Doc( - """ - A `Lifespan` context manager handler. This replaces `startup` and - `shutdown` functions with a single context manager. - - Read more in the - [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). - """ - ), - ] = None, - terms_of_service: Annotated[ - str | None, - Doc( - """ - A URL to the Terms of Service for your API. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more at the - [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-api). - - **Example** - - ```python - app = FastAPI(terms_of_service="http://example.com/terms/") - ``` - """ - ), - ] = None, - contact: Annotated[ - dict[str, str | Any] | None, - Doc( - """ - A dictionary with the contact information for the exposed API. - - It can contain several fields. - - * `name`: (`str`) The name of the contact person/organization. - * `url`: (`str`) A URL pointing to the contact information. MUST be in - the format of a URL. - * `email`: (`str`) The email address of the contact person/organization. - MUST be in the format of an email address. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more at the - [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-api). - - **Example** - - ```python - app = FastAPI( - contact={ - "name": "Deadpoolio the Amazing", - "url": "http://x-force.example.com/contact/", - "email": "dp@x-force.example.com", - } - ) - ``` - """ - ), - ] = None, - license_info: Annotated[ - dict[str, str | Any] | None, - Doc( - """ - A dictionary with the license information for the exposed API. - - It can contain several fields. - - * `name`: (`str`) **REQUIRED** (if a `license_info` is set). The - license name used for the API. - * `identifier`: (`str`) An [SPDX](https://spdx.dev/) license expression - for the API. The `identifier` field is mutually exclusive of the `url` - field. Available since OpenAPI 3.1.0, FastAPI 0.99.0. - * `url`: (`str`) A URL to the license used for the API. This MUST be - the format of a URL. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more at the - [FastAPI docs for Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-api). - - **Example** - - ```python - app = FastAPI( - license_info={ - "name": "Apache 2.0", - "url": "https://www.apache.org/licenses/LICENSE-2.0.html", - } - ) - ``` - """ - ), - ] = None, - openapi_prefix: Annotated[ - str, - Doc( - """ - A URL prefix for the OpenAPI URL. - """ - ), - deprecated( - """ - "openapi_prefix" has been deprecated in favor of "root_path", which - follows more closely the ASGI standard, is simpler, and more - automatic. - """ - ), - ] = "", - root_path: Annotated[ - str, - Doc( - """ - A path prefix handled by a proxy that is not seen by the application - but is seen by external clients, which affects things like Swagger UI. - - Read more about it at the - [FastAPI docs for Behind a Proxy](https://fastapi.tiangolo.com/advanced/behind-a-proxy/). - - **Example** - - ```python - from fastapi import FastAPI - - app = FastAPI(root_path="/api/v1") - ``` - """ - ), - ] = "", - root_path_in_servers: Annotated[ - bool, - Doc( - """ - To disable automatically generating the URLs in the `servers` field - in the autogenerated OpenAPI using the `root_path`. - - Read more about it in the - [FastAPI docs for Behind a Proxy](https://fastapi.tiangolo.com/advanced/behind-a-proxy/#disable-automatic-server-from-root-path). - - **Example** - - ```python - from fastapi import FastAPI - - app = FastAPI(root_path_in_servers=False) - ``` - """ - ), - ] = True, - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses to be shown in OpenAPI. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Additional Responses in OpenAPI](https://fastapi.tiangolo.com/advanced/additional-responses/). - - And in the - [FastAPI docs for Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - OpenAPI callbacks that should apply to all *path operations*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - webhooks: Annotated[ - routing.APIRouter | None, - Doc( - """ - Add OpenAPI webhooks. This is similar to `callbacks` but it doesn't - depend on specific *path operations*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - **Note**: This is available since OpenAPI 3.1.0, FastAPI 0.99.0. - - Read more about it in the - [FastAPI docs for OpenAPI Webhooks](https://fastapi.tiangolo.com/advanced/openapi-webhooks/). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark all *path operations* as deprecated. You probably don't need it, - but it's available. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#deprecate-a-path-operation). - """ - ), - ] = None, - include_in_schema: Annotated[ - bool, - Doc( - """ - To include (or not) all the *path operations* in the generated OpenAPI. - You probably don't need it, but it's available. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - swagger_ui_parameters: Annotated[ - dict[str, Any] | None, - Doc( - """ - Parameters to configure Swagger UI, the autogenerated interactive API - documentation (by default at `/docs`). - - Read more about it in the - [FastAPI docs about how to Configure Swagger UI](https://fastapi.tiangolo.com/how-to/configure-swagger-ui/). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[routing.APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - separate_input_output_schemas: Annotated[ - bool, - Doc( - """ - Whether to generate separate OpenAPI schemas for request body and - response body when the results would be more precise. - - This is particularly useful when automatically generating clients. - - For example, if you have a model like: - - ```python - from pydantic import BaseModel - - class Item(BaseModel): - name: str - tags: list[str] = [] - ``` - - When `Item` is used for input, a request body, `tags` is not required, - the client doesn't have to provide it. - - But when using `Item` for output, for a response body, `tags` is always - available because it has a default value, even if it's just an empty - list. So, the client should be able to always expect it. - - In this case, there would be two different schemas, one for input and - another one for output. - - Read more about it in the - [FastAPI docs about how to separate schemas for input and output](https://fastapi.tiangolo.com/how-to/separate-openapi-schemas) - """ - ), - ] = True, - openapi_external_docs: Annotated[ - dict[str, Any] | None, - Doc( - """ - This field allows you to provide additional external documentation links. - If provided, it must be a dictionary containing: - - * `description`: A brief description of the external documentation. - * `url`: The URL pointing to the external documentation. The value **MUST** - be a valid URL format. - - **Example**: - - ```python - from fastapi import FastAPI - - external_docs = { - "description": "Detailed API Reference", - "url": "https://example.com/api-docs", - } - - app = FastAPI(openapi_external_docs=external_docs) - ``` - """ - ), - ] = None, - strict_content_type: Annotated[ - bool, - Doc( - """ - Enable strict checking for request Content-Type headers. - - When `True` (the default), requests with a body that do not include - a `Content-Type` header will **not** be parsed as JSON. - - This prevents potential cross-site request forgery (CSRF) attacks - that exploit the browser's ability to send requests without a - Content-Type header, bypassing CORS preflight checks. In particular - applicable for apps that need to be run locally (in localhost). - - When `False`, requests without a `Content-Type` header will have - their body parsed as JSON, which maintains compatibility with - certain clients that don't send `Content-Type` headers. - - Read more about it in the - [FastAPI docs for Strict Content-Type](https://fastapi.tiangolo.com/advanced/strict-content-type/). - """ - ), - ] = True, - **extra: Annotated[ - Any, - Doc( - """ - Extra keyword arguments to be stored in the app, not used by FastAPI - anywhere. - """ - ), - ], - ) -> None: - self.debug = debug - self.title = title - self.summary = summary - self.description = description - self.version = version - self.terms_of_service = terms_of_service - self.contact = contact - self.license_info = license_info - self.openapi_url = openapi_url - self.openapi_tags = openapi_tags - self.root_path_in_servers = root_path_in_servers - self.docs_url = docs_url - self.redoc_url = redoc_url - self.swagger_ui_oauth2_redirect_url = swagger_ui_oauth2_redirect_url - self.swagger_ui_init_oauth = swagger_ui_init_oauth - self.swagger_ui_parameters = swagger_ui_parameters - self.servers = servers or [] - self.separate_input_output_schemas = separate_input_output_schemas - self.openapi_external_docs = openapi_external_docs - self.extra = extra - self.openapi_version: Annotated[ - str, - Doc( - """ - The version string of OpenAPI. - - FastAPI will generate OpenAPI version 3.1.0, and will output that as - the OpenAPI version. But some tools, even though they might be - compatible with OpenAPI 3.1.0, might not recognize it as a valid. - - So you could override this value to trick those tools into using - the generated OpenAPI. Have in mind that this is a hack. But if you - avoid using features added in OpenAPI 3.1.0, it might work for your - use case. - - This is not passed as a parameter to the `FastAPI` class to avoid - giving the false idea that FastAPI would generate a different OpenAPI - schema. It is only available as an attribute. - - **Example** - - ```python - from fastapi import FastAPI - - app = FastAPI() - - app.openapi_version = "3.0.2" - ``` - """ - ), - ] = "3.1.0" - self.openapi_schema: dict[str, Any] | None = None - if self.openapi_url: - assert self.title, "A title must be provided for OpenAPI, e.g.: 'My API'" - assert self.version, "A version must be provided for OpenAPI, e.g.: '2.1.0'" - # TODO: remove when discarding the openapi_prefix parameter - if openapi_prefix: - logger.warning( - '"openapi_prefix" has been deprecated in favor of "root_path", which ' - "follows more closely the ASGI standard, is simpler, and more " - "automatic. Check the docs at " - "https://fastapi.tiangolo.com/advanced/sub-applications/" - ) - self.webhooks: Annotated[ - routing.APIRouter, - Doc( - """ - The `app.webhooks` attribute is an `APIRouter` with the *path - operations* that will be used just for documentation of webhooks. - - Read more about it in the - [FastAPI docs for OpenAPI Webhooks](https://fastapi.tiangolo.com/advanced/openapi-webhooks/). - """ - ), - ] = webhooks or routing.APIRouter() - self.root_path = root_path or openapi_prefix - self.state: Annotated[ - State, - Doc( - """ - A state object for the application. This is the same object for the - entire application, it doesn't change from request to request. - - You normally wouldn't use this in FastAPI, for most of the cases you - would instead use FastAPI dependencies. - - This is simply inherited from Starlette. - - Read more about it in the - [Starlette docs for Applications](https://www.starlette.dev/applications/#storing-state-on-the-app-instance). - """ - ), - ] = State() - self.dependency_overrides: Annotated[ - dict[Callable[..., Any], Callable[..., Any]], - Doc( - """ - A dictionary with overrides for the dependencies. - - Each key is the original dependency callable, and the value is the - actual dependency that should be called. - - This is for testing, to replace expensive dependencies with testing - versions. - - Read more about it in the - [FastAPI docs for Testing Dependencies with Overrides](https://fastapi.tiangolo.com/advanced/testing-dependencies/). - """ - ), - ] = {} - self.router: routing.APIRouter = routing.APIRouter( - routes=routes, - redirect_slashes=redirect_slashes, - dependency_overrides_provider=self, - on_startup=on_startup, - on_shutdown=on_shutdown, - lifespan=lifespan, - default_response_class=default_response_class, - dependencies=dependencies, - callbacks=callbacks, - deprecated=deprecated, - include_in_schema=include_in_schema, - responses=responses, - generate_unique_id_function=generate_unique_id_function, - strict_content_type=strict_content_type, - ) - self.exception_handlers: dict[ - Any, Callable[[Request, Any], Response | Awaitable[Response]] - ] = {} if exception_handlers is None else dict(exception_handlers) - self.exception_handlers.setdefault(HTTPException, http_exception_handler) - self.exception_handlers.setdefault( - RequestValidationError, request_validation_exception_handler - ) - - # Starlette still has incorrect type specification for the handlers - self.exception_handlers.setdefault( - WebSocketRequestValidationError, - websocket_request_validation_exception_handler, # type: ignore[arg-type] # ty: ignore[unused-ignore-comment] - ) # ty: ignore[no-matching-overload] - - self.user_middleware: list[Middleware] = ( - [] if middleware is None else list(middleware) - ) - self.middleware_stack: ASGIApp | None = None - self.setup() - - def build_middleware_stack(self) -> ASGIApp: - # Duplicate/override from Starlette to add AsyncExitStackMiddleware - # inside of ExceptionMiddleware, inside of custom user middlewares - debug = self.debug - error_handler = None - exception_handlers: dict[Any, ExceptionHandler] = {} - - for key, value in self.exception_handlers.items(): - if key in (500, Exception): - error_handler = value - else: - exception_handlers[key] = value - - middleware = ( - [Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)] # ty: ignore[invalid-argument-type] - + self.user_middleware - + [ - Middleware( - ExceptionMiddleware, # ty: ignore[invalid-argument-type] - handlers=exception_handlers, - debug=debug, - ), - # Add FastAPI-specific AsyncExitStackMiddleware for closing files. - # Before this was also used for closing dependencies with yield but - # those now have their own AsyncExitStack, to properly support - # streaming responses while keeping compatibility with the previous - # versions (as of writing 0.117.1) that allowed doing - # except HTTPException inside a dependency with yield. - # This needs to happen after user middlewares because those create a - # new contextvars context copy by using a new AnyIO task group. - # This AsyncExitStack preserves the context for contextvars, not - # strictly necessary for closing files but it was one of the original - # intentions. - # If the AsyncExitStack lived outside of the custom middlewares and - # contextvars were set, for example in a dependency with 'yield' - # in that internal contextvars context, the values would not be - # available in the outer context of the AsyncExitStack. - # By placing the middleware and the AsyncExitStack here, inside all - # user middlewares, the same context is used. - # This is currently not needed, only for closing files, but used to be - # important when dependencies with yield were closed here. - Middleware(AsyncExitStackMiddleware), # ty: ignore[invalid-argument-type] - ] - ) - - app = self.router - for cls, args, kwargs in reversed(middleware): - app = cls(app, *args, **kwargs) - return app - - def openapi(self) -> dict[str, Any]: - """ - Generate the OpenAPI schema of the application. This is called by FastAPI - internally. - - The first time it is called it stores the result in the attribute - `app.openapi_schema`, and next times it is called, it just returns that same - result. To avoid the cost of generating the schema every time. - - If you need to modify the generated OpenAPI schema, you could modify it. - - Read more in the - [FastAPI docs for OpenAPI](https://fastapi.tiangolo.com/how-to/extending-openapi/). - """ - if not self.openapi_schema: - self.openapi_schema = get_openapi( - title=self.title, - version=self.version, - openapi_version=self.openapi_version, - summary=self.summary, - description=self.description, - terms_of_service=self.terms_of_service, - contact=self.contact, - license_info=self.license_info, - routes=self.routes, - webhooks=self.webhooks.routes, - tags=self.openapi_tags, - servers=self.servers, - separate_input_output_schemas=self.separate_input_output_schemas, - external_docs=self.openapi_external_docs, - ) - return self.openapi_schema - - def setup(self) -> None: - if self.openapi_url: - - async def openapi(req: Request) -> JSONResponse: - root_path = req.scope.get("root_path", "").rstrip("/") - schema = self.openapi() - if root_path and self.root_path_in_servers: - server_urls = {s.get("url") for s in schema.get("servers", [])} - if root_path not in server_urls: - schema = dict(schema) - schema["servers"] = [{"url": root_path}] + schema.get( - "servers", [] - ) - return JSONResponse(schema) - - self.add_route(self.openapi_url, openapi, include_in_schema=False) - if self.openapi_url and self.docs_url: - - async def swagger_ui_html(req: Request) -> HTMLResponse: - root_path = req.scope.get("root_path", "").rstrip("/") - openapi_url = root_path + self.openapi_url - oauth2_redirect_url = self.swagger_ui_oauth2_redirect_url - if oauth2_redirect_url: - oauth2_redirect_url = root_path + oauth2_redirect_url - return get_swagger_ui_html( - openapi_url=openapi_url, - title=f"{self.title} - Swagger UI", - oauth2_redirect_url=oauth2_redirect_url, - init_oauth=self.swagger_ui_init_oauth, - swagger_ui_parameters=self.swagger_ui_parameters, - ) - - self.add_route(self.docs_url, swagger_ui_html, include_in_schema=False) - - if self.swagger_ui_oauth2_redirect_url: - - async def swagger_ui_redirect(req: Request) -> HTMLResponse: - return get_swagger_ui_oauth2_redirect_html() - - self.add_route( - self.swagger_ui_oauth2_redirect_url, - swagger_ui_redirect, - include_in_schema=False, - ) - if self.openapi_url and self.redoc_url: - - async def redoc_html(req: Request) -> HTMLResponse: - root_path = req.scope.get("root_path", "").rstrip("/") - openapi_url = root_path + self.openapi_url - return get_redoc_html( - openapi_url=openapi_url, title=f"{self.title} - ReDoc" - ) - - self.add_route(self.redoc_url, redoc_html, include_in_schema=False) - - async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: - if self.root_path: - scope["root_path"] = self.root_path - await super().__call__(scope, receive, send) - - def add_api_route( - self, - path: str, - endpoint: Callable[..., Any], - *, - response_model: Any = Default(None), - status_code: int | None = None, - tags: list[str | Enum] | None = None, - dependencies: Sequence[Depends] | None = None, - summary: str | None = None, - description: str | None = None, - response_description: str = "Successful Response", - responses: dict[int | str, dict[str, Any]] | None = None, - deprecated: bool | None = None, - methods: list[str] | None = None, - operation_id: str | None = None, - response_model_include: IncEx | None = None, - response_model_exclude: IncEx | None = None, - response_model_by_alias: bool = True, - response_model_exclude_unset: bool = False, - response_model_exclude_defaults: bool = False, - response_model_exclude_none: bool = False, - include_in_schema: bool = True, - response_class: type[Response] | DefaultPlaceholder = Default(JSONResponse), - name: str | None = None, - openapi_extra: dict[str, Any] | None = None, - generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( - generate_unique_id - ), - ) -> None: - self.router.add_api_route( - path, - endpoint=endpoint, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - methods=methods, - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def api_route( - self, - path: str, - *, - response_model: Any = Default(None), - status_code: int | None = None, - tags: list[str | Enum] | None = None, - dependencies: Sequence[Depends] | None = None, - summary: str | None = None, - description: str | None = None, - response_description: str = "Successful Response", - responses: dict[int | str, dict[str, Any]] | None = None, - deprecated: bool | None = None, - methods: list[str] | None = None, - operation_id: str | None = None, - response_model_include: IncEx | None = None, - response_model_exclude: IncEx | None = None, - response_model_by_alias: bool = True, - response_model_exclude_unset: bool = False, - response_model_exclude_defaults: bool = False, - response_model_exclude_none: bool = False, - include_in_schema: bool = True, - response_class: type[Response] = Default(JSONResponse), - name: str | None = None, - openapi_extra: dict[str, Any] | None = None, - generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( - generate_unique_id - ), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - def decorator(func: DecoratedCallable) -> DecoratedCallable: - self.router.add_api_route( - path, - func, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - methods=methods, - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - return func - - return decorator - - def add_api_websocket_route( - self, - path: str, - endpoint: Callable[..., Any], - name: str | None = None, - *, - dependencies: Sequence[Depends] | None = None, - ) -> None: - self.router.add_api_websocket_route( - path, - endpoint, - name=name, - dependencies=dependencies, - ) - - def websocket( - self, - path: Annotated[ - str, - Doc( - """ - WebSocket path. - """ - ), - ], - name: Annotated[ - str | None, - Doc( - """ - A name for the WebSocket. Only used internally. - """ - ), - ] = None, - *, - dependencies: Annotated[ - Sequence[Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be used for this - WebSocket. - - Read more about it in the - [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/). - """ - ), - ] = None, - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Decorate a WebSocket function. - - Read more about it in the - [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/). - - **Example** - - ```python - from fastapi import FastAPI, WebSocket - - app = FastAPI() - - @app.websocket("/ws") - async def websocket_endpoint(websocket: WebSocket): - await websocket.accept() - while True: - data = await websocket.receive_text() - await websocket.send_text(f"Message text was: {data}") - ``` - """ - - def decorator(func: DecoratedCallable) -> DecoratedCallable: - self.add_api_websocket_route( - path, - func, - name=name, - dependencies=dependencies, - ) - return func - - return decorator - - def include_router( - self, - router: Annotated[routing.APIRouter, Doc("The `APIRouter` to include.")], - *, - prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "", - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to all the *path operations* in this - router. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to all the - *path operations* in this router. - - Read more about it in the - [FastAPI docs for Bigger Applications - Multiple Files](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). - - **Example** - - ```python - from fastapi import Depends, FastAPI - - from .dependencies import get_token_header - from .internal import admin - - app = FastAPI() - - app.include_router( - admin.router, - dependencies=[Depends(get_token_header)], - ) - ``` - """ - ), - ] = None, - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses to be shown in OpenAPI. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Additional Responses in OpenAPI](https://fastapi.tiangolo.com/advanced/additional-responses/). - - And in the - [FastAPI docs for Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark all the *path operations* in this router as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - **Example** - - ```python - from fastapi import FastAPI - - from .internal import old_api - - app = FastAPI() - - app.include_router( - old_api.router, - deprecated=True, - ) - ``` - """ - ), - ] = None, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include (or not) all the *path operations* in this router in the - generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - **Example** - - ```python - from fastapi import FastAPI - - from .internal import old_api - - app = FastAPI() - - app.include_router( - old_api.router, - include_in_schema=False, - ) - ``` - """ - ), - ] = True, - default_response_class: Annotated[ - type[Response], - Doc( - """ - Default response class to be used for the *path operations* in this - router. - - Read more in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#default-response-class). - - **Example** - - ```python - from fastapi import FastAPI - from fastapi.responses import ORJSONResponse - - from .internal import old_api - - app = FastAPI() - - app.include_router( - old_api.router, - default_response_class=ORJSONResponse, - ) - ``` - """ - ), - ] = Default(JSONResponse), - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[routing.APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> None: - """ - Include an `APIRouter` in the same app. - - Read more about it in the - [FastAPI docs for Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/). - - ## Example - - ```python - from fastapi import FastAPI - - from .users import users_router - - app = FastAPI() - - app.include_router(users_router) - ``` - """ - self.router.include_router( - router, - prefix=prefix, - tags=tags, - dependencies=dependencies, - responses=responses, - deprecated=deprecated, - include_in_schema=include_in_schema, - default_response_class=default_response_class, - callbacks=callbacks, - generate_unique_id_function=generate_unique_id_function, - ) - - def get( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[routing.APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP GET operation. - - ## Example - - ```python - from fastapi import FastAPI - - app = FastAPI() - - @app.get("/items/") - def read_items(): - return [{"name": "Empanada"}, {"name": "Arepa"}] - ``` - """ - return self.router.get( - path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def put( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[routing.APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP PUT operation. - - ## Example - - ```python - from fastapi import FastAPI - from pydantic import BaseModel - - class Item(BaseModel): - name: str - description: str | None = None - - app = FastAPI() - - @app.put("/items/{item_id}") - def replace_item(item_id: str, item: Item): - return {"message": "Item replaced", "id": item_id} - ``` - """ - return self.router.put( - path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def post( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[routing.APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP POST operation. - - ## Example - - ```python - from fastapi import FastAPI - from pydantic import BaseModel - - class Item(BaseModel): - name: str - description: str | None = None - - app = FastAPI() - - @app.post("/items/") - def create_item(item: Item): - return {"message": "Item created"} - ``` - """ - return self.router.post( - path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def delete( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[routing.APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP DELETE operation. - - ## Example - - ```python - from fastapi import FastAPI - - app = FastAPI() - - @app.delete("/items/{item_id}") - def delete_item(item_id: str): - return {"message": "Item deleted"} - ``` - """ - return self.router.delete( - path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def options( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[routing.APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP OPTIONS operation. - - ## Example - - ```python - from fastapi import FastAPI - - app = FastAPI() - - @app.options("/items/") - def get_item_options(): - return {"additions": ["Aji", "Guacamole"]} - ``` - """ - return self.router.options( - path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def head( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[routing.APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP HEAD operation. - - ## Example - - ```python - from fastapi import FastAPI, Response - - app = FastAPI() - - @app.head("/items/", status_code=204) - def get_items_headers(response: Response): - response.headers["X-Cat-Dog"] = "Alone in the world" - ``` - """ - return self.router.head( - path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def patch( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[routing.APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP PATCH operation. - - ## Example - - ```python - from fastapi import FastAPI - from pydantic import BaseModel - - class Item(BaseModel): - name: str - description: str | None = None - - app = FastAPI() - - @app.patch("/items/") - def update_item(item: Item): - return {"message": "Item updated in place"} - ``` - """ - return self.router.patch( - path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def trace( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[routing.APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP TRACE operation. - - ## Example - - ```python - from fastapi import FastAPI - - app = FastAPI() - - @app.trace("/items/{item_id}") - def trace_item(item_id: str): - return None - ``` - """ - return self.router.trace( - path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def websocket_route( - self, path: str, name: str | None = None - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - def decorator(func: DecoratedCallable) -> DecoratedCallable: - self.router.add_websocket_route(path, func, name=name) - return func - - return decorator - - @deprecated( - """ - on_event is deprecated, use lifespan event handlers instead. - - Read more about it in the - [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/). - """ - ) - def on_event( - self, - event_type: Annotated[ - str, - Doc( - """ - The type of event. `startup` or `shutdown`. - """ - ), - ], - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add an event handler for the application. - - `on_event` is deprecated, use `lifespan` event handlers instead. - - Read more about it in the - [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/#alternative-events-deprecated). - """ - return self.router.on_event(event_type) # ty: ignore[deprecated] - - def middleware( - self, - middleware_type: Annotated[ - str, - Doc( - """ - The type of middleware. Currently only supports `http`. - """ - ), - ], - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a middleware to the application. - - Read more about it in the - [FastAPI docs for Middleware](https://fastapi.tiangolo.com/tutorial/middleware/). - - ## Example - - ```python - import time - from typing import Awaitable, Callable - - from fastapi import FastAPI, Request, Response - - app = FastAPI() - - - @app.middleware("http") - async def add_process_time_header( - request: Request, call_next: Callable[[Request], Awaitable[Response]] - ) -> Response: - start_time = time.time() - response = await call_next(request) - process_time = time.time() - start_time - response.headers["X-Process-Time"] = str(process_time) - return response - ``` - """ - - def decorator(func: DecoratedCallable) -> DecoratedCallable: - self.add_middleware(BaseHTTPMiddleware, dispatch=func) # ty: ignore[invalid-argument-type] - return func - - return decorator - - def exception_handler( - self, - exc_class_or_status_code: Annotated[ - int | type[Exception], - Doc( - """ - The Exception class this would handle, or a status code. - """ - ), - ], - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add an exception handler to the app. - - Read more about it in the - [FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/). - - ## Example - - ```python - from fastapi import FastAPI, Request - from fastapi.responses import JSONResponse - - - class UnicornException(Exception): - def __init__(self, name: str): - self.name = name - - - app = FastAPI() - - - @app.exception_handler(UnicornException) - async def unicorn_exception_handler(request: Request, exc: UnicornException): - return JSONResponse( - status_code=418, - content={"message": f"Oops! {exc.name} did something. There goes a rainbow..."}, - ) - ``` - """ - - def decorator(func: DecoratedCallable) -> DecoratedCallable: - self.add_exception_handler(exc_class_or_status_code, func) - return func - - return decorator diff --git a/notification-service/venv/Lib/site-packages/fastapi/background.py b/notification-service/venv/Lib/site-packages/fastapi/background.py deleted file mode 100644 index 7677058..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/background.py +++ /dev/null @@ -1,61 +0,0 @@ -from collections.abc import Callable -from typing import Annotated, Any - -from annotated_doc import Doc -from starlette.background import BackgroundTasks as StarletteBackgroundTasks -from typing_extensions import ParamSpec - -P = ParamSpec("P") - - -class BackgroundTasks(StarletteBackgroundTasks): - """ - A collection of background tasks that will be called after a response has been - sent to the client. - - Read more about it in the - [FastAPI docs for Background Tasks](https://fastapi.tiangolo.com/tutorial/background-tasks/). - - ## Example - - ```python - from fastapi import BackgroundTasks, FastAPI - - app = FastAPI() - - - def write_notification(email: str, message=""): - with open("log.txt", mode="w") as email_file: - content = f"notification for {email}: {message}" - email_file.write(content) - - - @app.post("/send-notification/{email}") - async def send_notification(email: str, background_tasks: BackgroundTasks): - background_tasks.add_task(write_notification, email, message="some notification") - return {"message": "Notification sent in the background"} - ``` - """ - - def add_task( - self, - func: Annotated[ - Callable[P, Any], - Doc( - """ - The function to call after the response is sent. - - It can be a regular `def` function or an `async def` function. - """ - ), - ], - *args: P.args, - **kwargs: P.kwargs, - ) -> None: - """ - Add a function to be called in the background after the response is sent. - - Read more about it in the - [FastAPI docs for Background Tasks](https://fastapi.tiangolo.com/tutorial/background-tasks/). - """ - return super().add_task(func, *args, **kwargs) diff --git a/notification-service/venv/Lib/site-packages/fastapi/cli.py b/notification-service/venv/Lib/site-packages/fastapi/cli.py deleted file mode 100644 index fda271a..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/cli.py +++ /dev/null @@ -1,13 +0,0 @@ -try: - from fastapi_cli.cli import main as cli_main - -except ImportError: # pragma: no cover - cli_main = None # type: ignore - - -def main() -> None: - if not cli_main: # type: ignore[truthy-function] # ty: ignore[unused-ignore-comment] - message = 'To use the fastapi command, please install "fastapi[standard]":\n\n\tpip install "fastapi[standard]"\n' - print(message) - raise RuntimeError(message) # noqa: B904 - cli_main() diff --git a/notification-service/venv/Lib/site-packages/fastapi/concurrency.py b/notification-service/venv/Lib/site-packages/fastapi/concurrency.py deleted file mode 100644 index 76a5a2e..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/concurrency.py +++ /dev/null @@ -1,41 +0,0 @@ -from collections.abc import AsyncGenerator -from contextlib import AbstractContextManager -from contextlib import asynccontextmanager as asynccontextmanager -from typing import TypeVar - -import anyio.to_thread -from anyio import CapacityLimiter -from starlette.concurrency import iterate_in_threadpool as iterate_in_threadpool # noqa -from starlette.concurrency import run_in_threadpool as run_in_threadpool # noqa -from starlette.concurrency import ( # noqa - run_until_first_complete as run_until_first_complete, -) - -_T = TypeVar("_T") - - -@asynccontextmanager -async def contextmanager_in_threadpool( - cm: AbstractContextManager[_T], -) -> AsyncGenerator[_T, None]: - # blocking __exit__ from running waiting on a free thread - # can create race conditions/deadlocks if the context manager itself - # has its own internal pool (e.g. a database connection pool) - # to avoid this we let __exit__ run without a capacity limit - # since we're creating a new limiter for each call, any non-zero limit - # works (1 is arbitrary) - exit_limiter = CapacityLimiter(1) - try: - yield await run_in_threadpool(cm.__enter__) - except Exception as e: - ok = bool( - await anyio.to_thread.run_sync( - cm.__exit__, type(e), e, e.__traceback__, limiter=exit_limiter - ) - ) - if not ok: - raise e - else: - await anyio.to_thread.run_sync( - cm.__exit__, None, None, None, limiter=exit_limiter - ) diff --git a/notification-service/venv/Lib/site-packages/fastapi/datastructures.py b/notification-service/venv/Lib/site-packages/fastapi/datastructures.py deleted file mode 100644 index 1da784c..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/datastructures.py +++ /dev/null @@ -1,186 +0,0 @@ -from collections.abc import Callable, Mapping -from typing import ( - Annotated, - Any, - BinaryIO, - TypeVar, - cast, -) - -from annotated_doc import Doc -from pydantic import GetJsonSchemaHandler -from starlette.datastructures import URL as URL # noqa: F401 -from starlette.datastructures import Address as Address # noqa: F401 -from starlette.datastructures import FormData as FormData # noqa: F401 -from starlette.datastructures import Headers as Headers # noqa: F401 -from starlette.datastructures import QueryParams as QueryParams # noqa: F401 -from starlette.datastructures import State as State # noqa: F401 -from starlette.datastructures import UploadFile as StarletteUploadFile - - -class UploadFile(StarletteUploadFile): - """ - A file uploaded in a request. - - Define it as a *path operation function* (or dependency) parameter. - - If you are using a regular `def` function, you can use the `upload_file.file` - attribute to access the raw standard Python file (blocking, not async), useful and - needed for non-async code. - - Read more about it in the - [FastAPI docs for Request Files](https://fastapi.tiangolo.com/tutorial/request-files/). - - ## Example - - ```python - from typing import Annotated - - from fastapi import FastAPI, File, UploadFile - - app = FastAPI() - - - @app.post("/files/") - async def create_file(file: Annotated[bytes, File()]): - return {"file_size": len(file)} - - - @app.post("/uploadfile/") - async def create_upload_file(file: UploadFile): - return {"filename": file.filename} - ``` - """ - - file: Annotated[ - BinaryIO, - Doc("The standard Python file object (non-async)."), - ] - filename: Annotated[str | None, Doc("The original file name.")] - size: Annotated[int | None, Doc("The size of the file in bytes.")] - headers: Annotated[Headers, Doc("The headers of the request.")] - content_type: Annotated[ - str | None, Doc("The content type of the request, from the headers.") - ] - - async def write( - self, - data: Annotated[ - bytes, - Doc( - """ - The bytes to write to the file. - """ - ), - ], - ) -> None: - """ - Write some bytes to the file. - - You normally wouldn't use this from a file you read in a request. - - To be awaitable, compatible with async, this is run in threadpool. - """ - return await super().write(data) - - async def read( - self, - size: Annotated[ - int, - Doc( - """ - The number of bytes to read from the file. - """ - ), - ] = -1, - ) -> bytes: - """ - Read some bytes from the file. - - To be awaitable, compatible with async, this is run in threadpool. - """ - return await super().read(size) - - async def seek( - self, - offset: Annotated[ - int, - Doc( - """ - The position in bytes to seek to in the file. - """ - ), - ], - ) -> None: - """ - Move to a position in the file. - - Any next read or write will be done from that position. - - To be awaitable, compatible with async, this is run in threadpool. - """ - return await super().seek(offset) - - async def close(self) -> None: - """ - Close the file. - - To be awaitable, compatible with async, this is run in threadpool. - """ - return await super().close() - - @classmethod - def _validate(cls, __input_value: Any, _: Any) -> "UploadFile": - if not isinstance(__input_value, StarletteUploadFile): - raise ValueError(f"Expected UploadFile, received: {type(__input_value)}") - return cast(UploadFile, __input_value) - - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: Mapping[str, Any], handler: GetJsonSchemaHandler - ) -> dict[str, Any]: - return {"type": "string", "contentMediaType": "application/octet-stream"} - - @classmethod - def __get_pydantic_core_schema__( - cls, source: type[Any], handler: Callable[[Any], Mapping[str, Any]] - ) -> Mapping[str, Any]: - from ._compat.v2 import with_info_plain_validator_function - - return with_info_plain_validator_function(cls._validate) - - -class DefaultPlaceholder: - """ - You shouldn't use this class directly. - - It's used internally to recognize when a default value has been overwritten, even - if the overridden default value was truthy. - """ - - def __init__(self, value: Any): - self.value = value - - def __bool__(self) -> bool: - return bool(self.value) - - def __eq__(self, o: object) -> bool: - return isinstance(o, DefaultPlaceholder) and o.value == self.value - - -DefaultType = TypeVar("DefaultType") - - -def Default(value: DefaultType) -> DefaultType: - """ - You shouldn't use this function directly. - - It's used internally to recognize when a default value has been overwritten, even - if the overridden default value was truthy. - """ - return DefaultPlaceholder(value) # type: ignore - - -# Sentinel for "parameter not provided" in Param/FieldInfo. -# Typed as None to satisfy ty -_Unset = Default(None) diff --git a/notification-service/venv/Lib/site-packages/fastapi/dependencies/__init__.py b/notification-service/venv/Lib/site-packages/fastapi/dependencies/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/fastapi/dependencies/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/dependencies/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index a3b38c0..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/dependencies/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/dependencies/__pycache__/models.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/dependencies/__pycache__/models.cpython-312.pyc deleted file mode 100644 index 4176e6b..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/dependencies/__pycache__/models.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/dependencies/__pycache__/utils.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/dependencies/__pycache__/utils.cpython-312.pyc deleted file mode 100644 index 5bc080f..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/dependencies/__pycache__/utils.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/dependencies/models.py b/notification-service/venv/Lib/site-packages/fastapi/dependencies/models.py deleted file mode 100644 index 25ffb0d..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/dependencies/models.py +++ /dev/null @@ -1,193 +0,0 @@ -import inspect -import sys -from collections.abc import Callable -from dataclasses import dataclass, field -from functools import cached_property, partial -from typing import Any, Literal - -from fastapi._compat import ModelField -from fastapi.security.base import SecurityBase -from fastapi.types import DependencyCacheKey - -if sys.version_info >= (3, 13): # pragma: no cover - from inspect import iscoroutinefunction -else: # pragma: no cover - from asyncio import iscoroutinefunction - - -def _unwrapped_call(call: Callable[..., Any] | None) -> Any: - if call is None: - return call # pragma: no cover - unwrapped = inspect.unwrap(_impartial(call)) - return unwrapped - - -def _impartial(func: Callable[..., Any]) -> Callable[..., Any]: - while isinstance(func, partial): - func = func.func - return func - - -@dataclass -class Dependant: - path_params: list[ModelField] = field(default_factory=list) - query_params: list[ModelField] = field(default_factory=list) - header_params: list[ModelField] = field(default_factory=list) - cookie_params: list[ModelField] = field(default_factory=list) - body_params: list[ModelField] = field(default_factory=list) - dependencies: list["Dependant"] = field(default_factory=list) - name: str | None = None - call: Callable[..., Any] | None = None - request_param_name: str | None = None - websocket_param_name: str | None = None - http_connection_param_name: str | None = None - response_param_name: str | None = None - background_tasks_param_name: str | None = None - security_scopes_param_name: str | None = None - own_oauth_scopes: list[str] | None = None - parent_oauth_scopes: list[str] | None = None - use_cache: bool = True - path: str | None = None - scope: Literal["function", "request"] | None = None - - @cached_property - def oauth_scopes(self) -> list[str]: - scopes = self.parent_oauth_scopes.copy() if self.parent_oauth_scopes else [] - # This doesn't use a set to preserve order, just in case - for scope in self.own_oauth_scopes or []: - if scope not in scopes: - scopes.append(scope) - return scopes - - @cached_property - def cache_key(self) -> DependencyCacheKey: - scopes_for_cache = ( - tuple(sorted(set(self.oauth_scopes or []))) if self._uses_scopes else () - ) - return ( - self.call, - scopes_for_cache, - self.computed_scope or "", - ) - - @cached_property - def _uses_scopes(self) -> bool: - if self.own_oauth_scopes: - return True - if self.security_scopes_param_name is not None: - return True - if self._is_security_scheme: - return True - for sub_dep in self.dependencies: - if sub_dep._uses_scopes: - return True - return False - - @cached_property - def _is_security_scheme(self) -> bool: - if self.call is None: - return False # pragma: no cover - unwrapped = _unwrapped_call(self.call) - return isinstance(unwrapped, SecurityBase) - - # Mainly to get the type of SecurityBase, but it's the same self.call - @cached_property - def _security_scheme(self) -> SecurityBase: - unwrapped = _unwrapped_call(self.call) - assert isinstance(unwrapped, SecurityBase) - return unwrapped - - @cached_property - def _security_dependencies(self) -> list["Dependant"]: - security_deps = [dep for dep in self.dependencies if dep._is_security_scheme] - return security_deps - - @cached_property - def is_gen_callable(self) -> bool: - if self.call is None: - return False # pragma: no cover - if inspect.isgeneratorfunction( - _impartial(self.call) - ) or inspect.isgeneratorfunction(_unwrapped_call(self.call)): - return True - if inspect.isclass(_unwrapped_call(self.call)): - return False - dunder_call = getattr(_impartial(self.call), "__call__", None) # noqa: B004 - if dunder_call is None: - return False # pragma: no cover - if inspect.isgeneratorfunction( - _impartial(dunder_call) - ) or inspect.isgeneratorfunction(_unwrapped_call(dunder_call)): - return True - dunder_unwrapped_call = getattr(_unwrapped_call(self.call), "__call__", None) # noqa: B004 - if dunder_unwrapped_call is None: - return False # pragma: no cover - if inspect.isgeneratorfunction( - _impartial(dunder_unwrapped_call) - ) or inspect.isgeneratorfunction(_unwrapped_call(dunder_unwrapped_call)): - return True - return False - - @cached_property - def is_async_gen_callable(self) -> bool: - if self.call is None: - return False # pragma: no cover - if inspect.isasyncgenfunction( - _impartial(self.call) - ) or inspect.isasyncgenfunction(_unwrapped_call(self.call)): - return True - if inspect.isclass(_unwrapped_call(self.call)): - return False - dunder_call = getattr(_impartial(self.call), "__call__", None) # noqa: B004 - if dunder_call is None: - return False # pragma: no cover - if inspect.isasyncgenfunction( - _impartial(dunder_call) - ) or inspect.isasyncgenfunction(_unwrapped_call(dunder_call)): - return True - dunder_unwrapped_call = getattr(_unwrapped_call(self.call), "__call__", None) # noqa: B004 - if dunder_unwrapped_call is None: - return False # pragma: no cover - if inspect.isasyncgenfunction( - _impartial(dunder_unwrapped_call) - ) or inspect.isasyncgenfunction(_unwrapped_call(dunder_unwrapped_call)): - return True - return False - - @cached_property - def is_coroutine_callable(self) -> bool: - if self.call is None: - return False # pragma: no cover - if inspect.isroutine(_impartial(self.call)) and iscoroutinefunction( - _impartial(self.call) - ): - return True - if inspect.isroutine(_unwrapped_call(self.call)) and iscoroutinefunction( - _unwrapped_call(self.call) - ): - return True - if inspect.isclass(_unwrapped_call(self.call)): - return False - dunder_call = getattr(_impartial(self.call), "__call__", None) # noqa: B004 - if dunder_call is None: - return False # pragma: no cover - if iscoroutinefunction(_impartial(dunder_call)) or iscoroutinefunction( - _unwrapped_call(dunder_call) - ): - return True - dunder_unwrapped_call = getattr(_unwrapped_call(self.call), "__call__", None) # noqa: B004 - if dunder_unwrapped_call is None: - return False # pragma: no cover - if iscoroutinefunction( - _impartial(dunder_unwrapped_call) - ) or iscoroutinefunction(_unwrapped_call(dunder_unwrapped_call)): - return True - return False - - @cached_property - def computed_scope(self) -> str | None: - if self.scope: - return self.scope - if self.is_gen_callable or self.is_async_gen_callable: - return "request" - return None diff --git a/notification-service/venv/Lib/site-packages/fastapi/dependencies/utils.py b/notification-service/venv/Lib/site-packages/fastapi/dependencies/utils.py deleted file mode 100644 index aceca6a..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/dependencies/utils.py +++ /dev/null @@ -1,1057 +0,0 @@ -import dataclasses -import inspect -import sys -from collections.abc import ( - AsyncGenerator, - AsyncIterable, - AsyncIterator, - Callable, - Generator, - Iterable, - Iterator, - Mapping, - Sequence, -) -from contextlib import AsyncExitStack, contextmanager -from copy import copy, deepcopy -from dataclasses import dataclass -from typing import ( - Annotated, - Any, - ForwardRef, - Literal, - Union, - cast, - get_args, - get_origin, -) - -from fastapi import params -from fastapi._compat import ( - ModelField, - RequiredParam, - Undefined, - copy_field_info, - create_body_model, - evaluate_forwardref, - field_annotation_is_scalar, - field_annotation_is_scalar_sequence, - field_annotation_is_sequence, - get_cached_model_fields, - get_missing_field_error, - is_bytes_or_nonable_bytes_annotation, - is_bytes_sequence_annotation, - is_scalar_field, - is_uploadfile_or_nonable_uploadfile_annotation, - is_uploadfile_sequence_annotation, - lenient_issubclass, - sequence_types, - serialize_sequence_value, - value_is_sequence, -) -from fastapi.background import BackgroundTasks -from fastapi.concurrency import ( - asynccontextmanager, - contextmanager_in_threadpool, -) -from fastapi.dependencies.models import Dependant -from fastapi.exceptions import DependencyScopeError -from fastapi.logger import logger -from fastapi.security.oauth2 import SecurityScopes -from fastapi.types import DependencyCacheKey -from fastapi.utils import create_model_field, get_path_param_names -from pydantic import BaseModel, Json -from pydantic.fields import FieldInfo -from starlette.background import BackgroundTasks as StarletteBackgroundTasks -from starlette.concurrency import run_in_threadpool -from starlette.datastructures import ( - FormData, - Headers, - ImmutableMultiDict, - QueryParams, - UploadFile, -) -from starlette.requests import HTTPConnection, Request -from starlette.responses import Response -from starlette.websockets import WebSocket -from typing_inspection.typing_objects import is_typealiastype - -multipart_not_installed_error = ( - 'Form data requires "python-multipart" to be installed. \n' - 'You can install "python-multipart" with: \n\n' - "pip install python-multipart\n" -) -multipart_incorrect_install_error = ( - 'Form data requires "python-multipart" to be installed. ' - 'It seems you installed "multipart" instead. \n' - 'You can remove "multipart" with: \n\n' - "pip uninstall multipart\n\n" - 'And then install "python-multipart" with: \n\n' - "pip install python-multipart\n" -) - - -def ensure_multipart_is_installed() -> None: - try: - from python_multipart import __version__ - - # Import an attribute that can be mocked/deleted in testing - assert __version__ > "0.0.12" - except (ImportError, AssertionError): - try: - # __version__ is available in both multiparts, and can be mocked - from multipart import ( # type: ignore[no-redef,import-untyped] # ty: ignore[unused-ignore-comment] - __version__, - ) - - assert __version__ - try: - # parse_options_header is only available in the right multipart - from multipart.multipart import ( # type: ignore[import-untyped] # ty: ignore[unused-ignore-comment] - parse_options_header, - ) - - assert parse_options_header - except ImportError: - logger.error(multipart_incorrect_install_error) - raise RuntimeError(multipart_incorrect_install_error) from None - except ImportError: - logger.error(multipart_not_installed_error) - raise RuntimeError(multipart_not_installed_error) from None - - -def get_parameterless_sub_dependant(*, depends: params.Depends, path: str) -> Dependant: - assert callable(depends.dependency), ( - "A parameter-less dependency must have a callable dependency" - ) - own_oauth_scopes: list[str] = [] - if isinstance(depends, params.Security) and depends.scopes: - own_oauth_scopes.extend(depends.scopes) - return get_dependant( - path=path, - call=depends.dependency, - scope=depends.scope, - own_oauth_scopes=own_oauth_scopes, - ) - - -def get_flat_dependant( - dependant: Dependant, - *, - skip_repeats: bool = False, - visited: list[DependencyCacheKey] | None = None, - parent_oauth_scopes: list[str] | None = None, -) -> Dependant: - if visited is None: - visited = [] - visited.append(dependant.cache_key) - use_parent_oauth_scopes = (parent_oauth_scopes or []) + ( - dependant.oauth_scopes or [] - ) - - flat_dependant = Dependant( - path_params=dependant.path_params.copy(), - query_params=dependant.query_params.copy(), - header_params=dependant.header_params.copy(), - cookie_params=dependant.cookie_params.copy(), - body_params=dependant.body_params.copy(), - name=dependant.name, - call=dependant.call, - request_param_name=dependant.request_param_name, - websocket_param_name=dependant.websocket_param_name, - http_connection_param_name=dependant.http_connection_param_name, - response_param_name=dependant.response_param_name, - background_tasks_param_name=dependant.background_tasks_param_name, - security_scopes_param_name=dependant.security_scopes_param_name, - own_oauth_scopes=dependant.own_oauth_scopes, - parent_oauth_scopes=use_parent_oauth_scopes, - use_cache=dependant.use_cache, - path=dependant.path, - scope=dependant.scope, - ) - for sub_dependant in dependant.dependencies: - if skip_repeats and sub_dependant.cache_key in visited: - continue - flat_sub = get_flat_dependant( - sub_dependant, - skip_repeats=skip_repeats, - visited=visited, - parent_oauth_scopes=flat_dependant.oauth_scopes, - ) - flat_dependant.dependencies.append(flat_sub) - flat_dependant.path_params.extend(flat_sub.path_params) - flat_dependant.query_params.extend(flat_sub.query_params) - flat_dependant.header_params.extend(flat_sub.header_params) - flat_dependant.cookie_params.extend(flat_sub.cookie_params) - flat_dependant.body_params.extend(flat_sub.body_params) - flat_dependant.dependencies.extend(flat_sub.dependencies) - - return flat_dependant - - -def _get_flat_fields_from_params(fields: list[ModelField]) -> list[ModelField]: - if not fields: - return fields - first_field = fields[0] - if len(fields) == 1 and lenient_issubclass( - first_field.field_info.annotation, BaseModel - ): - fields_to_extract = get_cached_model_fields(first_field.field_info.annotation) - return fields_to_extract - return fields - - -def get_flat_params(dependant: Dependant) -> list[ModelField]: - flat_dependant = get_flat_dependant(dependant, skip_repeats=True) - path_params = _get_flat_fields_from_params(flat_dependant.path_params) - query_params = _get_flat_fields_from_params(flat_dependant.query_params) - header_params = _get_flat_fields_from_params(flat_dependant.header_params) - cookie_params = _get_flat_fields_from_params(flat_dependant.cookie_params) - return path_params + query_params + header_params + cookie_params - - -def _get_signature(call: Callable[..., Any]) -> inspect.Signature: - try: - signature = inspect.signature(call, eval_str=True) - except NameError: - # Handle type annotations with if TYPE_CHECKING, not used by FastAPI - # e.g. dependency return types - if sys.version_info >= (3, 14): - from annotationlib import Format - - signature = inspect.signature(call, annotation_format=Format.FORWARDREF) - else: - signature = inspect.signature(call) - return signature - - -def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: - signature = _get_signature(call) - unwrapped = inspect.unwrap(call) - globalns = getattr(unwrapped, "__globals__", {}) - typed_params = [ - inspect.Parameter( - name=param.name, - kind=param.kind, - default=param.default, - annotation=get_typed_annotation(param.annotation, globalns), - ) - for param in signature.parameters.values() - ] - typed_signature = inspect.Signature(typed_params) - return typed_signature - - -def get_typed_annotation(annotation: Any, globalns: dict[str, Any]) -> Any: - if isinstance(annotation, str): - annotation = ForwardRef(annotation) - annotation = evaluate_forwardref(annotation, globalns, globalns) - if annotation is type(None): - return None - return annotation - - -def get_typed_return_annotation(call: Callable[..., Any]) -> Any: - signature = _get_signature(call) - unwrapped = inspect.unwrap(call) - annotation = signature.return_annotation - - if annotation is inspect.Signature.empty: - return None - - globalns = getattr(unwrapped, "__globals__", {}) - return get_typed_annotation(annotation, globalns) - - -_STREAM_ORIGINS = { - AsyncIterable, - AsyncIterator, - AsyncGenerator, - Iterable, - Iterator, - Generator, -} - - -def get_stream_item_type(annotation: Any) -> Any | None: - origin = get_origin(annotation) - if origin is not None and origin in _STREAM_ORIGINS: - type_args = get_args(annotation) - if type_args: - return type_args[0] - return Any - return None - - -def get_dependant( - *, - path: str, - call: Callable[..., Any], - name: str | None = None, - own_oauth_scopes: list[str] | None = None, - parent_oauth_scopes: list[str] | None = None, - use_cache: bool = True, - scope: Literal["function", "request"] | None = None, -) -> Dependant: - dependant = Dependant( - call=call, - name=name, - path=path, - use_cache=use_cache, - scope=scope, - own_oauth_scopes=own_oauth_scopes, - parent_oauth_scopes=parent_oauth_scopes, - ) - current_scopes = (parent_oauth_scopes or []) + (own_oauth_scopes or []) - path_param_names = get_path_param_names(path) - endpoint_signature = get_typed_signature(call) - signature_params = endpoint_signature.parameters - for param_name, param in signature_params.items(): - is_path_param = param_name in path_param_names - param_details = analyze_param( - param_name=param_name, - annotation=param.annotation, - value=param.default, - is_path_param=is_path_param, - ) - if param_details.depends is not None: - assert param_details.depends.dependency - if ( - (dependant.is_gen_callable or dependant.is_async_gen_callable) - and dependant.computed_scope == "request" - and param_details.depends.scope == "function" - ): - assert dependant.call - call_name = getattr(dependant.call, "__name__", "") - raise DependencyScopeError( - f'The dependency "{call_name}" has a scope of ' - '"request", it cannot depend on dependencies with scope "function".' - ) - sub_own_oauth_scopes: list[str] = [] - if isinstance(param_details.depends, params.Security): - if param_details.depends.scopes: - sub_own_oauth_scopes = list(param_details.depends.scopes) - sub_dependant = get_dependant( - path=path, - call=param_details.depends.dependency, - name=param_name, - own_oauth_scopes=sub_own_oauth_scopes, - parent_oauth_scopes=current_scopes, - use_cache=param_details.depends.use_cache, - scope=param_details.depends.scope, - ) - dependant.dependencies.append(sub_dependant) - continue - if add_non_field_param_to_dependency( - param_name=param_name, - type_annotation=param_details.type_annotation, - dependant=dependant, - ): - assert param_details.field is None, ( - f"Cannot specify multiple FastAPI annotations for {param_name!r}" - ) - continue - assert param_details.field is not None - if isinstance(param_details.field.field_info, params.Body): - dependant.body_params.append(param_details.field) - else: - add_param_to_fields(field=param_details.field, dependant=dependant) - return dependant - - -def add_non_field_param_to_dependency( - *, param_name: str, type_annotation: Any, dependant: Dependant -) -> bool | None: - if lenient_issubclass(type_annotation, Request): - dependant.request_param_name = param_name - return True - elif lenient_issubclass(type_annotation, WebSocket): - dependant.websocket_param_name = param_name - return True - elif lenient_issubclass(type_annotation, HTTPConnection): - dependant.http_connection_param_name = param_name - return True - elif lenient_issubclass(type_annotation, Response): - dependant.response_param_name = param_name - return True - elif lenient_issubclass(type_annotation, StarletteBackgroundTasks): - dependant.background_tasks_param_name = param_name - return True - elif lenient_issubclass(type_annotation, SecurityScopes): - dependant.security_scopes_param_name = param_name - return True - return None - - -@dataclass -class ParamDetails: - type_annotation: Any - depends: params.Depends | None - field: ModelField | None - - -def analyze_param( - *, - param_name: str, - annotation: Any, - value: Any, - is_path_param: bool, -) -> ParamDetails: - field_info = None - depends = None - type_annotation: Any = Any - use_annotation: Any = Any - if is_typealiastype(annotation): - # unpack in case PEP 695 type syntax is used - annotation = annotation.__value__ - if annotation is not inspect.Signature.empty: - use_annotation = annotation - type_annotation = annotation - # Extract Annotated info - if get_origin(use_annotation) is Annotated: - annotated_args = get_args(annotation) - type_annotation = annotated_args[0] - fastapi_annotations = [ - arg - for arg in annotated_args[1:] - if isinstance(arg, (FieldInfo, params.Depends)) - ] - fastapi_specific_annotations = [ - arg - for arg in fastapi_annotations - if isinstance( - arg, - ( - params.Param, - params.Body, - params.Depends, - ), - ) - ] - if fastapi_specific_annotations: - fastapi_annotation: FieldInfo | params.Depends | None = ( - fastapi_specific_annotations[-1] - ) - else: - fastapi_annotation = None - # Set default for Annotated FieldInfo - if isinstance(fastapi_annotation, FieldInfo): - # Copy `field_info` because we mutate `field_info.default` below. - field_info = copy_field_info( - field_info=fastapi_annotation, - annotation=use_annotation, - ) - assert ( - field_info.default == Undefined or field_info.default == RequiredParam - ), ( - f"`{field_info.__class__.__name__}` default value cannot be set in" - f" `Annotated` for {param_name!r}. Set the default value with `=` instead." - ) - if value is not inspect.Signature.empty: - assert not is_path_param, "Path parameters cannot have default values" - field_info.default = value - else: - field_info.default = RequiredParam - # Get Annotated Depends - elif isinstance(fastapi_annotation, params.Depends): - depends = fastapi_annotation - # Get Depends from default value - if isinstance(value, params.Depends): - assert depends is None, ( - "Cannot specify `Depends` in `Annotated` and default value" - f" together for {param_name!r}" - ) - assert field_info is None, ( - "Cannot specify a FastAPI annotation in `Annotated` and `Depends` as a" - f" default value together for {param_name!r}" - ) - depends = value - # Get FieldInfo from default value - elif isinstance(value, FieldInfo): - assert field_info is None, ( - "Cannot specify FastAPI annotations in `Annotated` and default value" - f" together for {param_name!r}" - ) - field_info = value - if isinstance(field_info, FieldInfo): - field_info.annotation = type_annotation - - # Get Depends from type annotation - if depends is not None and depends.dependency is None: - # Copy `depends` before mutating it - depends = copy(depends) - depends = dataclasses.replace(depends, dependency=type_annotation) - - # Handle non-param type annotations like Request - # Only apply special handling when there's no explicit Depends - if there's a Depends, - # the dependency will be called and its return value used instead of the special injection - if depends is None and lenient_issubclass( - type_annotation, - ( - Request, - WebSocket, - HTTPConnection, - Response, - StarletteBackgroundTasks, - SecurityScopes, - ), - ): - assert field_info is None, ( - f"Cannot specify FastAPI annotation for type {type_annotation!r}" - ) - # Handle default assignations, neither field_info nor depends was not found in Annotated nor default value - elif field_info is None and depends is None: - default_value = value if value is not inspect.Signature.empty else RequiredParam - if is_path_param: - # We might check here that `default_value is RequiredParam`, but the fact is that the same - # parameter might sometimes be a path parameter and sometimes not. See - # `tests/test_infer_param_optionality.py` for an example. - field_info = params.Path(annotation=use_annotation) - elif is_uploadfile_or_nonable_uploadfile_annotation( - type_annotation - ) or is_uploadfile_sequence_annotation(type_annotation): - field_info = params.File(annotation=use_annotation, default=default_value) - elif not field_annotation_is_scalar(annotation=type_annotation): - field_info = params.Body(annotation=use_annotation, default=default_value) - else: - field_info = params.Query(annotation=use_annotation, default=default_value) - - field = None - # It's a field_info, not a dependency - if field_info is not None: - # Handle field_info.in_ - if is_path_param: - assert isinstance(field_info, params.Path), ( - f"Cannot use `{field_info.__class__.__name__}` for path param" - f" {param_name!r}" - ) - elif ( - isinstance(field_info, params.Param) - and getattr(field_info, "in_", None) is None - ): - field_info.in_ = params.ParamTypes.query - use_annotation_from_field_info = use_annotation - if isinstance(field_info, params.Form): - ensure_multipart_is_installed() - if not field_info.alias and getattr(field_info, "convert_underscores", None): - alias = param_name.replace("_", "-") - else: - alias = field_info.alias or param_name - field_info.alias = alias - field = create_model_field( - name=param_name, - type_=use_annotation_from_field_info, - default=field_info.default, - alias=alias, - field_info=field_info, - ) - if is_path_param: - assert is_scalar_field(field=field), ( - "Path params must be of one of the supported types" - ) - elif isinstance(field_info, params.Query): - assert ( - is_scalar_field(field) - or field_annotation_is_scalar_sequence(field.field_info.annotation) - or lenient_issubclass(field.field_info.annotation, BaseModel) - ), f"Query parameter {param_name!r} must be one of the supported types" - - return ParamDetails(type_annotation=type_annotation, depends=depends, field=field) - - -def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None: - field_info = field.field_info - field_info_in = getattr(field_info, "in_", None) - if field_info_in == params.ParamTypes.path: - dependant.path_params.append(field) - elif field_info_in == params.ParamTypes.query: - dependant.query_params.append(field) - elif field_info_in == params.ParamTypes.header: - dependant.header_params.append(field) - else: - assert field_info_in == params.ParamTypes.cookie, ( - f"non-body parameters must be in path, query, header or cookie: {field.name}" - ) - dependant.cookie_params.append(field) - - -async def _solve_generator( - *, dependant: Dependant, stack: AsyncExitStack, sub_values: dict[str, Any] -) -> Any: - assert dependant.call - if dependant.is_async_gen_callable: - cm = asynccontextmanager(dependant.call)(**sub_values) - elif dependant.is_gen_callable: - cm = contextmanager_in_threadpool(contextmanager(dependant.call)(**sub_values)) - return await stack.enter_async_context(cm) - - -@dataclass -class SolvedDependency: - values: dict[str, Any] - errors: list[Any] - background_tasks: StarletteBackgroundTasks | None - response: Response - dependency_cache: dict[DependencyCacheKey, Any] - - -async def solve_dependencies( - *, - request: Request | WebSocket, - dependant: Dependant, - body: dict[str, Any] | FormData | bytes | None = None, - background_tasks: StarletteBackgroundTasks | None = None, - response: Response | None = None, - dependency_overrides_provider: Any | None = None, - dependency_cache: dict[DependencyCacheKey, Any] | None = None, - # TODO: remove this parameter later, no longer used, not removing it yet as some - # people might be monkey patching this function (although that's not supported) - async_exit_stack: AsyncExitStack, - embed_body_fields: bool, -) -> SolvedDependency: - request_astack = request.scope.get("fastapi_inner_astack") - assert isinstance(request_astack, AsyncExitStack), ( - "fastapi_inner_astack not found in request scope" - ) - function_astack = request.scope.get("fastapi_function_astack") - assert isinstance(function_astack, AsyncExitStack), ( - "fastapi_function_astack not found in request scope" - ) - values: dict[str, Any] = {} - errors: list[Any] = [] - if response is None: - response = Response() - del response.headers["content-length"] - response.status_code = None # type: ignore # ty: ignore[unused-ignore-comment] - if dependency_cache is None: - dependency_cache = {} - for sub_dependant in dependant.dependencies: - sub_dependant.call = cast(Callable[..., Any], sub_dependant.call) - call = sub_dependant.call - use_sub_dependant = sub_dependant - if ( - dependency_overrides_provider - and dependency_overrides_provider.dependency_overrides - ): - original_call = sub_dependant.call - call = getattr( - dependency_overrides_provider, "dependency_overrides", {} - ).get(original_call, original_call) - use_path: str = sub_dependant.path # type: ignore - use_sub_dependant = get_dependant( - path=use_path, - call=call, - name=sub_dependant.name, - parent_oauth_scopes=sub_dependant.oauth_scopes, - scope=sub_dependant.scope, - ) - - solved_result = await solve_dependencies( - request=request, - dependant=use_sub_dependant, - body=body, - background_tasks=background_tasks, - response=response, - dependency_overrides_provider=dependency_overrides_provider, - dependency_cache=dependency_cache, - async_exit_stack=async_exit_stack, - embed_body_fields=embed_body_fields, - ) - background_tasks = solved_result.background_tasks - if solved_result.errors: - errors.extend(solved_result.errors) - continue - if sub_dependant.use_cache and sub_dependant.cache_key in dependency_cache: - solved = dependency_cache[sub_dependant.cache_key] - elif ( - use_sub_dependant.is_gen_callable or use_sub_dependant.is_async_gen_callable - ): - use_astack = request_astack - if sub_dependant.scope == "function": - use_astack = function_astack - solved = await _solve_generator( - dependant=use_sub_dependant, - stack=use_astack, - sub_values=solved_result.values, - ) - elif use_sub_dependant.is_coroutine_callable: - solved = await call(**solved_result.values) - else: - solved = await run_in_threadpool(call, **solved_result.values) - if sub_dependant.name is not None: - values[sub_dependant.name] = solved - if sub_dependant.cache_key not in dependency_cache: - dependency_cache[sub_dependant.cache_key] = solved - path_values, path_errors = request_params_to_args( - dependant.path_params, request.path_params - ) - query_values, query_errors = request_params_to_args( - dependant.query_params, request.query_params - ) - header_values, header_errors = request_params_to_args( - dependant.header_params, request.headers - ) - cookie_values, cookie_errors = request_params_to_args( - dependant.cookie_params, request.cookies - ) - values.update(path_values) - values.update(query_values) - values.update(header_values) - values.update(cookie_values) - errors += path_errors + query_errors + header_errors + cookie_errors - if dependant.body_params: - ( - body_values, - body_errors, - ) = await request_body_to_args( # body_params checked above - body_fields=dependant.body_params, - received_body=body, - embed_body_fields=embed_body_fields, - ) - values.update(body_values) - errors.extend(body_errors) - if dependant.http_connection_param_name: - values[dependant.http_connection_param_name] = request - if dependant.request_param_name and isinstance(request, Request): - values[dependant.request_param_name] = request - elif dependant.websocket_param_name and isinstance(request, WebSocket): - values[dependant.websocket_param_name] = request - if dependant.background_tasks_param_name: - if background_tasks is None: - background_tasks = BackgroundTasks() - values[dependant.background_tasks_param_name] = background_tasks - if dependant.response_param_name: - values[dependant.response_param_name] = response - if dependant.security_scopes_param_name: - values[dependant.security_scopes_param_name] = SecurityScopes( - scopes=dependant.oauth_scopes - ) - return SolvedDependency( - values=values, - errors=errors, - background_tasks=background_tasks, - response=response, - dependency_cache=dependency_cache, - ) - - -def _validate_value_with_model_field( - *, field: ModelField, value: Any, values: dict[str, Any], loc: tuple[str, ...] -) -> tuple[Any, list[Any]]: - if value is None: - if field.field_info.is_required(): - return None, [get_missing_field_error(loc=loc)] - else: - return deepcopy(field.default), [] - return field.validate(value, values, loc=loc) - - -def _is_json_field(field: ModelField) -> bool: - return any(type(item) is Json for item in field.field_info.metadata) - - -def _get_multidict_value( - field: ModelField, values: Mapping[str, Any], alias: str | None = None -) -> Any: - alias = alias or get_validation_alias(field) - if ( - (not _is_json_field(field)) - and field_annotation_is_sequence(field.field_info.annotation) - and isinstance(values, (ImmutableMultiDict, Headers)) - ): - value = values.getlist(alias) - else: - value = values.get(alias, None) - if ( - value is None - or ( - isinstance(field.field_info, params.Form) - and isinstance(value, str) # For type checks - and value == "" - ) - or ( - field_annotation_is_sequence(field.field_info.annotation) - and len(value) == 0 - ) - ): - if field.field_info.is_required(): - return - else: - return deepcopy(field.default) - return value - - -def request_params_to_args( - fields: Sequence[ModelField], - received_params: Mapping[str, Any] | QueryParams | Headers, -) -> tuple[dict[str, Any], list[Any]]: - values: dict[str, Any] = {} - errors: list[dict[str, Any]] = [] - - if not fields: - return values, errors - - first_field = fields[0] - fields_to_extract = fields - single_not_embedded_field = False - default_convert_underscores = True - if len(fields) == 1 and lenient_issubclass( - first_field.field_info.annotation, BaseModel - ): - fields_to_extract = get_cached_model_fields(first_field.field_info.annotation) - single_not_embedded_field = True - # If headers are in a Pydantic model, the way to disable convert_underscores - # would be with Header(convert_underscores=False) at the Pydantic model level - default_convert_underscores = getattr( - first_field.field_info, "convert_underscores", True - ) - - params_to_process: dict[str, Any] = {} - - processed_keys = set() - - for field in fields_to_extract: - alias = None - if isinstance(received_params, Headers): - # Handle fields extracted from a Pydantic Model for a header, each field - # doesn't have a FieldInfo of type Header with the default convert_underscores=True - convert_underscores = getattr( - field.field_info, "convert_underscores", default_convert_underscores - ) - if convert_underscores: - alias = get_validation_alias(field) - if alias == field.name: - alias = alias.replace("_", "-") - value = _get_multidict_value(field, received_params, alias=alias) - if value is not None: - params_to_process[get_validation_alias(field)] = value - processed_keys.add(alias or get_validation_alias(field)) - - for key in received_params.keys(): - if key not in processed_keys: - if isinstance(received_params, (ImmutableMultiDict, Headers)): - value = received_params.getlist(key) - if isinstance(value, list) and (len(value) == 1): - params_to_process[key] = value[0] - else: - params_to_process[key] = value - else: - params_to_process[key] = received_params.get(key) - - if single_not_embedded_field: - field_info = first_field.field_info - assert isinstance(field_info, params.Param), ( - "Params must be subclasses of Param" - ) - loc: tuple[str, ...] = (field_info.in_.value,) - v_, errors_ = _validate_value_with_model_field( - field=first_field, value=params_to_process, values=values, loc=loc - ) - return {first_field.name: v_}, errors_ - - for field in fields: - value = _get_multidict_value(field, received_params) - field_info = field.field_info - assert isinstance(field_info, params.Param), ( - "Params must be subclasses of Param" - ) - loc = (field_info.in_.value, get_validation_alias(field)) - v_, errors_ = _validate_value_with_model_field( - field=field, value=value, values=values, loc=loc - ) - if errors_: - errors.extend(errors_) - else: - values[field.name] = v_ - return values, errors - - -def is_union_of_base_models(field_type: Any) -> bool: - """Check if field type is a Union where all members are BaseModel subclasses.""" - from fastapi.types import UnionType - - origin = get_origin(field_type) - - # Check if it's a Union type (covers both typing.Union and types.UnionType in Python 3.10+) - if origin is not Union and origin is not UnionType: - return False - - union_args = get_args(field_type) - - for arg in union_args: - if not lenient_issubclass(arg, BaseModel): - return False - - return True - - -def _should_embed_body_fields(fields: list[ModelField]) -> bool: - if not fields: - return False - # More than one dependency could have the same field, it would show up as multiple - # fields but it's the same one, so count them by name - body_param_names_set = {field.name for field in fields} - # A top level field has to be a single field, not multiple - if len(body_param_names_set) > 1: - return True - first_field = fields[0] - # If it explicitly specifies it is embedded, it has to be embedded - if getattr(first_field.field_info, "embed", None): - return True - # If it's a Form (or File) field, it has to be a BaseModel (or a union of BaseModels) to be top level - # otherwise it has to be embedded, so that the key value pair can be extracted - if ( - isinstance(first_field.field_info, params.Form) - and not lenient_issubclass(first_field.field_info.annotation, BaseModel) - and not is_union_of_base_models(first_field.field_info.annotation) - ): - return True - return False - - -async def _extract_form_body( - body_fields: list[ModelField], - received_body: FormData, -) -> dict[str, Any]: - values = {} - - for field in body_fields: - value = _get_multidict_value(field, received_body) - field_info = field.field_info - if ( - isinstance(field_info, params.File) - and is_bytes_or_nonable_bytes_annotation(field.field_info.annotation) - and isinstance(value, UploadFile) - ): - value = await value.read() - elif ( - is_bytes_sequence_annotation(field.field_info.annotation) - and isinstance(field_info, params.File) - and value_is_sequence(value) - ): - # For types - assert isinstance(value, sequence_types) - results: list[bytes | str] = [] - for sub_value in value: - results.append(await sub_value.read()) - value = serialize_sequence_value(field=field, value=results) - if value is not None: - values[get_validation_alias(field)] = value - field_aliases = {get_validation_alias(field) for field in body_fields} - for key in received_body.keys(): - if key not in field_aliases: - param_values = received_body.getlist(key) - if len(param_values) == 1: - values[key] = param_values[0] - else: - values[key] = param_values - return values - - -async def request_body_to_args( - body_fields: list[ModelField], - received_body: dict[str, Any] | FormData | bytes | None, - embed_body_fields: bool, -) -> tuple[dict[str, Any], list[dict[str, Any]]]: - values: dict[str, Any] = {} - errors: list[dict[str, Any]] = [] - assert body_fields, "request_body_to_args() should be called with fields" - single_not_embedded_field = len(body_fields) == 1 and not embed_body_fields - first_field = body_fields[0] - body_to_process = received_body - - fields_to_extract: list[ModelField] = body_fields - - if ( - single_not_embedded_field - and lenient_issubclass(first_field.field_info.annotation, BaseModel) - and isinstance(received_body, FormData) - ): - fields_to_extract = get_cached_model_fields(first_field.field_info.annotation) - - if isinstance(received_body, FormData): - body_to_process = await _extract_form_body(fields_to_extract, received_body) - - if single_not_embedded_field: - loc: tuple[str, ...] = ("body",) - v_, errors_ = _validate_value_with_model_field( - field=first_field, value=body_to_process, values=values, loc=loc - ) - return {first_field.name: v_}, errors_ - for field in body_fields: - loc = ("body", get_validation_alias(field)) - value: Any | None = None - if body_to_process is not None and not isinstance(body_to_process, bytes): - try: - value = body_to_process.get(get_validation_alias(field)) - # If the received body is a list, not a dict - except AttributeError: - errors.append(get_missing_field_error(loc)) - continue - v_, errors_ = _validate_value_with_model_field( - field=field, value=value, values=values, loc=loc - ) - if errors_: - errors.extend(errors_) - else: - values[field.name] = v_ - return values, errors - - -def get_body_field( - *, flat_dependant: Dependant, name: str, embed_body_fields: bool -) -> ModelField | None: - """ - Get a ModelField representing the request body for a path operation, combining - all body parameters into a single field if necessary. - - Used to check if it's form data (with `isinstance(body_field, params.Form)`) - or JSON and to generate the JSON Schema for a request body. - - This is **not** used to validate/parse the request body, that's done with each - individual body parameter. - """ - if not flat_dependant.body_params: - return None - first_param = flat_dependant.body_params[0] - if not embed_body_fields: - return first_param - model_name = "Body_" + name - BodyModel = create_body_model( - fields=flat_dependant.body_params, model_name=model_name - ) - required = any( - True for f in flat_dependant.body_params if f.field_info.is_required() - ) - BodyFieldInfo_kwargs: dict[str, Any] = { - "annotation": BodyModel, - "alias": "body", - } - if not required: - BodyFieldInfo_kwargs["default"] = None - if any(isinstance(f.field_info, params.File) for f in flat_dependant.body_params): - BodyFieldInfo: type[params.Body] = params.File - elif any(isinstance(f.field_info, params.Form) for f in flat_dependant.body_params): - BodyFieldInfo = params.Form - else: - BodyFieldInfo = params.Body - - body_param_media_types = [ - f.field_info.media_type - for f in flat_dependant.body_params - if isinstance(f.field_info, params.Body) - ] - if len(set(body_param_media_types)) == 1: - BodyFieldInfo_kwargs["media_type"] = body_param_media_types[0] - final_field = create_model_field( - name="body", - type_=BodyModel, - alias="body", - field_info=BodyFieldInfo(**BodyFieldInfo_kwargs), - ) - return final_field - - -def get_validation_alias(field: ModelField) -> str: - va = getattr(field, "validation_alias", None) - return va or field.alias diff --git a/notification-service/venv/Lib/site-packages/fastapi/encoders.py b/notification-service/venv/Lib/site-packages/fastapi/encoders.py deleted file mode 100644 index 43f2410..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/encoders.py +++ /dev/null @@ -1,364 +0,0 @@ -import dataclasses -import datetime -from collections import defaultdict, deque -from collections.abc import Callable -from decimal import Decimal -from enum import Enum -from ipaddress import ( - IPv4Address, - IPv4Interface, - IPv4Network, - IPv6Address, - IPv6Interface, - IPv6Network, -) -from pathlib import Path, PurePath -from re import Pattern -from types import GeneratorType -from typing import Annotated, Any -from uuid import UUID - -from annotated_doc import Doc -from fastapi.exceptions import PydanticV1NotSupportedError -from fastapi.types import IncEx -from pydantic import BaseModel -from pydantic.networks import AnyUrl, NameEmail -from pydantic.types import SecretBytes, SecretStr -from pydantic_core import PydanticUndefinedType - -from ._compat import ( - Url, - is_pydantic_v1_model_instance, -) - -try: - # pydantic.color.Color is deprecated since v2.0b3, but supporting for bwd-compat - from pydantic.color import Color # ty: ignore[deprecated] -except ImportError: # pragma: no cover - - class Color: # type: ignore[no-redef] # ty: ignore[unused-ignore-comment] - pass - - -try: - # Supporting the new Color format for newer versions of Pydantic - from pydantic_extra_types.color import Color as PyExtraColor -except ImportError: # pragma: no cover - - class PyExtraColor: # type: ignore[no-redef] # ty: ignore[unused-ignore-comment] - pass - - -# Taken from Pydantic v1 as is -def isoformat(o: datetime.date | datetime.time) -> str: - return o.isoformat() - - -# Adapted from Pydantic v1 -# TODO: pv2 should this return strings instead? -def decimal_encoder(dec_value: Decimal) -> int | float: - """ - Encodes a Decimal as int if there's no exponent, otherwise float - - This is useful when we use ConstrainedDecimal to represent Numeric(x,0) - where an integer (but not int typed) is used. Encoding this as a float - results in failed round-tripping between encode and parse. - Our Id type is a prime example of this. - - >>> decimal_encoder(Decimal("1.0")) - 1.0 - - >>> decimal_encoder(Decimal("1")) - 1 - - >>> decimal_encoder(Decimal("NaN")) - nan - """ - exponent = dec_value.as_tuple().exponent - if isinstance(exponent, int) and exponent >= 0: - return int(dec_value) - else: - return float(dec_value) - - -ENCODERS_BY_TYPE: dict[type[Any], Callable[[Any], Any]] = { - bytes: lambda o: o.decode(), - Color: str, - PyExtraColor: str, - datetime.date: isoformat, - datetime.datetime: isoformat, - datetime.time: isoformat, - datetime.timedelta: lambda td: td.total_seconds(), - Decimal: decimal_encoder, - Enum: lambda o: o.value, - frozenset: list, - deque: list, - GeneratorType: list, - IPv4Address: str, - IPv4Interface: str, - IPv4Network: str, - IPv6Address: str, - IPv6Interface: str, - IPv6Network: str, - NameEmail: str, - Path: str, - Pattern: lambda o: o.pattern, - SecretBytes: str, - SecretStr: str, - set: list, - UUID: str, - Url: str, - AnyUrl: str, -} - - -def generate_encoders_by_class_tuples( - type_encoder_map: dict[Any, Callable[[Any], Any]], -) -> dict[Callable[[Any], Any], tuple[Any, ...]]: - encoders_by_class_tuples: dict[Callable[[Any], Any], tuple[Any, ...]] = defaultdict( - tuple - ) - for type_, encoder in type_encoder_map.items(): - encoders_by_class_tuples[encoder] += (type_,) - return encoders_by_class_tuples - - -encoders_by_class_tuples = generate_encoders_by_class_tuples(ENCODERS_BY_TYPE) - - -def jsonable_encoder( - obj: Annotated[ - Any, - Doc( - """ - The input object to convert to JSON. - """ - ), - ], - include: Annotated[ - IncEx | None, - Doc( - """ - Pydantic's `include` parameter, passed to Pydantic models to set the - fields to include. - """ - ), - ] = None, - exclude: Annotated[ - IncEx | None, - Doc( - """ - Pydantic's `exclude` parameter, passed to Pydantic models to set the - fields to exclude. - """ - ), - ] = None, - by_alias: Annotated[ - bool, - Doc( - """ - Pydantic's `by_alias` parameter, passed to Pydantic models to define if - the output should use the alias names (when provided) or the Python - attribute names. In an API, if you set an alias, it's probably because you - want to use it in the result, so you probably want to leave this set to - `True`. - """ - ), - ] = True, - exclude_unset: Annotated[ - bool, - Doc( - """ - Pydantic's `exclude_unset` parameter, passed to Pydantic models to define - if it should exclude from the output the fields that were not explicitly - set (and that only had their default values). - """ - ), - ] = False, - exclude_defaults: Annotated[ - bool, - Doc( - """ - Pydantic's `exclude_defaults` parameter, passed to Pydantic models to define - if it should exclude from the output the fields that had the same default - value, even when they were explicitly set. - """ - ), - ] = False, - exclude_none: Annotated[ - bool, - Doc( - """ - Pydantic's `exclude_none` parameter, passed to Pydantic models to define - if it should exclude from the output any fields that have a `None` value. - """ - ), - ] = False, - custom_encoder: Annotated[ - dict[Any, Callable[[Any], Any]] | None, - Doc( - """ - Pydantic's `custom_encoder` parameter, passed to Pydantic models to define - a custom encoder. - """ - ), - ] = None, - sqlalchemy_safe: Annotated[ - bool, - Doc( - """ - Exclude from the output any fields that start with the name `_sa`. - - This is mainly a hack for compatibility with SQLAlchemy objects, they - store internal SQLAlchemy-specific state in attributes named with `_sa`, - and those objects can't (and shouldn't be) serialized to JSON. - """ - ), - ] = True, -) -> Any: - """ - Convert any object to something that can be encoded in JSON. - - This is used internally by FastAPI to make sure anything you return can be - encoded as JSON before it is sent to the client. - - You can also use it yourself, for example to convert objects before saving them - in a database that supports only JSON. - - Read more about it in the - [FastAPI docs for JSON Compatible Encoder](https://fastapi.tiangolo.com/tutorial/encoder/). - """ - custom_encoder = custom_encoder or {} - if custom_encoder: - if type(obj) in custom_encoder: - return custom_encoder[type(obj)](obj) - else: - for encoder_type, encoder_instance in custom_encoder.items(): - if isinstance(obj, encoder_type): - return encoder_instance(obj) - if include is not None and not isinstance(include, (set, dict)): - include = set(include) # type: ignore[assignment] # ty: ignore[unused-ignore-comment] - if exclude is not None and not isinstance(exclude, (set, dict)): - exclude = set(exclude) # type: ignore[assignment] # ty: ignore[unused-ignore-comment] - if isinstance(obj, BaseModel): - obj_dict = obj.model_dump( - mode="json", - include=include, - exclude=exclude, - by_alias=by_alias, - exclude_unset=exclude_unset, - exclude_none=exclude_none, - exclude_defaults=exclude_defaults, - ) - return jsonable_encoder( - obj_dict, - exclude_none=exclude_none, - exclude_defaults=exclude_defaults, - sqlalchemy_safe=sqlalchemy_safe, - ) - if dataclasses.is_dataclass(obj): - assert not isinstance(obj, type) - obj_dict = dataclasses.asdict(obj) - return jsonable_encoder( - obj_dict, - include=include, - exclude=exclude, - by_alias=by_alias, - exclude_unset=exclude_unset, - exclude_defaults=exclude_defaults, - exclude_none=exclude_none, - custom_encoder=custom_encoder, - sqlalchemy_safe=sqlalchemy_safe, - ) - if isinstance(obj, Enum): - return obj.value - if isinstance(obj, PurePath): - return str(obj) - if isinstance(obj, (str, int, float, type(None))): - return obj - if isinstance(obj, PydanticUndefinedType): - return None - if isinstance(obj, dict): - encoded_dict = {} - allowed_keys = set(obj.keys()) - if include is not None: - allowed_keys &= set(include) - if exclude is not None: - allowed_keys -= set(exclude) - for key, value in obj.items(): - if ( - ( - not sqlalchemy_safe - or (not isinstance(key, str)) - or (not key.startswith("_sa")) - ) - and (value is not None or not exclude_none) - and key in allowed_keys - ): - encoded_key = jsonable_encoder( - key, - by_alias=by_alias, - exclude_unset=exclude_unset, - exclude_none=exclude_none, - custom_encoder=custom_encoder, - sqlalchemy_safe=sqlalchemy_safe, - ) - encoded_value = jsonable_encoder( - value, - by_alias=by_alias, - exclude_unset=exclude_unset, - exclude_none=exclude_none, - custom_encoder=custom_encoder, - sqlalchemy_safe=sqlalchemy_safe, - ) - encoded_dict[encoded_key] = encoded_value - return encoded_dict - if isinstance(obj, (list, set, frozenset, GeneratorType, tuple, deque)): - encoded_list = [] - for item in obj: - encoded_list.append( - jsonable_encoder( - item, - include=include, - exclude=exclude, - by_alias=by_alias, - exclude_unset=exclude_unset, - exclude_defaults=exclude_defaults, - exclude_none=exclude_none, - custom_encoder=custom_encoder, - sqlalchemy_safe=sqlalchemy_safe, - ) - ) - return encoded_list - - if type(obj) in ENCODERS_BY_TYPE: - return ENCODERS_BY_TYPE[type(obj)](obj) - for encoder, classes_tuple in encoders_by_class_tuples.items(): - if isinstance(obj, classes_tuple): - return encoder(obj) - if is_pydantic_v1_model_instance(obj): - raise PydanticV1NotSupportedError( - "pydantic.v1 models are no longer supported by FastAPI." - f" Please update the model {obj!r}." - ) - try: - data = dict(obj) - except Exception as e: - errors: list[Exception] = [] - errors.append(e) - try: - data = vars(obj) - except Exception as e: - errors.append(e) - raise ValueError(errors) from e - return jsonable_encoder( - data, - include=include, - exclude=exclude, - by_alias=by_alias, - exclude_unset=exclude_unset, - exclude_defaults=exclude_defaults, - exclude_none=exclude_none, - custom_encoder=custom_encoder, - sqlalchemy_safe=sqlalchemy_safe, - ) diff --git a/notification-service/venv/Lib/site-packages/fastapi/exception_handlers.py b/notification-service/venv/Lib/site-packages/fastapi/exception_handlers.py deleted file mode 100644 index 475dd7b..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/exception_handlers.py +++ /dev/null @@ -1,34 +0,0 @@ -from fastapi.encoders import jsonable_encoder -from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError -from fastapi.utils import is_body_allowed_for_status_code -from fastapi.websockets import WebSocket -from starlette.exceptions import HTTPException -from starlette.requests import Request -from starlette.responses import JSONResponse, Response -from starlette.status import WS_1008_POLICY_VIOLATION - - -async def http_exception_handler(request: Request, exc: HTTPException) -> Response: - headers = getattr(exc, "headers", None) - if not is_body_allowed_for_status_code(exc.status_code): - return Response(status_code=exc.status_code, headers=headers) - return JSONResponse( - {"detail": exc.detail}, status_code=exc.status_code, headers=headers - ) - - -async def request_validation_exception_handler( - request: Request, exc: RequestValidationError -) -> JSONResponse: - return JSONResponse( - status_code=422, - content={"detail": jsonable_encoder(exc.errors())}, - ) - - -async def websocket_request_validation_exception_handler( - websocket: WebSocket, exc: WebSocketRequestValidationError -) -> None: - await websocket.close( - code=WS_1008_POLICY_VIOLATION, reason=jsonable_encoder(exc.errors()) - ) diff --git a/notification-service/venv/Lib/site-packages/fastapi/exceptions.py b/notification-service/venv/Lib/site-packages/fastapi/exceptions.py deleted file mode 100644 index d7065c5..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/exceptions.py +++ /dev/null @@ -1,256 +0,0 @@ -from collections.abc import Mapping, Sequence -from typing import Annotated, Any, TypedDict - -from annotated_doc import Doc -from pydantic import BaseModel, create_model -from starlette.exceptions import HTTPException as StarletteHTTPException -from starlette.exceptions import WebSocketException as StarletteWebSocketException - - -class EndpointContext(TypedDict, total=False): - function: str - path: str - file: str - line: int - - -class HTTPException(StarletteHTTPException): - """ - An HTTP exception you can raise in your own code to show errors to the client. - - This is for client errors, invalid authentication, invalid data, etc. Not for server - errors in your code. - - Read more about it in the - [FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/). - - ## Example - - ```python - from fastapi import FastAPI, HTTPException - - app = FastAPI() - - items = {"foo": "The Foo Wrestlers"} - - - @app.get("/items/{item_id}") - async def read_item(item_id: str): - if item_id not in items: - raise HTTPException(status_code=404, detail="Item not found") - return {"item": items[item_id]} - ``` - """ - - def __init__( - self, - status_code: Annotated[ - int, - Doc( - """ - HTTP status code to send to the client. - - Read more about it in the - [FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/#use-httpexception) - """ - ), - ], - detail: Annotated[ - Any, - Doc( - """ - Any data to be sent to the client in the `detail` key of the JSON - response. - - Read more about it in the - [FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/#use-httpexception) - """ - ), - ] = None, - headers: Annotated[ - Mapping[str, str] | None, - Doc( - """ - Any headers to send to the client in the response. - - Read more about it in the - [FastAPI docs for Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/#add-custom-headers) - - """ - ), - ] = None, - ) -> None: - super().__init__(status_code=status_code, detail=detail, headers=headers) - - -class WebSocketException(StarletteWebSocketException): - """ - A WebSocket exception you can raise in your own code to show errors to the client. - - This is for client errors, invalid authentication, invalid data, etc. Not for server - errors in your code. - - Read more about it in the - [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/). - - ## Example - - ```python - from typing import Annotated - - from fastapi import ( - Cookie, - FastAPI, - WebSocket, - WebSocketException, - status, - ) - - app = FastAPI() - - @app.websocket("/items/{item_id}/ws") - async def websocket_endpoint( - *, - websocket: WebSocket, - session: Annotated[str | None, Cookie()] = None, - item_id: str, - ): - if session is None: - raise WebSocketException(code=status.WS_1008_POLICY_VIOLATION) - await websocket.accept() - while True: - data = await websocket.receive_text() - await websocket.send_text(f"Session cookie is: {session}") - await websocket.send_text(f"Message text was: {data}, for item ID: {item_id}") - ``` - """ - - def __init__( - self, - code: Annotated[ - int, - Doc( - """ - A closing code from the - [valid codes defined in the specification](https://datatracker.ietf.org/doc/html/rfc6455#section-7.4.1). - """ - ), - ], - reason: Annotated[ - str | None, - Doc( - """ - The reason to close the WebSocket connection. - - It is UTF-8-encoded data. The interpretation of the reason is up to the - application, it is not specified by the WebSocket specification. - - It could contain text that could be human-readable or interpretable - by the client code, etc. - """ - ), - ] = None, - ) -> None: - super().__init__(code=code, reason=reason) - - -RequestErrorModel: type[BaseModel] = create_model("Request") -WebSocketErrorModel: type[BaseModel] = create_model("WebSocket") - - -class FastAPIError(RuntimeError): - """ - A generic, FastAPI-specific error. - """ - - -class DependencyScopeError(FastAPIError): - """ - A dependency declared that it depends on another dependency with an invalid - (narrower) scope. - """ - - -class ValidationException(Exception): - def __init__( - self, - errors: Sequence[Any], - *, - endpoint_ctx: EndpointContext | None = None, - ) -> None: - self._errors = errors - self.endpoint_ctx = endpoint_ctx - - ctx = endpoint_ctx or {} - self.endpoint_function = ctx.get("function") - self.endpoint_path = ctx.get("path") - self.endpoint_file = ctx.get("file") - self.endpoint_line = ctx.get("line") - - def errors(self) -> Sequence[Any]: - return self._errors - - def _format_endpoint_context(self) -> str: - if not (self.endpoint_file and self.endpoint_line and self.endpoint_function): - if self.endpoint_path: - return f"\n Endpoint: {self.endpoint_path}" - return "" - - context = f'\n File "{self.endpoint_file}", line {self.endpoint_line}, in {self.endpoint_function}' - if self.endpoint_path: - context += f"\n {self.endpoint_path}" - return context - - def __str__(self) -> str: - message = f"{len(self._errors)} validation error{'s' if len(self._errors) != 1 else ''}:\n" - for err in self._errors: - message += f" {err}\n" - message += self._format_endpoint_context() - return message.rstrip() - - -class RequestValidationError(ValidationException): - def __init__( - self, - errors: Sequence[Any], - *, - body: Any = None, - endpoint_ctx: EndpointContext | None = None, - ) -> None: - super().__init__(errors, endpoint_ctx=endpoint_ctx) - self.body = body - - -class WebSocketRequestValidationError(ValidationException): - def __init__( - self, - errors: Sequence[Any], - *, - endpoint_ctx: EndpointContext | None = None, - ) -> None: - super().__init__(errors, endpoint_ctx=endpoint_ctx) - - -class ResponseValidationError(ValidationException): - def __init__( - self, - errors: Sequence[Any], - *, - body: Any = None, - endpoint_ctx: EndpointContext | None = None, - ) -> None: - super().__init__(errors, endpoint_ctx=endpoint_ctx) - self.body = body - - -class PydanticV1NotSupportedError(FastAPIError): - """ - A pydantic.v1 model is used, which is no longer supported. - """ - - -class FastAPIDeprecationWarning(UserWarning): - """ - A custom deprecation warning as DeprecationWarning is ignored - Ref: https://sethmlarson.dev/deprecations-via-warnings-dont-work-for-python-libraries - """ diff --git a/notification-service/venv/Lib/site-packages/fastapi/logger.py b/notification-service/venv/Lib/site-packages/fastapi/logger.py deleted file mode 100644 index 5b2c4ad..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/logger.py +++ /dev/null @@ -1,3 +0,0 @@ -import logging - -logger = logging.getLogger("fastapi") diff --git a/notification-service/venv/Lib/site-packages/fastapi/middleware/__init__.py b/notification-service/venv/Lib/site-packages/fastapi/middleware/__init__.py deleted file mode 100644 index 620296d..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/middleware/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from starlette.middleware import Middleware as Middleware diff --git a/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index f08734b..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/asyncexitstack.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/asyncexitstack.cpython-312.pyc deleted file mode 100644 index 604dffe..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/asyncexitstack.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/cors.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/cors.cpython-312.pyc deleted file mode 100644 index a124619..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/cors.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/gzip.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/gzip.cpython-312.pyc deleted file mode 100644 index 7cb6a51..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/gzip.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/httpsredirect.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/httpsredirect.cpython-312.pyc deleted file mode 100644 index a9bf302..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/httpsredirect.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/trustedhost.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/trustedhost.cpython-312.pyc deleted file mode 100644 index 6f478b8..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/trustedhost.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/wsgi.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/wsgi.cpython-312.pyc deleted file mode 100644 index f67e256..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/middleware/__pycache__/wsgi.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/middleware/asyncexitstack.py b/notification-service/venv/Lib/site-packages/fastapi/middleware/asyncexitstack.py deleted file mode 100644 index 4ce3f5a..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/middleware/asyncexitstack.py +++ /dev/null @@ -1,18 +0,0 @@ -from contextlib import AsyncExitStack - -from starlette.types import ASGIApp, Receive, Scope, Send - - -# Used mainly to close files after the request is done, dependencies are closed -# in their own AsyncExitStack -class AsyncExitStackMiddleware: - def __init__( - self, app: ASGIApp, context_name: str = "fastapi_middleware_astack" - ) -> None: - self.app = app - self.context_name = context_name - - async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: - async with AsyncExitStack() as stack: - scope[self.context_name] = stack - await self.app(scope, receive, send) diff --git a/notification-service/venv/Lib/site-packages/fastapi/middleware/cors.py b/notification-service/venv/Lib/site-packages/fastapi/middleware/cors.py deleted file mode 100644 index 8dfaad0..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/middleware/cors.py +++ /dev/null @@ -1 +0,0 @@ -from starlette.middleware.cors import CORSMiddleware as CORSMiddleware # noqa diff --git a/notification-service/venv/Lib/site-packages/fastapi/middleware/gzip.py b/notification-service/venv/Lib/site-packages/fastapi/middleware/gzip.py deleted file mode 100644 index bbeb2cc..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/middleware/gzip.py +++ /dev/null @@ -1 +0,0 @@ -from starlette.middleware.gzip import GZipMiddleware as GZipMiddleware # noqa diff --git a/notification-service/venv/Lib/site-packages/fastapi/middleware/httpsredirect.py b/notification-service/venv/Lib/site-packages/fastapi/middleware/httpsredirect.py deleted file mode 100644 index b7a3d8e..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/middleware/httpsredirect.py +++ /dev/null @@ -1,3 +0,0 @@ -from starlette.middleware.httpsredirect import ( # noqa - HTTPSRedirectMiddleware as HTTPSRedirectMiddleware, -) diff --git a/notification-service/venv/Lib/site-packages/fastapi/middleware/trustedhost.py b/notification-service/venv/Lib/site-packages/fastapi/middleware/trustedhost.py deleted file mode 100644 index 08d7e03..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/middleware/trustedhost.py +++ /dev/null @@ -1,3 +0,0 @@ -from starlette.middleware.trustedhost import ( # noqa - TrustedHostMiddleware as TrustedHostMiddleware, -) diff --git a/notification-service/venv/Lib/site-packages/fastapi/middleware/wsgi.py b/notification-service/venv/Lib/site-packages/fastapi/middleware/wsgi.py deleted file mode 100644 index 69e4dca..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/middleware/wsgi.py +++ /dev/null @@ -1,3 +0,0 @@ -from starlette.middleware.wsgi import ( - WSGIMiddleware as WSGIMiddleware, -) # pragma: no cover # noqa diff --git a/notification-service/venv/Lib/site-packages/fastapi/openapi/__init__.py b/notification-service/venv/Lib/site-packages/fastapi/openapi/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 03442d4..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/constants.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/constants.cpython-312.pyc deleted file mode 100644 index 721097b..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/constants.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/docs.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/docs.cpython-312.pyc deleted file mode 100644 index 906e235..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/docs.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/models.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/models.cpython-312.pyc deleted file mode 100644 index 52ee68f..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/models.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/utils.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/utils.cpython-312.pyc deleted file mode 100644 index d8bb8ba..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/openapi/__pycache__/utils.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/openapi/constants.py b/notification-service/venv/Lib/site-packages/fastapi/openapi/constants.py deleted file mode 100644 index d724ee3..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/openapi/constants.py +++ /dev/null @@ -1,3 +0,0 @@ -METHODS_WITH_BODY = {"GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"} -REF_PREFIX = "#/components/schemas/" -REF_TEMPLATE = "#/components/schemas/{model}" diff --git a/notification-service/venv/Lib/site-packages/fastapi/openapi/docs.py b/notification-service/venv/Lib/site-packages/fastapi/openapi/docs.py deleted file mode 100644 index 0d9242f..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/openapi/docs.py +++ /dev/null @@ -1,389 +0,0 @@ -import json -from typing import Annotated, Any - -from annotated_doc import Doc -from fastapi.encoders import jsonable_encoder -from starlette.responses import HTMLResponse - - -def _html_safe_json(value: Any) -> str: - """Serialize a value to JSON with HTML special characters escaped. - - This prevents injection when the JSON is embedded inside a - - - - - """ - return HTMLResponse(html) - - -def get_redoc_html( - *, - openapi_url: Annotated[ - str, - Doc( - """ - The OpenAPI URL that ReDoc should load and use. - - This is normally done automatically by FastAPI using the default URL - `/openapi.json`. - - Read more about it in the - [FastAPI docs for Conditional OpenAPI](https://fastapi.tiangolo.com/how-to/conditional-openapi/#conditional-openapi-from-settings-and-env-vars) - """ - ), - ], - title: Annotated[ - str, - Doc( - """ - The HTML `` content, normally shown in the browser tab. - - Read more about it in the - [FastAPI docs for Custom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/) - """ - ), - ], - redoc_js_url: Annotated[ - str, - Doc( - """ - The URL to use to load the ReDoc JavaScript. - - It is normally set to a CDN URL. - - Read more about it in the - [FastAPI docs for Custom Docs UI Static Assets](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/) - """ - ), - ] = "https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js", - redoc_favicon_url: Annotated[ - str, - Doc( - """ - The URL of the favicon to use. It is normally shown in the browser tab. - """ - ), - ] = "https://fastapi.tiangolo.com/img/favicon.png", - with_google_fonts: Annotated[ - bool, - Doc( - """ - Load and use Google Fonts. - """ - ), - ] = True, -) -> HTMLResponse: - """ - Generate and return the HTML response that loads ReDoc for the alternative - API docs (normally served at `/redoc`). - - You would only call this function yourself if you needed to override some parts, - for example the URLs to use to load ReDoc's JavaScript and CSS. - - Read more about it in the - [FastAPI docs for Custom Docs UI Static Assets (Self-Hosting)](https://fastapi.tiangolo.com/how-to/custom-docs-ui-assets/). - """ - html = f""" - <!DOCTYPE html> - <html> - <head> - <title>{title} - - - - """ - if with_google_fonts: - html += """ - - """ - html += f""" - - - - - - - - - - - """ - return HTMLResponse(html) - - -def get_swagger_ui_oauth2_redirect_html() -> HTMLResponse: - """ - Generate the HTML response with the OAuth2 redirection for Swagger UI. - - You normally don't need to use or change this. - """ - # copied from https://github.com/swagger-api/swagger-ui/blob/v4.14.0/dist/oauth2-redirect.html - html = """ - - - - Swagger UI: OAuth2 Redirect - - - - - - """ - return HTMLResponse(content=html) diff --git a/notification-service/venv/Lib/site-packages/fastapi/openapi/models.py b/notification-service/venv/Lib/site-packages/fastapi/openapi/models.py deleted file mode 100644 index b9fad31..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/openapi/models.py +++ /dev/null @@ -1,435 +0,0 @@ -from collections.abc import Callable, Iterable, Mapping -from enum import Enum -from typing import Annotated, Any, Literal, Optional, Union - -from fastapi._compat import with_info_plain_validator_function -from fastapi.logger import logger -from pydantic import ( - AnyUrl, - BaseModel, - Field, - GetJsonSchemaHandler, -) -from typing_extensions import TypedDict -from typing_extensions import deprecated as typing_deprecated - -try: - import email_validator - - assert email_validator # make autoflake ignore the unused import - from pydantic import EmailStr -except ImportError: # pragma: no cover - - class EmailStr(str): # type: ignore # ty: ignore[unused-ignore-comment] - @classmethod - def __get_validators__(cls) -> Iterable[Callable[..., Any]]: - yield cls.validate - - @classmethod - def validate(cls, v: Any) -> str: - logger.warning( - "email-validator not installed, email fields will be treated as str.\n" - "To install, run: pip install email-validator" - ) - return str(v) - - @classmethod - def _validate(cls, __input_value: Any, _: Any) -> str: - logger.warning( - "email-validator not installed, email fields will be treated as str.\n" - "To install, run: pip install email-validator" - ) - return str(__input_value) - - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: Mapping[str, Any], handler: GetJsonSchemaHandler - ) -> dict[str, Any]: - return {"type": "string", "format": "email"} - - @classmethod - def __get_pydantic_core_schema__( - cls, source: type[Any], handler: Callable[[Any], Mapping[str, Any]] - ) -> Mapping[str, Any]: - return with_info_plain_validator_function(cls._validate) - - -class BaseModelWithConfig(BaseModel): - model_config = {"extra": "allow"} - - -class Contact(BaseModelWithConfig): - name: str | None = None - url: AnyUrl | None = None - email: EmailStr | None = None - - -class License(BaseModelWithConfig): - name: str - identifier: str | None = None - url: AnyUrl | None = None - - -class Info(BaseModelWithConfig): - title: str - summary: str | None = None - description: str | None = None - termsOfService: str | None = None - contact: Contact | None = None - license: License | None = None - version: str - - -class ServerVariable(BaseModelWithConfig): - enum: Annotated[list[str] | None, Field(min_length=1)] = None - default: str - description: str | None = None - - -class Server(BaseModelWithConfig): - url: AnyUrl | str - description: str | None = None - variables: dict[str, ServerVariable] | None = None - - -class Reference(BaseModel): - ref: str = Field(alias="$ref") - - -class Discriminator(BaseModel): - propertyName: str - mapping: dict[str, str] | None = None - - -class XML(BaseModelWithConfig): - name: str | None = None - namespace: str | None = None - prefix: str | None = None - attribute: bool | None = None - wrapped: bool | None = None - - -class ExternalDocumentation(BaseModelWithConfig): - description: str | None = None - url: AnyUrl - - -# Ref JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation#name-type -SchemaType = Literal[ - "array", "boolean", "integer", "null", "number", "object", "string" -] - - -class Schema(BaseModelWithConfig): - # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-json-schema-core-vocabu - # Core Vocabulary - schema_: str | None = Field(default=None, alias="$schema") - vocabulary: str | None = Field(default=None, alias="$vocabulary") - id: str | None = Field(default=None, alias="$id") - anchor: str | None = Field(default=None, alias="$anchor") - dynamicAnchor: str | None = Field(default=None, alias="$dynamicAnchor") - ref: str | None = Field(default=None, alias="$ref") - dynamicRef: str | None = Field(default=None, alias="$dynamicRef") - defs: dict[str, "SchemaOrBool"] | None = Field(default=None, alias="$defs") - comment: str | None = Field(default=None, alias="$comment") - # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-a-vocabulary-for-applying-s - # A Vocabulary for Applying Subschemas - allOf: list["SchemaOrBool"] | None = None - anyOf: list["SchemaOrBool"] | None = None - oneOf: list["SchemaOrBool"] | None = None - not_: Optional["SchemaOrBool"] = Field(default=None, alias="not") - if_: Optional["SchemaOrBool"] = Field(default=None, alias="if") - then: Optional["SchemaOrBool"] = None - else_: Optional["SchemaOrBool"] = Field(default=None, alias="else") - dependentSchemas: dict[str, "SchemaOrBool"] | None = None - prefixItems: list["SchemaOrBool"] | None = None - items: Optional["SchemaOrBool"] = None - contains: Optional["SchemaOrBool"] = None - properties: dict[str, "SchemaOrBool"] | None = None - patternProperties: dict[str, "SchemaOrBool"] | None = None - additionalProperties: Optional["SchemaOrBool"] = None - propertyNames: Optional["SchemaOrBool"] = None - unevaluatedItems: Optional["SchemaOrBool"] = None - unevaluatedProperties: Optional["SchemaOrBool"] = None - # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural - # A Vocabulary for Structural Validation - type: SchemaType | list[SchemaType] | None = None - enum: list[Any] | None = None - const: Any | None = None - multipleOf: float | None = Field(default=None, gt=0) - maximum: float | None = None - exclusiveMaximum: float | None = None - minimum: float | None = None - exclusiveMinimum: float | None = None - maxLength: int | None = Field(default=None, ge=0) - minLength: int | None = Field(default=None, ge=0) - pattern: str | None = None - maxItems: int | None = Field(default=None, ge=0) - minItems: int | None = Field(default=None, ge=0) - uniqueItems: bool | None = None - maxContains: int | None = Field(default=None, ge=0) - minContains: int | None = Field(default=None, ge=0) - maxProperties: int | None = Field(default=None, ge=0) - minProperties: int | None = Field(default=None, ge=0) - required: list[str] | None = None - dependentRequired: dict[str, set[str]] | None = None - # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-vocabularies-for-semantic-c - # Vocabularies for Semantic Content With "format" - format: str | None = None - # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-the-conten - # A Vocabulary for the Contents of String-Encoded Data - contentEncoding: str | None = None - contentMediaType: str | None = None - contentSchema: Optional["SchemaOrBool"] = None - # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-basic-meta - # A Vocabulary for Basic Meta-Data Annotations - title: str | None = None - description: str | None = None - default: Any | None = None - deprecated: bool | None = None - readOnly: bool | None = None - writeOnly: bool | None = None - examples: list[Any] | None = None - # Ref: OpenAPI 3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#schema-object - # Schema Object - discriminator: Discriminator | None = None - xml: XML | None = None - externalDocs: ExternalDocumentation | None = None - example: Annotated[ - Any | None, - typing_deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = None - - -# Ref: https://json-schema.org/draft/2020-12/json-schema-core.html#name-json-schema-documents -# A JSON Schema MUST be an object or a boolean. -SchemaOrBool = Schema | bool - - -class Example(TypedDict, total=False): - summary: str | None - description: str | None - value: Any | None - externalValue: AnyUrl | None - - __pydantic_config__ = {"extra": "allow"} # type: ignore[misc] - - -class ParameterInType(Enum): - query = "query" - header = "header" - path = "path" - cookie = "cookie" - - -class Encoding(BaseModelWithConfig): - contentType: str | None = None - headers: dict[str, Union["Header", Reference]] | None = None - style: str | None = None - explode: bool | None = None - allowReserved: bool | None = None - - -class MediaType(BaseModelWithConfig): - schema_: Schema | Reference | None = Field(default=None, alias="schema") - example: Any | None = None - examples: dict[str, Example | Reference] | None = None - encoding: dict[str, Encoding] | None = None - - -class ParameterBase(BaseModelWithConfig): - description: str | None = None - required: bool | None = None - deprecated: bool | None = None - # Serialization rules for simple scenarios - style: str | None = None - explode: bool | None = None - allowReserved: bool | None = None - schema_: Schema | Reference | None = Field(default=None, alias="schema") - example: Any | None = None - examples: dict[str, Example | Reference] | None = None - # Serialization rules for more complex scenarios - content: dict[str, MediaType] | None = None - - -class Parameter(ParameterBase): - name: str - in_: ParameterInType = Field(alias="in") - - -class Header(ParameterBase): - pass - - -class RequestBody(BaseModelWithConfig): - description: str | None = None - content: dict[str, MediaType] - required: bool | None = None - - -class Link(BaseModelWithConfig): - operationRef: str | None = None - operationId: str | None = None - parameters: dict[str, Any | str] | None = None - requestBody: Any | str | None = None - description: str | None = None - server: Server | None = None - - -class Response(BaseModelWithConfig): - description: str - headers: dict[str, Header | Reference] | None = None - content: dict[str, MediaType] | None = None - links: dict[str, Link | Reference] | None = None - - -class Operation(BaseModelWithConfig): - tags: list[str] | None = None - summary: str | None = None - description: str | None = None - externalDocs: ExternalDocumentation | None = None - operationId: str | None = None - parameters: list[Parameter | Reference] | None = None - requestBody: RequestBody | Reference | None = None - # Using Any for Specification Extensions - responses: dict[str, Response | Any] | None = None - callbacks: dict[str, dict[str, "PathItem"] | Reference] | None = None - deprecated: bool | None = None - security: list[dict[str, list[str]]] | None = None - servers: list[Server] | None = None - - -class PathItem(BaseModelWithConfig): - ref: str | None = Field(default=None, alias="$ref") - summary: str | None = None - description: str | None = None - get: Operation | None = None - put: Operation | None = None - post: Operation | None = None - delete: Operation | None = None - options: Operation | None = None - head: Operation | None = None - patch: Operation | None = None - trace: Operation | None = None - servers: list[Server] | None = None - parameters: list[Parameter | Reference] | None = None - - -class SecuritySchemeType(Enum): - apiKey = "apiKey" - http = "http" - oauth2 = "oauth2" - openIdConnect = "openIdConnect" - - -class SecurityBase(BaseModelWithConfig): - type_: SecuritySchemeType = Field(alias="type") - description: str | None = None - - -class APIKeyIn(Enum): - query = "query" - header = "header" - cookie = "cookie" - - -class APIKey(SecurityBase): - type_: SecuritySchemeType = Field(default=SecuritySchemeType.apiKey, alias="type") - in_: APIKeyIn = Field(alias="in") - name: str - - -class HTTPBase(SecurityBase): - type_: SecuritySchemeType = Field(default=SecuritySchemeType.http, alias="type") - scheme: str - - -class HTTPBearer(HTTPBase): - scheme: Literal["bearer"] = "bearer" - bearerFormat: str | None = None - - -class OAuthFlow(BaseModelWithConfig): - refreshUrl: str | None = None - scopes: dict[str, str] = {} - - -class OAuthFlowImplicit(OAuthFlow): - authorizationUrl: str - - -class OAuthFlowPassword(OAuthFlow): - tokenUrl: str - - -class OAuthFlowClientCredentials(OAuthFlow): - tokenUrl: str - - -class OAuthFlowAuthorizationCode(OAuthFlow): - authorizationUrl: str - tokenUrl: str - - -class OAuthFlows(BaseModelWithConfig): - implicit: OAuthFlowImplicit | None = None - password: OAuthFlowPassword | None = None - clientCredentials: OAuthFlowClientCredentials | None = None - authorizationCode: OAuthFlowAuthorizationCode | None = None - - -class OAuth2(SecurityBase): - type_: SecuritySchemeType = Field(default=SecuritySchemeType.oauth2, alias="type") - flows: OAuthFlows - - -class OpenIdConnect(SecurityBase): - type_: SecuritySchemeType = Field( - default=SecuritySchemeType.openIdConnect, alias="type" - ) - openIdConnectUrl: str - - -SecurityScheme = APIKey | HTTPBase | OAuth2 | OpenIdConnect | HTTPBearer - - -class Components(BaseModelWithConfig): - schemas: dict[str, Schema | Reference] | None = None - responses: dict[str, Response | Reference] | None = None - parameters: dict[str, Parameter | Reference] | None = None - examples: dict[str, Example | Reference] | None = None - requestBodies: dict[str, RequestBody | Reference] | None = None - headers: dict[str, Header | Reference] | None = None - securitySchemes: dict[str, SecurityScheme | Reference] | None = None - links: dict[str, Link | Reference] | None = None - # Using Any for Specification Extensions - callbacks: dict[str, dict[str, PathItem] | Reference | Any] | None = None - pathItems: dict[str, PathItem | Reference] | None = None - - -class Tag(BaseModelWithConfig): - name: str - description: str | None = None - externalDocs: ExternalDocumentation | None = None - - -class OpenAPI(BaseModelWithConfig): - openapi: str - info: Info - jsonSchemaDialect: str | None = None - servers: list[Server] | None = None - # Using Any for Specification Extensions - paths: dict[str, PathItem | Any] | None = None - webhooks: dict[str, PathItem | Reference] | None = None - components: Components | None = None - security: list[dict[str, list[str]]] | None = None - tags: list[Tag] | None = None - externalDocs: ExternalDocumentation | None = None - - -Schema.model_rebuild() -Operation.model_rebuild() -Encoding.model_rebuild() diff --git a/notification-service/venv/Lib/site-packages/fastapi/openapi/utils.py b/notification-service/venv/Lib/site-packages/fastapi/openapi/utils.py deleted file mode 100644 index 8f1852b..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/openapi/utils.py +++ /dev/null @@ -1,606 +0,0 @@ -import copy -import http.client -import inspect -import warnings -from collections.abc import Sequence -from typing import Any, Literal, cast - -from fastapi import routing -from fastapi._compat import ( - ModelField, - get_definitions, - get_flat_models_from_fields, - get_model_name_map, - get_schema_from_model_field, - lenient_issubclass, -) -from fastapi.datastructures import DefaultPlaceholder, _Unset -from fastapi.dependencies.models import Dependant -from fastapi.dependencies.utils import ( - _get_flat_fields_from_params, - get_flat_dependant, - get_flat_params, - get_validation_alias, -) -from fastapi.encoders import jsonable_encoder -from fastapi.exceptions import FastAPIDeprecationWarning -from fastapi.openapi.constants import METHODS_WITH_BODY, REF_PREFIX -from fastapi.openapi.models import OpenAPI -from fastapi.params import Body, ParamTypes -from fastapi.responses import Response -from fastapi.sse import _SSE_EVENT_SCHEMA -from fastapi.types import ModelNameMap -from fastapi.utils import ( - deep_dict_update, - generate_operation_id_for_path, - is_body_allowed_for_status_code, -) -from pydantic import BaseModel -from starlette.responses import JSONResponse -from starlette.routing import BaseRoute - -validation_error_definition = { - "title": "ValidationError", - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - "input": {"title": "Input"}, - "ctx": {"title": "Context", "type": "object"}, - }, - "required": ["loc", "msg", "type"], -} - -validation_error_response_definition = { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": REF_PREFIX + "ValidationError"}, - } - }, -} - -status_code_ranges: dict[str, str] = { - "1XX": "Information", - "2XX": "Success", - "3XX": "Redirection", - "4XX": "Client Error", - "5XX": "Server Error", - "DEFAULT": "Default Response", -} - - -def get_openapi_security_definitions( - flat_dependant: Dependant, -) -> tuple[dict[str, Any], list[dict[str, Any]]]: - security_definitions = {} - # Use a dict to merge scopes for same security scheme - operation_security_dict: dict[str, list[str]] = {} - for security_dependency in flat_dependant._security_dependencies: - security_definition = jsonable_encoder( - security_dependency._security_scheme.model, - by_alias=True, - exclude_none=True, - ) - security_name = security_dependency._security_scheme.scheme_name - security_definitions[security_name] = security_definition - # Merge scopes for the same security scheme - if security_name not in operation_security_dict: - operation_security_dict[security_name] = [] - for scope in security_dependency.oauth_scopes or []: - if scope not in operation_security_dict[security_name]: - operation_security_dict[security_name].append(scope) - operation_security = [ - {name: scopes} for name, scopes in operation_security_dict.items() - ] - return security_definitions, operation_security - - -def _get_openapi_operation_parameters( - *, - dependant: Dependant, - model_name_map: ModelNameMap, - field_mapping: dict[ - tuple[ModelField, Literal["validation", "serialization"]], dict[str, Any] - ], - separate_input_output_schemas: bool = True, -) -> list[dict[str, Any]]: - parameters = [] - flat_dependant = get_flat_dependant(dependant, skip_repeats=True) - path_params = _get_flat_fields_from_params(flat_dependant.path_params) - query_params = _get_flat_fields_from_params(flat_dependant.query_params) - header_params = _get_flat_fields_from_params(flat_dependant.header_params) - cookie_params = _get_flat_fields_from_params(flat_dependant.cookie_params) - parameter_groups = [ - (ParamTypes.path, path_params), - (ParamTypes.query, query_params), - (ParamTypes.header, header_params), - (ParamTypes.cookie, cookie_params), - ] - default_convert_underscores = True - if len(flat_dependant.header_params) == 1: - first_field = flat_dependant.header_params[0] - if lenient_issubclass(first_field.field_info.annotation, BaseModel): - default_convert_underscores = getattr( - first_field.field_info, "convert_underscores", True - ) - for param_type, param_group in parameter_groups: - for param in param_group: - field_info = param.field_info - # field_info = cast(Param, field_info) - if not getattr(field_info, "include_in_schema", True): - continue - param_schema = get_schema_from_model_field( - field=param, - model_name_map=model_name_map, - field_mapping=field_mapping, - separate_input_output_schemas=separate_input_output_schemas, - ) - name = get_validation_alias(param) - convert_underscores = getattr( - param.field_info, - "convert_underscores", - default_convert_underscores, - ) - if ( - param_type == ParamTypes.header - and name == param.name - and convert_underscores - ): - name = param.name.replace("_", "-") - - parameter = { - "name": name, - "in": param_type.value, - "required": param.field_info.is_required(), - "schema": param_schema, - } - if field_info.description: - parameter["description"] = field_info.description - openapi_examples = getattr(field_info, "openapi_examples", None) - example = getattr(field_info, "example", None) - if openapi_examples: - parameter["examples"] = jsonable_encoder(openapi_examples) - elif example is not _Unset: - parameter["example"] = jsonable_encoder(example) - if getattr(field_info, "deprecated", None): - parameter["deprecated"] = True - parameters.append(parameter) - return parameters - - -def get_openapi_operation_request_body( - *, - body_field: ModelField | None, - model_name_map: ModelNameMap, - field_mapping: dict[ - tuple[ModelField, Literal["validation", "serialization"]], dict[str, Any] - ], - separate_input_output_schemas: bool = True, -) -> dict[str, Any] | None: - if not body_field: - return None - assert isinstance(body_field, ModelField) - body_schema = get_schema_from_model_field( - field=body_field, - model_name_map=model_name_map, - field_mapping=field_mapping, - separate_input_output_schemas=separate_input_output_schemas, - ) - field_info = cast(Body, body_field.field_info) - request_media_type = field_info.media_type - required = body_field.field_info.is_required() - request_body_oai: dict[str, Any] = {} - if required: - request_body_oai["required"] = required - request_media_content: dict[str, Any] = {"schema": body_schema} - if field_info.openapi_examples: - request_media_content["examples"] = jsonable_encoder( - field_info.openapi_examples - ) - elif field_info.example is not _Unset: - request_media_content["example"] = jsonable_encoder(field_info.example) - request_body_oai["content"] = {request_media_type: request_media_content} - return request_body_oai - - -def generate_operation_id( - *, route: routing.APIRoute, method: str -) -> str: # pragma: nocover - warnings.warn( - message="fastapi.openapi.utils.generate_operation_id() was deprecated, " - "it is not used internally, and will be removed soon", - category=FastAPIDeprecationWarning, - stacklevel=2, - ) - if route.operation_id: - return route.operation_id - path: str = route.path_format - return generate_operation_id_for_path(name=route.name, path=path, method=method) - - -def generate_operation_summary(*, route: routing.APIRoute, method: str) -> str: - if route.summary: - return route.summary - return route.name.replace("_", " ").title() - - -def get_openapi_operation_metadata( - *, route: routing.APIRoute, method: str, operation_ids: set[str] -) -> dict[str, Any]: - operation: dict[str, Any] = {} - if route.tags: - operation["tags"] = route.tags - operation["summary"] = generate_operation_summary(route=route, method=method) - if route.description: - operation["description"] = route.description - operation_id = route.operation_id or route.unique_id - if operation_id in operation_ids: - endpoint_name = getattr(route.endpoint, "__name__", "") - message = f"Duplicate Operation ID {operation_id} for function {endpoint_name}" - file_name = getattr(route.endpoint, "__globals__", {}).get("__file__") - if file_name: - message += f" at {file_name}" - warnings.warn(message, stacklevel=1) - operation_ids.add(operation_id) - operation["operationId"] = operation_id - if route.deprecated: - operation["deprecated"] = route.deprecated - return operation - - -def get_openapi_path( - *, - route: routing.APIRoute, - operation_ids: set[str], - model_name_map: ModelNameMap, - field_mapping: dict[ - tuple[ModelField, Literal["validation", "serialization"]], dict[str, Any] - ], - separate_input_output_schemas: bool = True, -) -> tuple[dict[str, Any], dict[str, Any], dict[str, Any]]: - path = {} - security_schemes: dict[str, Any] = {} - definitions: dict[str, Any] = {} - assert route.methods is not None, "Methods must be a list" - if isinstance(route.response_class, DefaultPlaceholder): - current_response_class: type[Response] = route.response_class.value - else: - current_response_class = route.response_class - assert current_response_class, "A response class is needed to generate OpenAPI" - route_response_media_type: str | None = current_response_class.media_type - if route.include_in_schema: - for method in route.methods: - operation = get_openapi_operation_metadata( - route=route, method=method, operation_ids=operation_ids - ) - parameters: list[dict[str, Any]] = [] - flat_dependant = get_flat_dependant(route.dependant, skip_repeats=True) - security_definitions, operation_security = get_openapi_security_definitions( - flat_dependant=flat_dependant - ) - if operation_security: - operation.setdefault("security", []).extend(operation_security) - if security_definitions: - security_schemes.update(security_definitions) - operation_parameters = _get_openapi_operation_parameters( - dependant=route.dependant, - model_name_map=model_name_map, - field_mapping=field_mapping, - separate_input_output_schemas=separate_input_output_schemas, - ) - parameters.extend(operation_parameters) - if parameters: - all_parameters = { - (param["in"], param["name"]): param for param in parameters - } - required_parameters = { - (param["in"], param["name"]): param - for param in parameters - if param.get("required") - } - # Make sure required definitions of the same parameter take precedence - # over non-required definitions - all_parameters.update(required_parameters) - operation["parameters"] = list(all_parameters.values()) - if method in METHODS_WITH_BODY: - request_body_oai = get_openapi_operation_request_body( - body_field=route.body_field, - model_name_map=model_name_map, - field_mapping=field_mapping, - separate_input_output_schemas=separate_input_output_schemas, - ) - if request_body_oai: - operation["requestBody"] = request_body_oai - if route.callbacks: - callbacks = {} - for callback in route.callbacks: - if isinstance(callback, routing.APIRoute): - ( - cb_path, - cb_security_schemes, - cb_definitions, - ) = get_openapi_path( - route=callback, - operation_ids=operation_ids, - model_name_map=model_name_map, - field_mapping=field_mapping, - separate_input_output_schemas=separate_input_output_schemas, - ) - callbacks[callback.name] = {callback.path: cb_path} - operation["callbacks"] = callbacks - if route.status_code is not None: - status_code = str(route.status_code) - else: - # It would probably make more sense for all response classes to have an - # explicit default status_code, and to extract it from them, instead of - # doing this inspection tricks, that would probably be in the future - # TODO: probably make status_code a default class attribute for all - # responses in Starlette - response_signature = inspect.signature(current_response_class.__init__) - status_code_param = response_signature.parameters.get("status_code") - if status_code_param is not None: - if isinstance(status_code_param.default, int): - status_code = str(status_code_param.default) - operation.setdefault("responses", {}).setdefault(status_code, {})[ - "description" - ] = route.response_description - if is_body_allowed_for_status_code(route.status_code): - # Check for JSONL streaming (generator endpoints) - if route.is_json_stream: - jsonl_content: dict[str, Any] = {} - if route.stream_item_field: - item_schema = get_schema_from_model_field( - field=route.stream_item_field, - model_name_map=model_name_map, - field_mapping=field_mapping, - separate_input_output_schemas=separate_input_output_schemas, - ) - jsonl_content["itemSchema"] = item_schema - else: - jsonl_content["itemSchema"] = {} - operation.setdefault("responses", {}).setdefault( - status_code, {} - ).setdefault("content", {})["application/jsonl"] = jsonl_content - elif route.is_sse_stream: - sse_content: dict[str, Any] = {} - item_schema = copy.deepcopy(_SSE_EVENT_SCHEMA) - if route.stream_item_field: - content_schema = get_schema_from_model_field( - field=route.stream_item_field, - model_name_map=model_name_map, - field_mapping=field_mapping, - separate_input_output_schemas=separate_input_output_schemas, - ) - item_schema["required"] = ["data"] - item_schema["properties"]["data"] = { - "type": "string", - "contentMediaType": "application/json", - "contentSchema": content_schema, - } - sse_content["itemSchema"] = item_schema - operation.setdefault("responses", {}).setdefault( - status_code, {} - ).setdefault("content", {})["text/event-stream"] = sse_content - elif route_response_media_type: - response_schema = {"type": "string"} - if lenient_issubclass(current_response_class, JSONResponse): - if route.response_field: - response_schema = get_schema_from_model_field( - field=route.response_field, - model_name_map=model_name_map, - field_mapping=field_mapping, - separate_input_output_schemas=separate_input_output_schemas, - ) - else: - response_schema = {} - operation.setdefault("responses", {}).setdefault( - status_code, {} - ).setdefault("content", {}).setdefault( - route_response_media_type, {} - )["schema"] = response_schema - if route.responses: - operation_responses = operation.setdefault("responses", {}) - for ( - additional_status_code, - additional_response, - ) in route.responses.items(): - process_response = copy.deepcopy(additional_response) - process_response.pop("model", None) - status_code_key = str(additional_status_code).upper() - if status_code_key == "DEFAULT": - status_code_key = "default" - openapi_response = operation_responses.setdefault( - status_code_key, {} - ) - assert isinstance(process_response, dict), ( - "An additional response must be a dict" - ) - field = route.response_fields.get(additional_status_code) - additional_field_schema: dict[str, Any] | None = None - if field: - additional_field_schema = get_schema_from_model_field( - field=field, - model_name_map=model_name_map, - field_mapping=field_mapping, - separate_input_output_schemas=separate_input_output_schemas, - ) - media_type = route_response_media_type or "application/json" - additional_schema = ( - process_response.setdefault("content", {}) - .setdefault(media_type, {}) - .setdefault("schema", {}) - ) - deep_dict_update(additional_schema, additional_field_schema) - status_text: str | None = status_code_ranges.get( - str(additional_status_code).upper() - ) or http.client.responses.get(int(additional_status_code)) - description = ( - process_response.get("description") - or openapi_response.get("description") - or status_text - or "Additional Response" - ) - deep_dict_update(openapi_response, process_response) - openapi_response["description"] = description - http422 = "422" - all_route_params = get_flat_params(route.dependant) - if (all_route_params or route.body_field) and not any( - status in operation["responses"] - for status in [http422, "4XX", "default"] - ): - operation["responses"][http422] = { - "description": "Validation Error", - "content": { - "application/json": { - "schema": {"$ref": REF_PREFIX + "HTTPValidationError"} - } - }, - } - if "ValidationError" not in definitions: - definitions.update( - { - "ValidationError": validation_error_definition, - "HTTPValidationError": validation_error_response_definition, - } - ) - if route.openapi_extra: - deep_dict_update(operation, route.openapi_extra) - path[method.lower()] = operation - return path, security_schemes, definitions - - -def get_fields_from_routes( - routes: Sequence[BaseRoute], -) -> list[ModelField]: - body_fields_from_routes: list[ModelField] = [] - responses_from_routes: list[ModelField] = [] - request_fields_from_routes: list[ModelField] = [] - callback_flat_models: list[ModelField] = [] - for route in routes: - if not isinstance(route, routing.APIRoute): - continue - if route.include_in_schema: - if route.body_field: - assert isinstance(route.body_field, ModelField), ( - "A request body must be a Pydantic Field" - ) - body_fields_from_routes.append(route.body_field) - if route.response_field: - responses_from_routes.append(route.response_field) - if route.response_fields: - responses_from_routes.extend(route.response_fields.values()) - if route.stream_item_field: - responses_from_routes.append(route.stream_item_field) - if route.callbacks: - callback_flat_models.extend(get_fields_from_routes(route.callbacks)) - params = get_flat_params(route.dependant) - request_fields_from_routes.extend(params) - - flat_models = callback_flat_models + list( - body_fields_from_routes + responses_from_routes + request_fields_from_routes - ) - return flat_models - - -def get_openapi( - *, - title: str, - version: str, - openapi_version: str = "3.1.0", - summary: str | None = None, - description: str | None = None, - routes: Sequence[BaseRoute], - webhooks: Sequence[BaseRoute] | None = None, - tags: list[dict[str, Any]] | None = None, - servers: list[dict[str, str | Any]] | None = None, - terms_of_service: str | None = None, - contact: dict[str, str | Any] | None = None, - license_info: dict[str, str | Any] | None = None, - separate_input_output_schemas: bool = True, - external_docs: dict[str, Any] | None = None, -) -> dict[str, Any]: - info: dict[str, Any] = {"title": title, "version": version} - if summary: - info["summary"] = summary - if description: - info["description"] = description - if terms_of_service: - info["termsOfService"] = terms_of_service - if contact: - info["contact"] = contact - if license_info: - info["license"] = license_info - output: dict[str, Any] = {"openapi": openapi_version, "info": info} - if servers: - output["servers"] = servers - components: dict[str, dict[str, Any]] = {} - paths: dict[str, dict[str, Any]] = {} - webhook_paths: dict[str, dict[str, Any]] = {} - operation_ids: set[str] = set() - all_fields = get_fields_from_routes(list(routes or []) + list(webhooks or [])) - flat_models = get_flat_models_from_fields(all_fields, known_models=set()) - model_name_map = get_model_name_map(flat_models) - field_mapping, definitions = get_definitions( - fields=all_fields, - model_name_map=model_name_map, - separate_input_output_schemas=separate_input_output_schemas, - ) - for route in routes or []: - if isinstance(route, routing.APIRoute): - result = get_openapi_path( - route=route, - operation_ids=operation_ids, - model_name_map=model_name_map, - field_mapping=field_mapping, - separate_input_output_schemas=separate_input_output_schemas, - ) - if result: - path, security_schemes, path_definitions = result - if path: - paths.setdefault(route.path_format, {}).update(path) - if security_schemes: - components.setdefault("securitySchemes", {}).update( - security_schemes - ) - if path_definitions: - definitions.update(path_definitions) - for webhook in webhooks or []: - if isinstance(webhook, routing.APIRoute): - result = get_openapi_path( - route=webhook, - operation_ids=operation_ids, - model_name_map=model_name_map, - field_mapping=field_mapping, - separate_input_output_schemas=separate_input_output_schemas, - ) - if result: - path, security_schemes, path_definitions = result - if path: - webhook_paths.setdefault(webhook.path_format, {}).update(path) - if security_schemes: - components.setdefault("securitySchemes", {}).update( - security_schemes - ) - if path_definitions: - definitions.update(path_definitions) - if definitions: - components["schemas"] = {k: definitions[k] for k in sorted(definitions)} - if components: - output["components"] = components - output["paths"] = paths - if webhook_paths: - output["webhooks"] = webhook_paths - if tags: - output["tags"] = tags - if external_docs: - output["externalDocs"] = external_docs - return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True) # type: ignore # ty: ignore[unused-ignore-comment] diff --git a/notification-service/venv/Lib/site-packages/fastapi/param_functions.py b/notification-service/venv/Lib/site-packages/fastapi/param_functions.py deleted file mode 100644 index 1856178..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/param_functions.py +++ /dev/null @@ -1,2460 +0,0 @@ -from collections.abc import Callable, Sequence -from typing import Annotated, Any, Literal - -from annotated_doc import Doc -from fastapi import params -from fastapi._compat import Undefined -from fastapi.datastructures import _Unset -from fastapi.openapi.models import Example -from pydantic import AliasChoices, AliasPath -from typing_extensions import deprecated - - -def Path( # noqa: N802 - default: Annotated[ - Any, - Doc( - """ - Default value if the parameter field is not set. - - This doesn't affect `Path` parameters as the value is always required. - The parameter is available only for compatibility. - """ - ), - ] = ..., - *, - default_factory: Annotated[ - Callable[[], Any] | None, - Doc( - """ - A callable to generate the default value. - - This doesn't affect `Path` parameters as the value is always required. - The parameter is available only for compatibility. - """ - ), - ] = _Unset, - alias: Annotated[ - str | None, - Doc( - """ - An alternative name for the parameter field. - - This will be used to extract the data and for the generated OpenAPI. - It is particularly useful when you can't use the name you want because it - is a Python reserved keyword or similar. - """ - ), - ] = None, - alias_priority: Annotated[ - int | None, - Doc( - """ - Priority of the alias. This affects whether an alias generator is used. - """ - ), - ] = _Unset, - validation_alias: Annotated[ - str | AliasPath | AliasChoices | None, - Doc( - """ - 'Whitelist' validation step. The parameter field will be the single one - allowed by the alias or set of aliases defined. - """ - ), - ] = None, - serialization_alias: Annotated[ - str | None, - Doc( - """ - 'Blacklist' validation step. The vanilla parameter field will be the - single one of the alias' or set of aliases' fields and all the other - fields will be ignored at serialization time. - """ - ), - ] = None, - title: Annotated[ - str | None, - Doc( - """ - Human-readable title. - - Read more about it in the - [FastAPI docs for Path Parameters and Numeric Validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#declare-metadata) - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Human-readable description. - """ - ), - ] = None, - gt: Annotated[ - float | None, - Doc( - """ - Greater than. If set, value must be greater than this. Only applicable to - numbers. - - Read more about it in the - [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) - """ - ), - ] = None, - ge: Annotated[ - float | None, - Doc( - """ - Greater than or equal. If set, value must be greater than or equal to - this. Only applicable to numbers. - - Read more about it in the - [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) - """ - ), - ] = None, - lt: Annotated[ - float | None, - Doc( - """ - Less than. If set, value must be less than this. Only applicable to numbers. - - Read more about it in the - [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) - """ - ), - ] = None, - le: Annotated[ - float | None, - Doc( - """ - Less than or equal. If set, value must be less than or equal to this. - Only applicable to numbers. - - Read more about it in the - [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) - """ - ), - ] = None, - min_length: Annotated[ - int | None, - Doc( - """ - Minimum length for strings. - """ - ), - ] = None, - max_length: Annotated[ - int | None, - Doc( - """ - Maximum length for strings. - """ - ), - ] = None, - pattern: Annotated[ - str | None, - Doc( - """ - RegEx pattern for strings. - """ - ), - ] = None, - regex: Annotated[ - str | None, - Doc( - """ - RegEx pattern for strings. - """ - ), - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: Annotated[ - str | None, - Doc( - """ - Parameter field name for discriminating the type in a tagged union. - """ - ), - ] = None, - strict: Annotated[ - bool | None, - Doc( - """ - If `True`, strict validation is applied to the field. - """ - ), - ] = _Unset, - multiple_of: Annotated[ - float | None, - Doc( - """ - Value must be a multiple of this. Only applicable to numbers. - """ - ), - ] = _Unset, - allow_inf_nan: Annotated[ - bool | None, - Doc( - """ - Allow `inf`, `-inf`, `nan`. Only applicable to numbers. - """ - ), - ] = _Unset, - max_digits: Annotated[ - int | None, - Doc( - """ - Maximum number of digits allowed for decimal values. - """ - ), - ] = _Unset, - decimal_places: Annotated[ - int | None, - Doc( - """ - Maximum number of decimal places allowed for decimal values. - """ - ), - ] = _Unset, - examples: Annotated[ - list[Any] | None, - Doc( - """ - Example values for this field. - - Read more about it in the - [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/) - """ - ), - ] = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: Annotated[ - dict[str, Example] | None, - Doc( - """ - OpenAPI-specific examples. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Swagger UI (that provides the `/docs` interface) has better support for the - OpenAPI-specific examples than the JSON Schema `examples`, that's the main - use case for this. - - Read more about it in the - [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#using-the-openapi_examples-parameter). - """ - ), - ] = None, - deprecated: Annotated[ - deprecated | str | bool | None, - Doc( - """ - Mark this parameter field as deprecated. - - It will affect the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - include_in_schema: Annotated[ - bool, - Doc( - """ - To include (or not) this parameter field in the generated OpenAPI. - You probably don't need it, but it's available. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = True, - json_schema_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Any additional JSON schema data. - """ - ), - ] = None, - **extra: Annotated[ - Any, - Doc( - """ - Include extra fields used by the JSON Schema. - """ - ), - deprecated( - """ - The `extra` kwargs is deprecated. Use `json_schema_extra` instead. - """ - ), - ], -) -> Any: - """ - Declare a path parameter for a *path operation*. - - Read more about it in the - [FastAPI docs for Path Parameters and Numeric Validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/). - - ```python - from typing import Annotated - - from fastapi import FastAPI, Path - - app = FastAPI() - - - @app.get("/items/{item_id}") - async def read_items( - item_id: Annotated[int, Path(title="The ID of the item to get")], - ): - return {"item_id": item_id} - ``` - """ - return params.Path( - default=default, - default_factory=default_factory, - alias=alias, - alias_priority=alias_priority, - validation_alias=validation_alias, - serialization_alias=serialization_alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - pattern=pattern, - regex=regex, - discriminator=discriminator, - strict=strict, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - example=example, - examples=examples, - openapi_examples=openapi_examples, - deprecated=deprecated, - include_in_schema=include_in_schema, - json_schema_extra=json_schema_extra, - **extra, - ) - - -def Query( # noqa: N802 - default: Annotated[ - Any, - Doc( - """ - Default value if the parameter field is not set. - - Read more about it in the - [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#alternative-old-query-as-the-default-value) - """ - ), - ] = Undefined, - *, - default_factory: Annotated[ - Callable[[], Any] | None, - Doc( - """ - A callable to generate the default value. - - This doesn't affect `Path` parameters as the value is always required. - The parameter is available only for compatibility. - """ - ), - ] = _Unset, - alias: Annotated[ - str | None, - Doc( - """ - An alternative name for the parameter field. - - This will be used to extract the data and for the generated OpenAPI. - It is particularly useful when you can't use the name you want because it - is a Python reserved keyword or similar. - - Read more about it in the - [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#alias-parameters) - """ - ), - ] = None, - alias_priority: Annotated[ - int | None, - Doc( - """ - Priority of the alias. This affects whether an alias generator is used. - """ - ), - ] = _Unset, - validation_alias: Annotated[ - str | AliasPath | AliasChoices | None, - Doc( - """ - 'Whitelist' validation step. The parameter field will be the single one - allowed by the alias or set of aliases defined. - """ - ), - ] = None, - serialization_alias: Annotated[ - str | None, - Doc( - """ - 'Blacklist' validation step. The vanilla parameter field will be the - single one of the alias' or set of aliases' fields and all the other - fields will be ignored at serialization time. - """ - ), - ] = None, - title: Annotated[ - str | None, - Doc( - """ - Human-readable title. - - Read more about it in the - [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#declare-more-metadata) - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Human-readable description. - - Read more about it in the - [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#declare-more-metadata) - """ - ), - ] = None, - gt: Annotated[ - float | None, - Doc( - """ - Greater than. If set, value must be greater than this. Only applicable to - numbers. - - Read more about it in the - [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) - """ - ), - ] = None, - ge: Annotated[ - float | None, - Doc( - """ - Greater than or equal. If set, value must be greater than or equal to - this. Only applicable to numbers. - - Read more about it in the - [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) - """ - ), - ] = None, - lt: Annotated[ - float | None, - Doc( - """ - Less than. If set, value must be less than this. Only applicable to numbers. - - Read more about it in the - [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) - """ - ), - ] = None, - le: Annotated[ - float | None, - Doc( - """ - Less than or equal. If set, value must be less than or equal to this. - Only applicable to numbers. - - Read more about it in the - [FastAPI docs about Path parameters numeric validations](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#number-validations-greater-than-and-less-than-or-equal) - """ - ), - ] = None, - min_length: Annotated[ - int | None, - Doc( - """ - Minimum length for strings. - - Read more about it in the - [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/) - """ - ), - ] = None, - max_length: Annotated[ - int | None, - Doc( - """ - Maximum length for strings. - - Read more about it in the - [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/) - """ - ), - ] = None, - pattern: Annotated[ - str | None, - Doc( - """ - RegEx pattern for strings. - - Read more about it in the - [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#add-regular-expressions - """ - ), - ] = None, - regex: Annotated[ - str | None, - Doc( - """ - RegEx pattern for strings. - """ - ), - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: Annotated[ - str | None, - Doc( - """ - Parameter field name for discriminating the type in a tagged union. - """ - ), - ] = None, - strict: Annotated[ - bool | None, - Doc( - """ - If `True`, strict validation is applied to the field. - """ - ), - ] = _Unset, - multiple_of: Annotated[ - float | None, - Doc( - """ - Value must be a multiple of this. Only applicable to numbers. - """ - ), - ] = _Unset, - allow_inf_nan: Annotated[ - bool | None, - Doc( - """ - Allow `inf`, `-inf`, `nan`. Only applicable to numbers. - """ - ), - ] = _Unset, - max_digits: Annotated[ - int | None, - Doc( - """ - Maximum number of digits allowed for decimal values. - """ - ), - ] = _Unset, - decimal_places: Annotated[ - int | None, - Doc( - """ - Maximum number of decimal places allowed for decimal values. - """ - ), - ] = _Unset, - examples: Annotated[ - list[Any] | None, - Doc( - """ - Example values for this field. - - Read more about it in the - [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/) - """ - ), - ] = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: Annotated[ - dict[str, Example] | None, - Doc( - """ - OpenAPI-specific examples. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Swagger UI (that provides the `/docs` interface) has better support for the - OpenAPI-specific examples than the JSON Schema `examples`, that's the main - use case for this. - - Read more about it in the - [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#using-the-openapi_examples-parameter). - """ - ), - ] = None, - deprecated: Annotated[ - deprecated | str | bool | None, - Doc( - """ - Mark this parameter field as deprecated. - - It will affect the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#deprecating-parameters) - """ - ), - ] = None, - include_in_schema: Annotated[ - bool, - Doc( - """ - To include (or not) this parameter field in the generated OpenAPI. - You probably don't need it, but it's available. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs about Query parameters](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi - """ - ), - ] = True, - json_schema_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Any additional JSON schema data. - """ - ), - ] = None, - **extra: Annotated[ - Any, - Doc( - """ - Include extra fields used by the JSON Schema. - """ - ), - deprecated( - """ - The `extra` kwargs is deprecated. Use `json_schema_extra` instead. - """ - ), - ], -) -> Any: - return params.Query( - default=default, - default_factory=default_factory, - alias=alias, - alias_priority=alias_priority, - validation_alias=validation_alias, - serialization_alias=serialization_alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - pattern=pattern, - regex=regex, - discriminator=discriminator, - strict=strict, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - example=example, - examples=examples, - openapi_examples=openapi_examples, - deprecated=deprecated, - include_in_schema=include_in_schema, - json_schema_extra=json_schema_extra, - **extra, - ) - - -def Header( # noqa: N802 - default: Annotated[ - Any, - Doc( - """ - Default value if the parameter field is not set. - """ - ), - ] = Undefined, - *, - default_factory: Annotated[ - Callable[[], Any] | None, - Doc( - """ - A callable to generate the default value. - - This doesn't affect `Path` parameters as the value is always required. - The parameter is available only for compatibility. - """ - ), - ] = _Unset, - alias: Annotated[ - str | None, - Doc( - """ - An alternative name for the parameter field. - - This will be used to extract the data and for the generated OpenAPI. - It is particularly useful when you can't use the name you want because it - is a Python reserved keyword or similar. - """ - ), - ] = None, - alias_priority: Annotated[ - int | None, - Doc( - """ - Priority of the alias. This affects whether an alias generator is used. - """ - ), - ] = _Unset, - validation_alias: Annotated[ - str | AliasPath | AliasChoices | None, - Doc( - """ - 'Whitelist' validation step. The parameter field will be the single one - allowed by the alias or set of aliases defined. - """ - ), - ] = None, - serialization_alias: Annotated[ - str | None, - Doc( - """ - 'Blacklist' validation step. The vanilla parameter field will be the - single one of the alias' or set of aliases' fields and all the other - fields will be ignored at serialization time. - """ - ), - ] = None, - convert_underscores: Annotated[ - bool, - Doc( - """ - Automatically convert underscores to hyphens in the parameter field name. - - Read more about it in the - [FastAPI docs for Header Parameters](https://fastapi.tiangolo.com/tutorial/header-params/#automatic-conversion) - """ - ), - ] = True, - title: Annotated[ - str | None, - Doc( - """ - Human-readable title. - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Human-readable description. - """ - ), - ] = None, - gt: Annotated[ - float | None, - Doc( - """ - Greater than. If set, value must be greater than this. Only applicable to - numbers. - """ - ), - ] = None, - ge: Annotated[ - float | None, - Doc( - """ - Greater than or equal. If set, value must be greater than or equal to - this. Only applicable to numbers. - """ - ), - ] = None, - lt: Annotated[ - float | None, - Doc( - """ - Less than. If set, value must be less than this. Only applicable to numbers. - """ - ), - ] = None, - le: Annotated[ - float | None, - Doc( - """ - Less than or equal. If set, value must be less than or equal to this. - Only applicable to numbers. - """ - ), - ] = None, - min_length: Annotated[ - int | None, - Doc( - """ - Minimum length for strings. - """ - ), - ] = None, - max_length: Annotated[ - int | None, - Doc( - """ - Maximum length for strings. - """ - ), - ] = None, - pattern: Annotated[ - str | None, - Doc( - """ - RegEx pattern for strings. - """ - ), - ] = None, - regex: Annotated[ - str | None, - Doc( - """ - RegEx pattern for strings. - """ - ), - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: Annotated[ - str | None, - Doc( - """ - Parameter field name for discriminating the type in a tagged union. - """ - ), - ] = None, - strict: Annotated[ - bool | None, - Doc( - """ - If `True`, strict validation is applied to the field. - """ - ), - ] = _Unset, - multiple_of: Annotated[ - float | None, - Doc( - """ - Value must be a multiple of this. Only applicable to numbers. - """ - ), - ] = _Unset, - allow_inf_nan: Annotated[ - bool | None, - Doc( - """ - Allow `inf`, `-inf`, `nan`. Only applicable to numbers. - """ - ), - ] = _Unset, - max_digits: Annotated[ - int | None, - Doc( - """ - Maximum number of digits allowed for decimal values. - """ - ), - ] = _Unset, - decimal_places: Annotated[ - int | None, - Doc( - """ - Maximum number of decimal places allowed for decimal values. - """ - ), - ] = _Unset, - examples: Annotated[ - list[Any] | None, - Doc( - """ - Example values for this field. - - Read more about it in the - [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/) - """ - ), - ] = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: Annotated[ - dict[str, Example] | None, - Doc( - """ - OpenAPI-specific examples. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Swagger UI (that provides the `/docs` interface) has better support for the - OpenAPI-specific examples than the JSON Schema `examples`, that's the main - use case for this. - - Read more about it in the - [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#using-the-openapi_examples-parameter). - """ - ), - ] = None, - deprecated: Annotated[ - deprecated | str | bool | None, - Doc( - """ - Mark this parameter field as deprecated. - - It will affect the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - include_in_schema: Annotated[ - bool, - Doc( - """ - To include (or not) this parameter field in the generated OpenAPI. - You probably don't need it, but it's available. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = True, - json_schema_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Any additional JSON schema data. - """ - ), - ] = None, - **extra: Annotated[ - Any, - Doc( - """ - Include extra fields used by the JSON Schema. - """ - ), - deprecated( - """ - The `extra` kwargs is deprecated. Use `json_schema_extra` instead. - """ - ), - ], -) -> Any: - return params.Header( - default=default, - default_factory=default_factory, - alias=alias, - alias_priority=alias_priority, - validation_alias=validation_alias, - serialization_alias=serialization_alias, - convert_underscores=convert_underscores, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - pattern=pattern, - regex=regex, - discriminator=discriminator, - strict=strict, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - example=example, - examples=examples, - openapi_examples=openapi_examples, - deprecated=deprecated, - include_in_schema=include_in_schema, - json_schema_extra=json_schema_extra, - **extra, - ) - - -def Cookie( # noqa: N802 - default: Annotated[ - Any, - Doc( - """ - Default value if the parameter field is not set. - """ - ), - ] = Undefined, - *, - default_factory: Annotated[ - Callable[[], Any] | None, - Doc( - """ - A callable to generate the default value. - - This doesn't affect `Path` parameters as the value is always required. - The parameter is available only for compatibility. - """ - ), - ] = _Unset, - alias: Annotated[ - str | None, - Doc( - """ - An alternative name for the parameter field. - - This will be used to extract the data and for the generated OpenAPI. - It is particularly useful when you can't use the name you want because it - is a Python reserved keyword or similar. - """ - ), - ] = None, - alias_priority: Annotated[ - int | None, - Doc( - """ - Priority of the alias. This affects whether an alias generator is used. - """ - ), - ] = _Unset, - validation_alias: Annotated[ - str | AliasPath | AliasChoices | None, - Doc( - """ - 'Whitelist' validation step. The parameter field will be the single one - allowed by the alias or set of aliases defined. - """ - ), - ] = None, - serialization_alias: Annotated[ - str | None, - Doc( - """ - 'Blacklist' validation step. The vanilla parameter field will be the - single one of the alias' or set of aliases' fields and all the other - fields will be ignored at serialization time. - """ - ), - ] = None, - title: Annotated[ - str | None, - Doc( - """ - Human-readable title. - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Human-readable description. - """ - ), - ] = None, - gt: Annotated[ - float | None, - Doc( - """ - Greater than. If set, value must be greater than this. Only applicable to - numbers. - """ - ), - ] = None, - ge: Annotated[ - float | None, - Doc( - """ - Greater than or equal. If set, value must be greater than or equal to - this. Only applicable to numbers. - """ - ), - ] = None, - lt: Annotated[ - float | None, - Doc( - """ - Less than. If set, value must be less than this. Only applicable to numbers. - """ - ), - ] = None, - le: Annotated[ - float | None, - Doc( - """ - Less than or equal. If set, value must be less than or equal to this. - Only applicable to numbers. - """ - ), - ] = None, - min_length: Annotated[ - int | None, - Doc( - """ - Minimum length for strings. - """ - ), - ] = None, - max_length: Annotated[ - int | None, - Doc( - """ - Maximum length for strings. - """ - ), - ] = None, - pattern: Annotated[ - str | None, - Doc( - """ - RegEx pattern for strings. - """ - ), - ] = None, - regex: Annotated[ - str | None, - Doc( - """ - RegEx pattern for strings. - """ - ), - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: Annotated[ - str | None, - Doc( - """ - Parameter field name for discriminating the type in a tagged union. - """ - ), - ] = None, - strict: Annotated[ - bool | None, - Doc( - """ - If `True`, strict validation is applied to the field. - """ - ), - ] = _Unset, - multiple_of: Annotated[ - float | None, - Doc( - """ - Value must be a multiple of this. Only applicable to numbers. - """ - ), - ] = _Unset, - allow_inf_nan: Annotated[ - bool | None, - Doc( - """ - Allow `inf`, `-inf`, `nan`. Only applicable to numbers. - """ - ), - ] = _Unset, - max_digits: Annotated[ - int | None, - Doc( - """ - Maximum number of digits allowed for decimal values. - """ - ), - ] = _Unset, - decimal_places: Annotated[ - int | None, - Doc( - """ - Maximum number of decimal places allowed for decimal values. - """ - ), - ] = _Unset, - examples: Annotated[ - list[Any] | None, - Doc( - """ - Example values for this field. - - Read more about it in the - [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/) - """ - ), - ] = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: Annotated[ - dict[str, Example] | None, - Doc( - """ - OpenAPI-specific examples. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Swagger UI (that provides the `/docs` interface) has better support for the - OpenAPI-specific examples than the JSON Schema `examples`, that's the main - use case for this. - - Read more about it in the - [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#using-the-openapi_examples-parameter). - """ - ), - ] = None, - deprecated: Annotated[ - deprecated | str | bool | None, - Doc( - """ - Mark this parameter field as deprecated. - - It will affect the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - include_in_schema: Annotated[ - bool, - Doc( - """ - To include (or not) this parameter field in the generated OpenAPI. - You probably don't need it, but it's available. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = True, - json_schema_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Any additional JSON schema data. - """ - ), - ] = None, - **extra: Annotated[ - Any, - Doc( - """ - Include extra fields used by the JSON Schema. - """ - ), - deprecated( - """ - The `extra` kwargs is deprecated. Use `json_schema_extra` instead. - """ - ), - ], -) -> Any: - return params.Cookie( - default=default, - default_factory=default_factory, - alias=alias, - alias_priority=alias_priority, - validation_alias=validation_alias, - serialization_alias=serialization_alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - pattern=pattern, - regex=regex, - discriminator=discriminator, - strict=strict, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - example=example, - examples=examples, - openapi_examples=openapi_examples, - deprecated=deprecated, - include_in_schema=include_in_schema, - json_schema_extra=json_schema_extra, - **extra, - ) - - -def Body( # noqa: N802 - default: Annotated[ - Any, - Doc( - """ - Default value if the parameter field is not set. - """ - ), - ] = Undefined, - *, - default_factory: Annotated[ - Callable[[], Any] | None, - Doc( - """ - A callable to generate the default value. - - This doesn't affect `Path` parameters as the value is always required. - The parameter is available only for compatibility. - """ - ), - ] = _Unset, - embed: Annotated[ - bool | None, - Doc( - """ - When `embed` is `True`, the parameter will be expected in a JSON body as a - key instead of being the JSON body itself. - - This happens automatically when more than one `Body` parameter is declared. - - Read more about it in the - [FastAPI docs for Body - Multiple Parameters](https://fastapi.tiangolo.com/tutorial/body-multiple-params/#embed-a-single-body-parameter). - """ - ), - ] = None, - media_type: Annotated[ - str, - Doc( - """ - The media type of this parameter field. Changing it would affect the - generated OpenAPI, but currently it doesn't affect the parsing of the data. - """ - ), - ] = "application/json", - alias: Annotated[ - str | None, - Doc( - """ - An alternative name for the parameter field. - - This will be used to extract the data and for the generated OpenAPI. - It is particularly useful when you can't use the name you want because it - is a Python reserved keyword or similar. - """ - ), - ] = None, - alias_priority: Annotated[ - int | None, - Doc( - """ - Priority of the alias. This affects whether an alias generator is used. - """ - ), - ] = _Unset, - validation_alias: Annotated[ - str | AliasPath | AliasChoices | None, - Doc( - """ - 'Whitelist' validation step. The parameter field will be the single one - allowed by the alias or set of aliases defined. - """ - ), - ] = None, - serialization_alias: Annotated[ - str | None, - Doc( - """ - 'Blacklist' validation step. The vanilla parameter field will be the - single one of the alias' or set of aliases' fields and all the other - fields will be ignored at serialization time. - """ - ), - ] = None, - title: Annotated[ - str | None, - Doc( - """ - Human-readable title. - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Human-readable description. - """ - ), - ] = None, - gt: Annotated[ - float | None, - Doc( - """ - Greater than. If set, value must be greater than this. Only applicable to - numbers. - """ - ), - ] = None, - ge: Annotated[ - float | None, - Doc( - """ - Greater than or equal. If set, value must be greater than or equal to - this. Only applicable to numbers. - """ - ), - ] = None, - lt: Annotated[ - float | None, - Doc( - """ - Less than. If set, value must be less than this. Only applicable to numbers. - """ - ), - ] = None, - le: Annotated[ - float | None, - Doc( - """ - Less than or equal. If set, value must be less than or equal to this. - Only applicable to numbers. - """ - ), - ] = None, - min_length: Annotated[ - int | None, - Doc( - """ - Minimum length for strings. - """ - ), - ] = None, - max_length: Annotated[ - int | None, - Doc( - """ - Maximum length for strings. - """ - ), - ] = None, - pattern: Annotated[ - str | None, - Doc( - """ - RegEx pattern for strings. - """ - ), - ] = None, - regex: Annotated[ - str | None, - Doc( - """ - RegEx pattern for strings. - """ - ), - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: Annotated[ - str | None, - Doc( - """ - Parameter field name for discriminating the type in a tagged union. - """ - ), - ] = None, - strict: Annotated[ - bool | None, - Doc( - """ - If `True`, strict validation is applied to the field. - """ - ), - ] = _Unset, - multiple_of: Annotated[ - float | None, - Doc( - """ - Value must be a multiple of this. Only applicable to numbers. - """ - ), - ] = _Unset, - allow_inf_nan: Annotated[ - bool | None, - Doc( - """ - Allow `inf`, `-inf`, `nan`. Only applicable to numbers. - """ - ), - ] = _Unset, - max_digits: Annotated[ - int | None, - Doc( - """ - Maximum number of digits allowed for decimal values. - """ - ), - ] = _Unset, - decimal_places: Annotated[ - int | None, - Doc( - """ - Maximum number of decimal places allowed for decimal values. - """ - ), - ] = _Unset, - examples: Annotated[ - list[Any] | None, - Doc( - """ - Example values for this field. - - Read more about it in the - [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/) - """ - ), - ] = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: Annotated[ - dict[str, Example] | None, - Doc( - """ - OpenAPI-specific examples. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Swagger UI (that provides the `/docs` interface) has better support for the - OpenAPI-specific examples than the JSON Schema `examples`, that's the main - use case for this. - - Read more about it in the - [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#using-the-openapi_examples-parameter). - """ - ), - ] = None, - deprecated: Annotated[ - deprecated | str | bool | None, - Doc( - """ - Mark this parameter field as deprecated. - - It will affect the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - include_in_schema: Annotated[ - bool, - Doc( - """ - To include (or not) this parameter field in the generated OpenAPI. - You probably don't need it, but it's available. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = True, - json_schema_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Any additional JSON schema data. - """ - ), - ] = None, - **extra: Annotated[ - Any, - Doc( - """ - Include extra fields used by the JSON Schema. - """ - ), - deprecated( - """ - The `extra` kwargs is deprecated. Use `json_schema_extra` instead. - """ - ), - ], -) -> Any: - return params.Body( - default=default, - default_factory=default_factory, - embed=embed, - media_type=media_type, - alias=alias, - alias_priority=alias_priority, - validation_alias=validation_alias, - serialization_alias=serialization_alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - pattern=pattern, - regex=regex, - discriminator=discriminator, - strict=strict, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - example=example, - examples=examples, - openapi_examples=openapi_examples, - deprecated=deprecated, - include_in_schema=include_in_schema, - json_schema_extra=json_schema_extra, - **extra, - ) - - -def Form( # noqa: N802 - default: Annotated[ - Any, - Doc( - """ - Default value if the parameter field is not set. - """ - ), - ] = Undefined, - *, - default_factory: Annotated[ - Callable[[], Any] | None, - Doc( - """ - A callable to generate the default value. - - This doesn't affect `Path` parameters as the value is always required. - The parameter is available only for compatibility. - """ - ), - ] = _Unset, - media_type: Annotated[ - str, - Doc( - """ - The media type of this parameter field. Changing it would affect the - generated OpenAPI, but currently it doesn't affect the parsing of the data. - """ - ), - ] = "application/x-www-form-urlencoded", - alias: Annotated[ - str | None, - Doc( - """ - An alternative name for the parameter field. - - This will be used to extract the data and for the generated OpenAPI. - It is particularly useful when you can't use the name you want because it - is a Python reserved keyword or similar. - """ - ), - ] = None, - alias_priority: Annotated[ - int | None, - Doc( - """ - Priority of the alias. This affects whether an alias generator is used. - """ - ), - ] = _Unset, - validation_alias: Annotated[ - str | AliasPath | AliasChoices | None, - Doc( - """ - 'Whitelist' validation step. The parameter field will be the single one - allowed by the alias or set of aliases defined. - """ - ), - ] = None, - serialization_alias: Annotated[ - str | None, - Doc( - """ - 'Blacklist' validation step. The vanilla parameter field will be the - single one of the alias' or set of aliases' fields and all the other - fields will be ignored at serialization time. - """ - ), - ] = None, - title: Annotated[ - str | None, - Doc( - """ - Human-readable title. - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Human-readable description. - """ - ), - ] = None, - gt: Annotated[ - float | None, - Doc( - """ - Greater than. If set, value must be greater than this. Only applicable to - numbers. - """ - ), - ] = None, - ge: Annotated[ - float | None, - Doc( - """ - Greater than or equal. If set, value must be greater than or equal to - this. Only applicable to numbers. - """ - ), - ] = None, - lt: Annotated[ - float | None, - Doc( - """ - Less than. If set, value must be less than this. Only applicable to numbers. - """ - ), - ] = None, - le: Annotated[ - float | None, - Doc( - """ - Less than or equal. If set, value must be less than or equal to this. - Only applicable to numbers. - """ - ), - ] = None, - min_length: Annotated[ - int | None, - Doc( - """ - Minimum length for strings. - """ - ), - ] = None, - max_length: Annotated[ - int | None, - Doc( - """ - Maximum length for strings. - """ - ), - ] = None, - pattern: Annotated[ - str | None, - Doc( - """ - RegEx pattern for strings. - """ - ), - ] = None, - regex: Annotated[ - str | None, - Doc( - """ - RegEx pattern for strings. - """ - ), - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: Annotated[ - str | None, - Doc( - """ - Parameter field name for discriminating the type in a tagged union. - """ - ), - ] = None, - strict: Annotated[ - bool | None, - Doc( - """ - If `True`, strict validation is applied to the field. - """ - ), - ] = _Unset, - multiple_of: Annotated[ - float | None, - Doc( - """ - Value must be a multiple of this. Only applicable to numbers. - """ - ), - ] = _Unset, - allow_inf_nan: Annotated[ - bool | None, - Doc( - """ - Allow `inf`, `-inf`, `nan`. Only applicable to numbers. - """ - ), - ] = _Unset, - max_digits: Annotated[ - int | None, - Doc( - """ - Maximum number of digits allowed for decimal values. - """ - ), - ] = _Unset, - decimal_places: Annotated[ - int | None, - Doc( - """ - Maximum number of decimal places allowed for decimal values. - """ - ), - ] = _Unset, - examples: Annotated[ - list[Any] | None, - Doc( - """ - Example values for this field. - - Read more about it in the - [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/) - """ - ), - ] = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: Annotated[ - dict[str, Example] | None, - Doc( - """ - OpenAPI-specific examples. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Swagger UI (that provides the `/docs` interface) has better support for the - OpenAPI-specific examples than the JSON Schema `examples`, that's the main - use case for this. - - Read more about it in the - [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#using-the-openapi_examples-parameter). - """ - ), - ] = None, - deprecated: Annotated[ - deprecated | str | bool | None, - Doc( - """ - Mark this parameter field as deprecated. - - It will affect the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - include_in_schema: Annotated[ - bool, - Doc( - """ - To include (or not) this parameter field in the generated OpenAPI. - You probably don't need it, but it's available. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = True, - json_schema_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Any additional JSON schema data. - """ - ), - ] = None, - **extra: Annotated[ - Any, - Doc( - """ - Include extra fields used by the JSON Schema. - """ - ), - deprecated( - """ - The `extra` kwargs is deprecated. Use `json_schema_extra` instead. - """ - ), - ], -) -> Any: - return params.Form( - default=default, - default_factory=default_factory, - media_type=media_type, - alias=alias, - alias_priority=alias_priority, - validation_alias=validation_alias, - serialization_alias=serialization_alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - pattern=pattern, - regex=regex, - discriminator=discriminator, - strict=strict, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - example=example, - examples=examples, - openapi_examples=openapi_examples, - deprecated=deprecated, - include_in_schema=include_in_schema, - json_schema_extra=json_schema_extra, - **extra, - ) - - -def File( # noqa: N802 - default: Annotated[ - Any, - Doc( - """ - Default value if the parameter field is not set. - """ - ), - ] = Undefined, - *, - default_factory: Annotated[ - Callable[[], Any] | None, - Doc( - """ - A callable to generate the default value. - - This doesn't affect `Path` parameters as the value is always required. - The parameter is available only for compatibility. - """ - ), - ] = _Unset, - media_type: Annotated[ - str, - Doc( - """ - The media type of this parameter field. Changing it would affect the - generated OpenAPI, but currently it doesn't affect the parsing of the data. - """ - ), - ] = "multipart/form-data", - alias: Annotated[ - str | None, - Doc( - """ - An alternative name for the parameter field. - - This will be used to extract the data and for the generated OpenAPI. - It is particularly useful when you can't use the name you want because it - is a Python reserved keyword or similar. - """ - ), - ] = None, - alias_priority: Annotated[ - int | None, - Doc( - """ - Priority of the alias. This affects whether an alias generator is used. - """ - ), - ] = _Unset, - validation_alias: Annotated[ - str | AliasPath | AliasChoices | None, - Doc( - """ - 'Whitelist' validation step. The parameter field will be the single one - allowed by the alias or set of aliases defined. - """ - ), - ] = None, - serialization_alias: Annotated[ - str | None, - Doc( - """ - 'Blacklist' validation step. The vanilla parameter field will be the - single one of the alias' or set of aliases' fields and all the other - fields will be ignored at serialization time. - """ - ), - ] = None, - title: Annotated[ - str | None, - Doc( - """ - Human-readable title. - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Human-readable description. - """ - ), - ] = None, - gt: Annotated[ - float | None, - Doc( - """ - Greater than. If set, value must be greater than this. Only applicable to - numbers. - """ - ), - ] = None, - ge: Annotated[ - float | None, - Doc( - """ - Greater than or equal. If set, value must be greater than or equal to - this. Only applicable to numbers. - """ - ), - ] = None, - lt: Annotated[ - float | None, - Doc( - """ - Less than. If set, value must be less than this. Only applicable to numbers. - """ - ), - ] = None, - le: Annotated[ - float | None, - Doc( - """ - Less than or equal. If set, value must be less than or equal to this. - Only applicable to numbers. - """ - ), - ] = None, - min_length: Annotated[ - int | None, - Doc( - """ - Minimum length for strings. - """ - ), - ] = None, - max_length: Annotated[ - int | None, - Doc( - """ - Maximum length for strings. - """ - ), - ] = None, - pattern: Annotated[ - str | None, - Doc( - """ - RegEx pattern for strings. - """ - ), - ] = None, - regex: Annotated[ - str | None, - Doc( - """ - RegEx pattern for strings. - """ - ), - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: Annotated[ - str | None, - Doc( - """ - Parameter field name for discriminating the type in a tagged union. - """ - ), - ] = None, - strict: Annotated[ - bool | None, - Doc( - """ - If `True`, strict validation is applied to the field. - """ - ), - ] = _Unset, - multiple_of: Annotated[ - float | None, - Doc( - """ - Value must be a multiple of this. Only applicable to numbers. - """ - ), - ] = _Unset, - allow_inf_nan: Annotated[ - bool | None, - Doc( - """ - Allow `inf`, `-inf`, `nan`. Only applicable to numbers. - """ - ), - ] = _Unset, - max_digits: Annotated[ - int | None, - Doc( - """ - Maximum number of digits allowed for decimal values. - """ - ), - ] = _Unset, - decimal_places: Annotated[ - int | None, - Doc( - """ - Maximum number of decimal places allowed for decimal values. - """ - ), - ] = _Unset, - examples: Annotated[ - list[Any] | None, - Doc( - """ - Example values for this field. - - Read more about it in the - [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/) - """ - ), - ] = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: Annotated[ - dict[str, Example] | None, - Doc( - """ - OpenAPI-specific examples. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Swagger UI (that provides the `/docs` interface) has better support for the - OpenAPI-specific examples than the JSON Schema `examples`, that's the main - use case for this. - - Read more about it in the - [FastAPI docs for Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#using-the-openapi_examples-parameter). - """ - ), - ] = None, - deprecated: Annotated[ - deprecated | str | bool | None, - Doc( - """ - Mark this parameter field as deprecated. - - It will affect the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - include_in_schema: Annotated[ - bool, - Doc( - """ - To include (or not) this parameter field in the generated OpenAPI. - You probably don't need it, but it's available. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = True, - json_schema_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Any additional JSON schema data. - """ - ), - ] = None, - **extra: Annotated[ - Any, - Doc( - """ - Include extra fields used by the JSON Schema. - """ - ), - deprecated( - """ - The `extra` kwargs is deprecated. Use `json_schema_extra` instead. - """ - ), - ], -) -> Any: - return params.File( - default=default, - default_factory=default_factory, - media_type=media_type, - alias=alias, - alias_priority=alias_priority, - validation_alias=validation_alias, - serialization_alias=serialization_alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - pattern=pattern, - regex=regex, - discriminator=discriminator, - strict=strict, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - example=example, - examples=examples, - openapi_examples=openapi_examples, - deprecated=deprecated, - include_in_schema=include_in_schema, - json_schema_extra=json_schema_extra, - **extra, - ) - - -def Depends( # noqa: N802 - dependency: Annotated[ - Callable[..., Any] | None, - Doc( - """ - A "dependable" callable (like a function). - - Don't call it directly, FastAPI will call it for you, just pass the object - directly. - - Read more about it in the - [FastAPI docs for Dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/) - """ - ), - ] = None, - *, - use_cache: Annotated[ - bool, - Doc( - """ - By default, after a dependency is called the first time in a request, if - the dependency is declared again for the rest of the request (for example - if the dependency is needed by several dependencies), the value will be - re-used for the rest of the request. - - Set `use_cache` to `False` to disable this behavior and ensure the - dependency is called again (if declared more than once) in the same request. - - Read more about it in the - [FastAPI docs about sub-dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/sub-dependencies/#using-the-same-dependency-multiple-times) - """ - ), - ] = True, - scope: Annotated[ - Literal["function", "request"] | None, - Doc( - """ - Mainly for dependencies with `yield`, define when the dependency function - should start (the code before `yield`) and when it should end (the code - after `yield`). - - * `"function"`: start the dependency before the *path operation function* - that handles the request, end the dependency after the *path operation - function* ends, but **before** the response is sent back to the client. - So, the dependency function will be executed **around** the *path operation - **function***. - * `"request"`: start the dependency before the *path operation function* - that handles the request (similar to when using `"function"`), but end - **after** the response is sent back to the client. So, the dependency - function will be executed **around** the **request** and response cycle. - - Read more about it in the - [FastAPI docs for FastAPI Dependencies with yield](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#early-exit-and-scope) - """ - ), - ] = None, -) -> Any: - """ - Declare a FastAPI dependency. - - It takes a single "dependable" callable (like a function). - - Don't call it directly, FastAPI will call it for you. - - Read more about it in the - [FastAPI docs for Dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/). - - **Example** - - ```python - from typing import Annotated - - from fastapi import Depends, FastAPI - - app = FastAPI() - - - async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100): - return {"q": q, "skip": skip, "limit": limit} - - - @app.get("/items/") - async def read_items(commons: Annotated[dict, Depends(common_parameters)]): - return commons - ``` - """ - return params.Depends(dependency=dependency, use_cache=use_cache, scope=scope) - - -def Security( # noqa: N802 - dependency: Annotated[ - Callable[..., Any] | None, - Doc( - """ - A "dependable" callable (like a function). - - Don't call it directly, FastAPI will call it for you, just pass the object - directly. - - Read more about it in the - [FastAPI docs for Dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/) - """ - ), - ] = None, - *, - scopes: Annotated[ - Sequence[str] | None, - Doc( - """ - OAuth2 scopes required for the *path operation* that uses this Security - dependency. - - The term "scope" comes from the OAuth2 specification, it seems to be - intentionally vague and interpretable. It normally refers to permissions, - in cases to roles. - - These scopes are integrated with OpenAPI (and the API docs at `/docs`). - So they are visible in the OpenAPI specification. - - Read more about it in the - [FastAPI docs about OAuth2 scopes](https://fastapi.tiangolo.com/advanced/security/oauth2-scopes/) - """ - ), - ] = None, - use_cache: Annotated[ - bool, - Doc( - """ - By default, after a dependency is called the first time in a request, if - the dependency is declared again for the rest of the request (for example - if the dependency is needed by several dependencies), the value will be - re-used for the rest of the request. - - Set `use_cache` to `False` to disable this behavior and ensure the - dependency is called again (if declared more than once) in the same request. - - Read more about it in the - [FastAPI docs about sub-dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/sub-dependencies/#using-the-same-dependency-multiple-times) - """ - ), - ] = True, -) -> Any: - """ - Declare a FastAPI Security dependency. - - The only difference with a regular dependency is that it can declare OAuth2 - scopes that will be integrated with OpenAPI and the automatic UI docs (by default - at `/docs`). - - It takes a single "dependable" callable (like a function). - - Don't call it directly, FastAPI will call it for you. - - Read more about it in the - [FastAPI docs for Security](https://fastapi.tiangolo.com/tutorial/security/) and - in the - [FastAPI docs for OAuth2 scopes](https://fastapi.tiangolo.com/advanced/security/oauth2-scopes/). - - **Example** - - ```python - from typing import Annotated - - from fastapi import Security, FastAPI - - from .db import User - from .security import get_current_active_user - - app = FastAPI() - - @app.get("/users/me/items/") - async def read_own_items( - current_user: Annotated[User, Security(get_current_active_user, scopes=["items"])] - ): - return [{"item_id": "Foo", "owner": current_user.username}] - ``` - """ - return params.Security(dependency=dependency, scopes=scopes, use_cache=use_cache) diff --git a/notification-service/venv/Lib/site-packages/fastapi/params.py b/notification-service/venv/Lib/site-packages/fastapi/params.py deleted file mode 100644 index e8f2eb2..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/params.py +++ /dev/null @@ -1,754 +0,0 @@ -import warnings -from collections.abc import Callable, Sequence -from dataclasses import dataclass -from enum import Enum -from typing import Annotated, Any, Literal - -from fastapi.exceptions import FastAPIDeprecationWarning -from fastapi.openapi.models import Example -from pydantic import AliasChoices, AliasPath -from pydantic.fields import FieldInfo -from typing_extensions import deprecated - -from ._compat import ( - Undefined, -) -from .datastructures import _Unset - - -class ParamTypes(Enum): - query = "query" - header = "header" - path = "path" - cookie = "cookie" - - -class Param(FieldInfo): # type: ignore[misc] - in_: ParamTypes - - def __init__( - self, - default: Any = Undefined, - *, - default_factory: Callable[[], Any] | None = _Unset, - annotation: Any | None = None, - alias: str | None = None, - alias_priority: int | None = _Unset, - validation_alias: str | AliasPath | AliasChoices | None = None, - serialization_alias: str | None = None, - title: str | None = None, - description: str | None = None, - gt: float | None = None, - ge: float | None = None, - lt: float | None = None, - le: float | None = None, - min_length: int | None = None, - max_length: int | None = None, - pattern: str | None = None, - regex: Annotated[ - str | None, - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: str | None = None, - strict: bool | None = _Unset, - multiple_of: float | None = _Unset, - allow_inf_nan: bool | None = _Unset, - max_digits: int | None = _Unset, - decimal_places: int | None = _Unset, - examples: list[Any] | None = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: dict[str, Example] | None = None, - deprecated: deprecated | str | bool | None = None, - include_in_schema: bool = True, - json_schema_extra: dict[str, Any] | None = None, - **extra: Any, - ): - if example is not _Unset: - warnings.warn( - "`example` has been deprecated, please use `examples` instead", - category=FastAPIDeprecationWarning, - stacklevel=4, - ) - self.example = example - self.include_in_schema = include_in_schema - self.openapi_examples = openapi_examples - kwargs = dict( - default=default, - default_factory=default_factory, - alias=alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - discriminator=discriminator, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - **extra, - ) - if examples is not None: - kwargs["examples"] = examples - if regex is not None: - warnings.warn( - "`regex` has been deprecated, please use `pattern` instead", - category=FastAPIDeprecationWarning, - stacklevel=4, - ) - current_json_schema_extra = json_schema_extra or extra - kwargs["deprecated"] = deprecated - - if serialization_alias in (_Unset, None) and isinstance(alias, str): - serialization_alias = alias - if validation_alias in (_Unset, None): - validation_alias = alias - kwargs.update( - { - "annotation": annotation, - "alias_priority": alias_priority, - "validation_alias": validation_alias, - "serialization_alias": serialization_alias, - "strict": strict, - "json_schema_extra": current_json_schema_extra, - } - ) - kwargs["pattern"] = pattern or regex - - use_kwargs = {k: v for k, v in kwargs.items() if v is not _Unset} - - super().__init__(**use_kwargs) - - def __repr__(self) -> str: - return f"{self.__class__.__name__}({self.default})" - - -class Path(Param): # type: ignore[misc] # ty: ignore[unused-ignore-comment] - in_ = ParamTypes.path - - def __init__( - self, - default: Any = ..., - *, - default_factory: Callable[[], Any] | None = _Unset, - annotation: Any | None = None, - alias: str | None = None, - alias_priority: int | None = _Unset, - validation_alias: str | AliasPath | AliasChoices | None = None, - serialization_alias: str | None = None, - title: str | None = None, - description: str | None = None, - gt: float | None = None, - ge: float | None = None, - lt: float | None = None, - le: float | None = None, - min_length: int | None = None, - max_length: int | None = None, - pattern: str | None = None, - regex: Annotated[ - str | None, - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: str | None = None, - strict: bool | None = _Unset, - multiple_of: float | None = _Unset, - allow_inf_nan: bool | None = _Unset, - max_digits: int | None = _Unset, - decimal_places: int | None = _Unset, - examples: list[Any] | None = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: dict[str, Example] | None = None, - deprecated: deprecated | str | bool | None = None, - include_in_schema: bool = True, - json_schema_extra: dict[str, Any] | None = None, - **extra: Any, - ): - assert default is ..., "Path parameters cannot have a default value" - self.in_ = self.in_ - super().__init__( - default=default, - default_factory=default_factory, - annotation=annotation, - alias=alias, - alias_priority=alias_priority, - validation_alias=validation_alias, - serialization_alias=serialization_alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - pattern=pattern, - regex=regex, - discriminator=discriminator, - strict=strict, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - deprecated=deprecated, - example=example, - examples=examples, - openapi_examples=openapi_examples, - include_in_schema=include_in_schema, - json_schema_extra=json_schema_extra, - **extra, - ) - - -class Query(Param): # type: ignore[misc] # ty: ignore[unused-ignore-comment] - in_ = ParamTypes.query - - def __init__( - self, - default: Any = Undefined, - *, - default_factory: Callable[[], Any] | None = _Unset, - annotation: Any | None = None, - alias: str | None = None, - alias_priority: int | None = _Unset, - validation_alias: str | AliasPath | AliasChoices | None = None, - serialization_alias: str | None = None, - title: str | None = None, - description: str | None = None, - gt: float | None = None, - ge: float | None = None, - lt: float | None = None, - le: float | None = None, - min_length: int | None = None, - max_length: int | None = None, - pattern: str | None = None, - regex: Annotated[ - str | None, - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: str | None = None, - strict: bool | None = _Unset, - multiple_of: float | None = _Unset, - allow_inf_nan: bool | None = _Unset, - max_digits: int | None = _Unset, - decimal_places: int | None = _Unset, - examples: list[Any] | None = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: dict[str, Example] | None = None, - deprecated: deprecated | str | bool | None = None, - include_in_schema: bool = True, - json_schema_extra: dict[str, Any] | None = None, - **extra: Any, - ): - super().__init__( - default=default, - default_factory=default_factory, - annotation=annotation, - alias=alias, - alias_priority=alias_priority, - validation_alias=validation_alias, - serialization_alias=serialization_alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - pattern=pattern, - regex=regex, - discriminator=discriminator, - strict=strict, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - deprecated=deprecated, - example=example, - examples=examples, - openapi_examples=openapi_examples, - include_in_schema=include_in_schema, - json_schema_extra=json_schema_extra, - **extra, - ) - - -class Header(Param): # type: ignore[misc] # ty: ignore[unused-ignore-comment] - in_ = ParamTypes.header - - def __init__( - self, - default: Any = Undefined, - *, - default_factory: Callable[[], Any] | None = _Unset, - annotation: Any | None = None, - alias: str | None = None, - alias_priority: int | None = _Unset, - validation_alias: str | AliasPath | AliasChoices | None = None, - serialization_alias: str | None = None, - convert_underscores: bool = True, - title: str | None = None, - description: str | None = None, - gt: float | None = None, - ge: float | None = None, - lt: float | None = None, - le: float | None = None, - min_length: int | None = None, - max_length: int | None = None, - pattern: str | None = None, - regex: Annotated[ - str | None, - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: str | None = None, - strict: bool | None = _Unset, - multiple_of: float | None = _Unset, - allow_inf_nan: bool | None = _Unset, - max_digits: int | None = _Unset, - decimal_places: int | None = _Unset, - examples: list[Any] | None = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: dict[str, Example] | None = None, - deprecated: deprecated | str | bool | None = None, - include_in_schema: bool = True, - json_schema_extra: dict[str, Any] | None = None, - **extra: Any, - ): - self.convert_underscores = convert_underscores - super().__init__( - default=default, - default_factory=default_factory, - annotation=annotation, - alias=alias, - alias_priority=alias_priority, - validation_alias=validation_alias, - serialization_alias=serialization_alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - pattern=pattern, - regex=regex, - discriminator=discriminator, - strict=strict, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - deprecated=deprecated, - example=example, - examples=examples, - openapi_examples=openapi_examples, - include_in_schema=include_in_schema, - json_schema_extra=json_schema_extra, - **extra, - ) - - -class Cookie(Param): # type: ignore[misc] # ty: ignore[unused-ignore-comment] - in_ = ParamTypes.cookie - - def __init__( - self, - default: Any = Undefined, - *, - default_factory: Callable[[], Any] | None = _Unset, - annotation: Any | None = None, - alias: str | None = None, - alias_priority: int | None = _Unset, - validation_alias: str | AliasPath | AliasChoices | None = None, - serialization_alias: str | None = None, - title: str | None = None, - description: str | None = None, - gt: float | None = None, - ge: float | None = None, - lt: float | None = None, - le: float | None = None, - min_length: int | None = None, - max_length: int | None = None, - pattern: str | None = None, - regex: Annotated[ - str | None, - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: str | None = None, - strict: bool | None = _Unset, - multiple_of: float | None = _Unset, - allow_inf_nan: bool | None = _Unset, - max_digits: int | None = _Unset, - decimal_places: int | None = _Unset, - examples: list[Any] | None = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: dict[str, Example] | None = None, - deprecated: deprecated | str | bool | None = None, - include_in_schema: bool = True, - json_schema_extra: dict[str, Any] | None = None, - **extra: Any, - ): - super().__init__( - default=default, - default_factory=default_factory, - annotation=annotation, - alias=alias, - alias_priority=alias_priority, - validation_alias=validation_alias, - serialization_alias=serialization_alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - pattern=pattern, - regex=regex, - discriminator=discriminator, - strict=strict, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - deprecated=deprecated, - example=example, - examples=examples, - openapi_examples=openapi_examples, - include_in_schema=include_in_schema, - json_schema_extra=json_schema_extra, - **extra, - ) - - -class Body(FieldInfo): # type: ignore[misc] - def __init__( - self, - default: Any = Undefined, - *, - default_factory: Callable[[], Any] | None = _Unset, - annotation: Any | None = None, - embed: bool | None = None, - media_type: str = "application/json", - alias: str | None = None, - alias_priority: int | None = _Unset, - validation_alias: str | AliasPath | AliasChoices | None = None, - serialization_alias: str | None = None, - title: str | None = None, - description: str | None = None, - gt: float | None = None, - ge: float | None = None, - lt: float | None = None, - le: float | None = None, - min_length: int | None = None, - max_length: int | None = None, - pattern: str | None = None, - regex: Annotated[ - str | None, - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: str | None = None, - strict: bool | None = _Unset, - multiple_of: float | None = _Unset, - allow_inf_nan: bool | None = _Unset, - max_digits: int | None = _Unset, - decimal_places: int | None = _Unset, - examples: list[Any] | None = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: dict[str, Example] | None = None, - deprecated: deprecated | str | bool | None = None, - include_in_schema: bool = True, - json_schema_extra: dict[str, Any] | None = None, - **extra: Any, - ): - self.embed = embed - self.media_type = media_type - if example is not _Unset: - warnings.warn( - "`example` has been deprecated, please use `examples` instead", - category=FastAPIDeprecationWarning, - stacklevel=4, - ) - self.example = example - self.include_in_schema = include_in_schema - self.openapi_examples = openapi_examples - kwargs = dict( - default=default, - default_factory=default_factory, - alias=alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - discriminator=discriminator, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - **extra, - ) - if examples is not None: - kwargs["examples"] = examples - if regex is not None: - warnings.warn( - "`regex` has been deprecated, please use `pattern` instead", - category=FastAPIDeprecationWarning, - stacklevel=4, - ) - current_json_schema_extra = json_schema_extra or extra - kwargs["deprecated"] = deprecated - if serialization_alias in (_Unset, None) and isinstance(alias, str): - serialization_alias = alias - if validation_alias in (_Unset, None): - validation_alias = alias - kwargs.update( - { - "annotation": annotation, - "alias_priority": alias_priority, - "validation_alias": validation_alias, - "serialization_alias": serialization_alias, - "strict": strict, - "json_schema_extra": current_json_schema_extra, - } - ) - kwargs["pattern"] = pattern or regex - - use_kwargs = {k: v for k, v in kwargs.items() if v is not _Unset} - - super().__init__(**use_kwargs) - - def __repr__(self) -> str: - return f"{self.__class__.__name__}({self.default})" - - -class Form(Body): # type: ignore[misc] # ty: ignore[unused-ignore-comment] - def __init__( - self, - default: Any = Undefined, - *, - default_factory: Callable[[], Any] | None = _Unset, - annotation: Any | None = None, - media_type: str = "application/x-www-form-urlencoded", - alias: str | None = None, - alias_priority: int | None = _Unset, - validation_alias: str | AliasPath | AliasChoices | None = None, - serialization_alias: str | None = None, - title: str | None = None, - description: str | None = None, - gt: float | None = None, - ge: float | None = None, - lt: float | None = None, - le: float | None = None, - min_length: int | None = None, - max_length: int | None = None, - pattern: str | None = None, - regex: Annotated[ - str | None, - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: str | None = None, - strict: bool | None = _Unset, - multiple_of: float | None = _Unset, - allow_inf_nan: bool | None = _Unset, - max_digits: int | None = _Unset, - decimal_places: int | None = _Unset, - examples: list[Any] | None = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: dict[str, Example] | None = None, - deprecated: deprecated | str | bool | None = None, - include_in_schema: bool = True, - json_schema_extra: dict[str, Any] | None = None, - **extra: Any, - ): - super().__init__( - default=default, - default_factory=default_factory, - annotation=annotation, - media_type=media_type, - alias=alias, - alias_priority=alias_priority, - validation_alias=validation_alias, - serialization_alias=serialization_alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - pattern=pattern, - regex=regex, - discriminator=discriminator, - strict=strict, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - deprecated=deprecated, - example=example, - examples=examples, - openapi_examples=openapi_examples, - include_in_schema=include_in_schema, - json_schema_extra=json_schema_extra, - **extra, - ) - - -class File(Form): # type: ignore[misc] # ty: ignore[unused-ignore-comment] - def __init__( - self, - default: Any = Undefined, - *, - default_factory: Callable[[], Any] | None = _Unset, - annotation: Any | None = None, - media_type: str = "multipart/form-data", - alias: str | None = None, - alias_priority: int | None = _Unset, - validation_alias: str | AliasPath | AliasChoices | None = None, - serialization_alias: str | None = None, - title: str | None = None, - description: str | None = None, - gt: float | None = None, - ge: float | None = None, - lt: float | None = None, - le: float | None = None, - min_length: int | None = None, - max_length: int | None = None, - pattern: str | None = None, - regex: Annotated[ - str | None, - deprecated( - "Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead." - ), - ] = None, - discriminator: str | None = None, - strict: bool | None = _Unset, - multiple_of: float | None = _Unset, - allow_inf_nan: bool | None = _Unset, - max_digits: int | None = _Unset, - decimal_places: int | None = _Unset, - examples: list[Any] | None = None, - example: Annotated[ - Any | None, - deprecated( - "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " - "although still supported. Use examples instead." - ), - ] = _Unset, - openapi_examples: dict[str, Example] | None = None, - deprecated: deprecated | str | bool | None = None, - include_in_schema: bool = True, - json_schema_extra: dict[str, Any] | None = None, - **extra: Any, - ): - super().__init__( - default=default, - default_factory=default_factory, - annotation=annotation, - media_type=media_type, - alias=alias, - alias_priority=alias_priority, - validation_alias=validation_alias, - serialization_alias=serialization_alias, - title=title, - description=description, - gt=gt, - ge=ge, - lt=lt, - le=le, - min_length=min_length, - max_length=max_length, - pattern=pattern, - regex=regex, - discriminator=discriminator, - strict=strict, - multiple_of=multiple_of, - allow_inf_nan=allow_inf_nan, - max_digits=max_digits, - decimal_places=decimal_places, - deprecated=deprecated, - example=example, - examples=examples, - openapi_examples=openapi_examples, - include_in_schema=include_in_schema, - json_schema_extra=json_schema_extra, - **extra, - ) - - -@dataclass(frozen=True) -class Depends: - dependency: Callable[..., Any] | None = None - use_cache: bool = True - scope: Literal["function", "request"] | None = None - - -@dataclass(frozen=True) -class Security(Depends): - scopes: Sequence[str] | None = None diff --git a/notification-service/venv/Lib/site-packages/fastapi/py.typed b/notification-service/venv/Lib/site-packages/fastapi/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/fastapi/requests.py b/notification-service/venv/Lib/site-packages/fastapi/requests.py deleted file mode 100644 index d16552c..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/requests.py +++ /dev/null @@ -1,2 +0,0 @@ -from starlette.requests import HTTPConnection as HTTPConnection # noqa: F401 -from starlette.requests import Request as Request # noqa: F401 diff --git a/notification-service/venv/Lib/site-packages/fastapi/responses.py b/notification-service/venv/Lib/site-packages/fastapi/responses.py deleted file mode 100644 index 970f365..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/responses.py +++ /dev/null @@ -1,98 +0,0 @@ -import importlib -from typing import Any, Protocol, cast - -from fastapi.exceptions import FastAPIDeprecationWarning -from fastapi.sse import EventSourceResponse as EventSourceResponse # noqa -from starlette.responses import FileResponse as FileResponse # noqa -from starlette.responses import HTMLResponse as HTMLResponse # noqa -from starlette.responses import JSONResponse as JSONResponse # noqa -from starlette.responses import PlainTextResponse as PlainTextResponse # noqa -from starlette.responses import RedirectResponse as RedirectResponse # noqa -from starlette.responses import Response as Response # noqa -from starlette.responses import StreamingResponse as StreamingResponse # noqa -from typing_extensions import deprecated - - -class _UjsonModule(Protocol): - def dumps(self, __obj: Any, *, ensure_ascii: bool = ...) -> str: ... - - -class _OrjsonModule(Protocol): - OPT_NON_STR_KEYS: int - OPT_SERIALIZE_NUMPY: int - - def dumps(self, __obj: Any, *, option: int = ...) -> bytes: ... - - -try: - ujson = cast(_UjsonModule, importlib.import_module("ujson")) -except ModuleNotFoundError: # pragma: nocover - ujson = None # type: ignore # ty: ignore[unused-ignore-comment] - - -try: - orjson = cast(_OrjsonModule, importlib.import_module("orjson")) -except ModuleNotFoundError: # pragma: nocover - orjson = None # type: ignore # ty: ignore[unused-ignore-comment] - - -@deprecated( - "UJSONResponse is deprecated, FastAPI now serializes data directly to JSON " - "bytes via Pydantic when a return type or response model is set, which is " - "faster and doesn't need a custom response class. Read more in the FastAPI " - "docs: https://fastapi.tiangolo.com/advanced/custom-response/#orjson-or-response-model " - "and https://fastapi.tiangolo.com/tutorial/response-model/", - category=FastAPIDeprecationWarning, - stacklevel=2, -) -class UJSONResponse(JSONResponse): - """JSON response using the ujson library to serialize data to JSON. - - **Deprecated**: `UJSONResponse` is deprecated. FastAPI now serializes data - directly to JSON bytes via Pydantic when a return type or response model is - set, which is faster and doesn't need a custom response class. - - Read more in the - [FastAPI docs for Custom Response](https://fastapi.tiangolo.com/advanced/custom-response/#orjson-or-response-model) - and the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - - **Note**: `ujson` is not included with FastAPI and must be installed - separately, e.g. `pip install ujson`. - """ - - def render(self, content: Any) -> bytes: - assert ujson is not None, "ujson must be installed to use UJSONResponse" - return ujson.dumps(content, ensure_ascii=False).encode("utf-8") - - -@deprecated( - "ORJSONResponse is deprecated, FastAPI now serializes data directly to JSON " - "bytes via Pydantic when a return type or response model is set, which is " - "faster and doesn't need a custom response class. Read more in the FastAPI " - "docs: https://fastapi.tiangolo.com/advanced/custom-response/#orjson-or-response-model " - "and https://fastapi.tiangolo.com/tutorial/response-model/", - category=FastAPIDeprecationWarning, - stacklevel=2, -) -class ORJSONResponse(JSONResponse): - """JSON response using the orjson library to serialize data to JSON. - - **Deprecated**: `ORJSONResponse` is deprecated. FastAPI now serializes data - directly to JSON bytes via Pydantic when a return type or response model is - set, which is faster and doesn't need a custom response class. - - Read more in the - [FastAPI docs for Custom Response](https://fastapi.tiangolo.com/advanced/custom-response/#orjson-or-response-model) - and the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - - **Note**: `orjson` is not included with FastAPI and must be installed - separately, e.g. `pip install orjson`. - """ - - def render(self, content: Any) -> bytes: - assert orjson is not None, "orjson must be installed to use ORJSONResponse" - return orjson.dumps( - content, option=orjson.OPT_NON_STR_KEYS | orjson.OPT_SERIALIZE_NUMPY - ) diff --git a/notification-service/venv/Lib/site-packages/fastapi/routing.py b/notification-service/venv/Lib/site-packages/fastapi/routing.py deleted file mode 100644 index 36acb6b..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/routing.py +++ /dev/null @@ -1,4956 +0,0 @@ -import contextlib -import email.message -import functools -import inspect -import json -import types -from collections.abc import ( - AsyncIterator, - Awaitable, - Callable, - Collection, - Coroutine, - Generator, - Iterator, - Mapping, - Sequence, -) -from contextlib import ( - AbstractAsyncContextManager, - AbstractContextManager, - AsyncExitStack, - asynccontextmanager, -) -from enum import Enum, IntEnum -from typing import ( - Annotated, - Any, - TypeVar, - cast, -) - -import anyio -from annotated_doc import Doc -from anyio.abc import ObjectReceiveStream -from fastapi import params -from fastapi._compat import ( - ModelField, - Undefined, - lenient_issubclass, -) -from fastapi.datastructures import Default, DefaultPlaceholder -from fastapi.dependencies.models import Dependant -from fastapi.dependencies.utils import ( - _should_embed_body_fields, - get_body_field, - get_dependant, - get_flat_dependant, - get_parameterless_sub_dependant, - get_stream_item_type, - get_typed_return_annotation, - solve_dependencies, -) -from fastapi.encoders import jsonable_encoder -from fastapi.exceptions import ( - EndpointContext, - FastAPIError, - RequestValidationError, - ResponseValidationError, - WebSocketRequestValidationError, -) -from fastapi.sse import ( - _PING_INTERVAL, - KEEPALIVE_COMMENT, - EventSourceResponse, - ServerSentEvent, - format_sse_event, -) -from fastapi.types import DecoratedCallable, IncEx -from fastapi.utils import ( - create_model_field, - generate_unique_id, - get_value_or_default, - is_body_allowed_for_status_code, -) -from starlette import routing -from starlette._exception_handler import wrap_app_handling_exceptions -from starlette._utils import is_async_callable -from starlette.concurrency import iterate_in_threadpool, run_in_threadpool -from starlette.datastructures import FormData -from starlette.exceptions import HTTPException -from starlette.requests import Request -from starlette.responses import JSONResponse, Response, StreamingResponse -from starlette.routing import ( - BaseRoute, - Match, - compile_path, - get_name, -) -from starlette.routing import Mount as Mount # noqa -from starlette.types import AppType, ASGIApp, Lifespan, Receive, Scope, Send -from starlette.websockets import WebSocket -from typing_extensions import deprecated - - -# Copy of starlette.routing.request_response modified to include the -# dependencies' AsyncExitStack -def request_response( - func: Callable[[Request], Awaitable[Response] | Response], -) -> ASGIApp: - """ - Takes a function or coroutine `func(request) -> response`, - and returns an ASGI application. - """ - f: Callable[[Request], Awaitable[Response]] = ( - func # type: ignore[assignment] # ty: ignore[unused-ignore-comment] - if is_async_callable(func) - else functools.partial(run_in_threadpool, func) # type: ignore[call-arg] # ty: ignore[unused-ignore-comment] - ) # ty: ignore[invalid-assignment] - - async def app(scope: Scope, receive: Receive, send: Send) -> None: - request = Request(scope, receive, send) - - async def app(scope: Scope, receive: Receive, send: Send) -> None: - # Starts customization - response_awaited = False - async with AsyncExitStack() as request_stack: - scope["fastapi_inner_astack"] = request_stack - async with AsyncExitStack() as function_stack: - scope["fastapi_function_astack"] = function_stack - response = await f(request) - await response(scope, receive, send) - # Continues customization - response_awaited = True - if not response_awaited: - raise FastAPIError( - "Response not awaited. There's a high chance that the " - "application code is raising an exception and a dependency with yield " - "has a block with a bare except, or a block with except Exception, " - "and is not raising the exception again. Read more about it in the " - "docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except" - ) - - # Same as in Starlette - await wrap_app_handling_exceptions(app, request)(scope, receive, send) - - return app - - -# Copy of starlette.routing.websocket_session modified to include the -# dependencies' AsyncExitStack -def websocket_session( - func: Callable[[WebSocket], Awaitable[None]], -) -> ASGIApp: - """ - Takes a coroutine `func(session)`, and returns an ASGI application. - """ - # assert asyncio.iscoroutinefunction(func), "WebSocket endpoints must be async" - - async def app(scope: Scope, receive: Receive, send: Send) -> None: - session = WebSocket(scope, receive=receive, send=send) - - async def app(scope: Scope, receive: Receive, send: Send) -> None: - async with AsyncExitStack() as request_stack: - scope["fastapi_inner_astack"] = request_stack - async with AsyncExitStack() as function_stack: - scope["fastapi_function_astack"] = function_stack - await func(session) - - # Same as in Starlette - await wrap_app_handling_exceptions(app, session)(scope, receive, send) - - return app - - -_T = TypeVar("_T") - - -# Vendored from starlette.routing to avoid importing private symbols -class _AsyncLiftContextManager(AbstractAsyncContextManager[_T]): - """ - Wraps a synchronous context manager to make it async. - - This is vendored from Starlette to avoid importing private symbols. - """ - - def __init__(self, cm: AbstractContextManager[_T]) -> None: - self._cm = cm - - async def __aenter__(self) -> _T: - return self._cm.__enter__() - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_value: BaseException | None, - traceback: types.TracebackType | None, - ) -> bool | None: - return self._cm.__exit__(exc_type, exc_value, traceback) - - -# Vendored from starlette.routing to avoid importing private symbols -def _wrap_gen_lifespan_context( - lifespan_context: Callable[[Any], Generator[Any, Any, Any]], -) -> Callable[[Any], AbstractAsyncContextManager[Any]]: - """ - Wrap a generator-based lifespan context into an async context manager. - - This is vendored from Starlette to avoid importing private symbols. - """ - cmgr = contextlib.contextmanager(lifespan_context) - - @functools.wraps(cmgr) - def wrapper(app: Any) -> _AsyncLiftContextManager[Any]: - return _AsyncLiftContextManager(cmgr(app)) - - return wrapper - - -def _merge_lifespan_context( - original_context: Lifespan[Any], nested_context: Lifespan[Any] -) -> Lifespan[Any]: - @asynccontextmanager - async def merged_lifespan( - app: AppType, - ) -> AsyncIterator[Mapping[str, Any] | None]: - async with original_context(app) as maybe_original_state: - async with nested_context(app) as maybe_nested_state: - if maybe_nested_state is None and maybe_original_state is None: - yield None # old ASGI compatibility - else: - yield {**(maybe_nested_state or {}), **(maybe_original_state or {})} - - return merged_lifespan # type: ignore[return-value] - - -class _DefaultLifespan: - """ - Default lifespan context manager that runs on_startup and on_shutdown handlers. - - This is a copy of the Starlette _DefaultLifespan class that was removed - in Starlette. FastAPI keeps it to maintain backward compatibility with - on_startup and on_shutdown event handlers. - - Ref: https://github.com/Kludex/starlette/pull/3117 - """ - - def __init__(self, router: "APIRouter") -> None: - self._router = router - - async def __aenter__(self) -> None: - await self._router._startup() - - async def __aexit__(self, *exc_info: object) -> None: - await self._router._shutdown() - - def __call__(self: _T, app: object) -> _T: - return self - - -# Cache for endpoint context to avoid re-extracting on every request -_endpoint_context_cache: dict[int, EndpointContext] = {} - - -def _extract_endpoint_context(func: Any) -> EndpointContext: - """Extract endpoint context with caching to avoid repeated file I/O.""" - func_id = id(func) - - if func_id in _endpoint_context_cache: - return _endpoint_context_cache[func_id] - - try: - ctx: EndpointContext = {} - - if (source_file := inspect.getsourcefile(func)) is not None: - ctx["file"] = source_file - if (line_number := inspect.getsourcelines(func)[1]) is not None: - ctx["line"] = line_number - if (func_name := getattr(func, "__name__", None)) is not None: - ctx["function"] = func_name - except Exception: - ctx = EndpointContext() - - _endpoint_context_cache[func_id] = ctx - return ctx - - -async def serialize_response( - *, - field: ModelField | None = None, - response_content: Any, - include: IncEx | None = None, - exclude: IncEx | None = None, - by_alias: bool = True, - exclude_unset: bool = False, - exclude_defaults: bool = False, - exclude_none: bool = False, - is_coroutine: bool = True, - endpoint_ctx: EndpointContext | None = None, - dump_json: bool = False, -) -> Any: - if field: - if is_coroutine: - value, errors = field.validate(response_content, {}, loc=("response",)) - else: - value, errors = await run_in_threadpool( - field.validate, response_content, {}, loc=("response",) - ) - if errors: - ctx = endpoint_ctx or EndpointContext() - raise ResponseValidationError( - errors=errors, - body=response_content, - endpoint_ctx=ctx, - ) - serializer = field.serialize_json if dump_json else field.serialize - return serializer( - value, - include=include, - exclude=exclude, - by_alias=by_alias, - exclude_unset=exclude_unset, - exclude_defaults=exclude_defaults, - exclude_none=exclude_none, - ) - - else: - return jsonable_encoder(response_content) - - -async def run_endpoint_function( - *, dependant: Dependant, values: dict[str, Any], is_coroutine: bool -) -> Any: - # Only called by get_request_handler. Has been split into its own function to - # facilitate profiling endpoints, since inner functions are harder to profile. - assert dependant.call is not None, "dependant.call must be a function" - - if is_coroutine: - return await dependant.call(**values) - else: - return await run_in_threadpool(dependant.call, **values) - - -def _build_response_args( - *, status_code: int | None, solved_result: Any -) -> dict[str, Any]: - response_args: dict[str, Any] = { - "background": solved_result.background_tasks, - } - # If status_code was set, use it, otherwise use the default from the - # response class, in the case of redirect it's 307 - current_status_code = ( - status_code if status_code else solved_result.response.status_code - ) - if current_status_code is not None: - response_args["status_code"] = current_status_code - if solved_result.response.status_code: - response_args["status_code"] = solved_result.response.status_code - return response_args - - -def get_request_handler( - dependant: Dependant, - body_field: ModelField | None = None, - status_code: int | None = None, - response_class: type[Response] | DefaultPlaceholder = Default(JSONResponse), - response_field: ModelField | None = None, - response_model_include: IncEx | None = None, - response_model_exclude: IncEx | None = None, - response_model_by_alias: bool = True, - response_model_exclude_unset: bool = False, - response_model_exclude_defaults: bool = False, - response_model_exclude_none: bool = False, - dependency_overrides_provider: Any | None = None, - embed_body_fields: bool = False, - strict_content_type: bool | DefaultPlaceholder = Default(True), - stream_item_field: ModelField | None = None, - is_json_stream: bool = False, -) -> Callable[[Request], Coroutine[Any, Any, Response]]: - assert dependant.call is not None, "dependant.call must be a function" - is_coroutine = dependant.is_coroutine_callable - is_body_form = body_field and isinstance(body_field.field_info, params.Form) - if isinstance(response_class, DefaultPlaceholder): - actual_response_class: type[Response] = response_class.value - else: - actual_response_class = response_class - is_sse_stream = lenient_issubclass(actual_response_class, EventSourceResponse) - if isinstance(strict_content_type, DefaultPlaceholder): - actual_strict_content_type: bool = strict_content_type.value - else: - actual_strict_content_type = strict_content_type - - async def app(request: Request) -> Response: - response: Response | None = None - file_stack = request.scope.get("fastapi_middleware_astack") - assert isinstance(file_stack, AsyncExitStack), ( - "fastapi_middleware_astack not found in request scope" - ) - - # Extract endpoint context for error messages - endpoint_ctx = ( - _extract_endpoint_context(dependant.call) - if dependant.call - else EndpointContext() - ) - - if dependant.path: - # For mounted sub-apps, include the mount path prefix - mount_path = request.scope.get("root_path", "").rstrip("/") - endpoint_ctx["path"] = f"{request.method} {mount_path}{dependant.path}" - - # Read body and auto-close files - try: - body: Any = None - if body_field: - if is_body_form: - body = await request.form() - file_stack.push_async_callback(body.close) - else: - body_bytes = await request.body() - if body_bytes: - json_body: Any = Undefined - content_type_value = request.headers.get("content-type") - if not content_type_value: - if not actual_strict_content_type: - json_body = await request.json() - else: - message = email.message.Message() - message["content-type"] = content_type_value - if message.get_content_maintype() == "application": - subtype = message.get_content_subtype() - if subtype == "json" or subtype.endswith("+json"): - json_body = await request.json() - if json_body != Undefined: - body = json_body - else: - body = body_bytes - except json.JSONDecodeError as e: - validation_error = RequestValidationError( - [ - { - "type": "json_invalid", - "loc": ("body", e.pos), - "msg": "JSON decode error", - "input": {}, - "ctx": {"error": e.msg}, - } - ], - body=e.doc, - endpoint_ctx=endpoint_ctx, - ) - raise validation_error from e - except HTTPException: - # If a middleware raises an HTTPException, it should be raised again - raise - except Exception as e: - http_error = HTTPException( - status_code=400, detail="There was an error parsing the body" - ) - raise http_error from e - - # Solve dependencies and run path operation function, auto-closing dependencies - errors: list[Any] = [] - async_exit_stack = request.scope.get("fastapi_inner_astack") - assert isinstance(async_exit_stack, AsyncExitStack), ( - "fastapi_inner_astack not found in request scope" - ) - solved_result = await solve_dependencies( - request=request, - dependant=dependant, - body=cast(dict[str, Any] | FormData | bytes | None, body), - dependency_overrides_provider=dependency_overrides_provider, - async_exit_stack=async_exit_stack, - embed_body_fields=embed_body_fields, - ) - errors = solved_result.errors - assert dependant.call # For types - if not errors: - # Shared serializer for stream items (JSONL and SSE). - # Validates against stream_item_field when set, then - # serializes to JSON bytes. - def _serialize_data(data: Any) -> bytes: - if stream_item_field: - value, errors_ = stream_item_field.validate( - data, {}, loc=("response",) - ) - if errors_: - ctx = endpoint_ctx or EndpointContext() - raise ResponseValidationError( - errors=errors_, - body=data, - endpoint_ctx=ctx, - ) - return stream_item_field.serialize_json( - value, - include=response_model_include, - exclude=response_model_exclude, - by_alias=response_model_by_alias, - exclude_unset=response_model_exclude_unset, - exclude_defaults=response_model_exclude_defaults, - exclude_none=response_model_exclude_none, - ) - else: - data = jsonable_encoder(data) - return json.dumps(data).encode("utf-8") - - if is_sse_stream: - # Generator endpoint: stream as Server-Sent Events - gen = dependant.call(**solved_result.values) - - def _serialize_sse_item(item: Any) -> bytes: - if isinstance(item, ServerSentEvent): - # User controls the event structure. - # Serialize the data payload if present. - # For ServerSentEvent items we skip stream_item_field - # validation (the user may mix types intentionally). - if item.raw_data is not None: - data_str: str | None = item.raw_data - elif item.data is not None: - if hasattr(item.data, "model_dump_json"): - data_str = item.data.model_dump_json() - else: - data_str = json.dumps(jsonable_encoder(item.data)) - else: - data_str = None - return format_sse_event( - data_str=data_str, - event=item.event, - id=item.id, - retry=item.retry, - comment=item.comment, - ) - else: - # Plain object: validate + serialize via - # stream_item_field (if set) and wrap in data field - return format_sse_event( - data_str=_serialize_data(item).decode("utf-8") - ) - - if dependant.is_async_gen_callable: - sse_aiter: AsyncIterator[Any] = gen.__aiter__() - else: - sse_aiter = iterate_in_threadpool(gen) - - @asynccontextmanager - async def _sse_producer_cm() -> AsyncIterator[ - ObjectReceiveStream[bytes] - ]: - # Use a memory stream to decouple generator iteration - # from the keepalive timer. A producer task pulls items - # from the generator independently, so - # `anyio.fail_after` never wraps the generator's - # `__anext__` directly - avoiding CancelledError that - # would finalize the generator and also working for sync - # generators running in a thread pool. - # - # This context manager is entered on the request-scoped - # AsyncExitStack so its __aexit__ (which cancels the - # task group) is called by the exit stack after the - # streaming response completes — not by async generator - # finalization via GeneratorExit. - # Ref: https://peps.python.org/pep-0789/ - send_stream, receive_stream = anyio.create_memory_object_stream[ - bytes - ](max_buffer_size=1) - - async def _producer() -> None: - async with send_stream: - async for raw_item in sse_aiter: - await send_stream.send(_serialize_sse_item(raw_item)) - - send_keepalive, receive_keepalive = ( - anyio.create_memory_object_stream[bytes](max_buffer_size=1) - ) - - async def _keepalive_inserter() -> None: - """Read from the producer and forward to the output, - inserting keepalive comments on timeout.""" - async with send_keepalive, receive_stream: - try: - while True: - try: - with anyio.fail_after(_PING_INTERVAL): - data = await receive_stream.receive() - await send_keepalive.send(data) - except TimeoutError: - await send_keepalive.send(KEEPALIVE_COMMENT) - except anyio.EndOfStream: - pass - - async with anyio.create_task_group() as tg: - tg.start_soon(_producer) - tg.start_soon(_keepalive_inserter) - yield receive_keepalive - tg.cancel_scope.cancel() - - # Enter the SSE context manager on the request-scoped - # exit stack. The stack outlives the streaming response, - # so __aexit__ runs via proper structured teardown, not - # via GeneratorExit thrown into an async generator. - sse_receive_stream = await async_exit_stack.enter_async_context( - _sse_producer_cm() - ) - # Ensure the receive stream is closed when the exit stack - # unwinds, preventing ResourceWarning from __del__. - async_exit_stack.push_async_callback(sse_receive_stream.aclose) - - async def _sse_with_checkpoints( - stream: ObjectReceiveStream[bytes], - ) -> AsyncIterator[bytes]: - async for data in stream: - yield data - # Guarantee a checkpoint so cancellation can be - # delivered even when the producer is faster than - # the consumer and receive() never suspends. - await anyio.sleep(0) - - sse_stream_content: AsyncIterator[bytes] | Iterator[bytes] = ( - _sse_with_checkpoints(sse_receive_stream) - ) - - response = StreamingResponse( - sse_stream_content, - media_type="text/event-stream", - background=solved_result.background_tasks, - ) - response.headers["Cache-Control"] = "no-cache" - # For Nginx proxies to not buffer server sent events - response.headers["X-Accel-Buffering"] = "no" - response.headers.raw.extend(solved_result.response.headers.raw) - elif is_json_stream: - # Generator endpoint: stream as JSONL - gen = dependant.call(**solved_result.values) - - def _serialize_item(item: Any) -> bytes: - return _serialize_data(item) + b"\n" - - if dependant.is_async_gen_callable: - - async def _async_stream_jsonl() -> AsyncIterator[bytes]: - async for item in gen: - yield _serialize_item(item) - # To allow for cancellation to trigger - # Ref: https://github.com/fastapi/fastapi/issues/14680 - await anyio.sleep(0) - - jsonl_stream_content: AsyncIterator[bytes] | Iterator[bytes] = ( - _async_stream_jsonl() - ) - else: - - def _sync_stream_jsonl() -> Iterator[bytes]: - for item in gen: # ty: ignore[not-iterable] - yield _serialize_item(item) - - jsonl_stream_content = _sync_stream_jsonl() - - response = StreamingResponse( - jsonl_stream_content, - media_type="application/jsonl", - background=solved_result.background_tasks, - ) - response.headers.raw.extend(solved_result.response.headers.raw) - elif dependant.is_async_gen_callable or dependant.is_gen_callable: - # Raw streaming with explicit response_class (e.g. StreamingResponse) - gen = dependant.call(**solved_result.values) - if dependant.is_async_gen_callable: - - async def _async_stream_raw( - async_gen: AsyncIterator[Any], - ) -> AsyncIterator[Any]: - async for chunk in async_gen: - yield chunk - # To allow for cancellation to trigger - # Ref: https://github.com/fastapi/fastapi/issues/14680 - await anyio.sleep(0) - - gen = _async_stream_raw(gen) - response_args = _build_response_args( - status_code=status_code, solved_result=solved_result - ) - response = actual_response_class(content=gen, **response_args) - response.headers.raw.extend(solved_result.response.headers.raw) - else: - raw_response = await run_endpoint_function( - dependant=dependant, - values=solved_result.values, - is_coroutine=is_coroutine, - ) - if isinstance(raw_response, Response): - if raw_response.background is None: - raw_response.background = solved_result.background_tasks - response = raw_response - else: - response_args = _build_response_args( - status_code=status_code, solved_result=solved_result - ) - # Use the fast path (dump_json) when no custom response - # class was set and a response field with a TypeAdapter - # exists. Serializes directly to JSON bytes via Pydantic's - # Rust core, skipping the intermediate Python dict + - # json.dumps() step. - use_dump_json = response_field is not None and isinstance( - response_class, DefaultPlaceholder - ) - content = await serialize_response( - field=response_field, - response_content=raw_response, - include=response_model_include, - exclude=response_model_exclude, - by_alias=response_model_by_alias, - exclude_unset=response_model_exclude_unset, - exclude_defaults=response_model_exclude_defaults, - exclude_none=response_model_exclude_none, - is_coroutine=is_coroutine, - endpoint_ctx=endpoint_ctx, - dump_json=use_dump_json, - ) - if use_dump_json: - response = Response( - content=content, - media_type="application/json", - **response_args, - ) - else: - response = actual_response_class(content, **response_args) - if not is_body_allowed_for_status_code(response.status_code): - response.body = b"" - response.headers.raw.extend(solved_result.response.headers.raw) - if errors: - validation_error = RequestValidationError( - errors, body=body, endpoint_ctx=endpoint_ctx - ) - raise validation_error - - # Return response - assert response - return response - - return app - - -def get_websocket_app( - dependant: Dependant, - dependency_overrides_provider: Any | None = None, - embed_body_fields: bool = False, -) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]: - async def app(websocket: WebSocket) -> None: - endpoint_ctx = ( - _extract_endpoint_context(dependant.call) - if dependant.call - else EndpointContext() - ) - if dependant.path: - # For mounted sub-apps, include the mount path prefix - mount_path = websocket.scope.get("root_path", "").rstrip("/") - endpoint_ctx["path"] = f"WS {mount_path}{dependant.path}" - async_exit_stack = websocket.scope.get("fastapi_inner_astack") - assert isinstance(async_exit_stack, AsyncExitStack), ( - "fastapi_inner_astack not found in request scope" - ) - solved_result = await solve_dependencies( - request=websocket, - dependant=dependant, - dependency_overrides_provider=dependency_overrides_provider, - async_exit_stack=async_exit_stack, - embed_body_fields=embed_body_fields, - ) - if solved_result.errors: - raise WebSocketRequestValidationError( - solved_result.errors, - endpoint_ctx=endpoint_ctx, - ) - assert dependant.call is not None, "dependant.call must be a function" - await dependant.call(**solved_result.values) - - return app - - -class APIWebSocketRoute(routing.WebSocketRoute): - def __init__( - self, - path: str, - endpoint: Callable[..., Any], - *, - name: str | None = None, - dependencies: Sequence[params.Depends] | None = None, - dependency_overrides_provider: Any | None = None, - ) -> None: - self.path = path - self.endpoint = endpoint - self.name = get_name(endpoint) if name is None else name - self.dependencies = list(dependencies or []) - self.path_regex, self.path_format, self.param_convertors = compile_path(path) - self.dependant = get_dependant( - path=self.path_format, call=self.endpoint, scope="function" - ) - for depends in self.dependencies[::-1]: - self.dependant.dependencies.insert( - 0, - get_parameterless_sub_dependant(depends=depends, path=self.path_format), - ) - self._flat_dependant = get_flat_dependant(self.dependant) - self._embed_body_fields = _should_embed_body_fields( - self._flat_dependant.body_params - ) - self.app = websocket_session( - get_websocket_app( - dependant=self.dependant, - dependency_overrides_provider=dependency_overrides_provider, - embed_body_fields=self._embed_body_fields, - ) - ) - - def matches(self, scope: Scope) -> tuple[Match, Scope]: - match, child_scope = super().matches(scope) - if match != Match.NONE: - child_scope["route"] = self - return match, child_scope - - -class APIRoute(routing.Route): - def __init__( - self, - path: str, - endpoint: Callable[..., Any], - *, - response_model: Any = Default(None), - status_code: int | None = None, - tags: list[str | Enum] | None = None, - dependencies: Sequence[params.Depends] | None = None, - summary: str | None = None, - description: str | None = None, - response_description: str = "Successful Response", - responses: dict[int | str, dict[str, Any]] | None = None, - deprecated: bool | None = None, - name: str | None = None, - methods: set[str] | list[str] | None = None, - operation_id: str | None = None, - response_model_include: IncEx | None = None, - response_model_exclude: IncEx | None = None, - response_model_by_alias: bool = True, - response_model_exclude_unset: bool = False, - response_model_exclude_defaults: bool = False, - response_model_exclude_none: bool = False, - include_in_schema: bool = True, - response_class: type[Response] | DefaultPlaceholder = Default(JSONResponse), - dependency_overrides_provider: Any | None = None, - callbacks: list[BaseRoute] | None = None, - openapi_extra: dict[str, Any] | None = None, - generate_unique_id_function: Callable[["APIRoute"], str] - | DefaultPlaceholder = Default(generate_unique_id), - strict_content_type: bool | DefaultPlaceholder = Default(True), - ) -> None: - self.path = path - self.endpoint = endpoint - self.stream_item_type: Any | None = None - if isinstance(response_model, DefaultPlaceholder): - return_annotation = get_typed_return_annotation(endpoint) - if lenient_issubclass(return_annotation, Response): - response_model = None - else: - stream_item = get_stream_item_type(return_annotation) - if stream_item is not None: - # Extract item type for JSONL or SSE streaming when - # response_class is DefaultPlaceholder (JSONL) or - # EventSourceResponse (SSE). - # ServerSentEvent is excluded: it's a transport - # wrapper, not a data model, so it shouldn't feed - # into validation or OpenAPI schema generation. - if ( - isinstance(response_class, DefaultPlaceholder) - or lenient_issubclass(response_class, EventSourceResponse) - ) and not lenient_issubclass(stream_item, ServerSentEvent): - self.stream_item_type = stream_item - response_model = None - else: - response_model = return_annotation - self.response_model = response_model - self.summary = summary - self.response_description = response_description - self.deprecated = deprecated - self.operation_id = operation_id - self.response_model_include = response_model_include - self.response_model_exclude = response_model_exclude - self.response_model_by_alias = response_model_by_alias - self.response_model_exclude_unset = response_model_exclude_unset - self.response_model_exclude_defaults = response_model_exclude_defaults - self.response_model_exclude_none = response_model_exclude_none - self.include_in_schema = include_in_schema - self.response_class = response_class - self.dependency_overrides_provider = dependency_overrides_provider - self.callbacks = callbacks - self.openapi_extra = openapi_extra - self.generate_unique_id_function = generate_unique_id_function - self.strict_content_type = strict_content_type - self.tags = tags or [] - self.responses = responses or {} - self.name = get_name(endpoint) if name is None else name - self.path_regex, self.path_format, self.param_convertors = compile_path(path) - if methods is None: - methods = ["GET"] - self.methods: set[str] = {method.upper() for method in methods} - if isinstance(generate_unique_id_function, DefaultPlaceholder): - current_generate_unique_id: Callable[[APIRoute], str] = ( - generate_unique_id_function.value - ) - else: - current_generate_unique_id = generate_unique_id_function - self.unique_id = self.operation_id or current_generate_unique_id(self) - # normalize enums e.g. http.HTTPStatus - if isinstance(status_code, IntEnum): - status_code = int(status_code) - self.status_code = status_code - if self.response_model: - assert is_body_allowed_for_status_code(status_code), ( - f"Status code {status_code} must not have a response body" - ) - response_name = "Response_" + self.unique_id - self.response_field = create_model_field( - name=response_name, - type_=self.response_model, - mode="serialization", - ) - else: - self.response_field = None # type: ignore # ty: ignore[unused-ignore-comment] - if self.stream_item_type: - stream_item_name = "StreamItem_" + self.unique_id - self.stream_item_field: ModelField | None = create_model_field( - name=stream_item_name, - type_=self.stream_item_type, - mode="serialization", - ) - else: - self.stream_item_field = None - self.dependencies = list(dependencies or []) - self.description = description or inspect.cleandoc(self.endpoint.__doc__ or "") - # if a "form feed" character (page break) is found in the description text, - # truncate description text to the content preceding the first "form feed" - self.description = self.description.split("\f")[0].strip() - response_fields = {} - for additional_status_code, response in self.responses.items(): - assert isinstance(response, dict), "An additional response must be a dict" - model = response.get("model") - if model: - assert is_body_allowed_for_status_code(additional_status_code), ( - f"Status code {additional_status_code} must not have a response body" - ) - response_name = f"Response_{additional_status_code}_{self.unique_id}" - response_field = create_model_field( - name=response_name, type_=model, mode="serialization" - ) - response_fields[additional_status_code] = response_field - if response_fields: - self.response_fields: dict[int | str, ModelField] = response_fields - else: - self.response_fields = {} - - assert callable(endpoint), "An endpoint must be a callable" - self.dependant = get_dependant( - path=self.path_format, call=self.endpoint, scope="function" - ) - for depends in self.dependencies[::-1]: - self.dependant.dependencies.insert( - 0, - get_parameterless_sub_dependant(depends=depends, path=self.path_format), - ) - self._flat_dependant = get_flat_dependant(self.dependant) - self._embed_body_fields = _should_embed_body_fields( - self._flat_dependant.body_params - ) - self.body_field = get_body_field( - flat_dependant=self._flat_dependant, - name=self.unique_id, - embed_body_fields=self._embed_body_fields, - ) - # Detect generator endpoints that should stream as JSONL or SSE - is_generator = ( - self.dependant.is_async_gen_callable or self.dependant.is_gen_callable - ) - self.is_sse_stream = is_generator and lenient_issubclass( - response_class, EventSourceResponse - ) - self.is_json_stream = is_generator and isinstance( - response_class, DefaultPlaceholder - ) - self.app = request_response(self.get_route_handler()) - - def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]: - return get_request_handler( - dependant=self.dependant, - body_field=self.body_field, - status_code=self.status_code, - response_class=self.response_class, - response_field=self.response_field, - response_model_include=self.response_model_include, - response_model_exclude=self.response_model_exclude, - response_model_by_alias=self.response_model_by_alias, - response_model_exclude_unset=self.response_model_exclude_unset, - response_model_exclude_defaults=self.response_model_exclude_defaults, - response_model_exclude_none=self.response_model_exclude_none, - dependency_overrides_provider=self.dependency_overrides_provider, - embed_body_fields=self._embed_body_fields, - strict_content_type=self.strict_content_type, - stream_item_field=self.stream_item_field, - is_json_stream=self.is_json_stream, - ) - - def matches(self, scope: Scope) -> tuple[Match, Scope]: - match, child_scope = super().matches(scope) - if match != Match.NONE: - child_scope["route"] = self - return match, child_scope - - -class APIRouter(routing.Router): - """ - `APIRouter` class, used to group *path operations*, for example to structure - an app in multiple files. It would then be included in the `FastAPI` app, or - in another `APIRouter` (ultimately included in the app). - - Read more about it in the - [FastAPI docs for Bigger Applications - Multiple Files](https://fastapi.tiangolo.com/tutorial/bigger-applications/). - - ## Example - - ```python - from fastapi import APIRouter, FastAPI - - app = FastAPI() - router = APIRouter() - - - @router.get("/users/", tags=["users"]) - async def read_users(): - return [{"username": "Rick"}, {"username": "Morty"}] - - - app.include_router(router) - ``` - """ - - def __init__( - self, - *, - prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "", - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to all the *path operations* in this - router. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[params.Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to all the - *path operations* in this router. - - Read more about it in the - [FastAPI docs for Bigger Applications - Multiple Files](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). - """ - ), - ] = None, - default_response_class: Annotated[ - type[Response], - Doc( - """ - The default response class to be used. - - Read more in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#default-response-class). - """ - ), - ] = Default(JSONResponse), - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses to be shown in OpenAPI. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Additional Responses in OpenAPI](https://fastapi.tiangolo.com/advanced/additional-responses/). - - And in the - [FastAPI docs for Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - OpenAPI callbacks that should apply to all *path operations* in this - router. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - routes: Annotated[ - list[BaseRoute] | None, - Doc( - """ - **Note**: you probably shouldn't use this parameter, it is inherited - from Starlette and supported for compatibility. - - --- - - A list of routes to serve incoming HTTP and WebSocket requests. - """ - ), - deprecated( - """ - You normally wouldn't use this parameter with FastAPI, it is inherited - from Starlette and supported for compatibility. - - In FastAPI, you normally would use the *path operation methods*, - like `router.get()`, `router.post()`, etc. - """ - ), - ] = None, - redirect_slashes: Annotated[ - bool, - Doc( - """ - Whether to detect and redirect slashes in URLs when the client doesn't - use the same format. - """ - ), - ] = True, - default: Annotated[ - ASGIApp | None, - Doc( - """ - Default function handler for this router. Used to handle - 404 Not Found errors. - """ - ), - ] = None, - dependency_overrides_provider: Annotated[ - Any | None, - Doc( - """ - Only used internally by FastAPI to handle dependency overrides. - - You shouldn't need to use it. It normally points to the `FastAPI` app - object. - """ - ), - ] = None, - route_class: Annotated[ - type[APIRoute], - Doc( - """ - Custom route (*path operation*) class to be used by this router. - - Read more about it in the - [FastAPI docs for Custom Request and APIRoute class](https://fastapi.tiangolo.com/how-to/custom-request-and-route/#custom-apiroute-class-in-a-router). - """ - ), - ] = APIRoute, - on_startup: Annotated[ - Sequence[Callable[[], Any]] | None, - Doc( - """ - A list of startup event handler functions. - - You should instead use the `lifespan` handlers. - - Read more in the [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). - """ - ), - ] = None, - on_shutdown: Annotated[ - Sequence[Callable[[], Any]] | None, - Doc( - """ - A list of shutdown event handler functions. - - You should instead use the `lifespan` handlers. - - Read more in the - [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). - """ - ), - ] = None, - # the generic to Lifespan[AppType] is the type of the top level application - # which the router cannot know statically, so we use typing.Any - lifespan: Annotated[ - Lifespan[Any] | None, - Doc( - """ - A `Lifespan` context manager handler. This replaces `startup` and - `shutdown` functions with a single context manager. - - Read more in the - [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark all *path operations* in this router as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - include_in_schema: Annotated[ - bool, - Doc( - """ - To include (or not) all the *path operations* in this router in the - generated OpenAPI. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - generate_unique_id_function: Annotated[ - Callable[[APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - strict_content_type: Annotated[ - bool, - Doc( - """ - Enable strict checking for request Content-Type headers. - - When `True` (the default), requests with a body that do not include - a `Content-Type` header will **not** be parsed as JSON. - - This prevents potential cross-site request forgery (CSRF) attacks - that exploit the browser's ability to send requests without a - Content-Type header, bypassing CORS preflight checks. In particular - applicable for apps that need to be run locally (in localhost). - - When `False`, requests without a `Content-Type` header will have - their body parsed as JSON, which maintains compatibility with - certain clients that don't send `Content-Type` headers. - - Read more about it in the - [FastAPI docs for Strict Content-Type](https://fastapi.tiangolo.com/advanced/strict-content-type/). - """ - ), - ] = Default(True), - ) -> None: - # Determine the lifespan context to use - if lifespan is None: - # Use the default lifespan that runs on_startup/on_shutdown handlers - lifespan_context: Lifespan[Any] = _DefaultLifespan(self) - elif inspect.isasyncgenfunction(lifespan): - lifespan_context = asynccontextmanager(lifespan) - elif inspect.isgeneratorfunction(lifespan): - lifespan_context = _wrap_gen_lifespan_context(lifespan) - else: - lifespan_context = lifespan - self.lifespan_context = lifespan_context - - super().__init__( - routes=routes, - redirect_slashes=redirect_slashes, - default=default, - lifespan=lifespan_context, - ) - if prefix: - assert prefix.startswith("/"), "A path prefix must start with '/'" - assert not prefix.endswith("/"), ( - "A path prefix must not end with '/', as the routes will start with '/'" - ) - - # Handle on_startup/on_shutdown locally since Starlette removed support - # Ref: https://github.com/Kludex/starlette/pull/3117 - # TODO: deprecate this once the lifespan (or alternative) interface is improved - self.on_startup: list[Callable[[], Any]] = ( - [] if on_startup is None else list(on_startup) - ) - self.on_shutdown: list[Callable[[], Any]] = ( - [] if on_shutdown is None else list(on_shutdown) - ) - - self.prefix = prefix - self.tags: list[str | Enum] = tags or [] - self.dependencies = list(dependencies or []) - self.deprecated = deprecated - self.include_in_schema = include_in_schema - self.responses = responses or {} - self.callbacks = callbacks or [] - self.dependency_overrides_provider = dependency_overrides_provider - self.route_class = route_class - self.default_response_class = default_response_class - self.generate_unique_id_function = generate_unique_id_function - self.strict_content_type = strict_content_type - - def route( - self, - path: str, - methods: Collection[str] | None = None, - name: str | None = None, - include_in_schema: bool = True, - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - def decorator(func: DecoratedCallable) -> DecoratedCallable: - self.add_route( - path, - func, - methods=methods, - name=name, - include_in_schema=include_in_schema, - ) - return func - - return decorator - - def add_api_route( - self, - path: str, - endpoint: Callable[..., Any], - *, - response_model: Any = Default(None), - status_code: int | None = None, - tags: list[str | Enum] | None = None, - dependencies: Sequence[params.Depends] | None = None, - summary: str | None = None, - description: str | None = None, - response_description: str = "Successful Response", - responses: dict[int | str, dict[str, Any]] | None = None, - deprecated: bool | None = None, - methods: set[str] | list[str] | None = None, - operation_id: str | None = None, - response_model_include: IncEx | None = None, - response_model_exclude: IncEx | None = None, - response_model_by_alias: bool = True, - response_model_exclude_unset: bool = False, - response_model_exclude_defaults: bool = False, - response_model_exclude_none: bool = False, - include_in_schema: bool = True, - response_class: type[Response] | DefaultPlaceholder = Default(JSONResponse), - name: str | None = None, - route_class_override: type[APIRoute] | None = None, - callbacks: list[BaseRoute] | None = None, - openapi_extra: dict[str, Any] | None = None, - generate_unique_id_function: Callable[[APIRoute], str] - | DefaultPlaceholder = Default(generate_unique_id), - strict_content_type: bool | DefaultPlaceholder = Default(True), - ) -> None: - route_class = route_class_override or self.route_class - responses = responses or {} - combined_responses = {**self.responses, **responses} - current_response_class = get_value_or_default( - response_class, self.default_response_class - ) - current_tags = self.tags.copy() - if tags: - current_tags.extend(tags) - current_dependencies = self.dependencies.copy() - if dependencies: - current_dependencies.extend(dependencies) - current_callbacks = self.callbacks.copy() - if callbacks: - current_callbacks.extend(callbacks) - current_generate_unique_id = get_value_or_default( - generate_unique_id_function, self.generate_unique_id_function - ) - route = route_class( - self.prefix + path, - endpoint=endpoint, - response_model=response_model, - status_code=status_code, - tags=current_tags, - dependencies=current_dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=combined_responses, - deprecated=deprecated or self.deprecated, - methods=methods, - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema and self.include_in_schema, - response_class=current_response_class, - name=name, - dependency_overrides_provider=self.dependency_overrides_provider, - callbacks=current_callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=current_generate_unique_id, - strict_content_type=get_value_or_default( - strict_content_type, self.strict_content_type - ), - ) - self.routes.append(route) - - def api_route( - self, - path: str, - *, - response_model: Any = Default(None), - status_code: int | None = None, - tags: list[str | Enum] | None = None, - dependencies: Sequence[params.Depends] | None = None, - summary: str | None = None, - description: str | None = None, - response_description: str = "Successful Response", - responses: dict[int | str, dict[str, Any]] | None = None, - deprecated: bool | None = None, - methods: list[str] | None = None, - operation_id: str | None = None, - response_model_include: IncEx | None = None, - response_model_exclude: IncEx | None = None, - response_model_by_alias: bool = True, - response_model_exclude_unset: bool = False, - response_model_exclude_defaults: bool = False, - response_model_exclude_none: bool = False, - include_in_schema: bool = True, - response_class: type[Response] = Default(JSONResponse), - name: str | None = None, - callbacks: list[BaseRoute] | None = None, - openapi_extra: dict[str, Any] | None = None, - generate_unique_id_function: Callable[[APIRoute], str] = Default( - generate_unique_id - ), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - def decorator(func: DecoratedCallable) -> DecoratedCallable: - self.add_api_route( - path, - func, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - methods=methods, - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - return func - - return decorator - - def add_api_websocket_route( - self, - path: str, - endpoint: Callable[..., Any], - name: str | None = None, - *, - dependencies: Sequence[params.Depends] | None = None, - ) -> None: - current_dependencies = self.dependencies.copy() - if dependencies: - current_dependencies.extend(dependencies) - - route = APIWebSocketRoute( - self.prefix + path, - endpoint=endpoint, - name=name, - dependencies=current_dependencies, - dependency_overrides_provider=self.dependency_overrides_provider, - ) - self.routes.append(route) - - def websocket( - self, - path: Annotated[ - str, - Doc( - """ - WebSocket path. - """ - ), - ], - name: Annotated[ - str | None, - Doc( - """ - A name for the WebSocket. Only used internally. - """ - ), - ] = None, - *, - dependencies: Annotated[ - Sequence[params.Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be used for this - WebSocket. - - Read more about it in the - [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/). - """ - ), - ] = None, - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Decorate a WebSocket function. - - Read more about it in the - [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/). - - **Example** - - ## Example - - ```python - from fastapi import APIRouter, FastAPI, WebSocket - - app = FastAPI() - router = APIRouter() - - @router.websocket("/ws") - async def websocket_endpoint(websocket: WebSocket): - await websocket.accept() - while True: - data = await websocket.receive_text() - await websocket.send_text(f"Message text was: {data}") - - app.include_router(router) - ``` - """ - - def decorator(func: DecoratedCallable) -> DecoratedCallable: - self.add_api_websocket_route( - path, func, name=name, dependencies=dependencies - ) - return func - - return decorator - - def websocket_route( - self, path: str, name: str | None = None - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - def decorator(func: DecoratedCallable) -> DecoratedCallable: - self.add_websocket_route(path, func, name=name) - return func - - return decorator - - def include_router( - self, - router: Annotated["APIRouter", Doc("The `APIRouter` to include.")], - *, - prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "", - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to all the *path operations* in this - router. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[params.Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to all the - *path operations* in this router. - - Read more about it in the - [FastAPI docs for Bigger Applications - Multiple Files](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). - """ - ), - ] = None, - default_response_class: Annotated[ - type[Response], - Doc( - """ - The default response class to be used. - - Read more in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#default-response-class). - """ - ), - ] = Default(JSONResponse), - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses to be shown in OpenAPI. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Additional Responses in OpenAPI](https://fastapi.tiangolo.com/advanced/additional-responses/). - - And in the - [FastAPI docs for Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - OpenAPI callbacks that should apply to all *path operations* in this - router. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark all *path operations* in this router as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include (or not) all the *path operations* in this router in the - generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = True, - generate_unique_id_function: Annotated[ - Callable[[APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> None: - """ - Include another `APIRouter` in the same current `APIRouter`. - - Read more about it in the - [FastAPI docs for Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/). - - ## Example - - ```python - from fastapi import APIRouter, FastAPI - - app = FastAPI() - internal_router = APIRouter() - users_router = APIRouter() - - @users_router.get("/users/") - def read_users(): - return [{"name": "Rick"}, {"name": "Morty"}] - - internal_router.include_router(users_router) - app.include_router(internal_router) - ``` - """ - assert self is not router, ( - "Cannot include the same APIRouter instance into itself. " - "Did you mean to include a different router?" - ) - if prefix: - assert prefix.startswith("/"), "A path prefix must start with '/'" - assert not prefix.endswith("/"), ( - "A path prefix must not end with '/', as the routes will start with '/'" - ) - else: - for r in router.routes: - path = getattr(r, "path") # noqa: B009 - name = getattr(r, "name", "unknown") - if path is not None and not path: - raise FastAPIError( - f"Prefix and path cannot be both empty (path operation: {name})" - ) - if responses is None: - responses = {} - for route in router.routes: - if isinstance(route, APIRoute): - combined_responses = {**responses, **route.responses} - use_response_class = get_value_or_default( - route.response_class, - router.default_response_class, - default_response_class, - self.default_response_class, - ) - current_tags = [] - if tags: - current_tags.extend(tags) - if route.tags: - current_tags.extend(route.tags) - current_dependencies: list[params.Depends] = [] - if dependencies: - current_dependencies.extend(dependencies) - if route.dependencies: - current_dependencies.extend(route.dependencies) - current_callbacks = [] - if callbacks: - current_callbacks.extend(callbacks) - if route.callbacks: - current_callbacks.extend(route.callbacks) - current_generate_unique_id = get_value_or_default( - route.generate_unique_id_function, - router.generate_unique_id_function, - generate_unique_id_function, - self.generate_unique_id_function, - ) - self.add_api_route( - prefix + route.path, - route.endpoint, - response_model=route.response_model, - status_code=route.status_code, - tags=current_tags, - dependencies=current_dependencies, - summary=route.summary, - description=route.description, - response_description=route.response_description, - responses=combined_responses, - deprecated=route.deprecated or deprecated or self.deprecated, - methods=route.methods, - operation_id=route.operation_id, - response_model_include=route.response_model_include, - response_model_exclude=route.response_model_exclude, - response_model_by_alias=route.response_model_by_alias, - response_model_exclude_unset=route.response_model_exclude_unset, - response_model_exclude_defaults=route.response_model_exclude_defaults, - response_model_exclude_none=route.response_model_exclude_none, - include_in_schema=route.include_in_schema - and self.include_in_schema - and include_in_schema, - response_class=use_response_class, - name=route.name, - route_class_override=type(route), - callbacks=current_callbacks, - openapi_extra=route.openapi_extra, - generate_unique_id_function=current_generate_unique_id, - strict_content_type=get_value_or_default( - route.strict_content_type, - router.strict_content_type, - self.strict_content_type, - ), - ) - elif isinstance(route, routing.Route): - methods = list(route.methods or []) - self.add_route( - prefix + route.path, - route.endpoint, - methods=methods, - include_in_schema=route.include_in_schema, - name=route.name, - ) - elif isinstance(route, APIWebSocketRoute): - current_dependencies = [] - if dependencies: - current_dependencies.extend(dependencies) - if route.dependencies: - current_dependencies.extend(route.dependencies) - self.add_api_websocket_route( - prefix + route.path, - route.endpoint, - dependencies=current_dependencies, - name=route.name, - ) - elif isinstance(route, routing.WebSocketRoute): - self.add_websocket_route( - prefix + route.path, route.endpoint, name=route.name - ) - for handler in router.on_startup: - self.add_event_handler("startup", handler) - for handler in router.on_shutdown: - self.add_event_handler("shutdown", handler) - self.lifespan_context = _merge_lifespan_context( - self.lifespan_context, - router.lifespan_context, - ) - - def get( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[params.Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP GET operation. - - ## Example - - ```python - from fastapi import APIRouter, FastAPI - - app = FastAPI() - router = APIRouter() - - @router.get("/items/") - def read_items(): - return [{"name": "Empanada"}, {"name": "Arepa"}] - - app.include_router(router) - ``` - """ - return self.api_route( - path=path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - methods=["GET"], - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def put( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[params.Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP PUT operation. - - ## Example - - ```python - from fastapi import APIRouter, FastAPI - from pydantic import BaseModel - - class Item(BaseModel): - name: str - description: str | None = None - - app = FastAPI() - router = APIRouter() - - @router.put("/items/{item_id}") - def replace_item(item_id: str, item: Item): - return {"message": "Item replaced", "id": item_id} - - app.include_router(router) - ``` - """ - return self.api_route( - path=path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - methods=["PUT"], - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def post( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[params.Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP POST operation. - - ## Example - - ```python - from fastapi import APIRouter, FastAPI - from pydantic import BaseModel - - class Item(BaseModel): - name: str - description: str | None = None - - app = FastAPI() - router = APIRouter() - - @router.post("/items/") - def create_item(item: Item): - return {"message": "Item created"} - - app.include_router(router) - ``` - """ - return self.api_route( - path=path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - methods=["POST"], - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def delete( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[params.Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP DELETE operation. - - ## Example - - ```python - from fastapi import APIRouter, FastAPI - - app = FastAPI() - router = APIRouter() - - @router.delete("/items/{item_id}") - def delete_item(item_id: str): - return {"message": "Item deleted"} - - app.include_router(router) - ``` - """ - return self.api_route( - path=path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - methods=["DELETE"], - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def options( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[params.Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP OPTIONS operation. - - ## Example - - ```python - from fastapi import APIRouter, FastAPI - - app = FastAPI() - router = APIRouter() - - @router.options("/items/") - def get_item_options(): - return {"additions": ["Aji", "Guacamole"]} - - app.include_router(router) - ``` - """ - return self.api_route( - path=path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - methods=["OPTIONS"], - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def head( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[params.Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP HEAD operation. - - ## Example - - ```python - from fastapi import APIRouter, FastAPI - from pydantic import BaseModel - - class Item(BaseModel): - name: str - description: str | None = None - - app = FastAPI() - router = APIRouter() - - @router.head("/items/", status_code=204) - def get_items_headers(response: Response): - response.headers["X-Cat-Dog"] = "Alone in the world" - - app.include_router(router) - ``` - """ - return self.api_route( - path=path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - methods=["HEAD"], - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def patch( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[params.Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP PATCH operation. - - ## Example - - ```python - from fastapi import APIRouter, FastAPI - from pydantic import BaseModel - - class Item(BaseModel): - name: str - description: str | None = None - - app = FastAPI() - router = APIRouter() - - @router.patch("/items/") - def update_item(item: Item): - return {"message": "Item updated in place"} - - app.include_router(router) - ``` - """ - return self.api_route( - path=path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - methods=["PATCH"], - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - def trace( - self, - path: Annotated[ - str, - Doc( - """ - The URL path to be used for this *path operation*. - - For example, in `http://example.com/items`, the path is `/items`. - """ - ), - ], - *, - response_model: Annotated[ - Any, - Doc( - """ - The type to use for the response. - - It could be any valid Pydantic *field* type. So, it doesn't have to - be a Pydantic model, it could be other things, like a `list`, `dict`, - etc. - - It will be used for: - - * Documentation: the generated OpenAPI (and the UI at `/docs`) will - show it as the response (JSON Schema). - * Serialization: you could return an arbitrary object and the - `response_model` would be used to serialize that object into the - corresponding JSON. - * Filtering: the JSON sent to the client will only contain the data - (fields) defined in the `response_model`. If you returned an object - that contains an attribute `password` but the `response_model` does - not include that field, the JSON sent to the client would not have - that `password`. - * Validation: whatever you return will be serialized with the - `response_model`, converting any data as necessary to generate the - corresponding JSON. But if the data in the object returned is not - valid, that would mean a violation of the contract with the client, - so it's an error from the API developer. So, FastAPI will raise an - error and return a 500 error code (Internal Server Error). - - Read more about it in the - [FastAPI docs for Response Model](https://fastapi.tiangolo.com/tutorial/response-model/). - """ - ), - ] = Default(None), - status_code: Annotated[ - int | None, - Doc( - """ - The default status code to be used for the response. - - You could override the status code by returning a response directly. - - Read more about it in the - [FastAPI docs for Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). - """ - ), - ] = None, - tags: Annotated[ - list[str | Enum] | None, - Doc( - """ - A list of tags to be applied to the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags). - """ - ), - ] = None, - dependencies: Annotated[ - Sequence[params.Depends] | None, - Doc( - """ - A list of dependencies (using `Depends()`) to be applied to the - *path operation*. - - Read more about it in the - [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/). - """ - ), - ] = None, - summary: Annotated[ - str | None, - Doc( - """ - A summary for the *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - A description for the *path operation*. - - If not provided, it will be extracted automatically from the docstring - of the *path operation function*. - - It can contain Markdown. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). - """ - ), - ] = None, - response_description: Annotated[ - str, - Doc( - """ - The description for the default response. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = "Successful Response", - responses: Annotated[ - dict[int | str, dict[str, Any]] | None, - Doc( - """ - Additional responses that could be returned by this *path operation*. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - deprecated: Annotated[ - bool | None, - Doc( - """ - Mark this *path operation* as deprecated. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - operation_id: Annotated[ - str | None, - Doc( - """ - Custom operation ID to be used by this *path operation*. - - By default, it is generated automatically. - - If you provide a custom operation ID, you need to make sure it is - unique for the whole API. - - You can customize the - operation ID generation with the parameter - `generate_unique_id_function` in the `FastAPI` class. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = None, - response_model_include: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to include only certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_exclude: Annotated[ - IncEx | None, - Doc( - """ - Configuration passed to Pydantic to exclude certain fields in the - response data. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = None, - response_model_by_alias: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response model - should be serialized by alias when an alias is used. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_include-and-response_model_exclude). - """ - ), - ] = True, - response_model_exclude_unset: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that were not set and - have their default values. This is different from - `response_model_exclude_defaults` in that if the fields are set, - they will be included in the response, even if the value is the same - as the default. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_defaults: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data - should have all the fields, including the ones that have the same value - as the default. This is different from `response_model_exclude_unset` - in that if the fields are set but contain the same default values, - they will be excluded from the response. - - When `True`, default values are omitted from the response. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). - """ - ), - ] = False, - response_model_exclude_none: Annotated[ - bool, - Doc( - """ - Configuration passed to Pydantic to define if the response data should - exclude fields set to `None`. - - This is much simpler (less smart) than `response_model_exclude_unset` - and `response_model_exclude_defaults`. You probably want to use one of - those two instead of this one, as those allow returning `None` values - when it makes sense. - - Read more about it in the - [FastAPI docs for Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/#response_model_exclude_none). - """ - ), - ] = False, - include_in_schema: Annotated[ - bool, - Doc( - """ - Include this *path operation* in the generated OpenAPI schema. - - This affects the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). - """ - ), - ] = True, - response_class: Annotated[ - type[Response], - Doc( - """ - Response class to be used for this *path operation*. - - This will not be used if you return a response directly. - - Read more about it in the - [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#redirectresponse). - """ - ), - ] = Default(JSONResponse), - name: Annotated[ - str | None, - Doc( - """ - Name for this *path operation*. Only used internally. - """ - ), - ] = None, - callbacks: Annotated[ - list[BaseRoute] | None, - Doc( - """ - List of *path operations* that will be used as OpenAPI callbacks. - - This is only for OpenAPI documentation, the callbacks won't be used - directly. - - It will be added to the generated OpenAPI (e.g. visible at `/docs`). - - Read more about it in the - [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). - """ - ), - ] = None, - openapi_extra: Annotated[ - dict[str, Any] | None, - Doc( - """ - Extra metadata to be included in the OpenAPI schema for this *path - operation*. - - Read more about it in the - [FastAPI docs for Path Operation Advanced Configuration](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#custom-openapi-path-operation-schema). - """ - ), - ] = None, - generate_unique_id_function: Annotated[ - Callable[[APIRoute], str], - Doc( - """ - Customize the function used to generate unique IDs for the *path - operations* shown in the generated OpenAPI. - - This is particularly useful when automatically generating clients or - SDKs for your API. - - Read more about it in the - [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). - """ - ), - ] = Default(generate_unique_id), - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add a *path operation* using an HTTP TRACE operation. - - ## Example - - ```python - from fastapi import APIRouter, FastAPI - from pydantic import BaseModel - - class Item(BaseModel): - name: str - description: str | None = None - - app = FastAPI() - router = APIRouter() - - @router.trace("/items/{item_id}") - def trace_item(item_id: str): - return None - - app.include_router(router) - ``` - """ - return self.api_route( - path=path, - response_model=response_model, - status_code=status_code, - tags=tags, - dependencies=dependencies, - summary=summary, - description=description, - response_description=response_description, - responses=responses, - deprecated=deprecated, - methods=["TRACE"], - operation_id=operation_id, - response_model_include=response_model_include, - response_model_exclude=response_model_exclude, - response_model_by_alias=response_model_by_alias, - response_model_exclude_unset=response_model_exclude_unset, - response_model_exclude_defaults=response_model_exclude_defaults, - response_model_exclude_none=response_model_exclude_none, - include_in_schema=include_in_schema, - response_class=response_class, - name=name, - callbacks=callbacks, - openapi_extra=openapi_extra, - generate_unique_id_function=generate_unique_id_function, - ) - - # TODO: remove this once the lifespan (or alternative) interface is improved - async def _startup(self) -> None: - """ - Run any `.on_startup` event handlers. - - This method is kept for backward compatibility after Starlette removed - support for on_startup/on_shutdown handlers. - - Ref: https://github.com/Kludex/starlette/pull/3117 - """ - for handler in self.on_startup: - if is_async_callable(handler): - await handler() - else: - handler() - - # TODO: remove this once the lifespan (or alternative) interface is improved - async def _shutdown(self) -> None: - """ - Run any `.on_shutdown` event handlers. - - This method is kept for backward compatibility after Starlette removed - support for on_startup/on_shutdown handlers. - - Ref: https://github.com/Kludex/starlette/pull/3117 - """ - for handler in self.on_shutdown: - if is_async_callable(handler): - await handler() - else: - handler() - - # TODO: remove this once the lifespan (or alternative) interface is improved - def add_event_handler( - self, - event_type: str, - func: Callable[[], Any], - ) -> None: - """ - Add an event handler function for startup or shutdown. - - This method is kept for backward compatibility after Starlette removed - support for on_startup/on_shutdown handlers. - - Ref: https://github.com/Kludex/starlette/pull/3117 - """ - assert event_type in ("startup", "shutdown") - if event_type == "startup": - self.on_startup.append(func) - else: - self.on_shutdown.append(func) - - @deprecated( - """ - on_event is deprecated, use lifespan event handlers instead. - - Read more about it in the - [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/). - """ - ) - def on_event( - self, - event_type: Annotated[ - str, - Doc( - """ - The type of event. `startup` or `shutdown`. - """ - ), - ], - ) -> Callable[[DecoratedCallable], DecoratedCallable]: - """ - Add an event handler for the router. - - `on_event` is deprecated, use `lifespan` event handlers instead. - - Read more about it in the - [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/#alternative-events-deprecated). - """ - - def decorator(func: DecoratedCallable) -> DecoratedCallable: - self.add_event_handler(event_type, func) - return func - - return decorator diff --git a/notification-service/venv/Lib/site-packages/fastapi/security/__init__.py b/notification-service/venv/Lib/site-packages/fastapi/security/__init__.py deleted file mode 100644 index 3aa6bf2..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/security/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -from .api_key import APIKeyCookie as APIKeyCookie -from .api_key import APIKeyHeader as APIKeyHeader -from .api_key import APIKeyQuery as APIKeyQuery -from .http import HTTPAuthorizationCredentials as HTTPAuthorizationCredentials -from .http import HTTPBasic as HTTPBasic -from .http import HTTPBasicCredentials as HTTPBasicCredentials -from .http import HTTPBearer as HTTPBearer -from .http import HTTPDigest as HTTPDigest -from .oauth2 import OAuth2 as OAuth2 -from .oauth2 import OAuth2AuthorizationCodeBearer as OAuth2AuthorizationCodeBearer -from .oauth2 import OAuth2PasswordBearer as OAuth2PasswordBearer -from .oauth2 import OAuth2PasswordRequestForm as OAuth2PasswordRequestForm -from .oauth2 import OAuth2PasswordRequestFormStrict as OAuth2PasswordRequestFormStrict -from .oauth2 import SecurityScopes as SecurityScopes -from .open_id_connect_url import OpenIdConnect as OpenIdConnect diff --git a/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index d55151d..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/api_key.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/api_key.cpython-312.pyc deleted file mode 100644 index 9617c86..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/api_key.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/base.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/base.cpython-312.pyc deleted file mode 100644 index 2a633a6..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/base.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/http.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/http.cpython-312.pyc deleted file mode 100644 index 9cc5a68..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/http.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/oauth2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/oauth2.cpython-312.pyc deleted file mode 100644 index f405314..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/oauth2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/open_id_connect_url.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/open_id_connect_url.cpython-312.pyc deleted file mode 100644 index 8f0c2f2..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/open_id_connect_url.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/utils.cpython-312.pyc b/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/utils.cpython-312.pyc deleted file mode 100644 index ddde4f8..0000000 Binary files a/notification-service/venv/Lib/site-packages/fastapi/security/__pycache__/utils.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/fastapi/security/api_key.py b/notification-service/venv/Lib/site-packages/fastapi/security/api_key.py deleted file mode 100644 index 83a4585..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/security/api_key.py +++ /dev/null @@ -1,320 +0,0 @@ -from typing import Annotated - -from annotated_doc import Doc -from fastapi.openapi.models import APIKey, APIKeyIn -from fastapi.security.base import SecurityBase -from starlette.exceptions import HTTPException -from starlette.requests import Request -from starlette.status import HTTP_401_UNAUTHORIZED - - -class APIKeyBase(SecurityBase): - model: APIKey - - def __init__( - self, - location: APIKeyIn, - name: str, - description: str | None, - scheme_name: str | None, - auto_error: bool, - ): - self.auto_error = auto_error - - self.model: APIKey = APIKey( - **{"in": location}, # ty: ignore[invalid-argument-type] - name=name, - description=description, - ) - self.scheme_name = scheme_name or self.__class__.__name__ - - def make_not_authenticated_error(self) -> HTTPException: - """ - The WWW-Authenticate header is not standardized for API Key authentication but - the HTTP specification requires that an error of 401 "Unauthorized" must - include a WWW-Authenticate header. - - Ref: https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized - - For this, this method sends a custom challenge `APIKey`. - """ - return HTTPException( - status_code=HTTP_401_UNAUTHORIZED, - detail="Not authenticated", - headers={"WWW-Authenticate": "APIKey"}, - ) - - def check_api_key(self, api_key: str | None) -> str | None: - if not api_key: - if self.auto_error: - raise self.make_not_authenticated_error() - return None - return api_key - - -class APIKeyQuery(APIKeyBase): - """ - API key authentication using a query parameter. - - This defines the name of the query parameter that should be provided in the request - with the API key and integrates that into the OpenAPI documentation. It extracts - the key value sent in the query parameter automatically and provides it as the - dependency result. But it doesn't define how to send that API key to the client. - - ## Usage - - Create an instance object and use that object as the dependency in `Depends()`. - - The dependency result will be a string containing the key value. - - ## Example - - ```python - from fastapi import Depends, FastAPI - from fastapi.security import APIKeyQuery - - app = FastAPI() - - query_scheme = APIKeyQuery(name="api_key") - - - @app.get("/items/") - async def read_items(api_key: str = Depends(query_scheme)): - return {"api_key": api_key} - ``` - """ - - def __init__( - self, - *, - name: Annotated[ - str, - Doc("Query parameter name."), - ], - scheme_name: Annotated[ - str | None, - Doc( - """ - Security scheme name. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Security scheme description. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - auto_error: Annotated[ - bool, - Doc( - """ - By default, if the query parameter is not provided, `APIKeyQuery` will - automatically cancel the request and send the client an error. - - If `auto_error` is set to `False`, when the query parameter is not - available, instead of erroring out, the dependency result will be - `None`. - - This is useful when you want to have optional authentication. - - It is also useful when you want to have authentication that can be - provided in one of multiple optional ways (for example, in a query - parameter or in an HTTP Bearer token). - """ - ), - ] = True, - ): - super().__init__( - location=APIKeyIn.query, - name=name, - scheme_name=scheme_name, - description=description, - auto_error=auto_error, - ) - - async def __call__(self, request: Request) -> str | None: - api_key = request.query_params.get(self.model.name) - return self.check_api_key(api_key) - - -class APIKeyHeader(APIKeyBase): - """ - API key authentication using a header. - - This defines the name of the header that should be provided in the request with - the API key and integrates that into the OpenAPI documentation. It extracts - the key value sent in the header automatically and provides it as the dependency - result. But it doesn't define how to send that key to the client. - - ## Usage - - Create an instance object and use that object as the dependency in `Depends()`. - - The dependency result will be a string containing the key value. - - ## Example - - ```python - from fastapi import Depends, FastAPI - from fastapi.security import APIKeyHeader - - app = FastAPI() - - header_scheme = APIKeyHeader(name="x-key") - - - @app.get("/items/") - async def read_items(key: str = Depends(header_scheme)): - return {"key": key} - ``` - """ - - def __init__( - self, - *, - name: Annotated[str, Doc("Header name.")], - scheme_name: Annotated[ - str | None, - Doc( - """ - Security scheme name. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Security scheme description. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - auto_error: Annotated[ - bool, - Doc( - """ - By default, if the header is not provided, `APIKeyHeader` will - automatically cancel the request and send the client an error. - - If `auto_error` is set to `False`, when the header is not available, - instead of erroring out, the dependency result will be `None`. - - This is useful when you want to have optional authentication. - - It is also useful when you want to have authentication that can be - provided in one of multiple optional ways (for example, in a header or - in an HTTP Bearer token). - """ - ), - ] = True, - ): - super().__init__( - location=APIKeyIn.header, - name=name, - scheme_name=scheme_name, - description=description, - auto_error=auto_error, - ) - - async def __call__(self, request: Request) -> str | None: - api_key = request.headers.get(self.model.name) - return self.check_api_key(api_key) - - -class APIKeyCookie(APIKeyBase): - """ - API key authentication using a cookie. - - This defines the name of the cookie that should be provided in the request with - the API key and integrates that into the OpenAPI documentation. It extracts - the key value sent in the cookie automatically and provides it as the dependency - result. But it doesn't define how to set that cookie. - - ## Usage - - Create an instance object and use that object as the dependency in `Depends()`. - - The dependency result will be a string containing the key value. - - ## Example - - ```python - from fastapi import Depends, FastAPI - from fastapi.security import APIKeyCookie - - app = FastAPI() - - cookie_scheme = APIKeyCookie(name="session") - - - @app.get("/items/") - async def read_items(session: str = Depends(cookie_scheme)): - return {"session": session} - ``` - """ - - def __init__( - self, - *, - name: Annotated[str, Doc("Cookie name.")], - scheme_name: Annotated[ - str | None, - Doc( - """ - Security scheme name. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Security scheme description. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - auto_error: Annotated[ - bool, - Doc( - """ - By default, if the cookie is not provided, `APIKeyCookie` will - automatically cancel the request and send the client an error. - - If `auto_error` is set to `False`, when the cookie is not available, - instead of erroring out, the dependency result will be `None`. - - This is useful when you want to have optional authentication. - - It is also useful when you want to have authentication that can be - provided in one of multiple optional ways (for example, in a cookie or - in an HTTP Bearer token). - """ - ), - ] = True, - ): - super().__init__( - location=APIKeyIn.cookie, - name=name, - scheme_name=scheme_name, - description=description, - auto_error=auto_error, - ) - - async def __call__(self, request: Request) -> str | None: - api_key = request.cookies.get(self.model.name) - return self.check_api_key(api_key) diff --git a/notification-service/venv/Lib/site-packages/fastapi/security/base.py b/notification-service/venv/Lib/site-packages/fastapi/security/base.py deleted file mode 100644 index c43555d..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/security/base.py +++ /dev/null @@ -1,6 +0,0 @@ -from fastapi.openapi.models import SecurityBase as SecurityBaseModel - - -class SecurityBase: - model: SecurityBaseModel - scheme_name: str diff --git a/notification-service/venv/Lib/site-packages/fastapi/security/http.py b/notification-service/venv/Lib/site-packages/fastapi/security/http.py deleted file mode 100644 index a32948e..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/security/http.py +++ /dev/null @@ -1,417 +0,0 @@ -import binascii -from base64 import b64decode -from typing import Annotated - -from annotated_doc import Doc -from fastapi.exceptions import HTTPException -from fastapi.openapi.models import HTTPBase as HTTPBaseModel -from fastapi.openapi.models import HTTPBearer as HTTPBearerModel -from fastapi.security.base import SecurityBase -from fastapi.security.utils import get_authorization_scheme_param -from pydantic import BaseModel -from starlette.requests import Request -from starlette.status import HTTP_401_UNAUTHORIZED - - -class HTTPBasicCredentials(BaseModel): - """ - The HTTP Basic credentials given as the result of using `HTTPBasic` in a - dependency. - - Read more about it in the - [FastAPI docs for HTTP Basic Auth](https://fastapi.tiangolo.com/advanced/security/http-basic-auth/). - """ - - username: Annotated[str, Doc("The HTTP Basic username.")] - password: Annotated[str, Doc("The HTTP Basic password.")] - - -class HTTPAuthorizationCredentials(BaseModel): - """ - The HTTP authorization credentials in the result of using `HTTPBearer` or - `HTTPDigest` in a dependency. - - The HTTP authorization header value is split by the first space. - - The first part is the `scheme`, the second part is the `credentials`. - - For example, in an HTTP Bearer token scheme, the client will send a header - like: - - ``` - Authorization: Bearer deadbeef12346 - ``` - - In this case: - - * `scheme` will have the value `"Bearer"` - * `credentials` will have the value `"deadbeef12346"` - """ - - scheme: Annotated[ - str, - Doc( - """ - The HTTP authorization scheme extracted from the header value. - """ - ), - ] - credentials: Annotated[ - str, - Doc( - """ - The HTTP authorization credentials extracted from the header value. - """ - ), - ] - - -class HTTPBase(SecurityBase): - model: HTTPBaseModel - - def __init__( - self, - *, - scheme: str, - scheme_name: str | None = None, - description: str | None = None, - auto_error: bool = True, - ): - self.model = HTTPBaseModel(scheme=scheme, description=description) - self.scheme_name = scheme_name or self.__class__.__name__ - self.auto_error = auto_error - - def make_authenticate_headers(self) -> dict[str, str]: - return {"WWW-Authenticate": f"{self.model.scheme.title()}"} - - def make_not_authenticated_error(self) -> HTTPException: - return HTTPException( - status_code=HTTP_401_UNAUTHORIZED, - detail="Not authenticated", - headers=self.make_authenticate_headers(), - ) - - async def __call__(self, request: Request) -> HTTPAuthorizationCredentials | None: - authorization = request.headers.get("Authorization") - scheme, credentials = get_authorization_scheme_param(authorization) - if not (authorization and scheme and credentials): - if self.auto_error: - raise self.make_not_authenticated_error() - else: - return None - return HTTPAuthorizationCredentials(scheme=scheme, credentials=credentials) - - -class HTTPBasic(HTTPBase): - """ - HTTP Basic authentication. - - Ref: https://datatracker.ietf.org/doc/html/rfc7617 - - ## Usage - - Create an instance object and use that object as the dependency in `Depends()`. - - The dependency result will be an `HTTPBasicCredentials` object containing the - `username` and the `password`. - - Read more about it in the - [FastAPI docs for HTTP Basic Auth](https://fastapi.tiangolo.com/advanced/security/http-basic-auth/). - - ## Example - - ```python - from typing import Annotated - - from fastapi import Depends, FastAPI - from fastapi.security import HTTPBasic, HTTPBasicCredentials - - app = FastAPI() - - security = HTTPBasic() - - - @app.get("/users/me") - def read_current_user(credentials: Annotated[HTTPBasicCredentials, Depends(security)]): - return {"username": credentials.username, "password": credentials.password} - ``` - """ - - def __init__( - self, - *, - scheme_name: Annotated[ - str | None, - Doc( - """ - Security scheme name. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - realm: Annotated[ - str | None, - Doc( - """ - HTTP Basic authentication realm. - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Security scheme description. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - auto_error: Annotated[ - bool, - Doc( - """ - By default, if the HTTP Basic authentication is not provided (a - header), `HTTPBasic` will automatically cancel the request and send the - client an error. - - If `auto_error` is set to `False`, when the HTTP Basic authentication - is not available, instead of erroring out, the dependency result will - be `None`. - - This is useful when you want to have optional authentication. - - It is also useful when you want to have authentication that can be - provided in one of multiple optional ways (for example, in HTTP Basic - authentication or in an HTTP Bearer token). - """ - ), - ] = True, - ): - self.model = HTTPBaseModel(scheme="basic", description=description) - self.scheme_name = scheme_name or self.__class__.__name__ - self.realm = realm - self.auto_error = auto_error - - def make_authenticate_headers(self) -> dict[str, str]: - if self.realm: - return {"WWW-Authenticate": f'Basic realm="{self.realm}"'} - return {"WWW-Authenticate": "Basic"} - - async def __call__( # type: ignore - self, request: Request - ) -> HTTPBasicCredentials | None: - authorization = request.headers.get("Authorization") - scheme, param = get_authorization_scheme_param(authorization) - if not authorization or scheme.lower() != "basic": - if self.auto_error: - raise self.make_not_authenticated_error() - else: - return None - try: - data = b64decode(param).decode("ascii") - except (ValueError, UnicodeDecodeError, binascii.Error) as e: - raise self.make_not_authenticated_error() from e - username, separator, password = data.partition(":") - if not separator: - raise self.make_not_authenticated_error() - return HTTPBasicCredentials(username=username, password=password) - - -class HTTPBearer(HTTPBase): - """ - HTTP Bearer token authentication. - - ## Usage - - Create an instance object and use that object as the dependency in `Depends()`. - - The dependency result will be an `HTTPAuthorizationCredentials` object containing - the `scheme` and the `credentials`. - - ## Example - - ```python - from typing import Annotated - - from fastapi import Depends, FastAPI - from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer - - app = FastAPI() - - security = HTTPBearer() - - - @app.get("/users/me") - def read_current_user( - credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)] - ): - return {"scheme": credentials.scheme, "credentials": credentials.credentials} - ``` - """ - - def __init__( - self, - *, - bearerFormat: Annotated[str | None, Doc("Bearer token format.")] = None, - scheme_name: Annotated[ - str | None, - Doc( - """ - Security scheme name. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Security scheme description. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - auto_error: Annotated[ - bool, - Doc( - """ - By default, if the HTTP Bearer token is not provided (in an - `Authorization` header), `HTTPBearer` will automatically cancel the - request and send the client an error. - - If `auto_error` is set to `False`, when the HTTP Bearer token - is not available, instead of erroring out, the dependency result will - be `None`. - - This is useful when you want to have optional authentication. - - It is also useful when you want to have authentication that can be - provided in one of multiple optional ways (for example, in an HTTP - Bearer token or in a cookie). - """ - ), - ] = True, - ): - self.model = HTTPBearerModel(bearerFormat=bearerFormat, description=description) - self.scheme_name = scheme_name or self.__class__.__name__ - self.auto_error = auto_error - - async def __call__(self, request: Request) -> HTTPAuthorizationCredentials | None: - authorization = request.headers.get("Authorization") - scheme, credentials = get_authorization_scheme_param(authorization) - if not (authorization and scheme and credentials): - if self.auto_error: - raise self.make_not_authenticated_error() - else: - return None - if scheme.lower() != "bearer": - if self.auto_error: - raise self.make_not_authenticated_error() - else: - return None - return HTTPAuthorizationCredentials(scheme=scheme, credentials=credentials) - - -class HTTPDigest(HTTPBase): - """ - HTTP Digest authentication. - - **Warning**: this is only a stub to connect the components with OpenAPI in FastAPI, - but it doesn't implement the full Digest scheme, you would need to subclass it - and implement it in your code. - - Ref: https://datatracker.ietf.org/doc/html/rfc7616 - - ## Usage - - Create an instance object and use that object as the dependency in `Depends()`. - - The dependency result will be an `HTTPAuthorizationCredentials` object containing - the `scheme` and the `credentials`. - - ## Example - - ```python - from typing import Annotated - - from fastapi import Depends, FastAPI - from fastapi.security import HTTPAuthorizationCredentials, HTTPDigest - - app = FastAPI() - - security = HTTPDigest() - - - @app.get("/users/me") - def read_current_user( - credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)] - ): - return {"scheme": credentials.scheme, "credentials": credentials.credentials} - ``` - """ - - def __init__( - self, - *, - scheme_name: Annotated[ - str | None, - Doc( - """ - Security scheme name. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Security scheme description. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - auto_error: Annotated[ - bool, - Doc( - """ - By default, if the HTTP Digest is not provided, `HTTPDigest` will - automatically cancel the request and send the client an error. - - If `auto_error` is set to `False`, when the HTTP Digest is not - available, instead of erroring out, the dependency result will - be `None`. - - This is useful when you want to have optional authentication. - - It is also useful when you want to have authentication that can be - provided in one of multiple optional ways (for example, in HTTP - Digest or in a cookie). - """ - ), - ] = True, - ): - self.model = HTTPBaseModel(scheme="digest", description=description) - self.scheme_name = scheme_name or self.__class__.__name__ - self.auto_error = auto_error - - async def __call__(self, request: Request) -> HTTPAuthorizationCredentials | None: - authorization = request.headers.get("Authorization") - scheme, credentials = get_authorization_scheme_param(authorization) - if not (authorization and scheme and credentials): - if self.auto_error: - raise self.make_not_authenticated_error() - else: - return None - if scheme.lower() != "digest": - if self.auto_error: - raise self.make_not_authenticated_error() - else: - return None - return HTTPAuthorizationCredentials(scheme=scheme, credentials=credentials) diff --git a/notification-service/venv/Lib/site-packages/fastapi/security/oauth2.py b/notification-service/venv/Lib/site-packages/fastapi/security/oauth2.py deleted file mode 100644 index 3fd9e41..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/security/oauth2.py +++ /dev/null @@ -1,693 +0,0 @@ -from typing import Annotated, Any, cast - -from annotated_doc import Doc -from fastapi.exceptions import HTTPException -from fastapi.openapi.models import OAuth2 as OAuth2Model -from fastapi.openapi.models import OAuthFlows as OAuthFlowsModel -from fastapi.param_functions import Form -from fastapi.security.base import SecurityBase -from fastapi.security.utils import get_authorization_scheme_param -from starlette.requests import Request -from starlette.status import HTTP_401_UNAUTHORIZED - - -class OAuth2PasswordRequestForm: - """ - This is a dependency class to collect the `username` and `password` as form data - for an OAuth2 password flow. - - The OAuth2 specification dictates that for a password flow the data should be - collected using form data (instead of JSON) and that it should have the specific - fields `username` and `password`. - - All the initialization parameters are extracted from the request. - - Read more about it in the - [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). - - ## Example - - ```python - from typing import Annotated - - from fastapi import Depends, FastAPI - from fastapi.security import OAuth2PasswordRequestForm - - app = FastAPI() - - - @app.post("/login") - def login(form_data: Annotated[OAuth2PasswordRequestForm, Depends()]): - data = {} - data["scopes"] = [] - for scope in form_data.scopes: - data["scopes"].append(scope) - if form_data.client_id: - data["client_id"] = form_data.client_id - if form_data.client_secret: - data["client_secret"] = form_data.client_secret - return data - ``` - - Note that for OAuth2 the scope `items:read` is a single scope in an opaque string. - You could have custom internal logic to separate it by colon characters (`:`) or - similar, and get the two parts `items` and `read`. Many applications do that to - group and organize permissions, you could do it as well in your application, just - know that it is application specific, it's not part of the specification. - """ - - def __init__( - self, - *, - grant_type: Annotated[ - str | None, - Form(pattern="^password$"), - Doc( - """ - The OAuth2 spec says it is required and MUST be the fixed string - "password". Nevertheless, this dependency class is permissive and - allows not passing it. If you want to enforce it, use instead the - `OAuth2PasswordRequestFormStrict` dependency. - - Read more about it in the - [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). - """ - ), - ] = None, - username: Annotated[ - str, - Form(), - Doc( - """ - `username` string. The OAuth2 spec requires the exact field name - `username`. - - Read more about it in the - [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). - """ - ), - ], - password: Annotated[ - str, - Form(json_schema_extra={"format": "password"}), - Doc( - """ - `password` string. The OAuth2 spec requires the exact field name - `password`. - - Read more about it in the - [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). - """ - ), - ], - scope: Annotated[ - str, - Form(), - Doc( - """ - A single string with actually several scopes separated by spaces. Each - scope is also a string. - - For example, a single string with: - - ```python - "items:read items:write users:read profile openid" - ```` - - would represent the scopes: - - * `items:read` - * `items:write` - * `users:read` - * `profile` - * `openid` - - Read more about it in the - [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). - """ - ), - ] = "", - client_id: Annotated[ - str | None, - Form(), - Doc( - """ - If there's a `client_id`, it can be sent as part of the form fields. - But the OAuth2 specification recommends sending the `client_id` and - `client_secret` (if any) using HTTP Basic auth. - """ - ), - ] = None, - client_secret: Annotated[ - str | None, - Form(json_schema_extra={"format": "password"}), - Doc( - """ - If there's a `client_secret` (and a `client_id`), they can be sent - as part of the form fields. But the OAuth2 specification recommends - sending the `client_id` and `client_secret` (if any) using HTTP Basic - auth. - """ - ), - ] = None, - ): - self.grant_type = grant_type - self.username = username - self.password = password - self.scopes = scope.split() - self.client_id = client_id - self.client_secret = client_secret - - -class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm): - """ - This is a dependency class to collect the `username` and `password` as form data - for an OAuth2 password flow. - - The OAuth2 specification dictates that for a password flow the data should be - collected using form data (instead of JSON) and that it should have the specific - fields `username` and `password`. - - All the initialization parameters are extracted from the request. - - The only difference between `OAuth2PasswordRequestFormStrict` and - `OAuth2PasswordRequestForm` is that `OAuth2PasswordRequestFormStrict` requires the - client to send the form field `grant_type` with the value `"password"`, which - is required in the OAuth2 specification (it seems that for no particular reason), - while for `OAuth2PasswordRequestForm` `grant_type` is optional. - - Read more about it in the - [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). - - ## Example - - ```python - from typing import Annotated - - from fastapi import Depends, FastAPI - from fastapi.security import OAuth2PasswordRequestForm - - app = FastAPI() - - - @app.post("/login") - def login(form_data: Annotated[OAuth2PasswordRequestFormStrict, Depends()]): - data = {} - data["scopes"] = [] - for scope in form_data.scopes: - data["scopes"].append(scope) - if form_data.client_id: - data["client_id"] = form_data.client_id - if form_data.client_secret: - data["client_secret"] = form_data.client_secret - return data - ``` - - Note that for OAuth2 the scope `items:read` is a single scope in an opaque string. - You could have custom internal logic to separate it by colon characters (`:`) or - similar, and get the two parts `items` and `read`. Many applications do that to - group and organize permissions, you could do it as well in your application, just - know that it is application specific, it's not part of the specification. - - - grant_type: the OAuth2 spec says it is required and MUST be the fixed string "password". - This dependency is strict about it. If you want to be permissive, use instead the - OAuth2PasswordRequestForm dependency class. - username: username string. The OAuth2 spec requires the exact field name "username". - password: password string. The OAuth2 spec requires the exact field name "password". - scope: Optional string. Several scopes (each one a string) separated by spaces. E.g. - "items:read items:write users:read profile openid" - client_id: optional string. OAuth2 recommends sending the client_id and client_secret (if any) - using HTTP Basic auth, as: client_id:client_secret - client_secret: optional string. OAuth2 recommends sending the client_id and client_secret (if any) - using HTTP Basic auth, as: client_id:client_secret - """ - - def __init__( - self, - grant_type: Annotated[ - str, - Form(pattern="^password$"), - Doc( - """ - The OAuth2 spec says it is required and MUST be the fixed string - "password". This dependency is strict about it. If you want to be - permissive, use instead the `OAuth2PasswordRequestForm` dependency - class. - - Read more about it in the - [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). - """ - ), - ], - username: Annotated[ - str, - Form(), - Doc( - """ - `username` string. The OAuth2 spec requires the exact field name - `username`. - - Read more about it in the - [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). - """ - ), - ], - password: Annotated[ - str, - Form(), - Doc( - """ - `password` string. The OAuth2 spec requires the exact field name - `password`. - - Read more about it in the - [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). - """ - ), - ], - scope: Annotated[ - str, - Form(), - Doc( - """ - A single string with actually several scopes separated by spaces. Each - scope is also a string. - - For example, a single string with: - - ```python - "items:read items:write users:read profile openid" - ```` - - would represent the scopes: - - * `items:read` - * `items:write` - * `users:read` - * `profile` - * `openid` - - Read more about it in the - [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). - """ - ), - ] = "", - client_id: Annotated[ - str | None, - Form(), - Doc( - """ - If there's a `client_id`, it can be sent as part of the form fields. - But the OAuth2 specification recommends sending the `client_id` and - `client_secret` (if any) using HTTP Basic auth. - """ - ), - ] = None, - client_secret: Annotated[ - str | None, - Form(), - Doc( - """ - If there's a `client_secret` (and a `client_id`), they can be sent - as part of the form fields. But the OAuth2 specification recommends - sending the `client_id` and `client_secret` (if any) using HTTP Basic - auth. - """ - ), - ] = None, - ): - super().__init__( - grant_type=grant_type, - username=username, - password=password, - scope=scope, - client_id=client_id, - client_secret=client_secret, - ) - - -class OAuth2(SecurityBase): - """ - This is the base class for OAuth2 authentication, an instance of it would be used - as a dependency. All other OAuth2 classes inherit from it and customize it for - each OAuth2 flow. - - You normally would not create a new class inheriting from it but use one of the - existing subclasses, and maybe compose them if you want to support multiple flows. - - Read more about it in the - [FastAPI docs for Security](https://fastapi.tiangolo.com/tutorial/security/). - """ - - def __init__( - self, - *, - flows: Annotated[ - OAuthFlowsModel | dict[str, dict[str, Any]], - Doc( - """ - The dictionary of OAuth2 flows. - """ - ), - ] = OAuthFlowsModel(), - scheme_name: Annotated[ - str | None, - Doc( - """ - Security scheme name. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Security scheme description. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - auto_error: Annotated[ - bool, - Doc( - """ - By default, if no HTTP Authorization header is provided, required for - OAuth2 authentication, it will automatically cancel the request and - send the client an error. - - If `auto_error` is set to `False`, when the HTTP Authorization header - is not available, instead of erroring out, the dependency result will - be `None`. - - This is useful when you want to have optional authentication. - - It is also useful when you want to have authentication that can be - provided in one of multiple optional ways (for example, with OAuth2 - or in a cookie). - """ - ), - ] = True, - ): - self.model = OAuth2Model( - flows=cast(OAuthFlowsModel, flows), description=description - ) - self.scheme_name = scheme_name or self.__class__.__name__ - self.auto_error = auto_error - - def make_not_authenticated_error(self) -> HTTPException: - """ - The OAuth 2 specification doesn't define the challenge that should be used, - because a `Bearer` token is not really the only option to authenticate. - - But declaring any other authentication challenge would be application-specific - as it's not defined in the specification. - - For practical reasons, this method uses the `Bearer` challenge by default, as - it's probably the most common one. - - If you are implementing an OAuth2 authentication scheme other than the provided - ones in FastAPI (based on bearer tokens), you might want to override this. - - Ref: https://datatracker.ietf.org/doc/html/rfc6749 - """ - return HTTPException( - status_code=HTTP_401_UNAUTHORIZED, - detail="Not authenticated", - headers={"WWW-Authenticate": "Bearer"}, - ) - - async def __call__(self, request: Request) -> str | None: - authorization = request.headers.get("Authorization") - if not authorization: - if self.auto_error: - raise self.make_not_authenticated_error() - else: - return None - return authorization - - -class OAuth2PasswordBearer(OAuth2): - """ - OAuth2 flow for authentication using a bearer token obtained with a password. - An instance of it would be used as a dependency. - - Read more about it in the - [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). - """ - - def __init__( - self, - tokenUrl: Annotated[ - str, - Doc( - """ - The URL to obtain the OAuth2 token. This would be the *path operation* - that has `OAuth2PasswordRequestForm` as a dependency. - - Read more about it in the - [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). - """ - ), - ], - scheme_name: Annotated[ - str | None, - Doc( - """ - Security scheme name. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - scopes: Annotated[ - dict[str, str] | None, - Doc( - """ - The OAuth2 scopes that would be required by the *path operations* that - use this dependency. - - Read more about it in the - [FastAPI docs for Simple OAuth2 with Password and Bearer](https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Security scheme description. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - auto_error: Annotated[ - bool, - Doc( - """ - By default, if no HTTP Authorization header is provided, required for - OAuth2 authentication, it will automatically cancel the request and - send the client an error. - - If `auto_error` is set to `False`, when the HTTP Authorization header - is not available, instead of erroring out, the dependency result will - be `None`. - - This is useful when you want to have optional authentication. - - It is also useful when you want to have authentication that can be - provided in one of multiple optional ways (for example, with OAuth2 - or in a cookie). - """ - ), - ] = True, - refreshUrl: Annotated[ - str | None, - Doc( - """ - The URL to refresh the token and obtain a new one. - """ - ), - ] = None, - ): - if not scopes: - scopes = {} - flows = OAuthFlowsModel( - password=cast( - Any, - { - "tokenUrl": tokenUrl, - "refreshUrl": refreshUrl, - "scopes": scopes, - }, - ) - ) - super().__init__( - flows=flows, - scheme_name=scheme_name, - description=description, - auto_error=auto_error, - ) - - async def __call__(self, request: Request) -> str | None: - authorization = request.headers.get("Authorization") - scheme, param = get_authorization_scheme_param(authorization) - if not authorization or scheme.lower() != "bearer": - if self.auto_error: - raise self.make_not_authenticated_error() - else: - return None - return param - - -class OAuth2AuthorizationCodeBearer(OAuth2): - """ - OAuth2 flow for authentication using a bearer token obtained with an OAuth2 code - flow. An instance of it would be used as a dependency. - """ - - def __init__( - self, - authorizationUrl: str, - tokenUrl: Annotated[ - str, - Doc( - """ - The URL to obtain the OAuth2 token. - """ - ), - ], - refreshUrl: Annotated[ - str | None, - Doc( - """ - The URL to refresh the token and obtain a new one. - """ - ), - ] = None, - scheme_name: Annotated[ - str | None, - Doc( - """ - Security scheme name. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - scopes: Annotated[ - dict[str, str] | None, - Doc( - """ - The OAuth2 scopes that would be required by the *path operations* that - use this dependency. - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Security scheme description. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - auto_error: Annotated[ - bool, - Doc( - """ - By default, if no HTTP Authorization header is provided, required for - OAuth2 authentication, it will automatically cancel the request and - send the client an error. - - If `auto_error` is set to `False`, when the HTTP Authorization header - is not available, instead of erroring out, the dependency result will - be `None`. - - This is useful when you want to have optional authentication. - - It is also useful when you want to have authentication that can be - provided in one of multiple optional ways (for example, with OAuth2 - or in a cookie). - """ - ), - ] = True, - ): - if not scopes: - scopes = {} - flows = OAuthFlowsModel( - authorizationCode=cast( - Any, - { - "authorizationUrl": authorizationUrl, - "tokenUrl": tokenUrl, - "refreshUrl": refreshUrl, - "scopes": scopes, - }, - ) - ) - super().__init__( - flows=flows, - scheme_name=scheme_name, - description=description, - auto_error=auto_error, - ) - - async def __call__(self, request: Request) -> str | None: - authorization = request.headers.get("Authorization") - scheme, param = get_authorization_scheme_param(authorization) - if not authorization or scheme.lower() != "bearer": - if self.auto_error: - raise self.make_not_authenticated_error() - else: - return None # pragma: nocover - return param - - -class SecurityScopes: - """ - This is a special class that you can define in a parameter in a dependency to - obtain the OAuth2 scopes required by all the dependencies in the same chain. - - This way, multiple dependencies can have different scopes, even when used in the - same *path operation*. And with this, you can access all the scopes required in - all those dependencies in a single place. - - Read more about it in the - [FastAPI docs for OAuth2 scopes](https://fastapi.tiangolo.com/advanced/security/oauth2-scopes/). - """ - - def __init__( - self, - scopes: Annotated[ - list[str] | None, - Doc( - """ - This will be filled by FastAPI. - """ - ), - ] = None, - ): - self.scopes: Annotated[ - list[str], - Doc( - """ - The list of all the scopes required by dependencies. - """ - ), - ] = scopes or [] - self.scope_str: Annotated[ - str, - Doc( - """ - All the scopes required by all the dependencies in a single string - separated by spaces, as defined in the OAuth2 specification. - """ - ), - ] = " ".join(self.scopes) diff --git a/notification-service/venv/Lib/site-packages/fastapi/security/open_id_connect_url.py b/notification-service/venv/Lib/site-packages/fastapi/security/open_id_connect_url.py deleted file mode 100644 index 125a819..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/security/open_id_connect_url.py +++ /dev/null @@ -1,94 +0,0 @@ -from typing import Annotated - -from annotated_doc import Doc -from fastapi.openapi.models import OpenIdConnect as OpenIdConnectModel -from fastapi.security.base import SecurityBase -from starlette.exceptions import HTTPException -from starlette.requests import Request -from starlette.status import HTTP_401_UNAUTHORIZED - - -class OpenIdConnect(SecurityBase): - """ - OpenID Connect authentication class. An instance of it would be used as a - dependency. - - **Warning**: this is only a stub to connect the components with OpenAPI in FastAPI, - but it doesn't implement the full OpenIdConnect scheme, for example, it doesn't use - the OpenIDConnect URL. You would need to subclass it and implement it in your - code. - """ - - def __init__( - self, - *, - openIdConnectUrl: Annotated[ - str, - Doc( - """ - The OpenID Connect URL. - """ - ), - ], - scheme_name: Annotated[ - str | None, - Doc( - """ - Security scheme name. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - description: Annotated[ - str | None, - Doc( - """ - Security scheme description. - - It will be included in the generated OpenAPI (e.g. visible at `/docs`). - """ - ), - ] = None, - auto_error: Annotated[ - bool, - Doc( - """ - By default, if no HTTP Authorization header is provided, required for - OpenID Connect authentication, it will automatically cancel the request - and send the client an error. - - If `auto_error` is set to `False`, when the HTTP Authorization header - is not available, instead of erroring out, the dependency result will - be `None`. - - This is useful when you want to have optional authentication. - - It is also useful when you want to have authentication that can be - provided in one of multiple optional ways (for example, with OpenID - Connect or in a cookie). - """ - ), - ] = True, - ): - self.model = OpenIdConnectModel( - openIdConnectUrl=openIdConnectUrl, description=description - ) - self.scheme_name = scheme_name or self.__class__.__name__ - self.auto_error = auto_error - - def make_not_authenticated_error(self) -> HTTPException: - return HTTPException( - status_code=HTTP_401_UNAUTHORIZED, - detail="Not authenticated", - headers={"WWW-Authenticate": "Bearer"}, - ) - - async def __call__(self, request: Request) -> str | None: - authorization = request.headers.get("Authorization") - if not authorization: - if self.auto_error: - raise self.make_not_authenticated_error() - else: - return None - return authorization diff --git a/notification-service/venv/Lib/site-packages/fastapi/security/utils.py b/notification-service/venv/Lib/site-packages/fastapi/security/utils.py deleted file mode 100644 index 8ee66fd..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/security/utils.py +++ /dev/null @@ -1,7 +0,0 @@ -def get_authorization_scheme_param( - authorization_header_value: str | None, -) -> tuple[str, str]: - if not authorization_header_value: - return "", "" - scheme, _, param = authorization_header_value.partition(" ") - return scheme, param.strip() diff --git a/notification-service/venv/Lib/site-packages/fastapi/sse.py b/notification-service/venv/Lib/site-packages/fastapi/sse.py deleted file mode 100644 index 901d824..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/sse.py +++ /dev/null @@ -1,222 +0,0 @@ -from typing import Annotated, Any - -from annotated_doc import Doc -from pydantic import AfterValidator, BaseModel, Field, model_validator -from starlette.responses import StreamingResponse - -# Canonical SSE event schema matching the OpenAPI 3.2 spec -# (Section 4.14.4 "Special Considerations for Server-Sent Events") -_SSE_EVENT_SCHEMA: dict[str, Any] = { - "type": "object", - "properties": { - "data": {"type": "string"}, - "event": {"type": "string"}, - "id": {"type": "string"}, - "retry": {"type": "integer", "minimum": 0}, - }, -} - - -class EventSourceResponse(StreamingResponse): - """Streaming response with `text/event-stream` media type. - - Use as `response_class=EventSourceResponse` on a *path operation* that uses `yield` - to enable Server Sent Events (SSE) responses. - - Works with **any HTTP method** (`GET`, `POST`, etc.), which makes it compatible - with protocols like MCP that stream SSE over `POST`. - - The actual encoding logic lives in the FastAPI routing layer. This class - serves mainly as a marker and sets the correct `Content-Type`. - """ - - media_type = "text/event-stream" - - -def _check_id_no_null(v: str | None) -> str | None: - if v is not None and "\0" in v: - raise ValueError("SSE 'id' must not contain null characters") - return v - - -class ServerSentEvent(BaseModel): - """Represents a single Server-Sent Event. - - When `yield`ed from a *path operation function* that uses - `response_class=EventSourceResponse`, each `ServerSentEvent` is encoded - into the [SSE wire format](https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream) - (`text/event-stream`). - - If you yield a plain object (dict, Pydantic model, etc.) instead, it is - automatically JSON-encoded and sent as the `data:` field. - - All `data` values **including plain strings** are JSON-serialized. - - For example, `data="hello"` produces `data: "hello"` on the wire (with - quotes). - """ - - data: Annotated[ - Any, - Doc( - """ - The event payload. - - Can be any JSON-serializable value: a Pydantic model, dict, list, - string, number, etc. It is **always** serialized to JSON: strings - are quoted (`"hello"` becomes `data: "hello"` on the wire). - - Mutually exclusive with `raw_data`. - """ - ), - ] = None - raw_data: Annotated[ - str | None, - Doc( - """ - Raw string to send as the `data:` field **without** JSON encoding. - - Use this when you need to send pre-formatted text, HTML fragments, - CSV lines, or any non-JSON payload. The string is placed directly - into the `data:` field as-is. - - Mutually exclusive with `data`. - """ - ), - ] = None - event: Annotated[ - str | None, - Doc( - """ - Optional event type name. - - Maps to `addEventListener(event, ...)` on the browser. When omitted, - the browser dispatches on the generic `message` event. - """ - ), - ] = None - id: Annotated[ - str | None, - AfterValidator(_check_id_no_null), - Doc( - """ - Optional event ID. - - The browser sends this value back as the `Last-Event-ID` header on - automatic reconnection. **Must not contain null (`\\0`) characters.** - """ - ), - ] = None - retry: Annotated[ - int | None, - Field(ge=0), - Doc( - """ - Optional reconnection time in **milliseconds**. - - Tells the browser how long to wait before reconnecting after the - connection is lost. Must be a non-negative integer. - """ - ), - ] = None - comment: Annotated[ - str | None, - Doc( - """ - Optional comment line(s). - - Comment lines start with `:` in the SSE wire format and are ignored by - `EventSource` clients. Useful for keep-alive pings to prevent - proxy/load-balancer timeouts. - """ - ), - ] = None - - @model_validator(mode="after") - def _check_data_exclusive(self) -> "ServerSentEvent": - if self.data is not None and self.raw_data is not None: - raise ValueError( - "Cannot set both 'data' and 'raw_data' on the same " - "ServerSentEvent. Use 'data' for JSON-serialized payloads " - "or 'raw_data' for pre-formatted strings." - ) - return self - - -def format_sse_event( - *, - data_str: Annotated[ - str | None, - Doc( - """ - Pre-serialized data string to use as the `data:` field. - """ - ), - ] = None, - event: Annotated[ - str | None, - Doc( - """ - Optional event type name (`event:` field). - """ - ), - ] = None, - id: Annotated[ - str | None, - Doc( - """ - Optional event ID (`id:` field). - """ - ), - ] = None, - retry: Annotated[ - int | None, - Doc( - """ - Optional reconnection time in milliseconds (`retry:` field). - """ - ), - ] = None, - comment: Annotated[ - str | None, - Doc( - """ - Optional comment line(s) (`:` prefix). - """ - ), - ] = None, -) -> bytes: - """Build SSE wire-format bytes from **pre-serialized** data. - - The result always ends with `\n\n` (the event terminator). - """ - lines: list[str] = [] - - if comment is not None: - for line in comment.splitlines(): - lines.append(f": {line}") - - if event is not None: - lines.append(f"event: {event}") - - if data_str is not None: - for line in data_str.splitlines(): - lines.append(f"data: {line}") - - if id is not None: - lines.append(f"id: {id}") - - if retry is not None: - lines.append(f"retry: {retry}") - - lines.append("") - lines.append("") - return "\n".join(lines).encode("utf-8") - - -# Keep-alive comment, per the SSE spec recommendation -KEEPALIVE_COMMENT = b": ping\n\n" - -# Seconds between keep-alive pings when a generator is idle. -# Private but importable so tests can monkeypatch it. -_PING_INTERVAL: float = 15.0 diff --git a/notification-service/venv/Lib/site-packages/fastapi/staticfiles.py b/notification-service/venv/Lib/site-packages/fastapi/staticfiles.py deleted file mode 100644 index 299015d..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/staticfiles.py +++ /dev/null @@ -1 +0,0 @@ -from starlette.staticfiles import StaticFiles as StaticFiles # noqa diff --git a/notification-service/venv/Lib/site-packages/fastapi/templating.py b/notification-service/venv/Lib/site-packages/fastapi/templating.py deleted file mode 100644 index 0cb8684..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/templating.py +++ /dev/null @@ -1 +0,0 @@ -from starlette.templating import Jinja2Templates as Jinja2Templates # noqa diff --git a/notification-service/venv/Lib/site-packages/fastapi/testclient.py b/notification-service/venv/Lib/site-packages/fastapi/testclient.py deleted file mode 100644 index 4012406..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/testclient.py +++ /dev/null @@ -1 +0,0 @@ -from starlette.testclient import TestClient as TestClient # noqa diff --git a/notification-service/venv/Lib/site-packages/fastapi/types.py b/notification-service/venv/Lib/site-packages/fastapi/types.py deleted file mode 100644 index 1fb86e1..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/types.py +++ /dev/null @@ -1,12 +0,0 @@ -import types -from collections.abc import Callable -from enum import Enum -from typing import Any, TypeVar, Union - -from pydantic import BaseModel -from pydantic.main import IncEx as IncEx - -DecoratedCallable = TypeVar("DecoratedCallable", bound=Callable[..., Any]) -UnionType = getattr(types, "UnionType", Union) -ModelNameMap = dict[type[BaseModel] | type[Enum], str] -DependencyCacheKey = tuple[Callable[..., Any] | None, tuple[str, ...], str] diff --git a/notification-service/venv/Lib/site-packages/fastapi/utils.py b/notification-service/venv/Lib/site-packages/fastapi/utils.py deleted file mode 100644 index 12eaa2b..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/utils.py +++ /dev/null @@ -1,136 +0,0 @@ -import re -import warnings -from typing import ( - TYPE_CHECKING, - Any, - Literal, -) - -import fastapi -from fastapi._compat import ( - ModelField, - PydanticSchemaGenerationError, - Undefined, - annotation_is_pydantic_v1, -) -from fastapi.datastructures import DefaultPlaceholder, DefaultType -from fastapi.exceptions import FastAPIDeprecationWarning, PydanticV1NotSupportedError -from pydantic.fields import FieldInfo - -from ._compat import v2 - -if TYPE_CHECKING: # pragma: nocover - from .routing import APIRoute - - -def is_body_allowed_for_status_code(status_code: int | str | None) -> bool: - if status_code is None: - return True - # Ref: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#patterned-fields-1 - if status_code in { - "default", - "1XX", - "2XX", - "3XX", - "4XX", - "5XX", - }: - return True - current_status_code = int(status_code) - return not (current_status_code < 200 or current_status_code in {204, 205, 304}) - - -def get_path_param_names(path: str) -> set[str]: - return set(re.findall("{(.*?)}", path)) - - -_invalid_args_message = ( - "Invalid args for response field! Hint: " - "check that {type_} is a valid Pydantic field type. " - "If you are using a return type annotation that is not a valid Pydantic " - "field (e.g. Union[Response, dict, None]) you can disable generating the " - "response model from the type annotation with the path operation decorator " - "parameter response_model=None. Read more: " - "https://fastapi.tiangolo.com/tutorial/response-model/" -) - - -def create_model_field( - name: str, - type_: Any, - default: Any | None = Undefined, - field_info: FieldInfo | None = None, - alias: str | None = None, - mode: Literal["validation", "serialization"] = "validation", -) -> ModelField: - if annotation_is_pydantic_v1(type_): - raise PydanticV1NotSupportedError( - "pydantic.v1 models are no longer supported by FastAPI." - f" Please update the response model {type_!r}." - ) - field_info = field_info or FieldInfo(annotation=type_, default=default, alias=alias) - try: - return v2.ModelField(mode=mode, name=name, field_info=field_info) - except PydanticSchemaGenerationError: - raise fastapi.exceptions.FastAPIError( - _invalid_args_message.format(type_=type_) - ) from None - - -def generate_operation_id_for_path( - *, name: str, path: str, method: str -) -> str: # pragma: nocover - warnings.warn( - message="fastapi.utils.generate_operation_id_for_path() was deprecated, " - "it is not used internally, and will be removed soon", - category=FastAPIDeprecationWarning, - stacklevel=2, - ) - operation_id = f"{name}{path}" - operation_id = re.sub(r"\W", "_", operation_id) - operation_id = f"{operation_id}_{method.lower()}" - return operation_id - - -def generate_unique_id(route: "APIRoute") -> str: - operation_id = f"{route.name}{route.path_format}" - operation_id = re.sub(r"\W", "_", operation_id) - assert route.methods - operation_id = f"{operation_id}_{list(route.methods)[0].lower()}" - return operation_id - - -def deep_dict_update(main_dict: dict[Any, Any], update_dict: dict[Any, Any]) -> None: - for key, value in update_dict.items(): - if ( - key in main_dict - and isinstance(main_dict[key], dict) - and isinstance(value, dict) - ): - deep_dict_update(main_dict[key], value) - elif ( - key in main_dict - and isinstance(main_dict[key], list) - and isinstance(update_dict[key], list) - ): - main_dict[key] = main_dict[key] + update_dict[key] - else: - main_dict[key] = value - - -def get_value_or_default( - first_item: DefaultPlaceholder | DefaultType, - *extra_items: DefaultPlaceholder | DefaultType, -) -> DefaultPlaceholder | DefaultType: - """ - Pass items or `DefaultPlaceholder`s by descending priority. - - The first one to _not_ be a `DefaultPlaceholder` will be returned. - - Otherwise, the first item (a `DefaultPlaceholder`) will be returned. - """ - items = (first_item,) + extra_items - for item in items: - if not isinstance(item, DefaultPlaceholder): - return item - return first_item diff --git a/notification-service/venv/Lib/site-packages/fastapi/websockets.py b/notification-service/venv/Lib/site-packages/fastapi/websockets.py deleted file mode 100644 index 55a4ac4..0000000 --- a/notification-service/venv/Lib/site-packages/fastapi/websockets.py +++ /dev/null @@ -1,3 +0,0 @@ -from starlette.websockets import WebSocket as WebSocket # noqa -from starlette.websockets import WebSocketDisconnect as WebSocketDisconnect # noqa -from starlette.websockets import WebSocketState as WebSocketState # noqa diff --git a/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/INSTALLER b/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/METADATA b/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/METADATA deleted file mode 100644 index 31117b2..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/METADATA +++ /dev/null @@ -1,41 +0,0 @@ -Metadata-Version: 2.4 -Name: firebase_admin -Version: 7.4.0 -Summary: Firebase Admin Python SDK -Home-page: https://firebase.google.com/docs/admin/setup/ -Author: Firebase -License: Apache License 2.0 -Project-URL: Release Notes, https://firebase.google.com/support/release-notes/admin/python -Project-URL: Source, https://github.com/firebase/firebase-admin-python -Keywords: firebase cloud development -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: Topic :: Software Development :: Build Tools -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: License :: OSI Approved :: Apache Software License -Requires-Python: >=3.9 -License-File: LICENSE -Requires-Dist: cachecontrol>=0.14.3 -Requires-Dist: google-api-core[grpc]<3.0.0dev,>=2.25.1; platform_python_implementation != "PyPy" -Requires-Dist: google-cloud-firestore>=2.21.0; platform_python_implementation != "PyPy" -Requires-Dist: google-cloud-storage>=3.1.1 -Requires-Dist: pyjwt[crypto]>=2.10.1 -Requires-Dist: httpx[http2]==0.28.1 -Dynamic: author -Dynamic: classifier -Dynamic: description -Dynamic: home-page -Dynamic: keywords -Dynamic: license -Dynamic: license-file -Dynamic: project-url -Dynamic: requires-dist -Dynamic: requires-python -Dynamic: summary - -The Firebase Admin Python SDK enables server-side (backend) Python developers to integrate Firebase into their services and applications. diff --git a/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/RECORD b/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/RECORD deleted file mode 100644 index 64bc9fe..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/RECORD +++ /dev/null @@ -1,71 +0,0 @@ -firebase_admin-7.4.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -firebase_admin-7.4.0.dist-info/METADATA,sha256=aNGJEUQUJghkPT3GKA7g30L-zO3JWmfRH4A32f66khQ,1656 -firebase_admin-7.4.0.dist-info/RECORD,, -firebase_admin-7.4.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -firebase_admin-7.4.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91 -firebase_admin-7.4.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357 -firebase_admin-7.4.0.dist-info/top_level.txt,sha256=j8IXOwvHIaefIBBzAehVx1lROs_uinrBtfYXG-wDO_A,15 -firebase_admin/__about__.py,sha256=3Kon_UxV3N893K8tGNxO0ZGmjm4E4ZCaa7tkdBRGlsY,808 -firebase_admin/__init__.py,sha256=Y7ajPM2EhrLD69DV_938JTUyyQ4y4oF7QlT7FhVtvDQ,12204 -firebase_admin/__pycache__/__about__.cpython-312.pyc,, -firebase_admin/__pycache__/__init__.cpython-312.pyc,, -firebase_admin/__pycache__/_auth_client.cpython-312.pyc,, -firebase_admin/__pycache__/_auth_providers.cpython-312.pyc,, -firebase_admin/__pycache__/_auth_utils.cpython-312.pyc,, -firebase_admin/__pycache__/_http_client.cpython-312.pyc,, -firebase_admin/__pycache__/_messaging_encoder.cpython-312.pyc,, -firebase_admin/__pycache__/_messaging_utils.cpython-312.pyc,, -firebase_admin/__pycache__/_retry.cpython-312.pyc,, -firebase_admin/__pycache__/_rfc3339.cpython-312.pyc,, -firebase_admin/__pycache__/_sseclient.cpython-312.pyc,, -firebase_admin/__pycache__/_token_gen.cpython-312.pyc,, -firebase_admin/__pycache__/_user_identifier.cpython-312.pyc,, -firebase_admin/__pycache__/_user_import.cpython-312.pyc,, -firebase_admin/__pycache__/_user_mgt.cpython-312.pyc,, -firebase_admin/__pycache__/_utils.cpython-312.pyc,, -firebase_admin/__pycache__/app_check.cpython-312.pyc,, -firebase_admin/__pycache__/auth.cpython-312.pyc,, -firebase_admin/__pycache__/credentials.cpython-312.pyc,, -firebase_admin/__pycache__/db.cpython-312.pyc,, -firebase_admin/__pycache__/exceptions.cpython-312.pyc,, -firebase_admin/__pycache__/firestore.cpython-312.pyc,, -firebase_admin/__pycache__/firestore_async.cpython-312.pyc,, -firebase_admin/__pycache__/functions.cpython-312.pyc,, -firebase_admin/__pycache__/instance_id.cpython-312.pyc,, -firebase_admin/__pycache__/messaging.cpython-312.pyc,, -firebase_admin/__pycache__/ml.cpython-312.pyc,, -firebase_admin/__pycache__/phone_number_verification.cpython-312.pyc,, -firebase_admin/__pycache__/project_management.cpython-312.pyc,, -firebase_admin/__pycache__/remote_config.cpython-312.pyc,, -firebase_admin/__pycache__/storage.cpython-312.pyc,, -firebase_admin/__pycache__/tenant_mgt.cpython-312.pyc,, -firebase_admin/_auth_client.py,sha256=gkt-DmtI4ckBjk7kbHEuw_g-spl_pvzk26IYPf6Xpkk,37017 -firebase_admin/_auth_providers.py,sha256=nbYO2XQ4wMzdiQwwnTJGZeW210nE30_0h8phsdxRFZE,17143 -firebase_admin/_auth_utils.py,sha256=sSCh40LG3bPs8Rr1dJY_ZUAiAcsXqgJKmzLomgPz_2k,18792 -firebase_admin/_http_client.py,sha256=xEk00i5MuChnxJEZzxn1EPjqv-r3I6Zc0qMhcV7V4I0,14242 -firebase_admin/_messaging_encoder.py,sha256=AB5jx6wBxC3cLl54L6zd3JJyovJ05DmrK8K3RR-bPUI,33949 -firebase_admin/_messaging_utils.py,sha256=jkb4mGe-hekVqRRJ3UmWKsZ5cAGgPVnduZu9SKY8NBs,25208 -firebase_admin/_retry.py,sha256=RAc2ymTPIWgUFzPLmdPTk6-UVCbN5zN0nVcEELGIIvU,8459 -firebase_admin/_rfc3339.py,sha256=tsOoDwpayouDhyQai4fUPrULiOdpsAkYNuqG42BfMtw,3180 -firebase_admin/_sseclient.py,sha256=lVvew2118bLFJFpvNBnlh_VJy-sBhpLnTVIsAqF5bv4,6804 -firebase_admin/_token_gen.py,sha256=Yb0EwH02dqHrBeJlpnmy-_PNh4horORyq6uSYv2jQb8,19425 -firebase_admin/_user_identifier.py,sha256=jiV5Y-q99-35HE5PZ-V-FHhH-I2uOQeyjsqtfMoQ0Xk,2721 -firebase_admin/_user_import.py,sha256=EHaQmhYr2f0XlAmGqX4Uf_LujDrBWt4xuFMlNFc9pcg,17411 -firebase_admin/_user_mgt.py,sha256=sdfzl2dZMrCRhdJKMKudoczo2ZoL5Rm88x4j_wMHeeI,33050 -firebase_admin/_utils.py,sha256=EWGw8KwSFBDV4ClBO9P6YjB_Uf1lRYZ1_eUatCXjuuo,13277 -firebase_admin/app_check.py,sha256=wiHpfKafqKOhM7R-jkDfu_NZ1QiTRclsODvbKkwGdAg,6677 -firebase_admin/auth.py,sha256=3ks4ISkgWAUxWWtODjUB6g032-HqMo0nKvzLkwC3w_w,38690 -firebase_admin/credentials.py,sha256=OsbpBGN6mPCm37_xi2fWUpm7Vs6R1hSgBbyXxIKBhhQ,8599 -firebase_admin/db.py,sha256=TwQLcPQAOhHYws6CULqqIXj6QjiagDcA4euc60wl8VE,36922 -firebase_admin/exceptions.py,sha256=yn_oVZ87TJwoWdcSsMtL-syWWsHlp5_8o8cVJ3KxcB0,8506 -firebase_admin/firestore.py,sha256=N2iSs44OgEjW_HLgkrh9afPeU0EjXeqhMeUx-6-kl0Y,3857 -firebase_admin/firestore_async.py,sha256=6bGSLU7tuNSXaj77pmS46YAm9xdVUINlpKuj3SQMrps,3979 -firebase_admin/functions.py,sha256=IK3YAhcOdZMJkGaFmjec9jBBCCkVgFrkkh_-KFW-b2g,22691 -firebase_admin/instance_id.py,sha256=KDxVT91FDTQrjZRfGjY1Yz1tqkQu8DKYczxuNknryk0,3759 -firebase_admin/messaging.py,sha256=2bFHtpEDMDvVVB4ZOu5NRYR4o2Brz6xfiMdVBqiRQYE,23267 -firebase_admin/ml.py,sha256=L0j9KX9AsUfKolMRl72Xwg6S_lDmSf1KoyQD4J8baDY,34947 -firebase_admin/phone_number_verification.py,sha256=bZ2bcxZzpPoyVkF-PvHkNLoColPAF65xnu56xRp96CY,9054 -firebase_admin/project_management.py,sha256=5TqWr4TC2pvd7JVBApYlWkmxQrivH1sO_80S7S6m-bw,24747 -firebase_admin/remote_config.py,sha256=8y02aFnVn_-v_RaVV6eDdBrA-EB-yWHB5qwSicyHTi4,33965 -firebase_admin/storage.py,sha256=AclNJFgvvt7T2wdUzdT-5hEHruigB4t7wJbEXz5-1wU,3510 -firebase_admin/tenant_mgt.py,sha256=t-e9zZh5Hb8Pt8OXfP3x-eTWzCFcCwAp_Ur1uHlPrRk,16767 diff --git a/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/REQUESTED b/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/REQUESTED deleted file mode 100644 index e69de29..0000000 diff --git a/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/WHEEL b/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/WHEEL deleted file mode 100644 index 14a883f..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (82.0.1) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/licenses/LICENSE b/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/licenses/LICENSE deleted file mode 100644 index 261eeb9..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/licenses/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/top_level.txt b/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/top_level.txt deleted file mode 100644 index 9b59c15..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin-7.4.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -firebase_admin diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__about__.py b/notification-service/venv/Lib/site-packages/firebase_admin/__about__.py deleted file mode 100644 index e8ae3bb..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/__about__.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""About information (version, etc) for Firebase Admin SDK.""" - -__version__ = '7.4.0' -__title__ = 'firebase_admin' -__author__ = 'Firebase' -__license__ = 'Apache License 2.0' -__url__ = 'https://firebase.google.com/docs/admin/setup/' diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__init__.py b/notification-service/venv/Lib/site-packages/firebase_admin/__init__.py deleted file mode 100644 index 8c9f628..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/__init__.py +++ /dev/null @@ -1,317 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase Admin SDK for Python.""" -import datetime -import json -import os -import threading - -from google.auth.credentials import Credentials as GoogleAuthCredentials -from google.auth.exceptions import DefaultCredentialsError -from firebase_admin import credentials -from firebase_admin.__about__ import __version__ - - -_apps = {} -_apps_lock = threading.RLock() -_clock = datetime.datetime.utcnow - -_DEFAULT_APP_NAME = '[DEFAULT]' -_FIREBASE_CONFIG_ENV_VAR = 'FIREBASE_CONFIG' -_CONFIG_VALID_KEYS = ['databaseAuthVariableOverride', 'databaseURL', 'httpTimeout', 'projectId', - 'storageBucket'] - -def initialize_app(credential=None, options=None, name=_DEFAULT_APP_NAME): - """Initializes and returns a new App instance. - - Creates a new App instance using the specified options - and the app name. If an instance already exists by the same - app name a ValueError is raised. - If options are not provided an attempt is made to load the options from the environment. - This is done by looking up the ``FIREBASE_CONFIG`` environment variable. If the value of - the variable starts with ``"{"``, it is parsed as a JSON object. Otherwise it is treated - as a file name and the JSON content is read from the corresponding file. - Use this function whenever a new App instance is required. Do not directly invoke the - App constructor. - - Args: - credential: A credential object used to initialize the SDK (optional). If none is provided, - Google Application Default Credentials are used. - options: A dictionary of configuration options (optional). Supported options include - ``databaseURL``, ``storageBucket``, ``projectId``, ``databaseAuthVariableOverride``, - ``serviceAccountId`` and ``httpTimeout``. If ``httpTimeout`` is not set, the SDK uses - a default timeout of 120 seconds. - - name: Name of the app (optional). - Returns: - App: A newly initialized instance of App. - - Raises: - ValueError: If the app name is already in use, or any of the - provided arguments are invalid. - """ - if credential is None: - credential = credentials.ApplicationDefault() - app = App(name, credential, options) - with _apps_lock: - if app.name not in _apps: - _apps[app.name] = app - return app - - if name == _DEFAULT_APP_NAME: - raise ValueError(( - 'The default Firebase app already exists. This means you called ' - 'initialize_app() more than once without providing an app name as ' - 'the second argument. In most cases you only need to call ' - 'initialize_app() once. But if you do want to initialize multiple ' - 'apps, pass a second argument to initialize_app() to give each app ' - 'a unique name.')) - - raise ValueError( - f'Firebase app named "{name}" already exists. This means you called ' - 'initialize_app() more than once with the same app name as the ' - 'second argument. Make sure you provide a unique name every time ' - 'you call initialize_app().') - - -def delete_app(app): - """Gracefully deletes an App instance. - - Args: - app: The app instance to be deleted. - - Raises: - ValueError: If the app is not initialized. - """ - if not isinstance(app, App): - raise ValueError(f'Illegal app argument type: "{type(app)}". Argument must be of type App.') - with _apps_lock: - if _apps.get(app.name) is app: - del _apps[app.name] - app._cleanup() # pylint: disable=protected-access - return - if app.name == _DEFAULT_APP_NAME: - raise ValueError( - 'The default Firebase app is not initialized. Make sure to initialize ' - 'the default app by calling initialize_app().') - - raise ValueError( - f'Firebase app named "{app.name}" is not initialized. Make sure to initialize ' - 'the app by calling initialize_app() with your app name as the ' - 'second argument.') - - -def get_app(name=_DEFAULT_APP_NAME): - """Retrieves an App instance by name. - - Args: - name: Name of the App instance to retrieve (optional). - - Returns: - App: An App instance with the given name. - - Raises: - ValueError: If the specified name is not a string, or if the specified - app does not exist. - """ - if not isinstance(name, str): - raise ValueError( - f'Illegal app name argument type: "{type(name)}". App name must be a string.') - with _apps_lock: - if name in _apps: - return _apps[name] - - if name == _DEFAULT_APP_NAME: - raise ValueError( - 'The default Firebase app does not exist. Make sure to initialize ' - 'the SDK by calling initialize_app().') - - raise ValueError( - f'Firebase app named "{name}" does not exist. Make sure to initialize ' - 'the SDK by calling initialize_app() with your app name as the ' - 'second argument.') - - -class _AppOptions: - """A collection of configuration options for an App.""" - - def __init__(self, options): - if options is None: - options = self._load_from_environment() - - if not isinstance(options, dict): - raise ValueError( - f'Illegal Firebase app options type: {type(options)}. ' - 'Options must be a dictionary.') - self._options = options - - def get(self, key, default=None): - """Returns the option identified by the provided key.""" - return self._options.get(key, default) - - def _load_from_environment(self): - """Invoked when no options are passed to __init__, loads options from FIREBASE_CONFIG. - - If the value of the FIREBASE_CONFIG environment variable starts with "{" an attempt is made - to parse it as a JSON object, otherwise it is assumed to be pointing to a JSON file. - """ - - config_file = os.getenv(_FIREBASE_CONFIG_ENV_VAR) - if not config_file: - return {} - if config_file.startswith('{'): - json_str = config_file - else: - try: - with open(config_file, 'r', encoding='utf-8') as json_file: - json_str = json_file.read() - except Exception as err: - raise ValueError(f'Unable to read file {config_file}. {err}') from err - try: - json_data = json.loads(json_str) - except Exception as err: - raise ValueError( - f'JSON string "{json_str}" is not valid json. {err}') from err - return {k: v for k, v in json_data.items() if k in _CONFIG_VALID_KEYS} - - -class App: - """The entry point for Firebase Python SDK. - - Represents a Firebase app, while holding the configuration and state - common to all Firebase APIs. - """ - - def __init__(self, name, credential, options): - """Constructs a new App using the provided name and options. - - Args: - name: Name of the application. - credential: A credential object. - options: A dictionary of configuration options. - - Raises: - ValueError: If an argument is None or invalid. - """ - if not name or not isinstance(name, str): - raise ValueError( - f'Illegal Firebase app name "{name}" provided. App name must be a ' - 'non-empty string.') - self._name = name - - if isinstance(credential, GoogleAuthCredentials): - self._credential = credentials._ExternalCredentials(credential) # pylint: disable=protected-access - elif isinstance(credential, credentials.Base): - self._credential = credential - else: - raise ValueError('Illegal Firebase credential provided. App must be initialized ' - 'with a valid credential instance.') - self._options = _AppOptions(options) - self._lock = threading.RLock() - self._services = {} - - App._validate_project_id(self._options.get('projectId')) - self._project_id_initialized = False - - @classmethod - def _validate_project_id(cls, project_id): - if project_id is not None and not isinstance(project_id, str): - raise ValueError( - f'Invalid project ID: "{project_id}". project ID must be a string.') - - @property - def name(self): - return self._name - - @property - def credential(self): - return self._credential - - @property - def options(self): - return self._options - - @property - def project_id(self): - if not self._project_id_initialized: - self._project_id = self._lookup_project_id() - self._project_id_initialized = True - return self._project_id - - def _lookup_project_id(self): - """Looks up the Firebase project ID associated with an App. - - If a ``projectId`` is specified in app options, it is returned. Then tries to - get the project ID from the credential used to initialize the app. If that also fails, - attempts to look up the ``GOOGLE_CLOUD_PROJECT`` and ``GCLOUD_PROJECT`` environment - variables. - - Returns: - str: A project ID string or None. - """ - project_id = self._options.get('projectId') - if not project_id: - try: - project_id = self._credential.project_id - except (AttributeError, DefaultCredentialsError): - pass - if not project_id: - project_id = os.environ.get('GOOGLE_CLOUD_PROJECT', - os.environ.get('GCLOUD_PROJECT')) - App._validate_project_id(self._options.get('projectId')) - return project_id - - def _get_service(self, name, initializer): - """Returns the service instance identified by the given name. - - Services are functional entities exposed by the Admin SDK (e.g. auth, database). Each - service instance is associated with exactly one App. If the named service - instance does not exist yet, _get_service() calls the provided initializer function to - create the service instance. The created instance will be cached, so that subsequent - calls would always fetch it from the cache. - - Args: - name: Name of the service to retrieve. - initializer: A function that can be used to initialize a service for the first time. - - Returns: - object: The specified service instance. - - Raises: - ValueError: If the provided name is invalid, or if the App is already deleted. - """ - if not name or not isinstance(name, str): - raise ValueError( - f'Illegal name argument: "{name}". Name must be a non-empty string.') - with self._lock: - if self._services is None: - raise ValueError( - f'Service requested from deleted Firebase App: "{self._name}".') - if name not in self._services: - self._services[name] = initializer(self) - return self._services[name] - - def _cleanup(self): - """Cleans up any services associated with this App. - - Checks whether each service contains a close() method, and calls it if available. - This is to be called when an App is being deleted, thus ensuring graceful termination of - any services started by the App. - """ - with self._lock: - for service in self._services.values(): - if hasattr(service, 'close') and hasattr(service.close, '__call__'): - service.close() - self._services = None diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/__about__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/__about__.cpython-312.pyc deleted file mode 100644 index 369e4ee..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/__about__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index c0dd0ec..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_auth_client.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_auth_client.cpython-312.pyc deleted file mode 100644 index cd03431..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_auth_client.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_auth_providers.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_auth_providers.cpython-312.pyc deleted file mode 100644 index 861bab6..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_auth_providers.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_auth_utils.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_auth_utils.cpython-312.pyc deleted file mode 100644 index 45eac88..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_auth_utils.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_http_client.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_http_client.cpython-312.pyc deleted file mode 100644 index 609750f..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_http_client.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_messaging_encoder.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_messaging_encoder.cpython-312.pyc deleted file mode 100644 index 395196b..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_messaging_encoder.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_messaging_utils.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_messaging_utils.cpython-312.pyc deleted file mode 100644 index ebff388..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_messaging_utils.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_retry.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_retry.cpython-312.pyc deleted file mode 100644 index 3032c22..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_retry.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_rfc3339.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_rfc3339.cpython-312.pyc deleted file mode 100644 index 9b39d10..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_rfc3339.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_sseclient.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_sseclient.cpython-312.pyc deleted file mode 100644 index 7823a2a..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_sseclient.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_token_gen.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_token_gen.cpython-312.pyc deleted file mode 100644 index c0c8320..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_token_gen.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_user_identifier.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_user_identifier.cpython-312.pyc deleted file mode 100644 index 87b1f64..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_user_identifier.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_user_import.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_user_import.cpython-312.pyc deleted file mode 100644 index 0691dd1..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_user_import.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_user_mgt.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_user_mgt.cpython-312.pyc deleted file mode 100644 index eaba949..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_user_mgt.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_utils.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_utils.cpython-312.pyc deleted file mode 100644 index 4dc1668..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/_utils.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/app_check.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/app_check.cpython-312.pyc deleted file mode 100644 index f20f5fb..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/app_check.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/auth.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/auth.cpython-312.pyc deleted file mode 100644 index 8b866aa..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/auth.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/credentials.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/credentials.cpython-312.pyc deleted file mode 100644 index 0402dc0..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/credentials.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/db.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/db.cpython-312.pyc deleted file mode 100644 index 8172864..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/db.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/exceptions.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/exceptions.cpython-312.pyc deleted file mode 100644 index 149722f..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/exceptions.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/firestore.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/firestore.cpython-312.pyc deleted file mode 100644 index 6e2dc5e..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/firestore.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/firestore_async.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/firestore_async.cpython-312.pyc deleted file mode 100644 index 12cc15f..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/firestore_async.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/functions.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/functions.cpython-312.pyc deleted file mode 100644 index 6689914..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/functions.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/instance_id.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/instance_id.cpython-312.pyc deleted file mode 100644 index 8c2ae3e..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/instance_id.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/messaging.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/messaging.cpython-312.pyc deleted file mode 100644 index bb6fe3b..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/messaging.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/ml.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/ml.cpython-312.pyc deleted file mode 100644 index aa2b201..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/ml.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/phone_number_verification.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/phone_number_verification.cpython-312.pyc deleted file mode 100644 index 8f180e2..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/phone_number_verification.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/project_management.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/project_management.cpython-312.pyc deleted file mode 100644 index c554616..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/project_management.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/remote_config.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/remote_config.cpython-312.pyc deleted file mode 100644 index 9b89eca..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/remote_config.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/storage.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/storage.cpython-312.pyc deleted file mode 100644 index 481ee62..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/storage.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/tenant_mgt.cpython-312.pyc b/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/tenant_mgt.cpython-312.pyc deleted file mode 100644 index bd08068..0000000 Binary files a/notification-service/venv/Lib/site-packages/firebase_admin/__pycache__/tenant_mgt.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/_auth_client.py b/notification-service/venv/Lib/site-packages/firebase_admin/_auth_client.py deleted file mode 100644 index 74261fa..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/_auth_client.py +++ /dev/null @@ -1,761 +0,0 @@ -# Copyright 2020 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase auth client sub module.""" - -import time - -import firebase_admin -from firebase_admin import _auth_providers -from firebase_admin import _auth_utils -from firebase_admin import _http_client -from firebase_admin import _token_gen -from firebase_admin import _user_identifier -from firebase_admin import _user_import -from firebase_admin import _user_mgt -from firebase_admin import _utils - - -class Client: - """Firebase Authentication client scoped to a specific tenant.""" - - def __init__(self, app, tenant_id=None): - if not app.project_id: - raise ValueError("""A project ID is required to access the auth service. - 1. Use a service account credential, or - 2. set the project ID explicitly via Firebase App options, or - 3. set the project ID via the GOOGLE_CLOUD_PROJECT environment variable.""") - - credential = None - version_header = f'Python/Admin/{firebase_admin.__version__}' - timeout = app.options.get('httpTimeout', _http_client.DEFAULT_TIMEOUT_SECONDS) - # Non-default endpoint URLs for emulator support are set in this dict later. - endpoint_urls = {} - self.emulated = False - - # If an emulator is present, check that the given value matches the expected format and set - # endpoint URLs to use the emulator. Additionally, use a fake credential. - emulator_host = _auth_utils.get_emulator_host() - if emulator_host: - base_url = f'http://{emulator_host}/identitytoolkit.googleapis.com' - endpoint_urls['v1'] = base_url + '/v1' - endpoint_urls['v2'] = base_url + '/v2' - credential = _utils.EmulatorAdminCredentials() - self.emulated = True - else: - # Use credentials if provided - credential = app.credential.get_credential() - - http_client = _http_client.JsonHttpClient( - credential=credential, headers={'X-Client-Version': version_header}, timeout=timeout) - - self._tenant_id = tenant_id - self._token_generator = _token_gen.TokenGenerator( - app, http_client, url_override=endpoint_urls.get('v1')) - self._token_verifier = _token_gen.TokenVerifier(app) - self._user_manager = _user_mgt.UserManager( - http_client, app.project_id, tenant_id, url_override=endpoint_urls.get('v1')) - self._provider_manager = _auth_providers.ProviderConfigClient( - http_client, app.project_id, tenant_id, url_override=endpoint_urls.get('v2')) - - @property - def tenant_id(self): - """Tenant ID associated with this client.""" - return self._tenant_id - - def create_custom_token(self, uid, developer_claims=None): - """Builds and signs a Firebase custom auth token. - - Args: - uid: ID of the user for whom the token is created. - developer_claims: A dictionary of claims to be included in the token - (optional). - - Returns: - bytes: A token minted from the input parameters. - - Raises: - ValueError: If input parameters are invalid. - TokenSignError: If an error occurs while signing the token using the remote IAM service. - """ - return self._token_generator.create_custom_token( - uid, developer_claims, tenant_id=self.tenant_id) - - def verify_id_token(self, id_token, check_revoked=False, clock_skew_seconds=0): - """Verifies the signature and data for the provided JWT. - - Accepts a signed token string, verifies that it is current, was issued - to this project, and that it was correctly signed by Google. - - Args: - id_token: A string of the encoded JWT. - check_revoked: Boolean, If true, checks whether the token has been revoked or - the user disabled (optional). - clock_skew_seconds: The number of seconds to tolerate when checking the token. - Must be between 0-60. Defaults to 0. - - Returns: - dict: A dictionary of key-value pairs parsed from the decoded JWT. - - Raises: - ValueError: If ``id_token`` is a not a string or is empty. - InvalidIdTokenError: If ``id_token`` is not a valid Firebase ID token. - ExpiredIdTokenError: If the specified ID token has expired. - RevokedIdTokenError: If ``check_revoked`` is ``True`` and the ID token has been - revoked. - TenantIdMismatchError: If ``id_token`` belongs to a tenant that is different than - this ``Client`` instance. - CertificateFetchError: If an error occurs while fetching the public key certificates - required to verify the ID token. - UserDisabledError: If ``check_revoked`` is ``True`` and the corresponding user - record is disabled. - """ - if not isinstance(check_revoked, bool): - # guard against accidental wrong assignment. - raise ValueError( - 'Illegal check_revoked argument. Argument must be of type bool, but given ' - f'"{type(check_revoked)}".') - - verified_claims = self._token_verifier.verify_id_token(id_token, clock_skew_seconds) - if self.tenant_id: - token_tenant_id = verified_claims.get('firebase', {}).get('tenant') - if self.tenant_id != token_tenant_id: - raise _auth_utils.TenantIdMismatchError( - f'Invalid tenant ID: {token_tenant_id}') - - if check_revoked: - self._check_jwt_revoked_or_disabled( - verified_claims, _token_gen.RevokedIdTokenError, 'ID token') - return verified_claims - - def revoke_refresh_tokens(self, uid): - """Revokes all refresh tokens for an existing user. - - This method updates the user's ``tokens_valid_after_timestamp`` to the current UTC - in seconds since the epoch. It is important that the server on which this is called has its - clock set correctly and synchronized. - - While this revokes all sessions for a specified user and disables any new ID tokens for - existing sessions from getting minted, existing ID tokens may remain active until their - natural expiration (one hour). To verify that ID tokens are revoked, use - ``verify_id_token(idToken, check_revoked=True)``. - - Args: - uid: A user ID string. - - Raises: - ValueError: If the user ID is None, empty or malformed. - FirebaseError: If an error occurs while revoking the refresh token. - """ - self._user_manager.update_user(uid, valid_since=int(time.time())) - - def get_user(self, uid): - """Gets the user data corresponding to the specified user ID. - - Args: - uid: A user ID string. - - Returns: - UserRecord: A user record instance. - - Raises: - ValueError: If the user ID is None, empty or malformed. - UserNotFoundError: If the specified user ID does not exist. - FirebaseError: If an error occurs while retrieving the user. - """ - response = self._user_manager.get_user(uid=uid) - return _user_mgt.UserRecord(response) - - def get_user_by_email(self, email): - """Gets the user data corresponding to the specified user email. - - Args: - email: A user email address string. - - Returns: - UserRecord: A user record instance. - - Raises: - ValueError: If the email is None, empty or malformed. - UserNotFoundError: If no user exists for the specified email address. - FirebaseError: If an error occurs while retrieving the user. - """ - response = self._user_manager.get_user(email=email) - return _user_mgt.UserRecord(response) - - def get_user_by_phone_number(self, phone_number): - """Gets the user data corresponding to the specified phone number. - - Args: - phone_number: A phone number string. - - Returns: - UserRecord: A user record instance. - - Raises: - ValueError: If the phone number is ``None``, empty or malformed. - UserNotFoundError: If no user exists for the specified phone number. - FirebaseError: If an error occurs while retrieving the user. - """ - response = self._user_manager.get_user(phone_number=phone_number) - return _user_mgt.UserRecord(response) - - def get_users(self, identifiers): - """Gets the user data corresponding to the specified identifiers. - - There are no ordering guarantees; in particular, the nth entry in the - result list is not guaranteed to correspond to the nth entry in the input - parameters list. - - A maximum of 100 identifiers may be supplied. If more than 100 - identifiers are supplied, this method raises a `ValueError`. - - Args: - identifiers (list[Identifier]): A list of ``Identifier`` instances used - to indicate which user records should be returned. Must have <= 100 - entries. - - Returns: - GetUsersResult: A ``GetUsersResult`` instance corresponding to the - specified identifiers. - - Raises: - ValueError: If any of the identifiers are invalid or if more than 100 - identifiers are specified. - """ - response = self._user_manager.get_users(identifiers=identifiers) - - def _matches(identifier, user_record): - if isinstance(identifier, _user_identifier.UidIdentifier): - return identifier.uid == user_record.uid - if isinstance(identifier, _user_identifier.EmailIdentifier): - return identifier.email == user_record.email - if isinstance(identifier, _user_identifier.PhoneIdentifier): - return identifier.phone_number == user_record.phone_number - if isinstance(identifier, _user_identifier.ProviderIdentifier): - return next(( - True - for user_info in user_record.provider_data - if identifier.provider_id == user_info.provider_id - and identifier.provider_uid == user_info.uid - ), False) - raise TypeError(f"Unexpected type: {type(identifier)}") - - def _is_user_found(identifier, user_records): - return any(_matches(identifier, user_record) for user_record in user_records) - - users = [_user_mgt.UserRecord(user) for user in response] - not_found = [ - identifier for identifier in identifiers if not _is_user_found(identifier, users)] - - return _user_mgt.GetUsersResult(users=users, not_found=not_found) - - def list_users(self, page_token=None, max_results=_user_mgt.MAX_LIST_USERS_RESULTS): - """Retrieves a page of user accounts from a Firebase project. - - The ``page_token`` argument governs the starting point of the page. The ``max_results`` - argument governs the maximum number of user accounts that may be included in the returned - page. This function never returns ``None``. If there are no user accounts in the Firebase - project, this returns an empty page. - - Args: - page_token: A non-empty page token string, which indicates the starting point of the - page (optional). Defaults to ``None``, which will retrieve the first page of users. - max_results: A positive integer indicating the maximum number of users to include in - the returned page (optional). Defaults to 1000, which is also the maximum number - allowed. - - Returns: - ListUsersPage: A page of user accounts. - - Raises: - ValueError: If max_results or page_token are invalid. - FirebaseError: If an error occurs while retrieving the user accounts. - """ - def download(page_token, max_results): - return self._user_manager.list_users(page_token, max_results) - return _user_mgt.ListUsersPage(download, page_token, max_results) - - def create_user(self, **kwargs): # pylint: disable=differing-param-doc - """Creates a new user account with the specified properties. - - Args: - **kwargs: A series of keyword arguments (optional). - - Keyword Args: - uid: User ID to assign to the newly created user (optional). - display_name: The user's display name (optional). - email: The user's primary email (optional). - email_verified: A boolean indicating whether or not the user's primary email is - verified (optional). - phone_number: The user's primary phone number (optional). - photo_url: The user's photo URL (optional). - password: The user's raw, unhashed password. (optional). - disabled: A boolean indicating whether or not the user account is disabled (optional). - - Returns: - UserRecord: A UserRecord instance for the newly created user. - - Raises: - ValueError: If the specified user properties are invalid. - FirebaseError: If an error occurs while creating the user account. - """ - uid = self._user_manager.create_user(**kwargs) - return self.get_user(uid=uid) - - def update_user(self, uid, **kwargs): # pylint: disable=differing-param-doc - """Updates an existing user account with the specified properties. - - Args: - uid: A user ID string. - **kwargs: A series of keyword arguments (optional). - - Keyword Args: - display_name: The user's display name (optional). Can be removed by explicitly passing - ``auth.DELETE_ATTRIBUTE``. - email: The user's primary email (optional). - email_verified: A boolean indicating whether or not the user's primary email is - verified (optional). - phone_number: The user's primary phone number (optional). Can be removed by explicitly - passing ``auth.DELETE_ATTRIBUTE``. - photo_url: The user's photo URL (optional). Can be removed by explicitly passing - ``auth.DELETE_ATTRIBUTE``. - password: The user's raw, unhashed password. (optional). - disabled: A boolean indicating whether or not the user account is disabled (optional). - custom_claims: A dictionary or a JSON string contining the custom claims to be set on - the user account (optional). To remove all custom claims, pass - ``auth.DELETE_ATTRIBUTE``. - valid_since: An integer signifying the seconds since the epoch (optional). This field - is set by ``revoke_refresh_tokens`` and it is discouraged to set this field - directly. - providers_to_delete: The list of provider IDs to unlink, - eg: 'google.com', 'password', etc. - - Returns: - UserRecord: An updated UserRecord instance for the user. - - Raises: - ValueError: If the specified user ID or properties are invalid. - FirebaseError: If an error occurs while updating the user account. - """ - self._user_manager.update_user(uid, **kwargs) - return self.get_user(uid=uid) - - def set_custom_user_claims(self, uid, custom_claims): - """Sets additional claims on an existing user account. - - Custom claims set via this function can be used to define user roles and privilege levels. - These claims propagate to all the devices where the user is already signed in (after token - expiration or when token refresh is forced), and next time the user signs in. The claims - can be accessed via the user's ID token JWT. If a reserved OIDC claim is specified (sub, - iat, iss, etc), an error is thrown. Claims payload must also not be larger then 1000 - characters when serialized into a JSON string. - - Args: - uid: A user ID string. - custom_claims: A dictionary or a JSON string of custom claims. Pass None to unset any - claims set previously. - - Raises: - ValueError: If the specified user ID or the custom claims are invalid. - FirebaseError: If an error occurs while updating the user account. - """ - if custom_claims is None: - custom_claims = _user_mgt.DELETE_ATTRIBUTE - self._user_manager.update_user(uid, custom_claims=custom_claims) - - def delete_user(self, uid): - """Deletes the user identified by the specified user ID. - - Args: - uid: A user ID string. - - Raises: - ValueError: If the user ID is None, empty or malformed. - FirebaseError: If an error occurs while deleting the user account. - """ - self._user_manager.delete_user(uid) - - def delete_users(self, uids): - """Deletes the users specified by the given identifiers. - - Deleting a non-existing user does not generate an error (the method is - idempotent.) Non-existing users are considered to be successfully - deleted and are therefore included in the - `DeleteUserResult.success_count` value. - - A maximum of 1000 identifiers may be supplied. If more than 1000 - identifiers are supplied, this method raises a `ValueError`. - - Args: - uids: A list of strings indicating the uids of the users to be deleted. - Must have <= 1000 entries. - - Returns: - DeleteUsersResult: The total number of successful/failed deletions, as - well as the array of errors that correspond to the failed - deletions. - - Raises: - ValueError: If any of the identifiers are invalid or if more than 1000 - identifiers are specified. - """ - result = self._user_manager.delete_users(uids, force_delete=True) - return _user_mgt.DeleteUsersResult(result, len(uids)) - - def import_users(self, users, hash_alg=None): - """Imports the specified list of users into Firebase Auth. - - At most 1000 users can be imported at a time. This operation is optimized for bulk imports - and ignores checks on identifier uniqueness, which could result in duplications. The - ``hash_alg`` parameter must be specified when importing users with passwords. Refer to the - ``UserImportHash`` class for supported hash algorithms. - - Args: - users: A list of ``ImportUserRecord`` instances to import. Length of the list must not - exceed 1000. - hash_alg: A ``UserImportHash`` object (optional). Required when importing users with - passwords. - - Returns: - UserImportResult: An object summarizing the result of the import operation. - - Raises: - ValueError: If the provided arguments are invalid. - FirebaseError: If an error occurs while importing users. - """ - result = self._user_manager.import_users(users, hash_alg) - return _user_import.UserImportResult(result, len(users)) - - def generate_password_reset_link(self, email, action_code_settings=None): - """Generates the out-of-band email action link for password reset flows for the specified - email address. - - Args: - email: The email of the user whose password is to be reset. - action_code_settings: ``ActionCodeSettings`` instance (optional). Defines whether - the link is to be handled by a mobile app and the additional state information to - be passed in the deep link. - - Returns: - link: The password reset link created by the API - - Raises: - ValueError: If the provided arguments are invalid - EmailNotFoundError: If no user exists for the specified email address. - FirebaseError: If an error occurs while generating the link - """ - return self._user_manager.generate_email_action_link( - 'PASSWORD_RESET', email, action_code_settings=action_code_settings) - - def generate_email_verification_link(self, email, action_code_settings=None): - """Generates the out-of-band email action link for email verification flows for the - specified email address. - - Args: - email: The email of the user to be verified. - action_code_settings: ``ActionCodeSettings`` instance (optional). Defines whether - the link is to be handled by a mobile app and the additional state information to - be passed in the deep link. - - Returns: - link: The email verification link created by the API - - Raises: - ValueError: If the provided arguments are invalid - UserNotFoundError: If no user exists for the specified email address. - FirebaseError: If an error occurs while generating the link - """ - return self._user_manager.generate_email_action_link( - 'VERIFY_EMAIL', email, action_code_settings=action_code_settings) - - def generate_sign_in_with_email_link(self, email, action_code_settings): - """Generates the out-of-band email action link for email link sign-in flows, using the - action code settings provided. - - Args: - email: The email of the user signing in. - action_code_settings: ``ActionCodeSettings`` instance. Defines whether - the link is to be handled by a mobile app and the additional state information to be - passed in the deep link. - - Returns: - link: The email sign-in link created by the API - - Raises: - ValueError: If the provided arguments are invalid - FirebaseError: If an error occurs while generating the link - """ - return self._user_manager.generate_email_action_link( - 'EMAIL_SIGNIN', email, action_code_settings=action_code_settings) - - def get_oidc_provider_config(self, provider_id): - """Returns the ``OIDCProviderConfig`` with the given ID. - - Args: - provider_id: Provider ID string. - - Returns: - SAMLProviderConfig: An OIDC provider config instance. - - Raises: - ValueError: If the provider ID is invalid, empty or does not have ``oidc.`` prefix. - ConfigurationNotFoundError: If no OIDC provider is available with the given identifier. - FirebaseError: If an error occurs while retrieving the OIDC provider. - """ - return self._provider_manager.get_oidc_provider_config(provider_id) - - def create_oidc_provider_config( - self, provider_id, client_id, issuer, display_name=None, enabled=None, - client_secret=None, id_token_response_type=None, code_response_type=None): - """Creates a new OIDC provider config from the given parameters. - - OIDC provider support requires Google Cloud's Identity Platform (GCIP). To learn more about - GCIP, including pricing and features, see https://cloud.google.com/identity-platform. - - Args: - provider_id: Provider ID string. Must have the prefix ``oidc.``. - client_id: Client ID of the new config. - issuer: Issuer of the new config. Must be a valid URL. - display_name: The user-friendly display name to the current configuration (optional). - This name is also used as the provider label in the Cloud Console. - enabled: A boolean indicating whether the provider configuration is enabled or disabled - (optional). A user cannot sign in using a disabled provider. - client_secret: A string which sets the client secret for the new provider. - This is required for the code flow. - code_response_type: A boolean which sets whether to enable the code response flow for - the new provider. By default, this is not enabled if no response type is - specified. A client secret must be set for this response type. - Having both the code and ID token response flows is currently not supported. - id_token_response_type: A boolean which sets whether to enable the ID token response - flow for the new provider. By default, this is enabled if no response type is - specified. - Having both the code and ID token response flows is currently not supported. - - Returns: - OIDCProviderConfig: The newly created OIDC provider config instance. - - Raises: - ValueError: If any of the specified input parameters are invalid. - FirebaseError: If an error occurs while creating the new OIDC provider config. - """ - return self._provider_manager.create_oidc_provider_config( - provider_id, client_id=client_id, issuer=issuer, display_name=display_name, - enabled=enabled, client_secret=client_secret, - id_token_response_type=id_token_response_type, code_response_type=code_response_type) - - def update_oidc_provider_config( - self, provider_id, client_id=None, issuer=None, display_name=None, enabled=None, - client_secret=None, id_token_response_type=None, code_response_type=None): - """Updates an existing OIDC provider config with the given parameters. - - Args: - provider_id: Provider ID string. Must have the prefix ``oidc.``. - client_id: Client ID of the new config (optional). - issuer: Issuer of the new config (optional). Must be a valid URL. - display_name: The user-friendly display name to the current configuration (optional). - Pass ``auth.DELETE_ATTRIBUTE`` to delete the current display name. - enabled: A boolean indicating whether the provider configuration is enabled or disabled - (optional). - client_secret: A string which sets the client secret for the new provider. - This is required for the code flow. - code_response_type: A boolean which sets whether to enable the code response flow for - the new provider. By default, this is not enabled if no response type is specified. - A client secret must be set for this response type. - Having both the code and ID token response flows is currently not supported. - id_token_response_type: A boolean which sets whether to enable the ID token response - flow for the new provider. By default, this is enabled if no response type is - specified. - Having both the code and ID token response flows is currently not supported. - - Returns: - OIDCProviderConfig: The updated OIDC provider config instance. - - Raises: - ValueError: If any of the specified input parameters are invalid. - FirebaseError: If an error occurs while updating the OIDC provider config. - """ - return self._provider_manager.update_oidc_provider_config( - provider_id, client_id=client_id, issuer=issuer, display_name=display_name, - enabled=enabled, client_secret=client_secret, - id_token_response_type=id_token_response_type, code_response_type=code_response_type) - - def delete_oidc_provider_config(self, provider_id): - """Deletes the ``OIDCProviderConfig`` with the given ID. - - Args: - provider_id: Provider ID string. - - Raises: - ValueError: If the provider ID is invalid, empty or does not have ``oidc.`` prefix. - ConfigurationNotFoundError: If no OIDC provider is available with the given identifier. - FirebaseError: If an error occurs while deleting the OIDC provider. - """ - self._provider_manager.delete_oidc_provider_config(provider_id) - - def list_oidc_provider_configs( - self, page_token=None, max_results=_auth_providers.MAX_LIST_CONFIGS_RESULTS): - """Retrieves a page of OIDC provider configs from a Firebase project. - - The ``page_token`` argument governs the starting point of the page. The ``max_results`` - argument governs the maximum number of configs that may be included in the returned - page. This function never returns ``None``. If there are no OIDC configs in the Firebase - project, this returns an empty page. - - Args: - page_token: A non-empty page token string, which indicates the starting point of the - page (optional). Defaults to ``None``, which will retrieve the first page of users. - max_results: A positive integer indicating the maximum number of users to include in - the returned page (optional). Defaults to 100, which is also the maximum number - allowed. - - Returns: - ListProviderConfigsPage: A page of OIDC provider config instances. - - Raises: - ValueError: If ``max_results`` or ``page_token`` are invalid. - FirebaseError: If an error occurs while retrieving the OIDC provider configs. - """ - return self._provider_manager.list_oidc_provider_configs(page_token, max_results) - - def get_saml_provider_config(self, provider_id): - """Returns the ``SAMLProviderConfig`` with the given ID. - - Args: - provider_id: Provider ID string. - - Returns: - SAMLProviderConfig: A SAML provider config instance. - - Raises: - ValueError: If the provider ID is invalid, empty or does not have ``saml.`` prefix. - ConfigurationNotFoundError: If no SAML provider is available with the given identifier. - FirebaseError: If an error occurs while retrieving the SAML provider. - """ - return self._provider_manager.get_saml_provider_config(provider_id) - - def create_saml_provider_config( - self, provider_id, idp_entity_id, sso_url, x509_certificates, rp_entity_id, - callback_url, display_name=None, enabled=None): - """Creates a new SAML provider config from the given parameters. - - SAML provider support requires Google Cloud's Identity Platform (GCIP). To learn more about - GCIP, including pricing and features, see https://cloud.google.com/identity-platform. - - Args: - provider_id: Provider ID string. Must have the prefix ``saml.``. - idp_entity_id: The SAML IdP entity identifier. - sso_url: The SAML IdP SSO URL. Must be a valid URL. - x509_certificates: The list of SAML IdP X.509 certificates issued by CA for this - provider. Multiple certificates are accepted to prevent outages during IdP key - rotation (for example ADFS rotates every 10 days). When the Auth server receives a - SAML response, it will match the SAML response with the certificate on record. - Otherwise the response is rejected. Developers are expected to manage the - certificate updates as keys are rotated. - rp_entity_id: The SAML relying party (service provider) entity ID. This is defined by - the developer but needs to be provided to the SAML IdP. - callback_url: Callback URL string. This is fixed and must always be the same as the - OAuth redirect URL provisioned by Firebase Auth, unless a custom authDomain is - used. - display_name: The user-friendly display name to the current configuration (optional). - This name is also used as the provider label in the Cloud Console. - enabled: A boolean indicating whether the provider configuration is enabled or disabled - (optional). A user cannot sign in using a disabled provider. - - Returns: - SAMLProviderConfig: The newly created SAML provider config instance. - - Raises: - ValueError: If any of the specified input parameters are invalid. - FirebaseError: If an error occurs while creating the new SAML provider config. - """ - return self._provider_manager.create_saml_provider_config( - provider_id, idp_entity_id=idp_entity_id, sso_url=sso_url, - x509_certificates=x509_certificates, rp_entity_id=rp_entity_id, - callback_url=callback_url, display_name=display_name, enabled=enabled) - - def update_saml_provider_config( - self, provider_id, idp_entity_id=None, sso_url=None, x509_certificates=None, - rp_entity_id=None, callback_url=None, display_name=None, enabled=None): - """Updates an existing SAML provider config with the given parameters. - - Args: - provider_id: Provider ID string. Must have the prefix ``saml.``. - idp_entity_id: The SAML IdP entity identifier (optional). - sso_url: The SAML IdP SSO URL. Must be a valid URL (optional). - x509_certificates: The list of SAML IdP X.509 certificates issued by CA for this - provider (optional). - rp_entity_id: The SAML relying party entity ID (optional). - callback_url: Callback URL string (optional). - display_name: The user-friendly display name of the current configuration (optional). - Pass ``auth.DELETE_ATTRIBUTE`` to delete the current display name. - enabled: A boolean indicating whether the provider configuration is enabled or disabled - (optional). - - Returns: - SAMLProviderConfig: The updated SAML provider config instance. - - Raises: - ValueError: If any of the specified input parameters are invalid. - FirebaseError: If an error occurs while updating the SAML provider config. - """ - return self._provider_manager.update_saml_provider_config( - provider_id, idp_entity_id=idp_entity_id, sso_url=sso_url, - x509_certificates=x509_certificates, rp_entity_id=rp_entity_id, - callback_url=callback_url, display_name=display_name, enabled=enabled) - - def delete_saml_provider_config(self, provider_id): - """Deletes the ``SAMLProviderConfig`` with the given ID. - - Args: - provider_id: Provider ID string. - - Raises: - ValueError: If the provider ID is invalid, empty or does not have ``saml.`` prefix. - ConfigurationNotFoundError: If no SAML provider is available with the given identifier. - FirebaseError: If an error occurs while deleting the SAML provider. - """ - self._provider_manager.delete_saml_provider_config(provider_id) - - def list_saml_provider_configs( - self, page_token=None, max_results=_auth_providers.MAX_LIST_CONFIGS_RESULTS): - """Retrieves a page of SAML provider configs from a Firebase project. - - The ``page_token`` argument governs the starting point of the page. The ``max_results`` - argument governs the maximum number of configs that may be included in the returned - page. This function never returns ``None``. If there are no SAML configs in the Firebase - project, this returns an empty page. - - Args: - page_token: A non-empty page token string, which indicates the starting point of the - page (optional). Defaults to ``None``, which will retrieve the first page of users. - max_results: A positive integer indicating the maximum number of users to include in - the returned page (optional). Defaults to 100, which is also the maximum number - allowed. - - Returns: - ListProviderConfigsPage: A page of SAML provider config instances. - - Raises: - ValueError: If ``max_results`` or ``page_token`` are invalid. - FirebaseError: If an error occurs while retrieving the SAML provider configs. - """ - return self._provider_manager.list_saml_provider_configs(page_token, max_results) - - def _check_jwt_revoked_or_disabled(self, verified_claims, exc_type, label): - user = self.get_user(verified_claims.get('uid')) - if user.disabled: - raise _auth_utils.UserDisabledError('The user record is disabled.') - if verified_claims.get('iat') * 1000 < user.tokens_valid_after_timestamp: - raise exc_type(f'The Firebase {label} has been revoked.') diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/_auth_providers.py b/notification-service/venv/Lib/site-packages/firebase_admin/_auth_providers.py deleted file mode 100644 index cc79495..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/_auth_providers.py +++ /dev/null @@ -1,431 +0,0 @@ -# Copyright 2020 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase auth providers management sub module.""" - -from urllib import parse - -import requests - -from firebase_admin import _auth_utils -from firebase_admin import _user_mgt - - -MAX_LIST_CONFIGS_RESULTS = 100 - - -class ProviderConfig: - """Parent type for all authentication provider config types.""" - - def __init__(self, data): - self._data = data - - @property - def provider_id(self): - name = self._data['name'] - return name.split('/')[-1] - - @property - def display_name(self): - return self._data.get('displayName') - - @property - def enabled(self): - return self._data.get('enabled', False) - - -class OIDCProviderConfig(ProviderConfig): - """Represents the OIDC auth provider configuration. - - See https://openid.net/specs/openid-connect-core-1_0-final.html. - """ - - @property - def issuer(self): - return self._data['issuer'] - - @property - def client_id(self): - return self._data['clientId'] - - @property - def client_secret(self): - return self._data.get('clientSecret') - - @property - def id_token_response_type(self): - return self._data.get('responseType', {}).get('idToken', False) - - @property - def code_response_type(self): - return self._data.get('responseType', {}).get('code', False) - - -class SAMLProviderConfig(ProviderConfig): - """Represents he SAML auth provider configuration. - - See http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html. - """ - - @property - def idp_entity_id(self): - return self._data.get('idpConfig', {})['idpEntityId'] - - @property - def sso_url(self): - return self._data.get('idpConfig', {})['ssoUrl'] - - @property - def x509_certificates(self): - certs = self._data.get('idpConfig', {})['idpCertificates'] - return [c['x509Certificate'] for c in certs] - - @property - def callback_url(self): - return self._data.get('spConfig', {})['callbackUri'] - - @property - def rp_entity_id(self): - return self._data.get('spConfig', {})['spEntityId'] - - -class ListProviderConfigsPage: - """Represents a page of AuthProviderConfig instances retrieved from a Firebase project. - - Provides methods for traversing the provider configs included in this page, as well as - retrieving subsequent pages. The iterator returned by ``iterate_all()`` can be used to iterate - through all provider configs in the Firebase project starting from this page. - """ - - def __init__(self, download, page_token, max_results): - self._download = download - self._max_results = max_results - self._current = download(page_token, max_results) - - @property - def provider_configs(self): - """A list of ``AuthProviderConfig`` instances available in this page.""" - raise NotImplementedError - - @property - def next_page_token(self): - """Page token string for the next page (empty string indicates no more pages).""" - return self._current.get('nextPageToken', '') - - @property - def has_next_page(self): - """A boolean indicating whether more pages are available.""" - return bool(self.next_page_token) - - def get_next_page(self): - """Retrieves the next page of provider configs, if available. - - Returns: - ListProviderConfigsPage: Next page of provider configs, or None if this is the last - page. - """ - if self.has_next_page: - return self.__class__(self._download, self.next_page_token, self._max_results) - return None - - def iterate_all(self): - """Retrieves an iterator for provider configs. - - Returned iterator will iterate through all the provider configs in the Firebase project - starting from this page. The iterator will never buffer more than one page of configs - in memory at a time. - - Returns: - iterator: An iterator of AuthProviderConfig instances. - """ - return _ProviderConfigIterator(self) - - -class _ListOIDCProviderConfigsPage(ListProviderConfigsPage): - - @property - def provider_configs(self): - return [OIDCProviderConfig(data) for data in self._current.get('oauthIdpConfigs', [])] - - -class _ListSAMLProviderConfigsPage(ListProviderConfigsPage): - - @property - def provider_configs(self): - return [SAMLProviderConfig(data) for data in self._current.get('inboundSamlConfigs', [])] - - -class _ProviderConfigIterator(_auth_utils.PageIterator): - - @property - def items(self): - return self._current_page.provider_configs - - -class ProviderConfigClient: - """Client for managing Auth provider configurations.""" - - PROVIDER_CONFIG_URL = 'https://identitytoolkit.googleapis.com/v2' - - def __init__(self, http_client, project_id, tenant_id=None, url_override=None): - self.http_client = http_client - url_prefix = url_override or self.PROVIDER_CONFIG_URL - self.base_url = f'{url_prefix}/projects/{project_id}' - if tenant_id: - self.base_url += f'/tenants/{tenant_id}' - - def get_oidc_provider_config(self, provider_id): - _validate_oidc_provider_id(provider_id) - body = self._make_request('get', f'/oauthIdpConfigs/{provider_id}') - return OIDCProviderConfig(body) - - def create_oidc_provider_config( - self, provider_id, client_id, issuer, display_name=None, enabled=None, - client_secret=None, id_token_response_type=None, code_response_type=None): - """Creates a new OIDC provider config from the given parameters.""" - _validate_oidc_provider_id(provider_id) - req = { - 'clientId': _validate_non_empty_string(client_id, 'client_id'), - 'issuer': _validate_url(issuer, 'issuer'), - } - if display_name is not None: - req['displayName'] = _auth_utils.validate_string(display_name, 'display_name') - if enabled is not None: - req['enabled'] = _auth_utils.validate_boolean(enabled, 'enabled') - - response_type = {} - if id_token_response_type is False and code_response_type is False: - raise ValueError('At least one response type must be returned.') - if id_token_response_type is not None: - response_type['idToken'] = _auth_utils.validate_boolean( - id_token_response_type, 'id_token_response_type') - if code_response_type is not None: - response_type['code'] = _auth_utils.validate_boolean( - code_response_type, 'code_response_type') - if code_response_type: - req['clientSecret'] = _validate_non_empty_string(client_secret, 'client_secret') - if response_type: - req['responseType'] = response_type - - params = f'oauthIdpConfigId={provider_id}' - body = self._make_request('post', '/oauthIdpConfigs', json=req, params=params) - return OIDCProviderConfig(body) - - def update_oidc_provider_config( - self, provider_id, client_id=None, issuer=None, display_name=None, - enabled=None, client_secret=None, id_token_response_type=None, - code_response_type=None): - """Updates an existing OIDC provider config with the given parameters.""" - _validate_oidc_provider_id(provider_id) - req = {} - if display_name is not None: - if display_name == _user_mgt.DELETE_ATTRIBUTE: - req['displayName'] = None - else: - req['displayName'] = _auth_utils.validate_string(display_name, 'display_name') - if enabled is not None: - req['enabled'] = _auth_utils.validate_boolean(enabled, 'enabled') - if client_id: - req['clientId'] = _validate_non_empty_string(client_id, 'client_id') - if issuer: - req['issuer'] = _validate_url(issuer, 'issuer') - - response_type = {} - if id_token_response_type is False and code_response_type is False: - raise ValueError('At least one response type must be returned.') - if id_token_response_type is not None: - response_type['idToken'] = _auth_utils.validate_boolean( - id_token_response_type, 'id_token_response_type') - if code_response_type is not None: - response_type['code'] = _auth_utils.validate_boolean( - code_response_type, 'code_response_type') - if code_response_type: - req['clientSecret'] = _validate_non_empty_string(client_secret, 'client_secret') - if response_type: - req['responseType'] = response_type - - if not req: - raise ValueError('At least one parameter must be specified for update.') - - update_mask = _auth_utils.build_update_mask(req) - params = f'updateMask={",".join(update_mask)}' - url = f'/oauthIdpConfigs/{provider_id}' - body = self._make_request('patch', url, json=req, params=params) - return OIDCProviderConfig(body) - - def delete_oidc_provider_config(self, provider_id): - _validate_oidc_provider_id(provider_id) - self._make_request('delete', f'/oauthIdpConfigs/{provider_id}') - - def list_oidc_provider_configs(self, page_token=None, max_results=MAX_LIST_CONFIGS_RESULTS): - return _ListOIDCProviderConfigsPage( - self._fetch_oidc_provider_configs, page_token, max_results) - - def _fetch_oidc_provider_configs(self, page_token=None, max_results=MAX_LIST_CONFIGS_RESULTS): - return self._fetch_provider_configs('/oauthIdpConfigs', page_token, max_results) - - def get_saml_provider_config(self, provider_id): - _validate_saml_provider_id(provider_id) - body = self._make_request('get', f'/inboundSamlConfigs/{provider_id}') - return SAMLProviderConfig(body) - - def create_saml_provider_config( - self, provider_id, idp_entity_id, sso_url, x509_certificates, - rp_entity_id, callback_url, display_name=None, enabled=None): - """Creates a new SAML provider config from the given parameters.""" - _validate_saml_provider_id(provider_id) - req = { - 'idpConfig': { - 'idpEntityId': _validate_non_empty_string(idp_entity_id, 'idp_entity_id'), - 'ssoUrl': _validate_url(sso_url, 'sso_url'), - 'idpCertificates': _validate_x509_certificates(x509_certificates), - }, - 'spConfig': { - 'spEntityId': _validate_non_empty_string(rp_entity_id, 'rp_entity_id'), - 'callbackUri': _validate_url(callback_url, 'callback_url'), - }, - } - if display_name is not None: - req['displayName'] = _auth_utils.validate_string(display_name, 'display_name') - if enabled is not None: - req['enabled'] = _auth_utils.validate_boolean(enabled, 'enabled') - - params = f'inboundSamlConfigId={provider_id}' - body = self._make_request('post', '/inboundSamlConfigs', json=req, params=params) - return SAMLProviderConfig(body) - - def update_saml_provider_config( - self, provider_id, idp_entity_id=None, sso_url=None, x509_certificates=None, - rp_entity_id=None, callback_url=None, display_name=None, enabled=None): - """Updates an existing SAML provider config with the given parameters.""" - _validate_saml_provider_id(provider_id) - idp_config = {} - if idp_entity_id is not None: - idp_config['idpEntityId'] = _validate_non_empty_string(idp_entity_id, 'idp_entity_id') - if sso_url is not None: - idp_config['ssoUrl'] = _validate_url(sso_url, 'sso_url') - if x509_certificates is not None: - idp_config['idpCertificates'] = _validate_x509_certificates(x509_certificates) - - sp_config = {} - if rp_entity_id is not None: - sp_config['spEntityId'] = _validate_non_empty_string(rp_entity_id, 'rp_entity_id') - if callback_url is not None: - sp_config['callbackUri'] = _validate_url(callback_url, 'callback_url') - - req = {} - if display_name is not None: - if display_name == _user_mgt.DELETE_ATTRIBUTE: - req['displayName'] = None - else: - req['displayName'] = _auth_utils.validate_string(display_name, 'display_name') - if enabled is not None: - req['enabled'] = _auth_utils.validate_boolean(enabled, 'enabled') - if idp_config: - req['idpConfig'] = idp_config - if sp_config: - req['spConfig'] = sp_config - - if not req: - raise ValueError('At least one parameter must be specified for update.') - - update_mask = _auth_utils.build_update_mask(req) - params = f'updateMask={",".join(update_mask)}' - url = f'/inboundSamlConfigs/{provider_id}' - body = self._make_request('patch', url, json=req, params=params) - return SAMLProviderConfig(body) - - def delete_saml_provider_config(self, provider_id): - _validate_saml_provider_id(provider_id) - self._make_request('delete', f'/inboundSamlConfigs/{provider_id}') - - def list_saml_provider_configs(self, page_token=None, max_results=MAX_LIST_CONFIGS_RESULTS): - return _ListSAMLProviderConfigsPage( - self._fetch_saml_provider_configs, page_token, max_results) - - def _fetch_saml_provider_configs(self, page_token=None, max_results=MAX_LIST_CONFIGS_RESULTS): - return self._fetch_provider_configs('/inboundSamlConfigs', page_token, max_results) - - def _fetch_provider_configs(self, path, page_token=None, max_results=MAX_LIST_CONFIGS_RESULTS): - """Fetches a page of auth provider configs""" - if page_token is not None: - if not isinstance(page_token, str) or not page_token: - raise ValueError('Page token must be a non-empty string.') - if not isinstance(max_results, int): - raise ValueError('Max results must be an integer.') - if max_results < 1 or max_results > MAX_LIST_CONFIGS_RESULTS: - raise ValueError( - 'Max results must be a positive integer less than or equal to ' - f'{MAX_LIST_CONFIGS_RESULTS}.') - - params = f'pageSize={max_results}' - if page_token: - params += f'&pageToken={page_token}' - return self._make_request('get', path, params=params) - - def _make_request(self, method, path, **kwargs): - url = f'{self.base_url}{path}' - try: - return self.http_client.body(method, url, **kwargs) - except requests.exceptions.RequestException as error: - raise _auth_utils.handle_auth_backend_error(error) - - -def _validate_oidc_provider_id(provider_id): - if not isinstance(provider_id, str): - raise ValueError( - f'Invalid OIDC provider ID: {provider_id}. Provider ID must be a non-empty string.') - if not provider_id.startswith('oidc.'): - raise ValueError(f'Invalid OIDC provider ID: {provider_id}.') - return provider_id - - -def _validate_saml_provider_id(provider_id): - if not isinstance(provider_id, str): - raise ValueError( - f'Invalid SAML provider ID: {provider_id}. Provider ID must be a non-empty string.') - if not provider_id.startswith('saml.'): - raise ValueError(f'Invalid SAML provider ID: {provider_id}.') - return provider_id - - -def _validate_non_empty_string(value, label): - """Validates that the given value is a non-empty string.""" - if not isinstance(value, str): - raise ValueError(f'Invalid type for {label}: {value}.') - if not value: - raise ValueError(f'{label} must not be empty.') - return value - - -def _validate_url(url, label): - """Validates that the given value is a well-formed URL string.""" - if not isinstance(url, str) or not url: - raise ValueError( - f'Invalid photo URL: "{url}". {label} must be a non-empty string.') - try: - parsed = parse.urlparse(url) - if not parsed.netloc: - raise ValueError(f'Malformed {label}: "{url}".') - return url - except Exception as exception: - raise ValueError(f'Malformed {label}: "{url}".') from exception - - -def _validate_x509_certificates(x509_certificates): - if not isinstance(x509_certificates, list) or not x509_certificates: - raise ValueError('x509_certificates must be a non-empty list.') - if not all(isinstance(cert, str) and cert for cert in x509_certificates): - raise ValueError('x509_certificates must only contain non-empty strings.') - return [{'x509Certificate': cert} for cert in x509_certificates] diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/_auth_utils.py b/notification-service/venv/Lib/site-packages/firebase_admin/_auth_utils.py deleted file mode 100644 index 8f3c419..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/_auth_utils.py +++ /dev/null @@ -1,491 +0,0 @@ -# Copyright 2018 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase auth utils.""" - -import json -import os -import re -from urllib import parse - -from firebase_admin import exceptions -from firebase_admin import _utils - - -EMULATOR_HOST_ENV_VAR = 'FIREBASE_AUTH_EMULATOR_HOST' -MAX_CLAIMS_PAYLOAD_SIZE = 1000 -RESERVED_CLAIMS = set([ - 'acr', 'amr', 'at_hash', 'aud', 'auth_time', 'azp', 'cnf', 'c_hash', 'exp', 'iat', - 'iss', 'jti', 'nbf', 'nonce', 'sub', 'firebase', -]) -VALID_EMAIL_ACTION_TYPES = set(['VERIFY_EMAIL', 'EMAIL_SIGNIN', 'PASSWORD_RESET']) - - -class PageIterator: - """An iterator that allows iterating over a sequence of items, one at a time. - - This implementation loads a page of items into memory, and iterates on them. When the whole - page has been traversed, it loads another page. This class never keeps more than one page - of entries in memory. - """ - - def __init__(self, current_page): - if not current_page: - raise ValueError('Current page must not be None.') - - self._current_page = current_page - self._iter = None - - def __next__(self): - if self._iter is None: - self._iter = iter(self.items) - - try: - return next(self._iter) - except StopIteration: - if self._current_page.has_next_page: - self._current_page = self._current_page.get_next_page() - self._iter = iter(self.items) - - return next(self._iter) - - raise - - def __iter__(self): - return self - - @property - def items(self): - raise NotImplementedError - - -def get_emulator_host(): - emulator_host = os.getenv(EMULATOR_HOST_ENV_VAR, '') - if emulator_host and '//' in emulator_host: - raise ValueError( - f'Invalid {EMULATOR_HOST_ENV_VAR}: "{emulator_host}". ' - 'It must follow format "host:port".') - return emulator_host - - -def is_emulated(): - return get_emulator_host() != '' - - -def validate_uid(uid, required=False): - if uid is None and not required: - return None - if not isinstance(uid, str) or not uid or len(uid) > 128: - raise ValueError( - f'Invalid uid: "{uid}". The uid must be a non-empty string with no more than 128 ' - 'characters.') - return uid - -def validate_email(email, required=False): - if email is None and not required: - return None - if not isinstance(email, str) or not email: - raise ValueError( - f'Invalid email: "{email}". Email must be a non-empty string.') - parts = email.split('@') - if len(parts) != 2 or not parts[0] or not parts[1]: - raise ValueError(f'Malformed email address string: "{email}".') - return email - -def validate_phone(phone, required=False): - """Validates the specified phone number. - - Phone number vlidation is very lax here. Backend will enforce E.164 spec compliance, and - normalize accordingly. Here we check if the number starts with + sign, and contains at - least one alphanumeric character. - """ - if phone is None and not required: - return None - if not isinstance(phone, str) or not phone: - raise ValueError( - f'Invalid phone number: "{phone}". Phone number must be a non-empty string.') - if not phone.startswith('+') or not re.search('[a-zA-Z0-9]', phone): - raise ValueError( - f'Invalid phone number: "{phone}". Phone number must be a valid, E.164 ' - 'compliant identifier.') - return phone - -def validate_password(password, required=False): - if password is None and not required: - return None - if not isinstance(password, str) or len(password) < 6: - raise ValueError( - 'Invalid password string. Password must be a string at least 6 characters long.') - return password - -def validate_bytes(value, label, required=False): - if value is None and not required: - return None - if not isinstance(value, bytes) or not value: - raise ValueError(f'{label} must be a non-empty byte sequence.') - return value - -def validate_display_name(display_name, required=False): - if display_name is None and not required: - return None - if not isinstance(display_name, str) or not display_name: - raise ValueError( - f'Invalid display name: "{display_name}". Display name must be a non-empty ' - 'string.') - return display_name - -def validate_provider_id(provider_id, required=True): - if provider_id is None and not required: - return None - if not isinstance(provider_id, str) or not provider_id: - raise ValueError( - f'Invalid provider ID: "{provider_id}". Provider ID must be a non-empty string.') - return provider_id - -def validate_provider_uid(provider_uid, required=True): - if provider_uid is None and not required: - return None - if not isinstance(provider_uid, str) or not provider_uid: - raise ValueError( - f'Invalid provider UID: "{provider_uid}". Provider UID must be a non-empty string.') - return provider_uid - -def validate_photo_url(photo_url, required=False): - """Parses and validates the given URL string.""" - if photo_url is None and not required: - return None - if not isinstance(photo_url, str) or not photo_url: - raise ValueError( - f'Invalid photo URL: "{photo_url}". Photo URL must be a non-empty string.') - try: - parsed = parse.urlparse(photo_url) - if not parsed.netloc: - raise ValueError(f'Malformed photo URL: "{photo_url}".') - return photo_url - except Exception as err: - raise ValueError(f'Malformed photo URL: "{photo_url}".') from err - -def validate_timestamp(timestamp, label, required=False): - """Validates the given timestamp value. Timestamps must be positive integers.""" - if timestamp is None and not required: - return None - if isinstance(timestamp, bool): - raise ValueError('Boolean value specified as timestamp.') - try: - timestamp_int = int(timestamp) - except TypeError as err: - raise ValueError(f'Invalid type for timestamp value: {timestamp}.') from err - if timestamp_int != timestamp: - raise ValueError(f'{label} must be a numeric value and a whole number.') - if timestamp_int <= 0: - raise ValueError(f'{label} timestamp must be a positive interger.') - return timestamp_int - -def validate_int(value, label, low=None, high=None): - """Validates that the given value represents an integer. - - There are several ways to represent an integer in Python (e.g. 2, 2L, 2.0). This method allows - for all such representations except for booleans. Booleans also behave like integers, but - always translate to 1 and 0. Passing a boolean to an API that expects integers is most likely - a developer error. - """ - if value is None or isinstance(value, bool): - raise ValueError(f'Invalid type for integer value: {value}.') - try: - val_int = int(value) - except TypeError as err: - raise ValueError(f'Invalid type for integer value: {value}.') from err - if val_int != value: - # This will be True for non-numeric values like '2' and non-whole numbers like 2.5. - raise ValueError(f'{label} must be a numeric value and a whole number.') - if low is not None and val_int < low: - raise ValueError(f'{label} must not be smaller than {low}.') - if high is not None and val_int > high: - raise ValueError(f'{label} must not be larger than {high}.') - return val_int - -def validate_string(value, label): - """Validates that the given value is a string.""" - if not isinstance(value, str): - raise ValueError(f'Invalid type for {label}: {value}.') - return value - -def validate_boolean(value, label): - """Validates that the given value is a boolean.""" - if not isinstance(value, bool): - raise ValueError(f'Invalid type for {label}: {value}.') - return value - -def validate_custom_claims(custom_claims, required=False): - """Validates the specified custom claims. - - Custom claims must be specified as a JSON string. The string must not exceed 1000 - characters, and the parsed JSON payload must not contain reserved JWT claims. - """ - if custom_claims is None and not required: - return None - claims_str = str(custom_claims) - if len(claims_str) > MAX_CLAIMS_PAYLOAD_SIZE: - raise ValueError( - f'Custom claims payload must not exceed {MAX_CLAIMS_PAYLOAD_SIZE} characters.') - try: - parsed = json.loads(claims_str) - except Exception as err: - raise ValueError('Failed to parse custom claims string as JSON.') from err - - if not isinstance(parsed, dict): - raise ValueError('Custom claims must be parseable as a JSON object.') - invalid_claims = RESERVED_CLAIMS.intersection(set(parsed.keys())) - if len(invalid_claims) > 1: - joined = ', '.join(sorted(invalid_claims)) - raise ValueError(f'Claims "{joined}" are reserved, and must not be set.') - if len(invalid_claims) == 1: - raise ValueError( - f'Claim "{invalid_claims.pop()}" is reserved, and must not be set.') - return claims_str - -def validate_action_type(action_type): - if action_type not in VALID_EMAIL_ACTION_TYPES: - raise ValueError( - f'Invalid action type provided action_type: {action_type}. Valid values are ' - f'{", ".join(VALID_EMAIL_ACTION_TYPES)}') - return action_type - -def validate_provider_ids(provider_ids, required=False): - if not provider_ids: - if required: - raise ValueError('Invalid provider IDs. Provider ids should be provided') - return [] - for provider_id in provider_ids: - validate_provider_id(provider_id, True) - return provider_ids - -def build_update_mask(params): - """Creates an update mask list from the given dictionary.""" - mask = [] - for key, value in params.items(): - if isinstance(value, dict): - child_mask = build_update_mask(value) - for child in child_mask: - mask.append(f'{key}.{child}') - else: - mask.append(key) - - return sorted(mask) - - -class UidAlreadyExistsError(exceptions.AlreadyExistsError): - """The user with the provided uid already exists.""" - - default_message = 'The user with the provided uid already exists' - - def __init__(self, message, cause, http_response): - exceptions.AlreadyExistsError.__init__(self, message, cause, http_response) - - -class EmailAlreadyExistsError(exceptions.AlreadyExistsError): - """The user with the provided email already exists.""" - - default_message = 'The user with the provided email already exists' - - def __init__(self, message, cause, http_response): - exceptions.AlreadyExistsError.__init__(self, message, cause, http_response) - - -class InsufficientPermissionError(exceptions.PermissionDeniedError): - """The credential used to initialize the SDK lacks required permissions.""" - - default_message = ('The credential used to initialize the SDK has insufficient ' - 'permissions to perform the requested operation. See ' - 'https://firebase.google.com/docs/admin/setup for details ' - 'on how to initialize the Admin SDK with appropriate permissions') - - def __init__(self, message, cause, http_response): - exceptions.PermissionDeniedError.__init__(self, message, cause, http_response) - - -class InvalidDynamicLinkDomainError(exceptions.InvalidArgumentError): - """Dynamic link domain in ActionCodeSettings is not authorized.""" - - default_message = 'Dynamic link domain specified in ActionCodeSettings is not authorized' - - def __init__(self, message, cause, http_response): - exceptions.InvalidArgumentError.__init__(self, message, cause, http_response) - - -class InvalidHostingLinkDomainError(exceptions.InvalidArgumentError): - """The provided hosting link domain is not configured in Firebase Hosting - or is not owned by the current project.""" - - default_message = ('The provided hosting link domain is not configured in Firebase ' - 'Hosting or is not owned by the current project') - - def __init__(self, message, cause, http_response): - exceptions.InvalidArgumentError.__init__(self, message, cause, http_response) - - -class InvalidIdTokenError(exceptions.InvalidArgumentError): - """The provided ID token is not a valid Firebase ID token.""" - - default_message = 'The provided ID token is invalid' - - def __init__(self, message, cause=None, http_response=None): - exceptions.InvalidArgumentError.__init__(self, message, cause, http_response) - - -class PhoneNumberAlreadyExistsError(exceptions.AlreadyExistsError): - """The user with the provided phone number already exists.""" - - default_message = 'The user with the provided phone number already exists' - - def __init__(self, message, cause, http_response): - exceptions.AlreadyExistsError.__init__(self, message, cause, http_response) - - -class UnexpectedResponseError(exceptions.UnknownError): - """Backend service responded with an unexpected or malformed response.""" - - def __init__(self, message, cause=None, http_response=None): - exceptions.UnknownError.__init__(self, message, cause, http_response) - - -class UserNotFoundError(exceptions.NotFoundError): - """No user record found for the specified identifier.""" - - default_message = 'No user record found for the given identifier' - - def __init__(self, message, cause=None, http_response=None): - exceptions.NotFoundError.__init__(self, message, cause, http_response) - - -class EmailNotFoundError(exceptions.NotFoundError): - """No user record found for the specified email.""" - - default_message = 'No user record found for the given email' - - def __init__(self, message, cause=None, http_response=None): - exceptions.NotFoundError.__init__(self, message, cause, http_response) - - -class TenantNotFoundError(exceptions.NotFoundError): - """No tenant found for the specified identifier.""" - - default_message = 'No tenant found for the given identifier' - - def __init__(self, message, cause=None, http_response=None): - exceptions.NotFoundError.__init__(self, message, cause, http_response) - - -class TenantIdMismatchError(exceptions.InvalidArgumentError): - """Missing or invalid tenant ID field in the given JWT.""" - - def __init__(self, message): - exceptions.InvalidArgumentError.__init__(self, message) - - -class ConfigurationNotFoundError(exceptions.NotFoundError): - """No auth provider found for the specified identifier.""" - - default_message = 'No auth provider found for the given identifier' - - def __init__(self, message, cause=None, http_response=None): - exceptions.NotFoundError.__init__(self, message, cause, http_response) - - -class UserDisabledError(exceptions.InvalidArgumentError): - """An operation failed due to a user record being disabled.""" - - default_message = 'The user record is disabled' - - def __init__(self, message, cause=None, http_response=None): - exceptions.InvalidArgumentError.__init__(self, message, cause, http_response) - - -class TooManyAttemptsTryLaterError(exceptions.ResourceExhaustedError): - """Rate limited because of too many attempts.""" - - def __init__(self, message, cause=None, http_response=None): - exceptions.ResourceExhaustedError.__init__(self, message, cause, http_response) - - -class ResetPasswordExceedLimitError(exceptions.ResourceExhaustedError): - """Reset password emails exceeded their limits.""" - - def __init__(self, message, cause=None, http_response=None): - exceptions.ResourceExhaustedError.__init__(self, message, cause, http_response) - - -_CODE_TO_EXC_TYPE = { - 'CONFIGURATION_NOT_FOUND': ConfigurationNotFoundError, - 'DUPLICATE_EMAIL': EmailAlreadyExistsError, - 'DUPLICATE_LOCAL_ID': UidAlreadyExistsError, - 'EMAIL_EXISTS': EmailAlreadyExistsError, - 'EMAIL_NOT_FOUND': EmailNotFoundError, - 'INSUFFICIENT_PERMISSION': InsufficientPermissionError, - 'INVALID_DYNAMIC_LINK_DOMAIN': InvalidDynamicLinkDomainError, - 'INVALID_HOSTING_LINK_DOMAIN': InvalidHostingLinkDomainError, - 'INVALID_ID_TOKEN': InvalidIdTokenError, - 'PHONE_NUMBER_EXISTS': PhoneNumberAlreadyExistsError, - 'TENANT_NOT_FOUND': TenantNotFoundError, - 'USER_NOT_FOUND': UserNotFoundError, - 'TOO_MANY_ATTEMPTS_TRY_LATER': TooManyAttemptsTryLaterError, - 'RESET_PASSWORD_EXCEED_LIMIT': ResetPasswordExceedLimitError, -} - - -def handle_auth_backend_error(error): - """Converts a requests error received from the Firebase Auth service into a FirebaseError.""" - if error.response is None: - return _utils.handle_requests_error(error) - - code, custom_message = _parse_error_body(error.response) - if not code: - msg = f'Unexpected error response: {error.response.content.decode()}' - return _utils.handle_requests_error(error, message=msg) - - exc_type = _CODE_TO_EXC_TYPE.get(code) - msg = _build_error_message(code, exc_type, custom_message) - if not exc_type: - return _utils.handle_requests_error(error, message=msg) - - return exc_type(msg, cause=error, http_response=error.response) - - -def _parse_error_body(response): - """Parses the given error response to extract Auth error code and message.""" - error_dict = {} - try: - parsed_body = response.json() - if isinstance(parsed_body, dict): - error_dict = parsed_body.get('error', {}) - except ValueError: - pass - - # Auth error response format: {"error": {"message": "AUTH_ERROR_CODE: Optional text"}} - code = error_dict.get('message') if isinstance(error_dict, dict) else None - custom_message = None - if code: - separator = code.find(':') - if separator != -1: - custom_message = code[separator + 1:].strip() - code = code[:separator].strip() - - return code, custom_message - - -def _build_error_message(code, exc_type, custom_message): - default_message = exc_type.default_message if ( - exc_type and hasattr(exc_type, 'default_message')) else 'Error while calling Auth service' - ext = f' {custom_message}' if custom_message else '' - return f'{default_message} ({code}).{ext}' diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/_http_client.py b/notification-service/venv/Lib/site-packages/firebase_admin/_http_client.py deleted file mode 100644 index 6d25822..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/_http_client.py +++ /dev/null @@ -1,357 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Internal HTTP client module. - -This module provides utilities for making HTTP calls using the requests library. -""" - -from __future__ import annotations -import logging -from typing import Any, Dict, Generator, Optional, Tuple, Union -import httpx -import requests.adapters -from requests.packages.urllib3.util import retry # pylint: disable=import-error -from google.auth import credentials -from google.auth import transport -from google.auth.transport import requests as google_auth_requests - -from firebase_admin import _utils -from firebase_admin._retry import HttpxRetry, HttpxRetryTransport - -logger = logging.getLogger(__name__) - -if hasattr(retry.Retry.DEFAULT, 'allowed_methods'): - _ANY_METHOD = {'allowed_methods': None} -else: - _ANY_METHOD = {'method_whitelist': None} -# Default retry configuration: Retries once on low-level connection and socket read errors. -# Retries up to 4 times on HTTP 500 and 503 errors, with exponential backoff. Returns the -# last response upon exhausting all retries. -DEFAULT_RETRY_CONFIG = retry.Retry( - connect=1, read=1, status=4, status_forcelist=[500, 503], - raise_on_status=False, backoff_factor=0.5, **_ANY_METHOD) - -DEFAULT_HTTPX_RETRY_CONFIG = HttpxRetry( - max_retries=4, status_forcelist=[500, 503], backoff_factor=0.5) - - -DEFAULT_TIMEOUT_SECONDS = 120 - -METRICS_HEADERS = { - 'x-goog-api-client': _utils.get_metrics_header(), -} - -class HttpClient: - """Base HTTP client used to make HTTP calls. - - HttpClient maintains an HTTP session, and handles request authentication and retries if - necessary. - """ - - def __init__( - self, credential=None, session=None, base_url='', headers=None, - retries=DEFAULT_RETRY_CONFIG, timeout=DEFAULT_TIMEOUT_SECONDS): - """Creates a new HttpClient instance from the provided arguments. - - If a credential is provided, initializes a new HTTP session authorized with it. If neither - a credential nor a session is provided, initializes a new unauthorized session. - - Args: - credential: A Google credential that can be used to authenticate requests (optional). - session: A custom HTTP session (optional). - base_url: A URL prefix to be added to all outgoing requests (optional). - headers: A map of headers to be added to all outgoing requests (optional). - retries: A urllib retry configuration. Default settings would retry once for low-level - connection and socket read errors, and up to 4 times for HTTP 500 and 503 errors. - Pass a False value to disable retries (optional). - timeout: HTTP timeout in seconds. Defaults to 120 seconds when not specified. Set to - None to disable timeouts (optional). - """ - if credential: - self._session = transport.requests.AuthorizedSession(credential) - elif session: - self._session = session - else: - self._session = requests.Session() # pylint: disable=redefined-variable-type - - if headers: - self._session.headers.update(headers) - if retries: - self._session.mount('http://', requests.adapters.HTTPAdapter(max_retries=retries)) - self._session.mount('https://', requests.adapters.HTTPAdapter(max_retries=retries)) - self._base_url = base_url - self._timeout = timeout - - @property - def session(self): - return self._session - - @property - def base_url(self): - return self._base_url - - @property - def timeout(self): - return self._timeout - - def parse_body(self, resp): - raise NotImplementedError - - def request(self, method, url, **kwargs): - """Makes an HTTP call using the Python requests library. - - This is the sole entry point to the requests library. All other helper methods in this - class call this method to send HTTP requests out. Refer to - http://docs.python-requests.org/en/master/api/ for more information on supported options - and features. - - Args: - method: HTTP method name as a string (e.g. get, post). - url: URL of the remote endpoint. - **kwargs: An additional set of keyword arguments to be passed into the requests API - (e.g. json, params, timeout). - - Returns: - Response: An HTTP response object. - - Raises: - RequestException: Any requests exceptions encountered while making the HTTP call. - """ - if 'timeout' not in kwargs: - kwargs['timeout'] = self.timeout - kwargs.setdefault('headers', {}).update(METRICS_HEADERS) - resp = self._session.request(method, self.base_url + url, **kwargs) - resp.raise_for_status() - return resp - - def headers(self, method, url, **kwargs): - resp = self.request(method, url, **kwargs) - return resp.headers - - def body_and_response(self, method, url, **kwargs): - resp = self.request(method, url, **kwargs) - return self.parse_body(resp), resp - - def body(self, method, url, **kwargs): - resp = self.request(method, url, **kwargs) - return self.parse_body(resp) - - def headers_and_body(self, method, url, **kwargs): - resp = self.request(method, url, **kwargs) - return resp.headers, self.parse_body(resp) - - def close(self): - self._session.close() - self._session = None - -class JsonHttpClient(HttpClient): - """An HTTP client that parses response messages as JSON.""" - - def __init__(self, **kwargs): - HttpClient.__init__(self, **kwargs) - - def parse_body(self, resp): - return resp.json() - -class GoogleAuthCredentialFlow(httpx.Auth): - """Google Auth Credential Auth Flow""" - def __init__(self, credential: credentials.Credentials): - self._credential = credential - self._max_refresh_attempts = 2 - self._refresh_status_codes = (401,) - - def apply_auth_headers( - self, - request: httpx.Request, - auth_request: google_auth_requests.Request - ) -> None: - """A helper function that refreshes credentials if needed and mutates the request headers - to contain access token and any other Google Auth headers.""" - - logger.debug( - 'Attempting to apply auth headers. Credential validity before: %s', - self._credential.valid - ) - self._credential.before_request( - auth_request, request.method, str(request.url), request.headers - ) - logger.debug('Auth headers applied. Credential validity after: %s', self._credential.valid) - - def auth_flow(self, request: httpx.Request) -> Generator[httpx.Request, httpx.Response, None]: - _original_headers = request.headers.copy() - _credential_refresh_attempt = 0 - - # Create a Google auth request object to be used for refreshing credentials - auth_request = google_auth_requests.Request() - - while True: - # Copy original headers for each attempt - request.headers = _original_headers.copy() - - # Apply auth headers (which might include an implicit refresh if token is expired) - self.apply_auth_headers(request, auth_request) - - logger.debug( - 'Dispatching request, attempt %d of %d', - _credential_refresh_attempt, self._max_refresh_attempts - ) - response: httpx.Response = yield request - - if response.status_code in self._refresh_status_codes: - if _credential_refresh_attempt < self._max_refresh_attempts: - logger.debug( - 'Received status %d. Attempting explicit credential refresh. \ - Attempt %d of %d.', - response.status_code, - _credential_refresh_attempt + 1, - self._max_refresh_attempts - ) - # Explicitly force a credentials refresh - self._credential.refresh(auth_request) - _credential_refresh_attempt += 1 - else: - logger.debug( - 'Received status %d, but max auth refresh attempts (%d) reached. \ - Returning last response.', - response.status_code, self._max_refresh_attempts - ) - break - else: - # Status code is not one that requires a refresh, so break and return response - logger.debug( - 'Status code %d does not require refresh. Returning response.', - response.status_code - ) - break - # The last yielded response is automatically returned by httpx's auth flow. - -class HttpxAsyncClient(): - """Async HTTP client used to make HTTP/2 calls using HTTPX. - - HttpxAsyncClient maintains an async HTTPX client, handles request authentication, and retries - if necessary. - """ - def __init__( - self, - credential: Optional[credentials.Credentials] = None, - base_url: str = '', - headers: Optional[Union[httpx.Headers, Dict[str, str]]] = None, - retry_config: HttpxRetry = DEFAULT_HTTPX_RETRY_CONFIG, - timeout: int = DEFAULT_TIMEOUT_SECONDS, - http2: bool = True - ) -> None: - """Creates a new HttpxAsyncClient instance from the provided arguments. - - If a credential is provided, initializes a new async HTTPX client authorized with it. - Otherwise, initializes a new unauthorized async HTTPX client. - - Args: - credential: A Google credential that can be used to authenticate requests (optional). - base_url: A URL prefix to be added to all outgoing requests (optional). - headers: A map of headers to be added to all outgoing requests (optional). - retry_config: A HttpxRetry configuration. Default settings would retry up to 4 times for - HTTP 500 and 503 errors (optional). - timeout: HTTP timeout in seconds. Defaults to 120 seconds when not specified (optional). - http2: A boolean indicating if HTTP/2 support should be enabled. Defaults to `True` when - not specified (optional). - """ - self._base_url = base_url - self._timeout = timeout - self._headers = {**headers, **METRICS_HEADERS} if headers else {**METRICS_HEADERS} - self._retry_config = retry_config - - # Only set up retries on urls starting with 'http://' and 'https://' - self._mounts = { - 'http://': HttpxRetryTransport(retry=self._retry_config, http2=http2), - 'https://': HttpxRetryTransport(retry=self._retry_config, http2=http2) - } - - if credential: - self._async_client = httpx.AsyncClient( - http2=http2, - timeout=self._timeout, - headers=self._headers, - auth=GoogleAuthCredentialFlow(credential), # Add auth flow for credentials. - mounts=self._mounts - ) - else: - self._async_client = httpx.AsyncClient( - http2=http2, - timeout=self._timeout, - headers=self._headers, - mounts=self._mounts - ) - - @property - def base_url(self): - return self._base_url - - @property - def timeout(self): - return self._timeout - - @property - def async_client(self): - return self._async_client - - async def request(self, method: str, url: str, **kwargs: Any) -> httpx.Response: - """Makes an HTTP call using the HTTPX library. - - This is the sole entry point to the HTTPX library. All other helper methods in this - class call this method to send HTTP requests out. Refer to - https://www.python-httpx.org/api/ for more information on supported options - and features. - - Args: - method: HTTP method name as a string (e.g. get, post). - url: URL of the remote endpoint. - **kwargs: An additional set of keyword arguments to be passed into the HTTPX API - (e.g. json, params, timeout). - - Returns: - Response: An HTTPX response object. - - Raises: - HTTPError: Any HTTPX exceptions encountered while making the HTTP call. - RequestException: Any requests exceptions encountered while making the HTTP call. - """ - if 'timeout' not in kwargs: - kwargs['timeout'] = self.timeout - resp = await self._async_client.request(method, self.base_url + url, **kwargs) - return resp.raise_for_status() - - async def headers(self, method: str, url: str, **kwargs: Any) -> httpx.Headers: - resp = await self.request(method, url, **kwargs) - return resp.headers - - async def body_and_response( - self, method: str, url: str, **kwargs: Any) -> Tuple[Any, httpx.Response]: - resp = await self.request(method, url, **kwargs) - return self.parse_body(resp), resp - - async def body(self, method: str, url: str, **kwargs: Any) -> Any: - resp = await self.request(method, url, **kwargs) - return self.parse_body(resp) - - async def headers_and_body( - self, method: str, url: str, **kwargs: Any) -> Tuple[httpx.Headers, Any]: - resp = await self.request(method, url, **kwargs) - return resp.headers, self.parse_body(resp) - - def parse_body(self, resp: httpx.Response) -> Any: - return resp.json() - - async def aclose(self) -> None: - await self._async_client.aclose() diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/_messaging_encoder.py b/notification-service/venv/Lib/site-packages/firebase_admin/_messaging_encoder.py deleted file mode 100644 index 4c0c6da..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/_messaging_encoder.py +++ /dev/null @@ -1,722 +0,0 @@ -# Copyright 2019 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Encoding and validation utils for the messaging (FCM) module.""" - -import datetime -import json -import math -import numbers -import re - -from firebase_admin import _messaging_utils - - -class Message: - """A message that can be sent via Firebase Cloud Messaging. - - Contains payload information as well as recipient information. In particular, the message must - contain exactly one of token, topic or condition fields. - - Args: - data: A dictionary of data fields (optional). All keys and values in the dictionary must be - strings. - notification: An instance of ``messaging.Notification`` (optional). - android: An instance of ``messaging.AndroidConfig`` (optional). - webpush: An instance of ``messaging.WebpushConfig`` (optional). - apns: An instance of ``messaging.ApnsConfig`` (optional). - fcm_options: An instance of ``messaging.FCMOptions`` (optional). - token: The registration token of the device to which the message should be sent (optional). - topic: Name of the FCM topic to which the message should be sent (optional). Topic name - may contain the ``/topics/`` prefix. - condition: The FCM condition to which the message should be sent (optional). - """ - - def __init__(self, data=None, notification=None, android=None, webpush=None, apns=None, - fcm_options=None, token=None, topic=None, condition=None): - self.data = data - self.notification = notification - self.android = android - self.webpush = webpush - self.apns = apns - self.fcm_options = fcm_options - self.token = token - self.topic = topic - self.condition = condition - - def __str__(self): - return json.dumps(self, cls=MessageEncoder, sort_keys=True) - - -class MulticastMessage: - """A message that can be sent to multiple tokens via Firebase Cloud Messaging. - - Args: - tokens: A list of registration tokens of targeted devices. - data: A dictionary of data fields (optional). All keys and values in the dictionary must be - strings. - notification: An instance of ``messaging.Notification`` (optional). - android: An instance of ``messaging.AndroidConfig`` (optional). - webpush: An instance of ``messaging.WebpushConfig`` (optional). - apns: An instance of ``messaging.ApnsConfig`` (optional). - fcm_options: An instance of ``messaging.FCMOptions`` (optional). - """ - def __init__(self, tokens, data=None, notification=None, android=None, webpush=None, apns=None, - fcm_options=None): - _Validators.check_string_list('MulticastMessage.tokens', tokens) - if len(tokens) > 500: - raise ValueError('MulticastMessage.tokens must not contain more than 500 tokens.') - self.tokens = tokens - self.data = data - self.notification = notification - self.android = android - self.webpush = webpush - self.apns = apns - self.fcm_options = fcm_options - - -class _Validators: - """A collection of data validation utilities. - - Methods provided in this class raise ``ValueErrors`` if any validations fail. - """ - - @classmethod - def check_string(cls, label, value, non_empty=False): - """Checks if the given value is a string.""" - if value is None: - return None - if not isinstance(value, str): - if non_empty: - raise ValueError(f'{label} must be a non-empty string.') - raise ValueError(f'{label} must be a string.') - if non_empty and not value: - raise ValueError(f'{label} must be a non-empty string.') - return value - - @classmethod - def check_number(cls, label, value): - if value is None: - return None - if not isinstance(value, numbers.Number): - raise ValueError(f'{label} must be a number.') - return value - - @classmethod - def check_string_dict(cls, label, value): - """Checks if the given value is a dictionary comprised only of string keys and values.""" - if value is None or value == {}: - return None - if not isinstance(value, dict): - raise ValueError(f'{label} must be a dictionary.') - non_str = [k for k in value if not isinstance(k, str)] - if non_str: - raise ValueError(f'{label} must not contain non-string keys.') - non_str = [v for v in value.values() if not isinstance(v, str)] - if non_str: - raise ValueError(f'{label} must not contain non-string values.') - return value - - @classmethod - def check_string_list(cls, label, value): - """Checks if the given value is a list comprised only of strings.""" - if value is None or value == []: - return None - if not isinstance(value, list): - raise ValueError(f'{label} must be a list of strings.') - non_str = [k for k in value if not isinstance(k, str)] - if non_str: - raise ValueError(f'{label} must not contain non-string values.') - return value - - @classmethod - def check_number_list(cls, label, value): - """Checks if the given value is a list comprised only of numbers.""" - if value is None or value == []: - return None - if not isinstance(value, list): - raise ValueError(f'{label} must be a list of numbers.') - non_number = [k for k in value if not isinstance(k, numbers.Number)] - if non_number: - raise ValueError(f'{label} must not contain non-number values.') - return value - - @classmethod - def check_analytics_label(cls, label, value): - """Checks if the given value is a valid analytics label.""" - value = _Validators.check_string(label, value) - if value is not None and not re.match(r'^[a-zA-Z0-9-_.~%]{1,50}$', value): - raise ValueError(f'Malformed {label}.') - return value - - @classmethod - def check_boolean(cls, label, value): - """Checks if the given value is boolean.""" - if value is None: - return None - if not isinstance(value, bool): - raise ValueError(f'{label} must be a boolean.') - return value - - @classmethod - def check_datetime(cls, label, value): - """Checks if the given value is a datetime.""" - if value is None: - return None - if not isinstance(value, datetime.datetime): - raise ValueError(f'{label} must be a datetime.') - return value - - -class MessageEncoder(json.JSONEncoder): - """A custom ``JSONEncoder`` implementation for serializing Message instances into JSON.""" - - @classmethod - def remove_null_values(cls, dict_value): - return {k: v for k, v in dict_value.items() if v not in [None, [], {}]} - - @classmethod - def encode_android(cls, android): - """Encodes an ``AndroidConfig`` instance into JSON.""" - if android is None: - return None - if not isinstance(android, _messaging_utils.AndroidConfig): - raise ValueError('Message.android must be an instance of AndroidConfig class.') - result = { - 'collapse_key': _Validators.check_string( - 'AndroidConfig.collapse_key', android.collapse_key), - 'data': _Validators.check_string_dict( - 'AndroidConfig.data', android.data), - 'notification': cls.encode_android_notification(android.notification), - 'priority': _Validators.check_string( - 'AndroidConfig.priority', android.priority, non_empty=True), - 'restricted_package_name': _Validators.check_string( - 'AndroidConfig.restricted_package_name', android.restricted_package_name), - 'ttl': cls.encode_ttl(android.ttl), - 'fcm_options': cls.encode_android_fcm_options(android.fcm_options), - 'direct_boot_ok': _Validators.check_boolean( - 'AndroidConfig.direct_boot_ok', android.direct_boot_ok), - 'bandwidth_constrained_ok': _Validators.check_boolean( - 'AndroidConfig.bandwidth_constrained_ok', android.bandwidth_constrained_ok), - 'restricted_satellite_ok': _Validators.check_boolean( - 'AndroidConfig.restricted_satellite_ok', android.restricted_satellite_ok), - } - result = cls.remove_null_values(result) - priority = result.get('priority') - if priority and priority not in ('high', 'normal'): - raise ValueError('AndroidConfig.priority must be "high" or "normal".') - return result - - @classmethod - def encode_android_fcm_options(cls, fcm_options): - """Encodes an ``AndroidFCMOptions`` instance into JSON.""" - if fcm_options is None: - return None - if not isinstance(fcm_options, _messaging_utils.AndroidFCMOptions): - raise ValueError('AndroidConfig.fcm_options must be an instance of ' - 'AndroidFCMOptions class.') - result = { - 'analytics_label': _Validators.check_analytics_label( - 'AndroidFCMOptions.analytics_label', fcm_options.analytics_label), - } - result = cls.remove_null_values(result) - return result - - @classmethod - def encode_ttl(cls, ttl): - """Encodes an ``AndroidConfig`` ``TTL`` duration into a string.""" - if ttl is None: - return None - if isinstance(ttl, numbers.Number): - ttl = datetime.timedelta(seconds=ttl) - if not isinstance(ttl, datetime.timedelta): - raise ValueError('AndroidConfig.ttl must be a duration in seconds or an instance of ' - 'datetime.timedelta.') - total_seconds = ttl.total_seconds() - if total_seconds < 0: - raise ValueError('AndroidConfig.ttl must not be negative.') - seconds = int(math.floor(total_seconds)) - nanos = int((total_seconds - seconds) * 1e9) - if nanos: - return f'{seconds}.{str(nanos).zfill(9)}s' - return f'{seconds}s' - - @classmethod - def encode_milliseconds(cls, label, msec): - """Encodes a duration in milliseconds into a string.""" - if msec is None: - return None - if isinstance(msec, numbers.Number): - msec = datetime.timedelta(milliseconds=msec) - if not isinstance(msec, datetime.timedelta): - raise ValueError( - f'{label} must be a duration in milliseconds or an instance of datetime.timedelta.') - total_seconds = msec.total_seconds() - if total_seconds < 0: - raise ValueError(f'{label} must not be negative.') - seconds = int(math.floor(total_seconds)) - nanos = int((total_seconds - seconds) * 1e9) - if nanos: - return f'{seconds}.{str(nanos).zfill(9)}s' - return f'{seconds}s' - - @classmethod - def encode_android_notification(cls, notification): - """Encodes an ``AndroidNotification`` instance into JSON.""" - if notification is None: - return None - if not isinstance(notification, _messaging_utils.AndroidNotification): - raise ValueError('AndroidConfig.notification must be an instance of ' - 'AndroidNotification class.') - result = { - 'body': _Validators.check_string( - 'AndroidNotification.body', notification.body), - 'body_loc_args': _Validators.check_string_list( - 'AndroidNotification.body_loc_args', notification.body_loc_args), - 'body_loc_key': _Validators.check_string( - 'AndroidNotification.body_loc_key', notification.body_loc_key), - 'click_action': _Validators.check_string( - 'AndroidNotification.click_action', notification.click_action), - 'color': _Validators.check_string( - 'AndroidNotification.color', notification.color, non_empty=True), - 'icon': _Validators.check_string( - 'AndroidNotification.icon', notification.icon), - 'sound': _Validators.check_string( - 'AndroidNotification.sound', notification.sound), - 'tag': _Validators.check_string( - 'AndroidNotification.tag', notification.tag), - 'title': _Validators.check_string( - 'AndroidNotification.title', notification.title), - 'title_loc_args': _Validators.check_string_list( - 'AndroidNotification.title_loc_args', notification.title_loc_args), - 'title_loc_key': _Validators.check_string( - 'AndroidNotification.title_loc_key', notification.title_loc_key), - 'channel_id': _Validators.check_string( - 'AndroidNotification.channel_id', notification.channel_id), - 'image': _Validators.check_string( - 'image', notification.image), - 'ticker': _Validators.check_string( - 'AndroidNotification.ticker', notification.ticker), - 'sticky': notification.sticky, - 'event_time': _Validators.check_datetime( - 'AndroidNotification.event_timestamp', notification.event_timestamp), - 'local_only': notification.local_only, - 'notification_priority': _Validators.check_string( - 'AndroidNotification.priority', notification.priority, non_empty=True), - 'vibrate_timings': _Validators.check_number_list( - 'AndroidNotification.vibrate_timings_millis', notification.vibrate_timings_millis), - 'default_vibrate_timings': notification.default_vibrate_timings, - 'default_sound': notification.default_sound, - 'default_light_settings': notification.default_light_settings, - 'light_settings': cls.encode_light_settings(notification.light_settings), - 'visibility': _Validators.check_string( - 'AndroidNotification.visibility', notification.visibility, non_empty=True), - 'notification_count': _Validators.check_number( - 'AndroidNotification.notification_count', notification.notification_count), - 'proxy': _Validators.check_string( - 'AndroidNotification.proxy', notification.proxy, non_empty=True) - } - result = cls.remove_null_values(result) - color = result.get('color') - if color and not re.match(r'^#[0-9a-fA-F]{6}$', color): - raise ValueError( - 'AndroidNotification.color must be in the form #RRGGBB.') - if result.get('body_loc_args') and not result.get('body_loc_key'): - raise ValueError( - 'AndroidNotification.body_loc_key is required when specifying body_loc_args.') - if result.get('title_loc_args') and not result.get('title_loc_key'): - raise ValueError( - 'AndroidNotification.title_loc_key is required when specifying title_loc_args.') - - event_time = result.get('event_time') - if event_time: - # if the datetime instance is not naive (tzinfo is present), convert to UTC - # otherwise (tzinfo is None) assume the datetime instance is already in UTC - if event_time.tzinfo is not None: - event_time = event_time.astimezone(datetime.timezone.utc) - result['event_time'] = event_time.strftime('%Y-%m-%dT%H:%M:%S.%fZ') - - priority = result.get('notification_priority') - if priority: - if priority not in ('min', 'low', 'default', 'high', 'max'): - raise ValueError('AndroidNotification.priority must be "default", "min", "low", ' - '"high" or "max".') - result['notification_priority'] = 'PRIORITY_' + priority.upper() - - visibility = result.get('visibility') - if visibility: - if visibility not in ('private', 'public', 'secret'): - raise ValueError( - 'AndroidNotification.visibility must be "private", "public" or "secret".') - result['visibility'] = visibility.upper() - - vibrate_timings_millis = result.get('vibrate_timings') - if vibrate_timings_millis: - vibrate_timing_strings = [] - for msec in vibrate_timings_millis: - formated_string = cls.encode_milliseconds( - 'AndroidNotification.vibrate_timings_millis', msec) - vibrate_timing_strings.append(formated_string) - result['vibrate_timings'] = vibrate_timing_strings - - proxy = result.get('proxy') - if proxy: - if proxy not in ('allow', 'deny', 'if_priority_lowered'): - raise ValueError( - 'AndroidNotification.proxy must be "allow", "deny" or "if_priority_lowered".') - result['proxy'] = proxy.upper() - return result - - @classmethod - def encode_light_settings(cls, light_settings): - """Encodes a ``LightSettings`` instance into JSON.""" - if light_settings is None: - return None - if not isinstance(light_settings, _messaging_utils.LightSettings): - raise ValueError( - 'AndroidNotification.light_settings must be an instance of LightSettings class.') - result = { - 'color': _Validators.check_string( - 'LightSettings.color', light_settings.color, non_empty=True), - 'light_on_duration': cls.encode_milliseconds( - 'LightSettings.light_on_duration_millis', light_settings.light_on_duration_millis), - 'light_off_duration': cls.encode_milliseconds( - 'LightSettings.light_off_duration_millis', - light_settings.light_off_duration_millis), - } - result = cls.remove_null_values(result) - light_on_duration = result.get('light_on_duration') - if not light_on_duration: - raise ValueError( - 'LightSettings.light_on_duration_millis is required.') - - light_off_duration = result.get('light_off_duration') - if not light_off_duration: - raise ValueError( - 'LightSettings.light_off_duration_millis is required.') - - color = result.get('color') - if not color: - raise ValueError('LightSettings.color is required.') - if not re.match(r'^#[0-9a-fA-F]{6}$', color) and not re.match(r'^#[0-9a-fA-F]{8}$', color): - raise ValueError( - 'LightSettings.color must be in the form #RRGGBB or #RRGGBBAA.') - if len(color) == 7: - color = color+'FF' - rgba = [int(color[i:i + 2], 16) / 255.0 for i in (1, 3, 5, 7)] - result['color'] = {'red': rgba[0], 'green': rgba[1], - 'blue': rgba[2], 'alpha': rgba[3]} - return result - - @classmethod - def encode_webpush(cls, webpush): - """Encodes a ``WebpushConfig`` instance into JSON.""" - if webpush is None: - return None - if not isinstance(webpush, _messaging_utils.WebpushConfig): - raise ValueError('Message.webpush must be an instance of WebpushConfig class.') - result = { - 'data': _Validators.check_string_dict( - 'WebpushConfig.data', webpush.data), - 'headers': _Validators.check_string_dict( - 'WebpushConfig.headers', webpush.headers), - 'notification': cls.encode_webpush_notification(webpush.notification), - 'fcm_options': cls.encode_webpush_fcm_options(webpush.fcm_options), - } - return cls.remove_null_values(result) - - @classmethod - def encode_webpush_notification(cls, notification): - """Encodes a ``WebpushNotification`` instance into JSON.""" - if notification is None: - return None - if not isinstance(notification, _messaging_utils.WebpushNotification): - raise ValueError('WebpushConfig.notification must be an instance of ' - 'WebpushNotification class.') - result = { - 'actions': cls.encode_webpush_notification_actions(notification.actions), - 'badge': _Validators.check_string( - 'WebpushNotification.badge', notification.badge), - 'body': _Validators.check_string( - 'WebpushNotification.body', notification.body), - 'data': notification.data, - 'dir': _Validators.check_string( - 'WebpushNotification.direction', notification.direction), - 'icon': _Validators.check_string( - 'WebpushNotification.icon', notification.icon), - 'image': _Validators.check_string( - 'WebpushNotification.image', notification.image), - 'lang': _Validators.check_string( - 'WebpushNotification.language', notification.language), - 'renotify': notification.renotify, - 'requireInteraction': notification.require_interaction, - 'silent': notification.silent, - 'tag': _Validators.check_string( - 'WebpushNotification.tag', notification.tag), - 'timestamp': _Validators.check_number( - 'WebpushNotification.timestamp_millis', notification.timestamp_millis), - 'title': _Validators.check_string( - 'WebpushNotification.title', notification.title), - 'vibrate': notification.vibrate, - } - direction = result.get('dir') - if direction and direction not in ('auto', 'ltr', 'rtl'): - raise ValueError('WebpushNotification.direction must be "auto", "ltr" or "rtl".') - if notification.custom_data is not None: - if not isinstance(notification.custom_data, dict): - raise ValueError('WebpushNotification.custom_data must be a dict.') - for key, value in notification.custom_data.items(): - if key in result: - raise ValueError( - f'Multiple specifications for {key} in WebpushNotification.') - result[key] = value - return cls.remove_null_values(result) - - @classmethod - def encode_webpush_notification_actions(cls, actions): - """Encodes a list of ``WebpushNotificationActions`` into JSON.""" - if actions is None: - return None - if not isinstance(actions, list): - raise ValueError('WebpushConfig.notification.actions must be a list of ' - 'WebpushNotificationAction instances.') - results = [] - for action in actions: - if not isinstance(action, _messaging_utils.WebpushNotificationAction): - raise ValueError('WebpushConfig.notification.actions must be a list of ' - 'WebpushNotificationAction instances.') - result = { - 'action': _Validators.check_string( - 'WebpushNotificationAction.action', action.action), - 'title': _Validators.check_string( - 'WebpushNotificationAction.title', action.title), - 'icon': _Validators.check_string( - 'WebpushNotificationAction.icon', action.icon), - } - results.append(cls.remove_null_values(result)) - return results - - @classmethod - def encode_webpush_fcm_options(cls, options): - """Encodes a ``WebpushFCMOptions`` instance into JSON.""" - if options is None: - return None - result = { - 'link': _Validators.check_string('WebpushConfig.fcm_options.link', options.link), - } - result = cls.remove_null_values(result) - link = result.get('link') - if link is not None and not link.startswith('https://'): - raise ValueError('WebpushFCMOptions.link must be a HTTPS URL.') - return result - - @classmethod - def encode_apns(cls, apns): - """Encodes an ``APNSConfig`` instance into JSON.""" - if apns is None: - return None - if not isinstance(apns, _messaging_utils.APNSConfig): - raise ValueError('Message.apns must be an instance of APNSConfig class.') - result = { - 'headers': _Validators.check_string_dict( - 'APNSConfig.headers', apns.headers), - 'payload': cls.encode_apns_payload(apns.payload), - 'fcm_options': cls.encode_apns_fcm_options(apns.fcm_options), - 'live_activity_token': _Validators.check_string( - 'APNSConfig.live_activity_token', apns.live_activity_token), - } - return cls.remove_null_values(result) - - @classmethod - def encode_apns_payload(cls, payload): - """Encodes an ``APNSPayload`` instance into JSON.""" - if payload is None: - return None - if not isinstance(payload, _messaging_utils.APNSPayload): - raise ValueError('APNSConfig.payload must be an instance of APNSPayload class.') - result = { - 'aps': cls.encode_aps(payload.aps) - } - for key, value in payload.custom_data.items(): - result[key] = value - return cls.remove_null_values(result) - - @classmethod - def encode_apns_fcm_options(cls, fcm_options): - """Encodes an ``APNSFCMOptions`` instance into JSON.""" - if fcm_options is None: - return None - if not isinstance(fcm_options, _messaging_utils.APNSFCMOptions): - raise ValueError('APNSConfig.fcm_options must be an instance of APNSFCMOptions class.') - result = { - 'analytics_label': _Validators.check_analytics_label( - 'APNSFCMOptions.analytics_label', fcm_options.analytics_label), - 'image': _Validators.check_string('APNSFCMOptions.image', fcm_options.image) - } - result = cls.remove_null_values(result) - return result - - @classmethod - def encode_aps(cls, aps): - """Encodes an ``Aps`` instance into JSON.""" - if not isinstance(aps, _messaging_utils.Aps): - raise ValueError('APNSPayload.aps must be an instance of Aps class.') - result = { - 'alert': cls.encode_aps_alert(aps.alert), - 'badge': _Validators.check_number('Aps.badge', aps.badge), - 'sound': cls.encode_aps_sound(aps.sound), - 'category': _Validators.check_string('Aps.category', aps.category), - 'thread-id': _Validators.check_string('Aps.thread_id', aps.thread_id), - } - if aps.content_available is True: - result['content-available'] = 1 - if aps.mutable_content is True: - result['mutable-content'] = 1 - if aps.custom_data is not None: - if not isinstance(aps.custom_data, dict): - raise ValueError('Aps.custom_data must be a dict.') - for key, val in aps.custom_data.items(): - _Validators.check_string('Aps.custom_data key', key) - if key in result: - raise ValueError(f'Multiple specifications for {key} in Aps.') - result[key] = val - return cls.remove_null_values(result) - - @classmethod - def encode_aps_sound(cls, sound): - """Encodes an APNs sound configuration into JSON.""" - if sound is None: - return None - if sound and isinstance(sound, str): - return sound - if not isinstance(sound, _messaging_utils.CriticalSound): - raise ValueError( - 'Aps.sound must be a non-empty string or an instance of CriticalSound class.') - result = { - 'name': _Validators.check_string('CriticalSound.name', sound.name, non_empty=True), - 'volume': _Validators.check_number('CriticalSound.volume', sound.volume), - } - if sound.critical: - result['critical'] = 1 - if not result['name']: - raise ValueError('CriticalSond.name must be a non-empty string.') - volume = result['volume'] - if volume is not None and (volume < 0 or volume > 1): - raise ValueError('CriticalSound.volume must be in the interval [0,1].') - return cls.remove_null_values(result) - - @classmethod - def encode_aps_alert(cls, alert): - """Encodes an ``ApsAlert`` instance into JSON.""" - if alert is None: - return None - if isinstance(alert, str): - return alert - if not isinstance(alert, _messaging_utils.ApsAlert): - raise ValueError('Aps.alert must be a string or an instance of ApsAlert class.') - result = { - 'title': _Validators.check_string('ApsAlert.title', alert.title), - 'subtitle': _Validators.check_string('ApsAlert.subtitle', alert.subtitle), - 'body': _Validators.check_string('ApsAlert.body', alert.body), - 'title-loc-key': _Validators.check_string( - 'ApsAlert.title_loc_key', alert.title_loc_key), - 'title-loc-args': _Validators.check_string_list( - 'ApsAlert.title_loc_args', alert.title_loc_args), - 'loc-key': _Validators.check_string( - 'ApsAlert.loc_key', alert.loc_key), - 'loc-args': _Validators.check_string_list( - 'ApsAlert.loc_args', alert.loc_args), - 'action-loc-key': _Validators.check_string( - 'ApsAlert.action_loc_key', alert.action_loc_key), - 'launch-image': _Validators.check_string( - 'ApsAlert.launch_image', alert.launch_image), - } - if result.get('loc-args') and not result.get('loc-key'): - raise ValueError( - 'ApsAlert.loc_key is required when specifying loc_args.') - if result.get('title-loc-args') and not result.get('title-loc-key'): - raise ValueError( - 'ApsAlert.title_loc_key is required when specifying title_loc_args.') - if alert.custom_data is not None: - if not isinstance(alert.custom_data, dict): - raise ValueError('ApsAlert.custom_data must be a dict.') - for key, val in alert.custom_data.items(): - _Validators.check_string('ApsAlert.custom_data key', key) - # allow specifying key override because Apple could update API so that key - # could have unexpected value type - result[key] = val - return cls.remove_null_values(result) - - @classmethod - def encode_notification(cls, notification): - """Encodes a ``Notification`` instance into JSON.""" - if notification is None: - return None - if not isinstance(notification, _messaging_utils.Notification): - raise ValueError('Message.notification must be an instance of Notification class.') - result = { - 'body': _Validators.check_string('Notification.body', notification.body), - 'title': _Validators.check_string('Notification.title', notification.title), - 'image': _Validators.check_string('Notification.image', notification.image) - } - return cls.remove_null_values(result) - - @classmethod - def sanitize_topic_name(cls, topic): - """Removes the /topics/ prefix from the topic name, if present.""" - if not topic: - return None - prefix = '/topics/' - if topic.startswith(prefix): - topic = topic[len(prefix):] - # Checks for illegal characters and empty string. - if not re.match(r'^[a-zA-Z0-9-_\.~%]+$', topic): - raise ValueError('Malformed topic name.') - return topic - - def default(self, o): # pylint: disable=method-hidden - if not isinstance(o, Message): - return json.JSONEncoder.default(self, o) - result = { - 'android': MessageEncoder.encode_android(o.android), - 'apns': MessageEncoder.encode_apns(o.apns), - 'condition': _Validators.check_string( - 'Message.condition', o.condition, non_empty=True), - 'data': _Validators.check_string_dict('Message.data', o.data), - 'notification': MessageEncoder.encode_notification(o.notification), - 'token': _Validators.check_string('Message.token', o.token, non_empty=True), - 'topic': _Validators.check_string('Message.topic', o.topic, non_empty=True), - 'webpush': MessageEncoder.encode_webpush(o.webpush), - 'fcm_options': MessageEncoder.encode_fcm_options(o.fcm_options), - } - result['topic'] = MessageEncoder.sanitize_topic_name(result.get('topic')) - result = MessageEncoder.remove_null_values(result) - target_count = sum(t in result for t in ['token', 'topic', 'condition']) - if target_count != 1: - raise ValueError('Exactly one of token, topic or condition must be specified.') - return result - - @classmethod - def encode_fcm_options(cls, fcm_options): - """Encodes an ``FCMOptions`` instance into JSON.""" - if fcm_options is None: - return None - if not isinstance(fcm_options, _messaging_utils.FCMOptions): - raise ValueError('Message.fcm_options must be an instance of FCMOptions class.') - result = { - 'analytics_label': _Validators.check_analytics_label( - 'FCMOptions.analytics_label', fcm_options.analytics_label), - } - result = cls.remove_null_values(result) - return result diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/_messaging_utils.py b/notification-service/venv/Lib/site-packages/firebase_admin/_messaging_utils.py deleted file mode 100644 index 773ed60..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/_messaging_utils.py +++ /dev/null @@ -1,525 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Types and utilities used by the messaging (FCM) module.""" -from __future__ import annotations -import datetime -from typing import Dict, Optional, Union - -from firebase_admin import exceptions - - -class Notification: - """A notification that can be included in a message. - - Args: - title: Title of the notification (optional). - body: Body of the notification (optional). - image: Image url of the notification (optional) - """ - - def __init__(self, title=None, body=None, image=None): - self.title = title - self.body = body - self.image = image - - -class AndroidConfig: - """Android-specific options that can be included in a message. - - Args: - collapse_key: Collapse key string for the message (optional). This is an identifier for a - group of messages that can be collapsed, so that only the last message is sent when - delivery can be resumed. A maximum of 4 different collapse keys may be active at a - given time. - priority: Priority of the message (optional). Must be one of ``high`` or ``normal``. - ttl: The time-to-live duration of the message (optional). This can be specified - as a numeric seconds value or a ``datetime.timedelta`` instance. - restricted_package_name: The package name of the application where the registration tokens - must match in order to receive the message (optional). - data: A dictionary of data fields (optional). All keys and values in the dictionary must be - strings. When specified, overrides any data fields set via ``Message.data``. - notification: A ``messaging.AndroidNotification`` to be included in the message (optional). - fcm_options: A ``messaging.AndroidFCMOptions`` to be included in the message (optional). - direct_boot_ok: A boolean indicating whether messages will be allowed to be delivered to - the app while the device is in direct boot mode (optional). - bandwidth_constrained_ok: A boolean indicating whether messages will be allowed to be - delivered to the app while the device is on a bandwidth constrained network (optional). - restricted_satellite_ok: A boolean indicating whether messages will be allowed to be - delivered to the app while the device is on a restricted satellite network (optional). - """ - - def __init__( - self, - collapse_key: Optional[str] = None, - priority: Optional[str] = None, - ttl: Optional[Union[int, float, datetime.timedelta]] = None, - restricted_package_name: Optional[str] = None, - data: Optional[Dict[str, str]] = None, - notification: Optional[AndroidNotification] = None, - fcm_options: Optional[AndroidFCMOptions] = None, - direct_boot_ok: Optional[bool] = None, - bandwidth_constrained_ok: Optional[bool] = None, - restricted_satellite_ok: Optional[bool] = None - ): - self.collapse_key = collapse_key - self.priority = priority - self.ttl = ttl - self.restricted_package_name = restricted_package_name - self.data = data - self.notification = notification - self.fcm_options = fcm_options - self.direct_boot_ok = direct_boot_ok - self.bandwidth_constrained_ok = bandwidth_constrained_ok - self.restricted_satellite_ok = restricted_satellite_ok - - -class AndroidNotification: - """Android-specific notification parameters. - - Args: - title: Title of the notification (optional). If specified, overrides the title set via - ``messaging.Notification``. - body: Body of the notification (optional). If specified, overrides the body set via - ``messaging.Notification``. - icon: Icon of the notification (optional). - color: Color of the notification icon expressed in ``#rrggbb`` form (optional). - sound: Sound to be played when the device receives the notification (optional). This is - usually the file name of the sound resource. - tag: Tag of the notification (optional). This is an identifier used to replace existing - notifications in the notification drawer. If not specified, each request creates a new - notification. - click_action: The action associated with a user click on the notification (optional). If - specified, an activity with a matching intent filter is launched when a user clicks on - the notification. - body_loc_key: Key of the body string in the app's string resources to use to localize the - body text (optional). - body_loc_args: A list of resource keys that will be used in place of the format specifiers - in ``body_loc_key`` (optional). - title_loc_key: Key of the title string in the app's string resources to use to localize the - title text (optional). - title_loc_args: A list of resource keys that will be used in place of the format specifiers - in ``title_loc_key`` (optional). - channel_id: channel_id of the notification (optional). - image: Image url of the notification (optional). - ticker: Sets the ``ticker`` text, which is sent to accessibility services. Prior to API - level 21 (Lollipop), sets the text that is displayed in the status bar when the - notification first arrives (optional). - sticky: When set to ``False`` or unset, the notification is automatically dismissed when the - user clicks it in the panel. When set to ``True``, the notification persists even when - the user clicks it (optional). - event_timestamp: For notifications that inform users about events with an absolute time - reference, sets the time that the event in the notification occurred as a - ``datetime.datetime`` instance. If the ``datetime.datetime`` instance is naive, it - defaults to be in the UTC timezone. Notifications in the panel are sorted by this time - (optional). - local_only: Sets whether or not this notification is relevant only to the current device. - Some notifications can be bridged to other devices for remote display, such as a Wear OS - watch. This hint can be set to recommend this notification not be bridged (optional). - See Wear OS guides: - https://developer.android.com/training/wearables/notifications/bridger#existing-method-of-preventing-bridging - priority: Sets the relative priority for this notification. Low-priority notifications may - be hidden from the user in certain situations. Note this priority differs from - ``AndroidMessagePriority``. This priority is processed by the client after the message - has been delivered. Whereas ``AndroidMessagePriority`` is an FCM concept that controls - when the message is delivered (optional). Must be one of ``default``, ``min``, ``low``, - ``high``, ``max`` or ``normal``. - vibrate_timings_millis: Sets the vibration pattern to use. Pass in an array of milliseconds - to turn the vibrator on or off. The first value indicates the duration to wait before - turning the vibrator on. The next value indicates the duration to keep the vibrator on. - Subsequent values alternate between duration to turn the vibrator off and to turn the - vibrator on. If ``vibrate_timings`` is set and ``default_vibrate_timings`` is set to - ``True``, the default value is used instead of the user-specified ``vibrate_timings``. - default_vibrate_timings: If set to ``True``, use the Android framework's default vibrate - pattern for the notification (optional). Default values are specified in ``config.xml`` - https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/values/config.xml. - If ``default_vibrate_timings`` is set to ``True`` and ``vibrate_timings`` is also set, - the default value is used instead of the user-specified ``vibrate_timings``. - default_sound: If set to ``True``, use the Android framework's default sound for the - notification (optional). Default values are specified in ``config.xml`` - https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/values/config.xml - light_settings: Settings to control the notification's LED blinking rate and color if LED is - available on the device. The total blinking time is controlled by the OS (optional). - default_light_settings: If set to ``True``, use the Android framework's default LED light - settings for the notification. Default values are specified in ``config.xml`` - https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/values/config.xml. - If ``default_light_settings`` is set to ``True`` and ``light_settings`` is also set, the - user-specified ``light_settings`` is used instead of the default value. - visibility: Sets the visibility of the notification. Must be either ``private``, ``public``, - or ``secret``. If unspecified, it remains undefined in the Admin SDK, and defers to - the FCM backend's default mapping. - notification_count: Sets the number of items this notification represents. May be displayed - as a badge count for Launchers that support badging. See ``NotificationBadge`` - https://developer.android.com/training/notify-user/badges. For example, this might be - useful if you're using just one notification to represent multiple new messages but you - want the count here to represent the number of total new messages. If zero or - unspecified, systems that support badging use the default, which is to increment a - number displayed on the long-press menu each time a new notification arrives. - proxy: Sets if the notification may be proxied. Must be one of ``allow``, ``deny``, or - ``if_priority_lowered``. If unspecified, it remains undefined in the Admin SDK, and - defers to the FCM backend's default mapping. - - - """ - - def __init__(self, title=None, body=None, icon=None, color=None, sound=None, tag=None, - click_action=None, body_loc_key=None, body_loc_args=None, title_loc_key=None, - title_loc_args=None, channel_id=None, image=None, ticker=None, sticky=None, - event_timestamp=None, local_only=None, priority=None, vibrate_timings_millis=None, - default_vibrate_timings=None, default_sound=None, light_settings=None, - default_light_settings=None, visibility=None, notification_count=None, - proxy=None): - self.title = title - self.body = body - self.icon = icon - self.color = color - self.sound = sound - self.tag = tag - self.click_action = click_action - self.body_loc_key = body_loc_key - self.body_loc_args = body_loc_args - self.title_loc_key = title_loc_key - self.title_loc_args = title_loc_args - self.channel_id = channel_id - self.image = image - self.ticker = ticker - self.sticky = sticky - self.event_timestamp = event_timestamp - self.local_only = local_only - self.priority = priority - self.vibrate_timings_millis = vibrate_timings_millis - self.default_vibrate_timings = default_vibrate_timings - self.default_sound = default_sound - self.light_settings = light_settings - self.default_light_settings = default_light_settings - self.visibility = visibility - self.notification_count = notification_count - self.proxy = proxy - - -class LightSettings: - """Represents settings to control notification LED that can be included in a - ``messaging.AndroidNotification``. - - Args: - color: Sets the color of the LED in ``#rrggbb`` or ``#rrggbbaa`` format. - light_on_duration_millis: Along with ``light_off_duration``, defines the blink rate of LED - flashes. - light_off_duration_millis: Along with ``light_on_duration``, defines the blink rate of LED - flashes. - """ - def __init__(self, color, light_on_duration_millis, - light_off_duration_millis): - self.color = color - self.light_on_duration_millis = light_on_duration_millis - self.light_off_duration_millis = light_off_duration_millis - - -class AndroidFCMOptions: - """Options for features provided by the FCM SDK for Android. - - Args: - analytics_label: contains additional options for features provided by the FCM Android SDK - (optional). - """ - - def __init__(self, analytics_label=None): - self.analytics_label = analytics_label - - -class WebpushConfig: - """Webpush-specific options that can be included in a message. - - Args: - headers: A dictionary of headers (optional). Refer `Webpush Specification`_ for supported - headers. - data: A dictionary of data fields (optional). All keys and values in the dictionary must be - strings. When specified, overrides any data fields set via ``Message.data``. - notification: A ``messaging.WebpushNotification`` to be included in the message (optional). - fcm_options: A ``messaging.WebpushFCMOptions`` instance to be included in the message - (optional). - - .. _Webpush Specification: https://tools.ietf.org/html/rfc8030#section-5 - """ - - def __init__(self, headers=None, data=None, notification=None, fcm_options=None): - self.headers = headers - self.data = data - self.notification = notification - self.fcm_options = fcm_options - - -class WebpushNotificationAction: - """An action available to the users when the notification is presented. - - Args: - action: Action string. - title: Title string. - icon: Icon URL for the action (optional). - """ - - def __init__(self, action, title, icon=None): - self.action = action - self.title = title - self.icon = icon - - -class WebpushNotification: - """Webpush-specific notification parameters. - - Refer to the `Notification Reference`_ for more information. - - Args: - title: Title of the notification (optional). If specified, overrides the title set via - ``messaging.Notification``. - body: Body of the notification (optional). If specified, overrides the body set via - ``messaging.Notification``. - icon: Icon URL of the notification (optional). - actions: A list of ``messaging.WebpushNotificationAction`` instances (optional). - badge: URL of the image used to represent the notification when there is - not enough space to display the notification itself (optional). - data: Any arbitrary JSON data that should be associated with the notification (optional). - direction: The direction in which to display the notification (optional). Must be either - 'auto', 'ltr' or 'rtl'. - image: The URL of an image to be displayed in the notification (optional). - language: Notification language (optional). - renotify: A boolean indicating whether the user should be notified after a new - notification replaces an old one (optional). - require_interaction: A boolean indicating whether a notification should remain active - until the user clicks or dismisses it, rather than closing automatically (optional). - silent: ``True`` to indicate that the notification should be silent (optional). - tag: An identifying tag on the notification (optional). - timestamp_millis: A timestamp value in milliseconds on the notification (optional). - vibrate: A vibration pattern for the device's vibration hardware to emit when the - notification fires (optional). The pattern is specified as an integer array. - custom_data: A dict of custom key-value pairs to be included in the notification - (optional) - - .. _Notification Reference: https://developer.mozilla.org/en-US/docs/Web/API\ - /notification/Notification - """ - - def __init__(self, title=None, body=None, icon=None, actions=None, badge=None, data=None, - direction=None, image=None, language=None, renotify=None, - require_interaction=None, silent=None, tag=None, timestamp_millis=None, - vibrate=None, custom_data=None): - self.title = title - self.body = body - self.icon = icon - self.actions = actions - self.badge = badge - self.data = data - self.direction = direction - self.image = image - self.language = language - self.renotify = renotify - self.require_interaction = require_interaction - self.silent = silent - self.tag = tag - self.timestamp_millis = timestamp_millis - self.vibrate = vibrate - self.custom_data = custom_data - - -class WebpushFCMOptions: - """Options for features provided by the FCM SDK for Web. - - Args: - link: The link to open when the user clicks on the notification. Must be an HTTPS URL - (optional). - """ - - def __init__(self, link=None): - self.link = link - - -class APNSConfig: - """APNS-specific options that can be included in a message. - - Refer to `APNS Documentation`_ for more information. - - Args: - headers: A dictionary of headers (optional). - payload: A ``messaging.APNSPayload`` to be included in the message (optional). - fcm_options: A ``messaging.APNSFCMOptions`` instance to be included in the message - (optional). - live_activity_token: A live activity token string (optional). - - .. _APNS Documentation: https://developer.apple.com/library/content/documentation\ - /NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html - """ - - def __init__(self, headers=None, payload=None, fcm_options=None, live_activity_token=None): - self.headers = headers - self.payload = payload - self.fcm_options = fcm_options - self.live_activity_token = live_activity_token - - -class APNSPayload: - """Payload of an APNS message. - - Args: - aps: A ``messaging.Aps`` instance to be included in the payload. - **kwargs: Arbitrary keyword arguments to be included as custom fields in the payload - (optional). - """ - - def __init__(self, aps, **kwargs): - self.aps = aps - self.custom_data = kwargs - - -class Aps: - """Aps dictionary to be included in an APNS payload. - - Args: - alert: A string or a ``messaging.ApsAlert`` instance (optional). - badge: A number representing the badge to be displayed with the message (optional). - sound: Name of the sound file to be played with the message or a - ``messaging.CriticalSound`` instance (optional). - content_available: A boolean indicating whether to configure a background update - notification (optional). - category: String identifier representing the message type (optional). - thread_id: An app-specific string identifier for grouping messages (optional). - mutable_content: A boolean indicating whether to support mutating notifications at - the client using app extensions (optional). - custom_data: A dict of custom key-value pairs to be included in the Aps dictionary - (optional). - """ - - def __init__(self, alert=None, badge=None, sound=None, content_available=None, category=None, - thread_id=None, mutable_content=None, custom_data=None): - self.alert = alert - self.badge = badge - self.sound = sound - self.content_available = content_available - self.category = category - self.thread_id = thread_id - self.mutable_content = mutable_content - self.custom_data = custom_data - - -class CriticalSound: - """Critical alert sound configuration that can be included in ``messaging.Aps``. - - Args: - name: The name of a sound file in your app's main bundle or in the ``Library/Sounds`` - folder of your app's container directory. Specify the string ``default`` to play the - system sound. - critical: Set to ``True`` to set the critical alert flag on the sound configuration - (optional). - volume: The volume for the critical alert's sound. Must be a value between 0.0 (silent) - and 1.0 (full volume) (optional). - """ - - def __init__(self, name, critical=None, volume=None): - self.name = name - self.critical = critical - self.volume = volume - - -class ApsAlert: - """An alert that can be included in ``messaging.Aps``. - - Args: - title: Title of the alert (optional). If specified, overrides the title set via - ``messaging.Notification``. - subtitle: Subtitle of the alert (optional). - body: Body of the alert (optional). If specified, overrides the body set via - ``messaging.Notification``. - loc_key: Key of the body string in the app's string resources to use to localize the - body text (optional). - loc_args: A list of resource keys that will be used in place of the format specifiers - in ``loc_key`` (optional). - title_loc_key: Key of the title string in the app's string resources to use to localize the - title text (optional). - title_loc_args: A list of resource keys that will be used in place of the format specifiers - in ``title_loc_key`` (optional). - action_loc_key: Key of the text in the app's string resources to use to localize the - action button text (optional). - launch_image: Image for the notification action (optional). - custom_data: A dict of custom key-value pairs to be included in the ApsAlert dictionary - (optional) - """ - - def __init__(self, title=None, subtitle=None, body=None, loc_key=None, loc_args=None, - title_loc_key=None, title_loc_args=None, action_loc_key=None, launch_image=None, - custom_data=None): - self.title = title - self.subtitle = subtitle - self.body = body - self.loc_key = loc_key - self.loc_args = loc_args - self.title_loc_key = title_loc_key - self.title_loc_args = title_loc_args - self.action_loc_key = action_loc_key - self.launch_image = launch_image - self.custom_data = custom_data - - -class APNSFCMOptions: - """Options for features provided by the FCM SDK for iOS. - - Args: - analytics_label: contains additional options for features provided by the FCM iOS SDK - (optional). - image: contains the URL of an image that is going to be displayed in a notification - (optional). - """ - - def __init__(self, analytics_label=None, image=None): - self.analytics_label = analytics_label - self.image = image - - -class FCMOptions: - """Options for features provided by SDK. - - Args: - analytics_label: contains additional options to use across all platforms (optional). - """ - - def __init__(self, analytics_label=None): - self.analytics_label = analytics_label - - -class ThirdPartyAuthError(exceptions.UnauthenticatedError): - """APNs certificate or web push auth key was invalid or missing.""" - - def __init__(self, message, cause=None, http_response=None): - exceptions.UnauthenticatedError.__init__(self, message, cause, http_response) - - -class QuotaExceededError(exceptions.ResourceExhaustedError): - """Sending limit exceeded for the message target.""" - - def __init__(self, message, cause=None, http_response=None): - exceptions.ResourceExhaustedError.__init__(self, message, cause, http_response) - - -class SenderIdMismatchError(exceptions.PermissionDeniedError): - """The authenticated sender ID is different from the sender ID for the registration token.""" - - def __init__(self, message, cause=None, http_response=None): - exceptions.PermissionDeniedError.__init__(self, message, cause, http_response) - - -class UnregisteredError(exceptions.NotFoundError): - """App instance was unregistered from FCM. - - This usually means that the token used is no longer valid and a new one must be used.""" - - def __init__(self, message, cause=None, http_response=None): - exceptions.NotFoundError.__init__(self, message, cause, http_response) diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/_retry.py b/notification-service/venv/Lib/site-packages/firebase_admin/_retry.py deleted file mode 100644 index efd90a7..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/_retry.py +++ /dev/null @@ -1,223 +0,0 @@ -# Copyright 2025 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Internal retry logic module - -This module provides utilities for adding retry logic to HTTPX requests -""" - -from __future__ import annotations -import copy -import email.utils -import random -import re -import time -from typing import Any, Callable, List, Optional, Tuple, Coroutine -import logging -import asyncio -import httpx - -logger = logging.getLogger(__name__) - - -class HttpxRetry: - """HTTPX based retry config""" - # Status codes to be used for respecting `Retry-After` header - RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503]) - - # Default maximum backoff time. - DEFAULT_BACKOFF_MAX = 120 - - def __init__( - self, - max_retries: int = 10, - status_forcelist: Optional[List[int]] = None, - backoff_factor: float = 0, - backoff_max: float = DEFAULT_BACKOFF_MAX, - backoff_jitter: float = 0, - history: Optional[List[Tuple[ - httpx.Request, - Optional[httpx.Response], - Optional[Exception] - ]]] = None, - respect_retry_after_header: bool = False, - ) -> None: - self.retries_left = max_retries - self.status_forcelist = status_forcelist - self.backoff_factor = backoff_factor - self.backoff_max = backoff_max - self.backoff_jitter = backoff_jitter - if history: - self.history = history - else: - self.history = [] - self.respect_retry_after_header = respect_retry_after_header - - def copy(self) -> HttpxRetry: - """Creates a deep copy of this instance.""" - return copy.deepcopy(self) - - def is_retryable_response(self, response: httpx.Response) -> bool: - """Determine if a response implies that the request should be retried if possible.""" - if self.status_forcelist and response.status_code in self.status_forcelist: - return True - - has_retry_after = bool(response.headers.get("Retry-After")) - if ( - self.respect_retry_after_header - and has_retry_after - and response.status_code in self.RETRY_AFTER_STATUS_CODES - ): - return True - - return False - - def is_exhausted(self) -> bool: - """Determine if there are anymore more retires.""" - # retries_left is negative - return self.retries_left < 0 - - # Identical implementation of `urllib3.Retry.parse_retry_after()` - def _parse_retry_after(self, retry_after_header: str) -> float | None: - """Parses Retry-After string into a float with unit seconds.""" - seconds: float - # Whitespace: https://tools.ietf.org/html/rfc7230#section-3.2.4 - if re.match(r"^\s*[0-9]+\s*$", retry_after_header): - seconds = int(retry_after_header) - else: - retry_date_tuple = email.utils.parsedate_tz(retry_after_header) - if retry_date_tuple is None: - raise httpx.RemoteProtocolError(f"Invalid Retry-After header: {retry_after_header}") - - retry_date = email.utils.mktime_tz(retry_date_tuple) - seconds = retry_date - time.time() - - seconds = max(seconds, 0) - - return seconds - - def get_retry_after(self, response: httpx.Response) -> float | None: - """Determine the Retry-After time needed before sending the next request.""" - retry_after_header = response.headers.get('Retry-After', None) - if retry_after_header: - # Convert retry header to a float in seconds - return self._parse_retry_after(retry_after_header) - return None - - def get_backoff_time(self): - """Determine the backoff time needed before sending the next request.""" - # attempt_count is the number of previous request attempts - attempt_count = len(self.history) - # Backoff should be set to 0 until after first retry. - if attempt_count <= 1: - return 0 - backoff = self.backoff_factor * (2 ** (attempt_count-1)) - if self.backoff_jitter: - backoff += random.random() * self.backoff_jitter - return float(max(0, min(self.backoff_max, backoff))) - - async def sleep_for_backoff(self) -> None: - """Determine and wait the backoff time needed before sending the next request.""" - backoff = self.get_backoff_time() - logger.debug('Sleeping for backoff of %f seconds following failed request', backoff) - await asyncio.sleep(backoff) - - async def sleep(self, response: httpx.Response) -> None: - """Determine and wait the time needed before sending the next request.""" - if self.respect_retry_after_header: - retry_after = self.get_retry_after(response) - if retry_after: - logger.debug( - 'Sleeping for Retry-After header of %f seconds following failed request', - retry_after - ) - await asyncio.sleep(retry_after) - return - await self.sleep_for_backoff() - - def increment( - self, - request: httpx.Request, - response: Optional[httpx.Response] = None, - error: Optional[Exception] = None - ) -> None: - """Update the retry state based on request attempt.""" - self.retries_left -= 1 - self.history.append((request, response, error)) - - -class HttpxRetryTransport(httpx.AsyncBaseTransport): - """HTTPX transport with retry logic.""" - - DEFAULT_RETRY = HttpxRetry(max_retries=4, status_forcelist=[500, 503], backoff_factor=0.5) - - def __init__(self, retry: HttpxRetry = DEFAULT_RETRY, **kwargs: Any) -> None: - self._retry = retry - - transport_kwargs = kwargs.copy() - transport_kwargs.update({'retries': 0, 'http2': True}) - # We use a full AsyncHTTPTransport under the hood that is already - # set up to handle requests. We also insure that that transport's internal - # retries are not allowed. - self._wrapped_transport = httpx.AsyncHTTPTransport(**transport_kwargs) - - async def handle_async_request(self, request: httpx.Request) -> httpx.Response: - return await self._dispatch_with_retry( - request, self._wrapped_transport.handle_async_request) - - async def _dispatch_with_retry( - self, - request: httpx.Request, - dispatch_method: Callable[[httpx.Request], Coroutine[Any, Any, httpx.Response]] - ) -> httpx.Response: - """Sends a request with retry logic using a provided dispatch method.""" - # This request config is used across all requests that use this transport and therefore - # needs to be copied to be used for just this request and it's retries. - retry = self._retry.copy() - # First request - response, error = None, None - - while not retry.is_exhausted(): - - # First retry - if response: - await retry.sleep(response) - - # Need to reset here so only last attempt's error or response is saved. - response, error = None, None - - try: - logger.debug('Sending request in _dispatch_with_retry(): %r', request) - response = await dispatch_method(request) - logger.debug('Received response: %r', response) - except httpx.HTTPError as err: - logger.debug('Received error: %r', err) - error = err - - if response and not retry.is_retryable_response(response): - return response - - if error: - raise error - - retry.increment(request, response, error) - - if response: - return response - if error: - raise error - raise AssertionError('_dispatch_with_retry() ended with no response or exception') - - async def aclose(self) -> None: - await self._wrapped_transport.aclose() diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/_rfc3339.py b/notification-service/venv/Lib/site-packages/firebase_admin/_rfc3339.py deleted file mode 100644 index 8489bdc..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/_rfc3339.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2020 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Parse RFC3339 date strings""" - -from datetime import datetime, timezone -import re - -def parse_to_epoch(datestr): - """Parse an RFC3339 date string and return the number of seconds since the - epoch (as a float). - - In particular, this method is meant to parse the strings returned by the - JSON mapping of protobuf google.protobuf.timestamp.Timestamp instances: - https://github.com/protocolbuffers/protobuf/blob/4cf5bfee9546101d98754d23ff378ff718ba8438/src/google/protobuf/timestamp.proto#L99 - - This method has microsecond precision; nanoseconds will be truncated. - - Args: - datestr: A string in RFC3339 format. - Returns: - Float: The number of seconds since the Unix epoch. - Raises: - ValueError: Raised if the `datestr` is not a valid RFC3339 date string. - """ - return _parse_to_datetime(datestr).timestamp() - - -def _parse_to_datetime(datestr): - """Parse an RFC3339 date string and return a python datetime instance. - - Args: - datestr: A string in RFC3339 format. - Returns: - datetime: The corresponding `datetime` (with timezone information). - Raises: - ValueError: Raised if the `datestr` is not a valid RFC3339 date string. - """ - # If more than 6 digits appear in the fractional seconds position, truncate - # to just the most significant 6. (i.e. we only have microsecond precision; - # nanos are truncated.) - datestr_modified = re.sub(r'(\.\d{6})\d*', r'\1', datestr) - - # This format is the one we actually expect to occur from our backend. The - # others are only present because the spec says we *should* accept them. - try: - return datetime.strptime( - datestr_modified, '%Y-%m-%dT%H:%M:%S.%fZ' - ).replace(tzinfo=timezone.utc) - except ValueError: - pass - - try: - return datetime.strptime( - datestr_modified, '%Y-%m-%dT%H:%M:%SZ' - ).replace(tzinfo=timezone.utc) - except ValueError: - pass - - # Note: %z parses timezone offsets, but requires the timezone offset *not* - # include a separating ':'. As of python 3.7, this was relaxed. - # TODO(rsgowman): Once python3.7 becomes our floor, we can drop the regex - # replacement. - datestr_modified = re.sub(r'(\d\d):(\d\d)$', r'\1\2', datestr_modified) - - try: - return datetime.strptime(datestr_modified, '%Y-%m-%dT%H:%M:%S.%f%z') - except ValueError: - pass - - try: - return datetime.strptime(datestr_modified, '%Y-%m-%dT%H:%M:%S%z') - except ValueError: - pass - - raise ValueError(f'time data {datestr} does not match RFC3339 format') diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/_sseclient.py b/notification-service/venv/Lib/site-packages/firebase_admin/_sseclient.py deleted file mode 100644 index 3372fe5..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/_sseclient.py +++ /dev/null @@ -1,205 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""SSEClient module to stream realtime updates from the Firebase Database. - -Based on a similar implementation from Pyrebase. -""" - -import re -import time -import warnings - -from google.auth import transport -import requests - - -# Technically, we should support streams that mix line endings. This regex, -# however, assumes that a system will provide consistent line endings. -end_of_field = re.compile(r'\r\n\r\n|\r\r|\n\n') - - -class KeepAuthSession(transport.requests.AuthorizedSession): - """A session that does not drop authentication on redirects between domains.""" - - def __init__(self, credential): - super().__init__(credential) - - def rebuild_auth(self, prepared_request, response): - pass - - -class _EventBuffer: - """A helper class for buffering and parsing raw SSE data.""" - - def __init__(self): - self._buffer = [] - self._tail = '' - - def append(self, char): - self._buffer.append(char) - self._tail += char - self._tail = self._tail[-4:] - - def truncate(self): - head, sep, _ = self.buffer_string.rpartition('\n') - rem = head + sep - self._buffer = list(rem) - self._tail = rem[-4:] - - @property - def is_end_of_field(self): - last_two_chars = self._tail[-2:] - return last_two_chars == '\n\n' or last_two_chars == '\r\r' or self._tail == '\r\n\r\n' - - @property - def buffer_string(self): - return ''.join(self._buffer) - - -class SSEClient: - """SSE client implementation.""" - - def __init__(self, url, session, retry=3000, **kwargs): - """Initializes the SSEClient. - - Args: - url: The remote url to connect to. - session: The requests session. - retry: The retry interval in milliseconds (optional). - **kwargs: Extra kwargs that will be sent to ``requests.get()`` (optional). - """ - self.url = url - self.session = session - self.retry = retry - self.requests_kwargs = kwargs - self.should_connect = True - self.last_id = None - self.buf = '' # Keep data here as it streams in - - headers = self.requests_kwargs.get('headers', {}) - # The SSE spec requires making requests with Cache-Control: no-cache - headers['Cache-Control'] = 'no-cache' - # The 'Accept' header is not required, but explicit > implicit - headers['Accept'] = 'text/event-stream' - self.requests_kwargs['headers'] = headers - self._connect() - - def close(self): - """Closes the SSEClient instance.""" - self.should_connect = False - self.retry = 0 - self.resp.close() - - def _connect(self): - """Connects to the server using requests.""" - if self.should_connect: - if self.last_id: - self.requests_kwargs['headers']['Last-Event-ID'] = self.last_id - self.resp = self.session.get(self.url, stream=True, **self.requests_kwargs) - self.resp_iterator = self.resp.iter_content(decode_unicode=True) - self.resp.raise_for_status() - else: - raise StopIteration() - - def __iter__(self): - return self - - def __next__(self): - if not re.search(end_of_field, self.buf): - temp_buffer = _EventBuffer() - while not temp_buffer.is_end_of_field: - try: - nextchar = next(self.resp_iterator) - temp_buffer.append(nextchar) - except (StopIteration, requests.RequestException): - time.sleep(self.retry / 1000.0) - self._connect() - # The SSE spec only supports resuming from a whole message, so - # if we have half a message we should throw it out. - temp_buffer.truncate() - continue - self.buf = temp_buffer.buffer_string - - split = re.split(end_of_field, self.buf) - head = split[0] - self.buf = '\n\n'.join(split[1:]) - event = Event.parse(head) - - if event.data == 'credential is no longer valid': - self._connect() - return None - if event.data == 'null': - return None - - # If the server requests a specific retry delay, we need to honor it. - if event.retry: - self.retry = event.retry - - # last_id should only be set if included in the message. It's not - # forgotten if a message omits it. - if event.event_id: - self.last_id = event.event_id - return event - - -class Event: - """Event represents the events fired by SSE.""" - - sse_line_pattern = re.compile('(?P[^:]*):?( ?(?P.*))?') - - def __init__(self, data='', event_type='message', event_id=None, retry=None): - self.data = data - self.event_type = event_type - self.event_id = event_id - self.retry = retry - - @classmethod - def parse(cls, raw): - """Given a possibly-multiline string representing an SSE message, parses it - and returns an Event object. - - Args: - raw: the raw data to parse. - - Returns: - Event: A new ``Event`` with the parameters initialized. - """ - event = cls() - for line in raw.split('\n'): - match = cls.sse_line_pattern.match(line) - if match is None: - # Malformed line. Discard but warn. - warnings.warn(f'Invalid SSE line: "{line}"', SyntaxWarning) - continue - - name = match.groupdict()['name'] - value = match.groupdict()['value'] - if name == '': - # line began with a ":", so is a comment. Ignore - continue - if name == 'data': - # If we already have some data, then join to it with a newline. - # Else this is it. - if event.data: - event.data = f'{event.data}\n{value}' - else: - event.data = value - elif name == 'event': - event.event_type = value - elif name == 'id': - event.event_id = value - elif name == 'retry': - event.retry = int(value) - return event diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/_token_gen.py b/notification-service/venv/Lib/site-packages/firebase_admin/_token_gen.py deleted file mode 100644 index 1607ef0..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/_token_gen.py +++ /dev/null @@ -1,466 +0,0 @@ -# Copyright 2018 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase token minting and validation sub module.""" - -import datetime -import time - -import cachecontrol -import requests -from google.auth import credentials -from google.auth import iam -from google.auth import jwt -from google.auth import transport -import google.auth.exceptions -import google.oauth2.id_token -import google.oauth2.service_account - -from firebase_admin import exceptions -from firebase_admin import _auth_utils -from firebase_admin import _http_client - - -# ID token constants -ID_TOKEN_ISSUER_PREFIX = 'https://securetoken.google.com/' -ID_TOKEN_CERT_URI = ('https://www.googleapis.com/robot/v1/metadata/x509/' - 'securetoken@system.gserviceaccount.com') - -# Session cookie constants -COOKIE_ISSUER_PREFIX = 'https://session.firebase.google.com/' -COOKIE_CERT_URI = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys' -MIN_SESSION_COOKIE_DURATION_SECONDS = int(datetime.timedelta(minutes=5).total_seconds()) -MAX_SESSION_COOKIE_DURATION_SECONDS = int(datetime.timedelta(days=14).total_seconds()) - -# Custom token constants -MAX_TOKEN_LIFETIME_SECONDS = int(datetime.timedelta(hours=1).total_seconds()) -FIREBASE_AUDIENCE = ('https://identitytoolkit.googleapis.com/google.' - 'identity.identitytoolkit.v1.IdentityToolkit') -RESERVED_CLAIMS = set([ - 'acr', 'amr', 'at_hash', 'aud', 'auth_time', 'azp', 'cnf', 'c_hash', - 'exp', 'firebase', 'iat', 'iss', 'jti', 'nbf', 'nonce', 'sub' -]) -METADATA_SERVICE_URL = ('http://metadata.google.internal/computeMetadata/v1/instance/' - 'service-accounts/default/email') -ALGORITHM_RS256 = 'RS256' -ALGORITHM_NONE = 'none' - -# Emulator fake account -AUTH_EMULATOR_EMAIL = 'firebase-auth-emulator@example.com' - - -class _EmulatedSigner(google.auth.crypt.Signer): - key_id = None - - def __init__(self): - pass - - def sign(self, message): - return b'' - - -class _SigningProvider: - """Stores a reference to a google.auth.crypto.Signer.""" - - def __init__(self, signer, signer_email, alg=ALGORITHM_RS256): - self._signer = signer - self._signer_email = signer_email - self._alg = alg - - @property - def signer(self): - return self._signer - - @property - def signer_email(self): - return self._signer_email - - @property - def alg(self): - return self._alg - - @classmethod - def from_credential(cls, google_cred): - return _SigningProvider(google_cred.signer, google_cred.signer_email) - - @classmethod - def from_iam(cls, request, google_cred, service_account): - signer = iam.Signer(request, google_cred, service_account) - return _SigningProvider(signer, service_account) - - @classmethod - def for_emulator(cls): - return _SigningProvider(_EmulatedSigner(), AUTH_EMULATOR_EMAIL, ALGORITHM_NONE) - - -class TokenGenerator: - """Generates custom tokens and session cookies.""" - - ID_TOOLKIT_URL = 'https://identitytoolkit.googleapis.com/v1' - - def __init__(self, app, http_client, url_override=None): - self.app = app - self.http_client = http_client - self.request = transport.requests.Request() - url_prefix = url_override or self.ID_TOOLKIT_URL - self.base_url = f'{url_prefix}/projects/{app.project_id}' - self._signing_provider = None - - def _init_signing_provider(self): - """Initializes a signing provider by following the go/firebase-admin-sign protocol.""" - if _auth_utils.is_emulated(): - return _SigningProvider.for_emulator() - # If the SDK was initialized with a service account, use it to sign bytes. - google_cred = self.app.credential.get_credential() - if isinstance(google_cred, google.oauth2.service_account.Credentials): - return _SigningProvider.from_credential(google_cred) - - # If the SDK was initialized with a service account email, use it with the IAM service - # to sign bytes. - service_account = self.app.options.get('serviceAccountId') - if service_account: - return _SigningProvider.from_iam(self.request, google_cred, service_account) - - # If the SDK was initialized with some other credential type that supports signing - # (e.g. GAE credentials), use it to sign bytes. - if isinstance(google_cred, credentials.Signing): - return _SigningProvider.from_credential(google_cred) - - # Attempt to discover a service account email from the local Metadata service. Use it - # with the IAM service to sign bytes. - resp = self.request(url=METADATA_SERVICE_URL, headers={'Metadata-Flavor': 'Google'}) - if resp.status != 200: - raise ValueError( - f'Failed to contact the local metadata service: {resp.data.decode()}.') - service_account = resp.data.decode() - return _SigningProvider.from_iam(self.request, google_cred, service_account) - - @property - def signing_provider(self): - """Initializes and returns the SigningProvider instance to be used.""" - if not self._signing_provider: - try: - self._signing_provider = self._init_signing_provider() - except Exception as error: - url = 'https://firebase.google.com/docs/auth/admin/create-custom-tokens' - raise ValueError( - f'Failed to determine service account: {error}. Make sure to initialize the ' - 'SDK with service account credentials or specify a service account ID with ' - f'iam.serviceAccounts.signBlob permission. Please refer to {url} for more ' - 'details on creating custom tokens.') from error - return self._signing_provider - - def create_custom_token(self, uid, developer_claims=None, tenant_id=None): - """Builds and signs a Firebase custom auth token.""" - if developer_claims is not None: - if not isinstance(developer_claims, dict): - raise ValueError('developer_claims must be a dictionary') - - disallowed_keys = set(developer_claims.keys()) & RESERVED_CLAIMS - if disallowed_keys: - if len(disallowed_keys) > 1: - error_message = ( - f'Developer claims {", ".join(disallowed_keys)} are reserved and cannot be ' - 'specified.') - else: - error_message = ( - f'Developer claim {", ".join(disallowed_keys)} is reserved and cannot be ' - 'specified.') - raise ValueError(error_message) - - if not uid or not isinstance(uid, str) or len(uid) > 128: - raise ValueError('uid must be a string between 1 and 128 characters.') - - signing_provider = self.signing_provider - now = int(time.time()) - payload = { - 'iss': signing_provider.signer_email, - 'sub': signing_provider.signer_email, - 'aud': FIREBASE_AUDIENCE, - 'uid': uid, - 'iat': now, - 'exp': now + MAX_TOKEN_LIFETIME_SECONDS, - } - if tenant_id: - payload['tenant_id'] = tenant_id - - if developer_claims is not None: - payload['claims'] = developer_claims - - header = {'alg': signing_provider.alg} - try: - return jwt.encode(signing_provider.signer, payload, header=header) - except google.auth.exceptions.TransportError as error: - msg = f'Failed to sign custom token. {error}' - raise TokenSignError(msg, error) from error - - - def create_session_cookie(self, id_token, expires_in): - """Creates a session cookie from the provided ID token.""" - id_token = id_token.decode('utf-8') if isinstance(id_token, bytes) else id_token - if not isinstance(id_token, str) or not id_token: - raise ValueError( - f'Illegal ID token provided: {id_token}. ID token must be a non-empty string.') - - if isinstance(expires_in, datetime.timedelta): - expires_in = int(expires_in.total_seconds()) - if isinstance(expires_in, bool) or not isinstance(expires_in, int): - raise ValueError(f'Illegal expiry duration: {expires_in}.') - if expires_in < MIN_SESSION_COOKIE_DURATION_SECONDS: - raise ValueError( - f'Illegal expiry duration: {expires_in}. Duration must be at least ' - f'{MIN_SESSION_COOKIE_DURATION_SECONDS} seconds.') - if expires_in > MAX_SESSION_COOKIE_DURATION_SECONDS: - raise ValueError( - f'Illegal expiry duration: {expires_in}. Duration must be at most ' - f'{MAX_SESSION_COOKIE_DURATION_SECONDS} seconds.') - - url = f'{self.base_url}:createSessionCookie' - payload = { - 'idToken': id_token, - 'validDuration': expires_in, - } - try: - body, http_resp = self.http_client.body_and_response('post', url, json=payload) - except requests.exceptions.RequestException as error: - raise _auth_utils.handle_auth_backend_error(error) - if not body or not body.get('sessionCookie'): - raise _auth_utils.UnexpectedResponseError( - 'Failed to create session cookie.', http_response=http_resp) - return body.get('sessionCookie') - - -class CertificateFetchRequest(transport.Request): - """A google-auth transport that supports HTTP cache-control. - - Also injects a timeout to each outgoing HTTP request. - """ - - def __init__(self, timeout_seconds=None): - self._session = cachecontrol.CacheControl(requests.Session()) - self._delegate = transport.requests.Request(self.session) - self._timeout_seconds = timeout_seconds - - @property - def session(self): - return self._session - - @property - def timeout_seconds(self): - return self._timeout_seconds - - def __call__(self, url, method='GET', body=None, headers=None, timeout=None, **kwargs): - timeout = timeout or self.timeout_seconds - return self._delegate( - url, method=method, body=body, headers=headers, timeout=timeout, **kwargs) - - -class TokenVerifier: - """Verifies ID tokens and session cookies.""" - - def __init__(self, app): - timeout = app.options.get('httpTimeout', _http_client.DEFAULT_TIMEOUT_SECONDS) - self.request = CertificateFetchRequest(timeout) - self.id_token_verifier = _JWTVerifier( - project_id=app.project_id, short_name='ID token', - operation='verify_id_token()', - doc_url='https://firebase.google.com/docs/auth/admin/verify-id-tokens', - cert_url=ID_TOKEN_CERT_URI, - issuer=ID_TOKEN_ISSUER_PREFIX, - invalid_token_error=_auth_utils.InvalidIdTokenError, - expired_token_error=ExpiredIdTokenError) - self.cookie_verifier = _JWTVerifier( - project_id=app.project_id, short_name='session cookie', - operation='verify_session_cookie()', - doc_url='https://firebase.google.com/docs/auth/admin/verify-id-tokens', - cert_url=COOKIE_CERT_URI, - issuer=COOKIE_ISSUER_PREFIX, - invalid_token_error=InvalidSessionCookieError, - expired_token_error=ExpiredSessionCookieError) - - def verify_id_token(self, id_token, clock_skew_seconds=0): - return self.id_token_verifier.verify(id_token, self.request, clock_skew_seconds) - - def verify_session_cookie(self, cookie, clock_skew_seconds=0): - return self.cookie_verifier.verify(cookie, self.request, clock_skew_seconds) - - -class _JWTVerifier: - """Verifies Firebase JWTs (ID tokens or session cookies).""" - - def __init__(self, **kwargs): - self.project_id = kwargs.pop('project_id') - self.short_name = kwargs.pop('short_name') - self.operation = kwargs.pop('operation') - self.url = kwargs.pop('doc_url') - self.cert_url = kwargs.pop('cert_url') - self.issuer = kwargs.pop('issuer') - if self.short_name[0].lower() in 'aeiou': - self.articled_short_name = f'an {self.short_name}' - else: - self.articled_short_name = f'a {self.short_name}' - self._invalid_token_error = kwargs.pop('invalid_token_error') - self._expired_token_error = kwargs.pop('expired_token_error') - - def verify(self, token, request, clock_skew_seconds=0): - """Verifies the signature and data for the provided JWT.""" - token = token.encode('utf-8') if isinstance(token, str) else token - if not isinstance(token, bytes) or not token: - raise ValueError( - f'Illegal {self.short_name} provided: {token}. {self.short_name} must be a ' - 'non-empty string.') - - if not self.project_id: - raise ValueError( - 'Failed to ascertain project ID from the credential or the environment. Project ' - f'ID is required to call {self.operation}. Initialize the app with a ' - 'credentials.Certificate or set your Firebase project ID as an app option. ' - 'Alternatively set the GOOGLE_CLOUD_PROJECT environment variable.') - - if clock_skew_seconds < 0 or clock_skew_seconds > 60: - raise ValueError( - f'Illegal clock_skew_seconds value: {clock_skew_seconds}. Must be between 0 and 60' - ', inclusive.') - - header, payload = self._decode_unverified(token) - issuer = payload.get('iss') - audience = payload.get('aud') - subject = payload.get('sub') - expected_issuer = self.issuer + self.project_id - - project_id_match_msg = ( - f'Make sure the {self.short_name} comes from the same Firebase project as the service ' - 'account used to authenticate this SDK.') - verify_id_token_msg = ( - f'See {self.url} for details on how to retrieve {self.short_name}.') - - emulated = _auth_utils.is_emulated() - - error_message = None - if audience == FIREBASE_AUDIENCE: - error_message = ( - f'{self.operation} expects {self.articled_short_name}, but was given a custom ' - 'token.') - elif not emulated and not header.get('kid'): - if header.get('alg') == 'HS256' and payload.get( - 'v') == 0 and 'uid' in payload.get('d', {}): - error_message = ( - f'{self.operation} expects {self.articled_short_name}, but was given a legacy ' - 'custom token.') - else: - error_message = f'Firebase {self.short_name} has no "kid" claim.' - elif not emulated and header.get('alg') != 'RS256': - error_message = ( - f'Firebase {self.short_name} has incorrect algorithm. Expected "RS256" but got ' - f'"{header.get("alg")}". {verify_id_token_msg}') - elif audience != self.project_id: - error_message = ( - f'Firebase {self.short_name} has incorrect "aud" (audience) claim. Expected ' - f'"{self.project_id}" but got "{audience}". {project_id_match_msg} ' - f'{verify_id_token_msg}') - elif issuer != expected_issuer: - error_message = ( - f'Firebase {self.short_name} has incorrect "iss" (issuer) claim. Expected ' - f'"{expected_issuer}" but got "{issuer}". {project_id_match_msg} ' - f'{verify_id_token_msg}') - elif subject is None or not isinstance(subject, str): - error_message = ( - f'Firebase {self.short_name} has no "sub" (subject) claim. {verify_id_token_msg}') - elif not subject: - error_message = ( - f'Firebase {self.short_name} has an empty string "sub" (subject) claim. ' - f'{verify_id_token_msg}') - elif len(subject) > 128: - error_message = ( - f'Firebase {self.short_name} has a "sub" (subject) claim longer than 128 ' - f'characters. {verify_id_token_msg}') - - if error_message: - raise self._invalid_token_error(error_message) - - try: - if emulated: - verified_claims = payload - else: - verified_claims = google.oauth2.id_token.verify_token( - token, - request=request, - audience=self.project_id, - certs_url=self.cert_url, - clock_skew_in_seconds=clock_skew_seconds) - verified_claims['uid'] = verified_claims['sub'] - return verified_claims - except google.auth.exceptions.TransportError as error: - raise CertificateFetchError(str(error), cause=error) from error - except ValueError as error: - if 'Token expired' in str(error): - raise self._expired_token_error(str(error), cause=error) - raise self._invalid_token_error(str(error), cause=error) - - def _decode_unverified(self, token): - try: - header = jwt.decode_header(token) - payload = jwt.decode(token, verify=False) - return header, payload - except ValueError as error: - raise self._invalid_token_error(str(error), cause=error) - - -class TokenSignError(exceptions.UnknownError): - """Unexpected error while signing a Firebase custom token.""" - - def __init__(self, message, cause): - exceptions.UnknownError.__init__(self, message, cause) - - -class CertificateFetchError(exceptions.UnknownError): - """Failed to fetch some public key certificates required to verify a token.""" - - def __init__(self, message, cause): - exceptions.UnknownError.__init__(self, message, cause) - - -class ExpiredIdTokenError(_auth_utils.InvalidIdTokenError): - """The provided ID token is expired.""" - - def __init__(self, message, cause): - _auth_utils.InvalidIdTokenError.__init__(self, message, cause) - - -class RevokedIdTokenError(_auth_utils.InvalidIdTokenError): - """The provided ID token has been revoked.""" - - def __init__(self, message): - _auth_utils.InvalidIdTokenError.__init__(self, message) - - -class InvalidSessionCookieError(exceptions.InvalidArgumentError): - """The provided string is not a valid Firebase session cookie.""" - - def __init__(self, message, cause=None): - exceptions.InvalidArgumentError.__init__(self, message, cause) - - -class ExpiredSessionCookieError(InvalidSessionCookieError): - """The provided session cookie is expired.""" - - def __init__(self, message, cause): - InvalidSessionCookieError.__init__(self, message, cause) - - -class RevokedSessionCookieError(InvalidSessionCookieError): - """The provided session cookie has been revoked.""" - - def __init__(self, message): - InvalidSessionCookieError.__init__(self, message) diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/_user_identifier.py b/notification-service/venv/Lib/site-packages/firebase_admin/_user_identifier.py deleted file mode 100644 index 85a224e..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/_user_identifier.py +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright 2020 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Classes to uniquely identify a user.""" - -from firebase_admin import _auth_utils - -class UserIdentifier: - """Identifies a user to be looked up.""" - - -class UidIdentifier(UserIdentifier): - """Used for looking up an account by uid. - - See ``auth.get_user()``. - """ - - def __init__(self, uid): - """Constructs a new `UidIdentifier` object. - - Args: - uid: A user ID string. - """ - self._uid = _auth_utils.validate_uid(uid, required=True) - - @property - def uid(self): - return self._uid - - -class EmailIdentifier(UserIdentifier): - """Used for looking up an account by email. - - See ``auth.get_user()``. - """ - - def __init__(self, email): - """Constructs a new `EmailIdentifier` object. - - Args: - email: A user email address string. - """ - self._email = _auth_utils.validate_email(email, required=True) - - @property - def email(self): - return self._email - - -class PhoneIdentifier(UserIdentifier): - """Used for looking up an account by phone number. - - See ``auth.get_user()``. - """ - - def __init__(self, phone_number): - """Constructs a new `PhoneIdentifier` object. - - Args: - phone_number: A phone number string. - """ - self._phone_number = _auth_utils.validate_phone(phone_number, required=True) - - @property - def phone_number(self): - return self._phone_number - - -class ProviderIdentifier(UserIdentifier): - """Used for looking up an account by provider. - - See ``auth.get_user()``. - """ - - def __init__(self, provider_id, provider_uid): - """Constructs a new `ProviderIdentifier` object. - -   Args: -     provider_id: A provider ID string. -     provider_uid: A provider UID string. - """ - self._provider_id = _auth_utils.validate_provider_id(provider_id, required=True) - self._provider_uid = _auth_utils.validate_provider_uid( - provider_uid, required=True) - - @property - def provider_id(self): - return self._provider_id - - @property - def provider_uid(self): - return self._provider_uid diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/_user_import.py b/notification-service/venv/Lib/site-packages/firebase_admin/_user_import.py deleted file mode 100644 index 7c7a9e7..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/_user_import.py +++ /dev/null @@ -1,520 +0,0 @@ -# Copyright 2018 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase user import sub module.""" - -import base64 -import json - -from firebase_admin import _auth_utils - - -def b64_encode(bytes_value): - return base64.urlsafe_b64encode(bytes_value).decode() - - -class UserProvider: - """Represents a user identity provider that can be associated with a Firebase user. - - One or more providers can be specified in an ``ImportUserRecord`` when importing users via - ``auth.import_users()``. - - Args: - uid: User's unique ID assigned by the identity provider. - provider_id: ID of the identity provider. This can be a short domain name or the identifier - of an OpenID identity provider. - email: User's email address (optional). - display_name: User's display name (optional). - photo_url: User's photo URL (optional). - """ - - def __init__(self, uid, provider_id, email=None, display_name=None, photo_url=None): - self.uid = uid - self.provider_id = provider_id - self.email = email - self.display_name = display_name - self.photo_url = photo_url - - @property - def uid(self): - return self._uid - - @uid.setter - def uid(self, uid): - self._uid = _auth_utils.validate_uid(uid, required=True) - - @property - def provider_id(self): - return self._provider_id - - @provider_id.setter - def provider_id(self, provider_id): - self._provider_id = _auth_utils.validate_provider_id(provider_id, required=True) - - @property - def email(self): - return self._email - - @email.setter - def email(self, email): - self._email = _auth_utils.validate_email(email) - - @property - def display_name(self): - return self._display_name - - @display_name.setter - def display_name(self, display_name): - self._display_name = _auth_utils.validate_display_name(display_name) - - @property - def photo_url(self): - return self._photo_url - - @photo_url.setter - def photo_url(self, photo_url): - self._photo_url = _auth_utils.validate_photo_url(photo_url) - - def to_dict(self): - payload = { - 'rawId': self.uid, - 'providerId': self.provider_id, - 'displayName': self.display_name, - 'email': self.email, - 'photoUrl': self.photo_url, - } - return {k: v for k, v in payload.items() if v is not None} - - -class ImportUserRecord: - """Represents a user account to be imported to Firebase Auth. - - Must specify the ``uid`` field at a minimum. A sequence of ``ImportUserRecord`` objects can be - passed to the ``auth.import_users()`` function, in order to import those users into Firebase - Auth in bulk. If the ``password_hash`` is set on a user, a hash configuration must be - specified when calling ``import_users()``. - - Args: - uid: User's unique ID. Must be a non-empty string not longer than 128 characters. - email: User's email address (optional). - email_verified: A boolean indicating whether the user's email has been verified (optional). - display_name: User's display name (optional). - phone_number: User's phone number (optional). - photo_url: User's photo URL (optional). - disabled: A boolean indicating whether this user account has been disabled (optional). - user_metadata: An ``auth.UserMetadata`` instance with additional user metadata (optional). - provider_data: A list of ``auth.UserProvider`` instances (optional). - custom_claims: A ``dict`` of custom claims to be set on the user account (optional). - password_hash: User's password hash as a ``bytes`` sequence (optional). - password_salt: User's password salt as a ``bytes`` sequence (optional). - - Raises: - ValueError: If provided arguments are invalid. - """ - - def __init__(self, uid, email=None, email_verified=None, display_name=None, phone_number=None, - photo_url=None, disabled=None, user_metadata=None, provider_data=None, - custom_claims=None, password_hash=None, password_salt=None): - self.uid = uid - self.email = email - self.display_name = display_name - self.phone_number = phone_number - self.photo_url = photo_url - self.password_hash = password_hash - self.password_salt = password_salt - self.email_verified = email_verified - self.disabled = disabled - self.user_metadata = user_metadata - self.provider_data = provider_data - self.custom_claims = custom_claims - - @property - def uid(self): - return self._uid - - @uid.setter - def uid(self, uid): - self._uid = _auth_utils.validate_uid(uid, required=True) - - @property - def email(self): - return self._email - - @email.setter - def email(self, email): - self._email = _auth_utils.validate_email(email) - - @property - def display_name(self): - return self._display_name - - @display_name.setter - def display_name(self, display_name): - self._display_name = _auth_utils.validate_display_name(display_name) - - @property - def phone_number(self): - return self._phone_number - - @phone_number.setter - def phone_number(self, phone_number): - self._phone_number = _auth_utils.validate_phone(phone_number) - - @property - def photo_url(self): - return self._photo_url - - @photo_url.setter - def photo_url(self, photo_url): - self._photo_url = _auth_utils.validate_photo_url(photo_url) - - @property - def password_hash(self): - return self._password_hash - - @password_hash.setter - def password_hash(self, password_hash): - self._password_hash = _auth_utils.validate_bytes(password_hash, 'password_hash') - - @property - def password_salt(self): - return self._password_salt - - @password_salt.setter - def password_salt(self, password_salt): - self._password_salt = _auth_utils.validate_bytes(password_salt, 'password_salt') - - @property - def user_metadata(self): - return self._user_metadata - - @user_metadata.setter - def user_metadata(self, user_metadata): - created_at = user_metadata.creation_timestamp if user_metadata is not None else None - last_login_at = user_metadata.last_sign_in_timestamp if user_metadata is not None else None - self._created_at = _auth_utils.validate_timestamp(created_at, 'creation_timestamp') - self._last_login_at = _auth_utils.validate_timestamp( - last_login_at, 'last_sign_in_timestamp') - self._user_metadata = user_metadata - - @property - def provider_data(self): - return self._provider_data - - @provider_data.setter - def provider_data(self, provider_data): - if provider_data is not None: - try: - if any(not isinstance(p, UserProvider) for p in provider_data): - raise ValueError('One or more provider data instances are invalid.') - except TypeError as err: - raise ValueError('provider_data must be iterable.') from err - self._provider_data = provider_data - - @property - def custom_claims(self): - return self._custom_claims - - @custom_claims.setter - def custom_claims(self, custom_claims): - json_claims = json.dumps(custom_claims) if isinstance( - custom_claims, dict) else custom_claims - self._custom_claims_str = _auth_utils.validate_custom_claims(json_claims) - self._custom_claims = custom_claims - - def to_dict(self): - """Returns a dict representation of the user. For internal use only.""" - payload = { - 'localId': self.uid, - 'email': self.email, - 'displayName': self.display_name, - 'phoneNumber': self.phone_number, - 'photoUrl': self.photo_url, - 'emailVerified': (bool(self.email_verified) - if self.email_verified is not None else None), - 'disabled': bool(self.disabled) if self.disabled is not None else None, - 'customAttributes': self._custom_claims_str, - 'createdAt': self._created_at, - 'lastLoginAt': self._last_login_at, - 'passwordHash': b64_encode(self.password_hash) if self.password_hash else None, - 'salt': b64_encode(self.password_salt) if self.password_salt else None, - } - if self.provider_data: - payload['providerUserInfo'] = [p.to_dict() for p in self.provider_data] - return {k: v for k, v in payload.items() if v is not None} - - -class UserImportHash: - """Represents a hash algorithm used to hash user passwords. - - An instance of this class must be specified when importing users with passwords via the - ``auth.import_users()`` API. Use one of the provided class methods to obtain new - instances when required. Refer to `documentation`_ for more details. - - .. _documentation: https://firebase.google.com/docs/auth/admin/import-users - """ - - def __init__(self, name, data=None): - self._name = name - self._data = data - - def to_dict(self): - payload = {'hashAlgorithm': self._name} - if self._data: - payload.update(self._data) - return payload - - @classmethod - def _hmac(cls, name, key): - data = { - 'signerKey': b64_encode(_auth_utils.validate_bytes(key, 'key', required=True)) - } - return UserImportHash(name, data) - - @classmethod - def hmac_sha512(cls, key): - """Creates a new HMAC SHA512 algorithm instance. - - Args: - key: Signer key as a byte sequence. - - Returns: - UserImportHash: A new ``UserImportHash``. - """ - return cls._hmac('HMAC_SHA512', key) - - @classmethod - def hmac_sha256(cls, key): - """Creates a new HMAC SHA256 algorithm instance. - - Args: - key: Signer key as a byte sequence. - - Returns: - UserImportHash: A new ``UserImportHash``. - """ - return cls._hmac('HMAC_SHA256', key) - - @classmethod - def hmac_sha1(cls, key): - """Creates a new HMAC SHA1 algorithm instance. - - Args: - key: Signer key as a byte sequence. - - Returns: - UserImportHash: A new ``UserImportHash``. - """ - return cls._hmac('HMAC_SHA1', key) - - @classmethod - def hmac_md5(cls, key): - """Creates a new HMAC MD5 algorithm instance. - - Args: - key: Signer key as a byte sequence. - - Returns: - UserImportHash: A new ``UserImportHash``. - """ - return cls._hmac('HMAC_MD5', key) - - @classmethod - def md5(cls, rounds): - """Creates a new MD5 algorithm instance. - - Args: - rounds: Number of rounds. Must be an integer between 0 and 8192. - - Returns: - UserImportHash: A new ``UserImportHash``. - """ - return UserImportHash( - 'MD5', - {'rounds': _auth_utils.validate_int(rounds, 'rounds', 0, 8192)}) - - @classmethod - def sha1(cls, rounds): - """Creates a new SHA1 algorithm instance. - - Args: - rounds: Number of rounds. Must be an integer between 1 and 8192. - - Returns: - UserImportHash: A new ``UserImportHash``. - """ - return UserImportHash( - 'SHA1', - {'rounds': _auth_utils.validate_int(rounds, 'rounds', 1, 8192)}) - - @classmethod - def sha256(cls, rounds): - """Creates a new SHA256 algorithm instance. - - Args: - rounds: Number of rounds. Must be an integer between 1 and 8192. - - Returns: - UserImportHash: A new ``UserImportHash``. - """ - return UserImportHash( - 'SHA256', - {'rounds': _auth_utils.validate_int(rounds, 'rounds', 1, 8192)}) - - @classmethod - def sha512(cls, rounds): - """Creates a new SHA512 algorithm instance. - - Args: - rounds: Number of rounds. Must be an integer between 1 and 8192. - - Returns: - UserImportHash: A new ``UserImportHash``. - """ - return UserImportHash( - 'SHA512', - {'rounds': _auth_utils.validate_int(rounds, 'rounds', 1, 8192)}) - - @classmethod - def pbkdf_sha1(cls, rounds): - """Creates a new PBKDF SHA1 algorithm instance. - - Args: - rounds: Number of rounds. Must be an integer between 0 and 120000. - - Returns: - UserImportHash: A new ``UserImportHash``. - """ - return UserImportHash( - 'PBKDF_SHA1', - {'rounds': _auth_utils.validate_int(rounds, 'rounds', 0, 120000)}) - - @classmethod - def pbkdf2_sha256(cls, rounds): - """Creates a new PBKDF2 SHA256 algorithm instance. - - Args: - rounds: Number of rounds. Must be an integer between 0 and 120000. - - Returns: - UserImportHash: A new ``UserImportHash``. - """ - return UserImportHash( - 'PBKDF2_SHA256', - {'rounds': _auth_utils.validate_int(rounds, 'rounds', 0, 120000)}) - - @classmethod - def scrypt(cls, key, rounds, memory_cost, salt_separator=None): - """Creates a new Scrypt algorithm instance. - - This is the modified Scrypt algorithm used by Firebase Auth. See ``standard_scrypt()`` - function for the standard Scrypt algorith, - - Args: - key: Signer key as a byte sequence. - rounds: Number of rounds. Must be an integer between 1 and 8. - memory_cost: Memory cost as an integer between 1 and 14. - salt_separator: Salt separator as a byte sequence (optional). - - Returns: - UserImportHash: A new ``UserImportHash``. - """ - data = { - 'signerKey': b64_encode(_auth_utils.validate_bytes(key, 'key', required=True)), - 'rounds': _auth_utils.validate_int(rounds, 'rounds', 1, 8), - 'memoryCost': _auth_utils.validate_int(memory_cost, 'memory_cost', 1, 14), - } - if salt_separator: - data['saltSeparator'] = b64_encode(_auth_utils.validate_bytes( - salt_separator, 'salt_separator')) - return UserImportHash('SCRYPT', data) - - @classmethod - def bcrypt(cls): - """Creates a new Bcrypt algorithm instance. - - Returns: - UserImportHash: A new ``UserImportHash``. - """ - return UserImportHash('BCRYPT') - - @classmethod - def standard_scrypt(cls, memory_cost, parallelization, block_size, derived_key_length): - """Creates a new standard Scrypt algorithm instance. - - Args: - memory_cost: CPU Memory cost as a non-negative integer. - parallelization: Parallelization as a non-negative integer. - block_size: Block size as a non-negative integer. - derived_key_length: Derived key length as a non-negative integer. - - Returns: - UserImportHash: A new ``UserImportHash``. - """ - data = { - 'cpuMemCost': _auth_utils.validate_int(memory_cost, 'memory_cost', low=0), - 'parallelization': _auth_utils.validate_int(parallelization, 'parallelization', low=0), - 'blockSize': _auth_utils.validate_int(block_size, 'block_size', low=0), - 'dkLen': _auth_utils.validate_int(derived_key_length, 'derived_key_length', low=0), - } - return UserImportHash('STANDARD_SCRYPT', data) - - -class ErrorInfo: - """Represents an error encountered while performing a batch operation such - as importing users or deleting multiple user accounts. - """ - # TODO(rsgowman): This class used to be specific to importing users (hence - # it's home in _user_import.py). It's now also used by bulk deletion of - # users. Move this to a more common location. - - def __init__(self, error): - self._index = error['index'] - self._reason = error['message'] - - @property - def index(self): - return self._index - - @property - def reason(self): - return self._reason - - -class UserImportResult: - """Represents the result of a bulk user import operation. - - See ``auth.import_users()`` API for more details. - """ - - def __init__(self, result, total): - errors = result.get('error', []) - self._success_count = total - len(errors) - self._failure_count = len(errors) - self._errors = [ErrorInfo(err) for err in errors] - - @property - def success_count(self): - """Returns the number of users successfully imported.""" - return self._success_count - - @property - def failure_count(self): - """Returns the number of users that failed to be imported.""" - return self._failure_count - - @property - def errors(self): - """Returns a list of ``auth.ErrorInfo`` instances describing the errors encountered.""" - return self._errors diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/_user_mgt.py b/notification-service/venv/Lib/site-packages/firebase_admin/_user_mgt.py deleted file mode 100644 index e782549..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/_user_mgt.py +++ /dev/null @@ -1,874 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase user management sub module.""" - -import base64 -from collections import defaultdict -import json -from typing import Optional -from urllib import parse -import warnings - -import requests - -from firebase_admin import _auth_utils -from firebase_admin import _rfc3339 -from firebase_admin import _user_identifier -from firebase_admin import _user_import -from firebase_admin._user_import import ErrorInfo - - -MAX_LIST_USERS_RESULTS = 1000 -MAX_IMPORT_USERS_SIZE = 1000 -B64_REDACTED = base64.b64encode(b'REDACTED') - - -class Sentinel: - - def __init__(self, description): - self.description = description - - -DELETE_ATTRIBUTE = Sentinel('Value used to delete an attribute from a user profile') - - -class UserMetadata: - """Contains additional metadata associated with a user account.""" - - def __init__(self, creation_timestamp=None, last_sign_in_timestamp=None, - last_refresh_timestamp=None): - self._creation_timestamp = _auth_utils.validate_timestamp( - creation_timestamp, 'creation_timestamp') - self._last_sign_in_timestamp = _auth_utils.validate_timestamp( - last_sign_in_timestamp, 'last_sign_in_timestamp') - self._last_refresh_timestamp = _auth_utils.validate_timestamp( - last_refresh_timestamp, 'last_refresh_timestamp') - - @property - def creation_timestamp(self): - """ Creation timestamp in milliseconds since the epoch. - - Returns: - integer: The user creation timestamp in milliseconds since the epoch. - """ - return self._creation_timestamp - - @property - def last_sign_in_timestamp(self): - """ Last sign in timestamp in milliseconds since the epoch. - - Returns: - integer: The last sign in timestamp in milliseconds since the epoch. - """ - return self._last_sign_in_timestamp - - @property - def last_refresh_timestamp(self): - """The time at which the user was last active (ID token refreshed). - - Returns: - integer: Milliseconds since epoch timestamp, or `None` if the user was - never active. - """ - return self._last_refresh_timestamp - - -class UserInfo: - """A collection of standard profile information for a user. - - Used to expose profile information returned by an identity provider. - """ - - @property - def uid(self): - """Returns the user ID of this user.""" - raise NotImplementedError - - @property - def display_name(self): - """Returns the display name of this user.""" - raise NotImplementedError - - @property - def email(self): - """Returns the email address associated with this user.""" - raise NotImplementedError - - @property - def phone_number(self): - """Returns the phone number associated with this user.""" - raise NotImplementedError - - @property - def photo_url(self): - """Returns the photo URL of this user.""" - raise NotImplementedError - - @property - def provider_id(self): - """Returns the ID of the identity provider. - - This can be a short domain name (e.g. google.com), or the identity of an OpenID - identity provider. - """ - raise NotImplementedError - - -class UserRecord(UserInfo): - """Contains metadata associated with a Firebase user account.""" - - def __init__(self, data): - super().__init__() - if not isinstance(data, dict): - raise ValueError(f'Invalid data argument: {data}. Must be a dictionary.') - if not data.get('localId'): - raise ValueError('User ID must not be None or empty.') - self._data = data - - @property - def uid(self): - """Returns the user ID of this user. - - Returns: - string: A user ID string. This value is never None or empty. - """ - return self._data.get('localId') - - @property - def display_name(self): - """Returns the display name of this user. - - Returns: - string: A display name string or None. - """ - return self._data.get('displayName') - - @property - def email(self): - """Returns the email address associated with this user. - - Returns: - string: An email address string or None. - """ - return self._data.get('email') - - @property - def phone_number(self): - """Returns the phone number associated with this user. - - Returns: - string: A phone number string or None. - """ - return self._data.get('phoneNumber') - - @property - def photo_url(self): - """Returns the photo URL of this user. - - Returns: - string: A URL string or None. - """ - return self._data.get('photoUrl') - - @property - def provider_id(self): - """Returns the provider ID of this user. - - Returns: - string: A constant provider ID value. - """ - return 'firebase' - - @property - def email_verified(self): - """Returns whether the email address of this user has been verified. - - Returns: - bool: True if the email has been verified, and False otherwise. - """ - return bool(self._data.get('emailVerified')) - - @property - def disabled(self): - """Returns whether this user account is disabled. - - Returns: - bool: True if the user account is disabled, and False otherwise. - """ - return bool(self._data.get('disabled')) - - @property - def tokens_valid_after_timestamp(self): - """Returns the time, in milliseconds since the epoch, before which tokens are invalid. - - Note: this is truncated to 1 second accuracy. - - Returns: - int: Timestamp in milliseconds since the epoch, truncated to the second. - All tokens issued before that time are considered revoked. - """ - valid_since = self._data.get('validSince') - if valid_since is not None: - return 1000 * int(valid_since) - return 0 - - @property - def user_metadata(self): - """Returns additional metadata associated with this user. - - Returns: - UserMetadata: A UserMetadata instance. Does not return None. - """ - def _int_or_none(key): - if key in self._data: - return int(self._data[key]) - return None - last_refresh_at_millis = None - last_refresh_at_rfc3339 = self._data.get('lastRefreshAt', None) - if last_refresh_at_rfc3339: - last_refresh_at_millis = int(_rfc3339.parse_to_epoch(last_refresh_at_rfc3339) * 1000) - return UserMetadata( - _int_or_none('createdAt'), _int_or_none('lastLoginAt'), last_refresh_at_millis) - - @property - def provider_data(self): - """Returns a list of UserInfo instances. - - Each object represents an identity from an identity provider that is linked to this user. - - Returns: - list: A list of UserInfo objects, which may be empty. - """ - providers = self._data.get('providerUserInfo', []) - return [ProviderUserInfo(entry) for entry in providers] - - @property - def custom_claims(self): - """Returns any custom claims set on this user account. - - Returns: - dict: A dictionary of claims or None. - """ - claims = self._data.get('customAttributes') - if claims: - parsed = json.loads(claims) - if parsed != {}: - return parsed - return None - - @property - def tenant_id(self): - """Returns the tenant ID of this user. - - Returns: - string: A tenant ID string or None. - """ - return self._data.get('tenantId') - - -class ExportedUserRecord(UserRecord): - """Contains metadata associated with a user including password hash and salt.""" - - @property - def password_hash(self): - """The user's password hash as a base64-encoded string. - - If the Firebase Auth hashing algorithm (SCRYPT) was used to create the user account, this - is the base64-encoded password hash of the user. If a different hashing algorithm was - used to create this user, as is typical when migrating from another Auth system, this - is an empty string. If no password is set, or if the service account doesn't have permission - to read the password, then this is ``None``. - """ - password_hash = self._data.get('passwordHash') - - # If the password hash is redacted (probably due to missing permissions) then clear it out, - # similar to how the salt is returned. (Otherwise, it *looks* like a b64-encoded hash is - # present, which is confusing.) - if password_hash == B64_REDACTED: - return None - return password_hash - - @property - def password_salt(self): - """The user's password salt as a base64-encoded string. - - If the Firebase Auth hashing algorithm (SCRYPT) was used to create the user account, this - is the base64-encoded password salt of the user. If a different hashing algorithm was - used to create this user, as is typical when migrating from another Auth system, this is - an empty string. If no password is set, or if the service account doesn't have permission to - read the password, then this is ``None``. - """ - return self._data.get('salt') - - -class GetUsersResult: - """Represents the result of the ``auth.get_users()`` API.""" - - def __init__(self, users, not_found): - """Constructs a `GetUsersResult` object. - - Args: - users: List of `UserRecord` instances. - not_found: List of `UserIdentifier` instances. - """ - self._users = users - self._not_found = not_found - - @property - def users(self): - """Set of `UserRecord` instances, corresponding to the set of users - that were requested. Only users that were found are listed here. The - result set is unordered. - """ - return self._users - - @property - def not_found(self): - """Set of `UserIdentifier` instances that were requested, but not - found. - """ - return self._not_found - - -class ListUsersPage: - """Represents a page of user records exported from a Firebase project. - - Provides methods for traversing the user accounts included in this page, as well as retrieving - subsequent pages of users. The iterator returned by ``iterate_all()`` can be used to iterate - through all users in the Firebase project starting from this page. - """ - - def __init__(self, download, page_token, max_results): - self._download = download - self._max_results = max_results - self._current = download(page_token, max_results) - - @property - def users(self): - """A list of ``ExportedUserRecord`` instances available in this page.""" - return [ExportedUserRecord(user) for user in self._current.get('users', [])] - - @property - def next_page_token(self): - """Page token string for the next page (empty string indicates no more pages).""" - return self._current.get('nextPageToken', '') - - @property - def has_next_page(self): - """A boolean indicating whether more pages are available.""" - return bool(self.next_page_token) - - def get_next_page(self): - """Retrieves the next page of user accounts, if available. - - Returns: - ListUsersPage: Next page of users, or None if this is the last page. - """ - if self.has_next_page: - return ListUsersPage(self._download, self.next_page_token, self._max_results) - return None - - def iterate_all(self): - """Retrieves an iterator for user accounts. - - Returned iterator will iterate through all the user accounts in the Firebase project - starting from this page. The iterator will never buffer more than one page of users - in memory at a time. - - Returns: - iterator: An iterator of ExportedUserRecord instances. - """ - return _UserIterator(self) - - -class DeleteUsersResult: - """Represents the result of the ``auth.delete_users()`` API.""" - - def __init__(self, result, total): - """Constructs a `DeleteUsersResult` object. - - Args: - result: The proto response, wrapped in a - `BatchDeleteAccountsResponse` instance. - total: Total integer number of deletion attempts. - """ - errors = result.errors - self._success_count = total - len(errors) - self._failure_count = len(errors) - self._errors = errors - - @property - def success_count(self): - """Returns the number of users that were deleted successfully (possibly - zero). - - Users that did not exist prior to calling `delete_users()` are - considered to be successfully deleted. - """ - return self._success_count - - @property - def failure_count(self): - """Returns the number of users that failed to be deleted (possibly - zero). - """ - return self._failure_count - - @property - def errors(self): - """A list of `auth.ErrorInfo` instances describing the errors that - were encountered during the deletion. Length of this list is equal to - `failure_count`. - """ - return self._errors - - -class BatchDeleteAccountsResponse: - """Represents the results of a `delete_users()` call.""" - - def __init__(self, errors=None): - """Constructs a `BatchDeleteAccountsResponse` instance, corresponding to - the JSON representing the `BatchDeleteAccountsResponse` proto. - - Args: - errors: List of dictionaries, with each dictionary representing an - `ErrorInfo` instance as returned by the server. `None` implies - an empty list. - """ - self.errors = [ErrorInfo(err) for err in errors] if errors else [] - - -class ProviderUserInfo(UserInfo): - """Contains metadata regarding how a user is known by a particular identity provider.""" - - def __init__(self, data): - super().__init__() - if not isinstance(data, dict): - raise ValueError(f'Invalid data argument: {data}. Must be a dictionary.') - if not data.get('rawId'): - raise ValueError('User ID must not be None or empty.') - self._data = data - - @property - def uid(self): - return self._data.get('rawId') - - @property - def display_name(self): - return self._data.get('displayName') - - @property - def email(self): - return self._data.get('email') - - @property - def phone_number(self): - return self._data.get('phoneNumber') - - @property - def photo_url(self): - return self._data.get('photoUrl') - - @property - def provider_id(self): - return self._data.get('providerId') - - -class ActionCodeSettings: - """Contains required continue/state URL with optional Android and iOS settings. - Used when invoking the email action link generation APIs. - """ - - def __init__( - self, - url: str, - handle_code_in_app: Optional[bool] = None, - dynamic_link_domain: Optional[str] = None, - ios_bundle_id: Optional[str] = None, - android_package_name: Optional[str] = None, - android_install_app: Optional[str] = None, - android_minimum_version: Optional[str] = None, - link_domain: Optional[str] = None, - ): - if dynamic_link_domain is not None: - warnings.warn( - 'dynamic_link_domain is deprecated, use link_domain instead', - DeprecationWarning - ) - self.url = url - self.handle_code_in_app = handle_code_in_app - self.dynamic_link_domain = dynamic_link_domain - self.ios_bundle_id = ios_bundle_id - self.android_package_name = android_package_name - self.android_install_app = android_install_app - self.android_minimum_version = android_minimum_version - self.link_domain = link_domain - - -def encode_action_code_settings(settings): - """ Validates the provided action code settings for email link generation and - populates the REST api parameters. - - settings - ``ActionCodeSettings`` object provided to be encoded - returns - dict of parameters to be passed for link gereration. - """ - - parameters = {} - # url - if not settings.url: - raise ValueError("Dynamic action links url is mandatory") - - try: - parsed = parse.urlparse(settings.url) - if not parsed.netloc: - raise ValueError(f'Malformed dynamic action links url: "{settings.url}".') - parameters['continueUrl'] = settings.url - except Exception as err: - raise ValueError(f'Malformed dynamic action links url: "{settings.url}".') from err - - # handle_code_in_app - if settings.handle_code_in_app is not None: - if not isinstance(settings.handle_code_in_app, bool): - raise ValueError( - f'Invalid value provided for handle_code_in_app: {settings.handle_code_in_app}') - parameters['canHandleCodeInApp'] = settings.handle_code_in_app - - # dynamic_link_domain - if settings.dynamic_link_domain is not None: - if not isinstance(settings.dynamic_link_domain, str): - raise ValueError( - f'Invalid value provided for dynamic_link_domain: {settings.dynamic_link_domain}') - parameters['dynamicLinkDomain'] = settings.dynamic_link_domain - - # link_domain - if settings.link_domain is not None: - if not isinstance(settings.link_domain, str): - raise ValueError( - f'Invalid value provided for link_domain: {settings.link_domain}') - parameters['linkDomain'] = settings.link_domain - - # ios_bundle_id - if settings.ios_bundle_id is not None: - if not isinstance(settings.ios_bundle_id, str): - raise ValueError( - f'Invalid value provided for ios_bundle_id: {settings.ios_bundle_id}') - parameters['iOSBundleId'] = settings.ios_bundle_id - - # android_* attributes - if (settings.android_minimum_version or settings.android_install_app) \ - and not settings.android_package_name: - raise ValueError("Android package name is required when specifying other Android settings") - - if settings.android_package_name is not None: - if not isinstance(settings.android_package_name, str): - raise ValueError( - f'Invalid value provided for android_package_name: {settings.android_package_name}') - parameters['androidPackageName'] = settings.android_package_name - - if settings.android_minimum_version is not None: - if not isinstance(settings.android_minimum_version, str): - raise ValueError( - 'Invalid value provided for android_minimum_version: ' - f'{settings.android_minimum_version}') - parameters['androidMinimumVersion'] = settings.android_minimum_version - - if settings.android_install_app is not None: - if not isinstance(settings.android_install_app, bool): - raise ValueError( - f'Invalid value provided for android_install_app: {settings.android_install_app}') - parameters['androidInstallApp'] = settings.android_install_app - - return parameters - - -class UserManager: - """Provides methods for interacting with the Google Identity Toolkit.""" - - ID_TOOLKIT_URL = 'https://identitytoolkit.googleapis.com/v1' - - def __init__(self, http_client, project_id, tenant_id=None, url_override=None): - self.http_client = http_client - url_prefix = url_override or self.ID_TOOLKIT_URL - self.base_url = f'{url_prefix}/projects/{project_id}' - if tenant_id: - self.base_url += f'/tenants/{tenant_id}' - - def get_user(self, **kwargs): - """Gets the user data corresponding to the provided key.""" - if 'uid' in kwargs: - key, key_type = kwargs.pop('uid'), 'user ID' - payload = {'localId' : [_auth_utils.validate_uid(key, required=True)]} - elif 'email' in kwargs: - key, key_type = kwargs.pop('email'), 'email' - payload = {'email' : [_auth_utils.validate_email(key, required=True)]} - elif 'phone_number' in kwargs: - key, key_type = kwargs.pop('phone_number'), 'phone number' - payload = {'phoneNumber' : [_auth_utils.validate_phone(key, required=True)]} - else: - raise TypeError(f'Unsupported keyword arguments: {kwargs}.') - - body, http_resp = self._make_request('post', '/accounts:lookup', json=payload) - if not body or not body.get('users'): - raise _auth_utils.UserNotFoundError( - f'No user record found for the provided {key_type}: {key}.', - http_response=http_resp) - return body['users'][0] - - def get_users(self, identifiers): - """Looks up multiple users by their identifiers (uid, email, etc.) - - Args: - identifiers: UserIdentifier[]: The identifiers indicating the user - to be looked up. Must have <= 100 entries. - - Returns: - list[dict[string, string]]: List of dicts representing the JSON - `UserInfo` responses from the server. - - Raises: - ValueError: If any of the identifiers are invalid or if more than - 100 identifiers are specified. - UnexpectedResponseError: If the backend server responds with an - unexpected message. - """ - if not identifiers: - return [] - if len(identifiers) > 100: - raise ValueError('`identifiers` parameter must have <= 100 entries.') - - payload = defaultdict(list) - for identifier in identifiers: - if isinstance(identifier, _user_identifier.UidIdentifier): - payload['localId'].append(identifier.uid) - elif isinstance(identifier, _user_identifier.EmailIdentifier): - payload['email'].append(identifier.email) - elif isinstance(identifier, _user_identifier.PhoneIdentifier): - payload['phoneNumber'].append(identifier.phone_number) - elif isinstance(identifier, _user_identifier.ProviderIdentifier): - payload['federatedUserId'].append({ - 'providerId': identifier.provider_id, - 'rawId': identifier.provider_uid - }) - else: - raise ValueError( - f'Invalid entry in "identifiers" list. Unsupported type: {type(identifier)}') - - body, http_resp = self._make_request( - 'post', '/accounts:lookup', json=payload) - if not http_resp.ok: - raise _auth_utils.UnexpectedResponseError( - 'Failed to get users.', http_response=http_resp) - return body.get('users', []) - - def list_users(self, page_token=None, max_results=MAX_LIST_USERS_RESULTS): - """Retrieves a batch of users.""" - if page_token is not None: - if not isinstance(page_token, str) or not page_token: - raise ValueError('Page token must be a non-empty string.') - if not isinstance(max_results, int): - raise ValueError('Max results must be an integer.') - if max_results < 1 or max_results > MAX_LIST_USERS_RESULTS: - raise ValueError( - f'Max results must be a positive integer less than {MAX_LIST_USERS_RESULTS}.') - - payload = {'maxResults': max_results} - if page_token: - payload['nextPageToken'] = page_token - body, _ = self._make_request('get', '/accounts:batchGet', params=payload) - return body - - def create_user(self, uid=None, display_name=None, email=None, phone_number=None, - photo_url=None, password=None, disabled=None, email_verified=None): - """Creates a new user account with the specified properties.""" - payload = { - 'localId': _auth_utils.validate_uid(uid), - 'displayName': _auth_utils.validate_display_name(display_name), - 'email': _auth_utils.validate_email(email), - 'phoneNumber': _auth_utils.validate_phone(phone_number), - 'photoUrl': _auth_utils.validate_photo_url(photo_url), - 'password': _auth_utils.validate_password(password), - 'emailVerified': bool(email_verified) if email_verified is not None else None, - 'disabled': bool(disabled) if disabled is not None else None, - } - payload = {k: v for k, v in payload.items() if v is not None} - body, http_resp = self._make_request('post', '/accounts', json=payload) - if not body or not body.get('localId'): - raise _auth_utils.UnexpectedResponseError( - 'Failed to create new user.', http_response=http_resp) - return body.get('localId') - - def update_user(self, uid, display_name=None, email=None, phone_number=None, - photo_url=None, password=None, disabled=None, email_verified=None, - valid_since=None, custom_claims=None, providers_to_delete=None): - """Updates an existing user account with the specified properties""" - payload = { - 'localId': _auth_utils.validate_uid(uid, required=True), - 'email': _auth_utils.validate_email(email), - 'password': _auth_utils.validate_password(password), - 'validSince': _auth_utils.validate_timestamp(valid_since, 'valid_since'), - 'emailVerified': bool(email_verified) if email_verified is not None else None, - 'disableUser': bool(disabled) if disabled is not None else None, - } - - remove = [] - remove_provider = _auth_utils.validate_provider_ids(providers_to_delete) - if display_name is not None: - if display_name is DELETE_ATTRIBUTE: - remove.append('DISPLAY_NAME') - else: - payload['displayName'] = _auth_utils.validate_display_name(display_name) - if photo_url is not None: - if photo_url is DELETE_ATTRIBUTE: - remove.append('PHOTO_URL') - else: - payload['photoUrl'] = _auth_utils.validate_photo_url(photo_url) - if remove: - payload['deleteAttribute'] = remove - - if phone_number is not None: - if phone_number is DELETE_ATTRIBUTE: - remove_provider.append('phone') - else: - payload['phoneNumber'] = _auth_utils.validate_phone(phone_number) - - if custom_claims is not None: - if custom_claims is DELETE_ATTRIBUTE: - custom_claims = {} - json_claims = json.dumps(custom_claims) if isinstance( - custom_claims, dict) else custom_claims - payload['customAttributes'] = _auth_utils.validate_custom_claims(json_claims) - - if remove_provider: - payload['deleteProvider'] = list(set(remove_provider)) - - payload = {k: v for k, v in payload.items() if v is not None} - body, http_resp = self._make_request('post', '/accounts:update', json=payload) - if not body or not body.get('localId'): - raise _auth_utils.UnexpectedResponseError( - f'Failed to update user: {uid}.', http_response=http_resp) - return body.get('localId') - - def delete_user(self, uid): - """Deletes the user identified by the specified user ID.""" - _auth_utils.validate_uid(uid, required=True) - body, http_resp = self._make_request('post', '/accounts:delete', json={'localId' : uid}) - if not body or not body.get('kind'): - raise _auth_utils.UnexpectedResponseError( - f'Failed to delete user: {uid}.', http_response=http_resp) - - def delete_users(self, uids, force_delete=False): - """Deletes the users identified by the specified user ids. - - Args: - uids: A list of strings indicating the uids of the users to be deleted. - Must have <= 1000 entries. - force_delete: Optional parameter that indicates if users should be - deleted, even if they're not disabled. Defaults to False. - - - Returns: - BatchDeleteAccountsResponse: Server's proto response, wrapped in a - python object. - - Raises: - ValueError: If any of the identifiers are invalid or if more than 1000 - identifiers are specified. - UnexpectedResponseError: If the backend server responds with an - unexpected message. - """ - if not uids: - return BatchDeleteAccountsResponse() - - if len(uids) > 1000: - raise ValueError("`uids` paramter must have <= 1000 entries.") - for uid in uids: - _auth_utils.validate_uid(uid, required=True) - - body, http_resp = self._make_request('post', '/accounts:batchDelete', - json={'localIds': uids, 'force': force_delete}) - if not isinstance(body, dict): - raise _auth_utils.UnexpectedResponseError( - 'Unexpected response from server while attempting to delete users.', - http_response=http_resp) - return BatchDeleteAccountsResponse(body.get('errors', [])) - - def import_users(self, users, hash_alg=None): - """Imports the given list of users to Firebase Auth.""" - try: - if not users or len(users) > MAX_IMPORT_USERS_SIZE: - raise ValueError( - 'Users must be a non-empty list with no more than ' - f'{MAX_IMPORT_USERS_SIZE} elements.') - if any(not isinstance(u, _user_import.ImportUserRecord) for u in users): - raise ValueError('One or more user objects are invalid.') - except TypeError as err: - raise ValueError('users must be iterable') from err - - payload = {'users': [u.to_dict() for u in users]} - if any('passwordHash' in u for u in payload['users']): - if not isinstance(hash_alg, _user_import.UserImportHash): - raise ValueError('A UserImportHash is required to import users with passwords.') - payload.update(hash_alg.to_dict()) - body, http_resp = self._make_request('post', '/accounts:batchCreate', json=payload) - if not isinstance(body, dict): - raise _auth_utils.UnexpectedResponseError( - 'Failed to import users.', http_response=http_resp) - return body - - def generate_email_action_link(self, action_type, email, action_code_settings=None): - """Fetches the email action links for types - - Args: - action_type: String. Valid values ['VERIFY_EMAIL', 'EMAIL_SIGNIN', 'PASSWORD_RESET'] - email: Email of the user for which the action is performed - action_code_settings: ``ActionCodeSettings`` object or dict (optional). Defines whether - the link is to be handled by a mobile app and the additional state information to be - passed in the deep link, etc. - Returns: - link_url: action url to be emailed to the user - - Raises: - UnexpectedResponseError: If the backend server responds with an unexpected message - FirebaseError: If an error occurs while generating the link - ValueError: If the provided arguments are invalid - """ - payload = { - 'requestType': _auth_utils.validate_action_type(action_type), - 'email': _auth_utils.validate_email(email), - 'returnOobLink': True - } - - if action_code_settings: - payload.update(encode_action_code_settings(action_code_settings)) - - body, http_resp = self._make_request('post', '/accounts:sendOobCode', json=payload) - if not body or not body.get('oobLink'): - raise _auth_utils.UnexpectedResponseError( - 'Failed to generate email action link.', http_response=http_resp) - return body.get('oobLink') - - def _make_request(self, method, path, **kwargs): - url = f'{self.base_url}{path}' - try: - return self.http_client.body_and_response(method, url, **kwargs) - except requests.exceptions.RequestException as error: - raise _auth_utils.handle_auth_backend_error(error) - - -class _UserIterator(_auth_utils.PageIterator): - - @property - def items(self): - return self._current_page.users diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/_utils.py b/notification-service/venv/Lib/site-packages/firebase_admin/_utils.py deleted file mode 100644 index 0277b9e..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/_utils.py +++ /dev/null @@ -1,347 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Internal utilities common to all modules.""" - -import json -from platform import python_version -from typing import Callable, Optional - -import google.auth -import requests -import httpx - -import firebase_admin -from firebase_admin import exceptions - - -_ERROR_CODE_TO_EXCEPTION_TYPE = { - exceptions.INVALID_ARGUMENT: exceptions.InvalidArgumentError, - exceptions.FAILED_PRECONDITION: exceptions.FailedPreconditionError, - exceptions.OUT_OF_RANGE: exceptions.OutOfRangeError, - exceptions.UNAUTHENTICATED: exceptions.UnauthenticatedError, - exceptions.PERMISSION_DENIED: exceptions.PermissionDeniedError, - exceptions.NOT_FOUND: exceptions.NotFoundError, - exceptions.ABORTED: exceptions.AbortedError, - exceptions.ALREADY_EXISTS: exceptions.AlreadyExistsError, - exceptions.CONFLICT: exceptions.ConflictError, - exceptions.RESOURCE_EXHAUSTED: exceptions.ResourceExhaustedError, - exceptions.CANCELLED: exceptions.CancelledError, - exceptions.DATA_LOSS: exceptions.DataLossError, - exceptions.UNKNOWN: exceptions.UnknownError, - exceptions.INTERNAL: exceptions.InternalError, - exceptions.UNAVAILABLE: exceptions.UnavailableError, - exceptions.DEADLINE_EXCEEDED: exceptions.DeadlineExceededError, -} - - -_HTTP_STATUS_TO_ERROR_CODE = { - 400: exceptions.INVALID_ARGUMENT, - 401: exceptions.UNAUTHENTICATED, - 403: exceptions.PERMISSION_DENIED, - 404: exceptions.NOT_FOUND, - 409: exceptions.CONFLICT, - 412: exceptions.FAILED_PRECONDITION, - 429: exceptions.RESOURCE_EXHAUSTED, - 500: exceptions.INTERNAL, - 503: exceptions.UNAVAILABLE, -} - - -# See https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto -_RPC_CODE_TO_ERROR_CODE = { - 1: exceptions.CANCELLED, - 2: exceptions.UNKNOWN, - 3: exceptions.INVALID_ARGUMENT, - 4: exceptions.DEADLINE_EXCEEDED, - 5: exceptions.NOT_FOUND, - 6: exceptions.ALREADY_EXISTS, - 7: exceptions.PERMISSION_DENIED, - 8: exceptions.RESOURCE_EXHAUSTED, - 9: exceptions.FAILED_PRECONDITION, - 10: exceptions.ABORTED, - 11: exceptions.OUT_OF_RANGE, - 13: exceptions.INTERNAL, - 14: exceptions.UNAVAILABLE, - 15: exceptions.DATA_LOSS, - 16: exceptions.UNAUTHENTICATED, -} - -def get_metrics_header(): - return f'gl-python/{python_version()} fire-admin/{firebase_admin.__version__}' - -def _get_initialized_app(app): - """Returns a reference to an initialized App instance.""" - if app is None: - return firebase_admin.get_app() - - if isinstance(app, firebase_admin.App): - initialized_app = firebase_admin.get_app(app.name) - if app is not initialized_app: - raise ValueError('Illegal app argument. App instance not ' - 'initialized via the firebase module.') - return app - - raise ValueError( - 'Illegal app argument. Argument must be of type firebase_admin.App, but given ' - f'"{type(app)}".') - - - -def get_app_service(app, name, initializer): - app = _get_initialized_app(app) - return app._get_service(name, initializer) # pylint: disable=protected-access - - -def handle_platform_error_from_requests(error, handle_func=None): - """Constructs a ``FirebaseError`` from the given requests error. - - This can be used to handle errors returned by Google Cloud Platform (GCP) APIs. - - Args: - error: An error raised by the requests module while making an HTTP call to a GCP API. - handle_func: A function that can be used to handle platform errors in a custom way. When - specified, this function will be called with three arguments. It has the same - signature as ```_handle_func_requests``, but may return ``None``. - - Returns: - FirebaseError: A ``FirebaseError`` that can be raised to the user code. - """ - if error.response is None: - return handle_requests_error(error) - - response = error.response - content = response.content.decode() - status_code = response.status_code - error_dict, message = _parse_platform_error(content, status_code) - exc = None - if handle_func: - exc = handle_func(error, message, error_dict) - - return exc if exc else _handle_func_requests(error, message, error_dict) - -def handle_platform_error_from_httpx( - error: httpx.HTTPError, - handle_func: Optional[Callable[..., Optional[exceptions.FirebaseError]]] = None -) -> exceptions.FirebaseError: - """Constructs a ``FirebaseError`` from the given httpx error. - - This can be used to handle errors returned by Google Cloud Platform (GCP) APIs. - - Args: - error: An error raised by the httpx module while making an HTTP call to a GCP API. - handle_func: A function that can be used to handle platform errors in a custom way. When - specified, this function will be called with three arguments. It has the same - signature as ```_handle_func_httpx``, but may return ``None``. - - Returns: - FirebaseError: A ``FirebaseError`` that can be raised to the user code. - """ - - if isinstance(error, httpx.HTTPStatusError): - response = error.response - content = response.content.decode() - status_code = response.status_code - error_dict, message = _parse_platform_error(content, status_code) - exc = None - if handle_func: - exc = handle_func(error, message, error_dict) - - return exc if exc else _handle_func_httpx(error, message, error_dict) - return handle_httpx_error(error) - - -def handle_operation_error(error): - """Constructs a ``FirebaseError`` from the given operation error. - - Args: - error: An error returned by a long running operation. - - Returns: - FirebaseError: A ``FirebaseError`` that can be raised to the user code. - """ - if not isinstance(error, dict): - return exceptions.UnknownError( - message=f'Unknown error while making a remote service call: {error}', - cause=error) - - rpc_code = error.get('code') - message = error.get('message') - error_code = _rpc_code_to_error_code(rpc_code) - err_type = _error_code_to_exception_type(error_code) - return err_type(message=message) - - -def _handle_func_requests(error, message, error_dict): - """Constructs a ``FirebaseError`` from the given GCP error. - - Args: - error: An error raised by the requests module while making an HTTP call. - message: A message to be included in the resulting ``FirebaseError``. - error_dict: Parsed GCP error response. - - Returns: - FirebaseError: A ``FirebaseError`` that can be raised to the user code or None. - """ - code = error_dict.get('status') - return handle_requests_error(error, message, code) - - -def handle_requests_error(error, message=None, code=None): - """Constructs a ``FirebaseError`` from the given requests error. - - This method is agnostic of the remote service that produced the error, whether it is a GCP - service or otherwise. Therefore, this method does not attempt to parse the error response in - any way. - - Args: - error: An error raised by the requests module while making an HTTP call. - message: A message to be included in the resulting ``FirebaseError`` (optional). If not - specified the string representation of the ``error`` argument is used as the message. - code: A GCP error code that will be used to determine the resulting error type (optional). - If not specified the HTTP status code on the error response is used to determine a - suitable error code. - - Returns: - FirebaseError: A ``FirebaseError`` that can be raised to the user code. - """ - if isinstance(error, requests.exceptions.Timeout): - return exceptions.DeadlineExceededError( - message=f'Timed out while making an API call: {error}', - cause=error) - if isinstance(error, requests.exceptions.ConnectionError): - return exceptions.UnavailableError( - message=f'Failed to establish a connection: {error}', - cause=error) - if error.response is None: - return exceptions.UnknownError( - message=f'Unknown error while making a remote service call: {error}', - cause=error) - - if not code: - code = _http_status_to_error_code(error.response.status_code) - if not message: - message = str(error) - - err_type = _error_code_to_exception_type(code) - return err_type(message=message, cause=error, http_response=error.response) - -def _handle_func_httpx(error: httpx.HTTPError, message, error_dict) -> exceptions.FirebaseError: - """Constructs a ``FirebaseError`` from the given GCP error. - - Args: - error: An error raised by the httpx module while making an HTTP call. - message: A message to be included in the resulting ``FirebaseError``. - error_dict: Parsed GCP error response. - - Returns: - FirebaseError: A ``FirebaseError`` that can be raised to the user code or None. - """ - code = error_dict.get('status') - return handle_httpx_error(error, message, code) - - -def handle_httpx_error(error: httpx.HTTPError, message=None, code=None) -> exceptions.FirebaseError: - """Constructs a ``FirebaseError`` from the given httpx error. - - This method is agnostic of the remote service that produced the error, whether it is a GCP - service or otherwise. Therefore, this method does not attempt to parse the error response in - any way. - - Args: - error: An error raised by the httpx module while making an HTTP call. - message: A message to be included in the resulting ``FirebaseError`` (optional). If not - specified the string representation of the ``error`` argument is used as the message. - code: A GCP error code that will be used to determine the resulting error type (optional). - If not specified the HTTP status code on the error response is used to determine a - suitable error code. - - Returns: - FirebaseError: A ``FirebaseError`` that can be raised to the user code. - """ - if isinstance(error, httpx.TimeoutException): - return exceptions.DeadlineExceededError( - message=f'Timed out while making an API call: {error}', - cause=error) - if isinstance(error, httpx.ConnectError): - return exceptions.UnavailableError( - message=f'Failed to establish a connection: {error}', - cause=error) - if isinstance(error, httpx.HTTPStatusError): - if not code: - code = _http_status_to_error_code(error.response.status_code) - if not message: - message = str(error) - - err_type = _error_code_to_exception_type(code) - return err_type(message=message, cause=error, http_response=error.response) - - return exceptions.UnknownError( - message=f'Unknown error while making a remote service call: {error}', - cause=error) - -def _http_status_to_error_code(status): - """Maps an HTTP status to a platform error code.""" - return _HTTP_STATUS_TO_ERROR_CODE.get(status, exceptions.UNKNOWN) - -def _rpc_code_to_error_code(rpc_code): - """Maps an RPC code to a platform error code.""" - return _RPC_CODE_TO_ERROR_CODE.get(rpc_code, exceptions.UNKNOWN) - -def _error_code_to_exception_type(code): - """Maps a platform error code to an exception type.""" - return _ERROR_CODE_TO_EXCEPTION_TYPE.get(code, exceptions.UnknownError) - - -def _parse_platform_error(content, status_code): - """Parses an HTTP error response from a Google Cloud Platform API and extracts the error code - and message fields. - - Args: - content: Decoded content of the response body. - status_code: HTTP status code. - - Returns: - tuple: A tuple containing error code and message. - """ - data = {} - try: - parsed_body = json.loads(content) - if isinstance(parsed_body, dict): - data = parsed_body - except ValueError: - pass - - error_dict = data.get('error', {}) - msg = error_dict.get('message') - if not msg: - msg = f'Unexpected HTTP response with status: {status_code}; body: {content}' - return error_dict, msg - - -# Temporarily disable the lint rule. For more information see: -# https://github.com/googleapis/google-auth-library-python/pull/561 -# pylint: disable=abstract-method -class EmulatorAdminCredentials(google.auth.credentials.Credentials): - """ Credentials for use with the firebase local emulator. - - This is used instead of user-supplied credentials or ADC. It will silently do nothing when - asked to refresh credentials. - """ - def __init__(self): - google.auth.credentials.Credentials.__init__(self) - self.token = 'owner' - - def refresh(self, request): - pass diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/app_check.py b/notification-service/venv/Lib/site-packages/firebase_admin/app_check.py deleted file mode 100644 index 40d857f..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/app_check.py +++ /dev/null @@ -1,161 +0,0 @@ -# Copyright 2022 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase App Check module.""" - -from typing import Any, Dict -import jwt -from jwt import PyJWKClient, ExpiredSignatureError, InvalidTokenError, DecodeError -from jwt import InvalidAudienceError, InvalidIssuerError, InvalidSignatureError -from firebase_admin import _utils - -_APP_CHECK_ATTRIBUTE = '_app_check' - -def _get_app_check_service(app) -> Any: - return _utils.get_app_service(app, _APP_CHECK_ATTRIBUTE, _AppCheckService) - -def verify_token(token: str, app=None) -> Dict[str, Any]: - """Verifies a Firebase App Check token. - - Args: - token: A token from App Check. - app: An App instance (optional). - - Returns: - Dict[str, Any]: The token's decoded claims. - - Raises: - ValueError: If the app's ``project_id`` is invalid or unspecified, - or if the token's headers or payload are invalid. - PyJWKClientError: If PyJWKClient fails to fetch a valid signing key. - """ - return _get_app_check_service(app).verify_token(token) - -class _AppCheckService: - """Service class that implements Firebase App Check functionality.""" - - _APP_CHECK_ISSUER = 'https://firebaseappcheck.googleapis.com/' - _JWKS_URL = 'https://firebaseappcheck.googleapis.com/v1/jwks' - _project_id = None - _scoped_project_id = None - _jwks_client = None - - _APP_CHECK_HEADERS = { - 'x-goog-api-client': _utils.get_metrics_header(), - } - - def __init__(self, app): - # Validate and store the project_id to validate the JWT claims - self._project_id = app.project_id - if not self._project_id: - raise ValueError( - 'A project ID must be specified to access the App Check ' - 'service. Either set the projectId option, use service ' - 'account credentials, or set the ' - 'GOOGLE_CLOUD_PROJECT environment variable.') - self._scoped_project_id = 'projects/' + app.project_id - # Default lifespan is 300 seconds (5 minutes) so we change it to 21600 seconds (6 hours). - self._jwks_client = PyJWKClient( - self._JWKS_URL, lifespan=21600, headers=self._APP_CHECK_HEADERS) - - - def verify_token(self, token: str) -> Dict[str, Any]: - """Verifies a Firebase App Check token.""" - _Validators.check_string("app check token", token) - - # Obtain the Firebase App Check Public Keys - # Note: It is not recommended to hard code these keys as they rotate, - # but you should cache them for up to 6 hours. - try: - signing_key = self._jwks_client.get_signing_key_from_jwt(token) - self._has_valid_token_headers(jwt.get_unverified_header(token)) - verified_claims = self._decode_and_verify(token, signing_key.key) - except (InvalidTokenError, DecodeError) as exception: - raise ValueError( - f'Verifying App Check token failed. Error: {exception}' - ) from exception - - verified_claims['app_id'] = verified_claims.get('sub') - return verified_claims - - def _has_valid_token_headers(self, headers: Any) -> None: - """Checks whether the token has valid headers for App Check.""" - # Ensure the token's header has type JWT - if headers.get('typ') != 'JWT': - raise ValueError("The provided App Check token has an incorrect type header") - # Ensure the token's header uses the algorithm RS256 - algorithm = headers.get('alg') - if algorithm != 'RS256': - raise ValueError( - 'The provided App Check token has an incorrect alg header. ' - f'Expected RS256 but got {algorithm}.' - ) - - def _decode_and_verify(self, token: str, signing_key: str): - """Decodes and verifies the token from App Check.""" - payload = {} - try: - payload = jwt.decode( - token, - signing_key, - algorithms=["RS256"], - audience=self._scoped_project_id - ) - except InvalidSignatureError as exception: - raise ValueError( - 'The provided App Check token has an invalid signature.' - ) from exception - except InvalidAudienceError as exception: - raise ValueError( - 'The provided App Check token has an incorrect "aud" (audience) claim. ' - f'Expected payload to include {self._scoped_project_id}.' - ) from exception - except InvalidIssuerError as exception: - raise ValueError( - 'The provided App Check token has an incorrect "iss" (issuer) claim. ' - f'Expected claim to include {self._APP_CHECK_ISSUER}' - ) from exception - except ExpiredSignatureError as exception: - raise ValueError( - 'The provided App Check token has expired.' - ) from exception - except InvalidTokenError as exception: - raise ValueError( - f'Decoding App Check token failed. Error: {exception}' - ) from exception - - audience = payload.get('aud') - if not isinstance(audience, list) or self._scoped_project_id not in audience: - raise ValueError('Firebase App Check token has incorrect "aud" (audience) claim.') - if not payload.get('iss').startswith(self._APP_CHECK_ISSUER): - raise ValueError('Token does not contain the correct "iss" (issuer).') - _Validators.check_string( - 'The provided App Check token "sub" (subject) claim', - payload.get('sub')) - - return payload - -class _Validators: - """A collection of data validation utilities. - - Methods provided in this class raise ``ValueErrors`` if any validations fail. - """ - - @classmethod - def check_string(cls, label: str, value: Any): - """Checks if the given value is a string.""" - if value is None: - raise ValueError(f'{label} "{value}" must be a non-empty string.') - if not isinstance(value, str): - raise ValueError(f'{label} "{value}" must be a string.') diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/auth.py b/notification-service/venv/Lib/site-packages/firebase_admin/auth.py deleted file mode 100644 index cb63ab7..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/auth.py +++ /dev/null @@ -1,926 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase Authentication module. - -This module contains functions for minting and verifying JWTs used for -authenticating against Firebase services. It also provides functions for -creating and managing user accounts in Firebase projects. -""" - -from firebase_admin import _auth_client -from firebase_admin import _auth_providers -from firebase_admin import _auth_utils -from firebase_admin import _user_identifier -from firebase_admin import _token_gen -from firebase_admin import _user_import -from firebase_admin import _user_mgt -from firebase_admin import _utils - - -_AUTH_ATTRIBUTE = '_auth' - - -__all__ = [ - 'ActionCodeSettings', - 'CertificateFetchError', - 'Client', - 'ConfigurationNotFoundError', - 'DELETE_ATTRIBUTE', - 'EmailAlreadyExistsError', - 'EmailNotFoundError', - 'ErrorInfo', - 'ExpiredIdTokenError', - 'ExpiredSessionCookieError', - 'ExportedUserRecord', - 'DeleteUsersResult', - 'GetUsersResult', - 'ImportUserRecord', - 'InsufficientPermissionError', - 'InvalidDynamicLinkDomainError', - 'InvalidHostingLinkDomainError', - 'InvalidIdTokenError', - 'InvalidSessionCookieError', - 'ListProviderConfigsPage', - 'ListUsersPage', - 'OIDCProviderConfig', - 'PhoneNumberAlreadyExistsError', - 'ProviderConfig', - 'ResetPasswordExceedLimitError', - 'RevokedIdTokenError', - 'RevokedSessionCookieError', - 'SAMLProviderConfig', - 'TokenSignError', - 'TooManyAttemptsTryLaterError', - 'UidAlreadyExistsError', - 'UnexpectedResponseError', - 'UserDisabledError', - 'UserImportHash', - 'UserImportResult', - 'UserInfo', - 'UserMetadata', - 'UserNotFoundError', - 'UserProvider', - 'UserRecord', - - 'UserIdentifier', - 'UidIdentifier', - 'EmailIdentifier', - 'PhoneIdentifier', - 'ProviderIdentifier', - - 'create_custom_token', - 'create_oidc_provider_config', - 'create_saml_provider_config', - 'create_session_cookie', - 'create_user', - 'delete_oidc_provider_config', - 'delete_saml_provider_config', - 'delete_user', - 'delete_users', - 'generate_email_verification_link', - 'generate_password_reset_link', - 'generate_sign_in_with_email_link', - 'get_oidc_provider_config', - 'get_saml_provider_config', - 'get_user', - 'get_user_by_email', - 'get_user_by_phone_number', - 'get_users', - 'import_users', - 'list_saml_provider_configs', - 'list_users', - 'revoke_refresh_tokens', - 'set_custom_user_claims', - 'update_oidc_provider_config', - 'update_saml_provider_config', - 'update_user', - 'verify_id_token', - 'verify_session_cookie', -] - -ActionCodeSettings = _user_mgt.ActionCodeSettings -CertificateFetchError = _token_gen.CertificateFetchError -Client = _auth_client.Client -ConfigurationNotFoundError = _auth_utils.ConfigurationNotFoundError -DELETE_ATTRIBUTE = _user_mgt.DELETE_ATTRIBUTE -DeleteUsersResult = _user_mgt.DeleteUsersResult -EmailAlreadyExistsError = _auth_utils.EmailAlreadyExistsError -EmailNotFoundError = _auth_utils.EmailNotFoundError -ErrorInfo = _user_import.ErrorInfo -ExpiredIdTokenError = _token_gen.ExpiredIdTokenError -ExpiredSessionCookieError = _token_gen.ExpiredSessionCookieError -ExportedUserRecord = _user_mgt.ExportedUserRecord -GetUsersResult = _user_mgt.GetUsersResult -ImportUserRecord = _user_import.ImportUserRecord -InsufficientPermissionError = _auth_utils.InsufficientPermissionError -InvalidDynamicLinkDomainError = _auth_utils.InvalidDynamicLinkDomainError -InvalidHostingLinkDomainError = _auth_utils.InvalidHostingLinkDomainError -InvalidIdTokenError = _auth_utils.InvalidIdTokenError -InvalidSessionCookieError = _token_gen.InvalidSessionCookieError -ListProviderConfigsPage = _auth_providers.ListProviderConfigsPage -ListUsersPage = _user_mgt.ListUsersPage -OIDCProviderConfig = _auth_providers.OIDCProviderConfig -PhoneNumberAlreadyExistsError = _auth_utils.PhoneNumberAlreadyExistsError -ProviderConfig = _auth_providers.ProviderConfig -ResetPasswordExceedLimitError = _auth_utils.ResetPasswordExceedLimitError -RevokedIdTokenError = _token_gen.RevokedIdTokenError -RevokedSessionCookieError = _token_gen.RevokedSessionCookieError -SAMLProviderConfig = _auth_providers.SAMLProviderConfig -TokenSignError = _token_gen.TokenSignError -TooManyAttemptsTryLaterError = _auth_utils.TooManyAttemptsTryLaterError -UidAlreadyExistsError = _auth_utils.UidAlreadyExistsError -UnexpectedResponseError = _auth_utils.UnexpectedResponseError -UserDisabledError = _auth_utils.UserDisabledError -UserImportHash = _user_import.UserImportHash -UserImportResult = _user_import.UserImportResult -UserInfo = _user_mgt.UserInfo -UserMetadata = _user_mgt.UserMetadata -UserNotFoundError = _auth_utils.UserNotFoundError -UserProvider = _user_import.UserProvider -UserRecord = _user_mgt.UserRecord - -UserIdentifier = _user_identifier.UserIdentifier -UidIdentifier = _user_identifier.UidIdentifier -EmailIdentifier = _user_identifier.EmailIdentifier -PhoneIdentifier = _user_identifier.PhoneIdentifier -ProviderIdentifier = _user_identifier.ProviderIdentifier - - -def _get_client(app): - """Returns a client instance for an App. - - If the App already has a client associated with it, simply returns - it. Otherwise creates a new client, and adds it to the App before - returning it. - - Args: - app: A Firebase App instance (or ``None`` to use the default App). - - Returns: - Client: A client for the specified App instance. - - Raises: - ValueError: If the app argument is invalid. - """ - return _utils.get_app_service(app, _AUTH_ATTRIBUTE, Client) - - -def create_custom_token(uid, developer_claims=None, app=None): - """Builds and signs a Firebase custom auth token. - - Args: - uid: ID of the user for whom the token is created. - developer_claims: A dictionary of claims to be included in the token - (optional). - app: An App instance (optional). - - Returns: - bytes: A token minted from the input parameters. - - Raises: - ValueError: If input parameters are invalid. - TokenSignError: If an error occurs while signing the token using the remote IAM service. - """ - client = _get_client(app) - return client.create_custom_token(uid, developer_claims) - - -def verify_id_token(id_token, app=None, check_revoked=False, clock_skew_seconds=0): - """Verifies the signature and data for the provided JWT. - - Accepts a signed token string, verifies that it is current, and issued - to this project, and that it was correctly signed by Google. - - Args: - id_token: A string of the encoded JWT. - app: An App instance (optional). - check_revoked: Boolean, If true, checks whether the token has been revoked or - the user disabled (optional). - clock_skew_seconds: The number of seconds to tolerate when checking the token. - Must be between 0-60. Defaults to 0. - Returns: - dict: A dictionary of key-value pairs parsed from the decoded JWT. - - Raises: - ValueError: If ``id_token`` is a not a string or is empty. - InvalidIdTokenError: If ``id_token`` is not a valid Firebase ID token. - ExpiredIdTokenError: If the specified ID token has expired. - RevokedIdTokenError: If ``check_revoked`` is ``True`` and the ID token has been revoked. - CertificateFetchError: If an error occurs while fetching the public key certificates - required to verify the ID token. - UserDisabledError: If ``check_revoked`` is ``True`` and the corresponding user - record is disabled. - """ - client = _get_client(app) - return client.verify_id_token( - id_token, check_revoked=check_revoked, clock_skew_seconds=clock_skew_seconds) - - -def create_session_cookie(id_token, expires_in, app=None): - """Creates a new Firebase session cookie from the given ID token and options. - - The returned JWT can be set as a server-side session cookie with a custom cookie policy. - - Args: - id_token: The Firebase ID token to exchange for a session cookie. - expires_in: Duration until the cookie is expired. This can be specified - as a numeric seconds value or a ``datetime.timedelta`` instance. - app: An App instance (optional). - - Returns: - bytes: A session cookie generated from the input parameters. - - Raises: - ValueError: If input parameters are invalid. - FirebaseError: If an error occurs while creating the cookie. - """ - client = _get_client(app) - # pylint: disable=protected-access - return client._token_generator.create_session_cookie(id_token, expires_in) - - -def verify_session_cookie(session_cookie, check_revoked=False, app=None, clock_skew_seconds=0): - """Verifies a Firebase session cookie. - - Accepts a session cookie string, verifies that it is current, and issued - to this project, and that it was correctly signed by Google. - - Args: - session_cookie: A session cookie string to verify. - check_revoked: Boolean, if true, checks whether the cookie has been revoked or the - user disabled (optional). - app: An App instance (optional). - clock_skew_seconds: The number of seconds to tolerate when checking the cookie. - - Returns: - dict: A dictionary of key-value pairs parsed from the decoded JWT. - - Raises: - ValueError: If ``session_cookie`` is a not a string or is empty. - InvalidSessionCookieError: If ``session_cookie`` is not a valid Firebase session cookie. - ExpiredSessionCookieError: If the specified session cookie has expired. - RevokedSessionCookieError: If ``check_revoked`` is ``True`` and the cookie has been revoked. - CertificateFetchError: If an error occurs while fetching the public key certificates - required to verify the session cookie. - UserDisabledError: If ``check_revoked`` is ``True`` and the corresponding user - record is disabled. - """ - client = _get_client(app) - # pylint: disable=protected-access - verified_claims = client._token_verifier.verify_session_cookie( - session_cookie, clock_skew_seconds) - if check_revoked: - client._check_jwt_revoked_or_disabled( - verified_claims, RevokedSessionCookieError, 'session cookie') - return verified_claims - - -def revoke_refresh_tokens(uid, app=None): - """Revokes all refresh tokens for an existing user. - - This function updates the user's ``tokens_valid_after_timestamp`` to the current UTC - in seconds since the epoch. It is important that the server on which this is called has its - clock set correctly and synchronized. - - While this revokes all sessions for a specified user and disables any new ID tokens for - existing sessions from getting minted, existing ID tokens may remain active until their - natural expiration (one hour). To verify that ID tokens are revoked, use - ``verify_id_token(idToken, check_revoked=True)``. - - Args: - uid: A user ID string. - app: An App instance (optional). - - Raises: - ValueError: If the user ID is None, empty or malformed. - FirebaseError: If an error occurs while revoking the refresh token. - """ - client = _get_client(app) - client.revoke_refresh_tokens(uid) - - -def get_user(uid, app=None): - """Gets the user data corresponding to the specified user ID. - - Args: - uid: A user ID string. - app: An App instance (optional). - - Returns: - UserRecord: A user record instance. - - Raises: - ValueError: If the user ID is None, empty or malformed. - UserNotFoundError: If the specified user ID does not exist. - FirebaseError: If an error occurs while retrieving the user. - """ - client = _get_client(app) - return client.get_user(uid=uid) - - -def get_user_by_email(email, app=None): - """Gets the user data corresponding to the specified user email. - - Args: - email: A user email address string. - app: An App instance (optional). - - Returns: - UserRecord: A user record instance. - - Raises: - ValueError: If the email is None, empty or malformed. - UserNotFoundError: If no user exists by the specified email address. - FirebaseError: If an error occurs while retrieving the user. - """ - client = _get_client(app) - return client.get_user_by_email(email=email) - - -def get_user_by_phone_number(phone_number, app=None): - """Gets the user data corresponding to the specified phone number. - - Args: - phone_number: A phone number string. - app: An App instance (optional). - - Returns: - UserRecord: A user record instance. - - Raises: - ValueError: If the phone number is None, empty or malformed. - UserNotFoundError: If no user exists by the specified phone number. - FirebaseError: If an error occurs while retrieving the user. - """ - client = _get_client(app) - return client.get_user_by_phone_number(phone_number=phone_number) - - -def get_users(identifiers, app=None): - """Gets the user data corresponding to the specified identifiers. - - There are no ordering guarantees; in particular, the nth entry in the - result list is not guaranteed to correspond to the nth entry in the input - parameters list. - - A maximum of 100 identifiers may be supplied. If more than 100 - identifiers are supplied, this method raises a `ValueError`. - - Args: - identifiers (list[UserIdentifier]): A list of ``UserIdentifier`` - instances used to indicate which user records should be returned. - Must have <= 100 entries. - app: An App instance (optional). - - Returns: - GetUsersResult: A ``GetUsersResult`` instance corresponding to the - specified identifiers. - - Raises: - ValueError: If any of the identifiers are invalid or if more than 100 - identifiers are specified. - """ - client = _get_client(app) - return client.get_users(identifiers) - - -def list_users(page_token=None, max_results=_user_mgt.MAX_LIST_USERS_RESULTS, app=None): - """Retrieves a page of user accounts from a Firebase project. - - The ``page_token`` argument governs the starting point of the page. The ``max_results`` - argument governs the maximum number of user accounts that may be included in the returned page. - This function never returns None. If there are no user accounts in the Firebase project, this - returns an empty page. - - Args: - page_token: A non-empty page token string, which indicates the starting point of the page - (optional). Defaults to ``None``, which will retrieve the first page of users. - max_results: A positive integer indicating the maximum number of users to include in the - returned page (optional). Defaults to 1000, which is also the maximum number allowed. - app: An App instance (optional). - - Returns: - ListUsersPage: A page of user accounts. - - Raises: - ValueError: If ``max_results`` or ``page_token`` are invalid. - FirebaseError: If an error occurs while retrieving the user accounts. - """ - client = _get_client(app) - return client.list_users(page_token=page_token, max_results=max_results) - - -def create_user(**kwargs): # pylint: disable=differing-param-doc - """Creates a new user account with the specified properties. - - Args: - **kwargs: A series of keyword arguments (optional). - - Keyword Args: - uid: User ID to assign to the newly created user (optional). - display_name: The user's display name (optional). - email: The user's primary email (optional). - email_verified: A boolean indicating whether or not the user's primary email is - verified (optional). - phone_number: The user's primary phone number (optional). - photo_url: The user's photo URL (optional). - password: The user's raw, unhashed password. (optional). - disabled: A boolean indicating whether or not the user account is disabled (optional). - app: An App instance (optional). - - Returns: - UserRecord: A user record instance for the newly created user. - - Raises: - ValueError: If the specified user properties are invalid. - FirebaseError: If an error occurs while creating the user account. - """ - app = kwargs.pop('app', None) - client = _get_client(app) - return client.create_user(**kwargs) - - -def update_user(uid, **kwargs): # pylint: disable=differing-param-doc - """Updates an existing user account with the specified properties. - - Args: - uid: A user ID string. - **kwargs: A series of keyword arguments (optional). - - Keyword Args: - display_name: The user's display name (optional). Can be removed by explicitly passing - ``auth.DELETE_ATTRIBUTE``. - email: The user's primary email (optional). - email_verified: A boolean indicating whether or not the user's primary email is - verified (optional). - phone_number: The user's primary phone number (optional). Can be removed by explicitly - passing ``auth.DELETE_ATTRIBUTE``. - photo_url: The user's photo URL (optional). Can be removed by explicitly passing - ``auth.DELETE_ATTRIBUTE``. - password: The user's raw, unhashed password. (optional). - disabled: A boolean indicating whether or not the user account is disabled (optional). - custom_claims: A dictionary or a JSON string containing the custom claims to be set on the - user account (optional). To remove all custom claims, pass ``auth.DELETE_ATTRIBUTE``. - valid_since: An integer signifying the seconds since the epoch (optional). This field is - set by ``revoke_refresh_tokens`` and it is discouraged to set this field directly. - app: An App instance (optional). - - Returns: - UserRecord: An updated user record instance for the user. - - Raises: - ValueError: If the specified user ID or properties are invalid. - FirebaseError: If an error occurs while updating the user account. - """ - app = kwargs.pop('app', None) - client = _get_client(app) - return client.update_user(uid, **kwargs) - - -def set_custom_user_claims(uid, custom_claims, app=None): - """Sets additional claims on an existing user account. - - Custom claims set via this function can be used to define user roles and privilege levels. - These claims propagate to all the devices where the user is already signed in (after token - expiration or when token refresh is forced), and next time the user signs in. The claims - can be accessed via the user's ID token JWT. If a reserved OIDC claim is specified (sub, iat, - iss, etc), an error is thrown. Claims payload must also not be larger then 1000 characters - when serialized into a JSON string. - - Args: - uid: A user ID string. - custom_claims: A dictionary or a JSON string of custom claims. Pass None to unset any - claims set previously. - app: An App instance (optional). - - Raises: - ValueError: If the specified user ID or the custom claims are invalid. - FirebaseError: If an error occurs while updating the user account. - """ - client = _get_client(app) - client.set_custom_user_claims(uid, custom_claims=custom_claims) - - -def delete_user(uid, app=None): - """Deletes the user identified by the specified user ID. - - Args: - uid: A user ID string. - app: An App instance (optional). - - Raises: - ValueError: If the user ID is None, empty or malformed. - FirebaseError: If an error occurs while deleting the user account. - """ - client = _get_client(app) - client.delete_user(uid) - - -def delete_users(uids, app=None): - """Deletes the users specified by the given identifiers. - - Deleting a non-existing user does not generate an error (the method is - idempotent.) Non-existing users are considered to be successfully deleted - and are therefore included in the `DeleteUserResult.success_count` value. - - A maximum of 1000 identifiers may be supplied. If more than 1000 - identifiers are supplied, this method raises a `ValueError`. - - Args: - uids: A list of strings indicating the uids of the users to be deleted. - Must have <= 1000 entries. - app: An App instance (optional). - - Returns: - DeleteUsersResult: The total number of successful/failed deletions, as - well as the array of errors that correspond to the failed deletions. - - Raises: - ValueError: If any of the identifiers are invalid or if more than 1000 - identifiers are specified. - """ - client = _get_client(app) - return client.delete_users(uids) - - -def import_users(users, hash_alg=None, app=None): - """Imports the specified list of users into Firebase Auth. - - At most 1000 users can be imported at a time. This operation is optimized for bulk imports and - will ignore checks on identifier uniqueness which could result in duplications. The - ``hash_alg`` parameter must be specified when importing users with passwords. Refer to the - ``UserImportHash`` class for supported hash algorithms. - - Args: - users: A list of ``ImportUserRecord`` instances to import. Length of the list must not - exceed 1000. - hash_alg: A ``UserImportHash`` object (optional). Required when importing users with - passwords. - app: An App instance (optional). - - Returns: - UserImportResult: An object summarizing the result of the import operation. - - Raises: - ValueError: If the provided arguments are invalid. - FirebaseError: If an error occurs while importing users. - """ - client = _get_client(app) - return client.import_users(users, hash_alg) - - -def generate_password_reset_link(email, action_code_settings=None, app=None): - """Generates the out-of-band email action link for password reset flows for the specified email - address. - - Args: - email: The email of the user whose password is to be reset. - action_code_settings: ``ActionCodeSettings`` instance (optional). Defines whether - the link is to be handled by a mobile app and the additional state information to be - passed in the deep link. - app: An App instance (optional). - Returns: - link: The password reset link created by the API - - Raises: - ValueError: If the provided arguments are invalid - FirebaseError: If an error occurs while generating the link - """ - client = _get_client(app) - return client.generate_password_reset_link(email, action_code_settings=action_code_settings) - - -def generate_email_verification_link(email, action_code_settings=None, app=None): - """Generates the out-of-band email action link for email verification flows for the specified - email address. - - Args: - email: The email of the user to be verified. - action_code_settings: ``ActionCodeSettings`` instance (optional). Defines whether - the link is to be handled by a mobile app and the additional state information to be - passed in the deep link. - app: An App instance (optional). - Returns: - link: The email verification link created by the API - - Raises: - ValueError: If the provided arguments are invalid - FirebaseError: If an error occurs while generating the link - """ - client = _get_client(app) - return client.generate_email_verification_link( - email, action_code_settings=action_code_settings) - - -def generate_sign_in_with_email_link(email, action_code_settings, app=None): - """Generates the out-of-band email action link for email link sign-in flows, using the action - code settings provided. - - Args: - email: The email of the user signing in. - action_code_settings: ``ActionCodeSettings`` instance. Defines whether - the link is to be handled by a mobile app and the additional state information to be - passed in the deep link. - app: An App instance (optional). - - Returns: - link: The email sign-in link created by the API - - Raises: - ValueError: If the provided arguments are invalid - FirebaseError: If an error occurs while generating the link - """ - client = _get_client(app) - return client.generate_sign_in_with_email_link( - email, action_code_settings=action_code_settings) - - -def get_oidc_provider_config(provider_id, app=None): - """Returns the ``OIDCProviderConfig`` with the given ID. - - Args: - provider_id: Provider ID string. - app: An App instance (optional). - - Returns: - OIDCProviderConfig: An OIDC provider config instance. - - Raises: - ValueError: If the provider ID is invalid, empty or does not have ``oidc.`` prefix. - ConfigurationNotFoundError: If no OIDC provider is available with the given identifier. - FirebaseError: If an error occurs while retrieving the OIDC provider. - """ - client = _get_client(app) - return client.get_oidc_provider_config(provider_id) - -def create_oidc_provider_config( - provider_id, client_id, issuer, display_name=None, enabled=None, client_secret=None, - id_token_response_type=None, code_response_type=None, app=None): - """Creates a new OIDC provider config from the given parameters. - - OIDC provider support requires Google Cloud's Identity Platform (GCIP). To learn more about - GCIP, including pricing and features, see https://cloud.google.com/identity-platform. - - Args: - provider_id: Provider ID string. Must have the prefix ``oidc.``. - client_id: Client ID of the new config. - issuer: Issuer of the new config. Must be a valid URL. - display_name: The user-friendly display name to the current configuration (optional). - This name is also used as the provider label in the Cloud Console. - enabled: A boolean indicating whether the provider configuration is enabled or disabled - (optional). A user cannot sign in using a disabled provider. - app: An App instance (optional). - client_secret: A string which sets the client secret for the new provider. - This is required for the code flow. - code_response_type: A boolean which sets whether to enable the code response flow for the - new provider. By default, this is not enabled if no response type is specified. - A client secret must be set for this response type. - Having both the code and ID token response flows is currently not supported. - id_token_response_type: A boolean which sets whether to enable the ID token response flow - for the new provider. By default, this is enabled if no response type is specified. - Having both the code and ID token response flows is currently not supported. - - Returns: - OIDCProviderConfig: The newly created OIDC provider config instance. - - Raises: - ValueError: If any of the specified input parameters are invalid. - FirebaseError: If an error occurs while creating the new OIDC provider config. - """ - client = _get_client(app) - return client.create_oidc_provider_config( - provider_id, client_id=client_id, issuer=issuer, display_name=display_name, - enabled=enabled, client_secret=client_secret, id_token_response_type=id_token_response_type, - code_response_type=code_response_type) - - -def update_oidc_provider_config( - provider_id, client_id=None, issuer=None, display_name=None, enabled=None, - client_secret=None, id_token_response_type=None, code_response_type=None, app=None): - """Updates an existing OIDC provider config with the given parameters. - - Args: - provider_id: Provider ID string. Must have the prefix ``oidc.``. - client_id: Client ID of the new config (optional). - issuer: Issuer of the new config (optional). Must be a valid URL. - display_name: The user-friendly display name of the current configuration (optional). - Pass ``auth.DELETE_ATTRIBUTE`` to delete the current display name. - enabled: A boolean indicating whether the provider configuration is enabled or disabled - (optional). - app: An App instance (optional). - client_secret: A string which sets the client secret for the new provider. - This is required for the code flow. - code_response_type: A boolean which sets whether to enable the code response flow for the - new provider. By default, this is not enabled if no response type is specified. - A client secret must be set for this response type. - Having both the code and ID token response flows is currently not supported. - id_token_response_type: A boolean which sets whether to enable the ID token response flow - for the new provider. By default, this is enabled if no response type is specified. - Having both the code and ID token response flows is currently not supported. - - Returns: - OIDCProviderConfig: The updated OIDC provider config instance. - - Raises: - ValueError: If any of the specified input parameters are invalid. - FirebaseError: If an error occurs while updating the OIDC provider config. - """ - client = _get_client(app) - return client.update_oidc_provider_config( - provider_id, client_id=client_id, issuer=issuer, display_name=display_name, - enabled=enabled, client_secret=client_secret, id_token_response_type=id_token_response_type, - code_response_type=code_response_type) - - -def delete_oidc_provider_config(provider_id, app=None): - """Deletes the ``OIDCProviderConfig`` with the given ID. - - Args: - provider_id: Provider ID string. - app: An App instance (optional). - - Raises: - ValueError: If the provider ID is invalid, empty or does not have ``oidc.`` prefix. - ConfigurationNotFoundError: If no OIDC provider is available with the given identifier. - FirebaseError: If an error occurs while deleting the OIDC provider. - """ - client = _get_client(app) - client.delete_oidc_provider_config(provider_id) - - -def list_oidc_provider_configs( - page_token=None, max_results=_auth_providers.MAX_LIST_CONFIGS_RESULTS, app=None): - """Retrieves a page of OIDC provider configs from a Firebase project. - - The ``page_token`` argument governs the starting point of the page. The ``max_results`` - argument governs the maximum number of configs that may be included in the returned - page. This function never returns ``None``. If there are no OIDC configs in the Firebase - project, this returns an empty page. - - Args: - page_token: A non-empty page token string, which indicates the starting point of the - page (optional). Defaults to ``None``, which will retrieve the first page of users. - max_results: A positive integer indicating the maximum number of users to include in - the returned page (optional). Defaults to 100, which is also the maximum number - allowed. - app: An App instance (optional). - - Returns: - ListProviderConfigsPage: A page of OIDC provider config instances. - - Raises: - ValueError: If ``max_results`` or ``page_token`` are invalid. - FirebaseError: If an error occurs while retrieving the OIDC provider configs. - """ - client = _get_client(app) - return client.list_oidc_provider_configs(page_token, max_results) - - -def get_saml_provider_config(provider_id, app=None): - """Returns the ``SAMLProviderConfig`` with the given ID. - - Args: - provider_id: Provider ID string. - app: An App instance (optional). - - Returns: - SAMLProviderConfig: A SAML provider config instance. - - Raises: - ValueError: If the provider ID is invalid, empty or does not have ``saml.`` prefix. - ConfigurationNotFoundError: If no SAML provider is available with the given identifier. - FirebaseError: If an error occurs while retrieving the SAML provider. - """ - client = _get_client(app) - return client.get_saml_provider_config(provider_id) - - -def create_saml_provider_config( - provider_id, idp_entity_id, sso_url, x509_certificates, rp_entity_id, callback_url, - display_name=None, enabled=None, app=None): - """Creates a new SAML provider config from the given parameters. - - SAML provider support requires Google Cloud's Identity Platform (GCIP). To learn more about - GCIP, including pricing and features, see https://cloud.google.com/identity-platform. - - Args: - provider_id: Provider ID string. Must have the prefix ``saml.``. - idp_entity_id: The SAML IdP entity identifier. - sso_url: The SAML IdP SSO URL. Must be a valid URL. - x509_certificates: The list of SAML IdP X.509 certificates issued by CA for this provider. - Multiple certificates are accepted to prevent outages during IdP key rotation (for - example ADFS rotates every 10 days). When the Auth server receives a SAML response, it - will match the SAML response with the certificate on record. Otherwise the response is - rejected. Developers are expected to manage the certificate updates as keys are - rotated. - rp_entity_id: The SAML relying party (service provider) entity ID. This is defined by the - developer but needs to be provided to the SAML IdP. - callback_url: Callback URL string. This is fixed and must always be the same as the OAuth - redirect URL provisioned by Firebase Auth, unless a custom authDomain is used. - display_name: The user-friendly display name to the current configuration (optional). This - name is also used as the provider label in the Cloud Console. - enabled: A boolean indicating whether the provider configuration is enabled or disabled - (optional). A user cannot sign in using a disabled provider. - app: An App instance (optional). - - Returns: - SAMLProviderConfig: The newly created SAML provider config instance. - - Raises: - ValueError: If any of the specified input parameters are invalid. - FirebaseError: If an error occurs while creating the new SAML provider config. - """ - client = _get_client(app) - return client.create_saml_provider_config( - provider_id, idp_entity_id=idp_entity_id, sso_url=sso_url, - x509_certificates=x509_certificates, rp_entity_id=rp_entity_id, callback_url=callback_url, - display_name=display_name, enabled=enabled) - - -def update_saml_provider_config( - provider_id, idp_entity_id=None, sso_url=None, x509_certificates=None, - rp_entity_id=None, callback_url=None, display_name=None, enabled=None, app=None): - """Updates an existing SAML provider config with the given parameters. - - Args: - provider_id: Provider ID string. Must have the prefix ``saml.``. - idp_entity_id: The SAML IdP entity identifier (optional). - sso_url: The SAML IdP SSO URL. Must be a valid URL (optional). - x509_certificates: The list of SAML IdP X.509 certificates issued by CA for this - provider (optional). - rp_entity_id: The SAML relying party entity ID (optional). - callback_url: Callback URL string (optional). - display_name: The user-friendly display name of the current configuration (optional). - Pass ``auth.DELETE_ATTRIBUTE`` to delete the current display name. - enabled: A boolean indicating whether the provider configuration is enabled or disabled - (optional). - app: An App instance (optional). - - Returns: - SAMLProviderConfig: The updated SAML provider config instance. - - Raises: - ValueError: If any of the specified input parameters are invalid. - FirebaseError: If an error occurs while updating the SAML provider config. - """ - client = _get_client(app) - return client.update_saml_provider_config( - provider_id, idp_entity_id=idp_entity_id, sso_url=sso_url, - x509_certificates=x509_certificates, rp_entity_id=rp_entity_id, - callback_url=callback_url, display_name=display_name, enabled=enabled) - - -def delete_saml_provider_config(provider_id, app=None): - """Deletes the ``SAMLProviderConfig`` with the given ID. - - Args: - provider_id: Provider ID string. - app: An App instance (optional). - - Raises: - ValueError: If the provider ID is invalid, empty or does not have ``saml.`` prefix. - ConfigurationNotFoundError: If no SAML provider is available with the given identifier. - FirebaseError: If an error occurs while deleting the SAML provider. - """ - client = _get_client(app) - client.delete_saml_provider_config(provider_id) - - -def list_saml_provider_configs( - page_token=None, max_results=_auth_providers.MAX_LIST_CONFIGS_RESULTS, app=None): - """Retrieves a page of SAML provider configs from a Firebase project. - - The ``page_token`` argument governs the starting point of the page. The ``max_results`` - argument governs the maximum number of configs that may be included in the returned - page. This function never returns ``None``. If there are no SAML configs in the Firebase - project, this returns an empty page. - - Args: - page_token: A non-empty page token string, which indicates the starting point of the - page (optional). Defaults to ``None``, which will retrieve the first page of users. - max_results: A positive integer indicating the maximum number of users to include in - the returned page (optional). Defaults to 100, which is also the maximum number - allowed. - app: An App instance (optional). - - Returns: - ListProviderConfigsPage: A page of SAML provider config instances. - - Raises: - ValueError: If ``max_results`` or ``page_token`` are invalid. - FirebaseError: If an error occurs while retrieving the SAML provider configs. - """ - client = _get_client(app) - return client.list_saml_provider_configs(page_token, max_results) diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/credentials.py b/notification-service/venv/Lib/site-packages/firebase_admin/credentials.py deleted file mode 100644 index 0edbeca..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/credentials.py +++ /dev/null @@ -1,239 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase credentials module.""" -import collections -import json -import pathlib - -import google.auth -from google.auth.credentials import Credentials as GoogleAuthCredentials -from google.auth.transport import requests -from google.oauth2 import credentials -from google.oauth2 import service_account - - -_request = requests.Request() -_scopes = [ - 'https://www.googleapis.com/auth/cloud-platform', - 'https://www.googleapis.com/auth/datastore', - 'https://www.googleapis.com/auth/devstorage.read_write', - 'https://www.googleapis.com/auth/firebase', - 'https://www.googleapis.com/auth/identitytoolkit', - 'https://www.googleapis.com/auth/userinfo.email' -] - -AccessTokenInfo = collections.namedtuple('AccessTokenInfo', ['access_token', 'expiry']) -"""Data included in an OAuth2 access token. - -Contains the access token string and the expiry time. The expiry time is exposed as a -``datetime`` value. -""" - - -class Base: - """Provides OAuth2 access tokens for accessing Firebase services.""" - - def get_access_token(self): - """Fetches a Google OAuth2 access token using this credential instance. - - Returns: - AccessTokenInfo: An access token obtained using the credential. - """ - google_cred = self.get_credential() - google_cred.refresh(_request) - return AccessTokenInfo(google_cred.token, google_cred.expiry) - - def get_credential(self): - """Returns the Google credential instance used for authentication.""" - raise NotImplementedError - -class _ExternalCredentials(Base): - """A wrapper for google.auth.credentials.Credentials typed credential instances""" - - def __init__(self, credential: GoogleAuthCredentials): - super().__init__() - self._g_credential = credential - - def get_credential(self): - """Returns the underlying Google Credential - - Returns: - google.auth.credentials.Credentials: A Google Auth credential instance.""" - return self._g_credential - -class Certificate(Base): - """A credential initialized from a JSON certificate keyfile.""" - - _CREDENTIAL_TYPE = 'service_account' - - def __init__(self, cert): - """Initializes a credential from a Google service account certificate. - - Service account certificates can be downloaded as JSON files from the Firebase console. - To instantiate a credential from a certificate file, either specify the file path or a - dict representing the parsed contents of the file. - - Args: - cert: Path to a certificate file or a dict representing the contents of a certificate. - - Raises: - IOError: If the specified certificate file doesn't exist or cannot be read. - ValueError: If the specified certificate is invalid. - """ - super().__init__() - if _is_file_path(cert): - with open(cert, encoding='utf-8') as json_file: - json_data = json.load(json_file) - elif isinstance(cert, dict): - json_data = cert - else: - raise ValueError( - f'Invalid certificate argument: "{cert}". Certificate argument must be a file ' - 'path, or a dict containing the parsed file contents.') - - if json_data.get('type') != self._CREDENTIAL_TYPE: - raise ValueError( - 'Invalid service account certificate. Certificate must contain a ' - f'"type" field set to "{self._CREDENTIAL_TYPE}".') - try: - self._g_credential = service_account.Credentials.from_service_account_info( - json_data, scopes=_scopes) - except ValueError as error: - raise ValueError( - f'Failed to initialize a certificate credential. Caused by: "{error}"') from error - - @property - def project_id(self): - return self._g_credential.project_id - - @property - def signer(self): - return self._g_credential.signer - - @property - def service_account_email(self): - return self._g_credential.service_account_email - - def get_credential(self): - """Returns the underlying Google credential. - - Returns: - google.auth.credentials.Credentials: A Google Auth credential instance.""" - return self._g_credential - - -class ApplicationDefault(Base): - """A Google Application Default credential.""" - - def __init__(self): - """Creates an instance that will use Application Default credentials. - - The credentials will be lazily initialized when get_credential() or - project_id() is called. See those methods for possible errors raised. - """ - super().__init__() - self._g_credential = None # Will be lazily-loaded via _load_credential(). - - def get_credential(self): - """Returns the underlying Google credential. - - Raises: - google.auth.exceptions.DefaultCredentialsError: If Application Default - credentials cannot be initialized in the current environment. - Returns: - google.auth.credentials.Credentials: A Google Auth credential instance.""" - self._load_credential() - return self._g_credential - - @property - def project_id(self): - """Returns the project_id from the underlying Google credential. - - Raises: - google.auth.exceptions.DefaultCredentialsError: If Application Default - credentials cannot be initialized in the current environment. - Returns: - str: The project id.""" - self._load_credential() - return self._project_id - - def _load_credential(self): - if not self._g_credential: - self._g_credential, self._project_id = google.auth.default(scopes=_scopes) - -class RefreshToken(Base): - """A credential initialized from an existing refresh token.""" - - _CREDENTIAL_TYPE = 'authorized_user' - - def __init__(self, refresh_token): - """Initializes a credential from a refresh token JSON file. - - The JSON must consist of client_id, client_secret and refresh_token fields. Refresh - token files are typically created and managed by the gcloud SDK. To instantiate - a credential from a refresh token file, either specify the file path or a dict - representing the parsed contents of the file. - - Args: - refresh_token: Path to a refresh token file or a dict representing the contents of a - refresh token file. - - Raises: - IOError: If the specified file doesn't exist or cannot be read. - ValueError: If the refresh token configuration is invalid. - """ - super().__init__() - if _is_file_path(refresh_token): - with open(refresh_token, encoding='utf-8') as json_file: - json_data = json.load(json_file) - elif isinstance(refresh_token, dict): - json_data = refresh_token - else: - raise ValueError( - f'Invalid refresh token argument: "{refresh_token}". Refresh token argument must ' - 'be a file path, or a dict containing the parsed file contents.') - - if json_data.get('type') != self._CREDENTIAL_TYPE: - raise ValueError( - 'Invalid refresh token configuration. JSON must contain a ' - f'"type" field set to "{self._CREDENTIAL_TYPE}".') - self._g_credential = credentials.Credentials.from_authorized_user_info(json_data, _scopes) - - @property - def client_id(self): - return self._g_credential.client_id - - @property - def client_secret(self): - return self._g_credential.client_secret - - @property - def refresh_token(self): - return self._g_credential.refresh_token - - def get_credential(self): - """Returns the underlying Google credential. - - Returns: - google.auth.credentials.Credentials: A Google Auth credential instance.""" - return self._g_credential - - -def _is_file_path(path): - try: - pathlib.Path(path) - return True - except TypeError: - return False diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/db.py b/notification-service/venv/Lib/site-packages/firebase_admin/db.py deleted file mode 100644 index 800cbf8..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/db.py +++ /dev/null @@ -1,965 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase Realtime Database module. - -This module contains functions and classes that facilitate interacting with the Firebase Realtime -Database. It supports basic data manipulation operations, as well as complex queries such as -limit queries and range queries. However, it does not support realtime update notifications. This -module uses the Firebase REST API underneath. -""" - -import collections -import json -import os -import sys -import threading -from urllib import parse - -import requests - -import firebase_admin -from firebase_admin import exceptions -from firebase_admin import _http_client -from firebase_admin import _sseclient -from firebase_admin import _utils - - -_DB_ATTRIBUTE = '_database' -_INVALID_PATH_CHARACTERS = '[].?#$' -_RESERVED_FILTERS = ('$key', '$value', '$priority') -_USER_AGENT = ( - f'Firebase/HTTP/{firebase_admin.__version__}/{sys.version_info.major}' - f'.{sys.version_info.minor}/AdminPython' -) -_TRANSACTION_MAX_RETRIES = 25 -_EMULATOR_HOST_ENV_VAR = 'FIREBASE_DATABASE_EMULATOR_HOST' - - -def reference(path='/', app=None, url=None): - """Returns a database ``Reference`` representing the node at the specified path. - - If no path is specified, this function returns a ``Reference`` that represents the database - root. By default, the returned References provide access to the Firebase Database specified at - app initialization. To connect to a different database instance in the same Firebase project, - specify the ``url`` parameter. - - Args: - path: Path to a node in the Firebase realtime database (optional). - app: An App instance (optional). - url: Base URL of the Firebase Database instance (optional). When specified, takes - precedence over the the ``databaseURL`` option set at app initialization. - - Returns: - Reference: A newly initialized Reference. - - Raises: - ValueError: If the specified path or app is invalid. - """ - service = _utils.get_app_service(app, _DB_ATTRIBUTE, _DatabaseService) - client = service.get_client(url) - return Reference(client=client, path=path) - -def _parse_path(path): - """Parses a path string into a set of segments.""" - if not isinstance(path, str): - raise ValueError(f'Invalid path: "{path}". Path must be a string.') - if any(ch in path for ch in _INVALID_PATH_CHARACTERS): - raise ValueError(f'Invalid path: "{path}". Path contains illegal characters.') - return [seg for seg in path.split('/') if seg] - - -class Event: - """Represents a realtime update event received from the database.""" - - def __init__(self, sse_event): - self._sse_event = sse_event - self._data = json.loads(sse_event.data) - - @property - def data(self): - """Parsed JSON data of this event.""" - return self._data['data'] - - @property - def path(self): - """Path of the database reference that triggered this event.""" - return self._data['path'] - - @property - def event_type(self): - """Event type string (put, patch).""" - return self._sse_event.event_type - - -class ListenerRegistration: - """Represents the addition of an event listener to a database reference.""" - - def __init__(self, callback, sse): - """Initializes a new listener with given parameters. - - This is an internal API. Use the ``db.Reference.listen()`` method to start a - new listener. - - Args: - callback: The callback function to fire in case of event. - sse: A transport session to make requests with. - """ - self._callback = callback - self._sse = sse - self._thread = threading.Thread(target=self._start_listen) - self._thread.start() - - def _start_listen(self): - # iterate the sse client's generator - for sse_event in self._sse: - # only inject data events - if sse_event: - self._callback(Event(sse_event)) - - def close(self): - """Stops the event listener represented by this registration - - This closes the SSE HTTP connection, and joins the background thread. - """ - self._sse.close() - self._thread.join() - - -class Reference: - """Reference represents a node in the Firebase realtime database.""" - - def __init__(self, **kwargs): - """Creates a new Reference using the provided parameters. - - This method is for internal use only. Use db.reference() to obtain an instance of - Reference. - """ - self._client = kwargs.get('client') - if 'segments' in kwargs: - self._segments = kwargs.get('segments') - else: - self._segments = _parse_path(kwargs.get('path')) - self._pathurl = '/' + '/'.join(self._segments) - - @property - def key(self): - if self._segments: - return self._segments[-1] - return None - - @property - def path(self): - return self._pathurl - - @property - def parent(self): - if self._segments: - return Reference(client=self._client, segments=self._segments[:-1]) - return None - - def child(self, path): - """Returns a Reference to the specified child node. - - The path may point to an immediate child of the current Reference, or a deeply nested - child. Child paths must not begin with '/'. - - Args: - path: Path to the child node. - - Returns: - Reference: A database Reference representing the specified child node. - - Raises: - ValueError: If the child path is not a string, not well-formed or begins with '/'. - """ - if not path or not isinstance(path, str): - raise ValueError(f'Invalid path argument: "{path}". Path must be a non-empty string.') - if path.startswith('/'): - raise ValueError(f'Invalid path argument: "{path}". Child path must not start with "/"') - full_path = self._pathurl + '/' + path - return Reference(client=self._client, path=full_path) - - def get(self, etag=False, shallow=False): - """Returns the value, and optionally the ETag, at the current location of the database. - - Args: - etag: A boolean indicating whether the Etag value should be returned or not (optional). - shallow: A boolean indicating whether to execute a shallow read (optional). Shallow - reads do not retrieve the child nodes of the current database location. Cannot be - set to True if ``etag`` is also set to True. - - Returns: - object: If etag is False returns the decoded JSON value of the current database location. - If etag is True, returns a 2-tuple consisting of the decoded JSON value and the Etag - associated with the current database location. - - Raises: - ValueError: If both ``etag`` and ``shallow`` are set to True. - FirebaseError: If an error occurs while communicating with the remote database server. - """ - if etag: - if shallow: - raise ValueError('etag and shallow cannot both be set to True.') - headers, data = self._client.headers_and_body( - 'get', self._add_suffix(), headers={'X-Firebase-ETag' : 'true'}) - return data, headers.get('ETag') - - params = 'shallow=true' if shallow else None - return self._client.body('get', self._add_suffix(), params=params) - - def get_if_changed(self, etag): - """Gets data in this location only if the specified ETag does not match. - - Args: - etag: The ETag value to be checked against the ETag of the current location. - - Returns: - tuple: A 3-tuple consisting of a boolean, a decoded JSON value and an ETag. If the ETag - specified by the caller did not match, the boolen value will be True and the JSON - and ETag values would reflect the corresponding values in the database. If the ETag - matched, the boolean value will be False and the other elements of the tuple will be - None. - - Raises: - ValueError: If the ETag is not a string. - FirebaseError: If an error occurs while communicating with the remote database server. - """ - if not isinstance(etag, str): - raise ValueError('ETag must be a string.') - - resp = self._client.request('get', self._add_suffix(), headers={'if-none-match': etag}) - if resp.status_code == 304: - return False, None, None - - return True, resp.json(), resp.headers.get('ETag') - - def set(self, value): - """Sets the data at this location to the given value. - - The value must be JSON-serializable and not None. - - Args: - value: JSON-serializable value to be set at this location. - - Raises: - ValueError: If the provided value is None. - TypeError: If the value is not JSON-serializable. - FirebaseError: If an error occurs while communicating with the remote database server. - """ - if value is None: - raise ValueError('Value must not be None.') - self._client.request('put', self._add_suffix(), json=value, params='print=silent') - - def set_if_unchanged(self, expected_etag, value): - """Conditonally sets the data at this location to the given value. - - Sets the data at this location to the given value only if ``expected_etag`` is same as the - ETag value in the database. - - Args: - expected_etag: Value of ETag we want to check. - value: JSON-serializable value to be set at this location. - - Returns: - tuple: A 3-tuple consisting of a boolean, a decoded JSON value and an ETag. The boolean - indicates whether the set operation was successful or not. The decoded JSON and the - ETag corresponds to the latest value in this database location. - - Raises: - ValueError: If the value is None, or if expected_etag is not a string. - FirebaseError: If an error occurs while communicating with the remote database server. - """ - # pylint: disable=missing-raises-doc - if not isinstance(expected_etag, str): - raise ValueError('Expected ETag must be a string.') - if value is None: - raise ValueError('Value must not be none.') - - try: - headers = self._client.headers( - 'put', self._add_suffix(), json=value, headers={'if-match': expected_etag}) - return True, value, headers.get('ETag') - except exceptions.FailedPreconditionError as error: - http_response = error.http_response - if http_response is not None and 'ETag' in http_response.headers: - etag = http_response.headers['ETag'] - snapshot = http_response.json() - return False, snapshot, etag - - raise error - - def push(self, value=''): - """Creates a new child node. - - The optional value argument can be used to provide an initial value for the child node. If - no value is provided, child node will have empty string as the default value. - - Args: - value: JSON-serializable initial value for the child node (optional). - - Returns: - Reference: A Reference representing the newly created child node. - - Raises: - ValueError: If the value is None. - TypeError: If the value is not JSON-serializable. - FirebaseError: If an error occurs while communicating with the remote database server. - """ - if value is None: - raise ValueError('Value must not be None.') - output = self._client.body('post', self._add_suffix(), json=value) - push_id = output.get('name') - return self.child(push_id) - - def update(self, value): - """Updates the specified child keys of this Reference to the provided values. - - Args: - value: A dictionary containing the child keys to update, and their new values. - - Raises: - ValueError: If value is empty or not a dictionary. - FirebaseError: If an error occurs while communicating with the remote database server. - """ - if not value or not isinstance(value, dict): - raise ValueError('Value argument must be a non-empty dictionary.') - if None in value.keys(): - raise ValueError('Dictionary must not contain None keys.') - self._client.request('patch', self._add_suffix(), json=value, params='print=silent') - - def delete(self): - """Deletes this node from the database. - - Raises: - FirebaseError: If an error occurs while communicating with the remote database server. - """ - self._client.request('delete', self._add_suffix()) - - def listen(self, callback): - """Registers the ``callback`` function to receive realtime updates. - - The specified callback function will get invoked with ``db.Event`` objects for each - realtime update received from the database. It will also get called whenever the SDK - reconnects to the server due to network issues or credential expiration. In general, - the OAuth2 credentials used to authorize connections to the server expire every hour. - Therefore clients should expect the ``callback`` to fire at least once every hour, even if - there are no updates in the database. - - This API is based on the event streaming support available in the Firebase REST API. Each - call to ``listen()`` starts a new HTTP connection and a background thread. This is an - experimental feature. It currently does not honor the auth overrides and timeout settings. - Cannot be used in thread-constrained environments like Google App Engine. - - Args: - callback: A function to be called when a data change is detected. - - Returns: - ListenerRegistration: An object that can be used to stop the event listener. - - Raises: - FirebaseError: If an error occurs while starting the initial HTTP connection. - """ - return self._listen_with_session(callback) - - def transaction(self, transaction_update): - """Atomically modifies the data at this location. - - Unlike a normal ``set()``, which just overwrites the data regardless of its previous state, - ``transaction()`` is used to modify the existing value to a new value, ensuring there are - no conflicts with other clients simultaneously writing to the same location. - - This is accomplished by passing an update function which is used to transform the current - value of this reference into a new value. If another client writes to this location before - the new value is successfully saved, the update function is called again with the new - current value, and the write will be retried. In case of repeated failures, this method - will retry the transaction up to 25 times before giving up and raising a - TransactionAbortedError. The update function may also force an early abort by raising an - exception instead of returning a value. - - Args: - transaction_update: A function which will be passed the current data stored at this - location. The function should return the new value it would like written. If - an exception is raised, the transaction will be aborted, and the data at this - location will not be modified. The exceptions raised by this function are - propagated to the caller of the transaction method. - - Returns: - object: New value of the current database Reference (only if the transaction commits). - - Raises: - TransactionAbortedError: If the transaction aborts after exhausting all retry attempts. - ValueError: If transaction_update is not a function. - """ - if not callable(transaction_update): - raise ValueError('transaction_update must be a function.') - - tries = 0 - data, etag = self.get(etag=True) - while tries < _TRANSACTION_MAX_RETRIES: - new_data = transaction_update(data) - success, data, etag = self.set_if_unchanged(etag, new_data) - if success: - return new_data - tries += 1 - - raise TransactionAbortedError('Transaction aborted after failed retries.') - - def order_by_child(self, path): - """Returns a Query that orders data by child values. - - Returned Query can be used to set additional parameters, and execute complex database - queries (e.g. limit queries, range queries). - - Args: - path: Path to a valid child of the current Reference. - - Returns: - Query: A database Query instance. - - Raises: - ValueError: If the child path is not a string, not well-formed or None. - """ - if path in _RESERVED_FILTERS: - raise ValueError(f'Illegal child path: {path}') - return Query(order_by=path, client=self._client, pathurl=self._add_suffix()) - - def order_by_key(self): - """Creates a Query that orderes data by key. - - Returned Query can be used to set additional parameters, and execute complex database - queries (e.g. limit queries, range queries). - - Returns: - Query: A database Query instance. - """ - return Query(order_by='$key', client=self._client, pathurl=self._add_suffix()) - - def order_by_value(self): - """Creates a Query that orderes data by value. - - Returned Query can be used to set additional parameters, and execute complex database - queries (e.g. limit queries, range queries). - - Returns: - Query: A database Query instance. - """ - return Query(order_by='$value', client=self._client, pathurl=self._add_suffix()) - - def _add_suffix(self, suffix='.json'): - return self._pathurl + suffix - - def _listen_with_session(self, callback, session=None): - url = self._client.base_url + self._add_suffix() - if not session: - session = self._client.create_listener_session() - - try: - sse = _sseclient.SSEClient(url, session, **{"params": self._client.params}) - return ListenerRegistration(callback, sse) - except requests.exceptions.RequestException as error: - raise _Client.handle_rtdb_error(error) - - -class Query: - """Represents a complex query that can be executed on a Reference. - - Complex queries can consist of up to 2 components: a required ordering constraint, and an - optional filtering constraint. At the server, data is first sorted according to the given - ordering constraint (e.g. order by child). Then the filtering constraint (e.g. limit, range) - is applied on the sorted data to produce the final result. Despite the ordering constraint, - the final result is returned by the server as an unordered collection. Therefore the Query - interface performs another round of sorting at the client-side before returning the results - to the caller. This client-side sorted results are returned to the user as a Python - OrderedDict. - """ - - def __init__(self, **kwargs): - order_by = kwargs.pop('order_by') - if not order_by or not isinstance(order_by, str): - raise ValueError('order_by field must be a non-empty string') - if order_by not in _RESERVED_FILTERS: - if order_by.startswith('/'): - raise ValueError( - f'Invalid path argument: "{order_by}". Child path must not start with "/"') - segments = _parse_path(order_by) - order_by = '/'.join(segments) - self._client = kwargs.pop('client') - self._pathurl = kwargs.pop('pathurl') - self._order_by = order_by - self._params = {'orderBy' : json.dumps(order_by)} - if kwargs: - raise ValueError(f'Unexpected keyword arguments: {kwargs}') - - def limit_to_first(self, limit): - """Creates a query with limit, and anchors it to the start of the window. - - Args: - limit: The maximum number of child nodes to return. - - Returns: - Query: The updated Query instance. - - Raises: - ValueError: If the value is not an integer, or set_limit_last() was called previously. - """ - if not isinstance(limit, int) or limit < 0: - raise ValueError('Limit must be a non-negative integer.') - if 'limitToLast' in self._params: - raise ValueError('Cannot set both first and last limits.') - self._params['limitToFirst'] = limit - return self - - def limit_to_last(self, limit): - """Creates a query with limit, and anchors it to the end of the window. - - Args: - limit: The maximum number of child nodes to return. - - Returns: - Query: The updated Query instance. - - Raises: - ValueError: If the value is not an integer, or set_limit_first() was called previously. - """ - if not isinstance(limit, int) or limit < 0: - raise ValueError('Limit must be a non-negative integer.') - if 'limitToFirst' in self._params: - raise ValueError('Cannot set both first and last limits.') - self._params['limitToLast'] = limit - return self - - def start_at(self, start): - """Sets the lower bound for a range query. - - The Query will only return child nodes with a value greater than or equal to the specified - value. - - Args: - start: JSON-serializable value to start at, inclusive. - - Returns: - Query: The updated Query instance. - - Raises: - ValueError: If the value is ``None``. - """ - if start is None: - raise ValueError('Start value must not be None.') - self._params['startAt'] = json.dumps(start) - return self - - def end_at(self, end): - """Sets the upper bound for a range query. - - The Query will only return child nodes with a value less than or equal to the specified - value. - - Args: - end: JSON-serializable value to end at, inclusive. - - Returns: - Query: The updated Query instance. - - Raises: - ValueError: If the value is ``None``. - """ - if end is None: - raise ValueError('End value must not be None.') - self._params['endAt'] = json.dumps(end) - return self - - def equal_to(self, value): - """Sets an equals constraint on the Query. - - The Query will only return child nodes whose value is equal to the specified value. - - Args: - value: JSON-serializable value to query for. - - Returns: - Query: The updated Query instance. - - Raises: - ValueError: If the value is ``None``. - """ - if value is None: - raise ValueError('Equal to value must not be None.') - self._params['equalTo'] = json.dumps(value) - return self - - @property - def _querystr(self): - params = [] - for key in sorted(self._params): - params.append(f'{key}={self._params[key]}') - return '&'.join(params) - - def get(self): - """Executes this Query and returns the results. - - The results will be returned as a sorted list or an OrderedDict. - - Returns: - object: Decoded JSON result of the Query. - - Raises: - FirebaseError: If an error occurs while communicating with the remote database server. - """ - result = self._client.body('get', self._pathurl, params=self._querystr) - if isinstance(result, (dict, list)) and self._order_by != '$priority': - return _Sorter(result, self._order_by).get() - return result - - -class TransactionAbortedError(exceptions.AbortedError): - """A transaction was aborted aftr exceeding the maximum number of retries.""" - - def __init__(self, message): - exceptions.AbortedError.__init__(self, message) - - -class _Sorter: - """Helper class for sorting query results.""" - - def __init__(self, results, order_by): - if isinstance(results, dict): - self.dict_input = True - entries = [_SortEntry(k, v, order_by) for k, v in results.items()] - elif isinstance(results, list): - self.dict_input = False - entries = [_SortEntry(k, v, order_by) for k, v in enumerate(results)] - else: - raise ValueError(f'Sorting not supported for "{type(results)}" object.') - self.sort_entries = sorted(entries) - - def get(self): - if self.dict_input: - return collections.OrderedDict([(e.key, e.value) for e in self.sort_entries]) - - return [e.value for e in self.sort_entries] - - -class _SortEntry: - """A wrapper that is capable of sorting items in a dictionary.""" - - _type_none = 0 - _type_bool_false = 1 - _type_bool_true = 2 - _type_numeric = 3 - _type_string = 4 - _type_object = 5 - - def __init__(self, key, value, order_by): - self._key = key - self._value = value - if order_by in ('$key', '$priority'): - self._index = key - elif order_by == '$value': - self._index = value - else: - self._index = _SortEntry._extract_child(value, order_by) - self._index_type = _SortEntry._get_index_type(self._index) - - @property - def key(self): - return self._key - - @property - def index(self): - return self._index - - @property - def index_type(self): - return self._index_type - - @property - def value(self): - return self._value - - @classmethod - def _get_index_type(cls, index): - """Assigns an integer code to the type of the index. - - The index type determines how differently typed values are sorted. This ordering is based - on https://firebase.google.com/docs/database/rest/retrieve-data#section-rest-ordered-data - """ - if index is None: - return cls._type_none - if isinstance(index, bool) and not index: - return cls._type_bool_false - if isinstance(index, bool) and index: - return cls._type_bool_true - if isinstance(index, (int, float)): - return cls._type_numeric - if isinstance(index, str): - return cls._type_string - - return cls._type_object - - @classmethod - def _extract_child(cls, value, path): - segments = path.split('/') - current = value - for segment in segments: - if isinstance(current, dict): - current = current.get(segment) - else: - return None - return current - - def _compare(self, other): - """Compares two _SortEntry instances. - - If the indices have the same numeric or string type, compare them directly. Ties are - broken by comparing the keys. If the indices have the same type, but are neither numeric - nor string, compare the keys. In all other cases compare based on the ordering provided - by index types. - """ - self_key, other_key = self.index_type, other.index_type - if self_key == other_key: - if self_key in (self._type_numeric, self._type_string) and self.index != other.index: - self_key, other_key = self.index, other.index - else: - self_key, other_key = self.key, other.key - - if self_key < other_key: - return -1 - if self_key > other_key: - return 1 - - return 0 - - def __lt__(self, other): - return self._compare(other) < 0 - - def __le__(self, other): - return self._compare(other) <= 0 - - def __gt__(self, other): - return self._compare(other) > 0 - - def __ge__(self, other): - return self._compare(other) >= 0 - - def __eq__(self, other): - return self._compare(other) == 0 - - -class _DatabaseService: - """Service that maintains a collection of database clients.""" - - _DEFAULT_AUTH_OVERRIDE = '_admin_' - - def __init__(self, app): - self._credential = app.credential - db_url = app.options.get('databaseURL') - if db_url: - self._db_url = db_url - else: - self._db_url = None - - auth_override = _DatabaseService._get_auth_override(app) - if auth_override not in (self._DEFAULT_AUTH_OVERRIDE, {}): - self._auth_override = json.dumps(auth_override, separators=(',', ':')) - else: - self._auth_override = None - self._timeout = app.options.get('httpTimeout', _http_client.DEFAULT_TIMEOUT_SECONDS) - self._clients = {} - - emulator_host = os.environ.get(_EMULATOR_HOST_ENV_VAR) - if emulator_host: - if '//' in emulator_host: - raise ValueError( - f'Invalid {_EMULATOR_HOST_ENV_VAR}: "{emulator_host}". It must follow format ' - '"host:port".') - self._emulator_host = emulator_host - else: - self._emulator_host = None - - def get_client(self, db_url=None): - """Creates a client based on the db_url. Clients may be cached.""" - if db_url is None: - db_url = self._db_url - - if not db_url or not isinstance(db_url, str): - raise ValueError( - f'Invalid database URL: "{db_url}". Database URL must be a non-empty URL string.') - - parsed_url = parse.urlparse(db_url) - if not parsed_url.netloc: - raise ValueError( - f'Invalid database URL: "{db_url}". Database URL must be a wellformed URL string.') - - emulator_config = self._get_emulator_config(parsed_url) - if emulator_config: - credential = _utils.EmulatorAdminCredentials() - base_url = emulator_config.base_url - params = {'ns': emulator_config.namespace} - else: - # Defer credential lookup until we are certain it's going to be prod connection. - credential = self._credential.get_credential() - base_url = f'https://{parsed_url.netloc}' - params = {} - - - if self._auth_override: - params['auth_variable_override'] = self._auth_override - - client_cache_key = (base_url, json.dumps(params, sort_keys=True)) - if client_cache_key not in self._clients: - client = _Client(credential, base_url, self._timeout, params) - self._clients[client_cache_key] = client - return self._clients[client_cache_key] - - def _get_emulator_config(self, parsed_url): - """Checks whether the SDK should connect to the RTDB emulator.""" - EmulatorConfig = collections.namedtuple('EmulatorConfig', ['base_url', 'namespace']) - if parsed_url.scheme != 'https': - # Emulator mode enabled by passing http URL via AppOptions - base_url, namespace = _DatabaseService._parse_emulator_url(parsed_url) - return EmulatorConfig(base_url, namespace) - if self._emulator_host: - # Emulator mode enabled via environment variable - base_url = f'http://{self._emulator_host}' - namespace = parsed_url.netloc.split('.')[0] - return EmulatorConfig(base_url, namespace) - - return None - - @classmethod - def _parse_emulator_url(cls, parsed_url): - """Parses emulator URL like http://localhost:8080/?ns=foo-bar""" - query_ns = parse.parse_qs(parsed_url.query).get('ns') - if parsed_url.scheme != 'http' or (not query_ns or len(query_ns) != 1 or not query_ns[0]): - raise ValueError( - f'Invalid database URL: "{parsed_url.geturl()}". Database URL must be a valid URL ' - 'to a Firebase Realtime Database instance.') - - namespace = query_ns[0] - base_url = f'{parsed_url.scheme}://{parsed_url.netloc}' - return base_url, namespace - - @classmethod - def _get_auth_override(cls, app): - """Gets and validates the database auth override to be used.""" - auth_override = app.options.get('databaseAuthVariableOverride', cls._DEFAULT_AUTH_OVERRIDE) - if auth_override == cls._DEFAULT_AUTH_OVERRIDE or auth_override is None: - return auth_override - if not isinstance(auth_override, dict): - raise ValueError( - f'Invalid databaseAuthVariableOverride option: "{auth_override}". Override ' - 'value must be a dict or None.') - - return auth_override - - def close(self): - for value in self._clients.values(): - value.close() - self._clients = {} - - -class _Client(_http_client.JsonHttpClient): - """HTTP client used to make REST calls. - - _Client maintains an HTTP session, and handles authenticating HTTP requests along with - marshalling and unmarshalling of JSON data. - """ - - def __init__(self, credential, base_url, timeout, params=None): - """Creates a new _Client from the given parameters. - - This exists primarily to enable testing. For regular use, obtain _Client instances by - calling the from_app() class method. - - Args: - credential: A Google credential that can be used to authenticate requests. - base_url: A URL prefix to be added to all outgoing requests. This is typically the - Firebase Realtime Database URL. - timeout: HTTP request timeout in seconds. If set to None connections will never - timeout, which is the default behavior of the underlying requests library. - params: Dict of query parameters to add to all outgoing requests. - """ - super().__init__( - credential=credential, base_url=base_url, - timeout=timeout, headers={'User-Agent': _USER_AGENT}) - self.credential = credential - self.params = params if params else {} - - def request(self, method, url, **kwargs): - """Makes an HTTP call using the Python requests library. - - Extends the request() method of the parent JsonHttpClient class. Handles default - params like auth overrides, and low-level exceptions. - - Args: - method: HTTP method name as a string (e.g. get, post). - url: URL path of the remote endpoint. This will be appended to the server's base URL. - **kwargs: An additional set of keyword arguments to be passed into requests API - (e.g. json, params). - - Returns: - Response: An HTTP response object. - - Raises: - FirebaseError: If an error occurs while making the HTTP call. - """ - query = '&'.join(f'{key}={value}' for key, value in self.params.items()) - extra_params = kwargs.get('params') - if extra_params: - if query: - query = extra_params + '&' + query - else: - query = extra_params - kwargs['params'] = query - - try: - return super().request(method, url, **kwargs) - except requests.exceptions.RequestException as error: - raise _Client.handle_rtdb_error(error) - - def create_listener_session(self): - return _sseclient.KeepAuthSession(self.credential) - - @classmethod - def handle_rtdb_error(cls, error): - """Converts an error encountered while calling RTDB into a FirebaseError.""" - if error.response is None: - return _utils.handle_requests_error(error) - - message = cls._extract_error_message(error.response) - return _utils.handle_requests_error(error, message=message) - - @classmethod - def _extract_error_message(cls, response): - """Extracts an error message from an error response. - - If the server has sent a JSON response with an 'error' field, which is the typical - behavior of the Realtime Database REST API, parses the response to retrieve the error - message. If the server has sent a non-JSON response, returns the full response - as the error message. - """ - message = None - try: - # RTDB error format: {"error": "text message"} - data = response.json() - if isinstance(data, dict): - message = data.get('error') - except ValueError: - pass - - if not message: - message = f'Unexpected response from database: {response.content.decode()}' - - return message diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/exceptions.py b/notification-service/venv/Lib/site-packages/firebase_admin/exceptions.py deleted file mode 100644 index 947f368..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/exceptions.py +++ /dev/null @@ -1,237 +0,0 @@ -# Copyright 2019 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase Exceptions module. - -This module defines the base types for exceptions and the platform-wide error codes as outlined in -https://cloud.google.com/apis/design/errors. - -:class:`FirebaseError` is the parent class of all exceptions raised by the Admin SDK. It contains -the ``code``, ``http_response`` and ``cause`` properties common to all Firebase exception types. -Each exception also carries a message that outlines what went wrong. This can be logged for -audit or debugging purposes. - -When calling an Admin SDK API, developers can catch the parent ``FirebaseError`` and -inspect its ``code`` to implement fine-grained error handling. Alternatively, developers can -catch one or more subtypes of ``FirebaseError``. Under normal conditions, any given API can raise -only a small subset of the available exception subtypes. However, the SDK also exposes rare error -conditions like connection timeouts and other I/O errors as instances of ``FirebaseError``. -Therefore it is always a good idea to have a handler specified for ``FirebaseError``, after all the -subtype error handlers. -""" - - -#: Error code for ``InvalidArgumentError`` type. -INVALID_ARGUMENT = 'INVALID_ARGUMENT' - -#: Error code for ``FailedPreconditionError`` type. -FAILED_PRECONDITION = 'FAILED_PRECONDITION' - -#: Error code for ``OutOfRangeError`` type. -OUT_OF_RANGE = 'OUT_OF_RANGE' - -#: Error code for ``UnauthenticatedError`` type. -UNAUTHENTICATED = 'UNAUTHENTICATED' - -#: Error code for ``PermissionDeniedError`` type. -PERMISSION_DENIED = 'PERMISSION_DENIED' - -#: Error code for ``NotFoundError`` type. -NOT_FOUND = 'NOT_FOUND' - -#: Error code for ``ConflictError`` type. -CONFLICT = 'CONFLICT' - -#: Error code for ``AbortedError`` type. -ABORTED = 'ABORTED' - -#: Error code for ``AlreadyExistsError`` type. -ALREADY_EXISTS = 'ALREADY_EXISTS' - -#: Error code for ``ResourceExhaustedError`` type. -RESOURCE_EXHAUSTED = 'RESOURCE_EXHAUSTED' - -#: Error code for ``CancelledError`` type. -CANCELLED = 'CANCELLED' - -#: Error code for ``DataLossError`` type. -DATA_LOSS = 'DATA_LOSS' - -#: Error code for ``UnknownError`` type. -UNKNOWN = 'UNKNOWN' - -#: Error code for ``InternalError`` type. -INTERNAL = 'INTERNAL' - -#: Error code for ``UnavailableError`` type. -UNAVAILABLE = 'UNAVAILABLE' - -#: Error code for ``DeadlineExceededError`` type. -DEADLINE_EXCEEDED = 'DEADLINE_EXCEEDED' - - -class FirebaseError(Exception): - """Base class for all errors raised by the Admin SDK. - - Args: - code: A string error code that represents the type of the exception. Possible error - codes are defined in https://cloud.google.com/apis/design/errors#handling_errors. - message: A human-readable error message string. - cause: The exception that caused this error (optional). - http_response: If this error was caused by an HTTP error response, this property is - set to the ``requests.Response`` object that represents the HTTP response (optional). - See https://docs.python-requests.org/en/master/api/#requests.Response for details of - this object. - """ - - def __init__(self, code, message, cause=None, http_response=None): - Exception.__init__(self, message) - self._code = code - self._cause = cause - self._http_response = http_response - - @property - def code(self): - return self._code - - @property - def cause(self): - return self._cause - - @property - def http_response(self): - return self._http_response - - -class InvalidArgumentError(FirebaseError): - """Client specified an invalid argument.""" - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, INVALID_ARGUMENT, message, cause, http_response) - - -class FailedPreconditionError(FirebaseError): - """Request can not be executed in the current system state, such as deleting a non-empty - directory.""" - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, FAILED_PRECONDITION, message, cause, http_response) - - -class OutOfRangeError(FirebaseError): - """Client specified an invalid range.""" - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, OUT_OF_RANGE, message, cause, http_response) - - -class UnauthenticatedError(FirebaseError): - """Request not authenticated due to missing, invalid, or expired OAuth token.""" - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, UNAUTHENTICATED, message, cause, http_response) - - -class PermissionDeniedError(FirebaseError): - """Client does not have sufficient permission. - - This can happen because the OAuth token does not have the right scopes, the client doesn't - have permission, or the API has not been enabled for the client project. - """ - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, PERMISSION_DENIED, message, cause, http_response) - - -class NotFoundError(FirebaseError): - """A specified resource is not found, or the request is rejected by undisclosed reasons, such - as whitelisting.""" - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, NOT_FOUND, message, cause, http_response) - - -class ConflictError(FirebaseError): - """Concurrency conflict, such as read-modify-write conflict.""" - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, CONFLICT, message, cause, http_response) - - -class AbortedError(FirebaseError): - """Concurrency conflict, such as read-modify-write conflict.""" - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, ABORTED, message, cause, http_response) - - -class AlreadyExistsError(FirebaseError): - """The resource that a client tried to create already exists.""" - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, ALREADY_EXISTS, message, cause, http_response) - - -class ResourceExhaustedError(FirebaseError): - """Either out of resource quota or reaching rate limiting.""" - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, RESOURCE_EXHAUSTED, message, cause, http_response) - - -class CancelledError(FirebaseError): - """Request cancelled by the client.""" - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, CANCELLED, message, cause, http_response) - - -class DataLossError(FirebaseError): - """Unrecoverable data loss or data corruption.""" - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, DATA_LOSS, message, cause, http_response) - - -class UnknownError(FirebaseError): - """Unknown server error.""" - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, UNKNOWN, message, cause, http_response) - - -class InternalError(FirebaseError): - """Internal server error.""" - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, INTERNAL, message, cause, http_response) - - -class UnavailableError(FirebaseError): - """Service unavailable. Typically the server is down.""" - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, UNAVAILABLE, message, cause, http_response) - - -class DeadlineExceededError(FirebaseError): - """Request deadline exceeded. - - This will happen only if the caller sets a deadline that is shorter than the method's - default deadline (i.e. requested deadline is not enough for the server to process the - request) and the request did not finish within the deadline. - """ - - def __init__(self, message, cause=None, http_response=None): - FirebaseError.__init__(self, DEADLINE_EXCEEDED, message, cause, http_response) diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/firestore.py b/notification-service/venv/Lib/site-packages/firebase_admin/firestore.py deleted file mode 100644 index 52ea906..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/firestore.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Cloud Firestore module. - -This module contains utilities for accessing the Google Cloud Firestore databases associated with -Firebase apps. This requires the ``google-cloud-firestore`` Python module. -""" - -from __future__ import annotations -from typing import Optional, Dict -from firebase_admin import App -from firebase_admin import _utils - -try: - from google.cloud import firestore - from google.cloud.firestore_v1.base_client import DEFAULT_DATABASE - existing = globals().keys() - for key, value in firestore.__dict__.items(): - if not key.startswith('_') and key not in existing: - globals()[key] = value -except ImportError as error: - raise ImportError('Failed to import the Cloud Firestore library for Python. Make sure ' - 'to install the "google-cloud-firestore" module.') from error - - -_FIRESTORE_ATTRIBUTE = '_firestore' - - -def client(app: Optional[App] = None, database_id: Optional[str] = None) -> firestore.Client: - """Returns a client that can be used to interact with Google Cloud Firestore. - - Args: - app: An App instance (optional). - database_id: The database ID of the Google Cloud Firestore database to be used. - Defaults to the default Firestore database ID if not specified or an empty string - (optional). - - Returns: - google.cloud.firestore.Firestore: A `Firestore Client`_. - - Raises: - ValueError: If the specified database ID is not a valid string, or if a project ID is not - specified either via options, credentials or environment variables, or if the specified - project ID is not a valid string. - - .. _Firestore Client: https://cloud.google.com/python/docs/reference/firestore/latest/\ - google.cloud.firestore_v1.client.Client - """ - # Validate database_id - if database_id is not None and not isinstance(database_id, str): - raise ValueError(f'database_id "{database_id}" must be a string or None.') - fs_service = _utils.get_app_service(app, _FIRESTORE_ATTRIBUTE, _FirestoreService) - return fs_service.get_client(database_id) - - -class _FirestoreService: - """Service that maintains a collection of firestore clients.""" - - def __init__(self, app: App) -> None: - self._app: App = app - self._clients: Dict[str, firestore.Client] = {} - - def get_client(self, database_id: Optional[str]) -> firestore.Client: - """Creates a client based on the database_id. These clients are cached.""" - database_id = database_id or DEFAULT_DATABASE - if database_id not in self._clients: - # Create a new client and cache it in _clients - credentials = self._app.credential.get_credential() - project = self._app.project_id - if not project: - raise ValueError( - 'Project ID is required to access Firestore. Either set the projectId option, ' - 'or use service account credentials. Alternatively, set the ' - 'GOOGLE_CLOUD_PROJECT environment variable.') - - fs_client = firestore.Client( - credentials=credentials, project=project, database=database_id) - self._clients[database_id] = fs_client - - return self._clients[database_id] diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/firestore_async.py b/notification-service/venv/Lib/site-packages/firebase_admin/firestore_async.py deleted file mode 100644 index 4a197e9..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/firestore_async.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright 2022 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Cloud Firestore Async module. - -This module contains utilities for asynchronusly accessing the Google Cloud Firestore databases -associated with Firebase apps. This requires the ``google-cloud-firestore`` Python module. -""" - -from __future__ import annotations -from typing import Optional, Dict -from firebase_admin import App -from firebase_admin import _utils - -try: - from google.cloud import firestore - from google.cloud.firestore_v1.base_client import DEFAULT_DATABASE - existing = globals().keys() - for key, value in firestore.__dict__.items(): - if not key.startswith('_') and key not in existing: - globals()[key] = value -except ImportError as error: - raise ImportError('Failed to import the Cloud Firestore library for Python. Make sure ' - 'to install the "google-cloud-firestore" module.') from error - - -_FIRESTORE_ASYNC_ATTRIBUTE: str = '_firestore_async' - - -def client(app: Optional[App] = None, database_id: Optional[str] = None) -> firestore.AsyncClient: - """Returns an async client that can be used to interact with Google Cloud Firestore. - - Args: - app: An App instance (optional). - database_id: The database ID of the Google Cloud Firestore database to be used. - Defaults to the default Firestore database ID if not specified or an empty string - (optional). - - Returns: - google.cloud.firestore.Firestore_Async: A `Firestore Async Client`_. - - Raises: - ValueError: If the specified database ID is not a valid string, or if a project ID is not - specified either via options, credentials or environment variables, or if the specified - project ID is not a valid string. - - .. _Firestore Async Client: https://cloud.google.com/python/docs/reference/firestore/latest/\ - google.cloud.firestore_v1.async_client.AsyncClient - """ - # Validate database_id - if database_id is not None and not isinstance(database_id, str): - raise ValueError(f'database_id "{database_id}" must be a string or None.') - - fs_service = _utils.get_app_service(app, _FIRESTORE_ASYNC_ATTRIBUTE, _FirestoreAsyncService) - return fs_service.get_client(database_id) - -class _FirestoreAsyncService: - """Service that maintains a collection of firestore async clients.""" - - def __init__(self, app: App) -> None: - self._app: App = app - self._clients: Dict[str, firestore.AsyncClient] = {} - - def get_client(self, database_id: Optional[str]) -> firestore.AsyncClient: - """Creates an async client based on the database_id. These clients are cached.""" - database_id = database_id or DEFAULT_DATABASE - if database_id not in self._clients: - # Create a new client and cache it in _clients - credentials = self._app.credential.get_credential() - project = self._app.project_id - if not project: - raise ValueError( - 'Project ID is required to access Firestore. Either set the projectId option, ' - 'or use service account credentials. Alternatively, set the ' - 'GOOGLE_CLOUD_PROJECT environment variable.') - - fs_client = firestore.AsyncClient( - credentials=credentials, project=project, database=database_id) - self._clients[database_id] = fs_client - - return self._clients[database_id] diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/functions.py b/notification-service/venv/Lib/site-packages/firebase_admin/functions.py deleted file mode 100644 index 66ba700..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/functions.py +++ /dev/null @@ -1,518 +0,0 @@ -# Copyright 2024 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase Functions module.""" - -from __future__ import annotations -from datetime import datetime, timedelta, timezone -from urllib import parse -import re -import os -import json -from base64 import b64encode -from typing import Any, Optional, Dict -from dataclasses import dataclass - -from google.auth.compute_engine import Credentials as ComputeEngineCredentials -from google.auth.credentials import TokenState -from google.auth.exceptions import RefreshError -from google.auth.transport import requests as google_auth_requests - -import requests -import firebase_admin -from firebase_admin import App -from firebase_admin import _http_client -from firebase_admin import _utils - -_FUNCTIONS_ATTRIBUTE = '_functions' - -__all__ = [ - 'TaskOptions', - - 'task_queue', -] - - -_CLOUD_TASKS_API_RESOURCE_PATH = \ - 'projects/{project_id}/locations/{location_id}/queues/{resource_id}/tasks' -_CLOUD_TASKS_API_URL_FORMAT = \ - 'https://cloudtasks.googleapis.com/v2/' + _CLOUD_TASKS_API_RESOURCE_PATH -_FIREBASE_FUNCTION_URL_FORMAT = \ - 'https://{location_id}-{project_id}.cloudfunctions.net/{resource_id}' -_EMULATOR_HOST_ENV_VAR = 'CLOUD_TASKS_EMULATOR_HOST' -_EMULATED_SERVICE_ACCOUNT_DEFAULT = 'emulated-service-acct@email.com' - -_FUNCTIONS_HEADERS = { - 'X-GOOG-API-FORMAT-VERSION': '2', - 'X-FIREBASE-CLIENT': f'fire-admin-python/{firebase_admin.__version__}', -} - -# Default canonical location ID of the task queue. -_DEFAULT_LOCATION = 'us-central1' - -def _get_emulator_host() -> Optional[str]: - emulator_host = os.environ.get(_EMULATOR_HOST_ENV_VAR) - if emulator_host: - if '//' in emulator_host: - raise ValueError( - f'Invalid {_EMULATOR_HOST_ENV_VAR}: "{emulator_host}". It must follow format ' - '"host:port".') - return emulator_host - return None - - -def _get_functions_service(app) -> _FunctionsService: - return _utils.get_app_service(app, _FUNCTIONS_ATTRIBUTE, _FunctionsService) - -def task_queue( - function_name: str, - extension_id: Optional[str] = None, - app: Optional[App] = None - ) -> TaskQueue: - """Creates a reference to a TaskQueue for a given function name. - - The function name can be either: - 1. A fully qualified function resource name: - `projects/{project-id}/locations/{location-id}/functions/{function-name}` - - 2. A partial resource name with location and function name, in which case - the runtime project ID is used: - `locations/{location-id}/functions/{function-name}` - - 3. A partial function name, in which case the runtime project ID and the - default location, `us-central1`, is used: - `{function-name}` - - Args: - function_name: Name of the function. - extension_id: Firebase extension ID (optional). - app: An App instance (optional). - - Returns: - TaskQueue: A TaskQueue instance. - - Raises: - ValueError: If the input arguments are invalid. - """ - return _get_functions_service(app).task_queue(function_name, extension_id) - -class _FunctionsService: - """Service class that implements Firebase Functions functionality.""" - def __init__(self, app: App): - self._project_id = app.project_id - if not self._project_id: - raise ValueError( - 'Project ID is required to access the Cloud Functions service. Either set the ' - 'projectId option, or use service account credentials. Alternatively, set the ' - 'GOOGLE_CLOUD_PROJECT environment variable.') - - self._emulator_host = _get_emulator_host() - if self._emulator_host: - self._credential = _utils.EmulatorAdminCredentials() - else: - self._credential = app.credential.get_credential() - - self._http_client = _http_client.JsonHttpClient(credential=self._credential) - - def task_queue(self, function_name: str, extension_id: Optional[str] = None) -> TaskQueue: - """Creates a TaskQueue instance.""" - return TaskQueue( - function_name, extension_id, self._project_id, self._credential, self._http_client, - self._emulator_host) - - @classmethod - def handle_functions_error(cls, error: Any): - """Handles errors received from the Cloud Functions API.""" - - return _utils.handle_platform_error_from_requests(error) - -class TaskQueue: - """TaskQueue class that implements Firebase Cloud Tasks Queues functionality.""" - def __init__( - self, - function_name: str, - extension_id: Optional[str], - project_id, - credential, - http_client, - emulator_host: Optional[str] = None - ) -> None: - - # Validate function_name - _Validators.check_non_empty_string('function_name', function_name) - - self._project_id = project_id - self._credential = credential - self._http_client = http_client - self._emulator_host = emulator_host - self._function_name = function_name - self._extension_id = extension_id - # Parse resources from function_name - self._resource = self._parse_resource_name(self._function_name, 'functions') - - # Apply defaults and validate resource_id - self._resource.project_id = self._resource.project_id or self._project_id - self._resource.location_id = self._resource.location_id or _DEFAULT_LOCATION - _Validators.check_non_empty_string('resource.resource_id', self._resource.resource_id) - # Validate extension_id if provided and edit resources depending - if self._extension_id is not None: - _Validators.check_non_empty_string('extension_id', self._extension_id) - self._resource.resource_id = f'ext-{self._extension_id}-{self._resource.resource_id}' - - - def enqueue(self, task_data: Any, opts: Optional[TaskOptions] = None) -> str: - """Creates a task and adds it to the queue. Tasks cannot be updated after creation. - - This action requires `cloudtasks.tasks.create` IAM permission on the service account. - - Args: - task_data: The data payload of the task. - opts: Options when enqueuing a new task (optional). - - Raises: - FirebaseError: If an error occurs while requesting the task to be queued by - the Cloud Functions service. - ValueError: If the input arguments are invalid. - - Returns: - str: The ID of the task relative to this queue. - """ - task = self._validate_task_options(task_data, self._resource, opts) - emulator_url = self._get_emulator_url(self._resource) - service_url = emulator_url or self._get_url(self._resource, _CLOUD_TASKS_API_URL_FORMAT) - task_payload = self._update_task_payload(task, self._resource, self._extension_id) - try: - resp = self._http_client.body( - 'post', - url=service_url, - headers=_FUNCTIONS_HEADERS, - json={'task': task_payload.to_api_dict()} - ) - if self._is_emulated(): - # Emulator returns a response with format {task: {name: }} - # The task name also has an extra '/' at the start compared to prod - task_info = resp.get('task') or {} - task_name = task_info.get('name') - if task_name: - task_name = task_name[1:] - else: - # Production returns a response with format {name: } - task_name = resp.get('name') - task_resource = \ - self._parse_resource_name(task_name, f'queues/{self._resource.resource_id}/tasks') - return task_resource.resource_id - except requests.exceptions.RequestException as error: - raise _FunctionsService.handle_functions_error(error) - - def delete(self, task_id: str) -> None: - """Deletes an enqueued task if it has not yet started. - - This action requires `cloudtasks.tasks.delete` IAM permission on the service account. - - Args: - task_id: The ID of the task relative to this queue. - - Raises: - FirebaseError: If an error occurs while requesting the task to be deleted by - the Cloud Functions service. - ValueError: If the input arguments are invalid. - """ - _Validators.check_non_empty_string('task_id', task_id) - emulator_url = self._get_emulator_url(self._resource) - if emulator_url: - service_url = emulator_url + f'/{task_id}' - else: - service_url = self._get_url(self._resource, _CLOUD_TASKS_API_URL_FORMAT + f'/{task_id}') - try: - self._http_client.body( - 'delete', - url=service_url, - headers=_FUNCTIONS_HEADERS, - ) - except requests.exceptions.RequestException as error: - raise _FunctionsService.handle_functions_error(error) - - - def _parse_resource_name(self, resource_name: str, resource_id_key: str) -> Resource: - """Parses a full or partial resource path into a ``Resource``.""" - if '/' not in resource_name: - return Resource(resource_id=resource_name) - - reg = f'^(projects/([^/]+)/)?locations/([^/]+)/{resource_id_key}/([^/]+)$' - match = re.search(reg, resource_name) - if match is None: - raise ValueError('Invalid resource name format.') - return Resource(project_id=match[2], location_id=match[3], resource_id=match[4]) - - def _get_url(self, resource: Resource, url_format: str) -> str: - """Generates url path from a ``Resource`` and url format string.""" - return url_format.format( - project_id=resource.project_id, - location_id=resource.location_id, - resource_id=resource.resource_id) - - def _validate_task_options( - self, - data: Any, - resource: Resource, - opts: Optional[TaskOptions] = None - ) -> Task: - """Validate and create a Task from optional ``TaskOptions``.""" - task_http_request = { - 'url': '', - 'oidcToken': { - 'serviceAccountEmail': '' - }, - 'body': b64encode(json.dumps(data).encode()).decode(), - 'headers': { - 'Content-Type': 'application/json', - } - } - task = Task(http_request=task_http_request) - - if opts is not None: - if opts.headers is not None: - task.http_request['headers'] = {**task.http_request['headers'], **opts.headers} - if opts.schedule_time is not None and opts.schedule_delay_seconds is not None: - raise ValueError( - 'Both schedule_delay_seconds and schedule_time cannot be set at the same time.') - if opts.schedule_time is not None and opts.schedule_delay_seconds is None: - if not isinstance(opts.schedule_time, datetime): - raise ValueError('schedule_time should be UTC datetime.') - task.schedule_time = opts.schedule_time.strftime('%Y-%m-%dT%H:%M:%S.%fZ') - if opts.schedule_delay_seconds is not None and opts.schedule_time is None: - if not isinstance(opts.schedule_delay_seconds, int) \ - or opts.schedule_delay_seconds < 0: - raise ValueError('schedule_delay_seconds should be positive int.') - schedule_time = ( - datetime.now(timezone.utc) + timedelta(seconds=opts.schedule_delay_seconds)) - task.schedule_time = schedule_time.strftime('%Y-%m-%dT%H:%M:%S.%fZ') - if opts.dispatch_deadline_seconds is not None: - if not isinstance(opts.dispatch_deadline_seconds, int) \ - or opts.dispatch_deadline_seconds < 15 \ - or opts.dispatch_deadline_seconds > 1800: - raise ValueError( - 'dispatch_deadline_seconds should be int in the range of 15s to ' - '1800s (30 mins).') - task.dispatch_deadline = f'{opts.dispatch_deadline_seconds}s' - if opts.task_id is not None: - if not _Validators.is_task_id(opts.task_id): - raise ValueError( - 'task_id can contain only letters ([A-Za-z]), numbers ([0-9]), hyphens (-)' - ', or underscores (_). The maximum length is 500 characters.') - task.name = self._get_url( - resource, _CLOUD_TASKS_API_RESOURCE_PATH + f'/{opts.task_id}') - if opts.uri is not None: - if not _Validators.is_url(opts.uri): - raise ValueError( - 'uri must be a valid RFC3986 URI string using the https or http schema.') - task.http_request['url'] = opts.uri - return task - - def _update_task_payload(self, task: Task, resource: Resource, extension_id: str) -> Task: - """Prepares task to be sent with credentials.""" - # Get function url from task or generate from resources - if not _Validators.is_non_empty_string(task.http_request['url']): - if self._is_emulated(): - task.http_request['url'] = '' - else: - task.http_request['url'] = self._get_url(resource, _FIREBASE_FUNCTION_URL_FORMAT) - - # Refresh the credential to ensure all attributes (e.g. service_account_email, id_token) - # are populated, preventing cold start errors. - if self._credential.token_state != TokenState.FRESH: - try: - self._credential.refresh(google_auth_requests.Request()) - except RefreshError as err: - raise ValueError(f'Initial task payload credential refresh failed: {err}') from err - - # If extension id is provided, it implies that it is being run from a deployed extension. - # Meaning that it's credential should be a Compute Engine Credential. - if _Validators.is_non_empty_string(extension_id) and \ - isinstance(self._credential, ComputeEngineCredentials): - id_token = self._credential.token - task.http_request['headers'] = \ - {**task.http_request['headers'], 'Authorization': f'Bearer {id_token}'} - # Delete oidc token - del task.http_request['oidcToken'] - else: - try: - task.http_request['oidcToken'] = \ - {'serviceAccountEmail': self._credential.service_account_email} - except AttributeError as error: - if self._is_emulated(): - task.http_request['oidcToken'] = \ - {'serviceAccountEmail': _EMULATED_SERVICE_ACCOUNT_DEFAULT} - else: - raise ValueError( - 'Failed to determine service account. Initialize the SDK with service ' - 'account credentials or set service account ID as an app option.' - ) from error - return task - - def _get_emulator_url(self, resource: Resource): - if self._emulator_host: - emulator_url_format = f'http://{self._emulator_host}/' + _CLOUD_TASKS_API_RESOURCE_PATH - url = self._get_url(resource, emulator_url_format) - return url - return None - - def _is_emulated(self): - return self._emulator_host is not None - - -class _Validators: - """A collection of data validation utilities.""" - @classmethod - def check_non_empty_string(cls, label: str, value: Any): - """Checks if given value is a non-empty string and throws error if not.""" - if not isinstance(value, str): - raise ValueError(f'{label} "{value}" must be a string.') - if value == '': - raise ValueError(f'{label} "{value}" must be a non-empty string.') - - @classmethod - def is_non_empty_string(cls, value: Any): - """Checks if given value is a non-empty string and returns bool.""" - if not isinstance(value, str) or value == '': - return False - return True - - @classmethod - def is_task_id(cls, task_id: Any): - """Checks if given value is a valid task id.""" - reg = '^[A-Za-z0-9_-]+$' - if re.match(reg, task_id) is not None and len(task_id) <= 500: - return True - return False - - @classmethod - def is_url(cls, url: Any): - """Checks if given value is a valid url.""" - if not isinstance(url, str): - return False - try: - parsed = parse.urlparse(url) - if not parsed.netloc or parsed.scheme not in ['http', 'https']: - return False - return True - except Exception: # pylint: disable=broad-except - return False - - -@dataclass -class TaskOptions: - """Task Options that can be applied to a Task. - - Args: - schedule_delay_seconds: The number of seconds after the current time at which to attempt or - retry the task. Should only be set if ``schedule_time`` is not set. - - schedule_time: The time when the task is scheduled to be attempted or retried. Should only - be set if ``schedule_delay_seconds`` is not set. - - dispatch_deadline_seconds: The deadline for requests sent to the worker. If the worker does - not respond by this deadline then the request is cancelled and the attempt is marked as - a ``DEADLINE_EXCEEDED`` failure. Cloud Tasks will retry the task according to the - ``RetryConfig``. The default is 10 minutes. The deadline must be in the range of 15 - seconds and 30 minutes (1800 seconds). - - task_id: The ID to use for the enqueued task. If not provided, one will be automatically - generated. - - If provided, an explicitly specified task ID enables task de-duplication. - Task IDs should be strings that contain only letters ([A-Za-z]), numbers ([0-9]), - hyphens (-), and underscores (_) with a maximum length of 500 characters. If a task's - ID is identical to that of an existing task or a task that was deleted or executed - recently then the call will throw an error with code `functions/task-already-exists`. - Another task with the same ID can't be created for ~1hour after the original task was - deleted or executed. - - Because there is an extra lookup cost to identify duplicate task IDs, setting ID - significantly increases latency. - - Also, note that the infrastructure relies on an approximately uniform distribution - of task IDs to store and serve tasks efficiently. For this reason, using hashed strings - for the task ID or for the prefix of the task ID is recommended. Choosing task IDs that - are sequential or have sequential prefixes, for example using a timestamp, causes an - increase in latency and error rates in all task commands. - - Push IDs from the Firebase Realtime Database make poor IDs because they are based on - timestamps and will cause contention (slowdowns) in your task queue. Reversed push IDs - however form a perfect distribution and are an ideal key. To reverse a string in Python - use ``reversedString = someString[::-1]`` - - headers: HTTP request headers to include in the request to the task queue function. These - headers represent a subset of the headers that will accompany the task's HTTP request. - Some HTTP request headers will be ignored or replaced: `Authorization`, `Host`, - `Content-Length`, `User-Agent` and others cannot be overridden. - - A complete list of these ignored or replaced headers can be found in the following - definition of the HttpRequest.headers property: - https://cloud.google.com/tasks/docs/reference/rest/v2/projects.locations.queues.tasks#httprequest - - By default, Content-Type is set to 'application/json'. - - The size of the headers must be less than 80KB. - - uri: The full URL that the request will be sent to. Must be a valid RFC3986 https or - http URL. - """ - schedule_delay_seconds: Optional[int] = None - schedule_time: Optional[datetime] = None - dispatch_deadline_seconds: Optional[int] = None - task_id: Optional[str] = None - headers: Optional[Dict[str, str]] = None - uri: Optional[str] = None - -@dataclass -class Task: - """Contains the relevant fields for enqueueing tasks that trigger Cloud Functions. - - This is a limited subset of the Cloud Functions `Task` resource. See the following - page for definitions of this class's properties: - https://cloud.google.com/tasks/docs/reference/rest/v2/projects.locations.queues.tasks#resource:-task - - Args: - httpRequest: The request to be made by the task worker. - name: The name of the function. See the Cloud docs for the format of this property. - schedule_time: The time when the task is scheduled to be attempted or retried. - dispatch_deadline: The deadline for requests sent to the worker. - """ - http_request: Dict[str, Optional[str | dict]] - name: Optional[str] = None - schedule_time: Optional[str] = None - dispatch_deadline: Optional[str] = None - - def to_api_dict(self) -> dict: - """Converts the Task object to a dictionary suitable for the Cloud Tasks API.""" - return { - 'httpRequest': self.http_request, - 'name': self.name, - 'scheduleTime': self.schedule_time, - 'dispatchDeadline': self.dispatch_deadline, - } - -@dataclass -class Resource: - """Contains the parsed address of a resource. - - Args: - resource_id: The ID of the resource. - project_id: The project ID of the resource. - location_id: The location ID of the resource. - """ - resource_id: str - project_id: Optional[str] = None - location_id: Optional[str] = None diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/instance_id.py b/notification-service/venv/Lib/site-packages/firebase_admin/instance_id.py deleted file mode 100644 index 812daf4..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/instance_id.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase Instance ID module. - -This module enables deleting instance IDs associated with Firebase projects. -""" - -import requests - -from firebase_admin import _http_client -from firebase_admin import _utils - - -_IID_SERVICE_URL = 'https://console.firebase.google.com/v1/' -_IID_ATTRIBUTE = '_iid' - - -def _get_iid_service(app): - return _utils.get_app_service(app, _IID_ATTRIBUTE, _InstanceIdService) - - -def delete_instance_id(instance_id, app=None): - """Deletes the specified instance ID and the associated data from Firebase. - - Note that Google Analytics for Firebase uses its own form of Instance ID to - keep track of analytics data. Therefore deleting a regular Instance ID does - not delete Analytics data. See `Delete an Instance ID`_ for more information. - - Args: - instance_id: A non-empty instance ID string. - app: An App instance (optional). - - Raises: - InstanceIdError: If an error occurs while invoking the backend instance ID service. - ValueError: If the specified instance ID or app is invalid. - - .. _Delete an Instance ID: https://firebase.google.com/support/privacy\ - /manage-iids#delete_an_instance_id - """ - _get_iid_service(app).delete_instance_id(instance_id) - - -class _InstanceIdService: - """Provides methods for interacting with the remote instance ID service.""" - - error_codes = { - 400: 'Malformed instance ID argument.', - 401: 'Request not authorized.', - 403: 'Project does not match instance ID or the client does not have ' - 'sufficient privileges.', - 404: 'Failed to find the instance ID.', - 409: 'Already deleted.', - 429: 'Request throttled out by the backend server.', - 500: 'Internal server error.', - 503: 'Backend servers are over capacity. Try again later.' - } - - def __init__(self, app): - project_id = app.project_id - if not project_id: - raise ValueError( - 'Project ID is required to access Instance ID service. Either set the projectId ' - 'option, or use service account credentials. Alternatively, set the ' - 'GOOGLE_CLOUD_PROJECT environment variable.') - self._project_id = project_id - self._client = _http_client.JsonHttpClient( - credential=app.credential.get_credential(), base_url=_IID_SERVICE_URL) - - def delete_instance_id(self, instance_id): - if not isinstance(instance_id, str) or not instance_id: - raise ValueError('Instance ID must be a non-empty string.') - path = f'project/{self._project_id}/instanceId/{instance_id}' - try: - self._client.request('delete', path) - except requests.exceptions.RequestException as error: - msg = self._extract_message(instance_id, error) - raise _utils.handle_requests_error(error, msg) - - def _extract_message(self, instance_id, error): - if error.response is None: - return None - status = error.response.status_code - msg = self.error_codes.get(status) - if msg: - return f'Instance ID "{instance_id}": {msg}' - - return f'Instance ID "{instance_id}": {error}' diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/messaging.py b/notification-service/venv/Lib/site-packages/firebase_admin/messaging.py deleted file mode 100644 index 7490444..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/messaging.py +++ /dev/null @@ -1,607 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase Cloud Messaging module.""" - -from __future__ import annotations -from typing import Any, Callable, Dict, List, Optional, cast -import concurrent.futures -import json -import asyncio -import logging -import requests -import httpx - -import firebase_admin -from firebase_admin import ( - _http_client, - _messaging_encoder, - _messaging_utils, - _utils, - exceptions, - App -) - -logger = logging.getLogger(__name__) - -_MESSAGING_ATTRIBUTE = '_messaging' - - -__all__ = [ - 'AndroidConfig', - 'AndroidFCMOptions', - 'AndroidNotification', - 'APNSConfig', - 'APNSFCMOptions', - 'APNSPayload', - 'Aps', - 'ApsAlert', - 'BatchResponse', - 'CriticalSound', - 'ErrorInfo', - 'FCMOptions', - 'LightSettings', - 'Message', - 'MulticastMessage', - 'Notification', - 'QuotaExceededError', - 'SenderIdMismatchError', - 'SendResponse', - 'ThirdPartyAuthError', - 'TopicManagementResponse', - 'UnregisteredError', - 'WebpushConfig', - 'WebpushFCMOptions', - 'WebpushNotification', - 'WebpushNotificationAction', - - 'send', - 'send_each', - 'send_each_async', - 'send_each_for_multicast', - 'send_each_for_multicast_async', - 'subscribe_to_topic', - 'unsubscribe_from_topic', -] - - -AndroidConfig = _messaging_utils.AndroidConfig -AndroidFCMOptions = _messaging_utils.AndroidFCMOptions -AndroidNotification = _messaging_utils.AndroidNotification -APNSConfig = _messaging_utils.APNSConfig -APNSFCMOptions = _messaging_utils.APNSFCMOptions -APNSPayload = _messaging_utils.APNSPayload -Aps = _messaging_utils.Aps -ApsAlert = _messaging_utils.ApsAlert -CriticalSound = _messaging_utils.CriticalSound -FCMOptions = _messaging_utils.FCMOptions -LightSettings = _messaging_utils.LightSettings -Message = _messaging_encoder.Message -MulticastMessage = _messaging_encoder.MulticastMessage -Notification = _messaging_utils.Notification -WebpushConfig = _messaging_utils.WebpushConfig -WebpushFCMOptions = _messaging_utils.WebpushFCMOptions -WebpushNotification = _messaging_utils.WebpushNotification -WebpushNotificationAction = _messaging_utils.WebpushNotificationAction - -QuotaExceededError = _messaging_utils.QuotaExceededError -SenderIdMismatchError = _messaging_utils.SenderIdMismatchError -ThirdPartyAuthError = _messaging_utils.ThirdPartyAuthError -UnregisteredError = _messaging_utils.UnregisteredError - - -def _get_messaging_service(app: Optional[App]) -> _MessagingService: - return _utils.get_app_service(app, _MESSAGING_ATTRIBUTE, _MessagingService) - -def send(message: Message, dry_run: bool = False, app: Optional[App] = None) -> str: - """Sends the given message via Firebase Cloud Messaging (FCM). - - If the ``dry_run`` mode is enabled, the message will not be actually delivered to the - recipients. Instead, FCM performs all the usual validations and emulates the send operation. - - Args: - message: An instance of ``messaging.Message``. - dry_run: A boolean indicating whether to run the operation in dry run mode (optional). - app: An App instance (optional). - - Returns: - string: A message ID string that uniquely identifies the sent message. - - Raises: - FirebaseError: If an error occurs while sending the message to the FCM service. - ValueError: If the input arguments are invalid. - """ - return _get_messaging_service(app).send(message, dry_run) - -def send_each( - messages: List[Message], - dry_run: bool = False, - app: Optional[App] = None - ) -> BatchResponse: - """Sends each message in the given list via Firebase Cloud Messaging. - - If the ``dry_run`` mode is enabled, the message will not be actually delivered to the - recipients. Instead, FCM performs all the usual validations and emulates the send operation. - - Args: - messages: A list of ``messaging.Message`` instances. - dry_run: A boolean indicating whether to run the operation in dry run mode (optional). - app: An App instance (optional). - - Returns: - BatchResponse: A ``messaging.BatchResponse`` instance. - - Raises: - FirebaseError: If an error occurs while sending the message to the FCM service. - ValueError: If the input arguments are invalid. - """ - return _get_messaging_service(app).send_each(messages, dry_run) - -async def send_each_async( - messages: List[Message], - dry_run: bool = False, - app: Optional[App] = None - ) -> BatchResponse: - """Sends each message in the given list asynchronously via Firebase Cloud Messaging. - - If the ``dry_run`` mode is enabled, the message will not be actually delivered to the - recipients. Instead, FCM performs all the usual validations and emulates the send operation. - - Args: - messages: A list of ``messaging.Message`` instances. - dry_run: A boolean indicating whether to run the operation in dry run mode (optional). - app: An App instance (optional). - - Returns: - BatchResponse: A ``messaging.BatchResponse`` instance. - - Raises: - FirebaseError: If an error occurs while sending the message to the FCM service. - ValueError: If the input arguments are invalid. - """ - return await _get_messaging_service(app).send_each_async(messages, dry_run) - -async def send_each_for_multicast_async( - multicast_message: MulticastMessage, - dry_run: bool = False, - app: Optional[App] = None - ) -> BatchResponse: - """Sends the given mutlicast message to each token asynchronously via Firebase Cloud Messaging - (FCM). - - If the ``dry_run`` mode is enabled, the message will not be actually delivered to the - recipients. Instead, FCM performs all the usual validations and emulates the send operation. - - Args: - multicast_message: An instance of ``messaging.MulticastMessage``. - dry_run: A boolean indicating whether to run the operation in dry run mode (optional). - app: An App instance (optional). - - Returns: - BatchResponse: A ``messaging.BatchResponse`` instance. - - Raises: - FirebaseError: If an error occurs while sending the message to the FCM service. - ValueError: If the input arguments are invalid. - """ - if not isinstance(multicast_message, MulticastMessage): - raise ValueError('Message must be an instance of messaging.MulticastMessage class.') - messages = [Message( - data=multicast_message.data, - notification=multicast_message.notification, - android=multicast_message.android, - webpush=multicast_message.webpush, - apns=multicast_message.apns, - fcm_options=multicast_message.fcm_options, - token=token - ) for token in multicast_message.tokens] - return await _get_messaging_service(app).send_each_async(messages, dry_run) - -def send_each_for_multicast(multicast_message, dry_run=False, app=None): - """Sends the given mutlicast message to each token via Firebase Cloud Messaging (FCM). - - If the ``dry_run`` mode is enabled, the message will not be actually delivered to the - recipients. Instead, FCM performs all the usual validations and emulates the send operation. - - Args: - multicast_message: An instance of ``messaging.MulticastMessage``. - dry_run: A boolean indicating whether to run the operation in dry run mode (optional). - app: An App instance (optional). - - Returns: - BatchResponse: A ``messaging.BatchResponse`` instance. - - Raises: - FirebaseError: If an error occurs while sending the message to the FCM service. - ValueError: If the input arguments are invalid. - """ - if not isinstance(multicast_message, MulticastMessage): - raise ValueError('Message must be an instance of messaging.MulticastMessage class.') - messages = [Message( - data=multicast_message.data, - notification=multicast_message.notification, - android=multicast_message.android, - webpush=multicast_message.webpush, - apns=multicast_message.apns, - fcm_options=multicast_message.fcm_options, - token=token - ) for token in multicast_message.tokens] - return _get_messaging_service(app).send_each(messages, dry_run) - -def subscribe_to_topic(tokens, topic, app=None): - """Subscribes a list of registration tokens to an FCM topic. - - Args: - tokens: A non-empty list of device registration tokens. List may not have more than 1000 - elements. - topic: Name of the topic to subscribe to. May contain the ``/topics/`` prefix. - app: An App instance (optional). - - Returns: - TopicManagementResponse: A ``TopicManagementResponse`` instance. - - Raises: - FirebaseError: If an error occurs while communicating with instance ID service. - ValueError: If the input arguments are invalid. - """ - return _get_messaging_service(app).make_topic_management_request( - tokens, topic, 'iid/v1:batchAdd') - -def unsubscribe_from_topic(tokens, topic, app=None): - """Unsubscribes a list of registration tokens from an FCM topic. - - Args: - tokens: A non-empty list of device registration tokens. List may not have more than 1000 - elements. - topic: Name of the topic to unsubscribe from. May contain the ``/topics/`` prefix. - app: An App instance (optional). - - Returns: - TopicManagementResponse: A ``TopicManagementResponse`` instance. - - Raises: - FirebaseError: If an error occurs while communicating with instance ID service. - ValueError: If the input arguments are invalid. - """ - return _get_messaging_service(app).make_topic_management_request( - tokens, topic, 'iid/v1:batchRemove') - - -class ErrorInfo: - """An error encountered when performing a topic management operation.""" - - def __init__(self, index, reason): - self._index = index - self._reason = reason - - @property - def index(self): - """Index of the registration token to which this error is related to.""" - return self._index - - @property - def reason(self): - """String describing the nature of the error.""" - return self._reason - - -class TopicManagementResponse: - """The response received from a topic management operation.""" - - def __init__(self, resp): - if not isinstance(resp, dict) or 'results' not in resp: - raise ValueError(f'Unexpected topic management response: {resp}.') - self._success_count = 0 - self._failure_count = 0 - self._errors = [] - for index, result in enumerate(resp['results']): - if 'error' in result: - self._failure_count += 1 - self._errors.append(ErrorInfo(index, result['error'])) - else: - self._success_count += 1 - - @property - def success_count(self): - """Number of tokens that were successfully subscribed or unsubscribed.""" - return self._success_count - - @property - def failure_count(self): - """Number of tokens that could not be subscribed or unsubscribed due to errors.""" - return self._failure_count - - @property - def errors(self): - """A list of ``messaging.ErrorInfo`` objects (possibly empty).""" - return self._errors - - -class BatchResponse: - """The response received from a batch request to the FCM API.""" - - def __init__(self, responses: List[SendResponse]) -> None: - self._responses = responses - self._success_count = sum(1 for resp in responses if resp.success) - - @property - def responses(self) -> List[SendResponse]: - """A list of ``messaging.SendResponse`` objects (possibly empty).""" - return self._responses - - @property - def success_count(self) -> int: - return self._success_count - - @property - def failure_count(self) -> int: - return len(self.responses) - self.success_count - - -class SendResponse: - """The response received from an individual batched request to the FCM API.""" - - def __init__(self, resp, exception): - self._exception = exception - self._message_id = None - if resp: - self._message_id = resp.get('name', None) - - @property - def message_id(self): - """A message ID string that uniquely identifies the message.""" - return self._message_id - - @property - def success(self): - """A boolean indicating if the request was successful.""" - return self._message_id is not None and not self._exception - - @property - def exception(self): - """A ``FirebaseError`` if an error occurs while sending the message to the FCM service.""" - return self._exception - -class _MessagingService: - """Service class that implements Firebase Cloud Messaging (FCM) functionality.""" - - FCM_URL = 'https://fcm.googleapis.com/v1/projects/{0}/messages:send' - FCM_BATCH_URL = 'https://fcm.googleapis.com/batch' - IID_URL = 'https://iid.googleapis.com' - IID_HEADERS = {'access_token_auth': 'true'} - JSON_ENCODER = _messaging_encoder.MessageEncoder() - - FCM_ERROR_TYPES = { - 'APNS_AUTH_ERROR': ThirdPartyAuthError, - 'QUOTA_EXCEEDED': QuotaExceededError, - 'SENDER_ID_MISMATCH': SenderIdMismatchError, - 'THIRD_PARTY_AUTH_ERROR': ThirdPartyAuthError, - 'UNREGISTERED': UnregisteredError, - } - - def __init__(self, app: App) -> None: - project_id = app.project_id - if not project_id: - raise ValueError( - 'Project ID is required to access Cloud Messaging service. Either set the ' - 'projectId option, or use service account credentials. Alternatively, set the ' - 'GOOGLE_CLOUD_PROJECT environment variable.') - self._fcm_url = _MessagingService.FCM_URL.format(project_id) - self._fcm_headers = { - 'X-GOOG-API-FORMAT-VERSION': '2', - 'X-FIREBASE-CLIENT': f'fire-admin-python/{firebase_admin.__version__}', - } - timeout = app.options.get('httpTimeout', _http_client.DEFAULT_TIMEOUT_SECONDS) - self._credential = app.credential.get_credential() - self._client = _http_client.JsonHttpClient(credential=self._credential, timeout=timeout) - self._async_client = _http_client.HttpxAsyncClient( - credential=self._credential, timeout=timeout) - - @classmethod - def encode_message(cls, message): - if not isinstance(message, Message): - raise ValueError('Message must be an instance of messaging.Message class.') - return cls.JSON_ENCODER.default(message) - - def send(self, message: Message, dry_run: bool = False) -> str: - """Sends the given message to FCM via the FCM v1 API.""" - data = self._message_data(message, dry_run) - try: - resp = self._client.body( - 'post', - url=self._fcm_url, - headers=self._fcm_headers, - json=data - ) - except requests.exceptions.RequestException as error: - raise self._handle_fcm_error(error) - return cast(str, resp['name']) - - def send_each(self, messages: List[Message], dry_run: bool = False) -> BatchResponse: - """Sends the given messages to FCM via the FCM v1 API.""" - if not isinstance(messages, list): - raise ValueError('messages must be a list of messaging.Message instances.') - if len(messages) > 500: - raise ValueError('messages must not contain more than 500 elements.') - - def send_data(data): - try: - resp = self._client.body( - 'post', - url=self._fcm_url, - headers=self._fcm_headers, - json=data) - except requests.exceptions.RequestException as exception: - return SendResponse(resp=None, exception=self._handle_fcm_error(exception)) - return SendResponse(resp, exception=None) - - message_data = [self._message_data(message, dry_run) for message in messages] - try: - with concurrent.futures.ThreadPoolExecutor(max_workers=len(message_data)) as executor: - responses = list(executor.map(send_data, message_data)) - return BatchResponse(responses) - except Exception as error: - raise exceptions.UnknownError( - message=f'Unknown error while making remote service calls: {error}', - cause=error) - - async def send_each_async(self, messages: List[Message], dry_run: bool = True) -> BatchResponse: - """Sends the given messages to FCM via the FCM v1 API.""" - if not isinstance(messages, list): - raise ValueError('messages must be a list of messaging.Message instances.') - if len(messages) > 500: - raise ValueError('messages must not contain more than 500 elements.') - - async def send_data(data): - try: - resp = await self._async_client.request( - 'post', - url=self._fcm_url, - headers=self._fcm_headers, - json=data) - except httpx.HTTPError as exception: - return SendResponse(resp=None, exception=self._handle_fcm_httpx_error(exception)) - # Catch errors caused by the requests library during authorization - except requests.exceptions.RequestException as exception: - return SendResponse(resp=None, exception=self._handle_fcm_error(exception)) - return SendResponse(resp.json(), exception=None) - - message_data = [self._message_data(message, dry_run) for message in messages] - try: - responses = await asyncio.gather(*[send_data(message) for message in message_data]) - return BatchResponse(responses) - except Exception as error: - raise exceptions.UnknownError( - message=f'Unknown error while making remote service calls: {error}', - cause=error) - - def make_topic_management_request(self, tokens, topic, operation): - """Invokes the IID service for topic management functionality.""" - if isinstance(tokens, str): - tokens = [tokens] - if not isinstance(tokens, list) or not tokens: - raise ValueError('Tokens must be a string or a non-empty list of strings.') - invalid_str = [t for t in tokens if not isinstance(t, str) or not t] - if invalid_str: - raise ValueError('Tokens must be non-empty strings.') - - if not isinstance(topic, str) or not topic: - raise ValueError('Topic must be a non-empty string.') - if not topic.startswith('/topics/'): - topic = f'/topics/{topic}' - data = { - 'to': topic, - 'registration_tokens': tokens, - } - url = f'{_MessagingService.IID_URL}/{operation}' - try: - resp = self._client.body( - 'post', - url=url, - json=data, - headers=_MessagingService.IID_HEADERS - ) - except requests.exceptions.RequestException as error: - raise self._handle_iid_error(error) - return TopicManagementResponse(resp) - - def _message_data(self, message, dry_run): - data = {'message': _MessagingService.encode_message(message)} - if dry_run: - data['validate_only'] = True - return data - - def _postproc(self, _, body): - """Handle response from batch API request.""" - # This only gets called for 2xx responses. - return json.loads(body.decode()) - - def _handle_fcm_error(self, error): - """Handles errors received from the FCM API.""" - return _utils.handle_platform_error_from_requests( - error, _MessagingService._build_fcm_error_requests) - - def _handle_fcm_httpx_error(self, error: httpx.HTTPError) -> exceptions.FirebaseError: - """Handles errors received from the FCM API.""" - return _utils.handle_platform_error_from_httpx( - error, _MessagingService._build_fcm_error_httpx) - - def _handle_iid_error(self, error): - """Handles errors received from the Instance ID API.""" - if error.response is None: - raise _utils.handle_requests_error(error) - - data = {} - try: - parsed_body = error.response.json() - if isinstance(parsed_body, dict): - data = parsed_body - except ValueError: - pass - - # IID error response format: {"error": "ErrorCode"} - code = data.get('error') - msg = None - if code: - msg = f'Error while calling the IID service: {code}' - else: - msg = ( - f'Unexpected HTTP response with status: {error.response.status_code}; body: ' - f'{error.response.content.decode()}' - ) - - return _utils.handle_requests_error(error, msg) - - def close(self) -> None: - asyncio.run(self._async_client.aclose()) - - @classmethod - def _build_fcm_error_requests(cls, error, message, error_dict): - """Parses an error response from the FCM API and creates a FCM-specific exception if - appropriate.""" - exc_type = cls._build_fcm_error(error_dict) - # pylint: disable=not-callable - return exc_type(message, cause=error, http_response=error.response) if exc_type else None - - @classmethod - def _build_fcm_error_httpx( - cls, - error: httpx.HTTPError, - message: str, - error_dict: Optional[Dict[str, Any]] - ) -> Optional[exceptions.FirebaseError]: - """Parses a httpx error response from the FCM API and creates a FCM-specific exception if - appropriate.""" - exc_type = cls._build_fcm_error(error_dict) - if isinstance(error, httpx.HTTPStatusError): - # pylint: disable=not-callable - return exc_type( - message, cause=error, http_response=error.response) if exc_type else None - # pylint: disable=not-callable - return exc_type(message, cause=error) if exc_type else None - - @classmethod - def _build_fcm_error( - cls, - error_dict: Optional[Dict[str, Any]] - ) -> Optional[Callable[..., exceptions.FirebaseError]]: - """Parses an error response to determine the appropriate FCM-specific error type.""" - if not error_dict: - return None - fcm_code = None - for detail in error_dict.get('details', []): - if detail.get('@type') == 'type.googleapis.com/google.firebase.fcm.v1.FcmError': - fcm_code = detail.get('errorCode') - break - return _MessagingService.FCM_ERROR_TYPES.get(fcm_code) if fcm_code else None diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/ml.py b/notification-service/venv/Lib/site-packages/firebase_admin/ml.py deleted file mode 100644 index 3a77dd0..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/ml.py +++ /dev/null @@ -1,939 +0,0 @@ -# Copyright 2019 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase ML module. - -This module contains functions for creating, updating, getting, listing, -deleting, publishing and unpublishing Firebase ML models. -""" - - -import datetime -import re -import time -import os -from urllib import parse - -import requests - -import firebase_admin -from firebase_admin import _http_client -from firebase_admin import _utils -from firebase_admin import exceptions - -# pylint: disable=import-error,no-member -try: - from firebase_admin import storage - _GCS_ENABLED = True -except ImportError: - _GCS_ENABLED = False - -# pylint: disable=import-error,no-member -try: - import tensorflow as tf - _TF_ENABLED = True -except ImportError: - _TF_ENABLED = False - -_ML_ATTRIBUTE = '_ml' -_MAX_PAGE_SIZE = 100 -_MODEL_ID_PATTERN = re.compile(r'^[A-Za-z0-9_-]{1,60}$') -_DISPLAY_NAME_PATTERN = re.compile(r'^[A-Za-z0-9_-]{1,32}$') -_TAG_PATTERN = re.compile(r'^[A-Za-z0-9_-]{1,32}$') -_GCS_TFLITE_URI_PATTERN = re.compile( - r'^gs://(?P[a-z0-9_.-]{3,63})/(?P.+)$') -_RESOURCE_NAME_PATTERN = re.compile( - r'^projects/(?P[a-z0-9-]{6,30})/models/(?P[A-Za-z0-9_-]{1,60})$') -_OPERATION_NAME_PATTERN = re.compile( - r'^projects/(?P[a-z0-9-]{6,30})/operations/[^/]+$') - - -def _get_ml_service(app): - """ Returns an _MLService instance for an App. - - Args: - app: A Firebase App instance (or None to use the default App). - - Returns: - _MLService: An _MLService for the specified App instance. - - Raises: - ValueError: If the app argument is invalid. - """ - return _utils.get_app_service(app, _ML_ATTRIBUTE, _MLService) - - -def create_model(model, app=None): - """Creates a model in the current Firebase project. - - Args: - model: An ml.Model to create. - app: A Firebase app instance (or None to use the default app). - - Returns: - Model: The model that was created in Firebase ML. - """ - ml_service = _get_ml_service(app) - return Model.from_dict(ml_service.create_model(model), app=app) - - -def update_model(model, app=None): - """Updates a model's metadata or model file. - - Args: - model: The ml.Model to update. - app: A Firebase app instance (or None to use the default app). - - Returns: - Model: The updated model. - """ - ml_service = _get_ml_service(app) - return Model.from_dict(ml_service.update_model(model), app=app) - - -def publish_model(model_id, app=None): - """Publishes a Firebase ML model. - - A published model can be downloaded to client apps. - - Args: - model_id: The id of the model to publish. - app: A Firebase app instance (or None to use the default app). - - Returns: - Model: The published model. - """ - ml_service = _get_ml_service(app) - return Model.from_dict(ml_service.set_published(model_id, publish=True), app=app) - - -def unpublish_model(model_id, app=None): - """Unpublishes a Firebase ML model. - - Args: - model_id: The id of the model to unpublish. - app: A Firebase app instance (or None to use the default app). - - Returns: - Model: The unpublished model. - """ - ml_service = _get_ml_service(app) - return Model.from_dict(ml_service.set_published(model_id, publish=False), app=app) - - -def get_model(model_id, app=None): - """Gets the model specified by the given ID. - - Args: - model_id: The id of the model to get. - app: A Firebase app instance (or None to use the default app). - - Returns: - Model: The requested model. - """ - ml_service = _get_ml_service(app) - return Model.from_dict(ml_service.get_model(model_id), app=app) - - -def list_models(list_filter=None, page_size=None, page_token=None, app=None): - """Lists the current project's models. - - Args: - list_filter: a list filter string such as ``tags:'tag_1'``. None will return all models. - page_size: A number between 1 and 100 inclusive that specifies the maximum - number of models to return per page. None for default. - page_token: A next page token returned from a previous page of results. None - for first page of results. - app: A Firebase app instance (or None to use the default app). - - Returns: - ListModelsPage: A (filtered) list of models. - """ - ml_service = _get_ml_service(app) - return ListModelsPage( - ml_service.list_models, list_filter, page_size, page_token, app=app) - - -def delete_model(model_id, app=None): - """Deletes a model from the current project. - - Args: - model_id: The id of the model you wish to delete. - app: A Firebase app instance (or None to use the default app). - """ - ml_service = _get_ml_service(app) - ml_service.delete_model(model_id) - - -class Model: - """A Firebase ML Model object. - - Args: - display_name: The display name of your model - used to identify your model in code. - tags: Optional list of strings associated with your model. Can be used in list queries. - model_format: A subclass of ModelFormat. (e.g. TFLiteFormat) Specifies the model details. - """ - def __init__(self, display_name=None, tags=None, model_format=None): - self._app = None # Only needed for wait_for_unlo - self._data = {} - self._model_format = None - - if display_name is not None: - self.display_name = display_name - if tags is not None: - self.tags = tags - if model_format is not None: - self.model_format = model_format - - @classmethod - def from_dict(cls, data, app=None): - """Create an instance of the object from a dict.""" - data_copy = dict(data) - tflite_format = None - tflite_format_data = data_copy.pop('tfliteModel', None) - data_copy.pop('@type', None) # Returned by Operations. (Not needed) - if tflite_format_data: - tflite_format = TFLiteFormat.from_dict(tflite_format_data) - model = Model(model_format=tflite_format) - model._data = data_copy # pylint: disable=protected-access - model._app = app # pylint: disable=protected-access - return model - - def _update_from_dict(self, data): - copy = Model.from_dict(data) - self.model_format = copy.model_format - self._data = copy._data # pylint: disable=protected-access - - def __eq__(self, other): - if isinstance(other, self.__class__): - # pylint: disable=protected-access - return self._data == other._data and self._model_format == other._model_format - return False - - def __ne__(self, other): - return not self.__eq__(other) - - @property - def model_id(self): - """The model's ID, unique to the project.""" - if not self._data.get('name'): - return None - _, model_id = _validate_and_parse_name(self._data.get('name')) - return model_id - - @property - def display_name(self): - """The model's display name, used to refer to the model in code and in - the Firebase console.""" - return self._data.get('displayName') - - @display_name.setter - def display_name(self, display_name): - self._data['displayName'] = _validate_display_name(display_name) - return self - - @staticmethod - def _convert_to_millis(date_string): - if not date_string: - return None - format_str = '%Y-%m-%dT%H:%M:%S.%fZ' - epoch = datetime.datetime.utcfromtimestamp(0) - datetime_object = datetime.datetime.strptime(date_string, format_str) - millis = int((datetime_object - epoch).total_seconds() * 1000) - return millis - - @property - def create_time(self): - """The time the model was created.""" - return Model._convert_to_millis(self._data.get('createTime', None)) - - @property - def update_time(self): - """The time the model was last updated.""" - return Model._convert_to_millis(self._data.get('updateTime', None)) - - @property - def validation_error(self): - """Validation error message.""" - return self._data.get('state', {}).get('validationError', {}).get('message') - - @property - def published(self): - """True if the model is published and available for clients to - download.""" - return bool(self._data.get('state', {}).get('published')) - - @property - def etag(self): - """The entity tag (ETag) of the model resource.""" - return self._data.get('etag') - - @property - def model_hash(self): - """SHA256 hash of the model binary.""" - return self._data.get('modelHash') - - @property - def tags(self): - """Tag strings, used for filtering query results.""" - return self._data.get('tags') - - @tags.setter - def tags(self, tags): - self._data['tags'] = _validate_tags(tags) - return self - - @property - def locked(self): - """True if the Model object is locked by an active operation.""" - return bool(self._data.get('activeOperations') and - len(self._data.get('activeOperations')) > 0) - - def wait_for_unlocked(self, max_time_seconds=None): - """Waits for the model to be unlocked. (All active operations complete) - - Args: - max_time_seconds: The maximum number of seconds to wait for the model to unlock. - (None for no limit) - - Raises: - exceptions.DeadlineExceeded: If max_time_seconds passed and the model is still locked. - """ - if not self.locked: - return - ml_service = _get_ml_service(self._app) - op_name = self._data.get('activeOperations')[0].get('name') - model_dict = ml_service.handle_operation( - ml_service.get_operation(op_name), - wait_for_operation=True, - max_time_seconds=max_time_seconds) - self._update_from_dict(model_dict) - - @property - def model_format(self): - """The model's ``ModelFormat`` object, which represents the model's - format and storage location.""" - return self._model_format - - @model_format.setter - def model_format(self, model_format): - if model_format is not None: - _validate_model_format(model_format) - self._model_format = model_format #Can be None - return self - - def as_dict(self, for_upload=False): - """Returns a serializable representation of the object.""" - copy = dict(self._data) - if self._model_format: - copy.update(self._model_format.as_dict(for_upload=for_upload)) - return copy - - -class ModelFormat: - """Abstract base class representing a Model Format such as TFLite.""" - def as_dict(self, for_upload=False): - """Returns a serializable representation of the object.""" - raise NotImplementedError - - -class TFLiteFormat(ModelFormat): - """Model format representing a TFLite model. - - Args: - model_source: A TFLiteModelSource sub class. Specifies the details of the model source. - """ - def __init__(self, model_source=None): - self._data = {} - self._model_source = None - - if model_source is not None: - self.model_source = model_source - - @classmethod - def from_dict(cls, data): - """Create an instance of the object from a dict.""" - data_copy = dict(data) - tflite_format = TFLiteFormat(model_source=cls._init_model_source(data_copy)) - tflite_format._data = data_copy # pylint: disable=protected-access - return tflite_format - - def __eq__(self, other): - if isinstance(other, self.__class__): - # pylint: disable=protected-access - return self._data == other._data and self._model_source == other._model_source - return False - - def __ne__(self, other): - return not self.__eq__(other) - - @staticmethod - def _init_model_source(data): - """Initialize the ML model source.""" - gcs_tflite_uri = data.pop('gcsTfliteUri', None) - if gcs_tflite_uri: - return TFLiteGCSModelSource(gcs_tflite_uri=gcs_tflite_uri) - return None - - @property - def model_source(self): - """The TF Lite model's location.""" - return self._model_source - - @model_source.setter - def model_source(self, model_source): - if model_source is not None: - if not isinstance(model_source, TFLiteModelSource): - raise TypeError('Model source must be a TFLiteModelSource object.') - self._model_source = model_source # Can be None - - @property - def size_bytes(self): - """The size in bytes of the TF Lite model.""" - return self._data.get('sizeBytes') - - def as_dict(self, for_upload=False): - """Returns a serializable representation of the object.""" - copy = dict(self._data) - if self._model_source: - copy.update(self._model_source.as_dict(for_upload=for_upload)) - return {'tfliteModel': copy} - - -class TFLiteModelSource: - """Abstract base class representing a model source for TFLite format models.""" - def as_dict(self, for_upload=False): - """Returns a serializable representation of the object.""" - raise NotImplementedError - - -class _CloudStorageClient: - """Cloud Storage helper class""" - - GCS_URI = 'gs://{0}/{1}' - BLOB_NAME = 'Firebase/ML/Models/{0}' - - @staticmethod - def _assert_gcs_enabled(): - if not _GCS_ENABLED: - raise ImportError('Failed to import the Cloud Storage library for Python. Make sure ' - 'to install the "google-cloud-storage" module.') - - @staticmethod - def _parse_gcs_tflite_uri(uri): - # GCS Bucket naming rules are complex. The regex is not comprehensive. - # See https://cloud.google.com/storage/docs/naming for full details. - matcher = _GCS_TFLITE_URI_PATTERN.match(uri) - if not matcher: - raise ValueError('GCS TFLite URI format is invalid.') - return matcher.group('bucket_name'), matcher.group('blob_name') - - @staticmethod - def upload(bucket_name, model_file_name, app): - """Upload a model file to the specified Storage bucket.""" - _CloudStorageClient._assert_gcs_enabled() - - file_name = os.path.basename(model_file_name) - bucket = storage.bucket(bucket_name, app=app) - blob_name = _CloudStorageClient.BLOB_NAME.format(file_name) - blob = bucket.blob(blob_name) - blob.upload_from_filename(model_file_name) - return _CloudStorageClient.GCS_URI.format(bucket.name, blob_name) - - @staticmethod - def sign_uri(gcs_tflite_uri, app): - """Makes the gcs_tflite_uri readable for GET for 10 minutes via signed_uri.""" - _CloudStorageClient._assert_gcs_enabled() - bucket_name, blob_name = _CloudStorageClient._parse_gcs_tflite_uri(gcs_tflite_uri) - bucket = storage.bucket(bucket_name, app=app) - blob = bucket.blob(blob_name) - return blob.generate_signed_url( - version='v4', - expiration=datetime.timedelta(minutes=10), - method='GET' - ) - - -class TFLiteGCSModelSource(TFLiteModelSource): - """TFLite model source representing a tflite model file stored in GCS.""" - - _STORAGE_CLIENT = _CloudStorageClient() - - def __init__(self, gcs_tflite_uri, app=None): - self._app = app - self._gcs_tflite_uri = _validate_gcs_tflite_uri(gcs_tflite_uri) - - def __eq__(self, other): - if isinstance(other, self.__class__): - return self._gcs_tflite_uri == other._gcs_tflite_uri # pylint: disable=protected-access - return False - - def __ne__(self, other): - return not self.__eq__(other) - - @classmethod - def from_tflite_model_file(cls, model_file_name, bucket_name=None, app=None): - """Uploads the model file to an existing Google Cloud Storage bucket. - - Args: - model_file_name: The name of the model file. - bucket_name: The name of an existing bucket. None to use the default bucket configured - in the app. - app: A Firebase app instance (or None to use the default app). - - Returns: - TFLiteGCSModelSource: The source created from the model_file - - Raises: - ImportError: If the Cloud Storage Library has not been installed. - """ - gcs_uri = TFLiteGCSModelSource._STORAGE_CLIENT.upload(bucket_name, model_file_name, app) - return TFLiteGCSModelSource(gcs_tflite_uri=gcs_uri, app=app) - - @staticmethod - def _assert_tf_enabled(): - if not _TF_ENABLED: - raise ImportError('Failed to import the tensorflow library for Python. Make sure ' - 'to install the tensorflow module.') - if not tf.version.VERSION.startswith('1.') and not tf.version.VERSION.startswith('2.'): - raise ImportError( - f'Expected tensorflow version 1.x or 2.x, but found {tf.version.VERSION}') - - @staticmethod - def _tf_convert_from_saved_model(saved_model_dir): - # Same for both v1.x and v2.x - converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) - return converter.convert() - - @staticmethod - def _tf_convert_from_keras_model(keras_model): - """Converts the given Keras model into a TF Lite model.""" - # Version 1.x conversion function takes a model file. Version 2.x takes the model itself. - if tf.version.VERSION.startswith('1.'): - keras_file = 'firebase_keras_model.h5' - tf.keras.models.save_model(keras_model, keras_file) - converter = tf.lite.TFLiteConverter.from_keras_model_file(keras_file) - else: - converter = tf.lite.TFLiteConverter.from_keras_model(keras_model) - - return converter.convert() - - @classmethod - def from_saved_model(cls, saved_model_dir, model_file_name='firebase_ml_model.tflite', - bucket_name=None, app=None): - """Creates a Tensor Flow Lite model from the saved model, and uploads the model to GCS. - - Args: - saved_model_dir: The saved model directory. - model_file_name: The name that the tflite model will be saved as in Cloud Storage. - bucket_name: The name of an existing bucket. None to use the default bucket configured - in the app. - app: Optional. A Firebase app instance (or None to use the default app) - - Returns: - TFLiteGCSModelSource: The source created from the saved_model_dir - - Raises: - ImportError: If the Tensor Flow or Cloud Storage Libraries have not been installed. - """ - TFLiteGCSModelSource._assert_tf_enabled() - tflite_model = TFLiteGCSModelSource._tf_convert_from_saved_model(saved_model_dir) - with open(model_file_name, 'wb') as model_file: - model_file.write(tflite_model) - return TFLiteGCSModelSource.from_tflite_model_file(model_file_name, bucket_name, app) - - @classmethod - def from_keras_model(cls, keras_model, model_file_name='firebase_ml_model.tflite', - bucket_name=None, app=None): - """Creates a Tensor Flow Lite model from the keras model, and uploads the model to GCS. - - Args: - keras_model: A tf.keras model. - model_file_name: The name that the tflite model will be saved as in Cloud Storage. - bucket_name: The name of an existing bucket. None to use the default bucket configured - in the app. - app: Optional. A Firebase app instance (or None to use the default app) - - Returns: - TFLiteGCSModelSource: The source created from the keras_model - - Raises: - ImportError: If the Tensor Flow or Cloud Storage Libraries have not been installed. - """ - TFLiteGCSModelSource._assert_tf_enabled() - tflite_model = TFLiteGCSModelSource._tf_convert_from_keras_model(keras_model) - with open(model_file_name, 'wb') as model_file: - model_file.write(tflite_model) - return TFLiteGCSModelSource.from_tflite_model_file(model_file_name, bucket_name, app) - - @property - def gcs_tflite_uri(self): - """URI of the model file in Cloud Storage.""" - return self._gcs_tflite_uri - - @gcs_tflite_uri.setter - def gcs_tflite_uri(self, gcs_tflite_uri): - self._gcs_tflite_uri = _validate_gcs_tflite_uri(gcs_tflite_uri) - - def _get_signed_gcs_tflite_uri(self): - """Signs the GCS uri, so the model file can be uploaded to Firebase ML and verified.""" - return TFLiteGCSModelSource._STORAGE_CLIENT.sign_uri(self._gcs_tflite_uri, self._app) - - def as_dict(self, for_upload=False): - """Returns a serializable representation of the object.""" - if for_upload: - return {'gcsTfliteUri': self._get_signed_gcs_tflite_uri()} - - return {'gcsTfliteUri': self._gcs_tflite_uri} - -class ListModelsPage: - """Represents a page of models in a Firebase project. - - Provides methods for traversing the models included in this page, as well as - retrieving subsequent pages of models. The iterator returned by - ``iterate_all()`` can be used to iterate through all the models in the - Firebase project starting from this page. - """ - def __init__(self, list_models_func, list_filter, page_size, page_token, app): - self._list_models_func = list_models_func - self._list_filter = list_filter - self._page_size = page_size - self._page_token = page_token - self._app = app - self._list_response = list_models_func(list_filter, page_size, page_token) - - @property - def models(self): - """A list of Models from this page.""" - return [ - Model.from_dict(model, app=self._app) for model in self._list_response.get('models', []) - ] - - @property - def list_filter(self): - """The filter string used to filter the models.""" - return self._list_filter - - @property - def next_page_token(self): - """Token identifying the next page of results.""" - return self._list_response.get('nextPageToken', '') - - @property - def has_next_page(self): - """True if more pages are available.""" - return bool(self.next_page_token) - - def get_next_page(self): - """Retrieves the next page of models if available. - - Returns: - ListModelsPage: Next page of models, or None if this is the last page. - """ - if self.has_next_page: - return ListModelsPage( - self._list_models_func, - self._list_filter, - self._page_size, - self.next_page_token, - self._app) - return None - - def iterate_all(self): - """Retrieves an iterator for Models. - - Returned iterator will iterate through all the models in the Firebase - project starting from this page. The iterator will never buffer more than - one page of models in memory at a time. - - Returns: - iterator: An iterator of Model instances. - """ - return _ModelIterator(self) - - -class _ModelIterator: - """An iterator that allows iterating over models, one at a time. - - This implementation loads a page of models into memory, and iterates on them. - When the whole page has been traversed, it loads another page. This class - never keeps more than one page of entries in memory. - """ - def __init__(self, current_page): - if not isinstance(current_page, ListModelsPage): - raise TypeError('Current page must be a ListModelsPage') - self._current_page = current_page - self._index = 0 - - def __next__(self): - if self._index == len(self._current_page.models): - if self._current_page.has_next_page: - self._current_page = self._current_page.get_next_page() - self._index = 0 - if self._index < len(self._current_page.models): - result = self._current_page.models[self._index] - self._index += 1 - return result - raise StopIteration - - def __iter__(self): - return self - - -def _validate_and_parse_name(name): - # The resource name is added automatically from API call responses. - # The only way it could be invalid is if someone tries to - # create a model from a dictionary manually and does it incorrectly. - matcher = _RESOURCE_NAME_PATTERN.match(name) - if not matcher: - raise ValueError('Model resource name format is invalid.') - return matcher.group('project_id'), matcher.group('model_id') - - -def _validate_model(model, update_mask=None): - if not isinstance(model, Model): - raise TypeError('Model must be an ml.Model.') - if update_mask is None and not model.display_name: - raise ValueError('Model must have a display name.') - - -def _validate_model_id(model_id): - if not _MODEL_ID_PATTERN.match(model_id): - raise ValueError('Model ID format is invalid.') - - -def _validate_operation_name(op_name): - if not _OPERATION_NAME_PATTERN.match(op_name): - raise ValueError('Operation name format is invalid.') - return op_name - - -def _validate_display_name(display_name): - if not _DISPLAY_NAME_PATTERN.match(display_name): - raise ValueError('Display name format is invalid.') - return display_name - - -def _validate_tags(tags): - if not isinstance(tags, list) or not \ - all(isinstance(tag, str) for tag in tags): - raise TypeError('Tags must be a list of strings.') - if not all(_TAG_PATTERN.match(tag) for tag in tags): - raise ValueError('Tag format is invalid.') - return tags - - -def _validate_gcs_tflite_uri(uri): - # GCS Bucket naming rules are complex. The regex is not comprehensive. - # See https://cloud.google.com/storage/docs/naming for full details. - if not _GCS_TFLITE_URI_PATTERN.match(uri): - raise ValueError('GCS TFLite URI format is invalid.') - return uri - - -def _validate_model_format(model_format): - if not isinstance(model_format, ModelFormat): - raise TypeError('Model format must be a ModelFormat object.') - return model_format - - -def _validate_list_filter(list_filter): - if list_filter is not None: - if not isinstance(list_filter, str): - raise TypeError('List filter must be a string or None.') - - -def _validate_page_size(page_size): - if page_size is not None: - if type(page_size) is not int: # pylint: disable=unidiomatic-typecheck - # Specifically type() to disallow boolean which is a subtype of int - raise TypeError('Page size must be a number or None.') - if page_size < 1 or page_size > _MAX_PAGE_SIZE: - raise ValueError( - f'Page size must be a positive integer between 1 and {_MAX_PAGE_SIZE}') - - -def _validate_page_token(page_token): - if page_token is not None: - if not isinstance(page_token, str): - raise TypeError('Page token must be a string or None.') - - -class _MLService: - """Firebase ML service.""" - - PROJECT_URL = 'https://firebaseml.googleapis.com/v1beta2/projects/{0}/' - OPERATION_URL = 'https://firebaseml.googleapis.com/v1beta2/' - POLL_EXPONENTIAL_BACKOFF_FACTOR = 1.5 - POLL_BASE_WAIT_TIME_SECONDS = 3 - - def __init__(self, app): - self._project_id = app.project_id - if not self._project_id: - raise ValueError( - 'Project ID is required to access ML service. Either set the ' - 'projectId option, or use service account credentials.') - self._project_url = _MLService.PROJECT_URL.format(self._project_id) - ml_headers = { - 'X-FIREBASE-CLIENT': f'fire-admin-python/{firebase_admin.__version__}', - } - self._client = _http_client.JsonHttpClient( - credential=app.credential.get_credential(), - headers=ml_headers, - base_url=self._project_url) - self._operation_client = _http_client.JsonHttpClient( - credential=app.credential.get_credential(), - headers=ml_headers, - base_url=_MLService.OPERATION_URL) - - def get_operation(self, op_name): - _validate_operation_name(op_name) - try: - return self._operation_client.body('get', url=op_name) - except requests.exceptions.RequestException as error: - raise _utils.handle_platform_error_from_requests(error) - - def _exponential_backoff(self, current_attempt, stop_time): - """Sleeps for the appropriate amount of time. Or throws deadline exceeded.""" - delay_factor = pow(_MLService.POLL_EXPONENTIAL_BACKOFF_FACTOR, current_attempt) - wait_time_seconds = delay_factor * _MLService.POLL_BASE_WAIT_TIME_SECONDS - - if stop_time is not None: - max_seconds_left = (stop_time - datetime.datetime.now()).total_seconds() - if max_seconds_left < 1: # allow a bit of time for rpc - raise exceptions.DeadlineExceededError('Polling max time exceeded.') - wait_time_seconds = min(wait_time_seconds, max_seconds_left - 1) - time.sleep(wait_time_seconds) - - def handle_operation(self, operation, wait_for_operation=False, max_time_seconds=None): - """Handles long running operations. - - Args: - operation: The operation to handle. - wait_for_operation: Should we allow polling for the operation to complete. - If no polling is requested, a locked model will be returned instead. - max_time_seconds: The maximum seconds to try polling for operation complete. - (None for no limit) - - Returns: - dict: A dictionary of the returned model properties. - - Raises: - TypeError: if the operation is not a dictionary. - ValueError: If the operation is malformed. - UnknownError: If the server responds with an unexpected response. - err: If the operation exceeds polling attempts or stop_time - """ - if not isinstance(operation, dict): - raise TypeError('Operation must be a dictionary.') - - if operation.get('done'): - # Operations which are immediately done don't have an operation name - if operation.get('response'): - return operation.get('response') - if operation.get('error'): - raise _utils.handle_operation_error(operation.get('error')) - raise exceptions.UnknownError(message='Internal Error: Malformed Operation.') - - op_name = _validate_operation_name(operation.get('name')) - metadata = operation.get('metadata', {}) - metadata_type = metadata.get('@type', '') - if not metadata_type.endswith('ModelOperationMetadata'): - raise TypeError('Unknown type of operation metadata.') - _, model_id = _validate_and_parse_name(metadata.get('name')) - current_attempt = 0 - start_time = datetime.datetime.now() - stop_time = (None if max_time_seconds is None else - start_time + datetime.timedelta(seconds=max_time_seconds)) - while wait_for_operation and not operation.get('done'): - # We just got this operation. Wait before getting another - # so we don't exceed the GetOperation maximum request rate. - self._exponential_backoff(current_attempt, stop_time) - operation = self.get_operation(op_name) - current_attempt += 1 - - if operation.get('done'): - if operation.get('response'): - return operation.get('response') - if operation.get('error'): - raise _utils.handle_operation_error(operation.get('error')) - - # If the operation is not complete or timed out, return a (locked) model instead - return get_model(model_id).as_dict() - - - def create_model(self, model): - _validate_model(model) - try: - return self.handle_operation( - self._client.body('post', url='models', json=model.as_dict(for_upload=True))) - except requests.exceptions.RequestException as error: - raise _utils.handle_platform_error_from_requests(error) - - def update_model(self, model, update_mask=None): - _validate_model(model, update_mask) - path = f'models/{model.model_id}' - if update_mask is not None: - path = path + f'?updateMask={update_mask}' - try: - return self.handle_operation( - self._client.body('patch', url=path, json=model.as_dict(for_upload=True))) - except requests.exceptions.RequestException as error: - raise _utils.handle_platform_error_from_requests(error) - - def set_published(self, model_id, publish): - _validate_model_id(model_id) - model_name = f'projects/{self._project_id}/models/{model_id}' - model = Model.from_dict({ - 'name': model_name, - 'state': { - 'published': publish - } - }) - return self.update_model(model, update_mask='state.published') - - def get_model(self, model_id): - _validate_model_id(model_id) - try: - return self._client.body('get', url=f'models/{model_id}') - except requests.exceptions.RequestException as error: - raise _utils.handle_platform_error_from_requests(error) - - def list_models(self, list_filter, page_size, page_token): - """ lists Firebase ML models.""" - _validate_list_filter(list_filter) - _validate_page_size(page_size) - _validate_page_token(page_token) - params = {} - if list_filter: - params['filter'] = list_filter - if page_size: - params['page_size'] = page_size - if page_token: - params['page_token'] = page_token - path = 'models' - if params: - param_str = parse.urlencode(sorted(params.items()), True) - path = path + '?' + param_str - try: - return self._client.body('get', url=path) - except requests.exceptions.RequestException as error: - raise _utils.handle_platform_error_from_requests(error) - - def delete_model(self, model_id): - _validate_model_id(model_id) - try: - self._client.body('delete', url=f'models/{model_id}') - except requests.exceptions.RequestException as error: - raise _utils.handle_platform_error_from_requests(error) diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/phone_number_verification.py b/notification-service/venv/Lib/site-packages/firebase_admin/phone_number_verification.py deleted file mode 100644 index ea8f0cd..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/phone_number_verification.py +++ /dev/null @@ -1,250 +0,0 @@ -# Copyright 2026 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase Phone Number Verification module. - -This module contains functions for verifying JWTs related to the Firebase -Phone Number Verification service. -""" -from __future__ import annotations -from typing import Any, Dict, Optional - -import jwt -from jwt import ( - PyJWKClient, InvalidSignatureError, - PyJWKClientError, InvalidAudienceError, InvalidIssuerError, ExpiredSignatureError -) - -from firebase_admin import App, _utils, exceptions - -_FPNV_ATTRIBUTE = '_phone_number_verification' -_FPNV_JWKS_URL = 'https://fpnv.googleapis.com/v1beta/jwks' -_FPNV_ISSUER = 'https://fpnv.googleapis.com/projects/' -_ALGORITHM_ES256 = 'ES256' - - -def _get_fpnv_service(app): - return _utils.get_app_service(app, _FPNV_ATTRIBUTE, _FpnvService) - -def verify_token(token: str, app: Optional[App] = None) -> PhoneNumberVerificationToken: - """Verifies a Firebase Phone Number Verification token. - - Args: - token: A string containing the Firebase Phone Number Verification JWT. - app: An App instance (optional). - - Returns: - PhoneNumberVerificationToken: The verified token claims. - - Raises: - ValueError: If the token is not a string or is empty. - InvalidTokenError: If the token is invalid or malformed. - ExpiredTokenError: If the token has expired. - """ - return _get_fpnv_service(app).verify_token(token) - - -class PhoneNumberVerificationToken(dict): - """Represents a verified Firebase Phone Number Verification token. - - This class behaves like a dictionary, allowing access to the decoded claims. - It also provides convenience properties for common claims. - """ - - def __init__(self, claims): - super().__init__(claims) - self['phone_number'] = claims.get('sub') - - @property - def phone_number(self) -> str: - """Returns the phone number of the user. - This corresponds to the 'sub' claim in the JWT. - """ - return self.get('sub') - - @property - def issuer(self) -> str: - """Returns the issuer identifier for the issuer of the response.""" - return self.get('iss') - - @property - def audience(self) -> str: - """Returns the audience for which this token is intended.""" - return self.get('aud') - - @property - def exp(self) -> int: - """Returns the expiration time since the Unix epoch.""" - return self.get('exp') - - @property - def iat(self) -> int: - """Returns the issued-at time since the Unix epoch.""" - return self.get('iat') - - @property - def sub(self) -> str: - """Returns the sub (subject) of the token, which is the phone number.""" - return self.get('sub') - - @property - def claims(self): - """Returns the entire map of claims.""" - return self - - -class _FpnvService: - """Service class that implements Firebase Phone Number Verification functionality.""" - _project_id = None - - def __init__(self, app): - self._project_id = app.project_id - if not self._project_id: - raise ValueError( - 'Project ID is required for Firebase Phone Number Verification. Please ensure the ' - 'app is initialized with a credential that contains a project ID.' - ) - - self._verifier = _FpnvTokenVerifier(self._project_id) - - def verify_token(self, token) -> PhoneNumberVerificationToken: - """Verifies a Firebase Phone Number Verification token. - - Verifies the signature, expiration, and claims of the token. - - Args: - token: A string containing the Firebase Phone Number Verification JWT. - - Returns: - PhoneNumberVerificationToken: The verified token claims. - - Raises: - ValueError: If the token is not a string or is empty. - InvalidTokenError: If the token is invalid or malformed. - ExpiredTokenError: If the token has expired. - """ - return PhoneNumberVerificationToken(self._verifier.verify(token)) - - -class _FpnvTokenVerifier: - """Internal class for verifying Firebase Phone Number Verification JWTs signed with ES256.""" - _jwks_client = None - _project_id = None - - def __init__(self, project_id): - self._project_id = project_id - self._jwks_client = PyJWKClient(_FPNV_JWKS_URL, lifespan=21600) - - def verify(self, token) -> Dict[str, Any]: - """Verifies the given Firebase Phone Number Verification token.""" - _Validators.check_string("Firebase Phone Number Verification check token", token) - try: - self._validate_headers(jwt.get_unverified_header(token)) - signing_key = self._jwks_client.get_signing_key_from_jwt(token) - claims = self._decode_and_verify(token, signing_key.key) - except (jwt.InvalidTokenError, PyJWKClientError) as exception: - raise InvalidTokenError( - 'Verifying phone number verification token failed.', - cause=exception, - http_response=getattr(exception, 'http_response', None) - ) from exception - - return claims - - def _validate_headers(self, headers: Any) -> None: - """Validates the headers.""" - if headers.get('kid') is None: - raise InvalidTokenError("Token has no 'kid' claim.") - - if headers.get('typ') != 'JWT': - raise InvalidTokenError( - 'The provided token has an incorrect type header. ' \ - f"Expected 'JWT' but got {headers.get('typ')!r}." - ) - - algorithm = headers.get('alg') - if algorithm != _ALGORITHM_ES256: - raise InvalidTokenError( - 'The provided token has an incorrect alg header. ' - f'Expected {_ALGORITHM_ES256} but got {algorithm}.' - ) - - def _decode_and_verify(self, token, signing_key) -> Dict[str, Any]: - """Decodes and verifies the token.""" - expected_issuer = f'{_FPNV_ISSUER}{self._project_id}' - try: - payload = jwt.decode( - token, - signing_key, - algorithms=[_ALGORITHM_ES256], - audience=expected_issuer, - issuer=expected_issuer - ) - except InvalidSignatureError as exception: - raise InvalidTokenError( - 'The provided token has an invalid signature.' - ) from exception - except InvalidAudienceError as exception: - raise InvalidTokenError( - 'The provided token has an incorrect "aud" (audience) claim. ' - f'Expected {expected_issuer}.' - ) from exception - except InvalidIssuerError as exception: - raise InvalidTokenError( - 'The provided token has an incorrect "iss" (issuer) claim. ' - f'Expected {expected_issuer}.' - ) from exception - except ExpiredSignatureError as exception: - raise ExpiredTokenError( - 'The provided token has expired.' - ) from exception - except jwt.InvalidTokenError as exception: - raise InvalidTokenError( - f'Decoding token failed. Error: {exception}' - ) from exception - - sub_claim = payload.get('sub') - if not isinstance(sub_claim, str) or not sub_claim: - raise InvalidTokenError( - 'The provided token has an incorrect "sub" (subject) claim. ' - 'Expected a non-empty string.' - ) - - return payload - - -class _Validators: - """A collection of data validation utilities. - - Methods provided in this class raise ``ValueErrors`` if any validations fail. - """ - - @classmethod - def check_string(cls, label: str, value: Any): - """Checks if the given value is a string.""" - if not isinstance(value, str) or not value: - raise ValueError(f'{label} must be a non-empty string.') - -# Firebase Phone Number Verification Errors -class InvalidTokenError(exceptions.InvalidArgumentError): - """Raised when a Firebase Phone Number Verification token is invalid.""" - - def __init__(self, message, cause=None, http_response=None): - exceptions.InvalidArgumentError.__init__(self, message, cause, http_response) - -class ExpiredTokenError(InvalidTokenError): - """Raised when a Firebase Phone Number Verification token is expired.""" - - def __init__(self, message, cause=None, http_response=None): - InvalidTokenError.__init__(self, message, cause, http_response) diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/project_management.py b/notification-service/venv/Lib/site-packages/firebase_admin/project_management.py deleted file mode 100644 index 73c100d..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/project_management.py +++ /dev/null @@ -1,663 +0,0 @@ -# Copyright 2018 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase Project Management module. - -This module enables management of resources in Firebase projects, such as Android and iOS apps. -""" - -import base64 -import re -import time - -import requests - -import firebase_admin -from firebase_admin import exceptions -from firebase_admin import _http_client -from firebase_admin import _utils - - -_PROJECT_MANAGEMENT_ATTRIBUTE = '_project_management' - - -def _get_project_management_service(app): - return _utils.get_app_service(app, _PROJECT_MANAGEMENT_ATTRIBUTE, _ProjectManagementService) - - -def android_app(app_id, app=None): - """Obtains a reference to an Android app in the associated Firebase project. - - Args: - app_id: The app ID that identifies this Android app. - app: An App instance (optional). - - Returns: - AndroidApp: An ``AndroidApp`` instance. - """ - return AndroidApp(app_id=app_id, service=_get_project_management_service(app)) - - -def ios_app(app_id, app=None): - """Obtains a reference to an iOS app in the associated Firebase project. - - Args: - app_id: The app ID that identifies this iOS app. - app: An App instance (optional). - - Returns: - IOSApp: An ``IOSApp`` instance. - """ - return IOSApp(app_id=app_id, service=_get_project_management_service(app)) - - -def list_android_apps(app=None): - """Lists all Android apps in the associated Firebase project. - - Args: - app: An App instance (optional). - - Returns: - list: a list of ``AndroidApp`` instances referring to each Android app in the Firebase - project. - """ - return _get_project_management_service(app).list_android_apps() - - -def list_ios_apps(app=None): - """Lists all iOS apps in the associated Firebase project. - - Args: - app: An App instance (optional). - - Returns: - list: a list of ``IOSApp`` instances referring to each iOS app in the Firebase project. - """ - return _get_project_management_service(app).list_ios_apps() - - -def create_android_app(package_name, display_name=None, app=None): - """Creates a new Android app in the associated Firebase project. - - Args: - package_name: The package name of the Android app to be created. - display_name: A nickname for this Android app (optional). - app: An App instance (optional). - - Returns: - AndroidApp: An ``AndroidApp`` instance that is a reference to the newly created app. - """ - return _get_project_management_service(app).create_android_app(package_name, display_name) - - -def create_ios_app(bundle_id, display_name=None, app=None): - """Creates a new iOS app in the associated Firebase project. - - Args: - bundle_id: The bundle ID of the iOS app to be created. - display_name: A nickname for this iOS app (optional). - app: An App instance (optional). - - Returns: - IOSApp: An ``IOSApp`` instance that is a reference to the newly created app. - """ - return _get_project_management_service(app).create_ios_app(bundle_id, display_name) - - -def _check_is_string_or_none(obj, field_name): - if obj is None or isinstance(obj, str): - return obj - raise ValueError(f'{field_name} must be a string.') - - -def _check_is_nonempty_string(obj, field_name): - if isinstance(obj, str) and obj: - return obj - raise ValueError(f'{field_name} must be a non-empty string.') - - -def _check_is_nonempty_string_or_none(obj, field_name): - if obj is None: - return None - return _check_is_nonempty_string(obj, field_name) - - -def _check_not_none(obj, field_name): - if obj is None: - raise ValueError(f'{field_name} cannot be None.') - return obj - - -class AndroidApp: - """A reference to an Android app within a Firebase project. - - Note: Unless otherwise specified, all methods defined in this class make an RPC. - - Please use the module-level function ``android_app(app_id)`` to obtain instances of this class - instead of instantiating it directly. - """ - - def __init__(self, app_id, service): - self._app_id = app_id - self._service = service - - @property - def app_id(self): - """Returns the app ID of the Android app to which this instance refers. - - Note: This method does not make an RPC. - - Returns: - string: The app ID of the Android app to which this instance refers. - """ - return self._app_id - - def get_metadata(self): - """Retrieves detailed information about this Android app. - - Returns: - AndroidAppMetadata: An ``AndroidAppMetadata`` instance. - - Raises: - FirebaseError: If an error occurs while communicating with the Firebase Project - Management Service. - """ - return self._service.get_android_app_metadata(self._app_id) - - def set_display_name(self, new_display_name): - """Updates the display name attribute of this Android app to the one given. - - Args: - new_display_name: The new display name for this Android app. - - Returns: - NoneType: None. - - Raises: - FirebaseError: If an error occurs while communicating with the Firebase Project - Management Service. - """ - return self._service.set_android_app_display_name(self._app_id, new_display_name) - - def get_config(self): - """Retrieves the configuration artifact associated with this Android app.""" - return self._service.get_android_app_config(self._app_id) - - def get_sha_certificates(self): - """Retrieves the entire list of SHA certificates associated with this Android app. - - Returns: - list: A list of ``SHACertificate`` instances. - - Raises: - FirebaseError: If an error occurs while communicating with the Firebase Project - Management Service. - """ - return self._service.get_sha_certificates(self._app_id) - - def add_sha_certificate(self, certificate_to_add): - """Adds a SHA certificate to this Android app. - - Args: - certificate_to_add: The SHA certificate to add. - - Returns: - NoneType: None. - - Raises: - FirebaseError: If an error occurs while communicating with the Firebase Project - Management Service. (For example, if the certificate_to_add already exists.) - """ - return self._service.add_sha_certificate(self._app_id, certificate_to_add) - - def delete_sha_certificate(self, certificate_to_delete): - """Removes a SHA certificate from this Android app. - - Args: - certificate_to_delete: The SHA certificate to delete. - - Returns: - NoneType: None. - - Raises: - FirebaseError: If an error occurs while communicating with the Firebase Project - Management Service. (For example, if the certificate_to_delete is not found.) - """ - return self._service.delete_sha_certificate(certificate_to_delete) - - -class IOSApp: - """A reference to an iOS app within a Firebase project. - - Note: Unless otherwise specified, all methods defined in this class make an RPC. - - Please use the module-level function ``ios_app(app_id)`` to obtain instances of this class - instead of instantiating it directly. - """ - - def __init__(self, app_id, service): - self._app_id = app_id - self._service = service - - @property - def app_id(self): - """Returns the app ID of the iOS app to which this instance refers. - - Note: This method does not make an RPC. - - Returns: - string: The app ID of the iOS app to which this instance refers. - """ - return self._app_id - - def get_metadata(self): - """Retrieves detailed information about this iOS app. - - Returns: - IOSAppMetadata: An ``IOSAppMetadata`` instance. - - Raises: - FirebaseError: If an error occurs while communicating with the Firebase Project - Management Service. - """ - return self._service.get_ios_app_metadata(self._app_id) - - def set_display_name(self, new_display_name): - """Updates the display name attribute of this iOS app to the one given. - - Args: - new_display_name: The new display name for this iOS app. - - Returns: - NoneType: None. - - Raises: - FirebaseError: If an error occurs while communicating with the Firebase Project - Management Service. - """ - return self._service.set_ios_app_display_name(self._app_id, new_display_name) - - def get_config(self): - """Retrieves the configuration artifact associated with this iOS app.""" - return self._service.get_ios_app_config(self._app_id) - - -class _AppMetadata: - """Detailed information about a Firebase Android or iOS app.""" - - def __init__(self, name, app_id, display_name, project_id): - # _name is the fully qualified resource name of this Android or iOS app; currently it is not - # exposed to client code. - self._name = _check_is_nonempty_string(name, 'name') - self._app_id = _check_is_nonempty_string(app_id, 'app_id') - self._display_name = _check_is_string_or_none(display_name, 'display_name') - self._project_id = _check_is_nonempty_string(project_id, 'project_id') - - @property - def app_id(self): - """The globally unique, Firebase-assigned identifier of this Android or iOS app. - - This ID is unique even across apps of different platforms. - """ - return self._app_id - - @property - def display_name(self): - """The user-assigned display name of this Android or iOS app. - - Note that the display name can be None if it has never been set by the user.""" - return self._display_name - - @property - def project_id(self): - """The permanent, globally unique, user-assigned ID of the parent Firebase project.""" - return self._project_id - - def __eq__(self, other): - if not isinstance(other, type(self)): - return False - # pylint: disable=protected-access - return (self._name == other._name and self.app_id == other.app_id and - self.display_name == other.display_name and self.project_id == other.project_id) - # pylint: enable=protected-access - - -class AndroidAppMetadata(_AppMetadata): - """Android-specific information about an Android Firebase app.""" - - def __init__(self, package_name, name, app_id, display_name, project_id): - """Clients should not instantiate this class directly.""" - super().__init__(name, app_id, display_name, project_id) - self._package_name = _check_is_nonempty_string(package_name, 'package_name') - - @property - def package_name(self): - """The canonical package name of this Android app as it would appear in the Play Store.""" - return self._package_name - - def __eq__(self, other): - return (super().__eq__(other) and - self.package_name == other.package_name) - - def __ne__(self, other): - return not self.__eq__(other) - - def __hash__(self): - return hash( - (self._name, self.app_id, self.display_name, self.project_id, self.package_name)) - - -class IOSAppMetadata(_AppMetadata): - """iOS-specific information about an iOS Firebase app.""" - - def __init__(self, bundle_id, name, app_id, display_name, project_id): - """Clients should not instantiate this class directly.""" - super().__init__(name, app_id, display_name, project_id) - self._bundle_id = _check_is_nonempty_string(bundle_id, 'bundle_id') - - @property - def bundle_id(self): - """The canonical bundle ID of this iOS app as it would appear in the iOS AppStore.""" - return self._bundle_id - - def __eq__(self, other): - return super().__eq__(other) and self.bundle_id == other.bundle_id - - def __ne__(self, other): - return not self.__eq__(other) - - def __hash__(self): - return hash((self._name, self.app_id, self.display_name, self.project_id, self.bundle_id)) - - -class SHACertificate: - """Represents a SHA-1 or SHA-256 certificate associated with an Android app.""" - - SHA_1 = 'SHA_1' - SHA_256 = 'SHA_256' - - _SHA_1_RE = re.compile('^[0-9A-Fa-f]{40}$') - _SHA_256_RE = re.compile('^[0-9A-Fa-f]{64}$') - - def __init__(self, sha_hash, name=None): - """Creates a new SHACertificate instance. - - Args: - sha_hash: A string; the certificate hash for the Android app. - name: The fully qualified resource name of this certificate; note that this field should - be omitted if the instance is being constructed for the purpose of calling the - add_sha_certificate() method on an ``AndroidApp``. - - Raises: - ValueError: If the sha_hash is not a valid SHA-1 or SHA-256 certificate hash. - """ - _check_is_nonempty_string(sha_hash, 'sha_hash') - _check_is_nonempty_string_or_none(name, 'name') - self._name = name - self._sha_hash = sha_hash.lower() - if SHACertificate._SHA_1_RE.match(sha_hash): - self._cert_type = SHACertificate.SHA_1 - elif SHACertificate._SHA_256_RE.match(sha_hash): - self._cert_type = SHACertificate.SHA_256 - else: - raise ValueError( - 'The supplied certificate hash is neither a valid SHA-1 nor SHA_256 hash.') - - @property - def name(self): - """Returns the fully qualified resource name of this certificate, if known. - - Returns: - string: The fully qualified resource name of this certificate, if known; otherwise, the - empty string. - """ - return self._name - - @property - def sha_hash(self): - """Returns the certificate hash. - - Returns: - string: The certificate hash. - """ - return self._sha_hash - - @property - def cert_type(self): - """Returns the type of the SHA certificate encoded in the hash. - - Returns: - string: One of 'SHA_1' or 'SHA_256'. - """ - return self._cert_type - - def __eq__(self, other): - if not isinstance(other, SHACertificate): - return False - return (self.name == other.name and self.sha_hash == other.sha_hash and - self.cert_type == other.cert_type) - - def __ne__(self, other): - return not self.__eq__(other) - - def __hash__(self): - return hash((self.name, self.sha_hash, self.cert_type)) - - -class _ProjectManagementService: - """Provides methods for interacting with the Firebase Project Management Service.""" - - BASE_URL = 'https://firebase.googleapis.com' - MAXIMUM_LIST_APPS_PAGE_SIZE = 100 - MAXIMUM_POLLING_ATTEMPTS = 8 - POLL_BASE_WAIT_TIME_SECONDS = 0.5 - POLL_EXPONENTIAL_BACKOFF_FACTOR = 1.5 - - ANDROID_APPS_RESOURCE_NAME = 'androidApps' - ANDROID_APP_IDENTIFIER_NAME = 'packageName' - IOS_APPS_RESOURCE_NAME = 'iosApps' - IOS_APP_IDENTIFIER_NAME = 'bundleId' - - def __init__(self, app): - project_id = app.project_id - if not project_id: - raise ValueError( - 'Project ID is required to access the Firebase Project Management Service. Either ' - 'set the projectId option, or use service account credentials. Alternatively, set ' - 'the GOOGLE_CLOUD_PROJECT environment variable.') - self._project_id = project_id - version_header = f'Python/Admin/{firebase_admin.__version__}' - timeout = app.options.get('httpTimeout', _http_client.DEFAULT_TIMEOUT_SECONDS) - self._client = _http_client.JsonHttpClient( - credential=app.credential.get_credential(), - base_url=_ProjectManagementService.BASE_URL, - headers={'X-Client-Version': version_header}, - timeout=timeout) - - def get_android_app_metadata(self, app_id): - return self._get_app_metadata( - platform_resource_name=_ProjectManagementService.ANDROID_APPS_RESOURCE_NAME, - identifier_name=_ProjectManagementService.ANDROID_APP_IDENTIFIER_NAME, - metadata_class=AndroidAppMetadata, - app_id=app_id) - - def get_ios_app_metadata(self, app_id): - return self._get_app_metadata( - platform_resource_name=_ProjectManagementService.IOS_APPS_RESOURCE_NAME, - identifier_name=_ProjectManagementService.IOS_APP_IDENTIFIER_NAME, - metadata_class=IOSAppMetadata, - app_id=app_id) - - def _get_app_metadata(self, platform_resource_name, identifier_name, metadata_class, app_id): - """Retrieves detailed information about an Android or iOS app.""" - _check_is_nonempty_string(app_id, 'app_id') - path = f'/v1beta1/projects/-/{platform_resource_name}/{app_id}' - response = self._make_request('get', path) - return metadata_class( - response[identifier_name], - name=response['name'], - app_id=response['appId'], - display_name=response.get('displayName') or None, - project_id=response['projectId']) - - def set_android_app_display_name(self, app_id, new_display_name): - self._set_display_name( - app_id=app_id, - new_display_name=new_display_name, - platform_resource_name=_ProjectManagementService.ANDROID_APPS_RESOURCE_NAME) - - def set_ios_app_display_name(self, app_id, new_display_name): - self._set_display_name( - app_id=app_id, - new_display_name=new_display_name, - platform_resource_name=_ProjectManagementService.IOS_APPS_RESOURCE_NAME) - - def _set_display_name(self, app_id, new_display_name, platform_resource_name): - """Sets the display name of an Android or iOS app.""" - path = f'/v1beta1/projects/-/{platform_resource_name}/{app_id}?updateMask=displayName' - request_body = {'displayName': new_display_name} - self._make_request('patch', path, json=request_body) - - def list_android_apps(self): - return self._list_apps( - platform_resource_name=_ProjectManagementService.ANDROID_APPS_RESOURCE_NAME, - app_class=AndroidApp) - - def list_ios_apps(self): - return self._list_apps( - platform_resource_name=_ProjectManagementService.IOS_APPS_RESOURCE_NAME, - app_class=IOSApp) - - def _list_apps(self, platform_resource_name, app_class): - """Lists all the Android or iOS apps within the Firebase project.""" - path = ( - f'/v1beta1/projects/{self._project_id}/{platform_resource_name}?pageSize=' - f'{_ProjectManagementService.MAXIMUM_LIST_APPS_PAGE_SIZE}' - ) - response = self._make_request('get', path) - apps_list = [] - while True: - apps = response.get('apps') - if not apps: - break - apps_list.extend(app_class(app_id=app['appId'], service=self) for app in apps) - next_page_token = response.get('nextPageToken') - if not next_page_token: - break - # Retrieve the next page of apps. - path = ( - f'/v1beta1/projects/{self._project_id}/{platform_resource_name}' - f'?pageToken={next_page_token}' - f'&pageSize={_ProjectManagementService.MAXIMUM_LIST_APPS_PAGE_SIZE}' - ) - response = self._make_request('get', path) - return apps_list - - def create_android_app(self, package_name, display_name=None): - return self._create_app( - platform_resource_name=_ProjectManagementService.ANDROID_APPS_RESOURCE_NAME, - identifier_name=_ProjectManagementService.ANDROID_APP_IDENTIFIER_NAME, - identifier=package_name, - display_name=display_name, - app_class=AndroidApp) - - def create_ios_app(self, bundle_id, display_name=None): - return self._create_app( - platform_resource_name=_ProjectManagementService.IOS_APPS_RESOURCE_NAME, - identifier_name=_ProjectManagementService.IOS_APP_IDENTIFIER_NAME, - identifier=bundle_id, - display_name=display_name, - app_class=IOSApp) - - def _create_app( - self, - platform_resource_name, - identifier_name, - identifier, - display_name, - app_class): - """Creates an Android or iOS app.""" - _check_is_string_or_none(display_name, 'display_name') - path = f'/v1beta1/projects/{self._project_id}/{platform_resource_name}' - request_body = {identifier_name: identifier} - if display_name: - request_body['displayName'] = display_name - response = self._make_request('post', path, json=request_body) - operation_name = response['name'] - poll_response = self._poll_app_creation(operation_name) - return app_class(app_id=poll_response['appId'], service=self) - - def _poll_app_creation(self, operation_name): - """Polls the Long-Running Operation repeatedly until it is done with exponential backoff.""" - for current_attempt in range(_ProjectManagementService.MAXIMUM_POLLING_ATTEMPTS): - delay_factor = pow( - _ProjectManagementService.POLL_EXPONENTIAL_BACKOFF_FACTOR, current_attempt) - wait_time_seconds = delay_factor * _ProjectManagementService.POLL_BASE_WAIT_TIME_SECONDS - time.sleep(wait_time_seconds) - path = f'/v1/{operation_name}' - poll_response, http_response = self._body_and_response('get', path) - done = poll_response.get('done') - if done: - response = poll_response.get('response') - if response: - return response - - raise exceptions.UnknownError( - 'Polling finished, but the operation terminated in an error.', - http_response=http_response) - raise exceptions.DeadlineExceededError('Polling deadline exceeded.') - - def get_android_app_config(self, app_id): - return self._get_app_config( - platform_resource_name=_ProjectManagementService.ANDROID_APPS_RESOURCE_NAME, - app_id=app_id) - - def get_ios_app_config(self, app_id): - return self._get_app_config( - platform_resource_name=_ProjectManagementService.IOS_APPS_RESOURCE_NAME, app_id=app_id) - - def _get_app_config(self, platform_resource_name, app_id): - path = f'/v1beta1/projects/-/{platform_resource_name}/{app_id}/config' - response = self._make_request('get', path) - # In Python 2.7, the base64 module works with strings, while in Python 3, it works with - # bytes objects. This line works in both versions. - return base64.standard_b64decode(response['configFileContents']).decode(encoding='utf-8') - - def get_sha_certificates(self, app_id): - path = f'/v1beta1/projects/-/androidApps/{app_id}/sha' - response = self._make_request('get', path) - cert_list = response.get('certificates') or [] - return [SHACertificate(sha_hash=cert['shaHash'], name=cert['name']) for cert in cert_list] - - def add_sha_certificate(self, app_id, certificate_to_add): - path = f'/v1beta1/projects/-/androidApps/{app_id}/sha' - sha_hash = _check_not_none(certificate_to_add, 'certificate_to_add').sha_hash - cert_type = certificate_to_add.cert_type - request_body = {'shaHash': sha_hash, 'certType': cert_type} - self._make_request('post', path, json=request_body) - - def delete_sha_certificate(self, certificate_to_delete): - name = _check_not_none(certificate_to_delete, 'certificate_to_delete').name - path = f'/v1beta1/{name}' - self._make_request('delete', path) - - def _make_request(self, method, url, json=None): - body, _ = self._body_and_response(method, url, json) - return body - - def _body_and_response(self, method, url, json=None): - try: - return self._client.body_and_response(method=method, url=url, json=json) - except requests.exceptions.RequestException as error: - raise _utils.handle_platform_error_from_requests(error) diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/remote_config.py b/notification-service/venv/Lib/site-packages/firebase_admin/remote_config.py deleted file mode 100644 index 880804d..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/remote_config.py +++ /dev/null @@ -1,762 +0,0 @@ -# Copyright 2024 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase Remote Config Module. -This module has required APIs for the clients to use Firebase Remote Config with python. -""" - -import asyncio -import json -import logging -import threading -from typing import Dict, Optional, Literal, Union, Any -from enum import Enum -import re -import hashlib -import requests -from firebase_admin import App, _http_client, _utils -import firebase_admin - -# Set up logging (you can customize the level and output) -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - -_REMOTE_CONFIG_ATTRIBUTE = '_remoteconfig' -MAX_CONDITION_RECURSION_DEPTH = 10 -ValueSource = Literal['default', 'remote', 'static'] # Define the ValueSource type - -class PercentConditionOperator(Enum): - """Enum representing the available operators for percent conditions. - """ - LESS_OR_EQUAL = "LESS_OR_EQUAL" - GREATER_THAN = "GREATER_THAN" - BETWEEN = "BETWEEN" - UNKNOWN = "UNKNOWN" - -class CustomSignalOperator(Enum): - """Enum representing the available operators for custom signal conditions. - """ - STRING_CONTAINS = "STRING_CONTAINS" - STRING_DOES_NOT_CONTAIN = "STRING_DOES_NOT_CONTAIN" - STRING_EXACTLY_MATCHES = "STRING_EXACTLY_MATCHES" - STRING_CONTAINS_REGEX = "STRING_CONTAINS_REGEX" - NUMERIC_LESS_THAN = "NUMERIC_LESS_THAN" - NUMERIC_LESS_EQUAL = "NUMERIC_LESS_EQUAL" - NUMERIC_EQUAL = "NUMERIC_EQUAL" - NUMERIC_NOT_EQUAL = "NUMERIC_NOT_EQUAL" - NUMERIC_GREATER_THAN = "NUMERIC_GREATER_THAN" - NUMERIC_GREATER_EQUAL = "NUMERIC_GREATER_EQUAL" - SEMANTIC_VERSION_LESS_THAN = "SEMANTIC_VERSION_LESS_THAN" - SEMANTIC_VERSION_LESS_EQUAL = "SEMANTIC_VERSION_LESS_EQUAL" - SEMANTIC_VERSION_EQUAL = "SEMANTIC_VERSION_EQUAL" - SEMANTIC_VERSION_NOT_EQUAL = "SEMANTIC_VERSION_NOT_EQUAL" - SEMANTIC_VERSION_GREATER_THAN = "SEMANTIC_VERSION_GREATER_THAN" - SEMANTIC_VERSION_GREATER_EQUAL = "SEMANTIC_VERSION_GREATER_EQUAL" - UNKNOWN = "UNKNOWN" - -class _ServerTemplateData: - """Parses, validates and encapsulates template data and metadata.""" - def __init__(self, template_data): - """Initializes a new ServerTemplateData instance. - - Args: - template_data: The data to be parsed for getting the parameters and conditions. - - Raises: - ValueError: If the template data is not valid. - """ - if 'parameters' in template_data: - if template_data['parameters'] is not None: - self._parameters = template_data['parameters'] - else: - raise ValueError('Remote Config parameters must be a non-null object') - else: - self._parameters = {} - - if 'conditions' in template_data: - if template_data['conditions'] is not None: - self._conditions = template_data['conditions'] - else: - raise ValueError('Remote Config conditions must be a non-null object') - else: - self._conditions = [] - - self._version = '' - if 'version' in template_data: - self._version = template_data['version'] - - self._etag = '' - if 'etag' in template_data and isinstance(template_data['etag'], str): - self._etag = template_data['etag'] - - self._template_data_json = json.dumps(template_data) - - @property - def parameters(self): - return self._parameters - - @property - def etag(self): - return self._etag - - @property - def version(self): - return self._version - - @property - def conditions(self): - return self._conditions - - @property - def template_data_json(self): - return self._template_data_json - - -class ServerTemplate: - """Represents a Server Template with implementations for loading and evaluating the template.""" - def __init__(self, app: App = None, default_config: Optional[Dict[str, str]] = None): - """Initializes a ServerTemplate instance. - - Args: - app: App instance to be used. This is optional and the default app instance will - be used if not present. - default_config: The default config to be used in the evaluated config. - """ - self._rc_service = _utils.get_app_service(app, - _REMOTE_CONFIG_ATTRIBUTE, _RemoteConfigService) - # This gets set when the template is - # fetched from RC servers via the load API, or via the set API. - self._cache = None - self._stringified_default_config: Dict[str, str] = {} - self._lock = threading.RLock() - - # RC stores all remote values as string, but it's more intuitive - # to declare default values with specific types, so this converts - # the external declaration to an internal string representation. - if default_config is not None: - for key in default_config: - self._stringified_default_config[key] = str(default_config[key]) - - async def load(self): - """Fetches the server template and caches the data.""" - rc_server_template = await self._rc_service.get_server_template() - with self._lock: - self._cache = rc_server_template - - def evaluate(self, context: Optional[Dict[str, Union[str, int]]] = None) -> 'ServerConfig': - """Evaluates the cached server template to produce a ServerConfig. - - Args: - context: A dictionary of values to use for evaluating conditions. - - Returns: - A ServerConfig object. - Raises: - ValueError: If the input arguments are invalid. - """ - # Logic to process the cached template into a ServerConfig here. - if not self._cache: - raise ValueError("""No Remote Config Server template in cache. - Call load() before calling evaluate().""") - context = context or {} - config_values = {} - - with self._lock: - template_conditions = self._cache.conditions - template_parameters = self._cache.parameters - - # Initializes config Value objects with default values. - if self._stringified_default_config is not None: - for key, value in self._stringified_default_config.items(): - config_values[key] = _Value('default', value) - self._evaluator = _ConditionEvaluator(template_conditions, - template_parameters, context, - config_values) - return ServerConfig(config_values=self._evaluator.evaluate()) - - def set(self, template_data_json: str): - """Updates the cache to store the given template is of type ServerTemplateData. - - Args: - template_data_json: A json string representing ServerTemplateData to be cached. - """ - template_data_map = json.loads(template_data_json) - template_data = _ServerTemplateData(template_data_map) - - with self._lock: - self._cache = template_data - - def to_json(self): - """Provides the server template in a JSON format to be used for initialization later.""" - if not self._cache: - raise ValueError("""No Remote Config Server template in cache. - Call load() before calling toJSON().""") - with self._lock: - template_json = self._cache.template_data_json - return template_json - - -class ServerConfig: - """Represents a Remote Config Server Side Config.""" - def __init__(self, config_values): - self._config_values = config_values # dictionary of param key to values - - def get_boolean(self, key): - """Returns the value as a boolean.""" - return self._get_value(key).as_boolean() - - def get_string(self, key): - """Returns the value as a string.""" - return self._get_value(key).as_string() - - def get_int(self, key): - """Returns the value as an integer.""" - return self._get_value(key).as_int() - - def get_float(self, key): - """Returns the value as a float.""" - return self._get_value(key).as_float() - - def get_value_source(self, key): - """Returns the source of the value.""" - return self._get_value(key).get_source() - - def _get_value(self, key): - return self._config_values.get(key, _Value('static')) - - -class _RemoteConfigService: - """Internal class that facilitates sending requests to the Firebase Remote - Config backend API. - """ - def __init__(self, app): - """Initialize a JsonHttpClient with necessary inputs. - - Args: - app: App instance to be used for fetching app specific details required - for initializing the http client. - """ - remote_config_base_url = 'https://firebaseremoteconfig.googleapis.com' - self._project_id = app.project_id - app_credential = app.credential.get_credential() - rc_headers = { - 'X-FIREBASE-CLIENT': f'fire-admin-python/{firebase_admin.__version__}', } - timeout = app.options.get('httpTimeout', _http_client.DEFAULT_TIMEOUT_SECONDS) - - self._client = _http_client.JsonHttpClient(credential=app_credential, - base_url=remote_config_base_url, - headers=rc_headers, timeout=timeout) - - async def get_server_template(self): - """Requests for a server template and converts the response to an instance of - ServerTemplateData for storing the template parameters and conditions.""" - try: - loop = asyncio.get_event_loop() - headers, template_data = await loop.run_in_executor(None, - self._client.headers_and_body, - 'get', self._get_url()) - except requests.exceptions.RequestException as error: - raise self._handle_remote_config_error(error) - template_data['etag'] = headers.get('etag') - return _ServerTemplateData(template_data) - - def _get_url(self): - """Returns project prefix for url, in the format of /v1/projects/${projectId}""" - return f"/v1/projects/{self._project_id}/namespaces/firebase-server/serverRemoteConfig" - - @classmethod - def _handle_remote_config_error(cls, error: Any): - """Handles errors received from the Cloud Functions API.""" - return _utils.handle_platform_error_from_requests(error) - - -class _ConditionEvaluator: - """Internal class that facilitates sending requests to the Firebase Remote - Config backend API.""" - def __init__(self, conditions, parameters, context, config_values): - self._context = context - self._conditions = conditions - self._parameters = parameters - self._config_values = config_values - - def evaluate(self): - """Internal function that evaluates the cached server template to produce - a ServerConfig""" - evaluated_conditions = self.evaluate_conditions(self._conditions, self._context) - - # Overlays config Value objects derived by evaluating the template. - if self._parameters: - for key, parameter in self._parameters.items(): - conditional_values = parameter.get('conditionalValues', {}) - default_value = parameter.get('defaultValue', {}) - parameter_value_wrapper = None - # Iterates in order over condition list. If there is a value associated - # with a condition, this checks if the condition is true. - if evaluated_conditions: - for condition_name, condition_evaluation in evaluated_conditions.items(): - if condition_name in conditional_values and condition_evaluation: - parameter_value_wrapper = conditional_values[condition_name] - break - - if parameter_value_wrapper and parameter_value_wrapper.get('useInAppDefault'): - logger.info("Using in-app default value for key '%s'", key) - continue - - if parameter_value_wrapper: - parameter_value = parameter_value_wrapper.get('value') - self._config_values[key] = _Value('remote', parameter_value) - continue - - if not default_value: - logger.warning("No default value found for key '%s'", key) - continue - - if default_value.get('useInAppDefault'): - logger.info("Using in-app default value for key '%s'", key) - continue - self._config_values[key] = _Value('remote', default_value.get('value')) - return self._config_values - - def evaluate_conditions(self, conditions, context)-> Dict[str, bool]: - """Evaluates a list of conditions and returns a dictionary of results. - - Args: - conditions: A list of NamedCondition objects. - context: An EvaluationContext object. - - Returns: - A dictionary that maps condition names to boolean evaluation results. - """ - evaluated_conditions = {} - for condition in conditions: - evaluated_conditions[condition.get('name')] = self.evaluate_condition( - condition.get('condition'), context - ) - return evaluated_conditions - - def evaluate_condition(self, condition, context, - nesting_level: int = 0) -> bool: - """Recursively evaluates a condition. - - Args: - condition: The condition to evaluate. - context: An EvaluationContext object. - nesting_level: The current recursion depth. - - Returns: - The boolean result of the condition evaluation. - """ - if nesting_level >= MAX_CONDITION_RECURSION_DEPTH: - logger.warning("Maximum condition recursion depth exceeded.") - return False - if condition.get('orCondition') is not None: - return self.evaluate_or_condition(condition.get('orCondition'), - context, nesting_level + 1) - if condition.get('andCondition') is not None: - return self.evaluate_and_condition(condition.get('andCondition'), - context, nesting_level + 1) - if condition.get('true') is not None: - return True - if condition.get('false') is not None: - return False - if condition.get('percent') is not None: - return self.evaluate_percent_condition(condition.get('percent'), context) - if condition.get('customSignal') is not None: - return self.evaluate_custom_signal_condition(condition.get('customSignal'), context) - logger.warning("Unknown condition type encountered.") - return False - - def evaluate_or_condition(self, or_condition, - context, - nesting_level: int = 0) -> bool: - """Evaluates an OR condition. - - Args: - or_condition: The OR condition to evaluate. - context: An EvaluationContext object. - nesting_level: The current recursion depth. - - Returns: - True if any of the subconditions are true, False otherwise. - """ - sub_conditions = or_condition.get('conditions') or [] - for sub_condition in sub_conditions: - result = self.evaluate_condition(sub_condition, context, nesting_level + 1) - if result: - return True - return False - - def evaluate_and_condition(self, and_condition, - context, - nesting_level: int = 0) -> bool: - """Evaluates an AND condition. - - Args: - and_condition: The AND condition to evaluate. - context: An EvaluationContext object. - nesting_level: The current recursion depth. - - Returns: - True if all of the subconditions are met; False otherwise. - """ - sub_conditions = and_condition.get('conditions') or [] - for sub_condition in sub_conditions: - result = self.evaluate_condition(sub_condition, context, nesting_level + 1) - if not result: - return False - return True - - def evaluate_percent_condition(self, percent_condition, - context) -> bool: - """Evaluates a percent condition. - - Args: - percent_condition: The percent condition to evaluate. - context: An EvaluationContext object. - - Returns: - True if the condition is met, False otherwise. - """ - if not context.get('randomization_id'): - logger.warning("Missing randomization_id in context for evaluating percent condition.") - return False - - seed = percent_condition.get('seed') - percent_operator = percent_condition.get('percentOperator') - micro_percent = percent_condition.get('microPercent') - micro_percent_range = percent_condition.get('microPercentRange') - if not percent_operator: - logger.warning("Missing percent operator for percent condition.") - return False - if micro_percent_range: - norm_percent_upper_bound = micro_percent_range.get('microPercentUpperBound') or 0 - norm_percent_lower_bound = micro_percent_range.get('microPercentLowerBound') or 0 - else: - norm_percent_upper_bound = 0 - norm_percent_lower_bound = 0 - if micro_percent: - norm_micro_percent = micro_percent - else: - norm_micro_percent = 0 - seed_prefix = f"{seed}." if seed else "" - string_to_hash = f"{seed_prefix}{context.get('randomization_id')}" - - hash64 = self.hash_seeded_randomization_id(string_to_hash) - instance_micro_percentile = hash64 % (100 * 1000000) - if percent_operator == PercentConditionOperator.LESS_OR_EQUAL.value: - return instance_micro_percentile <= norm_micro_percent - if percent_operator == PercentConditionOperator.GREATER_THAN.value: - return instance_micro_percentile > norm_micro_percent - if percent_operator == PercentConditionOperator.BETWEEN.value: - return norm_percent_lower_bound < instance_micro_percentile <= norm_percent_upper_bound - logger.warning("Unknown percent operator: %s", percent_operator) - return False - def hash_seeded_randomization_id(self, seeded_randomization_id: str) -> int: - """Hashes a seeded randomization ID. - - Args: - seeded_randomization_id: The seeded randomization ID to hash. - - Returns: - The hashed value. - """ - hash_object = hashlib.sha256() - hash_object.update(seeded_randomization_id.encode('utf-8')) - hash64 = hash_object.hexdigest() - return abs(int(hash64, 16)) - - def evaluate_custom_signal_condition(self, custom_signal_condition, - context) -> bool: - """Evaluates a custom signal condition. - - Args: - custom_signal_condition: The custom signal condition to evaluate. - context: An EvaluationContext object. - - Returns: - True if the condition is met, False otherwise. - """ - custom_signal_operator = custom_signal_condition.get('customSignalOperator') or {} - custom_signal_key = custom_signal_condition.get('customSignalKey') or {} - target_custom_signal_values = ( - custom_signal_condition.get('targetCustomSignalValues') or {}) - - if not all([custom_signal_operator, custom_signal_key, target_custom_signal_values]): - logger.warning("Missing operator, key, or target values for custom signal condition.") - return False - - if not target_custom_signal_values: - return False - actual_custom_signal_value = context.get(custom_signal_key) or {} - - if not actual_custom_signal_value: - logger.debug("Custom signal value not found in context: %s", custom_signal_key) - return False - - if custom_signal_operator == CustomSignalOperator.STRING_CONTAINS.value: - return self._compare_strings(target_custom_signal_values, - actual_custom_signal_value, - lambda target, actual: target in actual) - if custom_signal_operator == CustomSignalOperator.STRING_DOES_NOT_CONTAIN.value: - return not self._compare_strings(target_custom_signal_values, - actual_custom_signal_value, - lambda target, actual: target in actual) - if custom_signal_operator == CustomSignalOperator.STRING_EXACTLY_MATCHES.value: - return self._compare_strings(target_custom_signal_values, - actual_custom_signal_value, - lambda target, actual: target.strip() == actual.strip()) - if custom_signal_operator == CustomSignalOperator.STRING_CONTAINS_REGEX.value: - return self._compare_strings(target_custom_signal_values, - actual_custom_signal_value, - re.search) - - # For numeric operators only one target value is allowed. - if custom_signal_operator == CustomSignalOperator.NUMERIC_LESS_THAN.value: - return self._compare_numbers(custom_signal_key, - target_custom_signal_values[0], - actual_custom_signal_value, - lambda r: r < 0) - if custom_signal_operator == CustomSignalOperator.NUMERIC_LESS_EQUAL.value: - return self._compare_numbers(custom_signal_key, - target_custom_signal_values[0], - actual_custom_signal_value, - lambda r: r <= 0) - if custom_signal_operator == CustomSignalOperator.NUMERIC_EQUAL.value: - return self._compare_numbers(custom_signal_key, - target_custom_signal_values[0], - actual_custom_signal_value, - lambda r: r == 0) - if custom_signal_operator == CustomSignalOperator.NUMERIC_NOT_EQUAL.value: - return self._compare_numbers(custom_signal_key, - target_custom_signal_values[0], - actual_custom_signal_value, - lambda r: r != 0) - if custom_signal_operator == CustomSignalOperator.NUMERIC_GREATER_THAN.value: - return self._compare_numbers(custom_signal_key, - target_custom_signal_values[0], - actual_custom_signal_value, - lambda r: r > 0) - if custom_signal_operator == CustomSignalOperator.NUMERIC_GREATER_EQUAL.value: - return self._compare_numbers(custom_signal_key, - target_custom_signal_values[0], - actual_custom_signal_value, - lambda r: r >= 0) - - # For semantic operators only one target value is allowed. - if custom_signal_operator == CustomSignalOperator.SEMANTIC_VERSION_LESS_THAN.value: - return self._compare_semantic_versions(custom_signal_key, - target_custom_signal_values[0], - actual_custom_signal_value, - lambda r: r < 0) - if custom_signal_operator == CustomSignalOperator.SEMANTIC_VERSION_LESS_EQUAL.value: - return self._compare_semantic_versions(custom_signal_key, - target_custom_signal_values[0], - actual_custom_signal_value, - lambda r: r <= 0) - if custom_signal_operator == CustomSignalOperator.SEMANTIC_VERSION_EQUAL.value: - return self._compare_semantic_versions(custom_signal_key, - target_custom_signal_values[0], - actual_custom_signal_value, - lambda r: r == 0) - if custom_signal_operator == CustomSignalOperator.SEMANTIC_VERSION_NOT_EQUAL.value: - return self._compare_semantic_versions(custom_signal_key, - target_custom_signal_values[0], - actual_custom_signal_value, - lambda r: r != 0) - if custom_signal_operator == CustomSignalOperator.SEMANTIC_VERSION_GREATER_THAN.value: - return self._compare_semantic_versions(custom_signal_key, - target_custom_signal_values[0], - actual_custom_signal_value, - lambda r: r > 0) - if custom_signal_operator == CustomSignalOperator.SEMANTIC_VERSION_GREATER_EQUAL.value: - return self._compare_semantic_versions(custom_signal_key, - target_custom_signal_values[0], - actual_custom_signal_value, - lambda r: r >= 0) - logger.warning("Unknown custom signal operator: %s", custom_signal_operator) - return False - - def _compare_strings(self, target_values, actual_value, predicate_fn) -> bool: - """Compares the actual string value of a signal against a list of target values. - - Args: - target_values: A list of target string values. - actual_value: The actual value to compare, which can be a string or number. - predicate_fn: A function that takes two string arguments (target and actual) - and returns a boolean indicating whether - the target matches the actual value. - - Returns: - bool: True if the predicate function returns True for any target value in the list, - False otherwise. - """ - - for target in target_values: - if predicate_fn(target, str(actual_value)): - return True - return False - - def _compare_numbers(self, custom_signal_key, target_value, actual_value, predicate_fn) -> bool: - try: - target = float(target_value) - actual = float(actual_value) - result = -1 if actual < target else 1 if actual > target else 0 - return predicate_fn(result) - except ValueError: - logger.warning("Invalid numeric value for comparison for custom signal key %s.", - custom_signal_key) - return False - - def _compare_semantic_versions(self, custom_signal_key, - target_value, actual_value, predicate_fn) -> bool: - """Compares the actual semantic version value of a signal against a target value. - Calls the predicate function with -1, 0, 1 if actual is less than, equal to, - or greater than target. - - Args: - custom_signal_key: The custom signal for which the evaluation is being performed. - target_values: A list of target string values. - actual_value: The actual value to compare, which can be a string or number. - predicate_fn: A function that takes an integer (-1, 0, or 1) and returns a boolean. - - Returns: - bool: True if the predicate function returns True for the result of the comparison, - False otherwise. - """ - return self._compare_versions(custom_signal_key, str(actual_value), - str(target_value), predicate_fn) - - def _compare_versions(self, custom_signal_key, - sem_version_1, sem_version_2, predicate_fn) -> bool: - """Compares two semantic version strings. - - Args: - custom_signal_key: The custom singal for which the evaluation is being performed. - sem_version_1: The first semantic version string. - sem_version_2: The second semantic version string. - predicate_fn: A function that takes an integer and returns a boolean. - - Returns: - bool: The result of the predicate function. - """ - try: - v1_parts = [int(part) for part in sem_version_1.split('.')] - v2_parts = [int(part) for part in sem_version_2.split('.')] - max_length = max(len(v1_parts), len(v2_parts)) - v1_parts.extend([0] * (max_length - len(v1_parts))) - v2_parts.extend([0] * (max_length - len(v2_parts))) - - for part1, part2 in zip(v1_parts, v2_parts): - if any((part1 < 0, part2 < 0)): - raise ValueError - if part1 < part2: - return predicate_fn(-1) - if part1 > part2: - return predicate_fn(1) - return predicate_fn(0) - except ValueError: - logger.warning( - "Invalid semantic version format for comparison for custom signal key %s.", - custom_signal_key) - return False - -async def get_server_template(app: App = None, default_config: Optional[Dict[str, str]] = None): - """Initializes a new ServerTemplate instance and fetches the server template. - - Args: - app: App instance to be used. This is optional and the default app instance will - be used if not present. - default_config: The default config to be used in the evaluated config. - - Returns: - ServerTemplate: An object having the cached server template to be used for evaluation. - """ - template = init_server_template(app=app, default_config=default_config) - await template.load() - return template - -def init_server_template(app: App = None, default_config: Optional[Dict[str, str]] = None, - template_data_json: Optional[str] = None): - """Initializes a new ServerTemplate instance. - - Args: - app: App instance to be used. This is optional and the default app instance will - be used if not present. - default_config: The default config to be used in the evaluated config. - template_data_json: An optional template data JSON to be set on initialization. - - Returns: - ServerTemplate: A new ServerTemplate instance initialized with an optional - template and config. - """ - template = ServerTemplate(app=app, default_config=default_config) - if template_data_json is not None: - template.set(template_data_json) - return template - -class _Value: - """Represents a value fetched from Remote Config. - """ - DEFAULT_VALUE_FOR_BOOLEAN = False - DEFAULT_VALUE_FOR_STRING = '' - DEFAULT_VALUE_FOR_INTEGER = 0 - DEFAULT_VALUE_FOR_FLOAT_NUMBER = 0.0 - BOOLEAN_TRUTHY_VALUES = ['1', 'true', 't', 'yes', 'y', 'on'] - - def __init__(self, source: ValueSource, value: str = DEFAULT_VALUE_FOR_STRING): - """Initializes a Value instance. - - Args: - source: The source of the value (e.g., 'default', 'remote', 'static'). - "static" indicates the value was defined by a static constant. - "default" indicates the value was defined by default config. - "remote" indicates the value was defined by config produced by evaluating a template. - value: The string value. - """ - self.source = source - self.value = value - - def as_string(self) -> str: - """Returns the value as a string.""" - if self.source == 'static': - return self.DEFAULT_VALUE_FOR_STRING - return str(self.value) - - def as_boolean(self) -> bool: - """Returns the value as a boolean.""" - if self.source == 'static': - return self.DEFAULT_VALUE_FOR_BOOLEAN - return str(self.value).lower() in self.BOOLEAN_TRUTHY_VALUES - - def as_int(self) -> float: - """Returns the value as a number.""" - if self.source == 'static': - return self.DEFAULT_VALUE_FOR_INTEGER - try: - return int(self.value) - except ValueError: - return self.DEFAULT_VALUE_FOR_INTEGER - - def as_float(self) -> float: - """Returns the value as a number.""" - if self.source == 'static': - return self.DEFAULT_VALUE_FOR_FLOAT_NUMBER - try: - return float(self.value) - except ValueError: - return self.DEFAULT_VALUE_FOR_FLOAT_NUMBER - - def get_source(self) -> ValueSource: - """Returns the source of the value.""" - return self.source diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/storage.py b/notification-service/venv/Lib/site-packages/firebase_admin/storage.py deleted file mode 100644 index d2f004b..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/storage.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase Cloud Storage module. - -This module contains utilities for accessing Google Cloud Storage buckets associated with -Firebase apps. This requires the ``google-cloud-storage`` Python module. -""" - -# pylint: disable=import-error,no-name-in-module -try: - from google.cloud import storage -except ImportError as exception: - raise ImportError('Failed to import the Cloud Storage library for Python. Make sure ' - 'to install the "google-cloud-storage" module.') from exception - -from firebase_admin import _utils - - -_STORAGE_ATTRIBUTE = '_storage' - -def bucket(name=None, app=None) -> storage.Bucket: - """Returns a handle to a Google Cloud Storage bucket. - - If the name argument is not provided, uses the 'storageBucket' option specified when - initializing the App. If that is also not available raises an error. This function - does not make any RPC calls. - - Args: - name: Name of a cloud storage bucket (optional). - app: An App instance (optional). - - Returns: - google.cloud.storage.Bucket: A handle to the specified bucket. - - Raises: - ValueError: If a bucket name is not specified either via options or method arguments, - or if the specified bucket name is not a valid string. - """ - client = _utils.get_app_service(app, _STORAGE_ATTRIBUTE, _StorageClient.from_app) - return client.bucket(name) - - -class _StorageClient: - """Holds a Google Cloud Storage client instance.""" - - STORAGE_HEADERS = { - 'x-goog-api-client': _utils.get_metrics_header(), - } - - def __init__(self, credentials, project, default_bucket): - self._client = storage.Client( - credentials=credentials, project=project, extra_headers=self.STORAGE_HEADERS) - self._default_bucket = default_bucket - - @classmethod - def from_app(cls, app): - credentials = app.credential.get_credential() - default_bucket = app.options.get('storageBucket') - # Specifying project ID is not required, but providing it when available - # significantly speeds up the initialization of the storage client. - return _StorageClient(credentials, app.project_id, default_bucket) - - def bucket(self, name=None): - """Returns a handle to the specified Cloud Storage Bucket.""" - bucket_name = name if name is not None else self._default_bucket - if bucket_name is None: - raise ValueError( - 'Storage bucket name not specified. Specify the bucket name via the ' - '"storageBucket" option when initializing the App, or specify the bucket ' - 'name explicitly when calling the storage.bucket() function.') - if not bucket_name or not isinstance(bucket_name, str): - raise ValueError( - f'Invalid storage bucket name: "{bucket_name}". Bucket name must be a non-empty ' - 'string.') - return self._client.bucket(bucket_name) diff --git a/notification-service/venv/Lib/site-packages/firebase_admin/tenant_mgt.py b/notification-service/venv/Lib/site-packages/firebase_admin/tenant_mgt.py deleted file mode 100644 index 9e713d9..0000000 --- a/notification-service/venv/Lib/site-packages/firebase_admin/tenant_mgt.py +++ /dev/null @@ -1,439 +0,0 @@ -# Copyright 2020 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Firebase tenant management module. - -This module contains functions for creating and configuring authentication tenants within a -Google Cloud Identity Platform (GCIP) instance. -""" - -import re -import threading - -import requests - -import firebase_admin -from firebase_admin import auth -from firebase_admin import _auth_utils -from firebase_admin import _http_client -from firebase_admin import _utils - - -_TENANT_MGT_ATTRIBUTE = '_tenant_mgt' -_MAX_LIST_TENANTS_RESULTS = 100 -_DISPLAY_NAME_PATTERN = re.compile('^[a-zA-Z][a-zA-Z0-9-]{3,19}$') - - -__all__ = [ - 'ListTenantsPage', - 'Tenant', - 'TenantIdMismatchError', - 'TenantNotFoundError', - - 'auth_for_tenant', - 'create_tenant', - 'delete_tenant', - 'get_tenant', - 'list_tenants', - 'update_tenant', -] - - -TenantIdMismatchError = _auth_utils.TenantIdMismatchError -TenantNotFoundError = _auth_utils.TenantNotFoundError - - -def auth_for_tenant(tenant_id, app=None): - """Gets an Auth Client instance scoped to the given tenant ID. - - Args: - tenant_id: A tenant ID string. - app: An App instance (optional). - - Returns: - auth.Client: An ``auth.Client`` object. - - Raises: - ValueError: If the tenant ID is None, empty or not a string. - """ - tenant_mgt_service = _get_tenant_mgt_service(app) - return tenant_mgt_service.auth_for_tenant(tenant_id) - - -def get_tenant(tenant_id, app=None): - """Gets the tenant corresponding to the given ``tenant_id``. - - Args: - tenant_id: A tenant ID string. - app: An App instance (optional). - - Returns: - Tenant: A tenant object. - - Raises: - ValueError: If the tenant ID is None, empty or not a string. - TenantNotFoundError: If no tenant exists by the given ID. - FirebaseError: If an error occurs while retrieving the tenant. - """ - tenant_mgt_service = _get_tenant_mgt_service(app) - return tenant_mgt_service.get_tenant(tenant_id) - - -def create_tenant( - display_name, allow_password_sign_up=None, enable_email_link_sign_in=None, app=None): - """Creates a new tenant from the given options. - - Args: - display_name: Display name string for the new tenant. Must begin with a letter and contain - only letters, digits and hyphens. Length must be between 4 and 20. - allow_password_sign_up: A boolean indicating whether to enable or disable the email sign-in - provider (optional). - enable_email_link_sign_in: A boolean indicating whether to enable or disable email link - sign-in (optional). Disabling this makes the password required for email sign-in. - app: An App instance (optional). - - Returns: - Tenant: A tenant object. - - Raises: - ValueError: If any of the given arguments are invalid. - FirebaseError: If an error occurs while creating the tenant. - """ - tenant_mgt_service = _get_tenant_mgt_service(app) - return tenant_mgt_service.create_tenant( - display_name=display_name, allow_password_sign_up=allow_password_sign_up, - enable_email_link_sign_in=enable_email_link_sign_in) - - -def update_tenant( - tenant_id, display_name=None, allow_password_sign_up=None, enable_email_link_sign_in=None, - app=None): - """Updates an existing tenant with the given options. - - Args: - tenant_id: ID of the tenant to update. - display_name: Updated display name string for the tenant (optional). - allow_password_sign_up: A boolean indicating whether to enable or disable the email sign-in - provider. - enable_email_link_sign_in: A boolean indicating whether to enable or disable email link - sign-in. Disabling this makes the password required for email sign-in. - app: An App instance (optional). - - Returns: - Tenant: The updated tenant object. - - Raises: - ValueError: If any of the given arguments are invalid. - TenantNotFoundError: If no tenant exists by the given ID. - FirebaseError: If an error occurs while creating the tenant. - """ - tenant_mgt_service = _get_tenant_mgt_service(app) - return tenant_mgt_service.update_tenant( - tenant_id, display_name=display_name, allow_password_sign_up=allow_password_sign_up, - enable_email_link_sign_in=enable_email_link_sign_in) - - -def delete_tenant(tenant_id, app=None): - """Deletes the tenant corresponding to the given ``tenant_id``. - - Args: - tenant_id: A tenant ID string. - app: An App instance (optional). - - Raises: - ValueError: If the tenant ID is None, empty or not a string. - TenantNotFoundError: If no tenant exists by the given ID. - FirebaseError: If an error occurs while retrieving the tenant. - """ - tenant_mgt_service = _get_tenant_mgt_service(app) - tenant_mgt_service.delete_tenant(tenant_id) - - -def list_tenants(page_token=None, max_results=_MAX_LIST_TENANTS_RESULTS, app=None): - """Retrieves a page of tenants from a Firebase project. - - The ``page_token`` argument governs the starting point of the page. The ``max_results`` - argument governs the maximum number of tenants that may be included in the returned page. - This function never returns None. If there are no user accounts in the Firebase project, this - returns an empty page. - - Args: - page_token: A non-empty page token string, which indicates the starting point of the page - (optional). Defaults to ``None``, which will retrieve the first page of users. - max_results: A positive integer indicating the maximum number of users to include in the - returned page (optional). Defaults to 100, which is also the maximum number allowed. - app: An App instance (optional). - - Returns: - ListTenantsPage: A page of tenants. - - Raises: - ValueError: If ``max_results`` or ``page_token`` are invalid. - FirebaseError: If an error occurs while retrieving the user accounts. - """ - tenant_mgt_service = _get_tenant_mgt_service(app) - def download(page_token, max_results): - return tenant_mgt_service.list_tenants(page_token, max_results) - return ListTenantsPage(download, page_token, max_results) - - -def _get_tenant_mgt_service(app): - return _utils.get_app_service(app, _TENANT_MGT_ATTRIBUTE, _TenantManagementService) - - -class Tenant: - """Represents a tenant in a multi-tenant application. - - Multi-tenancy support requires Google Cloud Identity Platform (GCIP). To learn more about - GCIP including pricing and features, see https://cloud.google.com/identity-platform. - - Before multi-tenancy can be used in a Google Cloud Identity Platform project, tenants must be - enabled in that project via the Cloud Console UI. A Tenant instance provides information - such as the display name, tenant identifier and email authentication configuration. - """ - - def __init__(self, data): - if not isinstance(data, dict): - raise ValueError(f'Invalid data argument in Tenant constructor: {data}') - if not 'name' in data: - raise ValueError('Tenant response missing required keys.') - - self._data = data - - @property - def tenant_id(self): - name = self._data['name'] - return name.split('/')[-1] - - @property - def display_name(self): - return self._data.get('displayName') - - @property - def allow_password_sign_up(self): - return self._data.get('allowPasswordSignup', False) - - @property - def enable_email_link_sign_in(self): - return self._data.get('enableEmailLinkSignin', False) - - -class _TenantManagementService: - """Firebase tenant management service.""" - - TENANT_MGT_URL = 'https://identitytoolkit.googleapis.com/v2' - - def __init__(self, app): - credential = app.credential.get_credential() - version_header = f'Python/Admin/{firebase_admin.__version__}' - base_url = f'{self.TENANT_MGT_URL}/projects/{app.project_id}' - self.app = app - self.client = _http_client.JsonHttpClient( - credential=credential, base_url=base_url, headers={'X-Client-Version': version_header}) - self.tenant_clients = {} - self.lock = threading.RLock() - - def auth_for_tenant(self, tenant_id): - """Gets an Auth Client instance scoped to the given tenant ID.""" - if not isinstance(tenant_id, str) or not tenant_id: - raise ValueError( - f'Invalid tenant ID: {tenant_id}. Tenant ID must be a non-empty string.') - - with self.lock: - if tenant_id in self.tenant_clients: - return self.tenant_clients[tenant_id] - - client = auth.Client(self.app, tenant_id=tenant_id) - self.tenant_clients[tenant_id] = client - return client - - def get_tenant(self, tenant_id): - """Gets the tenant corresponding to the given ``tenant_id``.""" - if not isinstance(tenant_id, str) or not tenant_id: - raise ValueError( - f'Invalid tenant ID: {tenant_id}. Tenant ID must be a non-empty string.') - - try: - body = self.client.body('get', f'/tenants/{tenant_id}') - except requests.exceptions.RequestException as error: - raise _auth_utils.handle_auth_backend_error(error) - return Tenant(body) - - def create_tenant( - self, display_name, allow_password_sign_up=None, enable_email_link_sign_in=None): - """Creates a new tenant from the given parameters.""" - - payload = {'displayName': _validate_display_name(display_name)} - if allow_password_sign_up is not None: - payload['allowPasswordSignup'] = _auth_utils.validate_boolean( - allow_password_sign_up, 'allowPasswordSignup') - if enable_email_link_sign_in is not None: - payload['enableEmailLinkSignin'] = _auth_utils.validate_boolean( - enable_email_link_sign_in, 'enableEmailLinkSignin') - - try: - body = self.client.body('post', '/tenants', json=payload) - except requests.exceptions.RequestException as error: - raise _auth_utils.handle_auth_backend_error(error) - return Tenant(body) - - def update_tenant( - self, tenant_id, display_name=None, allow_password_sign_up=None, - enable_email_link_sign_in=None): - """Updates the specified tenant with the given parameters.""" - if not isinstance(tenant_id, str) or not tenant_id: - raise ValueError('Tenant ID must be a non-empty string.') - - payload = {} - if display_name is not None: - payload['displayName'] = _validate_display_name(display_name) - if allow_password_sign_up is not None: - payload['allowPasswordSignup'] = _auth_utils.validate_boolean( - allow_password_sign_up, 'allowPasswordSignup') - if enable_email_link_sign_in is not None: - payload['enableEmailLinkSignin'] = _auth_utils.validate_boolean( - enable_email_link_sign_in, 'enableEmailLinkSignin') - - if not payload: - raise ValueError('At least one parameter must be specified for update.') - - url = f'/tenants/{tenant_id}' - update_mask = ','.join(_auth_utils.build_update_mask(payload)) - params = f'updateMask={update_mask}' - try: - body = self.client.body('patch', url, json=payload, params=params) - except requests.exceptions.RequestException as error: - raise _auth_utils.handle_auth_backend_error(error) - return Tenant(body) - - def delete_tenant(self, tenant_id): - """Deletes the tenant corresponding to the given ``tenant_id``.""" - if not isinstance(tenant_id, str) or not tenant_id: - raise ValueError( - f'Invalid tenant ID: {tenant_id}. Tenant ID must be a non-empty string.') - - try: - self.client.request('delete', f'/tenants/{tenant_id}') - except requests.exceptions.RequestException as error: - raise _auth_utils.handle_auth_backend_error(error) - - def list_tenants(self, page_token=None, max_results=_MAX_LIST_TENANTS_RESULTS): - """Retrieves a batch of tenants.""" - if page_token is not None: - if not isinstance(page_token, str) or not page_token: - raise ValueError('Page token must be a non-empty string.') - if not isinstance(max_results, int): - raise ValueError('Max results must be an integer.') - if max_results < 1 or max_results > _MAX_LIST_TENANTS_RESULTS: - raise ValueError( - 'Max results must be a positive integer less than or equal to ' - f'{_MAX_LIST_TENANTS_RESULTS}.') - - payload = {'pageSize': max_results} - if page_token: - payload['pageToken'] = page_token - try: - return self.client.body('get', '/tenants', params=payload) - except requests.exceptions.RequestException as error: - raise _auth_utils.handle_auth_backend_error(error) - - -class ListTenantsPage: - """Represents a page of tenants fetched from a Firebase project. - - Provides methods for traversing tenants included in this page, as well as retrieving - subsequent pages of tenants. The iterator returned by ``iterate_all()`` can be used to iterate - through all tenants in the Firebase project starting from this page. - """ - - def __init__(self, download, page_token, max_results): - self._download = download - self._max_results = max_results - self._current = download(page_token, max_results) - - @property - def tenants(self): - """A list of ``ExportedUserRecord`` instances available in this page.""" - return [Tenant(data) for data in self._current.get('tenants', [])] - - @property - def next_page_token(self): - """Page token string for the next page (empty string indicates no more pages).""" - return self._current.get('nextPageToken', '') - - @property - def has_next_page(self): - """A boolean indicating whether more pages are available.""" - return bool(self.next_page_token) - - def get_next_page(self): - """Retrieves the next page of tenants, if available. - - Returns: - ListTenantsPage: Next page of tenants, or None if this is the last page. - """ - if self.has_next_page: - return ListTenantsPage(self._download, self.next_page_token, self._max_results) - return None - - def iterate_all(self): - """Retrieves an iterator for tenants. - - Returned iterator will iterate through all the tenants in the Firebase project - starting from this page. The iterator will never buffer more than one page of tenants - in memory at a time. - - Returns: - iterator: An iterator of Tenant instances. - """ - return _TenantIterator(self) - - -class _TenantIterator: - """An iterator that allows iterating over tenants. - - This implementation loads a page of tenants into memory, and iterates on them. When the whole - page has been traversed, it loads another page. This class never keeps more than one page - of entries in memory. - """ - - def __init__(self, current_page): - if not current_page: - raise ValueError('Current page must not be None.') - self._current_page = current_page - self._index = 0 - - def __next__(self): - if self._index == len(self._current_page.tenants): - if self._current_page.has_next_page: - self._current_page = self._current_page.get_next_page() - self._index = 0 - if self._index < len(self._current_page.tenants): - result = self._current_page.tenants[self._index] - self._index += 1 - return result - raise StopIteration - - def __iter__(self): - return self - - -def _validate_display_name(display_name): - if not isinstance(display_name, str): - raise ValueError('Invalid type for displayName') - if not _DISPLAY_NAME_PATTERN.search(display_name): - raise ValueError( - 'displayName must start with a letter and only consist of letters, digits and ' - 'hyphens with 4-20 characters.') - return display_name diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__init__.py b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__init__.py deleted file mode 100644 index eaade3e..0000000 --- a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__init__.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Utilities for Google Media Downloads and Resumable Uploads. - -This package has some general purposes modules, e.g. -:mod:`~google.resumable_media.common`, but the majority of the -public interface will be contained in subpackages. - -=========== -Subpackages -=========== - -Each subpackage is tailored to a specific transport library: - -* the :mod:`~google.resumable_media.requests` subpackage uses the ``requests`` - transport library. - -.. _requests: http://docs.python-requests.org/ - -========== -Installing -========== - -To install with `pip`_: - -.. code-block:: console - - $ pip install --upgrade google-resumable-media - -.. _pip: https://pip.pypa.io/ -""" - -from google.resumable_media.common import DataCorruption -from google.resumable_media.common import InvalidResponse -from google.resumable_media.common import PERMANENT_REDIRECT -from google.resumable_media.common import RetryStrategy -from google.resumable_media.common import TOO_MANY_REQUESTS -from google.resumable_media.common import UPLOAD_CHUNK_SIZE - - -__all__ = [ - "DataCorruption", - "InvalidResponse", - "PERMANENT_REDIRECT", - "RetryStrategy", - "TOO_MANY_REQUESTS", - "UPLOAD_CHUNK_SIZE", -] diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 9eef93c..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__pycache__/_download.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__pycache__/_download.cpython-312.pyc deleted file mode 100644 index ceb875c..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__pycache__/_download.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__pycache__/_helpers.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__pycache__/_helpers.cpython-312.pyc deleted file mode 100644 index 9b1bb6b..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__pycache__/_helpers.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__pycache__/_upload.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__pycache__/_upload.cpython-312.pyc deleted file mode 100644 index 3f9eb20..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/__pycache__/_upload.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/_download.py b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/_download.py deleted file mode 100644 index 1966f33..0000000 --- a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/_download.py +++ /dev/null @@ -1,550 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Virtual bases classes for downloading media from Google APIs.""" - -import http.client -import re - -from google._async_resumable_media import _helpers -from google.resumable_media import common - - -_CONTENT_RANGE_RE = re.compile( - r"bytes (?P\d+)-(?P\d+)/(?P\d+)", - flags=re.IGNORECASE, -) -_ACCEPTABLE_STATUS_CODES = (http.client.OK, http.client.PARTIAL_CONTENT) -_GET = "GET" -_ZERO_CONTENT_RANGE_HEADER = "bytes */0" - - -class DownloadBase(object): - """Base class for download helpers. - - Defines core shared behavior across different download types. - - Args: - media_url (str): The URL containing the media to be downloaded. - stream (IO[bytes]): A write-able stream (i.e. file-like object) that - the downloaded resource can be written to. - start (int): The first byte in a range to be downloaded. - end (int): The last byte in a range to be downloaded. - headers (Optional[Mapping[str, str]]): Extra headers that should - be sent with the request, e.g. headers for encrypted data. - - Attributes: - media_url (str): The URL containing the media to be downloaded. - start (Optional[int]): The first byte in a range to be downloaded. - end (Optional[int]): The last byte in a range to be downloaded. - """ - - def __init__(self, media_url, stream=None, start=None, end=None, headers=None): - self.media_url = media_url - self._stream = stream - self.start = start - self.end = end - if headers is None: - headers = {} - self._headers = headers - self._finished = False - self._retry_strategy = common.RetryStrategy() - - @property - def finished(self): - """bool: Flag indicating if the download has completed.""" - return self._finished - - @staticmethod - def _get_status_code(response): - """Access the status code from an HTTP response. - - Args: - response (object): The HTTP response object. - - Raises: - NotImplementedError: Always, since virtual. - """ - raise NotImplementedError("This implementation is virtual.") - - @staticmethod - def _get_headers(response): - """Access the headers from an HTTP response. - - Args: - response (object): The HTTP response object. - - Raises: - NotImplementedError: Always, since virtual. - """ - raise NotImplementedError("This implementation is virtual.") - - @staticmethod - def _get_body(response): - """Access the response body from an HTTP response. - - Args: - response (object): The HTTP response object. - - Raises: - NotImplementedError: Always, since virtual. - """ - raise NotImplementedError("This implementation is virtual.") - - -class Download(DownloadBase): - """Helper to manage downloading a resource from a Google API. - - "Slices" of the resource can be retrieved by specifying a range - with ``start`` and / or ``end``. However, in typical usage, neither - ``start`` nor ``end`` is expected to be provided. - - Args: - media_url (str): The URL containing the media to be downloaded. - stream (IO[bytes]): A write-able stream (i.e. file-like object) that - the downloaded resource can be written to. - start (int): The first byte in a range to be downloaded. If not - provided, but ``end`` is provided, will download from the - beginning to ``end`` of the media. - end (int): The last byte in a range to be downloaded. If not - provided, but ``start`` is provided, will download from the - ``start`` to the end of the media. - headers (Optional[Mapping[str, str]]): Extra headers that should - be sent with the request, e.g. headers for encrypted data. - checksum Optional([str]): The type of checksum to compute to verify - the integrity of the object. The response headers must contain - a checksum of the requested type. If the headers lack an - appropriate checksum (for instance in the case of transcoded or - ranged downloads where the remote service does not know the - correct checksum) an INFO-level log will be emitted. Supported - values are "md5", "crc32c" and None. - """ - - def __init__( - self, media_url, stream=None, start=None, end=None, headers=None, checksum="md5" - ): - super(Download, self).__init__( - media_url, stream=stream, start=start, end=end, headers=headers - ) - self.checksum = checksum - - def _prepare_request(self): - """Prepare the contents of an HTTP request. - - This is everything that must be done before a request that doesn't - require network I/O (or other I/O). This is based on the `sans-I/O`_ - philosophy. - - Returns: - Tuple[str, str, NoneType, Mapping[str, str]]: The quadruple - - * HTTP verb for the request (always GET) - * the URL for the request - * the body of the request (always :data:`None`) - * headers for the request - - Raises: - ValueError: If the current :class:`Download` has already - finished. - - .. _sans-I/O: https://sans-io.readthedocs.io/ - """ - if self.finished: - raise ValueError("A download can only be used once.") - - add_bytes_range(self.start, self.end, self._headers) - return _GET, self.media_url, None, self._headers - - def _process_response(self, response): - """Process the response from an HTTP request. - - This is everything that must be done after a request that doesn't - require network I/O (or other I/O). This is based on the `sans-I/O`_ - philosophy. - - Args: - response (object): The HTTP response object. - - .. _sans-I/O: https://sans-io.readthedocs.io/ - """ - # Tombstone the current Download so it cannot be used again. - self._finished = True - _helpers.require_status_code( - response, _ACCEPTABLE_STATUS_CODES, self._get_status_code - ) - - def consume(self, transport, timeout=None): - """Consume the resource to be downloaded. - - If a ``stream`` is attached to this download, then the downloaded - resource will be written to the stream. - - Args: - transport (object): An object which can make authenticated - requests. - timeout (Optional[Union[float, aiohttp.ClientTimeout]]): - The number of seconds to wait for the server response. - Depending on the retry strategy, a request may be repeated - several times using the same timeout each time. - Can also be passed as an `aiohttp.ClientTimeout` object. - - Raises: - NotImplementedError: Always, since virtual. - """ - raise NotImplementedError("This implementation is virtual.") - - -class ChunkedDownload(DownloadBase): - """Download a resource in chunks from a Google API. - - Args: - media_url (str): The URL containing the media to be downloaded. - chunk_size (int): The number of bytes to be retrieved in each - request. - stream (IO[bytes]): A write-able stream (i.e. file-like object) that - will be used to concatenate chunks of the resource as they are - downloaded. - start (int): The first byte in a range to be downloaded. If not - provided, defaults to ``0``. - end (int): The last byte in a range to be downloaded. If not - provided, will download to the end of the media. - headers (Optional[Mapping[str, str]]): Extra headers that should - be sent with each request, e.g. headers for data encryption - key headers. - - Attributes: - media_url (str): The URL containing the media to be downloaded. - start (Optional[int]): The first byte in a range to be downloaded. - end (Optional[int]): The last byte in a range to be downloaded. - chunk_size (int): The number of bytes to be retrieved in each request. - - Raises: - ValueError: If ``start`` is negative. - """ - - def __init__(self, media_url, chunk_size, stream, start=0, end=None, headers=None): - if start < 0: - raise ValueError( - "On a chunked download the starting value cannot be negative." - ) - super(ChunkedDownload, self).__init__( - media_url, stream=stream, start=start, end=end, headers=headers - ) - self.chunk_size = chunk_size - self._bytes_downloaded = 0 - self._total_bytes = None - self._invalid = False - - @property - def bytes_downloaded(self): - """int: Number of bytes that have been downloaded.""" - return self._bytes_downloaded - - @property - def total_bytes(self): - """Optional[int]: The total number of bytes to be downloaded.""" - return self._total_bytes - - @property - def invalid(self): - """bool: Indicates if the download is in an invalid state. - - This will occur if a call to :meth:`consume_next_chunk` fails. - """ - return self._invalid - - def _get_byte_range(self): - """Determines the byte range for the next request. - - Returns: - Tuple[int, int]: The pair of begin and end byte for the next - chunked request. - """ - curr_start = self.start + self.bytes_downloaded - curr_end = curr_start + self.chunk_size - 1 - # Make sure ``curr_end`` does not exceed ``end``. - if self.end is not None: - curr_end = min(curr_end, self.end) - # Make sure ``curr_end`` does not exceed ``total_bytes - 1``. - if self.total_bytes is not None: - curr_end = min(curr_end, self.total_bytes - 1) - return curr_start, curr_end - - def _prepare_request(self): - """Prepare the contents of an HTTP request. - - This is everything that must be done before a request that doesn't - require network I/O (or other I/O). This is based on the `sans-I/O`_ - philosophy. - - .. note: - - This method will be used multiple times, so ``headers`` will - be mutated in between requests. However, we don't make a copy - since the same keys are being updated. - - Returns: - Tuple[str, str, NoneType, Mapping[str, str]]: The quadruple - - * HTTP verb for the request (always GET) - * the URL for the request - * the body of the request (always :data:`None`) - * headers for the request - - Raises: - ValueError: If the current download has finished. - ValueError: If the current download is invalid. - - .. _sans-I/O: https://sans-io.readthedocs.io/ - """ - if self.finished: - raise ValueError("Download has finished.") - if self.invalid: - raise ValueError("Download is invalid and cannot be re-used.") - - curr_start, curr_end = self._get_byte_range() - add_bytes_range(curr_start, curr_end, self._headers) - return _GET, self.media_url, None, self._headers - - def _make_invalid(self): - """Simple setter for ``invalid``. - - This is intended to be passed along as a callback to helpers that - raise an exception so they can mark this instance as invalid before - raising. - """ - self._invalid = True - - async def _process_response(self, response): - """Process the response from an HTTP request. - - This is everything that must be done after a request that doesn't - require network I/O. This is based on the `sans-I/O`_ philosophy. - - For the time being, this **does require** some form of I/O to write - a chunk to ``stream``. However, this will (almost) certainly not be - network I/O. - - Updates the current state after consuming a chunk. First, - increments ``bytes_downloaded`` by the number of bytes in the - ``content-length`` header. - - If ``total_bytes`` is already set, this assumes (but does not check) - that we already have the correct value and doesn't bother to check - that it agrees with the headers. - - We expect the **total** length to be in the ``content-range`` header, - but this header is only present on requests which sent the ``range`` - header. This response header should be of the form - ``bytes {start}-{end}/{total}`` and ``{end} - {start} + 1`` - should be the same as the ``Content-Length``. - - Args: - response (object): The HTTP response object (need headers). - - Raises: - ~google.resumable_media.common.InvalidResponse: If the number - of bytes in the body doesn't match the content length header. - - .. _sans-I/O: https://sans-io.readthedocs.io/ - """ - # Verify the response before updating the current instance. - if _check_for_zero_content_range( - response, self._get_status_code, self._get_headers - ): - self._finished = True - return - - _helpers.require_status_code( - response, - _ACCEPTABLE_STATUS_CODES, - self._get_status_code, - callback=self._make_invalid, - ) - headers = self._get_headers(response) - response_body = await self._get_body(response) - - start_byte, end_byte, total_bytes = get_range_info( - response, self._get_headers, callback=self._make_invalid - ) - - transfer_encoding = headers.get("transfer-encoding") - - if transfer_encoding is None: - content_length = _helpers.header_required( - response, - "content-length", - self._get_headers, - callback=self._make_invalid, - ) - num_bytes = int(content_length) - - if len(response_body) != num_bytes: - self._make_invalid() - raise common.InvalidResponse( - response, - "Response is different size than content-length", - "Expected", - num_bytes, - "Received", - len(response_body), - ) - else: - # 'content-length' header not allowed with chunked encoding. - num_bytes = end_byte - start_byte + 1 - - # First update ``bytes_downloaded``. - self._bytes_downloaded += num_bytes - # If the end byte is past ``end`` or ``total_bytes - 1`` we are done. - if self.end is not None and end_byte >= self.end: - self._finished = True - elif end_byte >= total_bytes - 1: - self._finished = True - # NOTE: We only use ``total_bytes`` if not already known. - if self.total_bytes is None: - self._total_bytes = total_bytes - # Write the response body to the stream. - self._stream.write(response_body) - - def consume_next_chunk(self, transport, timeout=None): - """Consume the next chunk of the resource to be downloaded. - - Args: - transport (object): An object which can make authenticated - requests. - timeout (Optional[Union[float, aiohttp.ClientTimeout]]): - The number of seconds to wait for the server response. - Depending on the retry strategy, a request may be repeated - several times using the same timeout each time. - Can also be passed as an `aiohttp.ClientTimeout` object. - Raises: - NotImplementedError: Always, since virtual. - """ - raise NotImplementedError("This implementation is virtual.") - - -def add_bytes_range(start, end, headers): - """Add a bytes range to a header dictionary. - - Some possible inputs and the corresponding bytes ranges:: - - >>> headers = {} - >>> add_bytes_range(None, None, headers) - >>> headers - {} - >>> add_bytes_range(500, 999, headers) - >>> headers['range'] - 'bytes=500-999' - >>> add_bytes_range(None, 499, headers) - >>> headers['range'] - 'bytes=0-499' - >>> add_bytes_range(-500, None, headers) - >>> headers['range'] - 'bytes=-500' - >>> add_bytes_range(9500, None, headers) - >>> headers['range'] - 'bytes=9500-' - - Args: - start (Optional[int]): The first byte in a range. Can be zero, - positive, negative or :data:`None`. - end (Optional[int]): The last byte in a range. Assumed to be - positive. - headers (Mapping[str, str]): A headers mapping which can have the - bytes range added if at least one of ``start`` or ``end`` - is not :data:`None`. - """ - if start is None: - if end is None: - # No range to add. - return - else: - # NOTE: This assumes ``end`` is non-negative. - bytes_range = "0-{:d}".format(end) - else: - if end is None: - if start < 0: - bytes_range = "{:d}".format(start) - else: - bytes_range = "{:d}-".format(start) - else: - # NOTE: This is invalid if ``start < 0``. - bytes_range = "{:d}-{:d}".format(start, end) - - headers[_helpers.RANGE_HEADER] = "bytes=" + bytes_range - - -def get_range_info(response, get_headers, callback=_helpers.do_nothing): - """Get the start, end and total bytes from a content range header. - - Args: - response (object): An HTTP response object. - get_headers (Callable[Any, Mapping[str, str]]): Helper to get headers - from an HTTP response. - callback (Optional[Callable]): A callback that takes no arguments, - to be executed when an exception is being raised. - - Returns: - Tuple[int, int, int]: The start byte, end byte and total bytes. - - Raises: - ~google.resumable_media.common.InvalidResponse: If the - ``Content-Range`` header is not of the form - ``bytes {start}-{end}/{total}``. - """ - content_range = _helpers.header_required( - response, _helpers.CONTENT_RANGE_HEADER, get_headers, callback=callback - ) - match = _CONTENT_RANGE_RE.match(content_range) - if match is None: - callback() - raise common.InvalidResponse( - response, - "Unexpected content-range header", - content_range, - 'Expected to be of the form "bytes {start}-{end}/{total}"', - ) - - return ( - int(match.group("start_byte")), - int(match.group("end_byte")), - int(match.group("total_bytes")), - ) - - -def _check_for_zero_content_range(response, get_status_code, get_headers): - """Validate if response status code is 416 and content range is zero. - - This is the special case for handling zero bytes files. - - Args: - response (object): An HTTP response object. - get_status_code (Callable[Any, int]): Helper to get a status code - from a response. - get_headers (Callable[Any, Mapping[str, str]]): Helper to get headers - from an HTTP response. - - Returns: - bool: True if content range total bytes is zero, false otherwise. - """ - if get_status_code(response) == http.client.REQUESTED_RANGE_NOT_SATISFIABLE: - content_range = _helpers.header_required( - response, - _helpers.CONTENT_RANGE_HEADER, - get_headers, - callback=_helpers.do_nothing, - ) - if content_range == _ZERO_CONTENT_RANGE_HEADER: - return True - return False diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/_helpers.py b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/_helpers.py deleted file mode 100644 index 8cf0f2e..0000000 --- a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/_helpers.py +++ /dev/null @@ -1,197 +0,0 @@ -# Copyright 2020 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Shared utilities used by both downloads and uploads.""" - -import logging -import random -import time - - -from google.resumable_media import common - - -RANGE_HEADER = "range" -CONTENT_RANGE_HEADER = "content-range" - -_SLOW_CRC32C_WARNING = ( - "Currently using crcmod in pure python form. This is a slow " - "implementation. Python 3 has a faster implementation, `google-crc32c`, " - "which will be used if it is installed." -) -_HASH_HEADER = "x-goog-hash" -_MISSING_CHECKSUM = """\ -No {checksum_type} checksum was returned from the service while downloading {} -(which happens for composite objects), so client-side content integrity -checking is not being performed.""" -_LOGGER = logging.getLogger(__name__) - - -def do_nothing(): - """Simple default callback.""" - - -def header_required(response, name, get_headers, callback=do_nothing): - """Checks that a specific header is in a headers dictionary. - - Args: - response (object): An HTTP response object, expected to have a - ``headers`` attribute that is a ``Mapping[str, str]``. - name (str): The name of a required header. - get_headers (Callable[Any, Mapping[str, str]]): Helper to get headers - from an HTTP response. - callback (Optional[Callable]): A callback that takes no arguments, - to be executed when an exception is being raised. - - Returns: - str: The desired header. - - Raises: - ~google.resumable_media.common.InvalidResponse: If the header - is missing. - """ - headers = get_headers(response) - if name not in headers: - callback() - raise common.InvalidResponse( - response, "Response headers must contain header", name - ) - - return headers[name] - - -def require_status_code(response, status_codes, get_status_code, callback=do_nothing): - """Require a response has a status code among a list. - - Args: - response (object): The HTTP response object. - status_codes (tuple): The acceptable status codes. - get_status_code (Callable[Any, int]): Helper to get a status code - from a response. - callback (Optional[Callable]): A callback that takes no arguments, - to be executed when an exception is being raised. - - Returns: - int: The status code. - - Raises: - ~google.resumable_media.common.InvalidResponse: If the status code - is not one of the values in ``status_codes``. - """ - status_code = get_status_code(response) - if status_code not in status_codes: - callback() - raise common.InvalidResponse( - response, - "Request failed with status code", - status_code, - "Expected one of", - *status_codes, - ) - return status_code - - -def calculate_retry_wait(base_wait, max_sleep): - """Calculate the amount of time to wait before a retry attempt. - - Wait time grows exponentially with the number of attempts, until - ``max_sleep``. - - A random amount of jitter (between 0 and 1 seconds) is added to spread out - retry attempts from different clients. - - Args: - base_wait (float): The "base" wait time (i.e. without any jitter) - that will be doubled until it reaches the maximum sleep. - max_sleep (float): Maximum value that a sleep time is allowed to be. - - Returns: - Tuple[float, float]: The new base wait time as well as the wait time - to be applied (with a random amount of jitter between 0 and 1 seconds - added). - """ - new_base_wait = 2.0 * base_wait - if new_base_wait > max_sleep: - new_base_wait = max_sleep - - jitter_ms = random.randint(0, 1000) - return new_base_wait, new_base_wait + 0.001 * jitter_ms - - -async def wait_and_retry(func, get_status_code, retry_strategy): - """Attempts to retry a call to ``func`` until success. - - Expects ``func`` to return an HTTP response and uses ``get_status_code`` - to check if the response is retry-able. - - Will retry until :meth:`~.RetryStrategy.retry_allowed` (on the current - ``retry_strategy``) returns :data:`False`. Uses - :func:`calculate_retry_wait` to double the wait time (with jitter) after - each attempt. - - Args: - func (Callable): A callable that takes no arguments and produces - an HTTP response which will be checked as retry-able. - get_status_code (Callable[Any, int]): Helper to get a status code - from a response. - retry_strategy (~google.resumable_media.common.RetryStrategy): The - strategy to use if the request fails and must be retried. - - Returns: - object: The return value of ``func``. - """ - - total_sleep = 0.0 - num_retries = 0 - base_wait = 0.5 # When doubled will give 1.0 - - while True: # return on success or when retries exhausted. - error = None - try: - response = await func() - except ConnectionError as e: - error = e - else: - if get_status_code(response) not in common.RETRYABLE: - return response - - if not retry_strategy.retry_allowed(total_sleep, num_retries): - # Retries are exhausted and no acceptable response was received. Raise the - # retriable_error or return the unacceptable response. - if error: - raise error - - return response - - base_wait, wait_time = calculate_retry_wait(base_wait, retry_strategy.max_sleep) - - num_retries += 1 - total_sleep += wait_time - time.sleep(wait_time) - - -class _DoNothingHash(object): - """Do-nothing hash object. - - Intended as a stand-in for ``hashlib.md5`` or a crc32c checksum - implementation in cases where it isn't necessary to compute the hash. - """ - - def update(self, unused_chunk): - """Do-nothing ``update`` method. - - Intended to match the interface of ``hashlib.md5`` and other checksums. - Args: - unused_chunk (bytes): A chunk of data. - """ diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/_upload.py b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/_upload.py deleted file mode 100644 index 9f5b0de..0000000 --- a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/_upload.py +++ /dev/null @@ -1,976 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Virtual bases classes for uploading media via Google APIs. - -Supported here are: - -* simple (media) uploads -* multipart uploads that contain both metadata and a small file as payload -* resumable uploads (with metadata as well) -""" - -import http.client -import json -import os -import random -import sys - -from google import _async_resumable_media -from google._async_resumable_media import _helpers -from google.resumable_media import _helpers as sync_helpers -from google.resumable_media import _upload as sync_upload -from google.resumable_media import common - - -from google.resumable_media._upload import ( - _CONTENT_TYPE_HEADER, - _CONTENT_RANGE_TEMPLATE, - _RANGE_UNKNOWN_TEMPLATE, - _EMPTY_RANGE_TEMPLATE, - _BOUNDARY_FORMAT, - _MULTIPART_SEP, - _CRLF, - _MULTIPART_BEGIN, - _RELATED_HEADER, - _BYTES_RANGE_RE, - _STREAM_ERROR_TEMPLATE, - _POST, - _PUT, - _UPLOAD_CHECKSUM_MISMATCH_MESSAGE, - _UPLOAD_METADATA_NO_APPROPRIATE_CHECKSUM_MESSAGE, -) - - -class UploadBase(object): - """Base class for upload helpers. - - Defines core shared behavior across different upload types. - - Args: - upload_url (str): The URL where the content will be uploaded. - headers (Optional[Mapping[str, str]]): Extra headers that should - be sent with the request, e.g. headers for encrypted data. - - Attributes: - upload_url (str): The URL where the content will be uploaded. - """ - - def __init__(self, upload_url, headers=None): - self.upload_url = upload_url - if headers is None: - headers = {} - self._headers = headers - self._finished = False - self._retry_strategy = common.RetryStrategy() - - @property - def finished(self): - """bool: Flag indicating if the upload has completed.""" - return self._finished - - def _process_response(self, response): - """Process the response from an HTTP request. - - This is everything that must be done after a request that doesn't - require network I/O (or other I/O). This is based on the `sans-I/O`_ - philosophy. - - Args: - response (object): The HTTP response object. - - Raises: - ~google.resumable_media.common.InvalidResponse: If the status - code is not 200. - - .. _sans-I/O: https://sans-io.readthedocs.io/ - """ - # Tombstone the current upload so it cannot be used again (in either - # failure or success). - self._finished = True - _helpers.require_status_code(response, (http.client.OK,), self._get_status_code) - - @staticmethod - def _get_status_code(response): - """Access the status code from an HTTP response. - - Args: - response (object): The HTTP response object. - - Raises: - NotImplementedError: Always, since virtual. - """ - raise NotImplementedError("This implementation is virtual.") - - @staticmethod - def _get_headers(response): - """Access the headers from an HTTP response. - - Args: - response (object): The HTTP response object. - - Raises: - NotImplementedError: Always, since virtual. - """ - raise NotImplementedError("This implementation is virtual.") - - @staticmethod - def _get_body(response): - """Access the response body from an HTTP response. - - Args: - response (object): The HTTP response object. - - Raises: - NotImplementedError: Always, since virtual. - """ - raise NotImplementedError("This implementation is virtual.") - - -class SimpleUpload(UploadBase): - """Upload a resource to a Google API. - - A **simple** media upload sends no metadata and completes the upload - in a single request. - - Args: - upload_url (str): The URL where the content will be uploaded. - headers (Optional[Mapping[str, str]]): Extra headers that should - be sent with the request, e.g. headers for encrypted data. - - Attributes: - upload_url (str): The URL where the content will be uploaded. - """ - - def _prepare_request(self, data, content_type): - """Prepare the contents of an HTTP request. - - This is everything that must be done before a request that doesn't - require network I/O (or other I/O). This is based on the `sans-I/O`_ - philosophy. - - .. note: - - This method will be used only once, so ``headers`` will be - mutated by having a new key added to it. - - Args: - data (bytes): The resource content to be uploaded. - content_type (str): The content type for the request. - - Returns: - Tuple[str, str, bytes, Mapping[str, str]]: The quadruple - - * HTTP verb for the request (always POST) - * the URL for the request - * the body of the request - * headers for the request - - Raises: - ValueError: If the current upload has already finished. - TypeError: If ``data`` isn't bytes. - - .. _sans-I/O: https://sans-io.readthedocs.io/ - """ - if self.finished: - raise ValueError("An upload can only be used once.") - - if not isinstance(data, bytes): - raise TypeError("`data` must be bytes, received", type(data)) - self._headers[_CONTENT_TYPE_HEADER] = content_type - return _POST, self.upload_url, data, self._headers - - def transmit(self, transport, data, content_type, timeout=None): - """Transmit the resource to be uploaded. - - Args: - transport (object): An object which can make authenticated - requests. - data (bytes): The resource content to be uploaded. - content_type (str): The content type of the resource, e.g. a JPEG - image has content type ``image/jpeg``. - timeout (Optional[Union[float, aiohttp.ClientTimeout]]): - The number of seconds to wait for the server response. - Depending on the retry strategy, a request may be repeated - several times using the same timeout each time. - Can also be passed as an `aiohttp.ClientTimeout` object. - - Raises: - NotImplementedError: Always, since virtual. - """ - raise NotImplementedError("This implementation is virtual.") - - -class MultipartUpload(UploadBase): - """Upload a resource with metadata to a Google API. - - A **multipart** upload sends both metadata and the resource in a single - (multipart) request. - - Args: - upload_url (str): The URL where the content will be uploaded. - headers (Optional[Mapping[str, str]]): Extra headers that should - be sent with the request, e.g. headers for encrypted data. - checksum Optional([str]): The type of checksum to compute to verify - the integrity of the object. The request metadata will be amended - to include the computed value. Using this option will override a - manually-set checksum value. Supported values are "md5", "crc32c" - and None. The default is None. - - Attributes: - upload_url (str): The URL where the content will be uploaded. - """ - - def __init__(self, upload_url, headers=None, checksum=None): - super(MultipartUpload, self).__init__(upload_url, headers=headers) - self._checksum_type = checksum - - def _prepare_request(self, data, metadata, content_type): - """Prepare the contents of an HTTP request. - - This is everything that must be done before a request that doesn't - require network I/O (or other I/O). This is based on the `sans-I/O`_ - philosophy. - - .. note: - - This method will be used only once, so ``headers`` will be - mutated by having a new key added to it. - - Args: - data (bytes): The resource content to be uploaded. - metadata (Mapping[str, str]): The resource metadata, such as an - ACL list. - content_type (str): The content type of the resource, e.g. a JPEG - image has content type ``image/jpeg``. - - Returns: - Tuple[str, str, bytes, Mapping[str, str]]: The quadruple - - * HTTP verb for the request (always POST) - * the URL for the request - * the body of the request - * headers for the request - - Raises: - ValueError: If the current upload has already finished. - TypeError: If ``data`` isn't bytes. - - .. _sans-I/O: https://sans-io.readthedocs.io/ - """ - if self.finished: - raise ValueError("An upload can only be used once.") - - if not isinstance(data, bytes): - raise TypeError("`data` must be bytes, received", type(data)) - - checksum_object = sync_helpers._get_checksum_object(self._checksum_type) - - if checksum_object is not None: - checksum_object.update(data) - actual_checksum = sync_helpers.prepare_checksum_digest( - checksum_object.digest() - ) - metadata_key = sync_helpers._get_metadata_key(self._checksum_type) - metadata[metadata_key] = actual_checksum - - content, multipart_boundary = construct_multipart_request( - data, metadata, content_type - ) - multipart_content_type = _RELATED_HEADER + multipart_boundary + b'"' - - self._headers[_CONTENT_TYPE_HEADER] = multipart_content_type - - return _POST, self.upload_url, content, self._headers - - def transmit(self, transport, data, metadata, content_type, timeout=None): - """Transmit the resource to be uploaded. - - Args: - transport (object): An object which can make authenticated - requests. - data (bytes): The resource content to be uploaded. - metadata (Mapping[str, str]): The resource metadata, such as an - ACL list. - content_type (str): The content type of the resource, e.g. a JPEG - image has content type ``image/jpeg``. - timeout (Optional[Union[float, aiohttp.ClientTimeout]]): - The number of seconds to wait for the server response. - Depending on the retry strategy, a request may be repeated - several times using the same timeout each time. - Can also be passed as an `aiohttp.ClientTimeout` object. - - Raises: - NotImplementedError: Always, since virtual. - """ - raise NotImplementedError("This implementation is virtual.") - - -class ResumableUpload(UploadBase, sync_upload.ResumableUpload): - """Initiate and fulfill a resumable upload to a Google API. - - A **resumable** upload sends an initial request with the resource metadata - and then gets assigned an upload ID / upload URL to send bytes to. - Using the upload URL, the upload is then done in chunks (determined by - the user) until all bytes have been uploaded. - - Args: - upload_url (str): The URL where the resumable upload will be initiated. - chunk_size (int): The size of each chunk used to upload the resource. - headers (Optional[Mapping[str, str]]): Extra headers that should - be sent with the :meth:`initiate` request, e.g. headers for - encrypted data. These **will not** be sent with - :meth:`transmit_next_chunk` or :meth:`recover` requests. - checksum Optional([str]): The type of checksum to compute to verify - the integrity of the object. After the upload is complete, the - server-computed checksum of the resulting object will be read - and google.resumable_media.common.DataCorruption will be raised on - a mismatch. The corrupted file will not be deleted from the remote - host automatically. Supported values are "md5", "crc32c" and None. - The default is None. - - Attributes: - upload_url (str): The URL where the content will be uploaded. - - Raises: - ValueError: If ``chunk_size`` is not a multiple of - :data:`.UPLOAD_CHUNK_SIZE`. - """ - - def __init__(self, upload_url, chunk_size, checksum=None, headers=None): - super(ResumableUpload, self).__init__(upload_url, headers=headers) - if chunk_size % _async_resumable_media.UPLOAD_CHUNK_SIZE != 0: - raise ValueError( - "{} KB must divide chunk size".format( - _async_resumable_media.UPLOAD_CHUNK_SIZE / 1024 - ) - ) - self._chunk_size = chunk_size - self._stream = None - self._content_type = None - self._bytes_uploaded = 0 - self._bytes_checksummed = 0 - self._checksum_type = checksum - self._checksum_object = None - self._total_bytes = None - self._resumable_url = None - self._invalid = False - - @property - def invalid(self): - """bool: Indicates if the upload is in an invalid state. - - This will occur if a call to :meth:`transmit_next_chunk` fails. - To recover from such a failure, call :meth:`recover`. - """ - return self._invalid - - @property - def chunk_size(self): - """int: The size of each chunk used to upload the resource.""" - return self._chunk_size - - @property - def resumable_url(self): - """Optional[str]: The URL of the in-progress resumable upload.""" - return self._resumable_url - - @property - def bytes_uploaded(self): - """int: Number of bytes that have been uploaded.""" - return self._bytes_uploaded - - @property - def total_bytes(self): - """Optional[int]: The total number of bytes to be uploaded. - - If this upload is initiated (via :meth:`initiate`) with - ``stream_final=True``, this value will be populated based on the size - of the ``stream`` being uploaded. (By default ``stream_final=True``.) - - If this upload is initiated with ``stream_final=False``, - :attr:`total_bytes` will be :data:`None` since it cannot be - determined from the stream. - """ - return self._total_bytes - - def _prepare_initiate_request( - self, stream, metadata, content_type, total_bytes=None, stream_final=True - ): - """Prepare the contents of HTTP request to initiate upload. - - This is everything that must be done before a request that doesn't - require network I/O (or other I/O). This is based on the `sans-I/O`_ - philosophy. - - Args: - stream (IO[bytes]): The stream (i.e. file-like object) that will - be uploaded. The stream **must** be at the beginning (i.e. - ``stream.tell() == 0``). - metadata (Mapping[str, str]): The resource metadata, such as an - ACL list. - content_type (str): The content type of the resource, e.g. a JPEG - image has content type ``image/jpeg``. - total_bytes (Optional[int]): The total number of bytes to be - uploaded. If specified, the upload size **will not** be - determined from the stream (even if ``stream_final=True``). - stream_final (Optional[bool]): Indicates if the ``stream`` is - "final" (i.e. no more bytes will be added to it). In this case - we determine the upload size from the size of the stream. If - ``total_bytes`` is passed, this argument will be ignored. - - Returns: - Tuple[str, str, bytes, Mapping[str, str]]: The quadruple - - * HTTP verb for the request (always POST) - * the URL for the request - * the body of the request - * headers for the request - - Raises: - ValueError: If the current upload has already been initiated. - ValueError: If ``stream`` is not at the beginning. - - .. _sans-I/O: https://sans-io.readthedocs.io/ - """ - if self.resumable_url is not None: - raise ValueError("This upload has already been initiated.") - if stream.tell() != 0: - raise ValueError("Stream must be at beginning.") - - self._stream = stream - self._content_type = content_type - headers = { - _CONTENT_TYPE_HEADER: "application/json; charset=UTF-8", - "x-upload-content-type": content_type, - } - # Set the total bytes if possible. - if total_bytes is not None: - self._total_bytes = total_bytes - elif stream_final: - self._total_bytes = get_total_bytes(stream) - # Add the total bytes to the headers if set. - if self._total_bytes is not None: - content_length = "{:d}".format(self._total_bytes) - headers["x-upload-content-length"] = content_length - - headers.update(self._headers) - payload = json.dumps(metadata).encode("utf-8") - return _POST, self.upload_url, payload, headers - - def _process_initiate_response(self, response): - """Process the response from an HTTP request that initiated upload. - - This is everything that must be done after a request that doesn't - require network I/O (or other I/O). This is based on the `sans-I/O`_ - philosophy. - - This method takes the URL from the ``Location`` header and stores it - for future use. Within that URL, we assume the ``upload_id`` query - parameter has been included, but we do not check. - - Args: - response (object): The HTTP response object (need headers). - - .. _sans-I/O: https://sans-io.readthedocs.io/ - """ - _helpers.require_status_code( - response, - (http.client.OK,), - self._get_status_code, - callback=self._make_invalid, - ) - self._resumable_url = _helpers.header_required( - response, "location", self._get_headers - ) - - def initiate( - self, - transport, - stream, - metadata, - content_type, - total_bytes=None, - stream_final=True, - timeout=None, - ): - """Initiate a resumable upload. - - By default, this method assumes your ``stream`` is in a "final" - state ready to transmit. However, ``stream_final=False`` can be used - to indicate that the size of the resource is not known. This can happen - if bytes are being dynamically fed into ``stream``, e.g. if the stream - is attached to application logs. - - If ``stream_final=False`` is used, :attr:`chunk_size` bytes will be - read from the stream every time :meth:`transmit_next_chunk` is called. - If one of those reads produces strictly fewer bites than the chunk - size, the upload will be concluded. - - Args: - transport (object): An object which can make authenticated - requests. - stream (IO[bytes]): The stream (i.e. file-like object) that will - be uploaded. The stream **must** be at the beginning (i.e. - ``stream.tell() == 0``). - metadata (Mapping[str, str]): The resource metadata, such as an - ACL list. - content_type (str): The content type of the resource, e.g. a JPEG - image has content type ``image/jpeg``. - total_bytes (Optional[int]): The total number of bytes to be - uploaded. If specified, the upload size **will not** be - determined from the stream (even if ``stream_final=True``). - stream_final (Optional[bool]): Indicates if the ``stream`` is - "final" (i.e. no more bytes will be added to it). In this case - we determine the upload size from the size of the stream. If - ``total_bytes`` is passed, this argument will be ignored. - timeout (Optional[Union[float, aiohttp.ClientTimeout]]): - The number of seconds to wait for the server response. - Depending on the retry strategy, a request may be repeated - several times using the same timeout each time. - Can also be passed as an `aiohttp.ClientTimeout` object. - - Raises: - NotImplementedError: Always, since virtual. - """ - raise NotImplementedError("This implementation is virtual.") - - def _prepare_request(self): - """Prepare the contents of HTTP request to upload a chunk. - - This is everything that must be done before a request that doesn't - require network I/O. This is based on the `sans-I/O`_ philosophy. - - For the time being, this **does require** some form of I/O to read - a chunk from ``stream`` (via :func:`get_next_chunk`). However, this - will (almost) certainly not be network I/O. - - Returns: - Tuple[str, str, bytes, Mapping[str, str]]: The quadruple - - * HTTP verb for the request (always PUT) - * the URL for the request - * the body of the request - * headers for the request - - The headers **do not** incorporate the ``_headers`` on the - current instance. - - Raises: - ValueError: If the current upload has finished. - ValueError: If the current upload is in an invalid state. - ValueError: If the current upload has not been initiated. - ValueError: If the location in the stream (i.e. ``stream.tell()``) - does not agree with ``bytes_uploaded``. - - .. _sans-I/O: https://sans-io.readthedocs.io/ - """ - if self.finished: - raise ValueError("Upload has finished.") - if self.invalid: - raise ValueError( - "Upload is in an invalid state. To recover call `recover()`." - ) - if self.resumable_url is None: - raise ValueError( - "This upload has not been initiated. Please call " - "initiate() before beginning to transmit chunks." - ) - - start_byte, payload, content_range = get_next_chunk( - self._stream, self._chunk_size, self._total_bytes - ) - if start_byte != self.bytes_uploaded: - msg = _STREAM_ERROR_TEMPLATE.format(start_byte, self.bytes_uploaded) - raise ValueError(msg) - - self._update_checksum(start_byte, payload) - - headers = { - _CONTENT_TYPE_HEADER: self._content_type, - _helpers.CONTENT_RANGE_HEADER: content_range, - } - return _PUT, self.resumable_url, payload, headers - - def _make_invalid(self): - """Simple setter for ``invalid``. - - This is intended to be passed along as a callback to helpers that - raise an exception so they can mark this instance as invalid before - raising. - """ - self._invalid = True - - async def _process_resumable_response(self, response, bytes_sent): - """Process the response from an HTTP request. - - This is everything that must be done after a request that doesn't - require network I/O (or other I/O). This is based on the `sans-I/O`_ - philosophy. - - Args: - response (object): The HTTP response object. - bytes_sent (int): The number of bytes sent in the request that - ``response`` was returned for. - - Raises: - ~google.resumable_media.common.InvalidResponse: If the status - code is 308 and the ``range`` header is not of the form - ``bytes 0-{end}``. - ~google.resumable_media.common.InvalidResponse: If the status - code is not 200 or 308. - - .. _sans-I/O: https://sans-io.readthedocs.io/ - """ - status_code = _helpers.require_status_code( - response, - (http.client.OK, http.client.PERMANENT_REDIRECT), - self._get_status_code, - callback=self._make_invalid, - ) - if status_code == http.client.OK: - # NOTE: We use the "local" information of ``bytes_sent`` to update - # ``bytes_uploaded``, but do not verify this against other - # state. However, there may be some other information: - # - # * a ``size`` key in JSON response body - # * the ``total_bytes`` attribute (if set) - # * ``stream.tell()`` (relying on fact that ``initiate()`` - # requires stream to be at the beginning) - self._bytes_uploaded = self._bytes_uploaded + bytes_sent - # Tombstone the current upload so it cannot be used again. - self._finished = True - # Validate the checksum. This can raise an exception on failure. - await self._validate_checksum(response) - else: - bytes_range = _helpers.header_required( - response, - _helpers.RANGE_HEADER, - self._get_headers, - callback=self._make_invalid, - ) - match = _BYTES_RANGE_RE.match(bytes_range) - if match is None: - self._make_invalid() - raise common.InvalidResponse( - response, - 'Unexpected "range" header', - bytes_range, - 'Expected to be of the form "bytes=0-{end}"', - ) - self._bytes_uploaded = int(match.group("end_byte")) + 1 - - async def _validate_checksum(self, response): - """Check the computed checksum, if any, against the response headers. - Args: - response (object): The HTTP response object. - Raises: - ~google.resumable_media.common.DataCorruption: If the checksum - computed locally and the checksum reported by the remote host do - not match. - """ - if self._checksum_type is None: - return - metadata_key = sync_helpers._get_metadata_key(self._checksum_type) - metadata = await response.json() - remote_checksum = metadata.get(metadata_key) - if remote_checksum is None: - raise common.InvalidResponse( - response, - _UPLOAD_METADATA_NO_APPROPRIATE_CHECKSUM_MESSAGE.format(metadata_key), - self._get_headers(response), - ) - local_checksum = sync_helpers.prepare_checksum_digest( - self._checksum_object.digest() - ) - if local_checksum != remote_checksum: - raise common.DataCorruption( - response, - _UPLOAD_CHECKSUM_MISMATCH_MESSAGE.format( - self._checksum_type.upper(), local_checksum, remote_checksum - ), - ) - - def transmit_next_chunk(self, transport, timeout=None): - """Transmit the next chunk of the resource to be uploaded. - - If the current upload was initiated with ``stream_final=False``, - this method will dynamically determine if the upload has completed. - The upload will be considered complete if the stream produces - fewer than :attr:`chunk_size` bytes when a chunk is read from it. - - Args: - transport (object): An object which can make authenticated - requests. - timeout (Optional[Union[float, aiohttp.ClientTimeout]]): - The number of seconds to wait for the server response. - Depending on the retry strategy, a request may be repeated - several times using the same timeout each time. - Can also be passed as an `aiohttp.ClientTimeout` object. - - Raises: - NotImplementedError: Always, since virtual. - """ - raise NotImplementedError("This implementation is virtual.") - - def _prepare_recover_request(self): - """Prepare the contents of HTTP request to recover from failure. - - This is everything that must be done before a request that doesn't - require network I/O. This is based on the `sans-I/O`_ philosophy. - - We assume that the :attr:`resumable_url` is set (i.e. the only way - the upload can end up :attr:`invalid` is if it has been initiated. - - Returns: - Tuple[str, str, NoneType, Mapping[str, str]]: The quadruple - - * HTTP verb for the request (always PUT) - * the URL for the request - * the body of the request (always :data:`None`) - * headers for the request - - The headers **do not** incorporate the ``_headers`` on the - current instance. - - Raises: - ValueError: If the current upload is not in an invalid state. - - .. _sans-I/O: https://sans-io.readthedocs.io/ - """ - if not self.invalid: - raise ValueError("Upload is not in invalid state, no need to recover.") - - headers = {_helpers.CONTENT_RANGE_HEADER: "bytes */*"} - return _PUT, self.resumable_url, None, headers - - def _process_recover_response(self, response): - """Process the response from an HTTP request to recover from failure. - - This is everything that must be done after a request that doesn't - require network I/O (or other I/O). This is based on the `sans-I/O`_ - philosophy. - - Args: - response (object): The HTTP response object. - - Raises: - ~google.resumable_media.common.InvalidResponse: If the status - code is not 308. - ~google.resumable_media.common.InvalidResponse: If the status - code is 308 and the ``range`` header is not of the form - ``bytes 0-{end}``. - - .. _sans-I/O: https://sans-io.readthedocs.io/ - """ - _helpers.require_status_code( - response, - (http.client.PERMANENT_REDIRECT,), - self._get_status_code, - ) - headers = self._get_headers(response) - if _helpers.RANGE_HEADER in headers: - bytes_range = headers[_helpers.RANGE_HEADER] - match = _BYTES_RANGE_RE.match(bytes_range) - if match is None: - raise common.InvalidResponse( - response, - 'Unexpected "range" header', - bytes_range, - 'Expected to be of the form "bytes=0-{end}"', - ) - self._bytes_uploaded = int(match.group("end_byte")) + 1 - else: - # In this case, the upload has not "begun". - self._bytes_uploaded = 0 - - self._stream.seek(self._bytes_uploaded) - self._invalid = False - - def recover(self, transport): - """Recover from a failure. - - This method should be used when a :class:`ResumableUpload` is in an - :attr:`~ResumableUpload.invalid` state due to a request failure. - - This will verify the progress with the server and make sure the - current upload is in a valid state before :meth:`transmit_next_chunk` - can be used again. - - Args: - transport (object): An object which can make authenticated - requests. - - Raises: - NotImplementedError: Always, since virtual. - """ - raise NotImplementedError("This implementation is virtual.") - - -def get_boundary(): - """Get a random boundary for a multipart request. - - Returns: - bytes: The boundary used to separate parts of a multipart request. - """ - random_int = random.randrange(sys.maxsize) - boundary = _BOUNDARY_FORMAT.format(random_int) - # NOTE: Neither % formatting nor .format() are available for byte strings - # in Python 3.4, so we must use unicode strings as templates. - return boundary.encode("utf-8") - - -def construct_multipart_request(data, metadata, content_type): - """Construct a multipart request body. - - Args: - data (bytes): The resource content (UTF-8 encoded as bytes) - to be uploaded. - metadata (Mapping[str, str]): The resource metadata, such as an - ACL list. - content_type (str): The content type of the resource, e.g. a JPEG - image has content type ``image/jpeg``. - - Returns: - Tuple[bytes, bytes]: The multipart request body and the boundary used - between each part. - """ - multipart_boundary = get_boundary() - json_bytes = json.dumps(metadata).encode("utf-8") - content_type = content_type.encode("utf-8") - # Combine the two parts into a multipart payload. - # NOTE: We'd prefer a bytes template but are restricted by Python 3.4. - boundary_sep = _MULTIPART_SEP + multipart_boundary - content = ( - boundary_sep - + _MULTIPART_BEGIN - + json_bytes - + _CRLF - + boundary_sep - + _CRLF - + b"content-type: " - + content_type - + _CRLF - + _CRLF - + data # Empty line between headers and body. - + _CRLF - + boundary_sep - + _MULTIPART_SEP - ) - - return content, multipart_boundary - - -def get_total_bytes(stream): - """Determine the total number of bytes in a stream. - - Args: - stream (IO[bytes]): The stream (i.e. file-like object). - - Returns: - int: The number of bytes. - """ - current_position = stream.tell() - # NOTE: ``.seek()`` **should** return the same value that ``.tell()`` - # returns, but in Python 2, ``file`` objects do not. - stream.seek(0, os.SEEK_END) - end_position = stream.tell() - # Go back to the initial position. - stream.seek(current_position) - - return end_position - - -def get_next_chunk(stream, chunk_size, total_bytes): - """Get a chunk from an I/O stream. - - The ``stream`` may have fewer bytes remaining than ``chunk_size`` - so it may not always be the case that - ``end_byte == start_byte + chunk_size - 1``. - - Args: - stream (IO[bytes]): The stream (i.e. file-like object). - chunk_size (int): The size of the chunk to be read from the ``stream``. - total_bytes (Optional[int]): The (expected) total number of bytes - in the ``stream``. - - Returns: - Tuple[int, bytes, str]: Triple of: - - * the start byte index - * the content in between the start and end bytes (inclusive) - * content range header for the chunk (slice) that has been read - - Raises: - ValueError: If ``total_bytes == 0`` but ``stream.read()`` yields - non-empty content. - ValueError: If there is no data left to consume. This corresponds - exactly to the case ``end_byte < start_byte``, which can only - occur if ``end_byte == start_byte - 1``. - """ - start_byte = stream.tell() - if total_bytes is not None and start_byte + chunk_size >= total_bytes > 0: - payload = stream.read(total_bytes - start_byte) - else: - payload = stream.read(chunk_size) - end_byte = stream.tell() - 1 - - num_bytes_read = len(payload) - if total_bytes is None: - if num_bytes_read < chunk_size: - # We now **KNOW** the total number of bytes. - total_bytes = end_byte + 1 - elif total_bytes == 0: - # NOTE: We also expect ``start_byte == 0`` here but don't check - # because ``_prepare_initiate_request()`` requires the - # stream to be at the beginning. - if num_bytes_read != 0: - raise ValueError( - "Stream specified as empty, but produced non-empty content." - ) - else: - if num_bytes_read == 0: - raise ValueError( - "Stream is already exhausted. There is no content remaining." - ) - - content_range = get_content_range(start_byte, end_byte, total_bytes) - return start_byte, payload, content_range - - -def get_content_range(start_byte, end_byte, total_bytes): - """Convert start, end and total into content range header. - - If ``total_bytes`` is not known, uses "bytes {start}-{end}/*". - If we are dealing with an empty range (i.e. ``end_byte < start_byte``) - then "bytes */{total}" is used. - - This function **ASSUMES** that if the size is not known, the caller will - not also pass an empty range. - - Args: - start_byte (int): The start (inclusive) of the byte range. - end_byte (int): The end (inclusive) of the byte range. - total_bytes (Optional[int]): The number of bytes in the byte - range (if known). - - Returns: - str: The content range header. - """ - if total_bytes is None: - return _RANGE_UNKNOWN_TEMPLATE.format(start_byte, end_byte) - elif end_byte < start_byte: - return _EMPTY_RANGE_TEMPLATE.format(total_bytes) - else: - return _CONTENT_RANGE_TEMPLATE.format(start_byte, end_byte, total_bytes) diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__init__.py b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__init__.py deleted file mode 100644 index e6a6190..0000000 --- a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__init__.py +++ /dev/null @@ -1,683 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""``requests`` utilities for Google Media Downloads and Resumable Uploads. - -This sub-package assumes callers will use the `requests`_ library -as transport and `google-auth`_ for sending authenticated HTTP traffic -with ``requests``. - -.. _requests: http://docs.python-requests.org/ -.. _google-auth: https://google-auth.readthedocs.io/ - -==================== -Authorized Transport -==================== - -To use ``google-auth`` and ``requests`` to create an authorized transport -that has read-only access to Google Cloud Storage (GCS): - -.. testsetup:: get-credentials - - import google.auth - import google.auth.credentials as creds_mod - import mock - - def mock_default(scopes=None): - credentials = mock.Mock(spec=creds_mod.Credentials) - return credentials, 'mock-project' - - # Patch the ``default`` function on the module. - original_default = google.auth.default - google.auth.default = mock_default - -.. doctest:: get-credentials - - >>> import google.auth - >>> import google.auth.transport.requests as tr_requests - >>> - >>> ro_scope = 'https://www.googleapis.com/auth/devstorage.read_only' - >>> credentials, _ = google.auth.default(scopes=(ro_scope,)) - >>> transport = tr_requests.AuthorizedSession(credentials) - >>> transport - - -.. testcleanup:: get-credentials - - # Put back the correct ``default`` function on the module. - google.auth.default = original_default - -================ -Simple Downloads -================ - -To download an object from Google Cloud Storage, construct the media URL -for the GCS object and download it with an authorized transport that has -access to the resource: - -.. testsetup:: basic-download - - import mock - import requests - import http.client - - bucket = 'bucket-foo' - blob_name = 'file.txt' - - fake_response = requests.Response() - fake_response.status_code = int(http.client.OK) - fake_response.headers['Content-Length'] = '1364156' - fake_content = mock.MagicMock(spec=['__len__']) - fake_content.__len__.return_value = 1364156 - fake_response._content = fake_content - - get_method = mock.Mock(return_value=fake_response, spec=[]) - transport = mock.Mock(request=get_method, spec=['request']) - -.. doctest:: basic-download - - >>> from google.resumable_media.requests import Download - >>> - >>> url_template = ( - ... 'https://www.googleapis.com/download/storage/v1/b/' - ... '{bucket}/o/{blob_name}?alt=media') - >>> media_url = url_template.format( - ... bucket=bucket, blob_name=blob_name) - >>> - >>> download = Download(media_url) - >>> response = download.consume(transport) - >>> download.finished - True - >>> response - - >>> response.headers['Content-Length'] - '1364156' - >>> len(response.content) - 1364156 - -To download only a portion of the bytes in the object, -specify ``start`` and ``end`` byte positions (both optional): - -.. testsetup:: basic-download-with-slice - - import mock - import requests - import http.client - - from google.resumable_media.requests import Download - - media_url = 'http://test.invalid' - start = 4096 - end = 8191 - slice_size = end - start + 1 - - fake_response = requests.Response() - fake_response.status_code = int(http.client.PARTIAL_CONTENT) - fake_response.headers['Content-Length'] = '{:d}'.format(slice_size) - content_range = 'bytes {:d}-{:d}/1364156'.format(start, end) - fake_response.headers['Content-Range'] = content_range - fake_content = mock.MagicMock(spec=['__len__']) - fake_content.__len__.return_value = slice_size - fake_response._content = fake_content - - get_method = mock.Mock(return_value=fake_response, spec=[]) - transport = mock.Mock(request=get_method, spec=['request']) - -.. doctest:: basic-download-with-slice - - >>> download = Download(media_url, start=4096, end=8191) - >>> response = download.consume(transport) - >>> download.finished - True - >>> response - - >>> response.headers['Content-Length'] - '4096' - >>> response.headers['Content-Range'] - 'bytes 4096-8191/1364156' - >>> len(response.content) - 4096 - -================= -Chunked Downloads -================= - -For very large objects or objects of unknown size, it may make more sense -to download the object in chunks rather than all at once. This can be done -to avoid dropped connections with a poor internet connection or can allow -multiple chunks to be downloaded in parallel to speed up the total -download. - -A :class:`.ChunkedDownload` uses the same media URL and authorized -transport that a basic :class:`.Download` would use, but also -requires a chunk size and a write-able byte ``stream``. The chunk size is used -to determine how much of the resouce to consume with each request and the -stream is to allow the resource to be written out (e.g. to disk) without -having to fit in memory all at once. - -.. testsetup:: chunked-download - - import io - - import mock - import requests - import http.client - - media_url = 'http://test.invalid' - - fifty_mb = 50 * 1024 * 1024 - one_gb = 1024 * 1024 * 1024 - fake_response = requests.Response() - fake_response.status_code = int(http.client.PARTIAL_CONTENT) - fake_response.headers['Content-Length'] = '{:d}'.format(fifty_mb) - content_range = 'bytes 0-{:d}/{:d}'.format(fifty_mb - 1, one_gb) - fake_response.headers['Content-Range'] = content_range - fake_content_begin = b'The beginning of the chunk...' - fake_content = fake_content_begin + b'1' * (fifty_mb - 29) - fake_response._content = fake_content - - get_method = mock.Mock(return_value=fake_response, spec=[]) - transport = mock.Mock(request=get_method, spec=['request']) - -.. doctest:: chunked-download - - >>> from google.resumable_media.requests import ChunkedDownload - >>> - >>> chunk_size = 50 * 1024 * 1024 # 50MB - >>> stream = io.BytesIO() - >>> download = ChunkedDownload( - ... media_url, chunk_size, stream) - >>> # Check the state of the download before starting. - >>> download.bytes_downloaded - 0 - >>> download.total_bytes is None - True - >>> response = download.consume_next_chunk(transport) - >>> # Check the state of the download after consuming one chunk. - >>> download.finished - False - >>> download.bytes_downloaded # chunk_size - 52428800 - >>> download.total_bytes # 1GB - 1073741824 - >>> response - - >>> response.headers['Content-Length'] - '52428800' - >>> response.headers['Content-Range'] - 'bytes 0-52428799/1073741824' - >>> len(response.content) == chunk_size - True - >>> stream.seek(0) - 0 - >>> stream.read(29) - b'The beginning of the chunk...' - -The download will change it's ``finished`` status to :data:`True` -once the final chunk is consumed. In some cases, the final chunk may -not be the same size as the other chunks: - -.. testsetup:: chunked-download-end - - import mock - import requests - import http.client - - from google.resumable_media.requests import ChunkedDownload - - media_url = 'http://test.invalid' - - fifty_mb = 50 * 1024 * 1024 - one_gb = 1024 * 1024 * 1024 - stream = mock.Mock(spec=['write']) - download = ChunkedDownload(media_url, fifty_mb, stream) - download._bytes_downloaded = 20 * fifty_mb - download._total_bytes = one_gb - - fake_response = requests.Response() - fake_response.status_code = int(http.client.PARTIAL_CONTENT) - slice_size = one_gb - 20 * fifty_mb - fake_response.headers['Content-Length'] = '{:d}'.format(slice_size) - content_range = 'bytes {:d}-{:d}/{:d}'.format( - 20 * fifty_mb, one_gb - 1, one_gb) - fake_response.headers['Content-Range'] = content_range - fake_content = mock.MagicMock(spec=['__len__']) - fake_content.__len__.return_value = slice_size - fake_response._content = fake_content - - get_method = mock.Mock(return_value=fake_response, spec=[]) - transport = mock.Mock(request=get_method, spec=['request']) - -.. doctest:: chunked-download-end - - >>> # The state of the download in progress. - >>> download.finished - False - >>> download.bytes_downloaded # 20 chunks at 50MB - 1048576000 - >>> download.total_bytes # 1GB - 1073741824 - >>> response = download.consume_next_chunk(transport) - >>> # The state of the download after consuming the final chunk. - >>> download.finished - True - >>> download.bytes_downloaded == download.total_bytes - True - >>> response - - >>> response.headers['Content-Length'] - '25165824' - >>> response.headers['Content-Range'] - 'bytes 1048576000-1073741823/1073741824' - >>> len(response.content) < download.chunk_size - True - -In addition, a :class:`.ChunkedDownload` can also take optional -``start`` and ``end`` byte positions. - -Usually, no checksum is returned with a chunked download. Even if one is returned, -it is not validated. If you need to validate the checksum, you can do so -by buffering the chunks and validating the checksum against the completed download. - -============== -Simple Uploads -============== - -Among the three supported upload classes, the simplest is -:class:`.SimpleUpload`. A simple upload should be used when the resource -being uploaded is small and when there is no metadata (other than the name) -associated with the resource. - -.. testsetup:: simple-upload - - import json - - import mock - import requests - import http.client - - bucket = 'some-bucket' - blob_name = 'file.txt' - - fake_response = requests.Response() - fake_response.status_code = int(http.client.OK) - payload = { - 'bucket': bucket, - 'contentType': 'text/plain', - 'md5Hash': 'M0XLEsX9/sMdiI+4pB4CAQ==', - 'name': blob_name, - 'size': '27', - } - fake_response._content = json.dumps(payload).encode('utf-8') - - post_method = mock.Mock(return_value=fake_response, spec=[]) - transport = mock.Mock(request=post_method, spec=['request']) - -.. doctest:: simple-upload - :options: +NORMALIZE_WHITESPACE - - >>> from google.resumable_media.requests import SimpleUpload - >>> - >>> url_template = ( - ... 'https://www.googleapis.com/upload/storage/v1/b/{bucket}/o?' - ... 'uploadType=media&' - ... 'name={blob_name}') - >>> upload_url = url_template.format( - ... bucket=bucket, blob_name=blob_name) - >>> - >>> upload = SimpleUpload(upload_url) - >>> data = b'Some not too large content.' - >>> content_type = 'text/plain' - >>> response = upload.transmit(transport, data, content_type) - >>> upload.finished - True - >>> response - - >>> json_response = response.json() - >>> json_response['bucket'] == bucket - True - >>> json_response['name'] == blob_name - True - >>> json_response['contentType'] == content_type - True - >>> json_response['md5Hash'] - 'M0XLEsX9/sMdiI+4pB4CAQ==' - >>> int(json_response['size']) == len(data) - True - -In the rare case that an upload fails, an :exc:`.InvalidResponse` -will be raised: - -.. testsetup:: simple-upload-fail - - import time - - import mock - import requests - import http.client - - from google import resumable_media - from google.resumable_media import _helpers - from google.resumable_media.requests import SimpleUpload as constructor - - upload_url = 'http://test.invalid' - data = b'Some not too large content.' - content_type = 'text/plain' - - fake_response = requests.Response() - fake_response.status_code = int(http.client.SERVICE_UNAVAILABLE) - - post_method = mock.Mock(return_value=fake_response, spec=[]) - transport = mock.Mock(request=post_method, spec=['request']) - - time_sleep = time.sleep - def dont_sleep(seconds): - raise RuntimeError('No sleep', seconds) - - def SimpleUpload(*args, **kwargs): - upload = constructor(*args, **kwargs) - # Mock the cumulative sleep to avoid retries (and `time.sleep()`). - upload._retry_strategy = resumable_media.RetryStrategy( - max_cumulative_retry=-1.0) - return upload - - time.sleep = dont_sleep - -.. doctest:: simple-upload-fail - :options: +NORMALIZE_WHITESPACE - - >>> upload = SimpleUpload(upload_url) - >>> error = None - >>> try: - ... upload.transmit(transport, data, content_type) - ... except resumable_media.InvalidResponse as caught_exc: - ... error = caught_exc - ... - >>> error - InvalidResponse('Request failed with status code', 503, - 'Expected one of', ) - >>> error.response - - >>> - >>> upload.finished - True - -.. testcleanup:: simple-upload-fail - - # Put back the correct ``sleep`` function on the ``time`` module. - time.sleep = time_sleep - -Even in the case of failure, we see that the upload is -:attr:`~.SimpleUpload.finished`, i.e. it cannot be re-used. - -================= -Multipart Uploads -================= - -After the simple upload, the :class:`.MultipartUpload` can be used to -achieve essentially the same task. However, a multipart upload allows some -metadata about the resource to be sent along as well. (This is the "multi": -we send a first part with the metadata and a second part with the actual -bytes in the resource.) - -Usage is similar to the simple upload, but :meth:`~.MultipartUpload.transmit` -accepts an extra required argument: ``metadata``. - -.. testsetup:: multipart-upload - - import json - - import mock - import requests - import http.client - - bucket = 'some-bucket' - blob_name = 'file.txt' - data = b'Some not too large content.' - content_type = 'text/plain' - - fake_response = requests.Response() - fake_response.status_code = int(http.client.OK) - payload = { - 'bucket': bucket, - 'name': blob_name, - 'metadata': {'color': 'grurple'}, - } - fake_response._content = json.dumps(payload).encode('utf-8') - - post_method = mock.Mock(return_value=fake_response, spec=[]) - transport = mock.Mock(request=post_method, spec=['request']) - -.. doctest:: multipart-upload - - >>> from google.resumable_media.requests import MultipartUpload - >>> - >>> url_template = ( - ... 'https://www.googleapis.com/upload/storage/v1/b/{bucket}/o?' - ... 'uploadType=multipart') - >>> upload_url = url_template.format(bucket=bucket) - >>> - >>> upload = MultipartUpload(upload_url) - >>> metadata = { - ... 'name': blob_name, - ... 'metadata': { - ... 'color': 'grurple', - ... }, - ... } - >>> response = upload.transmit(transport, data, metadata, content_type) - >>> upload.finished - True - >>> response - - >>> json_response = response.json() - >>> json_response['bucket'] == bucket - True - >>> json_response['name'] == blob_name - True - >>> json_response['metadata'] == metadata['metadata'] - True - -As with the simple upload, in the case of failure an :exc:`.InvalidResponse` -is raised, enclosing the :attr:`~.InvalidResponse.response` that caused -the failure and the ``upload`` object cannot be re-used after a failure. - -================= -Resumable Uploads -================= - -A :class:`.ResumableUpload` deviates from the other two upload classes: -it transmits a resource over the course of multiple requests. This -is intended to be used in cases where: - -* the size of the resource is not known (i.e. it is generated on the fly) -* requests must be short-lived -* the client has request **size** limitations -* the resource is too large to fit into memory - -In general, a resource should be sent in a **single** request to avoid -latency and reduce QPS. See `GCS best practices`_ for more things to -consider when using a resumable upload. - -.. _GCS best practices: https://cloud.google.com/storage/docs/\ - best-practices#uploading - -After creating a :class:`.ResumableUpload` instance, a -**resumable upload session** must be initiated to let the server know that -a series of chunked upload requests will be coming and to obtain an -``upload_id`` for the session. In contrast to the other two upload classes, -:meth:`~.ResumableUpload.initiate` takes a byte ``stream`` as input rather -than raw bytes as ``data``. This can be a file object, a :class:`~io.BytesIO` -object or any other stream implementing the same interface. - -.. testsetup:: resumable-initiate - - import io - - import mock - import requests - import http.client - - bucket = 'some-bucket' - blob_name = 'file.txt' - data = b'Some resumable bytes.' - content_type = 'text/plain' - - fake_response = requests.Response() - fake_response.status_code = int(http.client.OK) - fake_response._content = b'' - upload_id = 'ABCdef189XY_super_serious' - resumable_url_template = ( - 'https://www.googleapis.com/upload/storage/v1/b/{bucket}' - '/o?uploadType=resumable&upload_id={upload_id}') - resumable_url = resumable_url_template.format( - bucket=bucket, upload_id=upload_id) - fake_response.headers['location'] = resumable_url - fake_response.headers['x-guploader-uploadid'] = upload_id - - post_method = mock.Mock(return_value=fake_response, spec=[]) - transport = mock.Mock(request=post_method, spec=['request']) - -.. doctest:: resumable-initiate - - >>> from google.resumable_media.requests import ResumableUpload - >>> - >>> url_template = ( - ... 'https://www.googleapis.com/upload/storage/v1/b/{bucket}/o?' - ... 'uploadType=resumable') - >>> upload_url = url_template.format(bucket=bucket) - >>> - >>> chunk_size = 1024 * 1024 # 1MB - >>> upload = ResumableUpload(upload_url, chunk_size) - >>> stream = io.BytesIO(data) - >>> # The upload doesn't know how "big" it is until seeing a stream. - >>> upload.total_bytes is None - True - >>> metadata = {'name': blob_name} - >>> response = upload.initiate(transport, stream, metadata, content_type) - >>> response - - >>> upload.resumable_url == response.headers['Location'] - True - >>> upload.total_bytes == len(data) - True - >>> upload_id = response.headers['X-GUploader-UploadID'] - >>> upload_id - 'ABCdef189XY_super_serious' - >>> upload.resumable_url == upload_url + '&upload_id=' + upload_id - True - -Once a :class:`.ResumableUpload` has been initiated, the resource is -transmitted in chunks until completion: - -.. testsetup:: resumable-transmit - - import io - import json - - import mock - import requests - import http.client - - from google import resumable_media - import google.resumable_media.requests.upload as upload_mod - - data = b'01234567891' - stream = io.BytesIO(data) - # Create an "already initiated" upload. - upload_url = 'http://test.invalid' - chunk_size = 256 * 1024 # 256KB - upload = upload_mod.ResumableUpload(upload_url, chunk_size) - upload._resumable_url = 'http://test.invalid?upload_id=mocked' - upload._stream = stream - upload._content_type = 'text/plain' - upload._total_bytes = len(data) - - # After-the-fact update the chunk size so that len(data) - # is split into three. - upload._chunk_size = 4 - # Make three fake responses. - fake_response0 = requests.Response() - fake_response0.status_code = http.client.PERMANENT_REDIRECT - fake_response0.headers['range'] = 'bytes=0-3' - - fake_response1 = requests.Response() - fake_response1.status_code = http.client.PERMANENT_REDIRECT - fake_response1.headers['range'] = 'bytes=0-7' - - fake_response2 = requests.Response() - fake_response2.status_code = int(http.client.OK) - bucket = 'some-bucket' - blob_name = 'file.txt' - payload = { - 'bucket': bucket, - 'name': blob_name, - 'size': '{:d}'.format(len(data)), - } - fake_response2._content = json.dumps(payload).encode('utf-8') - - # Use the fake responses to mock a transport. - responses = [fake_response0, fake_response1, fake_response2] - put_method = mock.Mock(side_effect=responses, spec=[]) - transport = mock.Mock(request=put_method, spec=['request']) - -.. doctest:: resumable-transmit - - >>> response0 = upload.transmit_next_chunk(transport) - >>> response0 - - >>> upload.finished - False - >>> upload.bytes_uploaded == upload.chunk_size - True - >>> - >>> response1 = upload.transmit_next_chunk(transport) - >>> response1 - - >>> upload.finished - False - >>> upload.bytes_uploaded == 2 * upload.chunk_size - True - >>> - >>> response2 = upload.transmit_next_chunk(transport) - >>> response2 - - >>> upload.finished - True - >>> upload.bytes_uploaded == upload.total_bytes - True - >>> json_response = response2.json() - >>> json_response['bucket'] == bucket - True - >>> json_response['name'] == blob_name - True -""" - -from google._async_resumable_media.requests.download import ChunkedDownload -from google._async_resumable_media.requests.download import Download -from google._async_resumable_media.requests.upload import MultipartUpload -from google._async_resumable_media.requests.download import RawChunkedDownload -from google._async_resumable_media.requests.download import RawDownload -from google._async_resumable_media.requests.upload import ResumableUpload -from google._async_resumable_media.requests.upload import SimpleUpload - - -__all__ = [ - "ChunkedDownload", - "Download", - "MultipartUpload", - "RawChunkedDownload", - "RawDownload", - "ResumableUpload", - "SimpleUpload", -] diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 4ec427b..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__pycache__/_request_helpers.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__pycache__/_request_helpers.cpython-312.pyc deleted file mode 100644 index 9f0018f..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__pycache__/_request_helpers.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__pycache__/download.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__pycache__/download.cpython-312.pyc deleted file mode 100644 index eeb756f..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__pycache__/download.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__pycache__/upload.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__pycache__/upload.cpython-312.pyc deleted file mode 100644 index e14e299..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/__pycache__/upload.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/_request_helpers.py b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/_request_helpers.py deleted file mode 100644 index cd9b9b8..0000000 --- a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/_request_helpers.py +++ /dev/null @@ -1,154 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Shared utilities used by both downloads and uploads. - -This utilities are explicitly catered to ``requests``-like transports. -""" - -import functools - -from google._async_resumable_media import _helpers -from google.resumable_media import common - -from google.auth.transport import _aiohttp_requests as aiohttp_requests # type: ignore -import aiohttp # type: ignore - -_DEFAULT_RETRY_STRATEGY = common.RetryStrategy() -_SINGLE_GET_CHUNK_SIZE = 8192 - - -# The number of seconds to wait to establish a connection -# (connect() call on socket). Avoid setting this to a multiple of 3 to not -# Align with TCP Retransmission timing. (typically 2.5-3s) -_DEFAULT_CONNECT_TIMEOUT = 61 -# The number of seconds to wait between bytes sent from the server. -_DEFAULT_READ_TIMEOUT = 60 -_DEFAULT_TIMEOUT = aiohttp.ClientTimeout( - connect=_DEFAULT_CONNECT_TIMEOUT, sock_read=_DEFAULT_READ_TIMEOUT -) - - -class RequestsMixin(object): - """Mix-in class implementing ``requests``-specific behavior. - - These are methods that are more general purpose, with implementations - specific to the types defined in ``requests``. - """ - - @staticmethod - def _get_status_code(response): - """Access the status code from an HTTP response. - - Args: - response (~requests.Response): The HTTP response object. - - Returns: - int: The status code. - """ - return response.status - - @staticmethod - def _get_headers(response): - """Access the headers from an HTTP response. - - Args: - response (~requests.Response): The HTTP response object. - - Returns: - ~requests.structures.CaseInsensitiveDict: The header mapping (keys - are case-insensitive). - """ - # For Async testing,`_headers` is modified instead of headers - # access via the internal field. - return response._headers - - @staticmethod - async def _get_body(response): - """Access the response body from an HTTP response. - - Args: - response (~requests.Response): The HTTP response object. - - Returns: - bytes: The body of the ``response``. - """ - wrapped_response = aiohttp_requests._CombinedResponse(response) - content = await wrapped_response.data.read() - return content - - -class RawRequestsMixin(RequestsMixin): - @staticmethod - async def _get_body(response): - """Access the response body from an HTTP response. - - Args: - response (~requests.Response): The HTTP response object. - - Returns: - bytes: The body of the ``response``. - """ - - wrapped_response = aiohttp_requests._CombinedResponse(response) - content = await wrapped_response.raw_content() - return content - - -async def http_request( - transport, - method, - url, - data=None, - headers=None, - retry_strategy=_DEFAULT_RETRY_STRATEGY, - **transport_kwargs, -): - """Make an HTTP request. - - Args: - transport (~requests.Session): A ``requests`` object which can make - authenticated requests via a ``request()`` method. This method - must accept an HTTP method, an upload URL, a ``data`` keyword - argument and a ``headers`` keyword argument. - method (str): The HTTP method for the request. - url (str): The URL for the request. - data (Optional[bytes]): The body of the request. - headers (Mapping[str, str]): The headers for the request (``transport`` - may also add additional headers). - retry_strategy (~google.resumable_media.common.RetryStrategy): The - strategy to use if the request fails and must be retried. - transport_kwargs (Dict[str, str]): Extra keyword arguments to be - passed along to ``transport.request``. - - Returns: - ~requests.Response: The return value of ``transport.request()``. - """ - - # NOTE(asyncio/aiohttp): Sync versions use a tuple for two timeouts, - # default connect timeout and read timeout. Since async requests only - # accepts a single value, this is using the connect timeout. This logic - # diverges from the sync implementation. - if "timeout" not in transport_kwargs: - timeout = _DEFAULT_TIMEOUT - transport_kwargs["timeout"] = timeout - - func = functools.partial( - transport.request, method, url, data=data, headers=headers, **transport_kwargs - ) - - resp = await _helpers.wait_and_retry( - func, RequestsMixin._get_status_code, retry_strategy - ) - return resp diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/download.py b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/download.py deleted file mode 100644 index 490017c..0000000 --- a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/download.py +++ /dev/null @@ -1,469 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Support for downloading media from Google APIs.""" - -import urllib3.response # type: ignore -import http - -from google._async_resumable_media import _download -from google._async_resumable_media import _helpers -from google._async_resumable_media.requests import _request_helpers -from google.resumable_media import common -from google.resumable_media import _helpers as sync_helpers -from google.resumable_media.requests import download - -_CHECKSUM_MISMATCH = download._CHECKSUM_MISMATCH - - -class Download(_request_helpers.RequestsMixin, _download.Download): - """Helper to manage downloading a resource from a Google API. - - "Slices" of the resource can be retrieved by specifying a range - with ``start`` and / or ``end``. However, in typical usage, neither - ``start`` nor ``end`` is expected to be provided. - - Args: - media_url (str): The URL containing the media to be downloaded. - stream (IO[bytes]): A write-able stream (i.e. file-like object) that - the downloaded resource can be written to. - start (int): The first byte in a range to be downloaded. If not - provided, but ``end`` is provided, will download from the - beginning to ``end`` of the media. - end (int): The last byte in a range to be downloaded. If not - provided, but ``start`` is provided, will download from the - ``start`` to the end of the media. - headers (Optional[Mapping[str, str]]): Extra headers that should - be sent with the request, e.g. headers for encrypted data. - checksum Optional([str]): The type of checksum to compute to verify - the integrity of the object. The response headers must contain - a checksum of the requested type. If the headers lack an - appropriate checksum (for instance in the case of transcoded or - ranged downloads where the remote service does not know the - correct checksum) an INFO-level log will be emitted. Supported - values are "md5", "crc32c" and None. The default is "md5". - - Attributes: - media_url (str): The URL containing the media to be downloaded. - start (Optional[int]): The first byte in a range to be downloaded. - end (Optional[int]): The last byte in a range to be downloaded. - """ - - async def _write_to_stream(self, response): - """Write response body to a write-able stream. - - .. note: - - This method assumes that the ``_stream`` attribute is set on the - current download. - - Args: - response (~requests.Response): The HTTP response object. - - Raises: - ~google.resumable_media.common.DataCorruption: If the download's - checksum doesn't agree with server-computed checksum. - """ - - # `_get_expected_checksum()` may return None even if a checksum was - # requested, in which case it will emit an info log _MISSING_CHECKSUM. - # If an invalid checksum type is specified, this will raise ValueError. - expected_checksum, checksum_object = sync_helpers._get_expected_checksum( - response, self._get_headers, self.media_url, checksum_type=self.checksum - ) - - local_checksum_object = _add_decoder(response, checksum_object) - - async for chunk in response.content.iter_chunked( - _request_helpers._SINGLE_GET_CHUNK_SIZE - ): - self._stream.write(chunk) - local_checksum_object.update(chunk) - - # Don't validate the checksum for partial responses. - if ( - expected_checksum is not None - and response.status != http.client.PARTIAL_CONTENT - ): - actual_checksum = sync_helpers.prepare_checksum_digest( - checksum_object.digest() - ) - if actual_checksum != expected_checksum: - msg = _CHECKSUM_MISMATCH.format( - self.media_url, - expected_checksum, - actual_checksum, - checksum_type=self.checksum.upper(), - ) - raise common.DataCorruption(response, msg) - - async def consume(self, transport, timeout=_request_helpers._DEFAULT_TIMEOUT): - """Consume the resource to be downloaded. - - If a ``stream`` is attached to this download, then the downloaded - resource will be written to the stream. - - Args: - transport (~requests.Session): A ``requests`` object which can - make authenticated requests. - timeout (Optional[Union[float, aiohttp.ClientTimeout]]): - The number of seconds to wait for the server response. - Depending on the retry strategy, a request may be repeated - several times using the same timeout each time. - Can also be passed as an `aiohttp.ClientTimeout` object. - - Returns: - ~requests.Response: The HTTP response returned by ``transport``. - - Raises: - ~google.resumable_media.common.DataCorruption: If the download's - checksum doesn't agree with server-computed checksum. - ValueError: If the current :class:`Download` has already - finished. - """ - method, url, payload, headers = self._prepare_request() - # NOTE: We assume "payload is None" but pass it along anyway. - request_kwargs = { - "data": payload, - "headers": headers, - "retry_strategy": self._retry_strategy, - "timeout": timeout, - } - - if self._stream is not None: - request_kwargs["stream"] = True - - result = await _request_helpers.http_request( - transport, method, url, **request_kwargs - ) - - self._process_response(result) - - if self._stream is not None: - await self._write_to_stream(result) - - return result - - -class RawDownload(_request_helpers.RawRequestsMixin, _download.Download): - """Helper to manage downloading a raw resource from a Google API. - - "Slices" of the resource can be retrieved by specifying a range - with ``start`` and / or ``end``. However, in typical usage, neither - ``start`` nor ``end`` is expected to be provided. - - Args: - media_url (str): The URL containing the media to be downloaded. - stream (IO[bytes]): A write-able stream (i.e. file-like object) that - the downloaded resource can be written to. - start (int): The first byte in a range to be downloaded. If not - provided, but ``end`` is provided, will download from the - beginning to ``end`` of the media. - end (int): The last byte in a range to be downloaded. If not - provided, but ``start`` is provided, will download from the - ``start`` to the end of the media. - headers (Optional[Mapping[str, str]]): Extra headers that should - be sent with the request, e.g. headers for encrypted data. - checksum Optional([str]): The type of checksum to compute to verify - the integrity of the object. The response headers must contain - a checksum of the requested type. If the headers lack an - appropriate checksum (for instance in the case of transcoded or - ranged downloads where the remote service does not know the - correct checksum) an INFO-level log will be emitted. Supported - values are "md5", "crc32c" and None. The default is "md5". - - Attributes: - media_url (str): The URL containing the media to be downloaded. - start (Optional[int]): The first byte in a range to be downloaded. - end (Optional[int]): The last byte in a range to be downloaded. - """ - - async def _write_to_stream(self, response): - """Write response body to a write-able stream. - - .. note: - - This method assumes that the ``_stream`` attribute is set on the - current download. - - Args: - response (~requests.Response): The HTTP response object. - - Raises: - ~google.resumable_media.common.DataCorruption: If the download's - checksum doesn't agree with server-computed checksum. - """ - - # `_get_expected_checksum()` may return None even if a checksum was - # requested, in which case it will emit an info log _MISSING_CHECKSUM. - # If an invalid checksum type is specified, this will raise ValueError. - expected_checksum, checksum_object = sync_helpers._get_expected_checksum( - response, self._get_headers, self.media_url, checksum_type=self.checksum - ) - - async for chunk in response.content.iter_chunked( - _request_helpers._SINGLE_GET_CHUNK_SIZE - ): - self._stream.write(chunk) - checksum_object.update(chunk) - - # Don't validate the checksum for partial responses. - if ( - expected_checksum is not None - and response.status != http.client.PARTIAL_CONTENT - ): - actual_checksum = sync_helpers.prepare_checksum_digest( - checksum_object.digest() - ) - - if actual_checksum != expected_checksum: - msg = _CHECKSUM_MISMATCH.format( - self.media_url, - expected_checksum, - actual_checksum, - checksum_type=self.checksum.upper(), - ) - raise common.DataCorruption(response, msg) - - async def consume(self, transport, timeout=_request_helpers._DEFAULT_TIMEOUT): - """Consume the resource to be downloaded. - - If a ``stream`` is attached to this download, then the downloaded - resource will be written to the stream. - - Args: - transport (~requests.Session): A ``requests`` object which can - make authenticated requests. - timeout (Optional[Union[float, Tuple[float, float]]]): - The number of seconds to wait for the server response. - Depending on the retry strategy, a request may be repeated - several times using the same timeout each time. - Can also be passed as a tuple (connect_timeout, read_timeout). - See :meth:`requests.Session.request` documentation for details. - - Returns: - ~requests.Response: The HTTP response returned by ``transport``. - - Raises: - ~google.resumable_media.common.DataCorruption: If the download's - checksum doesn't agree with server-computed checksum. - ValueError: If the current :class:`Download` has already - finished. - """ - method, url, payload, headers = self._prepare_request() - # NOTE: We assume "payload is None" but pass it along anyway. - result = await _request_helpers.http_request( - transport, - method, - url, - data=payload, - headers=headers, - retry_strategy=self._retry_strategy, - ) - - self._process_response(result) - - if self._stream is not None: - await self._write_to_stream(result) - - return result - - -class ChunkedDownload(_request_helpers.RequestsMixin, _download.ChunkedDownload): - """Download a resource in chunks from a Google API. - - Args: - media_url (str): The URL containing the media to be downloaded. - chunk_size (int): The number of bytes to be retrieved in each - request. - stream (IO[bytes]): A write-able stream (i.e. file-like object) that - will be used to concatenate chunks of the resource as they are - downloaded. - start (int): The first byte in a range to be downloaded. If not - provided, defaults to ``0``. - end (int): The last byte in a range to be downloaded. If not - provided, will download to the end of the media. - headers (Optional[Mapping[str, str]]): Extra headers that should - be sent with each request, e.g. headers for data encryption - key headers. - - Attributes: - media_url (str): The URL containing the media to be downloaded. - start (Optional[int]): The first byte in a range to be downloaded. - end (Optional[int]): The last byte in a range to be downloaded. - chunk_size (int): The number of bytes to be retrieved in each request. - - Raises: - ValueError: If ``start`` is negative. - """ - - async def consume_next_chunk( - self, transport, timeout=_request_helpers._DEFAULT_TIMEOUT - ): - """ - Consume the next chunk of the resource to be downloaded. - - Args: - transport (~requests.Session): A ``requests`` object which can - make authenticated requests. - timeout (Optional[Union[float, aiohttp.ClientTimeout]]): - The number of seconds to wait for the server response. - Depending on the retry strategy, a request may be repeated - several times using the same timeout each time. - Can also be passed as an `aiohttp.ClientTimeout` object. - - Returns: - ~requests.Response: The HTTP response returned by ``transport``. - - Raises: - ValueError: If the current download has finished. - """ - method, url, payload, headers = self._prepare_request() - # NOTE: We assume "payload is None" but pass it along anyway. - result = await _request_helpers.http_request( - transport, - method, - url, - data=payload, - headers=headers, - retry_strategy=self._retry_strategy, - timeout=timeout, - ) - - await self._process_response(result) - return result - - -class RawChunkedDownload(_request_helpers.RawRequestsMixin, _download.ChunkedDownload): - """Download a raw resource in chunks from a Google API. - - Args: - media_url (str): The URL containing the media to be downloaded. - chunk_size (int): The number of bytes to be retrieved in each - request. - stream (IO[bytes]): A write-able stream (i.e. file-like object) that - will be used to concatenate chunks of the resource as they are - downloaded. - start (int): The first byte in a range to be downloaded. If not - provided, defaults to ``0``. - end (int): The last byte in a range to be downloaded. If not - provided, will download to the end of the media. - headers (Optional[Mapping[str, str]]): Extra headers that should - be sent with each request, e.g. headers for data encryption - key headers. - - Attributes: - media_url (str): The URL containing the media to be downloaded. - start (Optional[int]): The first byte in a range to be downloaded. - end (Optional[int]): The last byte in a range to be downloaded. - chunk_size (int): The number of bytes to be retrieved in each request. - - Raises: - ValueError: If ``start`` is negative. - """ - - async def consume_next_chunk( - self, transport, timeout=_request_helpers._DEFAULT_TIMEOUT - ): - """Consume the next chunk of the resource to be downloaded. - - Args: - transport (~requests.Session): A ``requests`` object which can - make authenticated requests. - timeout (Optional[Union[float, aiohttp.ClientTimeout]]): - The number of seconds to wait for the server response. - Depending on the retry strategy, a request may be repeated - several times using the same timeout each time. - Can also be passed as an `aiohttp.ClientTimeout` object. - - Returns: - ~requests.Response: The HTTP response returned by ``transport``. - - Raises: - ValueError: If the current download has finished. - """ - method, url, payload, headers = self._prepare_request() - # NOTE: We assume "payload is None" but pass it along anyway. - result = await _request_helpers.http_request( - transport, - method, - url, - data=payload, - headers=headers, - retry_strategy=self._retry_strategy, - timeout=timeout, - ) - await self._process_response(result) - return result - - -def _add_decoder(response_raw, checksum): - """Patch the ``_decoder`` on a ``urllib3`` response. - - This is so that we can intercept the compressed bytes before they are - decoded. - - Only patches if the content encoding is ``gzip``. - - Args: - response_raw (urllib3.response.HTTPResponse): The raw response for - an HTTP request. - checksum (object): - A checksum which will be updated with compressed bytes. - - Returns: - object: Either the original ``checksum`` if ``_decoder`` is not - patched, or a ``_DoNothingHash`` if the decoder is patched, since the - caller will no longer need to hash to decoded bytes. - """ - - encoding = response_raw.headers.get("content-encoding", "").lower() - if encoding != "gzip": - return checksum - - response_raw._decoder = _GzipDecoder(checksum) - return _helpers._DoNothingHash() - - -class _GzipDecoder(urllib3.response.GzipDecoder): - """Custom subclass of ``urllib3`` decoder for ``gzip``-ed bytes. - - Allows a checksum function to see the compressed bytes before they are - decoded. This way the checksum of the compressed value can be computed. - - Args: - checksum (object): - A checksum which will be updated with compressed bytes. - """ - - def __init__(self, checksum): - super(_GzipDecoder, self).__init__() - self._checksum = checksum - - def decompress(self, data, max_length=-1): - """Decompress the bytes. - - Args: - data (bytes): The compressed bytes to be decompressed. - max_length (int): Maximum number of bytes to return. -1 for no - limit. Forwarded to the underlying decoder when supported. - - Returns: - bytes: The decompressed bytes from ``data``. - """ - self._checksum.update(data) - try: - return super(_GzipDecoder, self).decompress(data, max_length=max_length) - except TypeError: - return super(_GzipDecoder, self).decompress(data) diff --git a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/upload.py b/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/upload.py deleted file mode 100644 index cbe2f8f..0000000 --- a/notification-service/venv/Lib/site-packages/google/_async_resumable_media/requests/upload.py +++ /dev/null @@ -1,514 +0,0 @@ -# Copyright 2017 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Support for resumable uploads. - -Also supported here are simple (media) uploads and multipart -uploads that contain both metadata and a small file as payload. -""" - -from google._async_resumable_media import _upload -from google._async_resumable_media.requests import _request_helpers - - -class SimpleUpload(_request_helpers.RequestsMixin, _upload.SimpleUpload): - """Upload a resource to a Google API. - - A **simple** media upload sends no metadata and completes the upload - in a single request. - - Args: - upload_url (str): The URL where the content will be uploaded. - headers (Optional[Mapping[str, str]]): Extra headers that should - be sent with the request, e.g. headers for encrypted data. - - Attributes: - upload_url (str): The URL where the content will be uploaded. - """ - - async def transmit( - self, - transport, - data, - content_type, - timeout=_request_helpers._DEFAULT_TIMEOUT, - ): - """Transmit the resource to be uploaded. - - Args: - transport (~requests.Session): A ``requests`` object which can - make authenticated requests. - data (bytes): The resource content to be uploaded. - content_type (str): The content type of the resource, e.g. a JPEG - image has content type ``image/jpeg``. - timeout (Optional[Union[float, aiohttp.ClientTimeout]]): - The number of seconds to wait for the server response. - Depending on the retry strategy, a request may be repeated - several times using the same timeout each time. - Can also be passed as an `aiohttp.ClientTimeout` object. - - Returns: - ~requests.Response: The HTTP response returned by ``transport``. - """ - method, url, payload, headers = self._prepare_request(data, content_type) - - response = await _request_helpers.http_request( - transport, - method, - url, - data=payload, - headers=headers, - retry_strategy=self._retry_strategy, - timeout=timeout, - ) - self._process_response(response) - return response - - -class MultipartUpload(_request_helpers.RequestsMixin, _upload.MultipartUpload): - """Upload a resource with metadata to a Google API. - - A **multipart** upload sends both metadata and the resource in a single - (multipart) request. - - Args: - upload_url (str): The URL where the content will be uploaded. - headers (Optional[Mapping[str, str]]): Extra headers that should - be sent with the request, e.g. headers for encrypted data. - checksum Optional([str]): The type of checksum to compute to verify - the integrity of the object. The request metadata will be amended - to include the computed value. Using this option will override a - manually-set checksum value. Supported values are "md5", - "crc32c" and None. The default is None. - - Attributes: - upload_url (str): The URL where the content will be uploaded. - """ - - async def transmit( - self, - transport, - data, - metadata, - content_type, - timeout=_request_helpers._DEFAULT_TIMEOUT, - ): - """Transmit the resource to be uploaded. - - Args: - transport (~requests.Session): A ``requests`` object which can - make authenticated requests. - data (bytes): The resource content to be uploaded. - metadata (Mapping[str, str]): The resource metadata, such as an - ACL list. - content_type (str): The content type of the resource, e.g. a JPEG - image has content type ``image/jpeg``. - timeout (Optional[Union[float, aiohttp.ClientTimeout]]): - The number of seconds to wait for the server response. - Depending on the retry strategy, a request may be repeated - several times using the same timeout each time. - Can also be passed as an `aiohttp.ClientTimeout` object. - - Returns: - ~requests.Response: The HTTP response returned by ``transport``. - """ - method, url, payload, headers = self._prepare_request( - data, metadata, content_type - ) - - response = await _request_helpers.http_request( - transport, - method, - url, - data=payload, - headers=headers, - retry_strategy=self._retry_strategy, - timeout=timeout, - ) - self._process_response(response) - return response - - -class ResumableUpload(_request_helpers.RequestsMixin, _upload.ResumableUpload): - """Initiate and fulfill a resumable upload to a Google API. - - A **resumable** upload sends an initial request with the resource metadata - and then gets assigned an upload ID / upload URL to send bytes to. - Using the upload URL, the upload is then done in chunks (determined by - the user) until all bytes have been uploaded. - - When constructing a resumable upload, only the resumable upload URL and - the chunk size are required: - - .. testsetup:: resumable-constructor - - bucket = 'bucket-foo' - - .. doctest:: resumable-constructor - - >>> from google.resumable_media.requests import ResumableUpload - >>> - >>> url_template = ( - ... 'https://www.googleapis.com/upload/storage/v1/b/{bucket}/o?' - ... 'uploadType=resumable') - >>> upload_url = url_template.format(bucket=bucket) - >>> - >>> chunk_size = 3 * 1024 * 1024 # 3MB - >>> upload = ResumableUpload(upload_url, chunk_size) - - When initiating an upload (via :meth:`initiate`), the caller is expected - to pass the resource being uploaded as a file-like ``stream``. If the size - of the resource is explicitly known, it can be passed in directly: - - .. testsetup:: resumable-explicit-size - - import os - import tempfile - - import mock - import requests - import http.client - - from google.resumable_media.requests import ResumableUpload - - upload_url = 'http://test.invalid' - chunk_size = 3 * 1024 * 1024 # 3MB - upload = ResumableUpload(upload_url, chunk_size) - - file_desc, filename = tempfile.mkstemp() - os.close(file_desc) - - data = b'some bytes!' - with open(filename, 'wb') as file_obj: - file_obj.write(data) - - fake_response = requests.Response() - fake_response.status_code = int(http.client.OK) - fake_response._content = b'' - resumable_url = 'http://test.invalid?upload_id=7up' - fake_response.headers['location'] = resumable_url - - post_method = mock.Mock(return_value=fake_response, spec=[]) - transport = mock.Mock(request=post_method, spec=['request']) - - .. doctest:: resumable-explicit-size - - >>> import os - >>> - >>> upload.total_bytes is None - True - >>> - >>> stream = open(filename, 'rb') - >>> total_bytes = os.path.getsize(filename) - >>> metadata = {'name': filename} - >>> response = upload.initiate( - ... transport, stream, metadata, 'text/plain', - ... total_bytes=total_bytes) - >>> response - - >>> - >>> upload.total_bytes == total_bytes - True - - .. testcleanup:: resumable-explicit-size - - os.remove(filename) - - If the stream is in a "final" state (i.e. it won't have any more bytes - written to it), the total number of bytes can be determined implicitly - from the ``stream`` itself: - - .. testsetup:: resumable-implicit-size - - import io - - import mock - import requests - import http.client - - from google.resumable_media.requests import ResumableUpload - - upload_url = 'http://test.invalid' - chunk_size = 3 * 1024 * 1024 # 3MB - upload = ResumableUpload(upload_url, chunk_size) - - fake_response = requests.Response() - fake_response.status_code = int(http.client.OK) - fake_response._content = b'' - resumable_url = 'http://test.invalid?upload_id=7up' - fake_response.headers['location'] = resumable_url - - post_method = mock.Mock(return_value=fake_response, spec=[]) - transport = mock.Mock(request=post_method, spec=['request']) - - data = b'some MOAR bytes!' - metadata = {'name': 'some-file.jpg'} - content_type = 'image/jpeg' - - .. doctest:: resumable-implicit-size - - >>> stream = io.BytesIO(data) - >>> response = upload.initiate( - ... transport, stream, metadata, content_type) - >>> - >>> upload.total_bytes == len(data) - True - - If the size of the resource is **unknown** when the upload is initiated, - the ``stream_final`` argument can be used. This might occur if the - resource is being dynamically created on the client (e.g. application - logs). To use this argument: - - .. testsetup:: resumable-unknown-size - - import io - - import mock - import requests - import http.client - - from google.resumable_media.requests import ResumableUpload - - upload_url = 'http://test.invalid' - chunk_size = 3 * 1024 * 1024 # 3MB - upload = ResumableUpload(upload_url, chunk_size) - - fake_response = requests.Response() - fake_response.status_code = int(http.client.OK) - fake_response._content = b'' - resumable_url = 'http://test.invalid?upload_id=7up' - fake_response.headers['location'] = resumable_url - - post_method = mock.Mock(return_value=fake_response, spec=[]) - transport = mock.Mock(request=post_method, spec=['request']) - - metadata = {'name': 'some-file.jpg'} - content_type = 'application/octet-stream' - - stream = io.BytesIO(b'data') - - .. doctest:: resumable-unknown-size - - >>> response = upload.initiate( - ... transport, stream, metadata, content_type, - ... stream_final=False) - >>> - >>> upload.total_bytes is None - True - - Args: - upload_url (str): The URL where the resumable upload will be initiated. - chunk_size (int): The size of each chunk used to upload the resource. - headers (Optional[Mapping[str, str]]): Extra headers that should - be sent with the :meth:`initiate` request, e.g. headers for - encrypted data. These **will not** be sent with - :meth:`transmit_next_chunk` or :meth:`recover` requests. - checksum Optional([str]): The type of checksum to compute to verify - the integrity of the object. After the upload is complete, the - server-computed checksum of the resulting object will be checked - and google.resumable_media.common.DataCorruption will be raised on - a mismatch. The corrupted file will not be deleted from the remote - host automatically. Supported values are "md5", "crc32c" and None. - The default is None. - - Attributes: - upload_url (str): The URL where the content will be uploaded. - - Raises: - ValueError: If ``chunk_size`` is not a multiple of - :data:`.UPLOAD_CHUNK_SIZE`. - """ - - async def initiate( - self, - transport, - stream, - metadata, - content_type, - total_bytes=None, - stream_final=True, - timeout=_request_helpers._DEFAULT_TIMEOUT, - ): - """Initiate a resumable upload. - - By default, this method assumes your ``stream`` is in a "final" - state ready to transmit. However, ``stream_final=False`` can be used - to indicate that the size of the resource is not known. This can happen - if bytes are being dynamically fed into ``stream``, e.g. if the stream - is attached to application logs. - - If ``stream_final=False`` is used, :attr:`chunk_size` bytes will be - read from the stream every time :meth:`transmit_next_chunk` is called. - If one of those reads produces strictly fewer bites than the chunk - size, the upload will be concluded. - - Args: - transport (~requests.Session): A ``requests`` object which can - make authenticated requests. - stream (IO[bytes]): The stream (i.e. file-like object) that will - be uploaded. The stream **must** be at the beginning (i.e. - ``stream.tell() == 0``). - metadata (Mapping[str, str]): The resource metadata, such as an - ACL list. - content_type (str): The content type of the resource, e.g. a JPEG - image has content type ``image/jpeg``. - total_bytes (Optional[int]): The total number of bytes to be - uploaded. If specified, the upload size **will not** be - determined from the stream (even if ``stream_final=True``). - stream_final (Optional[bool]): Indicates if the ``stream`` is - "final" (i.e. no more bytes will be added to it). In this case - we determine the upload size from the size of the stream. If - ``total_bytes`` is passed, this argument will be ignored. - timeout (Optional[Union[float, aiohttp.ClientTimeout]]): - The number of seconds to wait for the server response. - Depending on the retry strategy, a request may be repeated - several times using the same timeout each time. - Can also be passed as an `aiohttp.ClientTimeout` object. - - Returns: - ~requests.Response: The HTTP response returned by ``transport``. - """ - method, url, payload, headers = self._prepare_initiate_request( - stream, - metadata, - content_type, - total_bytes=total_bytes, - stream_final=stream_final, - ) - response = await _request_helpers.http_request( - transport, - method, - url, - data=payload, - headers=headers, - retry_strategy=self._retry_strategy, - timeout=timeout, - ) - self._process_initiate_response(response) - return response - - async def transmit_next_chunk( - self, transport, timeout=_request_helpers._DEFAULT_TIMEOUT - ): - """Transmit the next chunk of the resource to be uploaded. - - If the current upload was initiated with ``stream_final=False``, - this method will dynamically determine if the upload has completed. - The upload will be considered complete if the stream produces - fewer than :attr:`chunk_size` bytes when a chunk is read from it. - - In the case of failure, an exception is thrown that preserves the - failed response: - - .. testsetup:: bad-response - - import io - - import mock - import requests - import http.client - - from google import resumable_media - import google.resumable_media.requests.upload as upload_mod - - transport = mock.Mock(spec=['request']) - fake_response = requests.Response() - fake_response.status_code = int(http.client.BAD_REQUEST) - transport.request.return_value = fake_response - - upload_url = 'http://test.invalid' - upload = upload_mod.ResumableUpload( - upload_url, resumable_media.UPLOAD_CHUNK_SIZE) - # Fake that the upload has been initiate()-d - data = b'data is here' - upload._stream = io.BytesIO(data) - upload._total_bytes = len(data) - upload._resumable_url = 'http://test.invalid?upload_id=nope' - - .. doctest:: bad-response - :options: +NORMALIZE_WHITESPACE - - >>> error = None - >>> try: - ... upload.transmit_next_chunk(transport) - ... except resumable_media.InvalidResponse as caught_exc: - ... error = caught_exc - ... - >>> error - InvalidResponse('Request failed with status code', 400, - 'Expected one of', , 308) - >>> error.response - - - Args: - transport (~requests.Session): A ``requests`` object which can - make authenticated requests. - timeout (Optional[Union[float, aiohttp.ClientTimeout]]): - The number of seconds to wait for the server response. - Depending on the retry strategy, a request may be repeated - several times using the same timeout each time. - Can also be passed as an `aiohttp.ClientTimeout` object. - - Returns: - ~requests.Response: The HTTP response returned by ``transport``. - - Raises: - ~google.resumable_media.common.InvalidResponse: If the status - code is not 200 or 308. - ~google.resumable_media.common.DataCorruption: If this is the final - chunk, a checksum validation was requested, and the checksum - does not match or is not available. - """ - method, url, payload, headers = self._prepare_request() - response = await _request_helpers.http_request( - transport, - method, - url, - data=payload, - headers=headers, - retry_strategy=self._retry_strategy, - timeout=timeout, - ) - await self._process_resumable_response(response, len(payload)) - return response - - async def recover(self, transport): - """Recover from a failure. - - This method should be used when a :class:`ResumableUpload` is in an - :attr:`~ResumableUpload.invalid` state due to a request failure. - - This will verify the progress with the server and make sure the - current upload is in a valid state before :meth:`transmit_next_chunk` - can be used again. - - Args: - transport (~requests.Session): A ``requests`` object which can - make authenticated requests. - - Returns: - ~requests.Response: The HTTP response returned by ``transport``. - """ - method, url, payload, headers = self._prepare_recover_request() - # NOTE: We assume "payload is None" but pass it along anyway. - response = await _request_helpers.http_request( - transport, - method, - url, - data=payload, - headers=headers, - retry_strategy=self._retry_strategy, - ) - self._process_recover_response(response) - return response diff --git a/notification-service/venv/Lib/site-packages/google/_upb/_message.pyd b/notification-service/venv/Lib/site-packages/google/_upb/_message.pyd deleted file mode 100644 index a9e1138..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/_upb/_message.pyd and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/annotations_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/annotations_pb2.cpython-312.pyc deleted file mode 100644 index 42515a9..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/annotations_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/auth_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/auth_pb2.cpython-312.pyc deleted file mode 100644 index 321301b..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/auth_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/backend_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/backend_pb2.cpython-312.pyc deleted file mode 100644 index 16936a9..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/backend_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/billing_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/billing_pb2.cpython-312.pyc deleted file mode 100644 index d4aa896..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/billing_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/client_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/client_pb2.cpython-312.pyc deleted file mode 100644 index 360d42f..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/client_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/config_change_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/config_change_pb2.cpython-312.pyc deleted file mode 100644 index f970bea..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/config_change_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/consumer_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/consumer_pb2.cpython-312.pyc deleted file mode 100644 index ad1e72c..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/consumer_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/context_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/context_pb2.cpython-312.pyc deleted file mode 100644 index a153fba..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/context_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/control_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/control_pb2.cpython-312.pyc deleted file mode 100644 index bbc45dc..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/control_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/distribution_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/distribution_pb2.cpython-312.pyc deleted file mode 100644 index 7b26b2c..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/distribution_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/documentation_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/documentation_pb2.cpython-312.pyc deleted file mode 100644 index db7c5d1..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/documentation_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/endpoint_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/endpoint_pb2.cpython-312.pyc deleted file mode 100644 index 7c80fd4..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/endpoint_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/error_reason_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/error_reason_pb2.cpython-312.pyc deleted file mode 100644 index 7b8fe37..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/error_reason_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/field_behavior_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/field_behavior_pb2.cpython-312.pyc deleted file mode 100644 index 3fe69e5..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/field_behavior_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/field_info_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/field_info_pb2.cpython-312.pyc deleted file mode 100644 index d5fabd6..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/field_info_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/http_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/http_pb2.cpython-312.pyc deleted file mode 100644 index 6699e61..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/http_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/httpbody_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/httpbody_pb2.cpython-312.pyc deleted file mode 100644 index d6c6a39..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/httpbody_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/label_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/label_pb2.cpython-312.pyc deleted file mode 100644 index 22fb363..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/label_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/launch_stage_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/launch_stage_pb2.cpython-312.pyc deleted file mode 100644 index 9ac4394..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/launch_stage_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/log_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/log_pb2.cpython-312.pyc deleted file mode 100644 index edd14d9..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/log_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/logging_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/logging_pb2.cpython-312.pyc deleted file mode 100644 index 77fdd83..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/logging_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/metric_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/metric_pb2.cpython-312.pyc deleted file mode 100644 index 9fcb090..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/metric_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/monitored_resource_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/monitored_resource_pb2.cpython-312.pyc deleted file mode 100644 index 3a3740d..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/monitored_resource_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/monitoring_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/monitoring_pb2.cpython-312.pyc deleted file mode 100644 index 21b95b0..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/monitoring_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/policy_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/policy_pb2.cpython-312.pyc deleted file mode 100644 index e748941..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/policy_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/quota_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/quota_pb2.cpython-312.pyc deleted file mode 100644 index 583d1ad..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/quota_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/resource_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/resource_pb2.cpython-312.pyc deleted file mode 100644 index 1ab744f..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/resource_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/routing_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/routing_pb2.cpython-312.pyc deleted file mode 100644 index d6e9c6c..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/routing_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/service_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/service_pb2.cpython-312.pyc deleted file mode 100644 index 48e5ff3..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/service_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/source_info_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/source_info_pb2.cpython-312.pyc deleted file mode 100644 index 254fa94..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/source_info_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/system_parameter_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/system_parameter_pb2.cpython-312.pyc deleted file mode 100644 index b52098d..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/system_parameter_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/usage_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/usage_pb2.cpython-312.pyc deleted file mode 100644 index 27f9728..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/usage_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/__pycache__/visibility_pb2.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api/__pycache__/visibility_pb2.cpython-312.pyc deleted file mode 100644 index 381edfb..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api/__pycache__/visibility_pb2.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api/annotations.proto b/notification-service/venv/Lib/site-packages/google/api/annotations.proto deleted file mode 100644 index 417edd8..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/annotations.proto +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/api/http.proto"; -import "google/protobuf/descriptor.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; -option java_multiple_files = true; -option java_outer_classname = "AnnotationsProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -extend google.protobuf.MethodOptions { - // See `HttpRule`. - HttpRule http = 72295728; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/annotations_pb2.py b/notification-service/venv/Lib/site-packages/google/api/annotations_pb2.py deleted file mode 100644 index ac5cf8d..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/annotations_pb2.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/annotations.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 - -from google.api import http_pb2 as google_dot_api_dot_http__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x1cgoogle/api/annotations.proto\x12\ngoogle.api\x1a\x15google/api/http.proto\x1a google/protobuf/descriptor.proto:E\n\x04http\x12\x1e.google.protobuf.MethodOptions\x18\xb0\xca\xbc" \x01(\x0b\x32\x14.google.api.HttpRuleBn\n\x0e\x63om.google.apiB\x10\x41nnotationsProtoP\x01ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, "google.api.annotations_pb2", _globals -) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\020AnnotationsProtoP\001ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\242\002\004GAPI" -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/annotations_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/annotations_pb2.pyi deleted file mode 100644 index 4c4afeb..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/annotations_pb2.pyi +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pb2 as _descriptor_pb2 - -from google.api import http_pb2 as _http_pb2 - -DESCRIPTOR: _descriptor.FileDescriptor -HTTP_FIELD_NUMBER: _ClassVar[int] -http: _descriptor.FieldDescriptor diff --git a/notification-service/venv/Lib/site-packages/google/api/auth.proto b/notification-service/venv/Lib/site-packages/google/api/auth.proto deleted file mode 100644 index 9b025ba..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/auth.proto +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "AuthProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// `Authentication` defines the authentication configuration for API methods -// provided by an API service. -// -// Example: -// -// name: calendar.googleapis.com -// authentication: -// providers: -// - id: google_calendar_auth -// jwks_uri: https://www.googleapis.com/oauth2/v1/certs -// issuer: https://securetoken.google.com -// rules: -// - selector: "*" -// requirements: -// provider_id: google_calendar_auth -// - selector: google.calendar.Delegate -// oauth: -// canonical_scopes: https://www.googleapis.com/auth/calendar.read -message Authentication { - // A list of authentication rules that apply to individual API methods. - // - // **NOTE:** All service configuration rules follow "last one wins" order. - repeated AuthenticationRule rules = 3; - - // Defines a set of authentication providers that a service supports. - repeated AuthProvider providers = 4; -} - -// Authentication rules for the service. -// -// By default, if a method has any authentication requirements, every request -// must include a valid credential matching one of the requirements. -// It's an error to include more than one kind of credential in a single -// request. -// -// If a method doesn't have any auth requirements, request credentials will be -// ignored. -message AuthenticationRule { - // Selects the methods to which this rule applies. - // - // Refer to [selector][google.api.DocumentationRule.selector] for syntax - // details. - string selector = 1; - - // The requirements for OAuth credentials. - OAuthRequirements oauth = 2; - - // If true, the service accepts API keys without any other credential. - // This flag only applies to HTTP and gRPC requests. - bool allow_without_credential = 5; - - // Requirements for additional authentication providers. - repeated AuthRequirement requirements = 7; -} - -// Specifies a location to extract JWT from an API request. -message JwtLocation { - oneof in { - // Specifies HTTP header name to extract JWT token. - string header = 1; - - // Specifies URL query parameter name to extract JWT token. - string query = 2; - - // Specifies cookie name to extract JWT token. - string cookie = 4; - } - - // The value prefix. The value format is "value_prefix{token}" - // Only applies to "in" header type. Must be empty for "in" query type. - // If not empty, the header value has to match (case sensitive) this prefix. - // If not matched, JWT will not be extracted. If matched, JWT will be - // extracted after the prefix is removed. - // - // For example, for "Authorization: Bearer {JWT}", - // value_prefix="Bearer " with a space at the end. - string value_prefix = 3; -} - -// Configuration for an authentication provider, including support for -// [JSON Web Token -// (JWT)](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32). -message AuthProvider { - // The unique identifier of the auth provider. It will be referred to by - // `AuthRequirement.provider_id`. - // - // Example: "bookstore_auth". - string id = 1; - - // Identifies the principal that issued the JWT. See - // https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32#section-4.1.1 - // Usually a URL or an email address. - // - // Example: https://securetoken.google.com - // Example: 1234567-compute@developer.gserviceaccount.com - string issuer = 2; - - // URL of the provider's public key set to validate signature of the JWT. See - // [OpenID - // Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata). - // Optional if the key set document: - // - can be retrieved from - // [OpenID - // Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) - // of the issuer. - // - can be inferred from the email domain of the issuer (e.g. a Google - // service account). - // - // Example: https://www.googleapis.com/oauth2/v1/certs - string jwks_uri = 3; - - // The list of JWT - // [audiences](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32#section-4.1.3). - // that are allowed to access. A JWT containing any of these audiences will - // be accepted. When this setting is absent, JWTs with audiences: - // - "https://[service.name]/[google.protobuf.Api.name]" - // - "https://[service.name]/" - // will be accepted. - // For example, if no audiences are in the setting, LibraryService API will - // accept JWTs with the following audiences: - // - - // https://library-example.googleapis.com/google.example.library.v1.LibraryService - // - https://library-example.googleapis.com/ - // - // Example: - // - // audiences: bookstore_android.apps.googleusercontent.com, - // bookstore_web.apps.googleusercontent.com - string audiences = 4; - - // Redirect URL if JWT token is required but not present or is expired. - // Implement authorizationUrl of securityDefinitions in OpenAPI spec. - string authorization_url = 5; - - // Defines the locations to extract the JWT. For now it is only used by the - // Cloud Endpoints to store the OpenAPI extension [x-google-jwt-locations] - // (https://cloud.google.com/endpoints/docs/openapi/openapi-extensions#x-google-jwt-locations) - // - // JWT locations can be one of HTTP headers, URL query parameters or - // cookies. The rule is that the first match wins. - // - // If not specified, default to use following 3 locations: - // 1) Authorization: Bearer - // 2) x-goog-iap-jwt-assertion - // 3) access_token query parameter - // - // Default locations can be specified as followings: - // jwt_locations: - // - header: Authorization - // value_prefix: "Bearer " - // - header: x-goog-iap-jwt-assertion - // - query: access_token - repeated JwtLocation jwt_locations = 6; -} - -// OAuth scopes are a way to define data and permissions on data. For example, -// there are scopes defined for "Read-only access to Google Calendar" and -// "Access to Cloud Platform". Users can consent to a scope for an application, -// giving it permission to access that data on their behalf. -// -// OAuth scope specifications should be fairly coarse grained; a user will need -// to see and understand the text description of what your scope means. -// -// In most cases: use one or at most two OAuth scopes for an entire family of -// products. If your product has multiple APIs, you should probably be sharing -// the OAuth scope across all of those APIs. -// -// When you need finer grained OAuth consent screens: talk with your product -// management about how developers will use them in practice. -// -// Please note that even though each of the canonical scopes is enough for a -// request to be accepted and passed to the backend, a request can still fail -// due to the backend requiring additional scopes or permissions. -message OAuthRequirements { - // The list of publicly documented OAuth scopes that are allowed access. An - // OAuth token containing any of these scopes will be accepted. - // - // - // Example: - // - // canonical_scopes: https://www.googleapis.com/auth/calendar, - // https://www.googleapis.com/auth/calendar.read - string canonical_scopes = 1; -} - -// User-defined authentication requirements, including support for -// [JSON Web Token -// (JWT)](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32). -message AuthRequirement { - // [id][google.api.AuthProvider.id] from authentication provider. - // - // Example: - // - // provider_id: bookstore_auth - string provider_id = 1; - - // NOTE: This will be deprecated soon, once AuthProvider.audiences is - // implemented and accepted in all the runtime components. - // - // The list of JWT - // [audiences](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32#section-4.1.3). - // that are allowed to access. A JWT containing any of these audiences will - // be accepted. When this setting is absent, only JWTs with audience - // "https://[Service_name][google.api.Service.name]/[API_name][google.protobuf.Api.name]" - // will be accepted. For example, if no audiences are in the setting, - // LibraryService API will only accept JWTs with the following audience - // "https://library-example.googleapis.com/google.example.library.v1.LibraryService". - // - // Example: - // - // audiences: bookstore_android.apps.googleusercontent.com, - // bookstore_web.apps.googleusercontent.com - string audiences = 2; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/auth_pb2.py b/notification-service/venv/Lib/site-packages/google/api/auth_pb2.py deleted file mode 100644 index 8287438..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/auth_pb2.py +++ /dev/null @@ -1,56 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/auth.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x15google/api/auth.proto\x12\ngoogle.api"l\n\x0e\x41uthentication\x12-\n\x05rules\x18\x03 \x03(\x0b\x32\x1e.google.api.AuthenticationRule\x12+\n\tproviders\x18\x04 \x03(\x0b\x32\x18.google.api.AuthProvider"\xa9\x01\n\x12\x41uthenticationRule\x12\x10\n\x08selector\x18\x01 \x01(\t\x12,\n\x05oauth\x18\x02 \x01(\x0b\x32\x1d.google.api.OAuthRequirements\x12 \n\x18\x61llow_without_credential\x18\x05 \x01(\x08\x12\x31\n\x0crequirements\x18\x07 \x03(\x0b\x32\x1b.google.api.AuthRequirement"^\n\x0bJwtLocation\x12\x10\n\x06header\x18\x01 \x01(\tH\x00\x12\x0f\n\x05query\x18\x02 \x01(\tH\x00\x12\x10\n\x06\x63ookie\x18\x04 \x01(\tH\x00\x12\x14\n\x0cvalue_prefix\x18\x03 \x01(\tB\x04\n\x02in"\x9a\x01\n\x0c\x41uthProvider\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0e\n\x06issuer\x18\x02 \x01(\t\x12\x10\n\x08jwks_uri\x18\x03 \x01(\t\x12\x11\n\taudiences\x18\x04 \x01(\t\x12\x19\n\x11\x61uthorization_url\x18\x05 \x01(\t\x12.\n\rjwt_locations\x18\x06 \x03(\x0b\x32\x17.google.api.JwtLocation"-\n\x11OAuthRequirements\x12\x18\n\x10\x63\x61nonical_scopes\x18\x01 \x01(\t"9\n\x0f\x41uthRequirement\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x11\n\taudiences\x18\x02 \x01(\tBk\n\x0e\x63om.google.apiB\tAuthProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.auth_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\tAuthProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_AUTHENTICATION"]._serialized_start = 37 - _globals["_AUTHENTICATION"]._serialized_end = 145 - _globals["_AUTHENTICATIONRULE"]._serialized_start = 148 - _globals["_AUTHENTICATIONRULE"]._serialized_end = 317 - _globals["_JWTLOCATION"]._serialized_start = 319 - _globals["_JWTLOCATION"]._serialized_end = 413 - _globals["_AUTHPROVIDER"]._serialized_start = 416 - _globals["_AUTHPROVIDER"]._serialized_end = 570 - _globals["_OAUTHREQUIREMENTS"]._serialized_start = 572 - _globals["_OAUTHREQUIREMENTS"]._serialized_end = 617 - _globals["_AUTHREQUIREMENT"]._serialized_start = 619 - _globals["_AUTHREQUIREMENT"]._serialized_end = 676 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/auth_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/auth_pb2.pyi deleted file mode 100644 index 660d996..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/auth_pb2.pyi +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor - -class Authentication(_message.Message): - __slots__ = ("rules", "providers") - RULES_FIELD_NUMBER: _ClassVar[int] - PROVIDERS_FIELD_NUMBER: _ClassVar[int] - rules: _containers.RepeatedCompositeFieldContainer[AuthenticationRule] - providers: _containers.RepeatedCompositeFieldContainer[AuthProvider] - def __init__( - self, - rules: _Optional[_Iterable[_Union[AuthenticationRule, _Mapping]]] = ..., - providers: _Optional[_Iterable[_Union[AuthProvider, _Mapping]]] = ..., - ) -> None: ... - -class AuthenticationRule(_message.Message): - __slots__ = ("selector", "oauth", "allow_without_credential", "requirements") - SELECTOR_FIELD_NUMBER: _ClassVar[int] - OAUTH_FIELD_NUMBER: _ClassVar[int] - ALLOW_WITHOUT_CREDENTIAL_FIELD_NUMBER: _ClassVar[int] - REQUIREMENTS_FIELD_NUMBER: _ClassVar[int] - selector: str - oauth: OAuthRequirements - allow_without_credential: bool - requirements: _containers.RepeatedCompositeFieldContainer[AuthRequirement] - def __init__( - self, - selector: _Optional[str] = ..., - oauth: _Optional[_Union[OAuthRequirements, _Mapping]] = ..., - allow_without_credential: bool = ..., - requirements: _Optional[_Iterable[_Union[AuthRequirement, _Mapping]]] = ..., - ) -> None: ... - -class JwtLocation(_message.Message): - __slots__ = ("header", "query", "cookie", "value_prefix") - HEADER_FIELD_NUMBER: _ClassVar[int] - QUERY_FIELD_NUMBER: _ClassVar[int] - COOKIE_FIELD_NUMBER: _ClassVar[int] - VALUE_PREFIX_FIELD_NUMBER: _ClassVar[int] - header: str - query: str - cookie: str - value_prefix: str - def __init__( - self, - header: _Optional[str] = ..., - query: _Optional[str] = ..., - cookie: _Optional[str] = ..., - value_prefix: _Optional[str] = ..., - ) -> None: ... - -class AuthProvider(_message.Message): - __slots__ = ( - "id", - "issuer", - "jwks_uri", - "audiences", - "authorization_url", - "jwt_locations", - ) - ID_FIELD_NUMBER: _ClassVar[int] - ISSUER_FIELD_NUMBER: _ClassVar[int] - JWKS_URI_FIELD_NUMBER: _ClassVar[int] - AUDIENCES_FIELD_NUMBER: _ClassVar[int] - AUTHORIZATION_URL_FIELD_NUMBER: _ClassVar[int] - JWT_LOCATIONS_FIELD_NUMBER: _ClassVar[int] - id: str - issuer: str - jwks_uri: str - audiences: str - authorization_url: str - jwt_locations: _containers.RepeatedCompositeFieldContainer[JwtLocation] - def __init__( - self, - id: _Optional[str] = ..., - issuer: _Optional[str] = ..., - jwks_uri: _Optional[str] = ..., - audiences: _Optional[str] = ..., - authorization_url: _Optional[str] = ..., - jwt_locations: _Optional[_Iterable[_Union[JwtLocation, _Mapping]]] = ..., - ) -> None: ... - -class OAuthRequirements(_message.Message): - __slots__ = ("canonical_scopes",) - CANONICAL_SCOPES_FIELD_NUMBER: _ClassVar[int] - canonical_scopes: str - def __init__(self, canonical_scopes: _Optional[str] = ...) -> None: ... - -class AuthRequirement(_message.Message): - __slots__ = ("provider_id", "audiences") - PROVIDER_ID_FIELD_NUMBER: _ClassVar[int] - AUDIENCES_FIELD_NUMBER: _ClassVar[int] - provider_id: str - audiences: str - def __init__( - self, provider_id: _Optional[str] = ..., audiences: _Optional[str] = ... - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/backend.proto b/notification-service/venv/Lib/site-packages/google/api/backend.proto deleted file mode 100644 index 7bff445..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/backend.proto +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "BackendProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// `Backend` defines the backend configuration for a service. -message Backend { - // A list of API backend rules that apply to individual API methods. - // - // **NOTE:** All service configuration rules follow "last one wins" order. - repeated BackendRule rules = 1; -} - -// A backend rule provides configuration for an individual API element. -message BackendRule { - // Path Translation specifies how to combine the backend address with the - // request path in order to produce the appropriate forwarding URL for the - // request. - // - // Path Translation is applicable only to HTTP-based backends. Backends which - // do not accept requests over HTTP/HTTPS should leave `path_translation` - // unspecified. - enum PathTranslation { - PATH_TRANSLATION_UNSPECIFIED = 0; - - // Use the backend address as-is, with no modification to the path. If the - // URL pattern contains variables, the variable names and values will be - // appended to the query string. If a query string parameter and a URL - // pattern variable have the same name, this may result in duplicate keys in - // the query string. - // - // # Examples - // - // Given the following operation config: - // - // Method path: /api/company/{cid}/user/{uid} - // Backend address: https://example.cloudfunctions.net/getUser - // - // Requests to the following request paths will call the backend at the - // translated path: - // - // Request path: /api/company/widgetworks/user/johndoe - // Translated: - // https://example.cloudfunctions.net/getUser?cid=widgetworks&uid=johndoe - // - // Request path: /api/company/widgetworks/user/johndoe?timezone=EST - // Translated: - // https://example.cloudfunctions.net/getUser?timezone=EST&cid=widgetworks&uid=johndoe - CONSTANT_ADDRESS = 1; - - // The request path will be appended to the backend address. - // - // # Examples - // - // Given the following operation config: - // - // Method path: /api/company/{cid}/user/{uid} - // Backend address: https://example.appspot.com - // - // Requests to the following request paths will call the backend at the - // translated path: - // - // Request path: /api/company/widgetworks/user/johndoe - // Translated: - // https://example.appspot.com/api/company/widgetworks/user/johndoe - // - // Request path: /api/company/widgetworks/user/johndoe?timezone=EST - // Translated: - // https://example.appspot.com/api/company/widgetworks/user/johndoe?timezone=EST - APPEND_PATH_TO_ADDRESS = 2; - } - - // Selects the methods to which this rule applies. - // - // Refer to [selector][google.api.DocumentationRule.selector] for syntax - // details. - string selector = 1; - - // The address of the API backend. - // - // The scheme is used to determine the backend protocol and security. - // The following schemes are accepted: - // - // SCHEME PROTOCOL SECURITY - // http:// HTTP None - // https:// HTTP TLS - // grpc:// gRPC None - // grpcs:// gRPC TLS - // - // It is recommended to explicitly include a scheme. Leaving out the scheme - // may cause constrasting behaviors across platforms. - // - // If the port is unspecified, the default is: - // - 80 for schemes without TLS - // - 443 for schemes with TLS - // - // For HTTP backends, use [protocol][google.api.BackendRule.protocol] - // to specify the protocol version. - string address = 2; - - // The number of seconds to wait for a response from a request. The default - // varies based on the request protocol and deployment environment. - double deadline = 3; - - // Deprecated, do not use. - double min_deadline = 4 [deprecated = true]; - - // The number of seconds to wait for the completion of a long running - // operation. The default is no deadline. - double operation_deadline = 5; - - // Path translation specifies how to combine the backend address with the - // request path in order to produce the appropriate forwarding URL for the - // request. See [PathTranslation][google.api.BackendRule.PathTranslation] for - // more details. - PathTranslation path_translation = 6; - - // Authentication settings used by the backend. - // - // These are typically used to provide service management functionality to - // a backend served on a publicly-routable URL. The `authentication` - // details should match the authentication behavior used by the backend. - // - // For example, specifying `jwt_audience` implies that the backend expects - // authentication via a JWT. - // - // When authentication is unspecified, the resulting behavior is the same - // as `disable_auth` set to `true`. - // - // Refer to https://developers.google.com/identity/protocols/OpenIDConnect for - // JWT ID token. - oneof authentication { - // The JWT audience is used when generating a JWT ID token for the backend. - // This ID token will be added in the HTTP "authorization" header, and sent - // to the backend. - string jwt_audience = 7; - - // When disable_auth is true, a JWT ID token won't be generated and the - // original "Authorization" HTTP header will be preserved. If the header is - // used to carry the original token and is expected by the backend, this - // field must be set to true to preserve the header. - bool disable_auth = 8; - } - - // The protocol used for sending a request to the backend. - // The supported values are "http/1.1" and "h2". - // - // The default value is inferred from the scheme in the - // [address][google.api.BackendRule.address] field: - // - // SCHEME PROTOCOL - // http:// http/1.1 - // https:// http/1.1 - // grpc:// h2 - // grpcs:// h2 - // - // For secure HTTP backends (https://) that support HTTP/2, set this field - // to "h2" for improved performance. - // - // Configuring this field to non-default values is only supported for secure - // HTTP backends. This field will be ignored for all other backends. - // - // See - // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids - // for more details on the supported values. - string protocol = 9; - - // The map between request protocol and the backend address. - map overrides_by_request_protocol = 10; - - // The load balancing policy used for connection to the application backend. - // - // Defined as an arbitrary string to accomondate custom load balancing - // policies supported by the underlying channel, but suggest most users use - // one of the standard policies, such as the default, "RoundRobin". - string load_balancing_policy = 11; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/backend_pb2.py b/notification-service/venv/Lib/site-packages/google/api/backend_pb2.py deleted file mode 100644 index 31dabcd..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/backend_pb2.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/backend.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x18google/api/backend.proto\x12\ngoogle.api"1\n\x07\x42\x61\x63kend\x12&\n\x05rules\x18\x01 \x03(\x0b\x32\x17.google.api.BackendRule"\xd1\x04\n\x0b\x42\x61\x63kendRule\x12\x10\n\x08selector\x18\x01 \x01(\t\x12\x0f\n\x07\x61\x64\x64ress\x18\x02 \x01(\t\x12\x10\n\x08\x64\x65\x61\x64line\x18\x03 \x01(\x01\x12\x18\n\x0cmin_deadline\x18\x04 \x01(\x01\x42\x02\x18\x01\x12\x1a\n\x12operation_deadline\x18\x05 \x01(\x01\x12\x41\n\x10path_translation\x18\x06 \x01(\x0e\x32\'.google.api.BackendRule.PathTranslation\x12\x16\n\x0cjwt_audience\x18\x07 \x01(\tH\x00\x12\x16\n\x0c\x64isable_auth\x18\x08 \x01(\x08H\x00\x12\x10\n\x08protocol\x18\t \x01(\t\x12^\n\x1doverrides_by_request_protocol\x18\n \x03(\x0b\x32\x37.google.api.BackendRule.OverridesByRequestProtocolEntry\x12\x1d\n\x15load_balancing_policy\x18\x0b \x01(\t\x1aZ\n\x1fOverridesByRequestProtocolEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05value\x18\x02 \x01(\x0b\x32\x17.google.api.BackendRule:\x02\x38\x01"e\n\x0fPathTranslation\x12 \n\x1cPATH_TRANSLATION_UNSPECIFIED\x10\x00\x12\x14\n\x10\x43ONSTANT_ADDRESS\x10\x01\x12\x1a\n\x16\x41PPEND_PATH_TO_ADDRESS\x10\x02\x42\x10\n\x0e\x61uthenticationBn\n\x0e\x63om.google.apiB\x0c\x42\x61\x63kendProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.backend_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\014BackendProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_BACKENDRULE_OVERRIDESBYREQUESTPROTOCOLENTRY"]._options = None - _globals[ - "_BACKENDRULE_OVERRIDESBYREQUESTPROTOCOLENTRY" - ]._serialized_options = b"8\001" - _globals["_BACKENDRULE"].fields_by_name["min_deadline"]._options = None - _globals["_BACKENDRULE"].fields_by_name[ - "min_deadline" - ]._serialized_options = b"\030\001" - _globals["_BACKEND"]._serialized_start = 40 - _globals["_BACKEND"]._serialized_end = 89 - _globals["_BACKENDRULE"]._serialized_start = 92 - _globals["_BACKENDRULE"]._serialized_end = 685 - _globals["_BACKENDRULE_OVERRIDESBYREQUESTPROTOCOLENTRY"]._serialized_start = 474 - _globals["_BACKENDRULE_OVERRIDESBYREQUESTPROTOCOLENTRY"]._serialized_end = 564 - _globals["_BACKENDRULE_PATHTRANSLATION"]._serialized_start = 566 - _globals["_BACKENDRULE_PATHTRANSLATION"]._serialized_end = 667 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/backend_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/backend_pb2.pyi deleted file mode 100644 index fbf8f33..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/backend_pb2.pyi +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper - -DESCRIPTOR: _descriptor.FileDescriptor - -class Backend(_message.Message): - __slots__ = ("rules",) - RULES_FIELD_NUMBER: _ClassVar[int] - rules: _containers.RepeatedCompositeFieldContainer[BackendRule] - def __init__( - self, rules: _Optional[_Iterable[_Union[BackendRule, _Mapping]]] = ... - ) -> None: ... - -class BackendRule(_message.Message): - __slots__ = ( - "selector", - "address", - "deadline", - "min_deadline", - "operation_deadline", - "path_translation", - "jwt_audience", - "disable_auth", - "protocol", - "overrides_by_request_protocol", - "load_balancing_policy", - ) - class PathTranslation(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - PATH_TRANSLATION_UNSPECIFIED: _ClassVar[BackendRule.PathTranslation] - CONSTANT_ADDRESS: _ClassVar[BackendRule.PathTranslation] - APPEND_PATH_TO_ADDRESS: _ClassVar[BackendRule.PathTranslation] - - PATH_TRANSLATION_UNSPECIFIED: BackendRule.PathTranslation - CONSTANT_ADDRESS: BackendRule.PathTranslation - APPEND_PATH_TO_ADDRESS: BackendRule.PathTranslation - class OverridesByRequestProtocolEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: BackendRule - def __init__( - self, - key: _Optional[str] = ..., - value: _Optional[_Union[BackendRule, _Mapping]] = ..., - ) -> None: ... - - SELECTOR_FIELD_NUMBER: _ClassVar[int] - ADDRESS_FIELD_NUMBER: _ClassVar[int] - DEADLINE_FIELD_NUMBER: _ClassVar[int] - MIN_DEADLINE_FIELD_NUMBER: _ClassVar[int] - OPERATION_DEADLINE_FIELD_NUMBER: _ClassVar[int] - PATH_TRANSLATION_FIELD_NUMBER: _ClassVar[int] - JWT_AUDIENCE_FIELD_NUMBER: _ClassVar[int] - DISABLE_AUTH_FIELD_NUMBER: _ClassVar[int] - PROTOCOL_FIELD_NUMBER: _ClassVar[int] - OVERRIDES_BY_REQUEST_PROTOCOL_FIELD_NUMBER: _ClassVar[int] - LOAD_BALANCING_POLICY_FIELD_NUMBER: _ClassVar[int] - selector: str - address: str - deadline: float - min_deadline: float - operation_deadline: float - path_translation: BackendRule.PathTranslation - jwt_audience: str - disable_auth: bool - protocol: str - overrides_by_request_protocol: _containers.MessageMap[str, BackendRule] - load_balancing_policy: str - def __init__( - self, - selector: _Optional[str] = ..., - address: _Optional[str] = ..., - deadline: _Optional[float] = ..., - min_deadline: _Optional[float] = ..., - operation_deadline: _Optional[float] = ..., - path_translation: _Optional[_Union[BackendRule.PathTranslation, str]] = ..., - jwt_audience: _Optional[str] = ..., - disable_auth: bool = ..., - protocol: _Optional[str] = ..., - overrides_by_request_protocol: _Optional[_Mapping[str, BackendRule]] = ..., - load_balancing_policy: _Optional[str] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/billing.proto b/notification-service/venv/Lib/site-packages/google/api/billing.proto deleted file mode 100644 index 2b86bb6..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/billing.proto +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "BillingProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// Billing related configuration of the service. -// -// The following example shows how to configure monitored resources and metrics -// for billing, `consumer_destinations` is the only supported destination and -// the monitored resources need at least one label key -// `cloud.googleapis.com/location` to indicate the location of the billing -// usage, using different monitored resources between monitoring and billing is -// recommended so they can be evolved independently: -// -// -// monitored_resources: -// - type: library.googleapis.com/billing_branch -// labels: -// - key: cloud.googleapis.com/location -// description: | -// Predefined label to support billing location restriction. -// - key: city -// description: | -// Custom label to define the city where the library branch is located -// in. -// - key: name -// description: Custom label to define the name of the library branch. -// metrics: -// - name: library.googleapis.com/book/borrowed_count -// metric_kind: DELTA -// value_type: INT64 -// unit: "1" -// billing: -// consumer_destinations: -// - monitored_resource: library.googleapis.com/billing_branch -// metrics: -// - library.googleapis.com/book/borrowed_count -message Billing { - // Configuration of a specific billing destination (Currently only support - // bill against consumer project). - message BillingDestination { - // The monitored resource type. The type must be defined in - // [Service.monitored_resources][google.api.Service.monitored_resources] - // section. - string monitored_resource = 1; - - // Names of the metrics to report to this billing destination. - // Each name must be defined in - // [Service.metrics][google.api.Service.metrics] section. - repeated string metrics = 2; - } - - // Billing configurations for sending metrics to the consumer project. - // There can be multiple consumer destinations per service, each one must have - // a different monitored resource type. A metric can be used in at most - // one consumer destination. - repeated BillingDestination consumer_destinations = 8; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/billing_pb2.py b/notification-service/venv/Lib/site-packages/google/api/billing_pb2.py deleted file mode 100644 index a554331..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/billing_pb2.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/billing.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x18google/api/billing.proto\x12\ngoogle.api"\x93\x01\n\x07\x42illing\x12\x45\n\x15\x63onsumer_destinations\x18\x08 \x03(\x0b\x32&.google.api.Billing.BillingDestination\x1a\x41\n\x12\x42illingDestination\x12\x1a\n\x12monitored_resource\x18\x01 \x01(\t\x12\x0f\n\x07metrics\x18\x02 \x03(\tBn\n\x0e\x63om.google.apiB\x0c\x42illingProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.billing_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\014BillingProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_BILLING"]._serialized_start = 41 - _globals["_BILLING"]._serialized_end = 188 - _globals["_BILLING_BILLINGDESTINATION"]._serialized_start = 123 - _globals["_BILLING_BILLINGDESTINATION"]._serialized_end = 188 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/billing_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/billing_pb2.pyi deleted file mode 100644 index de9ad20..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/billing_pb2.pyi +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor - -class Billing(_message.Message): - __slots__ = ("consumer_destinations",) - class BillingDestination(_message.Message): - __slots__ = ("monitored_resource", "metrics") - MONITORED_RESOURCE_FIELD_NUMBER: _ClassVar[int] - METRICS_FIELD_NUMBER: _ClassVar[int] - monitored_resource: str - metrics: _containers.RepeatedScalarFieldContainer[str] - def __init__( - self, - monitored_resource: _Optional[str] = ..., - metrics: _Optional[_Iterable[str]] = ..., - ) -> None: ... - - CONSUMER_DESTINATIONS_FIELD_NUMBER: _ClassVar[int] - consumer_destinations: _containers.RepeatedCompositeFieldContainer[ - Billing.BillingDestination - ] - def __init__( - self, - consumer_destinations: _Optional[ - _Iterable[_Union[Billing.BillingDestination, _Mapping]] - ] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/client.proto b/notification-service/venv/Lib/site-packages/google/api/client.proto deleted file mode 100644 index 332e0d0..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/client.proto +++ /dev/null @@ -1,598 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/api/launch_stage.proto"; -import "google/protobuf/descriptor.proto"; -import "google/protobuf/duration.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; -option java_multiple_files = true; -option java_outer_classname = "ClientProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -extend google.protobuf.MethodOptions { - // A definition of a client library method signature. - // - // In client libraries, each proto RPC corresponds to one or more methods - // which the end user is able to call, and calls the underlying RPC. - // Normally, this method receives a single argument (a struct or instance - // corresponding to the RPC request object). Defining this field will - // add one or more overloads providing flattened or simpler method signatures - // in some languages. - // - // The fields on the method signature are provided as a comma-separated - // string. - // - // For example, the proto RPC and annotation: - // - // rpc CreateSubscription(CreateSubscriptionRequest) - // returns (Subscription) { - // option (google.api.method_signature) = "name,topic"; - // } - // - // Would add the following Java overload (in addition to the method accepting - // the request object): - // - // public final Subscription createSubscription(String name, String topic) - // - // The following backwards-compatibility guidelines apply: - // - // * Adding this annotation to an unannotated method is backwards - // compatible. - // * Adding this annotation to a method which already has existing - // method signature annotations is backwards compatible if and only if - // the new method signature annotation is last in the sequence. - // * Modifying or removing an existing method signature annotation is - // a breaking change. - // * Re-ordering existing method signature annotations is a breaking - // change. - repeated string method_signature = 1051; -} - -extend google.protobuf.ServiceOptions { - // The hostname for this service. - // This should be specified with no prefix or protocol. - // - // Example: - // - // service Foo { - // option (google.api.default_host) = "foo.googleapi.com"; - // ... - // } - string default_host = 1049; - - // OAuth scopes needed for the client. - // - // Example: - // - // service Foo { - // option (google.api.oauth_scopes) = \ - // "https://www.googleapis.com/auth/cloud-platform"; - // ... - // } - // - // If there is more than one scope, use a comma-separated string: - // - // Example: - // - // service Foo { - // option (google.api.oauth_scopes) = \ - // "https://www.googleapis.com/auth/cloud-platform," - // "https://www.googleapis.com/auth/monitoring"; - // ... - // } - string oauth_scopes = 1050; - - // The API version of this service, which should be sent by version-aware - // clients to the service. This allows services to abide by the schema and - // behavior of the service at the time this API version was deployed. - // The format of the API version must be treated as opaque by clients. - // Services may use a format with an apparent structure, but clients must - // not rely on this to determine components within an API version, or attempt - // to construct other valid API versions. Note that this is for upcoming - // functionality and may not be implemented for all services. - // - // Example: - // - // service Foo { - // option (google.api.api_version) = "v1_20230821_preview"; - // } - string api_version = 525000001; -} - -// Required information for every language. -message CommonLanguageSettings { - // Link to automatically generated reference documentation. Example: - // https://cloud.google.com/nodejs/docs/reference/asset/latest - string reference_docs_uri = 1 [deprecated = true]; - - // The destination where API teams want this client library to be published. - repeated ClientLibraryDestination destinations = 2; - - // Configuration for which RPCs should be generated in the GAPIC client. - // - // Note: This field should not be used in most cases. - SelectiveGapicGeneration selective_gapic_generation = 3; -} - -// Details about how and where to publish client libraries. -message ClientLibrarySettings { - // Version of the API to apply these settings to. This is the full protobuf - // package for the API, ending in the version element. - // Examples: "google.cloud.speech.v1" and "google.spanner.admin.database.v1". - string version = 1; - - // Launch stage of this version of the API. - LaunchStage launch_stage = 2; - - // When using transport=rest, the client request will encode enums as - // numbers rather than strings. - bool rest_numeric_enums = 3; - - // Settings for legacy Java features, supported in the Service YAML. - JavaSettings java_settings = 21; - - // Settings for C++ client libraries. - CppSettings cpp_settings = 22; - - // Settings for PHP client libraries. - PhpSettings php_settings = 23; - - // Settings for Python client libraries. - PythonSettings python_settings = 24; - - // Settings for Node client libraries. - NodeSettings node_settings = 25; - - // Settings for .NET client libraries. - DotnetSettings dotnet_settings = 26; - - // Settings for Ruby client libraries. - RubySettings ruby_settings = 27; - - // Settings for Go client libraries. - GoSettings go_settings = 28; -} - -// This message configures the settings for publishing [Google Cloud Client -// libraries](https://cloud.google.com/apis/docs/cloud-client-libraries) -// generated from the service config. -message Publishing { - // A list of API method settings, e.g. the behavior for methods that use the - // long-running operation pattern. - repeated MethodSettings method_settings = 2; - - // Link to a *public* URI where users can report issues. Example: - // https://issuetracker.google.com/issues/new?component=190865&template=1161103 - string new_issue_uri = 101; - - // Link to product home page. Example: - // https://cloud.google.com/asset-inventory/docs/overview - string documentation_uri = 102; - - // Used as a tracking tag when collecting data about the APIs developer - // relations artifacts like docs, packages delivered to package managers, - // etc. Example: "speech". - string api_short_name = 103; - - // GitHub label to apply to issues and pull requests opened for this API. - string github_label = 104; - - // GitHub teams to be added to CODEOWNERS in the directory in GitHub - // containing source code for the client libraries for this API. - repeated string codeowner_github_teams = 105; - - // A prefix used in sample code when demarking regions to be included in - // documentation. - string doc_tag_prefix = 106; - - // For whom the client library is being published. - ClientLibraryOrganization organization = 107; - - // Client library settings. If the same version string appears multiple - // times in this list, then the last one wins. Settings from earlier - // settings with the same version string are discarded. - repeated ClientLibrarySettings library_settings = 109; - - // Optional link to proto reference documentation. Example: - // https://cloud.google.com/pubsub/lite/docs/reference/rpc - string proto_reference_documentation_uri = 110; - - // Optional link to REST reference documentation. Example: - // https://cloud.google.com/pubsub/lite/docs/reference/rest - string rest_reference_documentation_uri = 111; -} - -// Settings for Java client libraries. -message JavaSettings { - // The package name to use in Java. Clobbers the java_package option - // set in the protobuf. This should be used **only** by APIs - // who have already set the language_settings.java.package_name" field - // in gapic.yaml. API teams should use the protobuf java_package option - // where possible. - // - // Example of a YAML configuration:: - // - // publishing: - // library_settings: - // java_settings: - // library_package: com.google.cloud.pubsub.v1 - string library_package = 1; - - // Configure the Java class name to use instead of the service's for its - // corresponding generated GAPIC client. Keys are fully-qualified - // service names as they appear in the protobuf (including the full - // the language_settings.java.interface_names" field in gapic.yaml. API - // teams should otherwise use the service name as it appears in the - // protobuf. - // - // Example of a YAML configuration:: - // - // publishing: - // java_settings: - // service_class_names: - // - google.pubsub.v1.Publisher: TopicAdmin - // - google.pubsub.v1.Subscriber: SubscriptionAdmin - map service_class_names = 2; - - // Some settings. - CommonLanguageSettings common = 3; -} - -// Settings for C++ client libraries. -message CppSettings { - // Some settings. - CommonLanguageSettings common = 1; -} - -// Settings for Php client libraries. -message PhpSettings { - // Some settings. - CommonLanguageSettings common = 1; - - // The package name to use in Php. Clobbers the php_namespace option - // set in the protobuf. This should be used **only** by APIs - // who have already set the language_settings.php.package_name" field - // in gapic.yaml. API teams should use the protobuf php_namespace option - // where possible. - // - // Example of a YAML configuration:: - // - // publishing: - // library_settings: - // php_settings: - // library_package: Google\Cloud\PubSub\V1 - string library_package = 2; -} - -// Settings for Python client libraries. -message PythonSettings { - // Experimental features to be included during client library generation. - // These fields will be deprecated once the feature graduates and is enabled - // by default. - message ExperimentalFeatures { - // Enables generation of asynchronous REST clients if `rest` transport is - // enabled. By default, asynchronous REST clients will not be generated. - // This feature will be enabled by default 1 month after launching the - // feature in preview packages. - bool rest_async_io_enabled = 1; - - // Enables generation of protobuf code using new types that are more - // Pythonic which are included in `protobuf>=5.29.x`. This feature will be - // enabled by default 1 month after launching the feature in preview - // packages. - bool protobuf_pythonic_types_enabled = 2; - - // Disables generation of an unversioned Python package for this client - // library. This means that the module names will need to be versioned in - // import statements. For example `import google.cloud.library_v2` instead - // of `import google.cloud.library`. - bool unversioned_package_disabled = 3; - } - - // Some settings. - CommonLanguageSettings common = 1; - - // Experimental features to be included during client library generation. - ExperimentalFeatures experimental_features = 2; -} - -// Settings for Node client libraries. -message NodeSettings { - // Some settings. - CommonLanguageSettings common = 1; -} - -// Settings for Dotnet client libraries. -message DotnetSettings { - // Some settings. - CommonLanguageSettings common = 1; - - // Map from original service names to renamed versions. - // This is used when the default generated types - // would cause a naming conflict. (Neither name is - // fully-qualified.) - // Example: Subscriber to SubscriberServiceApi. - map renamed_services = 2; - - // Map from full resource types to the effective short name - // for the resource. This is used when otherwise resource - // named from different services would cause naming collisions. - // Example entry: - // "datalabeling.googleapis.com/Dataset": "DataLabelingDataset" - map renamed_resources = 3; - - // List of full resource types to ignore during generation. - // This is typically used for API-specific Location resources, - // which should be handled by the generator as if they were actually - // the common Location resources. - // Example entry: "documentai.googleapis.com/Location" - repeated string ignored_resources = 4; - - // Namespaces which must be aliased in snippets due to - // a known (but non-generator-predictable) naming collision - repeated string forced_namespace_aliases = 5; - - // Method signatures (in the form "service.method(signature)") - // which are provided separately, so shouldn't be generated. - // Snippets *calling* these methods are still generated, however. - repeated string handwritten_signatures = 6; -} - -// Settings for Ruby client libraries. -message RubySettings { - // Some settings. - CommonLanguageSettings common = 1; -} - -// Settings for Go client libraries. -message GoSettings { - // Some settings. - CommonLanguageSettings common = 1; - - // Map of service names to renamed services. Keys are the package relative - // service names and values are the name to be used for the service client - // and call options. - // - // Example: - // - // publishing: - // go_settings: - // renamed_services: - // Publisher: TopicAdmin - map renamed_services = 2; -} - -// Describes the generator configuration for a method. -message MethodSettings { - // Describes settings to use when generating API methods that use the - // long-running operation pattern. - // All default values below are from those used in the client library - // generators (e.g. - // [Java](https://github.com/googleapis/gapic-generator-java/blob/04c2faa191a9b5a10b92392fe8482279c4404803/src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java)). - message LongRunning { - // Initial delay after which the first poll request will be made. - // Default value: 5 seconds. - google.protobuf.Duration initial_poll_delay = 1; - - // Multiplier to gradually increase delay between subsequent polls until it - // reaches max_poll_delay. - // Default value: 1.5. - float poll_delay_multiplier = 2; - - // Maximum time between two subsequent poll requests. - // Default value: 45 seconds. - google.protobuf.Duration max_poll_delay = 3; - - // Total polling timeout. - // Default value: 5 minutes. - google.protobuf.Duration total_poll_timeout = 4; - } - - // The fully qualified name of the method, for which the options below apply. - // This is used to find the method to apply the options. - // - // Example: - // - // publishing: - // method_settings: - // - selector: google.storage.control.v2.StorageControl.CreateFolder - // # method settings for CreateFolder... - string selector = 1; - - // Describes settings to use for long-running operations when generating - // API methods for RPCs. Complements RPCs that use the annotations in - // google/longrunning/operations.proto. - // - // Example of a YAML configuration:: - // - // publishing: - // method_settings: - // - selector: google.cloud.speech.v2.Speech.BatchRecognize - // long_running: - // initial_poll_delay: 60s # 1 minute - // poll_delay_multiplier: 1.5 - // max_poll_delay: 360s # 6 minutes - // total_poll_timeout: 54000s # 90 minutes - LongRunning long_running = 2; - - // List of top-level fields of the request message, that should be - // automatically populated by the client libraries based on their - // (google.api.field_info).format. Currently supported format: UUID4. - // - // Example of a YAML configuration: - // - // publishing: - // method_settings: - // - selector: google.example.v1.ExampleService.CreateExample - // auto_populated_fields: - // - request_id - repeated string auto_populated_fields = 3; - - // Batching configuration for an API method in client libraries. - // - // Example of a YAML configuration: - // - // publishing: - // method_settings: - // - selector: google.example.v1.ExampleService.BatchCreateExample - // batching: - // element_count_threshold: 1000 - // request_byte_threshold: 100000000 - // delay_threshold_millis: 10 - BatchingConfigProto batching = 4; -} - -// The organization for which the client libraries are being published. -// Affects the url where generated docs are published, etc. -enum ClientLibraryOrganization { - // Not useful. - CLIENT_LIBRARY_ORGANIZATION_UNSPECIFIED = 0; - - // Google Cloud Platform Org. - CLOUD = 1; - - // Ads (Advertising) Org. - ADS = 2; - - // Photos Org. - PHOTOS = 3; - - // Street View Org. - STREET_VIEW = 4; - - // Shopping Org. - SHOPPING = 5; - - // Geo Org. - GEO = 6; - - // Generative AI - https://developers.generativeai.google - GENERATIVE_AI = 7; -} - -// To where should client libraries be published? -enum ClientLibraryDestination { - // Client libraries will neither be generated nor published to package - // managers. - CLIENT_LIBRARY_DESTINATION_UNSPECIFIED = 0; - - // Generate the client library in a repo under github.com/googleapis, - // but don't publish it to package managers. - GITHUB = 10; - - // Publish the library to package managers like nuget.org and npmjs.com. - PACKAGE_MANAGER = 20; -} - -// This message is used to configure the generation of a subset of the RPCs in -// a service for client libraries. -// -// Note: This feature should not be used in most cases. -message SelectiveGapicGeneration { - // An allowlist of the fully qualified names of RPCs that should be included - // on public client surfaces. - repeated string methods = 1; - - // Setting this to true indicates to the client generators that methods - // that would be excluded from the generation should instead be generated - // in a way that indicates these methods should not be consumed by - // end users. How this is expressed is up to individual language - // implementations to decide. Some examples may be: added annotations, - // obfuscated identifiers, or other language idiomatic patterns. - bool generate_omitted_as_internal = 2; -} - -// `BatchingConfigProto` defines the batching configuration for an API method. -message BatchingConfigProto { - // The thresholds which trigger a batched request to be sent. - BatchingSettingsProto thresholds = 1; - - // The request and response fields used in batching. - BatchingDescriptorProto batch_descriptor = 2; -} - -// `BatchingSettingsProto` specifies a set of batching thresholds, each of -// which acts as a trigger to send a batch of messages as a request. At least -// one threshold must be positive nonzero. -message BatchingSettingsProto { - // The number of elements of a field collected into a batch which, if - // exceeded, causes the batch to be sent. - int32 element_count_threshold = 1; - - // The aggregated size of the batched field which, if exceeded, causes the - // batch to be sent. This size is computed by aggregating the sizes of the - // request field to be batched, not of the entire request message. - int64 request_byte_threshold = 2; - - // The duration after which a batch should be sent, starting from the addition - // of the first message to that batch. - google.protobuf.Duration delay_threshold = 3; - - // The maximum number of elements collected in a batch that could be accepted - // by server. - int32 element_count_limit = 4; - - // The maximum size of the request that could be accepted by server. - int32 request_byte_limit = 5; - - // The maximum number of elements allowed by flow control. - int32 flow_control_element_limit = 6; - - // The maximum size of data allowed by flow control. - int32 flow_control_byte_limit = 7; - - // The behavior to take when the flow control limit is exceeded. - FlowControlLimitExceededBehaviorProto flow_control_limit_exceeded_behavior = - 8; -} - -// The behavior to take when the flow control limit is exceeded. -enum FlowControlLimitExceededBehaviorProto { - // Default behavior, system-defined. - UNSET_BEHAVIOR = 0; - - // Stop operation, raise error. - THROW_EXCEPTION = 1; - - // Pause operation until limit clears. - BLOCK = 2; - - // Continue operation, disregard limit. - IGNORE = 3; -} - -// `BatchingDescriptorProto` specifies the fields of the request message to be -// used for batching, and, optionally, the fields of the response message to be -// used for demultiplexing. -message BatchingDescriptorProto { - // The repeated field in the request message to be aggregated by batching. - string batched_field = 1; - - // A list of the fields in the request message. Two requests will be batched - // together only if the values of every field specified in - // `request_discriminator_fields` is equal between the two requests. - repeated string discriminator_fields = 2; - - // Optional. When present, indicates the field in the response message to be - // used to demultiplex the response into multiple response messages, in - // correspondence with the multiple request messages originally batched - // together. - string subresponse_field = 3; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/client_pb2.py b/notification-service/venv/Lib/site-packages/google/api/client_pb2.py deleted file mode 100644 index 7c41fb1..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/client_pb2.py +++ /dev/null @@ -1,113 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/client.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 -from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 - -from google.api import launch_stage_pb2 as google_dot_api_dot_launch__stage__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x17google/api/client.proto\x12\ngoogle.api\x1a\x1dgoogle/api/launch_stage.proto\x1a google/protobuf/descriptor.proto\x1a\x1egoogle/protobuf/duration.proto"\xbe\x01\n\x16\x43ommonLanguageSettings\x12\x1e\n\x12reference_docs_uri\x18\x01 \x01(\tB\x02\x18\x01\x12:\n\x0c\x64\x65stinations\x18\x02 \x03(\x0e\x32$.google.api.ClientLibraryDestination\x12H\n\x1aselective_gapic_generation\x18\x03 \x01(\x0b\x32$.google.api.SelectiveGapicGeneration"\xfb\x03\n\x15\x43lientLibrarySettings\x12\x0f\n\x07version\x18\x01 \x01(\t\x12-\n\x0claunch_stage\x18\x02 \x01(\x0e\x32\x17.google.api.LaunchStage\x12\x1a\n\x12rest_numeric_enums\x18\x03 \x01(\x08\x12/\n\rjava_settings\x18\x15 \x01(\x0b\x32\x18.google.api.JavaSettings\x12-\n\x0c\x63pp_settings\x18\x16 \x01(\x0b\x32\x17.google.api.CppSettings\x12-\n\x0cphp_settings\x18\x17 \x01(\x0b\x32\x17.google.api.PhpSettings\x12\x33\n\x0fpython_settings\x18\x18 \x01(\x0b\x32\x1a.google.api.PythonSettings\x12/\n\rnode_settings\x18\x19 \x01(\x0b\x32\x18.google.api.NodeSettings\x12\x33\n\x0f\x64otnet_settings\x18\x1a \x01(\x0b\x32\x1a.google.api.DotnetSettings\x12/\n\rruby_settings\x18\x1b \x01(\x0b\x32\x18.google.api.RubySettings\x12+\n\x0bgo_settings\x18\x1c \x01(\x0b\x32\x16.google.api.GoSettings"\xa8\x03\n\nPublishing\x12\x33\n\x0fmethod_settings\x18\x02 \x03(\x0b\x32\x1a.google.api.MethodSettings\x12\x15\n\rnew_issue_uri\x18\x65 \x01(\t\x12\x19\n\x11\x64ocumentation_uri\x18\x66 \x01(\t\x12\x16\n\x0e\x61pi_short_name\x18g \x01(\t\x12\x14\n\x0cgithub_label\x18h \x01(\t\x12\x1e\n\x16\x63odeowner_github_teams\x18i \x03(\t\x12\x16\n\x0e\x64oc_tag_prefix\x18j \x01(\t\x12;\n\x0corganization\x18k \x01(\x0e\x32%.google.api.ClientLibraryOrganization\x12;\n\x10library_settings\x18m \x03(\x0b\x32!.google.api.ClientLibrarySettings\x12)\n!proto_reference_documentation_uri\x18n \x01(\t\x12(\n rest_reference_documentation_uri\x18o \x01(\t"\xe3\x01\n\x0cJavaSettings\x12\x17\n\x0flibrary_package\x18\x01 \x01(\t\x12L\n\x13service_class_names\x18\x02 \x03(\x0b\x32/.google.api.JavaSettings.ServiceClassNamesEntry\x12\x32\n\x06\x63ommon\x18\x03 \x01(\x0b\x32".google.api.CommonLanguageSettings\x1a\x38\n\x16ServiceClassNamesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"A\n\x0b\x43ppSettings\x12\x32\n\x06\x63ommon\x18\x01 \x01(\x0b\x32".google.api.CommonLanguageSettings"Z\n\x0bPhpSettings\x12\x32\n\x06\x63ommon\x18\x01 \x01(\x0b\x32".google.api.CommonLanguageSettings\x12\x17\n\x0flibrary_package\x18\x02 \x01(\t"\x9b\x02\n\x0ePythonSettings\x12\x32\n\x06\x63ommon\x18\x01 \x01(\x0b\x32".google.api.CommonLanguageSettings\x12N\n\x15\x65xperimental_features\x18\x02 \x01(\x0b\x32/.google.api.PythonSettings.ExperimentalFeatures\x1a\x84\x01\n\x14\x45xperimentalFeatures\x12\x1d\n\x15rest_async_io_enabled\x18\x01 \x01(\x08\x12\'\n\x1fprotobuf_pythonic_types_enabled\x18\x02 \x01(\x08\x12$\n\x1cunversioned_package_disabled\x18\x03 \x01(\x08"B\n\x0cNodeSettings\x12\x32\n\x06\x63ommon\x18\x01 \x01(\x0b\x32".google.api.CommonLanguageSettings"\xaa\x03\n\x0e\x44otnetSettings\x12\x32\n\x06\x63ommon\x18\x01 \x01(\x0b\x32".google.api.CommonLanguageSettings\x12I\n\x10renamed_services\x18\x02 \x03(\x0b\x32/.google.api.DotnetSettings.RenamedServicesEntry\x12K\n\x11renamed_resources\x18\x03 \x03(\x0b\x32\x30.google.api.DotnetSettings.RenamedResourcesEntry\x12\x19\n\x11ignored_resources\x18\x04 \x03(\t\x12 \n\x18\x66orced_namespace_aliases\x18\x05 \x03(\t\x12\x1e\n\x16handwritten_signatures\x18\x06 \x03(\t\x1a\x36\n\x14RenamedServicesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x37\n\x15RenamedResourcesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"B\n\x0cRubySettings\x12\x32\n\x06\x63ommon\x18\x01 \x01(\x0b\x32".google.api.CommonLanguageSettings"\xbf\x01\n\nGoSettings\x12\x32\n\x06\x63ommon\x18\x01 \x01(\x0b\x32".google.api.CommonLanguageSettings\x12\x45\n\x10renamed_services\x18\x02 \x03(\x0b\x32+.google.api.GoSettings.RenamedServicesEntry\x1a\x36\n\x14RenamedServicesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x82\x03\n\x0eMethodSettings\x12\x10\n\x08selector\x18\x01 \x01(\t\x12<\n\x0clong_running\x18\x02 \x01(\x0b\x32&.google.api.MethodSettings.LongRunning\x12\x1d\n\x15\x61uto_populated_fields\x18\x03 \x03(\t\x12\x31\n\x08\x62\x61tching\x18\x04 \x01(\x0b\x32\x1f.google.api.BatchingConfigProto\x1a\xcd\x01\n\x0bLongRunning\x12\x35\n\x12initial_poll_delay\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x1d\n\x15poll_delay_multiplier\x18\x02 \x01(\x02\x12\x31\n\x0emax_poll_delay\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x35\n\x12total_poll_timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration"Q\n\x18SelectiveGapicGeneration\x12\x0f\n\x07methods\x18\x01 \x03(\t\x12$\n\x1cgenerate_omitted_as_internal\x18\x02 \x01(\x08"\x8b\x01\n\x13\x42\x61tchingConfigProto\x12\x35\n\nthresholds\x18\x01 \x01(\x0b\x32!.google.api.BatchingSettingsProto\x12=\n\x10\x62\x61tch_descriptor\x18\x02 \x01(\x0b\x32#.google.api.BatchingDescriptorProto"\xeb\x02\n\x15\x42\x61tchingSettingsProto\x12\x1f\n\x17\x65lement_count_threshold\x18\x01 \x01(\x05\x12\x1e\n\x16request_byte_threshold\x18\x02 \x01(\x03\x12\x32\n\x0f\x64\x65lay_threshold\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x1b\n\x13\x65lement_count_limit\x18\x04 \x01(\x05\x12\x1a\n\x12request_byte_limit\x18\x05 \x01(\x05\x12"\n\x1a\x66low_control_element_limit\x18\x06 \x01(\x05\x12\x1f\n\x17\x66low_control_byte_limit\x18\x07 \x01(\x05\x12_\n$flow_control_limit_exceeded_behavior\x18\x08 \x01(\x0e\x32\x31.google.api.FlowControlLimitExceededBehaviorProto"i\n\x17\x42\x61tchingDescriptorProto\x12\x15\n\rbatched_field\x18\x01 \x01(\t\x12\x1c\n\x14\x64iscriminator_fields\x18\x02 \x03(\t\x12\x19\n\x11subresponse_field\x18\x03 \x01(\t*\xa3\x01\n\x19\x43lientLibraryOrganization\x12+\n\'CLIENT_LIBRARY_ORGANIZATION_UNSPECIFIED\x10\x00\x12\t\n\x05\x43LOUD\x10\x01\x12\x07\n\x03\x41\x44S\x10\x02\x12\n\n\x06PHOTOS\x10\x03\x12\x0f\n\x0bSTREET_VIEW\x10\x04\x12\x0c\n\x08SHOPPING\x10\x05\x12\x07\n\x03GEO\x10\x06\x12\x11\n\rGENERATIVE_AI\x10\x07*g\n\x18\x43lientLibraryDestination\x12*\n&CLIENT_LIBRARY_DESTINATION_UNSPECIFIED\x10\x00\x12\n\n\x06GITHUB\x10\n\x12\x13\n\x0fPACKAGE_MANAGER\x10\x14*g\n%FlowControlLimitExceededBehaviorProto\x12\x12\n\x0eUNSET_BEHAVIOR\x10\x00\x12\x13\n\x0fTHROW_EXCEPTION\x10\x01\x12\t\n\x05\x42LOCK\x10\x02\x12\n\n\x06IGNORE\x10\x03:9\n\x10method_signature\x12\x1e.google.protobuf.MethodOptions\x18\x9b\x08 \x03(\t:6\n\x0c\x64\x65\x66\x61ult_host\x12\x1f.google.protobuf.ServiceOptions\x18\x99\x08 \x01(\t:6\n\x0coauth_scopes\x12\x1f.google.protobuf.ServiceOptions\x18\x9a\x08 \x01(\t:8\n\x0b\x61pi_version\x12\x1f.google.protobuf.ServiceOptions\x18\xc1\xba\xab\xfa\x01 \x01(\tBi\n\x0e\x63om.google.apiB\x0b\x43lientProtoP\x01ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.client_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\013ClientProtoP\001ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\242\002\004GAPI" - _globals["_COMMONLANGUAGESETTINGS"].fields_by_name[ - "reference_docs_uri" - ]._options = None - _globals["_COMMONLANGUAGESETTINGS"].fields_by_name[ - "reference_docs_uri" - ]._serialized_options = b"\030\001" - _globals["_JAVASETTINGS_SERVICECLASSNAMESENTRY"]._options = None - _globals["_JAVASETTINGS_SERVICECLASSNAMESENTRY"]._serialized_options = b"8\001" - _globals["_DOTNETSETTINGS_RENAMEDSERVICESENTRY"]._options = None - _globals["_DOTNETSETTINGS_RENAMEDSERVICESENTRY"]._serialized_options = b"8\001" - _globals["_DOTNETSETTINGS_RENAMEDRESOURCESENTRY"]._options = None - _globals["_DOTNETSETTINGS_RENAMEDRESOURCESENTRY"]._serialized_options = b"8\001" - _globals["_GOSETTINGS_RENAMEDSERVICESENTRY"]._options = None - _globals["_GOSETTINGS_RENAMEDSERVICESENTRY"]._serialized_options = b"8\001" - _globals["_CLIENTLIBRARYORGANIZATION"]._serialized_start = 3788 - _globals["_CLIENTLIBRARYORGANIZATION"]._serialized_end = 3951 - _globals["_CLIENTLIBRARYDESTINATION"]._serialized_start = 3953 - _globals["_CLIENTLIBRARYDESTINATION"]._serialized_end = 4056 - _globals["_FLOWCONTROLLIMITEXCEEDEDBEHAVIORPROTO"]._serialized_start = 4058 - _globals["_FLOWCONTROLLIMITEXCEEDEDBEHAVIORPROTO"]._serialized_end = 4161 - _globals["_COMMONLANGUAGESETTINGS"]._serialized_start = 137 - _globals["_COMMONLANGUAGESETTINGS"]._serialized_end = 327 - _globals["_CLIENTLIBRARYSETTINGS"]._serialized_start = 330 - _globals["_CLIENTLIBRARYSETTINGS"]._serialized_end = 837 - _globals["_PUBLISHING"]._serialized_start = 840 - _globals["_PUBLISHING"]._serialized_end = 1264 - _globals["_JAVASETTINGS"]._serialized_start = 1267 - _globals["_JAVASETTINGS"]._serialized_end = 1494 - _globals["_JAVASETTINGS_SERVICECLASSNAMESENTRY"]._serialized_start = 1438 - _globals["_JAVASETTINGS_SERVICECLASSNAMESENTRY"]._serialized_end = 1494 - _globals["_CPPSETTINGS"]._serialized_start = 1496 - _globals["_CPPSETTINGS"]._serialized_end = 1561 - _globals["_PHPSETTINGS"]._serialized_start = 1563 - _globals["_PHPSETTINGS"]._serialized_end = 1653 - _globals["_PYTHONSETTINGS"]._serialized_start = 1656 - _globals["_PYTHONSETTINGS"]._serialized_end = 1939 - _globals["_PYTHONSETTINGS_EXPERIMENTALFEATURES"]._serialized_start = 1807 - _globals["_PYTHONSETTINGS_EXPERIMENTALFEATURES"]._serialized_end = 1939 - _globals["_NODESETTINGS"]._serialized_start = 1941 - _globals["_NODESETTINGS"]._serialized_end = 2007 - _globals["_DOTNETSETTINGS"]._serialized_start = 2010 - _globals["_DOTNETSETTINGS"]._serialized_end = 2436 - _globals["_DOTNETSETTINGS_RENAMEDSERVICESENTRY"]._serialized_start = 2325 - _globals["_DOTNETSETTINGS_RENAMEDSERVICESENTRY"]._serialized_end = 2379 - _globals["_DOTNETSETTINGS_RENAMEDRESOURCESENTRY"]._serialized_start = 2381 - _globals["_DOTNETSETTINGS_RENAMEDRESOURCESENTRY"]._serialized_end = 2436 - _globals["_RUBYSETTINGS"]._serialized_start = 2438 - _globals["_RUBYSETTINGS"]._serialized_end = 2504 - _globals["_GOSETTINGS"]._serialized_start = 2507 - _globals["_GOSETTINGS"]._serialized_end = 2698 - _globals["_GOSETTINGS_RENAMEDSERVICESENTRY"]._serialized_start = 2325 - _globals["_GOSETTINGS_RENAMEDSERVICESENTRY"]._serialized_end = 2379 - _globals["_METHODSETTINGS"]._serialized_start = 2701 - _globals["_METHODSETTINGS"]._serialized_end = 3087 - _globals["_METHODSETTINGS_LONGRUNNING"]._serialized_start = 2882 - _globals["_METHODSETTINGS_LONGRUNNING"]._serialized_end = 3087 - _globals["_SELECTIVEGAPICGENERATION"]._serialized_start = 3089 - _globals["_SELECTIVEGAPICGENERATION"]._serialized_end = 3170 - _globals["_BATCHINGCONFIGPROTO"]._serialized_start = 3173 - _globals["_BATCHINGCONFIGPROTO"]._serialized_end = 3312 - _globals["_BATCHINGSETTINGSPROTO"]._serialized_start = 3315 - _globals["_BATCHINGSETTINGSPROTO"]._serialized_end = 3678 - _globals["_BATCHINGDESCRIPTORPROTO"]._serialized_start = 3680 - _globals["_BATCHINGDESCRIPTORPROTO"]._serialized_end = 3785 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/client_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/client_pb2.pyi deleted file mode 100644 index 369f013..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/client_pb2.pyi +++ /dev/null @@ -1,493 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pb2 as _descriptor_pb2 -from google.protobuf import duration_pb2 as _duration_pb2 -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper - -from google.api import launch_stage_pb2 as _launch_stage_pb2 - -DESCRIPTOR: _descriptor.FileDescriptor - -class ClientLibraryOrganization(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - CLIENT_LIBRARY_ORGANIZATION_UNSPECIFIED: _ClassVar[ClientLibraryOrganization] - CLOUD: _ClassVar[ClientLibraryOrganization] - ADS: _ClassVar[ClientLibraryOrganization] - PHOTOS: _ClassVar[ClientLibraryOrganization] - STREET_VIEW: _ClassVar[ClientLibraryOrganization] - SHOPPING: _ClassVar[ClientLibraryOrganization] - GEO: _ClassVar[ClientLibraryOrganization] - GENERATIVE_AI: _ClassVar[ClientLibraryOrganization] - -class ClientLibraryDestination(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - CLIENT_LIBRARY_DESTINATION_UNSPECIFIED: _ClassVar[ClientLibraryDestination] - GITHUB: _ClassVar[ClientLibraryDestination] - PACKAGE_MANAGER: _ClassVar[ClientLibraryDestination] - -class FlowControlLimitExceededBehaviorProto( - int, metaclass=_enum_type_wrapper.EnumTypeWrapper -): - __slots__ = () - UNSET_BEHAVIOR: _ClassVar[FlowControlLimitExceededBehaviorProto] - THROW_EXCEPTION: _ClassVar[FlowControlLimitExceededBehaviorProto] - BLOCK: _ClassVar[FlowControlLimitExceededBehaviorProto] - IGNORE: _ClassVar[FlowControlLimitExceededBehaviorProto] - -CLIENT_LIBRARY_ORGANIZATION_UNSPECIFIED: ClientLibraryOrganization -CLOUD: ClientLibraryOrganization -ADS: ClientLibraryOrganization -PHOTOS: ClientLibraryOrganization -STREET_VIEW: ClientLibraryOrganization -SHOPPING: ClientLibraryOrganization -GEO: ClientLibraryOrganization -GENERATIVE_AI: ClientLibraryOrganization -CLIENT_LIBRARY_DESTINATION_UNSPECIFIED: ClientLibraryDestination -GITHUB: ClientLibraryDestination -PACKAGE_MANAGER: ClientLibraryDestination -UNSET_BEHAVIOR: FlowControlLimitExceededBehaviorProto -THROW_EXCEPTION: FlowControlLimitExceededBehaviorProto -BLOCK: FlowControlLimitExceededBehaviorProto -IGNORE: FlowControlLimitExceededBehaviorProto -METHOD_SIGNATURE_FIELD_NUMBER: _ClassVar[int] -method_signature: _descriptor.FieldDescriptor -DEFAULT_HOST_FIELD_NUMBER: _ClassVar[int] -default_host: _descriptor.FieldDescriptor -OAUTH_SCOPES_FIELD_NUMBER: _ClassVar[int] -oauth_scopes: _descriptor.FieldDescriptor -API_VERSION_FIELD_NUMBER: _ClassVar[int] -api_version: _descriptor.FieldDescriptor - -class CommonLanguageSettings(_message.Message): - __slots__ = ("reference_docs_uri", "destinations", "selective_gapic_generation") - REFERENCE_DOCS_URI_FIELD_NUMBER: _ClassVar[int] - DESTINATIONS_FIELD_NUMBER: _ClassVar[int] - SELECTIVE_GAPIC_GENERATION_FIELD_NUMBER: _ClassVar[int] - reference_docs_uri: str - destinations: _containers.RepeatedScalarFieldContainer[ClientLibraryDestination] - selective_gapic_generation: SelectiveGapicGeneration - def __init__( - self, - reference_docs_uri: _Optional[str] = ..., - destinations: _Optional[_Iterable[_Union[ClientLibraryDestination, str]]] = ..., - selective_gapic_generation: _Optional[ - _Union[SelectiveGapicGeneration, _Mapping] - ] = ..., - ) -> None: ... - -class ClientLibrarySettings(_message.Message): - __slots__ = ( - "version", - "launch_stage", - "rest_numeric_enums", - "java_settings", - "cpp_settings", - "php_settings", - "python_settings", - "node_settings", - "dotnet_settings", - "ruby_settings", - "go_settings", - ) - VERSION_FIELD_NUMBER: _ClassVar[int] - LAUNCH_STAGE_FIELD_NUMBER: _ClassVar[int] - REST_NUMERIC_ENUMS_FIELD_NUMBER: _ClassVar[int] - JAVA_SETTINGS_FIELD_NUMBER: _ClassVar[int] - CPP_SETTINGS_FIELD_NUMBER: _ClassVar[int] - PHP_SETTINGS_FIELD_NUMBER: _ClassVar[int] - PYTHON_SETTINGS_FIELD_NUMBER: _ClassVar[int] - NODE_SETTINGS_FIELD_NUMBER: _ClassVar[int] - DOTNET_SETTINGS_FIELD_NUMBER: _ClassVar[int] - RUBY_SETTINGS_FIELD_NUMBER: _ClassVar[int] - GO_SETTINGS_FIELD_NUMBER: _ClassVar[int] - version: str - launch_stage: _launch_stage_pb2.LaunchStage - rest_numeric_enums: bool - java_settings: JavaSettings - cpp_settings: CppSettings - php_settings: PhpSettings - python_settings: PythonSettings - node_settings: NodeSettings - dotnet_settings: DotnetSettings - ruby_settings: RubySettings - go_settings: GoSettings - def __init__( - self, - version: _Optional[str] = ..., - launch_stage: _Optional[_Union[_launch_stage_pb2.LaunchStage, str]] = ..., - rest_numeric_enums: bool = ..., - java_settings: _Optional[_Union[JavaSettings, _Mapping]] = ..., - cpp_settings: _Optional[_Union[CppSettings, _Mapping]] = ..., - php_settings: _Optional[_Union[PhpSettings, _Mapping]] = ..., - python_settings: _Optional[_Union[PythonSettings, _Mapping]] = ..., - node_settings: _Optional[_Union[NodeSettings, _Mapping]] = ..., - dotnet_settings: _Optional[_Union[DotnetSettings, _Mapping]] = ..., - ruby_settings: _Optional[_Union[RubySettings, _Mapping]] = ..., - go_settings: _Optional[_Union[GoSettings, _Mapping]] = ..., - ) -> None: ... - -class Publishing(_message.Message): - __slots__ = ( - "method_settings", - "new_issue_uri", - "documentation_uri", - "api_short_name", - "github_label", - "codeowner_github_teams", - "doc_tag_prefix", - "organization", - "library_settings", - "proto_reference_documentation_uri", - "rest_reference_documentation_uri", - ) - METHOD_SETTINGS_FIELD_NUMBER: _ClassVar[int] - NEW_ISSUE_URI_FIELD_NUMBER: _ClassVar[int] - DOCUMENTATION_URI_FIELD_NUMBER: _ClassVar[int] - API_SHORT_NAME_FIELD_NUMBER: _ClassVar[int] - GITHUB_LABEL_FIELD_NUMBER: _ClassVar[int] - CODEOWNER_GITHUB_TEAMS_FIELD_NUMBER: _ClassVar[int] - DOC_TAG_PREFIX_FIELD_NUMBER: _ClassVar[int] - ORGANIZATION_FIELD_NUMBER: _ClassVar[int] - LIBRARY_SETTINGS_FIELD_NUMBER: _ClassVar[int] - PROTO_REFERENCE_DOCUMENTATION_URI_FIELD_NUMBER: _ClassVar[int] - REST_REFERENCE_DOCUMENTATION_URI_FIELD_NUMBER: _ClassVar[int] - method_settings: _containers.RepeatedCompositeFieldContainer[MethodSettings] - new_issue_uri: str - documentation_uri: str - api_short_name: str - github_label: str - codeowner_github_teams: _containers.RepeatedScalarFieldContainer[str] - doc_tag_prefix: str - organization: ClientLibraryOrganization - library_settings: _containers.RepeatedCompositeFieldContainer[ClientLibrarySettings] - proto_reference_documentation_uri: str - rest_reference_documentation_uri: str - def __init__( - self, - method_settings: _Optional[_Iterable[_Union[MethodSettings, _Mapping]]] = ..., - new_issue_uri: _Optional[str] = ..., - documentation_uri: _Optional[str] = ..., - api_short_name: _Optional[str] = ..., - github_label: _Optional[str] = ..., - codeowner_github_teams: _Optional[_Iterable[str]] = ..., - doc_tag_prefix: _Optional[str] = ..., - organization: _Optional[_Union[ClientLibraryOrganization, str]] = ..., - library_settings: _Optional[ - _Iterable[_Union[ClientLibrarySettings, _Mapping]] - ] = ..., - proto_reference_documentation_uri: _Optional[str] = ..., - rest_reference_documentation_uri: _Optional[str] = ..., - ) -> None: ... - -class JavaSettings(_message.Message): - __slots__ = ("library_package", "service_class_names", "common") - class ServiceClassNamesEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: str - def __init__( - self, key: _Optional[str] = ..., value: _Optional[str] = ... - ) -> None: ... - - LIBRARY_PACKAGE_FIELD_NUMBER: _ClassVar[int] - SERVICE_CLASS_NAMES_FIELD_NUMBER: _ClassVar[int] - COMMON_FIELD_NUMBER: _ClassVar[int] - library_package: str - service_class_names: _containers.ScalarMap[str, str] - common: CommonLanguageSettings - def __init__( - self, - library_package: _Optional[str] = ..., - service_class_names: _Optional[_Mapping[str, str]] = ..., - common: _Optional[_Union[CommonLanguageSettings, _Mapping]] = ..., - ) -> None: ... - -class CppSettings(_message.Message): - __slots__ = ("common",) - COMMON_FIELD_NUMBER: _ClassVar[int] - common: CommonLanguageSettings - def __init__( - self, common: _Optional[_Union[CommonLanguageSettings, _Mapping]] = ... - ) -> None: ... - -class PhpSettings(_message.Message): - __slots__ = ("common", "library_package") - COMMON_FIELD_NUMBER: _ClassVar[int] - LIBRARY_PACKAGE_FIELD_NUMBER: _ClassVar[int] - common: CommonLanguageSettings - library_package: str - def __init__( - self, - common: _Optional[_Union[CommonLanguageSettings, _Mapping]] = ..., - library_package: _Optional[str] = ..., - ) -> None: ... - -class PythonSettings(_message.Message): - __slots__ = ("common", "experimental_features") - class ExperimentalFeatures(_message.Message): - __slots__ = ( - "rest_async_io_enabled", - "protobuf_pythonic_types_enabled", - "unversioned_package_disabled", - ) - REST_ASYNC_IO_ENABLED_FIELD_NUMBER: _ClassVar[int] - PROTOBUF_PYTHONIC_TYPES_ENABLED_FIELD_NUMBER: _ClassVar[int] - UNVERSIONED_PACKAGE_DISABLED_FIELD_NUMBER: _ClassVar[int] - rest_async_io_enabled: bool - protobuf_pythonic_types_enabled: bool - unversioned_package_disabled: bool - def __init__( - self, - rest_async_io_enabled: bool = ..., - protobuf_pythonic_types_enabled: bool = ..., - unversioned_package_disabled: bool = ..., - ) -> None: ... - - COMMON_FIELD_NUMBER: _ClassVar[int] - EXPERIMENTAL_FEATURES_FIELD_NUMBER: _ClassVar[int] - common: CommonLanguageSettings - experimental_features: PythonSettings.ExperimentalFeatures - def __init__( - self, - common: _Optional[_Union[CommonLanguageSettings, _Mapping]] = ..., - experimental_features: _Optional[ - _Union[PythonSettings.ExperimentalFeatures, _Mapping] - ] = ..., - ) -> None: ... - -class NodeSettings(_message.Message): - __slots__ = ("common",) - COMMON_FIELD_NUMBER: _ClassVar[int] - common: CommonLanguageSettings - def __init__( - self, common: _Optional[_Union[CommonLanguageSettings, _Mapping]] = ... - ) -> None: ... - -class DotnetSettings(_message.Message): - __slots__ = ( - "common", - "renamed_services", - "renamed_resources", - "ignored_resources", - "forced_namespace_aliases", - "handwritten_signatures", - ) - class RenamedServicesEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: str - def __init__( - self, key: _Optional[str] = ..., value: _Optional[str] = ... - ) -> None: ... - - class RenamedResourcesEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: str - def __init__( - self, key: _Optional[str] = ..., value: _Optional[str] = ... - ) -> None: ... - - COMMON_FIELD_NUMBER: _ClassVar[int] - RENAMED_SERVICES_FIELD_NUMBER: _ClassVar[int] - RENAMED_RESOURCES_FIELD_NUMBER: _ClassVar[int] - IGNORED_RESOURCES_FIELD_NUMBER: _ClassVar[int] - FORCED_NAMESPACE_ALIASES_FIELD_NUMBER: _ClassVar[int] - HANDWRITTEN_SIGNATURES_FIELD_NUMBER: _ClassVar[int] - common: CommonLanguageSettings - renamed_services: _containers.ScalarMap[str, str] - renamed_resources: _containers.ScalarMap[str, str] - ignored_resources: _containers.RepeatedScalarFieldContainer[str] - forced_namespace_aliases: _containers.RepeatedScalarFieldContainer[str] - handwritten_signatures: _containers.RepeatedScalarFieldContainer[str] - def __init__( - self, - common: _Optional[_Union[CommonLanguageSettings, _Mapping]] = ..., - renamed_services: _Optional[_Mapping[str, str]] = ..., - renamed_resources: _Optional[_Mapping[str, str]] = ..., - ignored_resources: _Optional[_Iterable[str]] = ..., - forced_namespace_aliases: _Optional[_Iterable[str]] = ..., - handwritten_signatures: _Optional[_Iterable[str]] = ..., - ) -> None: ... - -class RubySettings(_message.Message): - __slots__ = ("common",) - COMMON_FIELD_NUMBER: _ClassVar[int] - common: CommonLanguageSettings - def __init__( - self, common: _Optional[_Union[CommonLanguageSettings, _Mapping]] = ... - ) -> None: ... - -class GoSettings(_message.Message): - __slots__ = ("common", "renamed_services") - class RenamedServicesEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: str - def __init__( - self, key: _Optional[str] = ..., value: _Optional[str] = ... - ) -> None: ... - - COMMON_FIELD_NUMBER: _ClassVar[int] - RENAMED_SERVICES_FIELD_NUMBER: _ClassVar[int] - common: CommonLanguageSettings - renamed_services: _containers.ScalarMap[str, str] - def __init__( - self, - common: _Optional[_Union[CommonLanguageSettings, _Mapping]] = ..., - renamed_services: _Optional[_Mapping[str, str]] = ..., - ) -> None: ... - -class MethodSettings(_message.Message): - __slots__ = ("selector", "long_running", "auto_populated_fields", "batching") - class LongRunning(_message.Message): - __slots__ = ( - "initial_poll_delay", - "poll_delay_multiplier", - "max_poll_delay", - "total_poll_timeout", - ) - INITIAL_POLL_DELAY_FIELD_NUMBER: _ClassVar[int] - POLL_DELAY_MULTIPLIER_FIELD_NUMBER: _ClassVar[int] - MAX_POLL_DELAY_FIELD_NUMBER: _ClassVar[int] - TOTAL_POLL_TIMEOUT_FIELD_NUMBER: _ClassVar[int] - initial_poll_delay: _duration_pb2.Duration - poll_delay_multiplier: float - max_poll_delay: _duration_pb2.Duration - total_poll_timeout: _duration_pb2.Duration - def __init__( - self, - initial_poll_delay: _Optional[ - _Union[_duration_pb2.Duration, _Mapping] - ] = ..., - poll_delay_multiplier: _Optional[float] = ..., - max_poll_delay: _Optional[_Union[_duration_pb2.Duration, _Mapping]] = ..., - total_poll_timeout: _Optional[ - _Union[_duration_pb2.Duration, _Mapping] - ] = ..., - ) -> None: ... - - SELECTOR_FIELD_NUMBER: _ClassVar[int] - LONG_RUNNING_FIELD_NUMBER: _ClassVar[int] - AUTO_POPULATED_FIELDS_FIELD_NUMBER: _ClassVar[int] - BATCHING_FIELD_NUMBER: _ClassVar[int] - selector: str - long_running: MethodSettings.LongRunning - auto_populated_fields: _containers.RepeatedScalarFieldContainer[str] - batching: BatchingConfigProto - def __init__( - self, - selector: _Optional[str] = ..., - long_running: _Optional[_Union[MethodSettings.LongRunning, _Mapping]] = ..., - auto_populated_fields: _Optional[_Iterable[str]] = ..., - batching: _Optional[_Union[BatchingConfigProto, _Mapping]] = ..., - ) -> None: ... - -class SelectiveGapicGeneration(_message.Message): - __slots__ = ("methods", "generate_omitted_as_internal") - METHODS_FIELD_NUMBER: _ClassVar[int] - GENERATE_OMITTED_AS_INTERNAL_FIELD_NUMBER: _ClassVar[int] - methods: _containers.RepeatedScalarFieldContainer[str] - generate_omitted_as_internal: bool - def __init__( - self, - methods: _Optional[_Iterable[str]] = ..., - generate_omitted_as_internal: bool = ..., - ) -> None: ... - -class BatchingConfigProto(_message.Message): - __slots__ = ("thresholds", "batch_descriptor") - THRESHOLDS_FIELD_NUMBER: _ClassVar[int] - BATCH_DESCRIPTOR_FIELD_NUMBER: _ClassVar[int] - thresholds: BatchingSettingsProto - batch_descriptor: BatchingDescriptorProto - def __init__( - self, - thresholds: _Optional[_Union[BatchingSettingsProto, _Mapping]] = ..., - batch_descriptor: _Optional[_Union[BatchingDescriptorProto, _Mapping]] = ..., - ) -> None: ... - -class BatchingSettingsProto(_message.Message): - __slots__ = ( - "element_count_threshold", - "request_byte_threshold", - "delay_threshold", - "element_count_limit", - "request_byte_limit", - "flow_control_element_limit", - "flow_control_byte_limit", - "flow_control_limit_exceeded_behavior", - ) - ELEMENT_COUNT_THRESHOLD_FIELD_NUMBER: _ClassVar[int] - REQUEST_BYTE_THRESHOLD_FIELD_NUMBER: _ClassVar[int] - DELAY_THRESHOLD_FIELD_NUMBER: _ClassVar[int] - ELEMENT_COUNT_LIMIT_FIELD_NUMBER: _ClassVar[int] - REQUEST_BYTE_LIMIT_FIELD_NUMBER: _ClassVar[int] - FLOW_CONTROL_ELEMENT_LIMIT_FIELD_NUMBER: _ClassVar[int] - FLOW_CONTROL_BYTE_LIMIT_FIELD_NUMBER: _ClassVar[int] - FLOW_CONTROL_LIMIT_EXCEEDED_BEHAVIOR_FIELD_NUMBER: _ClassVar[int] - element_count_threshold: int - request_byte_threshold: int - delay_threshold: _duration_pb2.Duration - element_count_limit: int - request_byte_limit: int - flow_control_element_limit: int - flow_control_byte_limit: int - flow_control_limit_exceeded_behavior: FlowControlLimitExceededBehaviorProto - def __init__( - self, - element_count_threshold: _Optional[int] = ..., - request_byte_threshold: _Optional[int] = ..., - delay_threshold: _Optional[_Union[_duration_pb2.Duration, _Mapping]] = ..., - element_count_limit: _Optional[int] = ..., - request_byte_limit: _Optional[int] = ..., - flow_control_element_limit: _Optional[int] = ..., - flow_control_byte_limit: _Optional[int] = ..., - flow_control_limit_exceeded_behavior: _Optional[ - _Union[FlowControlLimitExceededBehaviorProto, str] - ] = ..., - ) -> None: ... - -class BatchingDescriptorProto(_message.Message): - __slots__ = ("batched_field", "discriminator_fields", "subresponse_field") - BATCHED_FIELD_FIELD_NUMBER: _ClassVar[int] - DISCRIMINATOR_FIELDS_FIELD_NUMBER: _ClassVar[int] - SUBRESPONSE_FIELD_FIELD_NUMBER: _ClassVar[int] - batched_field: str - discriminator_fields: _containers.RepeatedScalarFieldContainer[str] - subresponse_field: str - def __init__( - self, - batched_field: _Optional[str] = ..., - discriminator_fields: _Optional[_Iterable[str]] = ..., - subresponse_field: _Optional[str] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/config_change.proto b/notification-service/venv/Lib/site-packages/google/api/config_change.proto deleted file mode 100644 index b6792b9..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/config_change.proto +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/configchange;configchange"; -option java_multiple_files = true; -option java_outer_classname = "ConfigChangeProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// Output generated from semantically comparing two versions of a service -// configuration. -// -// Includes detailed information about a field that have changed with -// applicable advice about potential consequences for the change, such as -// backwards-incompatibility. -message ConfigChange { - // Object hierarchy path to the change, with levels separated by a '.' - // character. For repeated fields, an applicable unique identifier field is - // used for the index (usually selector, name, or id). For maps, the term - // 'key' is used. If the field has no unique identifier, the numeric index - // is used. - // Examples: - // - visibility.rules[selector=="google.LibraryService.ListBooks"].restriction - // - quota.metric_rules[selector=="google"].metric_costs[key=="reads"].value - // - logging.producer_destinations[0] - string element = 1; - - // Value of the changed object in the old Service configuration, - // in JSON format. This field will not be populated if ChangeType == ADDED. - string old_value = 2; - - // Value of the changed object in the new Service configuration, - // in JSON format. This field will not be populated if ChangeType == REMOVED. - string new_value = 3; - - // The type for this change, either ADDED, REMOVED, or MODIFIED. - ChangeType change_type = 4; - - // Collection of advice provided for this change, useful for determining the - // possible impact of this change. - repeated Advice advices = 5; -} - -// Generated advice about this change, used for providing more -// information about how a change will affect the existing service. -message Advice { - // Useful description for why this advice was applied and what actions should - // be taken to mitigate any implied risks. - string description = 2; -} - -// Classifies set of possible modifications to an object in the service -// configuration. -enum ChangeType { - // No value was provided. - CHANGE_TYPE_UNSPECIFIED = 0; - - // The changed object exists in the 'new' service configuration, but not - // in the 'old' service configuration. - ADDED = 1; - - // The changed object exists in the 'old' service configuration, but not - // in the 'new' service configuration. - REMOVED = 2; - - // The changed object exists in both service configurations, but its value - // is different. - MODIFIED = 3; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/config_change_pb2.py b/notification-service/venv/Lib/site-packages/google/api/config_change_pb2.py deleted file mode 100644 index dace725..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/config_change_pb2.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/config_change.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x1egoogle/api/config_change.proto\x12\ngoogle.api"\x97\x01\n\x0c\x43onfigChange\x12\x0f\n\x07\x65lement\x18\x01 \x01(\t\x12\x11\n\told_value\x18\x02 \x01(\t\x12\x11\n\tnew_value\x18\x03 \x01(\t\x12+\n\x0b\x63hange_type\x18\x04 \x01(\x0e\x32\x16.google.api.ChangeType\x12#\n\x07\x61\x64vices\x18\x05 \x03(\x0b\x32\x12.google.api.Advice"\x1d\n\x06\x41\x64vice\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t*O\n\nChangeType\x12\x1b\n\x17\x43HANGE_TYPE_UNSPECIFIED\x10\x00\x12\t\n\x05\x41\x44\x44\x45\x44\x10\x01\x12\x0b\n\x07REMOVED\x10\x02\x12\x0c\n\x08MODIFIED\x10\x03\x42q\n\x0e\x63om.google.apiB\x11\x43onfigChangeProtoP\x01ZCgoogle.golang.org/genproto/googleapis/api/configchange;configchange\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, "google.api.config_change_pb2", _globals -) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\021ConfigChangeProtoP\001ZCgoogle.golang.org/genproto/googleapis/api/configchange;configchange\242\002\004GAPI" - _globals["_CHANGETYPE"]._serialized_start = 231 - _globals["_CHANGETYPE"]._serialized_end = 310 - _globals["_CONFIGCHANGE"]._serialized_start = 47 - _globals["_CONFIGCHANGE"]._serialized_end = 198 - _globals["_ADVICE"]._serialized_start = 200 - _globals["_ADVICE"]._serialized_end = 229 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/config_change_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/config_change_pb2.pyi deleted file mode 100644 index b6c1c45..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/config_change_pb2.pyi +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper - -DESCRIPTOR: _descriptor.FileDescriptor - -class ChangeType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - CHANGE_TYPE_UNSPECIFIED: _ClassVar[ChangeType] - ADDED: _ClassVar[ChangeType] - REMOVED: _ClassVar[ChangeType] - MODIFIED: _ClassVar[ChangeType] - -CHANGE_TYPE_UNSPECIFIED: ChangeType -ADDED: ChangeType -REMOVED: ChangeType -MODIFIED: ChangeType - -class ConfigChange(_message.Message): - __slots__ = ("element", "old_value", "new_value", "change_type", "advices") - ELEMENT_FIELD_NUMBER: _ClassVar[int] - OLD_VALUE_FIELD_NUMBER: _ClassVar[int] - NEW_VALUE_FIELD_NUMBER: _ClassVar[int] - CHANGE_TYPE_FIELD_NUMBER: _ClassVar[int] - ADVICES_FIELD_NUMBER: _ClassVar[int] - element: str - old_value: str - new_value: str - change_type: ChangeType - advices: _containers.RepeatedCompositeFieldContainer[Advice] - def __init__( - self, - element: _Optional[str] = ..., - old_value: _Optional[str] = ..., - new_value: _Optional[str] = ..., - change_type: _Optional[_Union[ChangeType, str]] = ..., - advices: _Optional[_Iterable[_Union[Advice, _Mapping]]] = ..., - ) -> None: ... - -class Advice(_message.Message): - __slots__ = ("description",) - DESCRIPTION_FIELD_NUMBER: _ClassVar[int] - description: str - def __init__(self, description: _Optional[str] = ...) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/consumer.proto b/notification-service/venv/Lib/site-packages/google/api/consumer.proto deleted file mode 100644 index 3036049..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/consumer.proto +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "ConsumerProto"; -option java_package = "com.google.api"; - -// A descriptor for defining project properties for a service. One service may -// have many consumer projects, and the service may want to behave differently -// depending on some properties on the project. For example, a project may be -// associated with a school, or a business, or a government agency, a business -// type property on the project may affect how a service responds to the client. -// This descriptor defines which properties are allowed to be set on a project. -// -// Example: -// -// project_properties: -// properties: -// - name: NO_WATERMARK -// type: BOOL -// description: Allows usage of the API without watermarks. -// - name: EXTENDED_TILE_CACHE_PERIOD -// type: INT64 -message ProjectProperties { - // List of per consumer project-specific properties. - repeated Property properties = 1; -} - -// Defines project properties. -// -// API services can define properties that can be assigned to consumer projects -// so that backends can perform response customization without having to make -// additional calls or maintain additional storage. For example, Maps API -// defines properties that controls map tile cache period, or whether to embed a -// watermark in a result. -// -// These values can be set via API producer console. Only API providers can -// define and set these properties. -message Property { - // Supported data type of the property values - enum PropertyType { - // The type is unspecified, and will result in an error. - UNSPECIFIED = 0; - - // The type is `int64`. - INT64 = 1; - - // The type is `bool`. - BOOL = 2; - - // The type is `string`. - STRING = 3; - - // The type is 'double'. - DOUBLE = 4; - } - - // The name of the property (a.k.a key). - string name = 1; - - // The type of this property. - PropertyType type = 2; - - // The description of the property - string description = 3; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/consumer_pb2.py b/notification-service/venv/Lib/site-packages/google/api/consumer_pb2.py deleted file mode 100644 index e1088c4..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/consumer_pb2.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/consumer.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x19google/api/consumer.proto\x12\ngoogle.api"=\n\x11ProjectProperties\x12(\n\nproperties\x18\x01 \x03(\x0b\x32\x14.google.api.Property"\xac\x01\n\x08Property\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x04type\x18\x02 \x01(\x0e\x32!.google.api.Property.PropertyType\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t"L\n\x0cPropertyType\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\t\n\x05INT64\x10\x01\x12\x08\n\x04\x42OOL\x10\x02\x12\n\n\x06STRING\x10\x03\x12\n\n\x06\x44OUBLE\x10\x04\x42h\n\x0e\x63om.google.apiB\rConsumerProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfigb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.consumer_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\rConsumerProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig" - _globals["_PROJECTPROPERTIES"]._serialized_start = 41 - _globals["_PROJECTPROPERTIES"]._serialized_end = 102 - _globals["_PROPERTY"]._serialized_start = 105 - _globals["_PROPERTY"]._serialized_end = 277 - _globals["_PROPERTY_PROPERTYTYPE"]._serialized_start = 201 - _globals["_PROPERTY_PROPERTYTYPE"]._serialized_end = 277 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/consumer_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/consumer_pb2.pyi deleted file mode 100644 index 4ddcd7b..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/consumer_pb2.pyi +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper - -DESCRIPTOR: _descriptor.FileDescriptor - -class ProjectProperties(_message.Message): - __slots__ = ("properties",) - PROPERTIES_FIELD_NUMBER: _ClassVar[int] - properties: _containers.RepeatedCompositeFieldContainer[Property] - def __init__( - self, properties: _Optional[_Iterable[_Union[Property, _Mapping]]] = ... - ) -> None: ... - -class Property(_message.Message): - __slots__ = ("name", "type", "description") - class PropertyType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - UNSPECIFIED: _ClassVar[Property.PropertyType] - INT64: _ClassVar[Property.PropertyType] - BOOL: _ClassVar[Property.PropertyType] - STRING: _ClassVar[Property.PropertyType] - DOUBLE: _ClassVar[Property.PropertyType] - - UNSPECIFIED: Property.PropertyType - INT64: Property.PropertyType - BOOL: Property.PropertyType - STRING: Property.PropertyType - DOUBLE: Property.PropertyType - NAME_FIELD_NUMBER: _ClassVar[int] - TYPE_FIELD_NUMBER: _ClassVar[int] - DESCRIPTION_FIELD_NUMBER: _ClassVar[int] - name: str - type: Property.PropertyType - description: str - def __init__( - self, - name: _Optional[str] = ..., - type: _Optional[_Union[Property.PropertyType, str]] = ..., - description: _Optional[str] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/context.proto b/notification-service/venv/Lib/site-packages/google/api/context.proto deleted file mode 100644 index c1704f1..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/context.proto +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "ContextProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// `Context` defines which contexts an API requests. -// -// Example: -// -// context: -// rules: -// - selector: "*" -// requested: -// - google.rpc.context.ProjectContext -// - google.rpc.context.OriginContext -// -// The above specifies that all methods in the API request -// `google.rpc.context.ProjectContext` and -// `google.rpc.context.OriginContext`. -// -// Available context types are defined in package -// `google.rpc.context`. -// -// This also provides mechanism to allowlist any protobuf message extension that -// can be sent in grpc metadata using “x-goog-ext--bin” and -// “x-goog-ext--jspb” format. For example, list any service -// specific protobuf types that can appear in grpc metadata as follows in your -// yaml file: -// -// Example: -// -// context: -// rules: -// - selector: "google.example.library.v1.LibraryService.CreateBook" -// allowed_request_extensions: -// - google.foo.v1.NewExtension -// allowed_response_extensions: -// - google.foo.v1.NewExtension -// -// You can also specify extension ID instead of fully qualified extension name -// here. -message Context { - // A list of RPC context rules that apply to individual API methods. - // - // **NOTE:** All service configuration rules follow "last one wins" order. - repeated ContextRule rules = 1; -} - -// A context rule provides information about the context for an individual API -// element. -message ContextRule { - // Selects the methods to which this rule applies. - // - // Refer to [selector][google.api.DocumentationRule.selector] for syntax - // details. - string selector = 1; - - // A list of full type names of requested contexts, only the requested context - // will be made available to the backend. - repeated string requested = 2; - - // A list of full type names of provided contexts. It is used to support - // propagating HTTP headers and ETags from the response extension. - repeated string provided = 3; - - // A list of full type names or extension IDs of extensions allowed in grpc - // side channel from client to backend. - repeated string allowed_request_extensions = 4; - - // A list of full type names or extension IDs of extensions allowed in grpc - // side channel from backend to client. - repeated string allowed_response_extensions = 5; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/context_pb2.py b/notification-service/venv/Lib/site-packages/google/api/context_pb2.py deleted file mode 100644 index 116d92f..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/context_pb2.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/context.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x18google/api/context.proto\x12\ngoogle.api"1\n\x07\x43ontext\x12&\n\x05rules\x18\x01 \x03(\x0b\x32\x17.google.api.ContextRule"\x8d\x01\n\x0b\x43ontextRule\x12\x10\n\x08selector\x18\x01 \x01(\t\x12\x11\n\trequested\x18\x02 \x03(\t\x12\x10\n\x08provided\x18\x03 \x03(\t\x12"\n\x1a\x61llowed_request_extensions\x18\x04 \x03(\t\x12#\n\x1b\x61llowed_response_extensions\x18\x05 \x03(\tBn\n\x0e\x63om.google.apiB\x0c\x43ontextProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.context_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\014ContextProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_CONTEXT"]._serialized_start = 40 - _globals["_CONTEXT"]._serialized_end = 89 - _globals["_CONTEXTRULE"]._serialized_start = 92 - _globals["_CONTEXTRULE"]._serialized_end = 233 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/context_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/context_pb2.pyi deleted file mode 100644 index 6f761ad..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/context_pb2.pyi +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor - -class Context(_message.Message): - __slots__ = ("rules",) - RULES_FIELD_NUMBER: _ClassVar[int] - rules: _containers.RepeatedCompositeFieldContainer[ContextRule] - def __init__( - self, rules: _Optional[_Iterable[_Union[ContextRule, _Mapping]]] = ... - ) -> None: ... - -class ContextRule(_message.Message): - __slots__ = ( - "selector", - "requested", - "provided", - "allowed_request_extensions", - "allowed_response_extensions", - ) - SELECTOR_FIELD_NUMBER: _ClassVar[int] - REQUESTED_FIELD_NUMBER: _ClassVar[int] - PROVIDED_FIELD_NUMBER: _ClassVar[int] - ALLOWED_REQUEST_EXTENSIONS_FIELD_NUMBER: _ClassVar[int] - ALLOWED_RESPONSE_EXTENSIONS_FIELD_NUMBER: _ClassVar[int] - selector: str - requested: _containers.RepeatedScalarFieldContainer[str] - provided: _containers.RepeatedScalarFieldContainer[str] - allowed_request_extensions: _containers.RepeatedScalarFieldContainer[str] - allowed_response_extensions: _containers.RepeatedScalarFieldContainer[str] - def __init__( - self, - selector: _Optional[str] = ..., - requested: _Optional[_Iterable[str]] = ..., - provided: _Optional[_Iterable[str]] = ..., - allowed_request_extensions: _Optional[_Iterable[str]] = ..., - allowed_response_extensions: _Optional[_Iterable[str]] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/control.proto b/notification-service/venv/Lib/site-packages/google/api/control.proto deleted file mode 100644 index c0dc0cd..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/control.proto +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/api/policy.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "ControlProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// Selects and configures the service controller used by the service. -// -// Example: -// -// control: -// environment: servicecontrol.googleapis.com -message Control { - // The service controller environment to use. If empty, no control plane - // features (like quota and billing) will be enabled. The recommended value - // for most services is servicecontrol.googleapis.com. - string environment = 1; - - // Defines policies applying to the API methods of the service. - repeated MethodPolicy method_policies = 4; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/control_pb2.py b/notification-service/venv/Lib/site-packages/google/api/control_pb2.py deleted file mode 100644 index 6efa1b0..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/control_pb2.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/control.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import policy_pb2 as google_dot_api_dot_policy__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x18google/api/control.proto\x12\ngoogle.api\x1a\x17google/api/policy.proto"Q\n\x07\x43ontrol\x12\x13\n\x0b\x65nvironment\x18\x01 \x01(\t\x12\x31\n\x0fmethod_policies\x18\x04 \x03(\x0b\x32\x18.google.api.MethodPolicyBn\n\x0e\x63om.google.apiB\x0c\x43ontrolProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.control_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\014ControlProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_CONTROL"]._serialized_start = 65 - _globals["_CONTROL"]._serialized_end = 146 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/control_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/control_pb2.pyi deleted file mode 100644 index c7898c3..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/control_pb2.pyi +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -from google.api import policy_pb2 as _policy_pb2 - -DESCRIPTOR: _descriptor.FileDescriptor - -class Control(_message.Message): - __slots__ = ("environment", "method_policies") - ENVIRONMENT_FIELD_NUMBER: _ClassVar[int] - METHOD_POLICIES_FIELD_NUMBER: _ClassVar[int] - environment: str - method_policies: _containers.RepeatedCompositeFieldContainer[ - _policy_pb2.MethodPolicy - ] - def __init__( - self, - environment: _Optional[str] = ..., - method_policies: _Optional[ - _Iterable[_Union[_policy_pb2.MethodPolicy, _Mapping]] - ] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/distribution.proto b/notification-service/venv/Lib/site-packages/google/api/distribution.proto deleted file mode 100644 index 51cf36e..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/distribution.proto +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/protobuf/any.proto"; -import "google/protobuf/timestamp.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/distribution;distribution"; -option java_multiple_files = true; -option java_outer_classname = "DistributionProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// `Distribution` contains summary statistics for a population of values. It -// optionally contains a histogram representing the distribution of those values -// across a set of buckets. -// -// The summary statistics are the count, mean, sum of the squared deviation from -// the mean, the minimum, and the maximum of the set of population of values. -// The histogram is based on a sequence of buckets and gives a count of values -// that fall into each bucket. The boundaries of the buckets are given either -// explicitly or by formulas for buckets of fixed or exponentially increasing -// widths. -// -// Although it is not forbidden, it is generally a bad idea to include -// non-finite values (infinities or NaNs) in the population of values, as this -// will render the `mean` and `sum_of_squared_deviation` fields meaningless. -message Distribution { - // The range of the population values. - message Range { - // The minimum of the population values. - double min = 1; - - // The maximum of the population values. - double max = 2; - } - - // `BucketOptions` describes the bucket boundaries used to create a histogram - // for the distribution. The buckets can be in a linear sequence, an - // exponential sequence, or each bucket can be specified explicitly. - // `BucketOptions` does not include the number of values in each bucket. - // - // A bucket has an inclusive lower bound and exclusive upper bound for the - // values that are counted for that bucket. The upper bound of a bucket must - // be strictly greater than the lower bound. The sequence of N buckets for a - // distribution consists of an underflow bucket (number 0), zero or more - // finite buckets (number 1 through N - 2) and an overflow bucket (number N - - // 1). The buckets are contiguous: the lower bound of bucket i (i > 0) is the - // same as the upper bound of bucket i - 1. The buckets span the whole range - // of finite values: lower bound of the underflow bucket is -infinity and the - // upper bound of the overflow bucket is +infinity. The finite buckets are - // so-called because both bounds are finite. - message BucketOptions { - // Specifies a linear sequence of buckets that all have the same width - // (except overflow and underflow). Each bucket represents a constant - // absolute uncertainty on the specific value in the bucket. - // - // There are `num_finite_buckets + 2` (= N) buckets. Bucket `i` has the - // following boundaries: - // - // Upper bound (0 <= i < N-1): offset + (width * i). - // - // Lower bound (1 <= i < N): offset + (width * (i - 1)). - message Linear { - // Must be greater than 0. - int32 num_finite_buckets = 1; - - // Must be greater than 0. - double width = 2; - - // Lower bound of the first bucket. - double offset = 3; - } - - // Specifies an exponential sequence of buckets that have a width that is - // proportional to the value of the lower bound. Each bucket represents a - // constant relative uncertainty on a specific value in the bucket. - // - // There are `num_finite_buckets + 2` (= N) buckets. Bucket `i` has the - // following boundaries: - // - // Upper bound (0 <= i < N-1): scale * (growth_factor ^ i). - // - // Lower bound (1 <= i < N): scale * (growth_factor ^ (i - 1)). - message Exponential { - // Must be greater than 0. - int32 num_finite_buckets = 1; - - // Must be greater than 1. - double growth_factor = 2; - - // Must be greater than 0. - double scale = 3; - } - - // Specifies a set of buckets with arbitrary widths. - // - // There are `size(bounds) + 1` (= N) buckets. Bucket `i` has the following - // boundaries: - // - // Upper bound (0 <= i < N-1): bounds[i] - // Lower bound (1 <= i < N); bounds[i - 1] - // - // The `bounds` field must contain at least one element. If `bounds` has - // only one element, then there are no finite buckets, and that single - // element is the common boundary of the overflow and underflow buckets. - message Explicit { - // The values must be monotonically increasing. - repeated double bounds = 1; - } - - // Exactly one of these three fields must be set. - oneof options { - // The linear bucket. - Linear linear_buckets = 1; - - // The exponential buckets. - Exponential exponential_buckets = 2; - - // The explicit buckets. - Explicit explicit_buckets = 3; - } - } - - // Exemplars are example points that may be used to annotate aggregated - // distribution values. They are metadata that gives information about a - // particular value added to a Distribution bucket, such as a trace ID that - // was active when a value was added. They may contain further information, - // such as a example values and timestamps, origin, etc. - message Exemplar { - // Value of the exemplar point. This value determines to which bucket the - // exemplar belongs. - double value = 1; - - // The observation (sampling) time of the above value. - google.protobuf.Timestamp timestamp = 2; - - // Contextual information about the example value. Examples are: - // - // Trace: type.googleapis.com/google.monitoring.v3.SpanContext - // - // Literal string: type.googleapis.com/google.protobuf.StringValue - // - // Labels dropped during aggregation: - // type.googleapis.com/google.monitoring.v3.DroppedLabels - // - // There may be only a single attachment of any given message type in a - // single exemplar, and this is enforced by the system. - repeated google.protobuf.Any attachments = 3; - } - - // The number of values in the population. Must be non-negative. This value - // must equal the sum of the values in `bucket_counts` if a histogram is - // provided. - int64 count = 1; - - // The arithmetic mean of the values in the population. If `count` is zero - // then this field must be zero. - double mean = 2; - - // The sum of squared deviations from the mean of the values in the - // population. For values x_i this is: - // - // Sum[i=1..n]((x_i - mean)^2) - // - // Knuth, "The Art of Computer Programming", Vol. 2, page 232, 3rd edition - // describes Welford's method for accumulating this sum in one pass. - // - // If `count` is zero then this field must be zero. - double sum_of_squared_deviation = 3; - - // If specified, contains the range of the population values. The field - // must not be present if the `count` is zero. - Range range = 4; - - // Defines the histogram bucket boundaries. If the distribution does not - // contain a histogram, then omit this field. - BucketOptions bucket_options = 6; - - // The number of values in each bucket of the histogram, as described in - // `bucket_options`. If the distribution does not have a histogram, then omit - // this field. If there is a histogram, then the sum of the values in - // `bucket_counts` must equal the value in the `count` field of the - // distribution. - // - // If present, `bucket_counts` should contain N values, where N is the number - // of buckets specified in `bucket_options`. If you supply fewer than N - // values, the remaining values are assumed to be 0. - // - // The order of the values in `bucket_counts` follows the bucket numbering - // schemes described for the three bucket types. The first value must be the - // count for the underflow bucket (number 0). The next N-2 values are the - // counts for the finite buckets (number 1 through N-2). The N'th value in - // `bucket_counts` is the count for the overflow bucket (number N-1). - repeated int64 bucket_counts = 7; - - // Must be in increasing order of `value` field. - repeated Exemplar exemplars = 10; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/distribution_pb2.py b/notification-service/venv/Lib/site-packages/google/api/distribution_pb2.py deleted file mode 100644 index d877a71..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/distribution_pb2.py +++ /dev/null @@ -1,63 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/distribution.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 -from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x1dgoogle/api/distribution.proto\x12\ngoogle.api\x1a\x19google/protobuf/any.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\xd9\x06\n\x0c\x44istribution\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x0c\n\x04mean\x18\x02 \x01(\x01\x12 \n\x18sum_of_squared_deviation\x18\x03 \x01(\x01\x12-\n\x05range\x18\x04 \x01(\x0b\x32\x1e.google.api.Distribution.Range\x12>\n\x0e\x62ucket_options\x18\x06 \x01(\x0b\x32&.google.api.Distribution.BucketOptions\x12\x15\n\rbucket_counts\x18\x07 \x03(\x03\x12\x34\n\texemplars\x18\n \x03(\x0b\x32!.google.api.Distribution.Exemplar\x1a!\n\x05Range\x12\x0b\n\x03min\x18\x01 \x01(\x01\x12\x0b\n\x03max\x18\x02 \x01(\x01\x1a\xb5\x03\n\rBucketOptions\x12G\n\x0elinear_buckets\x18\x01 \x01(\x0b\x32-.google.api.Distribution.BucketOptions.LinearH\x00\x12Q\n\x13\x65xponential_buckets\x18\x02 \x01(\x0b\x32\x32.google.api.Distribution.BucketOptions.ExponentialH\x00\x12K\n\x10\x65xplicit_buckets\x18\x03 \x01(\x0b\x32/.google.api.Distribution.BucketOptions.ExplicitH\x00\x1a\x43\n\x06Linear\x12\x1a\n\x12num_finite_buckets\x18\x01 \x01(\x05\x12\r\n\x05width\x18\x02 \x01(\x01\x12\x0e\n\x06offset\x18\x03 \x01(\x01\x1aO\n\x0b\x45xponential\x12\x1a\n\x12num_finite_buckets\x18\x01 \x01(\x05\x12\x15\n\rgrowth_factor\x18\x02 \x01(\x01\x12\r\n\x05scale\x18\x03 \x01(\x01\x1a\x1a\n\x08\x45xplicit\x12\x0e\n\x06\x62ounds\x18\x01 \x03(\x01\x42\t\n\x07options\x1as\n\x08\x45xemplar\x12\r\n\x05value\x18\x01 \x01(\x01\x12-\n\ttimestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12)\n\x0b\x61ttachments\x18\x03 \x03(\x0b\x32\x14.google.protobuf.AnyBq\n\x0e\x63om.google.apiB\x11\x44istributionProtoP\x01ZCgoogle.golang.org/genproto/googleapis/api/distribution;distribution\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, "google.api.distribution_pb2", _globals -) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\021DistributionProtoP\001ZCgoogle.golang.org/genproto/googleapis/api/distribution;distribution\242\002\004GAPI" - _globals["_DISTRIBUTION"]._serialized_start = 106 - _globals["_DISTRIBUTION"]._serialized_end = 963 - _globals["_DISTRIBUTION_RANGE"]._serialized_start = 373 - _globals["_DISTRIBUTION_RANGE"]._serialized_end = 406 - _globals["_DISTRIBUTION_BUCKETOPTIONS"]._serialized_start = 409 - _globals["_DISTRIBUTION_BUCKETOPTIONS"]._serialized_end = 846 - _globals["_DISTRIBUTION_BUCKETOPTIONS_LINEAR"]._serialized_start = 659 - _globals["_DISTRIBUTION_BUCKETOPTIONS_LINEAR"]._serialized_end = 726 - _globals["_DISTRIBUTION_BUCKETOPTIONS_EXPONENTIAL"]._serialized_start = 728 - _globals["_DISTRIBUTION_BUCKETOPTIONS_EXPONENTIAL"]._serialized_end = 807 - _globals["_DISTRIBUTION_BUCKETOPTIONS_EXPLICIT"]._serialized_start = 809 - _globals["_DISTRIBUTION_BUCKETOPTIONS_EXPLICIT"]._serialized_end = 835 - _globals["_DISTRIBUTION_EXEMPLAR"]._serialized_start = 848 - _globals["_DISTRIBUTION_EXEMPLAR"]._serialized_end = 963 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/distribution_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/distribution_pb2.pyi deleted file mode 100644 index 1c65b4e..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/distribution_pb2.pyi +++ /dev/null @@ -1,144 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import any_pb2 as _any_pb2 -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import timestamp_pb2 as _timestamp_pb2 -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor - -class Distribution(_message.Message): - __slots__ = ( - "count", - "mean", - "sum_of_squared_deviation", - "range", - "bucket_options", - "bucket_counts", - "exemplars", - ) - class Range(_message.Message): - __slots__ = ("min", "max") - MIN_FIELD_NUMBER: _ClassVar[int] - MAX_FIELD_NUMBER: _ClassVar[int] - min: float - max: float - def __init__( - self, min: _Optional[float] = ..., max: _Optional[float] = ... - ) -> None: ... - - class BucketOptions(_message.Message): - __slots__ = ("linear_buckets", "exponential_buckets", "explicit_buckets") - class Linear(_message.Message): - __slots__ = ("num_finite_buckets", "width", "offset") - NUM_FINITE_BUCKETS_FIELD_NUMBER: _ClassVar[int] - WIDTH_FIELD_NUMBER: _ClassVar[int] - OFFSET_FIELD_NUMBER: _ClassVar[int] - num_finite_buckets: int - width: float - offset: float - def __init__( - self, - num_finite_buckets: _Optional[int] = ..., - width: _Optional[float] = ..., - offset: _Optional[float] = ..., - ) -> None: ... - - class Exponential(_message.Message): - __slots__ = ("num_finite_buckets", "growth_factor", "scale") - NUM_FINITE_BUCKETS_FIELD_NUMBER: _ClassVar[int] - GROWTH_FACTOR_FIELD_NUMBER: _ClassVar[int] - SCALE_FIELD_NUMBER: _ClassVar[int] - num_finite_buckets: int - growth_factor: float - scale: float - def __init__( - self, - num_finite_buckets: _Optional[int] = ..., - growth_factor: _Optional[float] = ..., - scale: _Optional[float] = ..., - ) -> None: ... - - class Explicit(_message.Message): - __slots__ = ("bounds",) - BOUNDS_FIELD_NUMBER: _ClassVar[int] - bounds: _containers.RepeatedScalarFieldContainer[float] - def __init__(self, bounds: _Optional[_Iterable[float]] = ...) -> None: ... - - LINEAR_BUCKETS_FIELD_NUMBER: _ClassVar[int] - EXPONENTIAL_BUCKETS_FIELD_NUMBER: _ClassVar[int] - EXPLICIT_BUCKETS_FIELD_NUMBER: _ClassVar[int] - linear_buckets: Distribution.BucketOptions.Linear - exponential_buckets: Distribution.BucketOptions.Exponential - explicit_buckets: Distribution.BucketOptions.Explicit - def __init__( - self, - linear_buckets: _Optional[ - _Union[Distribution.BucketOptions.Linear, _Mapping] - ] = ..., - exponential_buckets: _Optional[ - _Union[Distribution.BucketOptions.Exponential, _Mapping] - ] = ..., - explicit_buckets: _Optional[ - _Union[Distribution.BucketOptions.Explicit, _Mapping] - ] = ..., - ) -> None: ... - - class Exemplar(_message.Message): - __slots__ = ("value", "timestamp", "attachments") - VALUE_FIELD_NUMBER: _ClassVar[int] - TIMESTAMP_FIELD_NUMBER: _ClassVar[int] - ATTACHMENTS_FIELD_NUMBER: _ClassVar[int] - value: float - timestamp: _timestamp_pb2.Timestamp - attachments: _containers.RepeatedCompositeFieldContainer[_any_pb2.Any] - def __init__( - self, - value: _Optional[float] = ..., - timestamp: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., - attachments: _Optional[_Iterable[_Union[_any_pb2.Any, _Mapping]]] = ..., - ) -> None: ... - - COUNT_FIELD_NUMBER: _ClassVar[int] - MEAN_FIELD_NUMBER: _ClassVar[int] - SUM_OF_SQUARED_DEVIATION_FIELD_NUMBER: _ClassVar[int] - RANGE_FIELD_NUMBER: _ClassVar[int] - BUCKET_OPTIONS_FIELD_NUMBER: _ClassVar[int] - BUCKET_COUNTS_FIELD_NUMBER: _ClassVar[int] - EXEMPLARS_FIELD_NUMBER: _ClassVar[int] - count: int - mean: float - sum_of_squared_deviation: float - range: Distribution.Range - bucket_options: Distribution.BucketOptions - bucket_counts: _containers.RepeatedScalarFieldContainer[int] - exemplars: _containers.RepeatedCompositeFieldContainer[Distribution.Exemplar] - def __init__( - self, - count: _Optional[int] = ..., - mean: _Optional[float] = ..., - sum_of_squared_deviation: _Optional[float] = ..., - range: _Optional[_Union[Distribution.Range, _Mapping]] = ..., - bucket_options: _Optional[_Union[Distribution.BucketOptions, _Mapping]] = ..., - bucket_counts: _Optional[_Iterable[int]] = ..., - exemplars: _Optional[_Iterable[_Union[Distribution.Exemplar, _Mapping]]] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/documentation.proto b/notification-service/venv/Lib/site-packages/google/api/documentation.proto deleted file mode 100644 index a730ab8..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/documentation.proto +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "DocumentationProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// `Documentation` provides the information for describing a service. -// -// Example: -//
documentation:
-//   summary: >
-//     The Google Calendar API gives access
-//     to most calendar features.
-//   pages:
-//   - name: Overview
-//     content: (== include google/foo/overview.md ==)
-//   - name: Tutorial
-//     content: (== include google/foo/tutorial.md ==)
-//     subpages:
-//     - name: Java
-//       content: (== include google/foo/tutorial_java.md ==)
-//   rules:
-//   - selector: google.calendar.Calendar.Get
-//     description: >
-//       ...
-//   - selector: google.calendar.Calendar.Put
-//     description: >
-//       ...
-// 
-// Documentation is provided in markdown syntax. In addition to -// standard markdown features, definition lists, tables and fenced -// code blocks are supported. Section headers can be provided and are -// interpreted relative to the section nesting of the context where -// a documentation fragment is embedded. -// -// Documentation from the IDL is merged with documentation defined -// via the config at normalization time, where documentation provided -// by config rules overrides IDL provided. -// -// A number of constructs specific to the API platform are supported -// in documentation text. -// -// In order to reference a proto element, the following -// notation can be used: -//
[fully.qualified.proto.name][]
-// To override the display text used for the link, this can be used: -//
[display text][fully.qualified.proto.name]
-// Text can be excluded from doc using the following notation: -//
(-- internal comment --)
-// -// A few directives are available in documentation. Note that -// directives must appear on a single line to be properly -// identified. The `include` directive includes a markdown file from -// an external source: -//
(== include path/to/file ==)
-// The `resource_for` directive marks a message to be the resource of -// a collection in REST view. If it is not specified, tools attempt -// to infer the resource from the operations in a collection: -//
(== resource_for v1.shelves.books ==)
-// The directive `suppress_warning` does not directly affect documentation -// and is documented together with service config validation. -message Documentation { - // A short description of what the service does. The summary must be plain - // text. It becomes the overview of the service displayed in Google Cloud - // Console. - // NOTE: This field is equivalent to the standard field `description`. - string summary = 1; - - // The top level pages for the documentation set. - repeated Page pages = 5; - - // A list of documentation rules that apply to individual API elements. - // - // **NOTE:** All service configuration rules follow "last one wins" order. - repeated DocumentationRule rules = 3; - - // The URL to the root of documentation. - string documentation_root_url = 4; - - // Specifies the service root url if the default one (the service name - // from the yaml file) is not suitable. This can be seen in any fully - // specified service urls as well as sections that show a base that other - // urls are relative to. - string service_root_url = 6; - - // Declares a single overview page. For example: - //
documentation:
-  //   summary: ...
-  //   overview: (== include overview.md ==)
-  // 
- // This is a shortcut for the following declaration (using pages style): - //
documentation:
-  //   summary: ...
-  //   pages:
-  //   - name: Overview
-  //     content: (== include overview.md ==)
-  // 
- // Note: you cannot specify both `overview` field and `pages` field. - string overview = 2; -} - -// A documentation rule provides information about individual API elements. -message DocumentationRule { - // The selector is a comma-separated list of patterns for any element such as - // a method, a field, an enum value. Each pattern is a qualified name of the - // element which may end in "*", indicating a wildcard. Wildcards are only - // allowed at the end and for a whole component of the qualified name, - // i.e. "foo.*" is ok, but not "foo.b*" or "foo.*.bar". A wildcard will match - // one or more components. To specify a default for all applicable elements, - // the whole pattern "*" is used. - string selector = 1; - - // Description of the selected proto element (e.g. a message, a method, a - // 'service' definition, or a field). Defaults to leading & trailing comments - // taken from the proto source definition of the proto element. - string description = 2; - - // Deprecation description of the selected element(s). It can be provided if - // an element is marked as `deprecated`. - string deprecation_description = 3; -} - -// Represents a documentation page. A page can contain subpages to represent -// nested documentation set structure. -message Page { - // The name of the page. It will be used as an identity of the page to - // generate URI of the page, text of the link to this page in navigation, - // etc. The full page name (start from the root page name to this page - // concatenated with `.`) can be used as reference to the page in your - // documentation. For example: - //
pages:
-  // - name: Tutorial
-  //   content: (== include tutorial.md ==)
-  //   subpages:
-  //   - name: Java
-  //     content: (== include tutorial_java.md ==)
-  // 
- // You can reference `Java` page using Markdown reference link syntax: - // `[Java][Tutorial.Java]`. - string name = 1; - - // The Markdown content of the page. You can use ```(== include {path} - // ==)``` to include content from a Markdown file. The content can be used - // to produce the documentation page such as HTML format page. - string content = 2; - - // Subpages of this page. The order of subpages specified here will be - // honored in the generated docset. - repeated Page subpages = 3; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/documentation_pb2.py b/notification-service/venv/Lib/site-packages/google/api/documentation_pb2.py deleted file mode 100644 index 9469e0c..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/documentation_pb2.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/documentation.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x1egoogle/api/documentation.proto\x12\ngoogle.api"\xbb\x01\n\rDocumentation\x12\x0f\n\x07summary\x18\x01 \x01(\t\x12\x1f\n\x05pages\x18\x05 \x03(\x0b\x32\x10.google.api.Page\x12,\n\x05rules\x18\x03 \x03(\x0b\x32\x1d.google.api.DocumentationRule\x12\x1e\n\x16\x64ocumentation_root_url\x18\x04 \x01(\t\x12\x18\n\x10service_root_url\x18\x06 \x01(\t\x12\x10\n\x08overview\x18\x02 \x01(\t"[\n\x11\x44ocumentationRule\x12\x10\n\x08selector\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x1f\n\x17\x64\x65precation_description\x18\x03 \x01(\t"I\n\x04Page\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\x12"\n\x08subpages\x18\x03 \x03(\x0b\x32\x10.google.api.PageBt\n\x0e\x63om.google.apiB\x12\x44ocumentationProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, "google.api.documentation_pb2", _globals -) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\022DocumentationProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_DOCUMENTATION"]._serialized_start = 47 - _globals["_DOCUMENTATION"]._serialized_end = 234 - _globals["_DOCUMENTATIONRULE"]._serialized_start = 236 - _globals["_DOCUMENTATIONRULE"]._serialized_end = 327 - _globals["_PAGE"]._serialized_start = 329 - _globals["_PAGE"]._serialized_end = 402 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/documentation_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/documentation_pb2.pyi deleted file mode 100644 index 82f1a2b..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/documentation_pb2.pyi +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor - -class Documentation(_message.Message): - __slots__ = ( - "summary", - "pages", - "rules", - "documentation_root_url", - "service_root_url", - "overview", - ) - SUMMARY_FIELD_NUMBER: _ClassVar[int] - PAGES_FIELD_NUMBER: _ClassVar[int] - RULES_FIELD_NUMBER: _ClassVar[int] - DOCUMENTATION_ROOT_URL_FIELD_NUMBER: _ClassVar[int] - SERVICE_ROOT_URL_FIELD_NUMBER: _ClassVar[int] - OVERVIEW_FIELD_NUMBER: _ClassVar[int] - summary: str - pages: _containers.RepeatedCompositeFieldContainer[Page] - rules: _containers.RepeatedCompositeFieldContainer[DocumentationRule] - documentation_root_url: str - service_root_url: str - overview: str - def __init__( - self, - summary: _Optional[str] = ..., - pages: _Optional[_Iterable[_Union[Page, _Mapping]]] = ..., - rules: _Optional[_Iterable[_Union[DocumentationRule, _Mapping]]] = ..., - documentation_root_url: _Optional[str] = ..., - service_root_url: _Optional[str] = ..., - overview: _Optional[str] = ..., - ) -> None: ... - -class DocumentationRule(_message.Message): - __slots__ = ("selector", "description", "deprecation_description") - SELECTOR_FIELD_NUMBER: _ClassVar[int] - DESCRIPTION_FIELD_NUMBER: _ClassVar[int] - DEPRECATION_DESCRIPTION_FIELD_NUMBER: _ClassVar[int] - selector: str - description: str - deprecation_description: str - def __init__( - self, - selector: _Optional[str] = ..., - description: _Optional[str] = ..., - deprecation_description: _Optional[str] = ..., - ) -> None: ... - -class Page(_message.Message): - __slots__ = ("name", "content", "subpages") - NAME_FIELD_NUMBER: _ClassVar[int] - CONTENT_FIELD_NUMBER: _ClassVar[int] - SUBPAGES_FIELD_NUMBER: _ClassVar[int] - name: str - content: str - subpages: _containers.RepeatedCompositeFieldContainer[Page] - def __init__( - self, - name: _Optional[str] = ..., - content: _Optional[str] = ..., - subpages: _Optional[_Iterable[_Union[Page, _Mapping]]] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/endpoint.proto b/notification-service/venv/Lib/site-packages/google/api/endpoint.proto deleted file mode 100644 index 047cf54..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/endpoint.proto +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "EndpointProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// `Endpoint` describes a network address of a service that serves a set of -// APIs. It is commonly known as a service endpoint. A service may expose -// any number of service endpoints, and all service endpoints share the same -// service definition, such as quota limits and monitoring metrics. -// -// Example: -// -// type: google.api.Service -// name: library-example.googleapis.com -// endpoints: -// # Declares network address `https://library-example.googleapis.com` -// # for service `library-example.googleapis.com`. The `https` scheme -// # is implicit for all service endpoints. Other schemes may be -// # supported in the future. -// - name: library-example.googleapis.com -// allow_cors: false -// - name: content-staging-library-example.googleapis.com -// # Allows HTTP OPTIONS calls to be passed to the API frontend, for it -// # to decide whether the subsequent cross-origin request is allowed -// # to proceed. -// allow_cors: true -message Endpoint { - // The canonical name of this endpoint. - string name = 1; - - // Aliases for this endpoint, these will be served by the same UrlMap as the - // parent endpoint, and will be provisioned in the GCP stack for the Regional - // Endpoints. - repeated string aliases = 2; - - // The specification of an Internet routable address of API frontend that will - // handle requests to this [API - // Endpoint](https://cloud.google.com/apis/design/glossary). It should be - // either a valid IPv4 address or a fully-qualified domain name. For example, - // "8.8.8.8" or "myservice.appspot.com". - string target = 101; - - // Allowing - // [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing), aka - // cross-domain traffic, would allow the backends served from this endpoint to - // receive and respond to HTTP OPTIONS requests. The response will be used by - // the browser to determine whether the subsequent cross-origin request is - // allowed to proceed. - bool allow_cors = 5; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/endpoint_pb2.py b/notification-service/venv/Lib/site-packages/google/api/endpoint_pb2.py deleted file mode 100644 index 964e7f0..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/endpoint_pb2.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/endpoint.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x19google/api/endpoint.proto\x12\ngoogle.api"M\n\x08\x45ndpoint\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x61liases\x18\x02 \x03(\t\x12\x0e\n\x06target\x18\x65 \x01(\t\x12\x12\n\nallow_cors\x18\x05 \x01(\x08\x42o\n\x0e\x63om.google.apiB\rEndpointProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.endpoint_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\rEndpointProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_ENDPOINT"]._serialized_start = 41 - _globals["_ENDPOINT"]._serialized_end = 118 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/endpoint_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/endpoint_pb2.pyi deleted file mode 100644 index cb78d20..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/endpoint_pb2.pyi +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Optional as _Optional - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor - -class Endpoint(_message.Message): - __slots__ = ("name", "aliases", "target", "allow_cors") - NAME_FIELD_NUMBER: _ClassVar[int] - ALIASES_FIELD_NUMBER: _ClassVar[int] - TARGET_FIELD_NUMBER: _ClassVar[int] - ALLOW_CORS_FIELD_NUMBER: _ClassVar[int] - name: str - aliases: _containers.RepeatedScalarFieldContainer[str] - target: str - allow_cors: bool - def __init__( - self, - name: _Optional[str] = ..., - aliases: _Optional[_Iterable[str]] = ..., - target: _Optional[str] = ..., - allow_cors: bool = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/error_reason.proto b/notification-service/venv/Lib/site-packages/google/api/error_reason.proto deleted file mode 100644 index 3b4826e..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/error_reason.proto +++ /dev/null @@ -1,807 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/error_reason;error_reason"; -option java_multiple_files = true; -option java_outer_classname = "ErrorReasonProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// Defines the supported values for `google.rpc.ErrorInfo.reason` for the -// `googleapis.com` error domain. This error domain is reserved for [Service -// Infrastructure](https://cloud.google.com/service-infrastructure/docs/overview). -// For each error info of this domain, the metadata key "service" refers to the -// logical identifier of an API service, such as "pubsub.googleapis.com". The -// "consumer" refers to the entity that consumes an API Service. It typically is -// a Google project that owns the client application or the server resource, -// such as "projects/123". Other metadata keys are specific to each error -// reason. For more information, see the definition of the specific error -// reason. -enum ErrorReason { - // Do not use this default value. - ERROR_REASON_UNSPECIFIED = 0; - - // The request is calling a disabled service for a consumer. - // - // Example of an ErrorInfo when the consumer "projects/123" contacting - // "pubsub.googleapis.com" service which is disabled: - // - // { "reason": "SERVICE_DISABLED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "pubsub.googleapis.com" - // } - // } - // - // This response indicates the "pubsub.googleapis.com" has been disabled in - // "projects/123". - SERVICE_DISABLED = 1; - - // The request whose associated billing account is disabled. - // - // Example of an ErrorInfo when the consumer "projects/123" fails to contact - // "pubsub.googleapis.com" service because the associated billing account is - // disabled: - // - // { "reason": "BILLING_DISABLED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "pubsub.googleapis.com" - // } - // } - // - // This response indicates the billing account associated has been disabled. - BILLING_DISABLED = 2; - - // The request is denied because the provided [API - // key](https://cloud.google.com/docs/authentication/api-keys) is invalid. It - // may be in a bad format, cannot be found, or has been expired). - // - // Example of an ErrorInfo when the request is contacting - // "storage.googleapis.com" service with an invalid API key: - // - // { "reason": "API_KEY_INVALID", - // "domain": "googleapis.com", - // "metadata": { - // "service": "storage.googleapis.com", - // } - // } - API_KEY_INVALID = 3; - - // The request is denied because it violates [API key API - // restrictions](https://cloud.google.com/docs/authentication/api-keys#adding_api_restrictions). - // - // Example of an ErrorInfo when the consumer "projects/123" fails to call the - // "storage.googleapis.com" service because this service is restricted in the - // API key: - // - // { "reason": "API_KEY_SERVICE_BLOCKED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "storage.googleapis.com" - // } - // } - API_KEY_SERVICE_BLOCKED = 4; - - // The request is denied because it violates [API key HTTP - // restrictions](https://cloud.google.com/docs/authentication/api-keys#adding_http_restrictions). - // - // Example of an ErrorInfo when the consumer "projects/123" fails to call - // "storage.googleapis.com" service because the http referrer of the request - // violates API key HTTP restrictions: - // - // { "reason": "API_KEY_HTTP_REFERRER_BLOCKED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "storage.googleapis.com", - // } - // } - API_KEY_HTTP_REFERRER_BLOCKED = 7; - - // The request is denied because it violates [API key IP address - // restrictions](https://cloud.google.com/docs/authentication/api-keys#adding_application_restrictions). - // - // Example of an ErrorInfo when the consumer "projects/123" fails to call - // "storage.googleapis.com" service because the caller IP of the request - // violates API key IP address restrictions: - // - // { "reason": "API_KEY_IP_ADDRESS_BLOCKED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "storage.googleapis.com", - // } - // } - API_KEY_IP_ADDRESS_BLOCKED = 8; - - // The request is denied because it violates [API key Android application - // restrictions](https://cloud.google.com/docs/authentication/api-keys#adding_application_restrictions). - // - // Example of an ErrorInfo when the consumer "projects/123" fails to call - // "storage.googleapis.com" service because the request from the Android apps - // violates the API key Android application restrictions: - // - // { "reason": "API_KEY_ANDROID_APP_BLOCKED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "storage.googleapis.com" - // } - // } - API_KEY_ANDROID_APP_BLOCKED = 9; - - // The request is denied because it violates [API key iOS application - // restrictions](https://cloud.google.com/docs/authentication/api-keys#adding_application_restrictions). - // - // Example of an ErrorInfo when the consumer "projects/123" fails to call - // "storage.googleapis.com" service because the request from the iOS apps - // violates the API key iOS application restrictions: - // - // { "reason": "API_KEY_IOS_APP_BLOCKED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "storage.googleapis.com" - // } - // } - API_KEY_IOS_APP_BLOCKED = 13; - - // The request is denied because there is not enough rate quota for the - // consumer. - // - // Example of an ErrorInfo when the consumer "projects/123" fails to contact - // "pubsub.googleapis.com" service because consumer's rate quota usage has - // reached the maximum value set for the quota limit - // "ReadsPerMinutePerProject" on the quota metric - // "pubsub.googleapis.com/read_requests": - // - // { "reason": "RATE_LIMIT_EXCEEDED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "pubsub.googleapis.com", - // "quota_metric": "pubsub.googleapis.com/read_requests", - // "quota_limit": "ReadsPerMinutePerProject" - // } - // } - // - // Example of an ErrorInfo when the consumer "projects/123" checks quota on - // the service "dataflow.googleapis.com" and hits the organization quota - // limit "DefaultRequestsPerMinutePerOrganization" on the metric - // "dataflow.googleapis.com/default_requests". - // - // { "reason": "RATE_LIMIT_EXCEEDED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "dataflow.googleapis.com", - // "quota_metric": "dataflow.googleapis.com/default_requests", - // "quota_limit": "DefaultRequestsPerMinutePerOrganization" - // } - // } - RATE_LIMIT_EXCEEDED = 5; - - // The request is denied because there is not enough resource quota for the - // consumer. - // - // Example of an ErrorInfo when the consumer "projects/123" fails to contact - // "compute.googleapis.com" service because consumer's resource quota usage - // has reached the maximum value set for the quota limit "VMsPerProject" - // on the quota metric "compute.googleapis.com/vms": - // - // { "reason": "RESOURCE_QUOTA_EXCEEDED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "compute.googleapis.com", - // "quota_metric": "compute.googleapis.com/vms", - // "quota_limit": "VMsPerProject" - // } - // } - // - // Example of an ErrorInfo when the consumer "projects/123" checks resource - // quota on the service "dataflow.googleapis.com" and hits the organization - // quota limit "jobs-per-organization" on the metric - // "dataflow.googleapis.com/job_count". - // - // { "reason": "RESOURCE_QUOTA_EXCEEDED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "dataflow.googleapis.com", - // "quota_metric": "dataflow.googleapis.com/job_count", - // "quota_limit": "jobs-per-organization" - // } - // } - RESOURCE_QUOTA_EXCEEDED = 6; - - // The request whose associated billing account address is in a tax restricted - // location, violates the local tax restrictions when creating resources in - // the restricted region. - // - // Example of an ErrorInfo when creating the Cloud Storage Bucket in the - // container "projects/123" under a tax restricted region - // "locations/asia-northeast3": - // - // { "reason": "LOCATION_TAX_POLICY_VIOLATED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "storage.googleapis.com", - // "location": "locations/asia-northeast3" - // } - // } - // - // This response indicates creating the Cloud Storage Bucket in - // "locations/asia-northeast3" violates the location tax restriction. - LOCATION_TAX_POLICY_VIOLATED = 10; - - // The request is denied because the caller does not have required permission - // on the user project "projects/123" or the user project is invalid. For more - // information, check the [userProject System - // Parameters](https://cloud.google.com/apis/docs/system-parameters). - // - // Example of an ErrorInfo when the caller is calling Cloud Storage service - // with insufficient permissions on the user project: - // - // { "reason": "USER_PROJECT_DENIED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "storage.googleapis.com" - // } - // } - USER_PROJECT_DENIED = 11; - - // The request is denied because the consumer "projects/123" is suspended due - // to Terms of Service(Tos) violations. Check [Project suspension - // guidelines](https://cloud.google.com/resource-manager/docs/project-suspension-guidelines) - // for more information. - // - // Example of an ErrorInfo when calling Cloud Storage service with the - // suspended consumer "projects/123": - // - // { "reason": "CONSUMER_SUSPENDED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "storage.googleapis.com" - // } - // } - CONSUMER_SUSPENDED = 12; - - // The request is denied because the associated consumer is invalid. It may be - // in a bad format, cannot be found, or have been deleted. - // - // Example of an ErrorInfo when calling Cloud Storage service with the - // invalid consumer "projects/123": - // - // { "reason": "CONSUMER_INVALID", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "storage.googleapis.com" - // } - // } - CONSUMER_INVALID = 14; - - // The request is denied because it violates [VPC Service - // Controls](https://cloud.google.com/vpc-service-controls/docs/overview). - // The 'uid' field is a random generated identifier that customer can use it - // to search the audit log for a request rejected by VPC Service Controls. For - // more information, please refer [VPC Service Controls - // Troubleshooting](https://cloud.google.com/vpc-service-controls/docs/troubleshooting#unique-id) - // - // Example of an ErrorInfo when the consumer "projects/123" fails to call - // Cloud Storage service because the request is prohibited by the VPC Service - // Controls. - // - // { "reason": "SECURITY_POLICY_VIOLATED", - // "domain": "googleapis.com", - // "metadata": { - // "uid": "123456789abcde", - // "consumer": "projects/123", - // "service": "storage.googleapis.com" - // } - // } - SECURITY_POLICY_VIOLATED = 15; - - // The request is denied because the provided access token has expired. - // - // Example of an ErrorInfo when the request is calling Cloud Storage service - // with an expired access token: - // - // { "reason": "ACCESS_TOKEN_EXPIRED", - // "domain": "googleapis.com", - // "metadata": { - // "service": "storage.googleapis.com", - // "method": "google.storage.v1.Storage.GetObject" - // } - // } - ACCESS_TOKEN_EXPIRED = 16; - - // The request is denied because the provided access token doesn't have at - // least one of the acceptable scopes required for the API. Please check - // [OAuth 2.0 Scopes for Google - // APIs](https://developers.google.com/identity/protocols/oauth2/scopes) for - // the list of the OAuth 2.0 scopes that you might need to request to access - // the API. - // - // Example of an ErrorInfo when the request is calling Cloud Storage service - // with an access token that is missing required scopes: - // - // { "reason": "ACCESS_TOKEN_SCOPE_INSUFFICIENT", - // "domain": "googleapis.com", - // "metadata": { - // "service": "storage.googleapis.com", - // "method": "google.storage.v1.Storage.GetObject" - // } - // } - ACCESS_TOKEN_SCOPE_INSUFFICIENT = 17; - - // The request is denied because the account associated with the provided - // access token is in an invalid state, such as disabled or deleted. - // For more information, see https://cloud.google.com/docs/authentication. - // - // Warning: For privacy reasons, the server may not be able to disclose the - // email address for some accounts. The client MUST NOT depend on the - // availability of the `email` attribute. - // - // Example of an ErrorInfo when the request is to the Cloud Storage API with - // an access token that is associated with a disabled or deleted [service - // account](http://cloud/iam/docs/service-accounts): - // - // { "reason": "ACCOUNT_STATE_INVALID", - // "domain": "googleapis.com", - // "metadata": { - // "service": "storage.googleapis.com", - // "method": "google.storage.v1.Storage.GetObject", - // "email": "user@123.iam.gserviceaccount.com" - // } - // } - ACCOUNT_STATE_INVALID = 18; - - // The request is denied because the type of the provided access token is not - // supported by the API being called. - // - // Example of an ErrorInfo when the request is to the Cloud Storage API with - // an unsupported token type. - // - // { "reason": "ACCESS_TOKEN_TYPE_UNSUPPORTED", - // "domain": "googleapis.com", - // "metadata": { - // "service": "storage.googleapis.com", - // "method": "google.storage.v1.Storage.GetObject" - // } - // } - ACCESS_TOKEN_TYPE_UNSUPPORTED = 19; - - // The request is denied because the request doesn't have any authentication - // credentials. For more information regarding the supported authentication - // strategies for Google Cloud APIs, see - // https://cloud.google.com/docs/authentication. - // - // Example of an ErrorInfo when the request is to the Cloud Storage API - // without any authentication credentials. - // - // { "reason": "CREDENTIALS_MISSING", - // "domain": "googleapis.com", - // "metadata": { - // "service": "storage.googleapis.com", - // "method": "google.storage.v1.Storage.GetObject" - // } - // } - CREDENTIALS_MISSING = 20; - - // The request is denied because the provided project owning the resource - // which acts as the [API - // consumer](https://cloud.google.com/apis/design/glossary#api_consumer) is - // invalid. It may be in a bad format or empty. - // - // Example of an ErrorInfo when the request is to the Cloud Functions API, - // but the offered resource project in the request in a bad format which can't - // perform the ListFunctions method. - // - // { "reason": "RESOURCE_PROJECT_INVALID", - // "domain": "googleapis.com", - // "metadata": { - // "service": "cloudfunctions.googleapis.com", - // "method": - // "google.cloud.functions.v1.CloudFunctionsService.ListFunctions" - // } - // } - RESOURCE_PROJECT_INVALID = 21; - - // The request is denied because the provided session cookie is missing, - // invalid or failed to decode. - // - // Example of an ErrorInfo when the request is calling Cloud Storage service - // with a SID cookie which can't be decoded. - // - // { "reason": "SESSION_COOKIE_INVALID", - // "domain": "googleapis.com", - // "metadata": { - // "service": "storage.googleapis.com", - // "method": "google.storage.v1.Storage.GetObject", - // "cookie": "SID" - // } - // } - SESSION_COOKIE_INVALID = 23; - - // The request is denied because the user is from a Google Workspace customer - // that blocks their users from accessing a particular service. - // - // Example scenario: https://support.google.com/a/answer/9197205?hl=en - // - // Example of an ErrorInfo when access to Google Cloud Storage service is - // blocked by the Google Workspace administrator: - // - // { "reason": "USER_BLOCKED_BY_ADMIN", - // "domain": "googleapis.com", - // "metadata": { - // "service": "storage.googleapis.com", - // "method": "google.storage.v1.Storage.GetObject", - // } - // } - USER_BLOCKED_BY_ADMIN = 24; - - // The request is denied because the resource service usage is restricted - // by administrators according to the organization policy constraint. - // For more information see - // https://cloud.google.com/resource-manager/docs/organization-policy/restricting-services. - // - // Example of an ErrorInfo when access to Google Cloud Storage service is - // restricted by Resource Usage Restriction policy: - // - // { "reason": "RESOURCE_USAGE_RESTRICTION_VIOLATED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/project-123", - // "service": "storage.googleapis.com" - // } - // } - RESOURCE_USAGE_RESTRICTION_VIOLATED = 25; - - // Unimplemented. Do not use. - // - // The request is denied because it contains unsupported system parameters in - // URL query parameters or HTTP headers. For more information, - // see https://cloud.google.com/apis/docs/system-parameters - // - // Example of an ErrorInfo when access "pubsub.googleapis.com" service with - // a request header of "x-goog-user-ip": - // - // { "reason": "SYSTEM_PARAMETER_UNSUPPORTED", - // "domain": "googleapis.com", - // "metadata": { - // "service": "pubsub.googleapis.com" - // "parameter": "x-goog-user-ip" - // } - // } - SYSTEM_PARAMETER_UNSUPPORTED = 26; - - // The request is denied because it violates Org Restriction: the requested - // resource does not belong to allowed organizations specified in - // "X-Goog-Allowed-Resources" header. - // - // Example of an ErrorInfo when accessing a GCP resource that is restricted by - // Org Restriction for "pubsub.googleapis.com" service. - // - // { - // reason: "ORG_RESTRICTION_VIOLATION" - // domain: "googleapis.com" - // metadata { - // "consumer":"projects/123456" - // "service": "pubsub.googleapis.com" - // } - // } - ORG_RESTRICTION_VIOLATION = 27; - - // The request is denied because "X-Goog-Allowed-Resources" header is in a bad - // format. - // - // Example of an ErrorInfo when - // accessing "pubsub.googleapis.com" service with an invalid - // "X-Goog-Allowed-Resources" request header. - // - // { - // reason: "ORG_RESTRICTION_HEADER_INVALID" - // domain: "googleapis.com" - // metadata { - // "consumer":"projects/123456" - // "service": "pubsub.googleapis.com" - // } - // } - ORG_RESTRICTION_HEADER_INVALID = 28; - - // Unimplemented. Do not use. - // - // The request is calling a service that is not visible to the consumer. - // - // Example of an ErrorInfo when the consumer "projects/123" contacting - // "pubsub.googleapis.com" service which is not visible to the consumer. - // - // { "reason": "SERVICE_NOT_VISIBLE", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "pubsub.googleapis.com" - // } - // } - // - // This response indicates the "pubsub.googleapis.com" is not visible to - // "projects/123" (or it may not exist). - SERVICE_NOT_VISIBLE = 29; - - // The request is related to a project for which GCP access is suspended. - // - // Example of an ErrorInfo when the consumer "projects/123" fails to contact - // "pubsub.googleapis.com" service because GCP access is suspended: - // - // { "reason": "GCP_SUSPENDED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "pubsub.googleapis.com" - // } - // } - // - // This response indicates the associated GCP account has been suspended. - GCP_SUSPENDED = 30; - - // The request violates the location policies when creating resources in - // the restricted region. - // - // Example of an ErrorInfo when creating the Cloud Storage Bucket by - // "projects/123" for service storage.googleapis.com: - // - // { "reason": "LOCATION_POLICY_VIOLATED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "storage.googleapis.com", - // } - // } - // - // This response indicates creating the Cloud Storage Bucket in - // "locations/asia-northeast3" violates at least one location policy. - // The troubleshooting guidance is provided in the Help links. - LOCATION_POLICY_VIOLATED = 31; - - // The request is denied because origin request header is missing. - // - // Example of an ErrorInfo when - // accessing "pubsub.googleapis.com" service with an empty "Origin" request - // header. - // - // { - // reason: "MISSING_ORIGIN" - // domain: "googleapis.com" - // metadata { - // "consumer":"projects/123456" - // "service": "pubsub.googleapis.com" - // } - // } - MISSING_ORIGIN = 33; - - // The request is denied because the request contains more than one credential - // type that are individually acceptable, but not together. The customer - // should retry their request with only one set of credentials. - // - // Example of an ErrorInfo when - // accessing "pubsub.googleapis.com" service with overloaded credentials. - // - // { - // reason: "OVERLOADED_CREDENTIALS" - // domain: "googleapis.com" - // metadata { - // "consumer":"projects/123456" - // "service": "pubsub.googleapis.com" - // } - // } - OVERLOADED_CREDENTIALS = 34; - - // The request whose associated location violates the location org policy - // restrictions when creating resources in the restricted region. - // - // Example of an ErrorInfo when creating the Cloud Storage Bucket in the - // container "projects/123" under a restricted region - // "locations/asia-northeast3": - // - // { - // "reason": "LOCATION_ORG_POLICY_VIOLATED", - // "domain": "googleapis.com", - // "metadata": { - // "resource": "projects/123", - // "location": "locations/asia-northeast3" - // } - // } - // - // This response indicates creating the Cloud Storage Bucket in - // "locations/asia-northeast3" violates the location org policy restriction. - LOCATION_ORG_POLICY_VIOLATED = 35; - - // The request is denied because it access data of regulated customers using - // TLS 1.0 and 1.1. - // - // Example of an ErrorInfo when accessing a GCP resource "projects/123" that - // is restricted by TLS Version Restriction for "pubsub.googleapis.com" - // service. - // - // { - // "reason": "TLS_ORG_POLICY_VIOLATED", - // "domain": "googleapis.com", - // "metadata": { - // "service": "pubsub.googleapis.com" - // "resource": "projects/123", - // "policyName": "constraints/gcp.restrictTLSVersion", - // "tlsVersion": "TLS_VERSION_1" - // } - // } - TLS_ORG_POLICY_VIOLATED = 36; - - // The request is denied because the associated project has exceeded the - // emulator quota limit. - // - // Example of an ErrorInfo when the associated "projects/123" has exceeded the - // emulator quota limit. - // - // { - // "reason": "EMULATOR_QUOTA_EXCEEDED", - // "domain": "googleapis.com", - // "metadata": { - // "service": "pubsub.googleapis.com" - // "consumer": "projects/123" - // } - // } - EMULATOR_QUOTA_EXCEEDED = 38; - - // The request is denied because the associated application credential header - // is invalid for an Android applications. - // - // Example of an ErrorInfo when the request from an Android application to the - // "pubsub.googleapis.com" with an invalid application credential header. - // - // { - // "reason": "CREDENTIAL_ANDROID_APP_INVALID", - // "domain": "googleapis.com", - // "metadata": { - // "service": "pubsub.googleapis.com" - // } - // } - CREDENTIAL_ANDROID_APP_INVALID = 39; - - // The request is denied because IAM permission on resource is denied. - // - // Example of an ErrorInfo when the IAM permission `aiplatform.datasets.list` - // is denied on resource `projects/123`. - // - // { - // "reason": "IAM_PERMISSION_DENIED", - // "domain": "googleapis.com", - // "metadata": { - // "resource": "projects/123" - // "permission": "aiplatform.datasets.list" - // } - // } - IAM_PERMISSION_DENIED = 41; - - // The request is denied because it contains the invalid JWT token. - // - // Example of an ErrorInfo when the request contains an invalid JWT token for - // service `storage.googleapis.com`. - // - // { - // "reason": "JWT_TOKEN_INVALID", - // "domain": "googleapis.com", - // "metadata": { - // "service": "storage.googleapis.com" - // } - // } - JWT_TOKEN_INVALID = 42; - - // The request is denied because it contains credential with type that is - // unsupported. - // - // Example of an ErrorInfo when the request contains an unsupported credential - // type for service `storage.googleapis.com`. - // - // { - // "reason": "CREDENTIAL_TYPE_UNSUPPORTED", - // "domain": "googleapis.com", - // "metadata": { - // "service": "storage.googleapis.com" - // } - // } - CREDENTIAL_TYPE_UNSUPPORTED = 43; - - // The request is denied because it contains unsupported account type. - // - // Example of an ErrorInfo when the request contains an unsupported account - // type for service `storage.googleapis.com`. - // - // { - // "reason": "ACCOUNT_TYPE_UNSUPPORTED", - // "domain": "googleapis.com", - // "metadata": { - // "service": "storage.googleapis.com" - // } - // } - ACCOUNT_TYPE_UNSUPPORTED = 44; - - // The request is denied because the API endpoint is restricted by - // administrators according to the organization policy constraint. - // For more information see - // https://cloud.google.com/assured-workloads/docs/restrict-endpoint-usage. - // - // Example of an ErrorInfo when access to Google Cloud Storage service is - // restricted by Restrict Endpoint Usage policy: - // - // { - // "reason": "ENDPOINT_USAGE_RESTRICTION_VIOLATED", - // "domain": "googleapis.com/policies/endpointUsageRestriction", - // "metadata": { - // "policy_name": "constraints/gcp.restrictEndpointUsage", - // "checked_value": "storage.googleapis.com" - // "consumer": "organization/123" - // "service": "storage.googleapis.com" - // } - // } - ENDPOINT_USAGE_RESTRICTION_VIOLATED = 45; - - // The request is denied because the TLS Cipher Suite is restricted by - // administrators according to the organization policy constraint. - // For more information see - // https://cloud.google.com/assured-workloads/docs/restrict-tls-cipher-suites - // - // Example of an ErrorInfo when access to Google Cloud BigQuery service is - // restricted by Restrict TLS Cipher Suites policy: - // - // { - // "reason": "TLS_CIPHER_RESTRICTION_VIOLATED", - // "domain": "googleapis.com/policies/tlsCipherRestriction", - // "metadata": { - // "policy_name": "constraints/gcp.restrictTLSCipherSuites", - // "checked_value": "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - // "consumer": "organization/123" - // "service": "bigquery.googleapis.com" - // } - // } - TLS_CIPHER_RESTRICTION_VIOLATED = 46; - - // The request is denied because the MCP activation check fails. - // - // Example of an ErrorInfo when the container "projects/123" contacting - // "pubsub.googleapis.com" service which is disabled by MCP: - // - // { "reason": "MCP_SERVER_DISABLED", - // "domain": "googleapis.com", - // "metadata": { - // "consumer": "projects/123", - // "service": "pubsub.googleapis.com" - // } - // } - // - // This response indicates the "pubsub.googleapis.com" has been disabled in - // "projects/123" for MCP. - MCP_SERVER_DISABLED = 47; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/error_reason_pb2.py b/notification-service/venv/Lib/site-packages/google/api/error_reason_pb2.py deleted file mode 100644 index a3240a6..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/error_reason_pb2.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/error_reason.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b"\n\x1dgoogle/api/error_reason.proto\x12\ngoogle.api*\x92\n\n\x0b\x45rrorReason\x12\x1c\n\x18\x45RROR_REASON_UNSPECIFIED\x10\x00\x12\x14\n\x10SERVICE_DISABLED\x10\x01\x12\x14\n\x10\x42ILLING_DISABLED\x10\x02\x12\x13\n\x0f\x41PI_KEY_INVALID\x10\x03\x12\x1b\n\x17\x41PI_KEY_SERVICE_BLOCKED\x10\x04\x12!\n\x1d\x41PI_KEY_HTTP_REFERRER_BLOCKED\x10\x07\x12\x1e\n\x1a\x41PI_KEY_IP_ADDRESS_BLOCKED\x10\x08\x12\x1f\n\x1b\x41PI_KEY_ANDROID_APP_BLOCKED\x10\t\x12\x1b\n\x17\x41PI_KEY_IOS_APP_BLOCKED\x10\r\x12\x17\n\x13RATE_LIMIT_EXCEEDED\x10\x05\x12\x1b\n\x17RESOURCE_QUOTA_EXCEEDED\x10\x06\x12 \n\x1cLOCATION_TAX_POLICY_VIOLATED\x10\n\x12\x17\n\x13USER_PROJECT_DENIED\x10\x0b\x12\x16\n\x12\x43ONSUMER_SUSPENDED\x10\x0c\x12\x14\n\x10\x43ONSUMER_INVALID\x10\x0e\x12\x1c\n\x18SECURITY_POLICY_VIOLATED\x10\x0f\x12\x18\n\x14\x41\x43\x43\x45SS_TOKEN_EXPIRED\x10\x10\x12#\n\x1f\x41\x43\x43\x45SS_TOKEN_SCOPE_INSUFFICIENT\x10\x11\x12\x19\n\x15\x41\x43\x43OUNT_STATE_INVALID\x10\x12\x12!\n\x1d\x41\x43\x43\x45SS_TOKEN_TYPE_UNSUPPORTED\x10\x13\x12\x17\n\x13\x43REDENTIALS_MISSING\x10\x14\x12\x1c\n\x18RESOURCE_PROJECT_INVALID\x10\x15\x12\x1a\n\x16SESSION_COOKIE_INVALID\x10\x17\x12\x19\n\x15USER_BLOCKED_BY_ADMIN\x10\x18\x12'\n#RESOURCE_USAGE_RESTRICTION_VIOLATED\x10\x19\x12 \n\x1cSYSTEM_PARAMETER_UNSUPPORTED\x10\x1a\x12\x1d\n\x19ORG_RESTRICTION_VIOLATION\x10\x1b\x12\"\n\x1eORG_RESTRICTION_HEADER_INVALID\x10\x1c\x12\x17\n\x13SERVICE_NOT_VISIBLE\x10\x1d\x12\x11\n\rGCP_SUSPENDED\x10\x1e\x12\x1c\n\x18LOCATION_POLICY_VIOLATED\x10\x1f\x12\x12\n\x0eMISSING_ORIGIN\x10!\x12\x1a\n\x16OVERLOADED_CREDENTIALS\x10\"\x12 \n\x1cLOCATION_ORG_POLICY_VIOLATED\x10#\x12\x1b\n\x17TLS_ORG_POLICY_VIOLATED\x10$\x12\x1b\n\x17\x45MULATOR_QUOTA_EXCEEDED\x10&\x12\"\n\x1e\x43REDENTIAL_ANDROID_APP_INVALID\x10'\x12\x19\n\x15IAM_PERMISSION_DENIED\x10)\x12\x15\n\x11JWT_TOKEN_INVALID\x10*\x12\x1f\n\x1b\x43REDENTIAL_TYPE_UNSUPPORTED\x10+\x12\x1c\n\x18\x41\x43\x43OUNT_TYPE_UNSUPPORTED\x10,\x12'\n#ENDPOINT_USAGE_RESTRICTION_VIOLATED\x10-\x12#\n\x1fTLS_CIPHER_RESTRICTION_VIOLATED\x10.\x12\x17\n\x13MCP_SERVER_DISABLED\x10/Bp\n\x0e\x63om.google.apiB\x10\x45rrorReasonProtoP\x01ZCgoogle.golang.org/genproto/googleapis/api/error_reason;error_reason\xa2\x02\x04GAPIb\x06proto3" -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, "google.api.error_reason_pb2", _globals -) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\020ErrorReasonProtoP\001ZCgoogle.golang.org/genproto/googleapis/api/error_reason;error_reason\242\002\004GAPI" - _globals["_ERRORREASON"]._serialized_start = 46 - _globals["_ERRORREASON"]._serialized_end = 1344 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/error_reason_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/error_reason_pb2.pyi deleted file mode 100644 index 9450370..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/error_reason_pb2.pyi +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar - -from google.protobuf import descriptor as _descriptor -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper - -DESCRIPTOR: _descriptor.FileDescriptor - -class ErrorReason(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - ERROR_REASON_UNSPECIFIED: _ClassVar[ErrorReason] - SERVICE_DISABLED: _ClassVar[ErrorReason] - BILLING_DISABLED: _ClassVar[ErrorReason] - API_KEY_INVALID: _ClassVar[ErrorReason] - API_KEY_SERVICE_BLOCKED: _ClassVar[ErrorReason] - API_KEY_HTTP_REFERRER_BLOCKED: _ClassVar[ErrorReason] - API_KEY_IP_ADDRESS_BLOCKED: _ClassVar[ErrorReason] - API_KEY_ANDROID_APP_BLOCKED: _ClassVar[ErrorReason] - API_KEY_IOS_APP_BLOCKED: _ClassVar[ErrorReason] - RATE_LIMIT_EXCEEDED: _ClassVar[ErrorReason] - RESOURCE_QUOTA_EXCEEDED: _ClassVar[ErrorReason] - LOCATION_TAX_POLICY_VIOLATED: _ClassVar[ErrorReason] - USER_PROJECT_DENIED: _ClassVar[ErrorReason] - CONSUMER_SUSPENDED: _ClassVar[ErrorReason] - CONSUMER_INVALID: _ClassVar[ErrorReason] - SECURITY_POLICY_VIOLATED: _ClassVar[ErrorReason] - ACCESS_TOKEN_EXPIRED: _ClassVar[ErrorReason] - ACCESS_TOKEN_SCOPE_INSUFFICIENT: _ClassVar[ErrorReason] - ACCOUNT_STATE_INVALID: _ClassVar[ErrorReason] - ACCESS_TOKEN_TYPE_UNSUPPORTED: _ClassVar[ErrorReason] - CREDENTIALS_MISSING: _ClassVar[ErrorReason] - RESOURCE_PROJECT_INVALID: _ClassVar[ErrorReason] - SESSION_COOKIE_INVALID: _ClassVar[ErrorReason] - USER_BLOCKED_BY_ADMIN: _ClassVar[ErrorReason] - RESOURCE_USAGE_RESTRICTION_VIOLATED: _ClassVar[ErrorReason] - SYSTEM_PARAMETER_UNSUPPORTED: _ClassVar[ErrorReason] - ORG_RESTRICTION_VIOLATION: _ClassVar[ErrorReason] - ORG_RESTRICTION_HEADER_INVALID: _ClassVar[ErrorReason] - SERVICE_NOT_VISIBLE: _ClassVar[ErrorReason] - GCP_SUSPENDED: _ClassVar[ErrorReason] - LOCATION_POLICY_VIOLATED: _ClassVar[ErrorReason] - MISSING_ORIGIN: _ClassVar[ErrorReason] - OVERLOADED_CREDENTIALS: _ClassVar[ErrorReason] - LOCATION_ORG_POLICY_VIOLATED: _ClassVar[ErrorReason] - TLS_ORG_POLICY_VIOLATED: _ClassVar[ErrorReason] - EMULATOR_QUOTA_EXCEEDED: _ClassVar[ErrorReason] - CREDENTIAL_ANDROID_APP_INVALID: _ClassVar[ErrorReason] - IAM_PERMISSION_DENIED: _ClassVar[ErrorReason] - JWT_TOKEN_INVALID: _ClassVar[ErrorReason] - CREDENTIAL_TYPE_UNSUPPORTED: _ClassVar[ErrorReason] - ACCOUNT_TYPE_UNSUPPORTED: _ClassVar[ErrorReason] - ENDPOINT_USAGE_RESTRICTION_VIOLATED: _ClassVar[ErrorReason] - TLS_CIPHER_RESTRICTION_VIOLATED: _ClassVar[ErrorReason] - MCP_SERVER_DISABLED: _ClassVar[ErrorReason] - -ERROR_REASON_UNSPECIFIED: ErrorReason -SERVICE_DISABLED: ErrorReason -BILLING_DISABLED: ErrorReason -API_KEY_INVALID: ErrorReason -API_KEY_SERVICE_BLOCKED: ErrorReason -API_KEY_HTTP_REFERRER_BLOCKED: ErrorReason -API_KEY_IP_ADDRESS_BLOCKED: ErrorReason -API_KEY_ANDROID_APP_BLOCKED: ErrorReason -API_KEY_IOS_APP_BLOCKED: ErrorReason -RATE_LIMIT_EXCEEDED: ErrorReason -RESOURCE_QUOTA_EXCEEDED: ErrorReason -LOCATION_TAX_POLICY_VIOLATED: ErrorReason -USER_PROJECT_DENIED: ErrorReason -CONSUMER_SUSPENDED: ErrorReason -CONSUMER_INVALID: ErrorReason -SECURITY_POLICY_VIOLATED: ErrorReason -ACCESS_TOKEN_EXPIRED: ErrorReason -ACCESS_TOKEN_SCOPE_INSUFFICIENT: ErrorReason -ACCOUNT_STATE_INVALID: ErrorReason -ACCESS_TOKEN_TYPE_UNSUPPORTED: ErrorReason -CREDENTIALS_MISSING: ErrorReason -RESOURCE_PROJECT_INVALID: ErrorReason -SESSION_COOKIE_INVALID: ErrorReason -USER_BLOCKED_BY_ADMIN: ErrorReason -RESOURCE_USAGE_RESTRICTION_VIOLATED: ErrorReason -SYSTEM_PARAMETER_UNSUPPORTED: ErrorReason -ORG_RESTRICTION_VIOLATION: ErrorReason -ORG_RESTRICTION_HEADER_INVALID: ErrorReason -SERVICE_NOT_VISIBLE: ErrorReason -GCP_SUSPENDED: ErrorReason -LOCATION_POLICY_VIOLATED: ErrorReason -MISSING_ORIGIN: ErrorReason -OVERLOADED_CREDENTIALS: ErrorReason -LOCATION_ORG_POLICY_VIOLATED: ErrorReason -TLS_ORG_POLICY_VIOLATED: ErrorReason -EMULATOR_QUOTA_EXCEEDED: ErrorReason -CREDENTIAL_ANDROID_APP_INVALID: ErrorReason -IAM_PERMISSION_DENIED: ErrorReason -JWT_TOKEN_INVALID: ErrorReason -CREDENTIAL_TYPE_UNSUPPORTED: ErrorReason -ACCOUNT_TYPE_UNSUPPORTED: ErrorReason -ENDPOINT_USAGE_RESTRICTION_VIOLATED: ErrorReason -TLS_CIPHER_RESTRICTION_VIOLATED: ErrorReason -MCP_SERVER_DISABLED: ErrorReason diff --git a/notification-service/venv/Lib/site-packages/google/api/field_behavior.proto b/notification-service/venv/Lib/site-packages/google/api/field_behavior.proto deleted file mode 100644 index 861f825..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/field_behavior.proto +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/protobuf/descriptor.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; -option java_multiple_files = true; -option java_outer_classname = "FieldBehaviorProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -extend google.protobuf.FieldOptions { - // A designation of a specific field behavior (required, output only, etc.) - // in protobuf messages. - // - // Examples: - // - // string name = 1 [(google.api.field_behavior) = REQUIRED]; - // State state = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; - // google.protobuf.Duration ttl = 1 - // [(google.api.field_behavior) = INPUT_ONLY]; - // google.protobuf.Timestamp expire_time = 1 - // [(google.api.field_behavior) = OUTPUT_ONLY, - // (google.api.field_behavior) = IMMUTABLE]; - repeated google.api.FieldBehavior field_behavior = 1052 [packed = false]; -} - -// An indicator of the behavior of a given field (for example, that a field -// is required in requests, or given as output but ignored as input). -// This **does not** change the behavior in protocol buffers itself; it only -// denotes the behavior and may affect how API tooling handles the field. -// -// Note: This enum **may** receive new values in the future. -enum FieldBehavior { - // Conventional default for enums. Do not use this. - FIELD_BEHAVIOR_UNSPECIFIED = 0; - - // Specifically denotes a field as optional. - // While all fields in protocol buffers are optional, this may be specified - // for emphasis if appropriate. - OPTIONAL = 1; - - // Denotes a field as required. - // This indicates that the field **must** be provided as part of the request, - // and failure to do so will cause an error (usually `INVALID_ARGUMENT`). - REQUIRED = 2; - - // Denotes a field as output only. - // This indicates that the field is provided in responses, but including the - // field in a request does nothing (the server *must* ignore it and - // *must not* throw an error as a result of the field's presence). - OUTPUT_ONLY = 3; - - // Denotes a field as input only. - // This indicates that the field is provided in requests, and the - // corresponding field is not included in output. - INPUT_ONLY = 4; - - // Denotes a field as immutable. - // This indicates that the field may be set once in a request to create a - // resource, but may not be changed thereafter. - IMMUTABLE = 5; - - // Denotes that a (repeated) field is an unordered list. - // This indicates that the service may provide the elements of the list - // in any arbitrary order, rather than the order the user originally - // provided. Additionally, the list's order may or may not be stable. - UNORDERED_LIST = 6; - - // Denotes that this field returns a non-empty default value if not set. - // This indicates that if the user provides the empty value in a request, - // a non-empty value will be returned. The user will not be aware of what - // non-empty value to expect. - NON_EMPTY_DEFAULT = 7; - - // Denotes that the field in a resource (a message annotated with - // google.api.resource) is used in the resource name to uniquely identify the - // resource. For AIP-compliant APIs, this should only be applied to the - // `name` field on the resource. - // - // This behavior should not be applied to references to other resources within - // the message. - // - // The identifier field of resources often have different field behavior - // depending on the request it is embedded in (e.g. for Create methods name - // is optional and unused, while for Update methods it is required). Instead - // of method-specific annotations, only `IDENTIFIER` is required. - IDENTIFIER = 8; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/field_behavior_pb2.py b/notification-service/venv/Lib/site-packages/google/api/field_behavior_pb2.py deleted file mode 100644 index b34ec2e..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/field_behavior_pb2.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/field_behavior.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b"\n\x1fgoogle/api/field_behavior.proto\x12\ngoogle.api\x1a google/protobuf/descriptor.proto*\xb6\x01\n\rFieldBehavior\x12\x1e\n\x1a\x46IELD_BEHAVIOR_UNSPECIFIED\x10\x00\x12\x0c\n\x08OPTIONAL\x10\x01\x12\x0c\n\x08REQUIRED\x10\x02\x12\x0f\n\x0bOUTPUT_ONLY\x10\x03\x12\x0e\n\nINPUT_ONLY\x10\x04\x12\r\n\tIMMUTABLE\x10\x05\x12\x12\n\x0eUNORDERED_LIST\x10\x06\x12\x15\n\x11NON_EMPTY_DEFAULT\x10\x07\x12\x0e\n\nIDENTIFIER\x10\x08:U\n\x0e\x66ield_behavior\x12\x1d.google.protobuf.FieldOptions\x18\x9c\x08 \x03(\x0e\x32\x19.google.api.FieldBehaviorB\x02\x10\x00\x42p\n\x0e\x63om.google.apiB\x12\x46ieldBehaviorProtoP\x01ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\xa2\x02\x04GAPIb\x06proto3" -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, "google.api.field_behavior_pb2", _globals -) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\022FieldBehaviorProtoP\001ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\242\002\004GAPI" - _globals["field_behavior"]._options = None - _globals["field_behavior"]._serialized_options = b"\020\000" - _globals["_FIELDBEHAVIOR"]._serialized_start = 82 - _globals["_FIELDBEHAVIOR"]._serialized_end = 264 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/field_behavior_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/field_behavior_pb2.pyi deleted file mode 100644 index c67ed03..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/field_behavior_pb2.pyi +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pb2 as _descriptor_pb2 -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper - -DESCRIPTOR: _descriptor.FileDescriptor - -class FieldBehavior(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - FIELD_BEHAVIOR_UNSPECIFIED: _ClassVar[FieldBehavior] - OPTIONAL: _ClassVar[FieldBehavior] - REQUIRED: _ClassVar[FieldBehavior] - OUTPUT_ONLY: _ClassVar[FieldBehavior] - INPUT_ONLY: _ClassVar[FieldBehavior] - IMMUTABLE: _ClassVar[FieldBehavior] - UNORDERED_LIST: _ClassVar[FieldBehavior] - NON_EMPTY_DEFAULT: _ClassVar[FieldBehavior] - IDENTIFIER: _ClassVar[FieldBehavior] - -FIELD_BEHAVIOR_UNSPECIFIED: FieldBehavior -OPTIONAL: FieldBehavior -REQUIRED: FieldBehavior -OUTPUT_ONLY: FieldBehavior -INPUT_ONLY: FieldBehavior -IMMUTABLE: FieldBehavior -UNORDERED_LIST: FieldBehavior -NON_EMPTY_DEFAULT: FieldBehavior -IDENTIFIER: FieldBehavior -FIELD_BEHAVIOR_FIELD_NUMBER: _ClassVar[int] -field_behavior: _descriptor.FieldDescriptor diff --git a/notification-service/venv/Lib/site-packages/google/api/field_info.proto b/notification-service/venv/Lib/site-packages/google/api/field_info.proto deleted file mode 100644 index 64387fd..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/field_info.proto +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/protobuf/descriptor.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; -option java_multiple_files = true; -option java_outer_classname = "FieldInfoProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -extend google.protobuf.FieldOptions { - // Rich semantic descriptor of an API field beyond the basic typing. - // - // Examples: - // - // string request_id = 1 [(google.api.field_info).format = UUID4]; - // string old_ip_address = 2 [(google.api.field_info).format = IPV4]; - // string new_ip_address = 3 [(google.api.field_info).format = IPV6]; - // string actual_ip_address = 4 [ - // (google.api.field_info).format = IPV4_OR_IPV6 - // ]; - // google.protobuf.Any generic_field = 5 [ - // (google.api.field_info).referenced_types = {type_name: "ActualType"}, - // (google.api.field_info).referenced_types = {type_name: "OtherType"}, - // ]; - // google.protobuf.Any generic_user_input = 5 [ - // (google.api.field_info).referenced_types = {type_name: "*"}, - // ]; - google.api.FieldInfo field_info = 291403980; -} - -// Rich semantic information of an API field beyond basic typing. -message FieldInfo { - // The standard format of a field value. The supported formats are all backed - // by either an RFC defined by the IETF or a Google-defined AIP. - enum Format { - // Default, unspecified value. - FORMAT_UNSPECIFIED = 0; - - // Universally Unique Identifier, version 4, value as defined by - // https://datatracker.ietf.org/doc/html/rfc4122. The value may be - // normalized to entirely lowercase letters. For example, the value - // `F47AC10B-58CC-0372-8567-0E02B2C3D479` would be normalized to - // `f47ac10b-58cc-0372-8567-0e02b2c3d479`. - UUID4 = 1; - - // Internet Protocol v4 value as defined by [RFC - // 791](https://datatracker.ietf.org/doc/html/rfc791). The value may be - // condensed, with leading zeros in each octet stripped. For example, - // `001.022.233.040` would be condensed to `1.22.233.40`. - IPV4 = 2; - - // Internet Protocol v6 value as defined by [RFC - // 2460](https://datatracker.ietf.org/doc/html/rfc2460). The value may be - // normalized to entirely lowercase letters with zeros compressed, following - // [RFC 5952](https://datatracker.ietf.org/doc/html/rfc5952). For example, - // the value `2001:0DB8:0::0` would be normalized to `2001:db8::`. - IPV6 = 3; - - // An IP address in either v4 or v6 format as described by the individual - // values defined herein. See the comments on the IPV4 and IPV6 types for - // allowed normalizations of each. - IPV4_OR_IPV6 = 4; - } - - // The standard format of a field value. This does not explicitly configure - // any API consumer, just documents the API's format for the field it is - // applied to. - Format format = 1; - - // The type(s) that the annotated, generic field may represent. - // - // Currently, this must only be used on fields of type `google.protobuf.Any`. - // Supporting other generic types may be considered in the future. - repeated TypeReference referenced_types = 2; -} - -// A reference to a message type, for use in [FieldInfo][google.api.FieldInfo]. -message TypeReference { - // The name of the type that the annotated, generic field may represent. - // If the type is in the same protobuf package, the value can be the simple - // message name e.g., `"MyMessage"`. Otherwise, the value must be the - // fully-qualified message name e.g., `"google.library.v1.Book"`. - // - // If the type(s) are unknown to the service (e.g. the field accepts generic - // user input), use the wildcard `"*"` to denote this behavior. - // - // See [AIP-202](https://google.aip.dev/202#type-references) for more details. - string type_name = 1; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/field_info_pb2.py b/notification-service/venv/Lib/site-packages/google/api/field_info_pb2.py deleted file mode 100644 index 56a1fd6..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/field_info_pb2.py +++ /dev/null @@ -1,54 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/field_info.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x1bgoogle/api/field_info.proto\x12\ngoogle.api\x1a google/protobuf/descriptor.proto"\xc1\x01\n\tFieldInfo\x12,\n\x06\x66ormat\x18\x01 \x01(\x0e\x32\x1c.google.api.FieldInfo.Format\x12\x33\n\x10referenced_types\x18\x02 \x03(\x0b\x32\x19.google.api.TypeReference"Q\n\x06\x46ormat\x12\x16\n\x12\x46ORMAT_UNSPECIFIED\x10\x00\x12\t\n\x05UUID4\x10\x01\x12\x08\n\x04IPV4\x10\x02\x12\x08\n\x04IPV6\x10\x03\x12\x10\n\x0cIPV4_OR_IPV6\x10\x04""\n\rTypeReference\x12\x11\n\ttype_name\x18\x01 \x01(\t:L\n\nfield_info\x12\x1d.google.protobuf.FieldOptions\x18\xcc\xf1\xf9\x8a\x01 \x01(\x0b\x32\x15.google.api.FieldInfoBl\n\x0e\x63om.google.apiB\x0e\x46ieldInfoProtoP\x01ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, "google.api.field_info_pb2", _globals -) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\016FieldInfoProtoP\001ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\242\002\004GAPI" - _globals["_FIELDINFO"]._serialized_start = 78 - _globals["_FIELDINFO"]._serialized_end = 271 - _globals["_FIELDINFO_FORMAT"]._serialized_start = 190 - _globals["_FIELDINFO_FORMAT"]._serialized_end = 271 - _globals["_TYPEREFERENCE"]._serialized_start = 273 - _globals["_TYPEREFERENCE"]._serialized_end = 307 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/field_info_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/field_info_pb2.pyi deleted file mode 100644 index 5681cdd..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/field_info_pb2.pyi +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pb2 as _descriptor_pb2 -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper - -DESCRIPTOR: _descriptor.FileDescriptor -FIELD_INFO_FIELD_NUMBER: _ClassVar[int] -field_info: _descriptor.FieldDescriptor - -class FieldInfo(_message.Message): - __slots__ = ("format", "referenced_types") - class Format(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - FORMAT_UNSPECIFIED: _ClassVar[FieldInfo.Format] - UUID4: _ClassVar[FieldInfo.Format] - IPV4: _ClassVar[FieldInfo.Format] - IPV6: _ClassVar[FieldInfo.Format] - IPV4_OR_IPV6: _ClassVar[FieldInfo.Format] - - FORMAT_UNSPECIFIED: FieldInfo.Format - UUID4: FieldInfo.Format - IPV4: FieldInfo.Format - IPV6: FieldInfo.Format - IPV4_OR_IPV6: FieldInfo.Format - FORMAT_FIELD_NUMBER: _ClassVar[int] - REFERENCED_TYPES_FIELD_NUMBER: _ClassVar[int] - format: FieldInfo.Format - referenced_types: _containers.RepeatedCompositeFieldContainer[TypeReference] - def __init__( - self, - format: _Optional[_Union[FieldInfo.Format, str]] = ..., - referenced_types: _Optional[_Iterable[_Union[TypeReference, _Mapping]]] = ..., - ) -> None: ... - -class TypeReference(_message.Message): - __slots__ = ("type_name",) - TYPE_NAME_FIELD_NUMBER: _ClassVar[int] - type_name: str - def __init__(self, type_name: _Optional[str] = ...) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/http.proto b/notification-service/venv/Lib/site-packages/google/api/http.proto deleted file mode 100644 index bb3af8e..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/http.proto +++ /dev/null @@ -1,370 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; -option java_multiple_files = true; -option java_outer_classname = "HttpProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// Defines the HTTP configuration for an API service. It contains a list of -// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method -// to one or more HTTP REST API methods. -message Http { - // A list of HTTP configuration rules that apply to individual API methods. - // - // **NOTE:** All service configuration rules follow "last one wins" order. - repeated HttpRule rules = 1; - - // When set to true, URL path parameters will be fully URI-decoded except in - // cases of single segment matches in reserved expansion, where "%2F" will be - // left encoded. - // - // The default behavior is to not decode RFC 6570 reserved characters in multi - // segment matches. - bool fully_decode_reserved_expansion = 2; -} - -// gRPC Transcoding -// -// gRPC Transcoding is a feature for mapping between a gRPC method and one or -// more HTTP REST endpoints. It allows developers to build a single API service -// that supports both gRPC APIs and REST APIs. Many systems, including [Google -// APIs](https://github.com/googleapis/googleapis), -// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC -// Gateway](https://github.com/grpc-ecosystem/grpc-gateway), -// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature -// and use it for large scale production services. -// -// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies -// how different portions of the gRPC request message are mapped to the URL -// path, URL query parameters, and HTTP request body. It also controls how the -// gRPC response message is mapped to the HTTP response body. `HttpRule` is -// typically specified as an `google.api.http` annotation on the gRPC method. -// -// Each mapping specifies a URL path template and an HTTP method. The path -// template may refer to one or more fields in the gRPC request message, as long -// as each field is a non-repeated field with a primitive (non-message) type. -// The path template controls how fields of the request message are mapped to -// the URL path. -// -// Example: -// -// service Messaging { -// rpc GetMessage(GetMessageRequest) returns (Message) { -// option (google.api.http) = { -// get: "/v1/{name=messages/*}" -// }; -// } -// } -// message GetMessageRequest { -// string name = 1; // Mapped to URL path. -// } -// message Message { -// string text = 1; // The resource content. -// } -// -// This enables an HTTP REST to gRPC mapping as below: -// -// - HTTP: `GET /v1/messages/123456` -// - gRPC: `GetMessage(name: "messages/123456")` -// -// Any fields in the request message which are not bound by the path template -// automatically become HTTP query parameters if there is no HTTP request body. -// For example: -// -// service Messaging { -// rpc GetMessage(GetMessageRequest) returns (Message) { -// option (google.api.http) = { -// get:"/v1/messages/{message_id}" -// }; -// } -// } -// message GetMessageRequest { -// message SubMessage { -// string subfield = 1; -// } -// string message_id = 1; // Mapped to URL path. -// int64 revision = 2; // Mapped to URL query parameter `revision`. -// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. -// } -// -// This enables a HTTP JSON to RPC mapping as below: -// -// - HTTP: `GET /v1/messages/123456?revision=2&sub.subfield=foo` -// - gRPC: `GetMessage(message_id: "123456" revision: 2 sub: -// SubMessage(subfield: "foo"))` -// -// Note that fields which are mapped to URL query parameters must have a -// primitive type or a repeated primitive type or a non-repeated message type. -// In the case of a repeated type, the parameter can be repeated in the URL -// as `...?param=A¶m=B`. In the case of a message type, each field of the -// message is mapped to a separate parameter, such as -// `...?foo.a=A&foo.b=B&foo.c=C`. -// -// For HTTP methods that allow a request body, the `body` field -// specifies the mapping. Consider a REST update method on the -// message resource collection: -// -// service Messaging { -// rpc UpdateMessage(UpdateMessageRequest) returns (Message) { -// option (google.api.http) = { -// patch: "/v1/messages/{message_id}" -// body: "message" -// }; -// } -// } -// message UpdateMessageRequest { -// string message_id = 1; // mapped to the URL -// Message message = 2; // mapped to the body -// } -// -// The following HTTP JSON to RPC mapping is enabled, where the -// representation of the JSON in the request body is determined by -// protos JSON encoding: -// -// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }` -// - gRPC: `UpdateMessage(message_id: "123456" message { text: "Hi!" })` -// -// The special name `*` can be used in the body mapping to define that -// every field not bound by the path template should be mapped to the -// request body. This enables the following alternative definition of -// the update method: -// -// service Messaging { -// rpc UpdateMessage(Message) returns (Message) { -// option (google.api.http) = { -// patch: "/v1/messages/{message_id}" -// body: "*" -// }; -// } -// } -// message Message { -// string message_id = 1; -// string text = 2; -// } -// -// -// The following HTTP JSON to RPC mapping is enabled: -// -// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }` -// - gRPC: `UpdateMessage(message_id: "123456" text: "Hi!")` -// -// Note that when using `*` in the body mapping, it is not possible to -// have HTTP parameters, as all fields not bound by the path end in -// the body. This makes this option more rarely used in practice when -// defining REST APIs. The common usage of `*` is in custom methods -// which don't use the URL at all for transferring data. -// -// It is possible to define multiple HTTP methods for one RPC by using -// the `additional_bindings` option. Example: -// -// service Messaging { -// rpc GetMessage(GetMessageRequest) returns (Message) { -// option (google.api.http) = { -// get: "/v1/messages/{message_id}" -// additional_bindings { -// get: "/v1/users/{user_id}/messages/{message_id}" -// } -// }; -// } -// } -// message GetMessageRequest { -// string message_id = 1; -// string user_id = 2; -// } -// -// This enables the following two alternative HTTP JSON to RPC mappings: -// -// - HTTP: `GET /v1/messages/123456` -// - gRPC: `GetMessage(message_id: "123456")` -// -// - HTTP: `GET /v1/users/me/messages/123456` -// - gRPC: `GetMessage(user_id: "me" message_id: "123456")` -// -// Rules for HTTP mapping -// -// 1. Leaf request fields (recursive expansion nested messages in the request -// message) are classified into three categories: -// - Fields referred by the path template. They are passed via the URL path. -// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They -// are passed via the HTTP -// request body. -// - All other fields are passed via the URL query parameters, and the -// parameter name is the field path in the request message. A repeated -// field can be represented as multiple query parameters under the same -// name. -// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL -// query parameter, all fields -// are passed via URL path and HTTP request body. -// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP -// request body, all -// fields are passed via URL path and URL query parameters. -// -// Path template syntax -// -// Template = "/" Segments [ Verb ] ; -// Segments = Segment { "/" Segment } ; -// Segment = "*" | "**" | LITERAL | Variable ; -// Variable = "{" FieldPath [ "=" Segments ] "}" ; -// FieldPath = IDENT { "." IDENT } ; -// Verb = ":" LITERAL ; -// -// The syntax `*` matches a single URL path segment. The syntax `**` matches -// zero or more URL path segments, which must be the last part of the URL path -// except the `Verb`. -// -// The syntax `Variable` matches part of the URL path as specified by its -// template. A variable template must not contain other variables. If a variable -// matches a single path segment, its template may be omitted, e.g. `{var}` -// is equivalent to `{var=*}`. -// -// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` -// contains any reserved character, such characters should be percent-encoded -// before the matching. -// -// If a variable contains exactly one path segment, such as `"{var}"` or -// `"{var=*}"`, when such a variable is expanded into a URL path on the client -// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The -// server side does the reverse decoding. Such variables show up in the -// [Discovery -// Document](https://developers.google.com/discovery/v1/reference/apis) as -// `{var}`. -// -// If a variable contains multiple path segments, such as `"{var=foo/*}"` -// or `"{var=**}"`, when such a variable is expanded into a URL path on the -// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. -// The server side does the reverse decoding, except "%2F" and "%2f" are left -// unchanged. Such variables show up in the -// [Discovery -// Document](https://developers.google.com/discovery/v1/reference/apis) as -// `{+var}`. -// -// Using gRPC API Service Configuration -// -// gRPC API Service Configuration (service config) is a configuration language -// for configuring a gRPC service to become a user-facing product. The -// service config is simply the YAML representation of the `google.api.Service` -// proto message. -// -// As an alternative to annotating your proto file, you can configure gRPC -// transcoding in your service config YAML files. You do this by specifying a -// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same -// effect as the proto annotation. This can be particularly useful if you -// have a proto that is reused in multiple services. Note that any transcoding -// specified in the service config will override any matching transcoding -// configuration in the proto. -// -// The following example selects a gRPC method and applies an `HttpRule` to it: -// -// http: -// rules: -// - selector: example.v1.Messaging.GetMessage -// get: /v1/messages/{message_id}/{sub.subfield} -// -// Special notes -// -// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the -// proto to JSON conversion must follow the [proto3 -// specification](https://developers.google.com/protocol-buffers/docs/proto3#json). -// -// While the single segment variable follows the semantics of -// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String -// Expansion, the multi segment variable **does not** follow RFC 6570 Section -// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion -// does not expand special characters like `?` and `#`, which would lead -// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding -// for multi segment variables. -// -// The path variables **must not** refer to any repeated or mapped field, -// because client libraries are not capable of handling such variable expansion. -// -// The path variables **must not** capture the leading "/" character. The reason -// is that the most common use case "{var}" does not capture the leading "/" -// character. For consistency, all path variables must share the same behavior. -// -// Repeated message fields must not be mapped to URL query parameters, because -// no client library can support such complicated mapping. -// -// If an API needs to use a JSON array for request or response body, it can map -// the request or response body to a repeated field. However, some gRPC -// Transcoding implementations may not support this feature. -message HttpRule { - // Selects a method to which this rule applies. - // - // Refer to [selector][google.api.DocumentationRule.selector] for syntax - // details. - string selector = 1; - - // Determines the URL pattern is matched by this rules. This pattern can be - // used with any of the {get|put|post|delete|patch} methods. A custom method - // can be defined using the 'custom' field. - oneof pattern { - // Maps to HTTP GET. Used for listing and getting information about - // resources. - string get = 2; - - // Maps to HTTP PUT. Used for replacing a resource. - string put = 3; - - // Maps to HTTP POST. Used for creating a resource or performing an action. - string post = 4; - - // Maps to HTTP DELETE. Used for deleting a resource. - string delete = 5; - - // Maps to HTTP PATCH. Used for updating a resource. - string patch = 6; - - // The custom pattern is used for specifying an HTTP method that is not - // included in the `pattern` field, such as HEAD, or "*" to leave the - // HTTP method unspecified for this rule. The wild-card rule is useful - // for services that provide content to Web (HTML) clients. - CustomHttpPattern custom = 8; - } - - // The name of the request field whose value is mapped to the HTTP request - // body, or `*` for mapping all request fields not captured by the path - // pattern to the HTTP body, or omitted for not having any HTTP request body. - // - // NOTE: the referred field must be present at the top-level of the request - // message type. - string body = 7; - - // Optional. The name of the response field whose value is mapped to the HTTP - // response body. When omitted, the entire response message will be used - // as the HTTP response body. - // - // NOTE: The referred field must be present at the top-level of the response - // message type. - string response_body = 12; - - // Additional HTTP bindings for the selector. Nested bindings must - // not contain an `additional_bindings` field themselves (that is, - // the nesting may only be one level deep). - repeated HttpRule additional_bindings = 11; -} - -// A custom pattern is used for defining custom HTTP verb. -message CustomHttpPattern { - // The name of this custom HTTP verb. - string kind = 1; - - // The path matched by this custom verb. - string path = 2; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/http_pb2.py b/notification-service/venv/Lib/site-packages/google/api/http_pb2.py deleted file mode 100644 index 1999eb3..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/http_pb2.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/http.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x15google/api/http.proto\x12\ngoogle.api"T\n\x04Http\x12#\n\x05rules\x18\x01 \x03(\x0b\x32\x14.google.api.HttpRule\x12\'\n\x1f\x66ully_decode_reserved_expansion\x18\x02 \x01(\x08"\x81\x02\n\x08HttpRule\x12\x10\n\x08selector\x18\x01 \x01(\t\x12\r\n\x03get\x18\x02 \x01(\tH\x00\x12\r\n\x03put\x18\x03 \x01(\tH\x00\x12\x0e\n\x04post\x18\x04 \x01(\tH\x00\x12\x10\n\x06\x64\x65lete\x18\x05 \x01(\tH\x00\x12\x0f\n\x05patch\x18\x06 \x01(\tH\x00\x12/\n\x06\x63ustom\x18\x08 \x01(\x0b\x32\x1d.google.api.CustomHttpPatternH\x00\x12\x0c\n\x04\x62ody\x18\x07 \x01(\t\x12\x15\n\rresponse_body\x18\x0c \x01(\t\x12\x31\n\x13\x61\x64\x64itional_bindings\x18\x0b \x03(\x0b\x32\x14.google.api.HttpRuleB\t\n\x07pattern"/\n\x11\x43ustomHttpPattern\x12\x0c\n\x04kind\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\tBg\n\x0e\x63om.google.apiB\tHttpProtoP\x01ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.http_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\tHttpProtoP\001ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\242\002\004GAPI" - _globals["_HTTP"]._serialized_start = 37 - _globals["_HTTP"]._serialized_end = 121 - _globals["_HTTPRULE"]._serialized_start = 124 - _globals["_HTTPRULE"]._serialized_end = 381 - _globals["_CUSTOMHTTPPATTERN"]._serialized_start = 383 - _globals["_CUSTOMHTTPPATTERN"]._serialized_end = 430 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/http_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/http_pb2.pyi deleted file mode 100644 index 445ea68..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/http_pb2.pyi +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor - -class Http(_message.Message): - __slots__ = ("rules", "fully_decode_reserved_expansion") - RULES_FIELD_NUMBER: _ClassVar[int] - FULLY_DECODE_RESERVED_EXPANSION_FIELD_NUMBER: _ClassVar[int] - rules: _containers.RepeatedCompositeFieldContainer[HttpRule] - fully_decode_reserved_expansion: bool - def __init__( - self, - rules: _Optional[_Iterable[_Union[HttpRule, _Mapping]]] = ..., - fully_decode_reserved_expansion: bool = ..., - ) -> None: ... - -class HttpRule(_message.Message): - __slots__ = ( - "selector", - "get", - "put", - "post", - "delete", - "patch", - "custom", - "body", - "response_body", - "additional_bindings", - ) - SELECTOR_FIELD_NUMBER: _ClassVar[int] - GET_FIELD_NUMBER: _ClassVar[int] - PUT_FIELD_NUMBER: _ClassVar[int] - POST_FIELD_NUMBER: _ClassVar[int] - DELETE_FIELD_NUMBER: _ClassVar[int] - PATCH_FIELD_NUMBER: _ClassVar[int] - CUSTOM_FIELD_NUMBER: _ClassVar[int] - BODY_FIELD_NUMBER: _ClassVar[int] - RESPONSE_BODY_FIELD_NUMBER: _ClassVar[int] - ADDITIONAL_BINDINGS_FIELD_NUMBER: _ClassVar[int] - selector: str - get: str - put: str - post: str - delete: str - patch: str - custom: CustomHttpPattern - body: str - response_body: str - additional_bindings: _containers.RepeatedCompositeFieldContainer[HttpRule] - def __init__( - self, - selector: _Optional[str] = ..., - get: _Optional[str] = ..., - put: _Optional[str] = ..., - post: _Optional[str] = ..., - delete: _Optional[str] = ..., - patch: _Optional[str] = ..., - custom: _Optional[_Union[CustomHttpPattern, _Mapping]] = ..., - body: _Optional[str] = ..., - response_body: _Optional[str] = ..., - additional_bindings: _Optional[_Iterable[_Union[HttpRule, _Mapping]]] = ..., - ) -> None: ... - -class CustomHttpPattern(_message.Message): - __slots__ = ("kind", "path") - KIND_FIELD_NUMBER: _ClassVar[int] - PATH_FIELD_NUMBER: _ClassVar[int] - kind: str - path: str - def __init__( - self, kind: _Optional[str] = ..., path: _Optional[str] = ... - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/httpbody.proto b/notification-service/venv/Lib/site-packages/google/api/httpbody.proto deleted file mode 100644 index 3fd226a..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/httpbody.proto +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/protobuf/any.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/httpbody;httpbody"; -option java_multiple_files = true; -option java_outer_classname = "HttpBodyProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// Message that represents an arbitrary HTTP body. It should only be used for -// payload formats that can't be represented as JSON, such as raw binary or -// an HTML page. -// -// -// This message can be used both in streaming and non-streaming API methods in -// the request as well as the response. -// -// It can be used as a top-level request field, which is convenient if one -// wants to extract parameters from either the URL or HTTP template into the -// request fields and also want access to the raw HTTP body. -// -// Example: -// -// message GetResourceRequest { -// // A unique request id. -// string request_id = 1; -// -// // The raw HTTP body is bound to this field. -// google.api.HttpBody http_body = 2; -// -// } -// -// service ResourceService { -// rpc GetResource(GetResourceRequest) -// returns (google.api.HttpBody); -// rpc UpdateResource(google.api.HttpBody) -// returns (google.protobuf.Empty); -// -// } -// -// Example with streaming methods: -// -// service CaldavService { -// rpc GetCalendar(stream google.api.HttpBody) -// returns (stream google.api.HttpBody); -// rpc UpdateCalendar(stream google.api.HttpBody) -// returns (stream google.api.HttpBody); -// -// } -// -// Use of this type only changes how the request and response bodies are -// handled, all other features will continue to work unchanged. -message HttpBody { - // The HTTP Content-Type header value specifying the content type of the body. - string content_type = 1; - - // The HTTP request/response body as raw binary. - bytes data = 2; - - // Application specific response metadata. Must be set in the first response - // for streaming APIs. - repeated google.protobuf.Any extensions = 3; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/httpbody_pb2.py b/notification-service/venv/Lib/site-packages/google/api/httpbody_pb2.py deleted file mode 100644 index 30c9271..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/httpbody_pb2.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/httpbody.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x19google/api/httpbody.proto\x12\ngoogle.api\x1a\x19google/protobuf/any.proto"X\n\x08HttpBody\x12\x14\n\x0c\x63ontent_type\x18\x01 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12(\n\nextensions\x18\x03 \x03(\x0b\x32\x14.google.protobuf.AnyBe\n\x0e\x63om.google.apiB\rHttpBodyProtoP\x01Z;google.golang.org/genproto/googleapis/api/httpbody;httpbody\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.httpbody_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\rHttpBodyProtoP\001Z;google.golang.org/genproto/googleapis/api/httpbody;httpbody\242\002\004GAPI" - _globals["_HTTPBODY"]._serialized_start = 68 - _globals["_HTTPBODY"]._serialized_end = 156 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/httpbody_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/httpbody_pb2.pyi deleted file mode 100644 index 27e90c0..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/httpbody_pb2.pyi +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import any_pb2 as _any_pb2 -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor - -class HttpBody(_message.Message): - __slots__ = ("content_type", "data", "extensions") - CONTENT_TYPE_FIELD_NUMBER: _ClassVar[int] - DATA_FIELD_NUMBER: _ClassVar[int] - EXTENSIONS_FIELD_NUMBER: _ClassVar[int] - content_type: str - data: bytes - extensions: _containers.RepeatedCompositeFieldContainer[_any_pb2.Any] - def __init__( - self, - content_type: _Optional[str] = ..., - data: _Optional[bytes] = ..., - extensions: _Optional[_Iterable[_Union[_any_pb2.Any, _Mapping]]] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/label.proto b/notification-service/venv/Lib/site-packages/google/api/label.proto deleted file mode 100644 index 5d77c70..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/label.proto +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/label;label"; -option java_multiple_files = true; -option java_outer_classname = "LabelProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// A description of a label. -message LabelDescriptor { - // Value types that can be used as label values. - enum ValueType { - // A variable-length string. This is the default. - STRING = 0; - - // Boolean; true or false. - BOOL = 1; - - // A 64-bit signed integer. - INT64 = 2; - } - - // The label key. - string key = 1; - - // The type of data that can be assigned to the label. - ValueType value_type = 2; - - // A human-readable description for the label. - string description = 3; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/label_pb2.py b/notification-service/venv/Lib/site-packages/google/api/label_pb2.py deleted file mode 100644 index 8291742..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/label_pb2.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/label.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x16google/api/label.proto\x12\ngoogle.api"\x9c\x01\n\x0fLabelDescriptor\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\nvalue_type\x18\x02 \x01(\x0e\x32%.google.api.LabelDescriptor.ValueType\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t",\n\tValueType\x12\n\n\x06STRING\x10\x00\x12\x08\n\x04\x42OOL\x10\x01\x12\t\n\x05INT64\x10\x02\x42\\\n\x0e\x63om.google.apiB\nLabelProtoP\x01Z5google.golang.org/genproto/googleapis/api/label;label\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.label_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\nLabelProtoP\001Z5google.golang.org/genproto/googleapis/api/label;label\242\002\004GAPI" - _globals["_LABELDESCRIPTOR"]._serialized_start = 39 - _globals["_LABELDESCRIPTOR"]._serialized_end = 195 - _globals["_LABELDESCRIPTOR_VALUETYPE"]._serialized_start = 151 - _globals["_LABELDESCRIPTOR_VALUETYPE"]._serialized_end = 195 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/label_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/label_pb2.pyi deleted file mode 100644 index ca9a0b7..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/label_pb2.pyi +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper - -DESCRIPTOR: _descriptor.FileDescriptor - -class LabelDescriptor(_message.Message): - __slots__ = ("key", "value_type", "description") - class ValueType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - STRING: _ClassVar[LabelDescriptor.ValueType] - BOOL: _ClassVar[LabelDescriptor.ValueType] - INT64: _ClassVar[LabelDescriptor.ValueType] - - STRING: LabelDescriptor.ValueType - BOOL: LabelDescriptor.ValueType - INT64: LabelDescriptor.ValueType - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_TYPE_FIELD_NUMBER: _ClassVar[int] - DESCRIPTION_FIELD_NUMBER: _ClassVar[int] - key: str - value_type: LabelDescriptor.ValueType - description: str - def __init__( - self, - key: _Optional[str] = ..., - value_type: _Optional[_Union[LabelDescriptor.ValueType, str]] = ..., - description: _Optional[str] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/launch_stage.proto b/notification-service/venv/Lib/site-packages/google/api/launch_stage.proto deleted file mode 100644 index 0fff247..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/launch_stage.proto +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api;api"; -option java_multiple_files = true; -option java_outer_classname = "LaunchStageProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// The launch stage as defined by [Google Cloud Platform -// Launch Stages](https://cloud.google.com/terms/launch-stages). -enum LaunchStage { - // Do not use this default value. - LAUNCH_STAGE_UNSPECIFIED = 0; - - // The feature is not yet implemented. Users can not use it. - UNIMPLEMENTED = 6; - - // Prelaunch features are hidden from users and are only visible internally. - PRELAUNCH = 7; - - // Early Access features are limited to a closed group of testers. To use - // these features, you must sign up in advance and sign a Trusted Tester - // agreement (which includes confidentiality provisions). These features may - // be unstable, changed in backward-incompatible ways, and are not - // guaranteed to be released. - EARLY_ACCESS = 1; - - // Alpha is a limited availability test for releases before they are cleared - // for widespread use. By Alpha, all significant design issues are resolved - // and we are in the process of verifying functionality. Alpha customers - // need to apply for access, agree to applicable terms, and have their - // projects allowlisted. Alpha releases don't have to be feature complete, - // no SLAs are provided, and there are no technical support obligations, but - // they will be far enough along that customers can actually use them in - // test environments or for limited-use tests -- just like they would in - // normal production cases. - ALPHA = 2; - - // Beta is the point at which we are ready to open a release for any - // customer to use. There are no SLA or technical support obligations in a - // Beta release. Products will be complete from a feature perspective, but - // may have some open outstanding issues. Beta releases are suitable for - // limited production use cases. - BETA = 3; - - // GA features are open to all developers and are considered stable and - // fully qualified for production use. - GA = 4; - - // Deprecated features are scheduled to be shut down and removed. For more - // information, see the "Deprecation Policy" section of our [Terms of - // Service](https://cloud.google.com/terms/) - // and the [Google Cloud Platform Subject to the Deprecation - // Policy](https://cloud.google.com/terms/deprecation) documentation. - DEPRECATED = 5; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/launch_stage_pb2.py b/notification-service/venv/Lib/site-packages/google/api/launch_stage_pb2.py deleted file mode 100644 index 72ad6f4..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/launch_stage_pb2.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/launch_stage.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b"\n\x1dgoogle/api/launch_stage.proto\x12\ngoogle.api*\x8c\x01\n\x0bLaunchStage\x12\x1c\n\x18LAUNCH_STAGE_UNSPECIFIED\x10\x00\x12\x11\n\rUNIMPLEMENTED\x10\x06\x12\r\n\tPRELAUNCH\x10\x07\x12\x10\n\x0c\x45\x41RLY_ACCESS\x10\x01\x12\t\n\x05\x41LPHA\x10\x02\x12\x08\n\x04\x42\x45TA\x10\x03\x12\x06\n\x02GA\x10\x04\x12\x0e\n\nDEPRECATED\x10\x05\x42Z\n\x0e\x63om.google.apiB\x10LaunchStageProtoP\x01Z-google.golang.org/genproto/googleapis/api;api\xa2\x02\x04GAPIb\x06proto3" -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, "google.api.launch_stage_pb2", _globals -) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\020LaunchStageProtoP\001Z-google.golang.org/genproto/googleapis/api;api\242\002\004GAPI" - _globals["_LAUNCHSTAGE"]._serialized_start = 46 - _globals["_LAUNCHSTAGE"]._serialized_end = 186 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/launch_stage_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/launch_stage_pb2.pyi deleted file mode 100644 index bdbe119..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/launch_stage_pb2.pyi +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar - -from google.protobuf import descriptor as _descriptor -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper - -DESCRIPTOR: _descriptor.FileDescriptor - -class LaunchStage(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - LAUNCH_STAGE_UNSPECIFIED: _ClassVar[LaunchStage] - UNIMPLEMENTED: _ClassVar[LaunchStage] - PRELAUNCH: _ClassVar[LaunchStage] - EARLY_ACCESS: _ClassVar[LaunchStage] - ALPHA: _ClassVar[LaunchStage] - BETA: _ClassVar[LaunchStage] - GA: _ClassVar[LaunchStage] - DEPRECATED: _ClassVar[LaunchStage] - -LAUNCH_STAGE_UNSPECIFIED: LaunchStage -UNIMPLEMENTED: LaunchStage -PRELAUNCH: LaunchStage -EARLY_ACCESS: LaunchStage -ALPHA: LaunchStage -BETA: LaunchStage -GA: LaunchStage -DEPRECATED: LaunchStage diff --git a/notification-service/venv/Lib/site-packages/google/api/log.proto b/notification-service/venv/Lib/site-packages/google/api/log.proto deleted file mode 100644 index 2f13e72..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/log.proto +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/api/label.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "LogProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// A description of a log type. Example in YAML format: -// -// - name: library.googleapis.com/activity_history -// description: The history of borrowing and returning library items. -// display_name: Activity -// labels: -// - key: /customer_id -// description: Identifier of a library customer -message LogDescriptor { - // The name of the log. It must be less than 512 characters long and can - // include the following characters: upper- and lower-case alphanumeric - // characters [A-Za-z0-9], and punctuation characters including - // slash, underscore, hyphen, period [/_-.]. - string name = 1; - - // The set of labels that are available to describe a specific log entry. - // Runtime requests that contain labels not specified here are - // considered invalid. - repeated LabelDescriptor labels = 2; - - // A human-readable description of this log. This information appears in - // the documentation and can contain details. - string description = 3; - - // The human-readable name for this log. This information appears on - // the user interface and should be concise. - string display_name = 4; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/log_pb2.py b/notification-service/venv/Lib/site-packages/google/api/log_pb2.py deleted file mode 100644 index a4c9930..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/log_pb2.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/log.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import label_pb2 as google_dot_api_dot_label__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x14google/api/log.proto\x12\ngoogle.api\x1a\x16google/api/label.proto"u\n\rLogDescriptor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12+\n\x06labels\x18\x02 \x03(\x0b\x32\x1b.google.api.LabelDescriptor\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x04 \x01(\tBj\n\x0e\x63om.google.apiB\x08LogProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.log_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\010LogProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_LOGDESCRIPTOR"]._serialized_start = 60 - _globals["_LOGDESCRIPTOR"]._serialized_end = 177 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/log_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/log_pb2.pyi deleted file mode 100644 index e177859..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/log_pb2.pyi +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -from google.api import label_pb2 as _label_pb2 - -DESCRIPTOR: _descriptor.FileDescriptor - -class LogDescriptor(_message.Message): - __slots__ = ("name", "labels", "description", "display_name") - NAME_FIELD_NUMBER: _ClassVar[int] - LABELS_FIELD_NUMBER: _ClassVar[int] - DESCRIPTION_FIELD_NUMBER: _ClassVar[int] - DISPLAY_NAME_FIELD_NUMBER: _ClassVar[int] - name: str - labels: _containers.RepeatedCompositeFieldContainer[_label_pb2.LabelDescriptor] - description: str - display_name: str - def __init__( - self, - name: _Optional[str] = ..., - labels: _Optional[ - _Iterable[_Union[_label_pb2.LabelDescriptor, _Mapping]] - ] = ..., - description: _Optional[str] = ..., - display_name: _Optional[str] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/logging.proto b/notification-service/venv/Lib/site-packages/google/api/logging.proto deleted file mode 100644 index 7a82de9..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/logging.proto +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "LoggingProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// Logging configuration of the service. -// -// The following example shows how to configure logs to be sent to the -// producer and consumer projects. In the example, the `activity_history` -// log is sent to both the producer and consumer projects, whereas the -// `purchase_history` log is only sent to the producer project. -// -// monitored_resources: -// - type: library.googleapis.com/branch -// labels: -// - key: /city -// description: The city where the library branch is located in. -// - key: /name -// description: The name of the branch. -// logs: -// - name: activity_history -// labels: -// - key: /customer_id -// - name: purchase_history -// logging: -// producer_destinations: -// - monitored_resource: library.googleapis.com/branch -// logs: -// - activity_history -// - purchase_history -// consumer_destinations: -// - monitored_resource: library.googleapis.com/branch -// logs: -// - activity_history -message Logging { - // Configuration of a specific logging destination (the producer project - // or the consumer project). - message LoggingDestination { - // The monitored resource type. The type must be defined in the - // [Service.monitored_resources][google.api.Service.monitored_resources] - // section. - string monitored_resource = 3; - - // Names of the logs to be sent to this destination. Each name must - // be defined in the [Service.logs][google.api.Service.logs] section. If the - // log name is not a domain scoped name, it will be automatically prefixed - // with the service name followed by "/". - repeated string logs = 1; - } - - // Logging configurations for sending logs to the producer project. - // There can be multiple producer destinations, each one must have a - // different monitored resource type. A log can be used in at most - // one producer destination. - repeated LoggingDestination producer_destinations = 1; - - // Logging configurations for sending logs to the consumer project. - // There can be multiple consumer destinations, each one must have a - // different monitored resource type. A log can be used in at most - // one consumer destination. - repeated LoggingDestination consumer_destinations = 2; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/logging_pb2.py b/notification-service/venv/Lib/site-packages/google/api/logging_pb2.py deleted file mode 100644 index 2360e16..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/logging_pb2.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/logging.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x18google/api/logging.proto\x12\ngoogle.api"\xd7\x01\n\x07Logging\x12\x45\n\x15producer_destinations\x18\x01 \x03(\x0b\x32&.google.api.Logging.LoggingDestination\x12\x45\n\x15\x63onsumer_destinations\x18\x02 \x03(\x0b\x32&.google.api.Logging.LoggingDestination\x1a>\n\x12LoggingDestination\x12\x1a\n\x12monitored_resource\x18\x03 \x01(\t\x12\x0c\n\x04logs\x18\x01 \x03(\tBn\n\x0e\x63om.google.apiB\x0cLoggingProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.logging_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\014LoggingProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_LOGGING"]._serialized_start = 41 - _globals["_LOGGING"]._serialized_end = 256 - _globals["_LOGGING_LOGGINGDESTINATION"]._serialized_start = 194 - _globals["_LOGGING_LOGGINGDESTINATION"]._serialized_end = 256 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/logging_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/logging_pb2.pyi deleted file mode 100644 index 97f0944..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/logging_pb2.pyi +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor - -class Logging(_message.Message): - __slots__ = ("producer_destinations", "consumer_destinations") - class LoggingDestination(_message.Message): - __slots__ = ("monitored_resource", "logs") - MONITORED_RESOURCE_FIELD_NUMBER: _ClassVar[int] - LOGS_FIELD_NUMBER: _ClassVar[int] - monitored_resource: str - logs: _containers.RepeatedScalarFieldContainer[str] - def __init__( - self, - monitored_resource: _Optional[str] = ..., - logs: _Optional[_Iterable[str]] = ..., - ) -> None: ... - - PRODUCER_DESTINATIONS_FIELD_NUMBER: _ClassVar[int] - CONSUMER_DESTINATIONS_FIELD_NUMBER: _ClassVar[int] - producer_destinations: _containers.RepeatedCompositeFieldContainer[ - Logging.LoggingDestination - ] - consumer_destinations: _containers.RepeatedCompositeFieldContainer[ - Logging.LoggingDestination - ] - def __init__( - self, - producer_destinations: _Optional[ - _Iterable[_Union[Logging.LoggingDestination, _Mapping]] - ] = ..., - consumer_destinations: _Optional[ - _Iterable[_Union[Logging.LoggingDestination, _Mapping]] - ] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/metric.proto b/notification-service/venv/Lib/site-packages/google/api/metric.proto deleted file mode 100644 index b7fb82a..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/metric.proto +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/api/label.proto"; -import "google/api/launch_stage.proto"; -import "google/protobuf/duration.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/metric;metric"; -option java_multiple_files = true; -option java_outer_classname = "MetricProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// Defines a metric type and its schema. Once a metric descriptor is created, -// deleting or altering it stops data collection and makes the metric type's -// existing data unusable. -// -message MetricDescriptor { - // The kind of measurement. It describes how the data is reported. - // For information on setting the start time and end time based on - // the MetricKind, see [TimeInterval][google.monitoring.v3.TimeInterval]. - enum MetricKind { - // Do not use this default value. - METRIC_KIND_UNSPECIFIED = 0; - - // An instantaneous measurement of a value. - GAUGE = 1; - - // The change in a value during a time interval. - DELTA = 2; - - // A value accumulated over a time interval. Cumulative - // measurements in a time series should have the same start time - // and increasing end times, until an event resets the cumulative - // value to zero and sets a new start time for the following - // points. - CUMULATIVE = 3; - } - - // The value type of a metric. - enum ValueType { - // Do not use this default value. - VALUE_TYPE_UNSPECIFIED = 0; - - // The value is a boolean. - // This value type can be used only if the metric kind is `GAUGE`. - BOOL = 1; - - // The value is a signed 64-bit integer. - INT64 = 2; - - // The value is a double precision floating point number. - DOUBLE = 3; - - // The value is a text string. - // This value type can be used only if the metric kind is `GAUGE`. - STRING = 4; - - // The value is a [`Distribution`][google.api.Distribution]. - DISTRIBUTION = 5; - - // The value is money. - MONEY = 6; - } - - // Additional annotations that can be used to guide the usage of a metric. - message MetricDescriptorMetadata { - // The resource hierarchy level of the timeseries data of a metric. - enum TimeSeriesResourceHierarchyLevel { - // Do not use this default value. - TIME_SERIES_RESOURCE_HIERARCHY_LEVEL_UNSPECIFIED = 0; - - // Scopes a metric to a project. - PROJECT = 1; - - // Scopes a metric to an organization. - ORGANIZATION = 2; - - // Scopes a metric to a folder. - FOLDER = 3; - } - - // Deprecated. Must use the - // [MetricDescriptor.launch_stage][google.api.MetricDescriptor.launch_stage] - // instead. - LaunchStage launch_stage = 1 [deprecated = true]; - - // The sampling period of metric data points. For metrics which are written - // periodically, consecutive data points are stored at this time interval, - // excluding data loss due to errors. Metrics with a higher granularity have - // a smaller sampling period. - google.protobuf.Duration sample_period = 2; - - // The delay of data points caused by ingestion. Data points older than this - // age are guaranteed to be ingested and available to be read, excluding - // data loss due to errors. - google.protobuf.Duration ingest_delay = 3; - - // The scope of the timeseries data of the metric. - repeated TimeSeriesResourceHierarchyLevel - time_series_resource_hierarchy_level = 4; - } - - // The resource name of the metric descriptor. - string name = 1; - - // The metric type, including its DNS name prefix. The type is not - // URL-encoded. All user-defined metric types have the DNS name - // `custom.googleapis.com` or `external.googleapis.com`. Metric types should - // use a natural hierarchical grouping. For example: - // - // "custom.googleapis.com/invoice/paid/amount" - // "external.googleapis.com/prometheus/up" - // "appengine.googleapis.com/http/server/response_latencies" - string type = 8; - - // The set of labels that can be used to describe a specific - // instance of this metric type. For example, the - // `appengine.googleapis.com/http/server/response_latencies` metric - // type has a label for the HTTP response code, `response_code`, so - // you can look at latencies for successful responses or just - // for responses that failed. - repeated LabelDescriptor labels = 2; - - // Whether the metric records instantaneous values, changes to a value, etc. - // Some combinations of `metric_kind` and `value_type` might not be supported. - MetricKind metric_kind = 3; - - // Whether the measurement is an integer, a floating-point number, etc. - // Some combinations of `metric_kind` and `value_type` might not be supported. - ValueType value_type = 4; - - // The units in which the metric value is reported. It is only applicable - // if the `value_type` is `INT64`, `DOUBLE`, or `DISTRIBUTION`. The `unit` - // defines the representation of the stored metric values. - // - // Different systems might scale the values to be more easily displayed (so a - // value of `0.02kBy` _might_ be displayed as `20By`, and a value of - // `3523kBy` _might_ be displayed as `3.5MBy`). However, if the `unit` is - // `kBy`, then the value of the metric is always in thousands of bytes, no - // matter how it might be displayed. - // - // If you want a custom metric to record the exact number of CPU-seconds used - // by a job, you can create an `INT64 CUMULATIVE` metric whose `unit` is - // `s{CPU}` (or equivalently `1s{CPU}` or just `s`). If the job uses 12,005 - // CPU-seconds, then the value is written as `12005`. - // - // Alternatively, if you want a custom metric to record data in a more - // granular way, you can create a `DOUBLE CUMULATIVE` metric whose `unit` is - // `ks{CPU}`, and then write the value `12.005` (which is `12005/1000`), - // or use `Kis{CPU}` and write `11.723` (which is `12005/1024`). - // - // The supported units are a subset of [The Unified Code for Units of - // Measure](https://unitsofmeasure.org/ucum.html) standard: - // - // **Basic units (UNIT)** - // - // * `bit` bit - // * `By` byte - // * `s` second - // * `min` minute - // * `h` hour - // * `d` day - // * `1` dimensionless - // - // **Prefixes (PREFIX)** - // - // * `k` kilo (10^3) - // * `M` mega (10^6) - // * `G` giga (10^9) - // * `T` tera (10^12) - // * `P` peta (10^15) - // * `E` exa (10^18) - // * `Z` zetta (10^21) - // * `Y` yotta (10^24) - // - // * `m` milli (10^-3) - // * `u` micro (10^-6) - // * `n` nano (10^-9) - // * `p` pico (10^-12) - // * `f` femto (10^-15) - // * `a` atto (10^-18) - // * `z` zepto (10^-21) - // * `y` yocto (10^-24) - // - // * `Ki` kibi (2^10) - // * `Mi` mebi (2^20) - // * `Gi` gibi (2^30) - // * `Ti` tebi (2^40) - // * `Pi` pebi (2^50) - // - // **Grammar** - // - // The grammar also includes these connectors: - // - // * `/` division or ratio (as an infix operator). For examples, - // `kBy/{email}` or `MiBy/10ms` (although you should almost never - // have `/s` in a metric `unit`; rates should always be computed at - // query time from the underlying cumulative or delta value). - // * `.` multiplication or composition (as an infix operator). For - // examples, `GBy.d` or `k{watt}.h`. - // - // The grammar for a unit is as follows: - // - // Expression = Component { "." Component } { "/" Component } ; - // - // Component = ( [ PREFIX ] UNIT | "%" ) [ Annotation ] - // | Annotation - // | "1" - // ; - // - // Annotation = "{" NAME "}" ; - // - // Notes: - // - // * `Annotation` is just a comment if it follows a `UNIT`. If the annotation - // is used alone, then the unit is equivalent to `1`. For examples, - // `{request}/s == 1/s`, `By{transmitted}/s == By/s`. - // * `NAME` is a sequence of non-blank printable ASCII characters not - // containing `{` or `}`. - // * `1` represents a unitary [dimensionless - // unit](https://en.wikipedia.org/wiki/Dimensionless_quantity) of 1, such - // as in `1/s`. It is typically used when none of the basic units are - // appropriate. For example, "new users per day" can be represented as - // `1/d` or `{new-users}/d` (and a metric value `5` would mean "5 new - // users). Alternatively, "thousands of page views per day" would be - // represented as `1000/d` or `k1/d` or `k{page_views}/d` (and a metric - // value of `5.3` would mean "5300 page views per day"). - // * `%` represents dimensionless value of 1/100, and annotates values giving - // a percentage (so the metric values are typically in the range of 0..100, - // and a metric value `3` means "3 percent"). - // * `10^2.%` indicates a metric contains a ratio, typically in the range - // 0..1, that will be multiplied by 100 and displayed as a percentage - // (so a metric value `0.03` means "3 percent"). - string unit = 5; - - // A detailed description of the metric, which can be used in documentation. - string description = 6; - - // A concise name for the metric, which can be displayed in user interfaces. - // Use sentence case without an ending period, for example "Request count". - // This field is optional but it is recommended to be set for any metrics - // associated with user-visible concepts, such as Quota. - string display_name = 7; - - // Optional. Metadata which can be used to guide usage of the metric. - MetricDescriptorMetadata metadata = 10; - - // Optional. The launch stage of the metric definition. - LaunchStage launch_stage = 12; - - // Read-only. If present, then a [time - // series][google.monitoring.v3.TimeSeries], which is identified partially by - // a metric type and a - // [MonitoredResourceDescriptor][google.api.MonitoredResourceDescriptor], that - // is associated with this metric type can only be associated with one of the - // monitored resource types listed here. - repeated string monitored_resource_types = 13; -} - -// A specific metric, identified by specifying values for all of the -// labels of a [`MetricDescriptor`][google.api.MetricDescriptor]. -message Metric { - // An existing metric type, see - // [google.api.MetricDescriptor][google.api.MetricDescriptor]. For example, - // `custom.googleapis.com/invoice/paid/amount`. - string type = 3; - - // The set of label values that uniquely identify this metric. All - // labels listed in the `MetricDescriptor` must be assigned values. - map labels = 2; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/metric_pb2.py b/notification-service/venv/Lib/site-packages/google/api/metric_pb2.py deleted file mode 100644 index 53ab18b..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/metric_pb2.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/metric.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 - -from google.api import label_pb2 as google_dot_api_dot_label__pb2 -from google.api import launch_stage_pb2 as google_dot_api_dot_launch__stage__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x17google/api/metric.proto\x12\ngoogle.api\x1a\x16google/api/label.proto\x1a\x1dgoogle/api/launch_stage.proto\x1a\x1egoogle/protobuf/duration.proto"\xac\x08\n\x10MetricDescriptor\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x08 \x01(\t\x12+\n\x06labels\x18\x02 \x03(\x0b\x32\x1b.google.api.LabelDescriptor\x12<\n\x0bmetric_kind\x18\x03 \x01(\x0e\x32\'.google.api.MetricDescriptor.MetricKind\x12:\n\nvalue_type\x18\x04 \x01(\x0e\x32&.google.api.MetricDescriptor.ValueType\x12\x0c\n\x04unit\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x07 \x01(\t\x12G\n\x08metadata\x18\n \x01(\x0b\x32\x35.google.api.MetricDescriptor.MetricDescriptorMetadata\x12-\n\x0claunch_stage\x18\x0c \x01(\x0e\x32\x17.google.api.LaunchStage\x12 \n\x18monitored_resource_types\x18\r \x03(\t\x1a\xbd\x03\n\x18MetricDescriptorMetadata\x12\x31\n\x0claunch_stage\x18\x01 \x01(\x0e\x32\x17.google.api.LaunchStageB\x02\x18\x01\x12\x30\n\rsample_period\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12/\n\x0cingest_delay\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x84\x01\n$time_series_resource_hierarchy_level\x18\x04 \x03(\x0e\x32V.google.api.MetricDescriptor.MetricDescriptorMetadata.TimeSeriesResourceHierarchyLevel"\x83\x01\n TimeSeriesResourceHierarchyLevel\x12\x34\n0TIME_SERIES_RESOURCE_HIERARCHY_LEVEL_UNSPECIFIED\x10\x00\x12\x0b\n\x07PROJECT\x10\x01\x12\x10\n\x0cORGANIZATION\x10\x02\x12\n\n\x06\x46OLDER\x10\x03"O\n\nMetricKind\x12\x1b\n\x17METRIC_KIND_UNSPECIFIED\x10\x00\x12\t\n\x05GAUGE\x10\x01\x12\t\n\x05\x44\x45LTA\x10\x02\x12\x0e\n\nCUMULATIVE\x10\x03"q\n\tValueType\x12\x1a\n\x16VALUE_TYPE_UNSPECIFIED\x10\x00\x12\x08\n\x04\x42OOL\x10\x01\x12\t\n\x05INT64\x10\x02\x12\n\n\x06\x44OUBLE\x10\x03\x12\n\n\x06STRING\x10\x04\x12\x10\n\x0c\x44ISTRIBUTION\x10\x05\x12\t\n\x05MONEY\x10\x06"u\n\x06Metric\x12\x0c\n\x04type\x18\x03 \x01(\t\x12.\n\x06labels\x18\x02 \x03(\x0b\x32\x1e.google.api.Metric.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42_\n\x0e\x63om.google.apiB\x0bMetricProtoP\x01Z7google.golang.org/genproto/googleapis/api/metric;metric\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.metric_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\013MetricProtoP\001Z7google.golang.org/genproto/googleapis/api/metric;metric\242\002\004GAPI" - _globals["_METRICDESCRIPTOR_METRICDESCRIPTORMETADATA"].fields_by_name[ - "launch_stage" - ]._options = None - _globals["_METRICDESCRIPTOR_METRICDESCRIPTORMETADATA"].fields_by_name[ - "launch_stage" - ]._serialized_options = b"\030\001" - _globals["_METRIC_LABELSENTRY"]._options = None - _globals["_METRIC_LABELSENTRY"]._serialized_options = b"8\001" - _globals["_METRICDESCRIPTOR"]._serialized_start = 127 - _globals["_METRICDESCRIPTOR"]._serialized_end = 1195 - _globals["_METRICDESCRIPTOR_METRICDESCRIPTORMETADATA"]._serialized_start = 554 - _globals["_METRICDESCRIPTOR_METRICDESCRIPTORMETADATA"]._serialized_end = 999 - _globals[ - "_METRICDESCRIPTOR_METRICDESCRIPTORMETADATA_TIMESERIESRESOURCEHIERARCHYLEVEL" - ]._serialized_start = 868 - _globals[ - "_METRICDESCRIPTOR_METRICDESCRIPTORMETADATA_TIMESERIESRESOURCEHIERARCHYLEVEL" - ]._serialized_end = 999 - _globals["_METRICDESCRIPTOR_METRICKIND"]._serialized_start = 1001 - _globals["_METRICDESCRIPTOR_METRICKIND"]._serialized_end = 1080 - _globals["_METRICDESCRIPTOR_VALUETYPE"]._serialized_start = 1082 - _globals["_METRICDESCRIPTOR_VALUETYPE"]._serialized_end = 1195 - _globals["_METRIC"]._serialized_start = 1197 - _globals["_METRIC"]._serialized_end = 1314 - _globals["_METRIC_LABELSENTRY"]._serialized_start = 1269 - _globals["_METRIC_LABELSENTRY"]._serialized_end = 1314 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/metric_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/metric_pb2.pyi deleted file mode 100644 index 2ff6b74..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/metric_pb2.pyi +++ /dev/null @@ -1,194 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import duration_pb2 as _duration_pb2 -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper - -from google.api import label_pb2 as _label_pb2 -from google.api import launch_stage_pb2 as _launch_stage_pb2 - -DESCRIPTOR: _descriptor.FileDescriptor - -class MetricDescriptor(_message.Message): - __slots__ = ( - "name", - "type", - "labels", - "metric_kind", - "value_type", - "unit", - "description", - "display_name", - "metadata", - "launch_stage", - "monitored_resource_types", - ) - class MetricKind(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - METRIC_KIND_UNSPECIFIED: _ClassVar[MetricDescriptor.MetricKind] - GAUGE: _ClassVar[MetricDescriptor.MetricKind] - DELTA: _ClassVar[MetricDescriptor.MetricKind] - CUMULATIVE: _ClassVar[MetricDescriptor.MetricKind] - - METRIC_KIND_UNSPECIFIED: MetricDescriptor.MetricKind - GAUGE: MetricDescriptor.MetricKind - DELTA: MetricDescriptor.MetricKind - CUMULATIVE: MetricDescriptor.MetricKind - class ValueType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - VALUE_TYPE_UNSPECIFIED: _ClassVar[MetricDescriptor.ValueType] - BOOL: _ClassVar[MetricDescriptor.ValueType] - INT64: _ClassVar[MetricDescriptor.ValueType] - DOUBLE: _ClassVar[MetricDescriptor.ValueType] - STRING: _ClassVar[MetricDescriptor.ValueType] - DISTRIBUTION: _ClassVar[MetricDescriptor.ValueType] - MONEY: _ClassVar[MetricDescriptor.ValueType] - - VALUE_TYPE_UNSPECIFIED: MetricDescriptor.ValueType - BOOL: MetricDescriptor.ValueType - INT64: MetricDescriptor.ValueType - DOUBLE: MetricDescriptor.ValueType - STRING: MetricDescriptor.ValueType - DISTRIBUTION: MetricDescriptor.ValueType - MONEY: MetricDescriptor.ValueType - class MetricDescriptorMetadata(_message.Message): - __slots__ = ( - "launch_stage", - "sample_period", - "ingest_delay", - "time_series_resource_hierarchy_level", - ) - class TimeSeriesResourceHierarchyLevel( - int, metaclass=_enum_type_wrapper.EnumTypeWrapper - ): - __slots__ = () - TIME_SERIES_RESOURCE_HIERARCHY_LEVEL_UNSPECIFIED: _ClassVar[ - MetricDescriptor.MetricDescriptorMetadata.TimeSeriesResourceHierarchyLevel - ] - PROJECT: _ClassVar[ - MetricDescriptor.MetricDescriptorMetadata.TimeSeriesResourceHierarchyLevel - ] - ORGANIZATION: _ClassVar[ - MetricDescriptor.MetricDescriptorMetadata.TimeSeriesResourceHierarchyLevel - ] - FOLDER: _ClassVar[ - MetricDescriptor.MetricDescriptorMetadata.TimeSeriesResourceHierarchyLevel - ] - - TIME_SERIES_RESOURCE_HIERARCHY_LEVEL_UNSPECIFIED: ( - MetricDescriptor.MetricDescriptorMetadata.TimeSeriesResourceHierarchyLevel - ) - PROJECT: ( - MetricDescriptor.MetricDescriptorMetadata.TimeSeriesResourceHierarchyLevel - ) - ORGANIZATION: ( - MetricDescriptor.MetricDescriptorMetadata.TimeSeriesResourceHierarchyLevel - ) - FOLDER: ( - MetricDescriptor.MetricDescriptorMetadata.TimeSeriesResourceHierarchyLevel - ) - LAUNCH_STAGE_FIELD_NUMBER: _ClassVar[int] - SAMPLE_PERIOD_FIELD_NUMBER: _ClassVar[int] - INGEST_DELAY_FIELD_NUMBER: _ClassVar[int] - TIME_SERIES_RESOURCE_HIERARCHY_LEVEL_FIELD_NUMBER: _ClassVar[int] - launch_stage: _launch_stage_pb2.LaunchStage - sample_period: _duration_pb2.Duration - ingest_delay: _duration_pb2.Duration - time_series_resource_hierarchy_level: _containers.RepeatedScalarFieldContainer[ - MetricDescriptor.MetricDescriptorMetadata.TimeSeriesResourceHierarchyLevel - ] - def __init__( - self, - launch_stage: _Optional[_Union[_launch_stage_pb2.LaunchStage, str]] = ..., - sample_period: _Optional[_Union[_duration_pb2.Duration, _Mapping]] = ..., - ingest_delay: _Optional[_Union[_duration_pb2.Duration, _Mapping]] = ..., - time_series_resource_hierarchy_level: _Optional[ - _Iterable[ - _Union[ - MetricDescriptor.MetricDescriptorMetadata.TimeSeriesResourceHierarchyLevel, - str, - ] - ] - ] = ..., - ) -> None: ... - - NAME_FIELD_NUMBER: _ClassVar[int] - TYPE_FIELD_NUMBER: _ClassVar[int] - LABELS_FIELD_NUMBER: _ClassVar[int] - METRIC_KIND_FIELD_NUMBER: _ClassVar[int] - VALUE_TYPE_FIELD_NUMBER: _ClassVar[int] - UNIT_FIELD_NUMBER: _ClassVar[int] - DESCRIPTION_FIELD_NUMBER: _ClassVar[int] - DISPLAY_NAME_FIELD_NUMBER: _ClassVar[int] - METADATA_FIELD_NUMBER: _ClassVar[int] - LAUNCH_STAGE_FIELD_NUMBER: _ClassVar[int] - MONITORED_RESOURCE_TYPES_FIELD_NUMBER: _ClassVar[int] - name: str - type: str - labels: _containers.RepeatedCompositeFieldContainer[_label_pb2.LabelDescriptor] - metric_kind: MetricDescriptor.MetricKind - value_type: MetricDescriptor.ValueType - unit: str - description: str - display_name: str - metadata: MetricDescriptor.MetricDescriptorMetadata - launch_stage: _launch_stage_pb2.LaunchStage - monitored_resource_types: _containers.RepeatedScalarFieldContainer[str] - def __init__( - self, - name: _Optional[str] = ..., - type: _Optional[str] = ..., - labels: _Optional[ - _Iterable[_Union[_label_pb2.LabelDescriptor, _Mapping]] - ] = ..., - metric_kind: _Optional[_Union[MetricDescriptor.MetricKind, str]] = ..., - value_type: _Optional[_Union[MetricDescriptor.ValueType, str]] = ..., - unit: _Optional[str] = ..., - description: _Optional[str] = ..., - display_name: _Optional[str] = ..., - metadata: _Optional[ - _Union[MetricDescriptor.MetricDescriptorMetadata, _Mapping] - ] = ..., - launch_stage: _Optional[_Union[_launch_stage_pb2.LaunchStage, str]] = ..., - monitored_resource_types: _Optional[_Iterable[str]] = ..., - ) -> None: ... - -class Metric(_message.Message): - __slots__ = ("type", "labels") - class LabelsEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: str - def __init__( - self, key: _Optional[str] = ..., value: _Optional[str] = ... - ) -> None: ... - - TYPE_FIELD_NUMBER: _ClassVar[int] - LABELS_FIELD_NUMBER: _ClassVar[int] - type: str - labels: _containers.ScalarMap[str, str] - def __init__( - self, type: _Optional[str] = ..., labels: _Optional[_Mapping[str, str]] = ... - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/monitored_resource.proto b/notification-service/venv/Lib/site-packages/google/api/monitored_resource.proto deleted file mode 100644 index eaf1f12..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/monitored_resource.proto +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/api/label.proto"; -import "google/api/launch_stage.proto"; -import "google/protobuf/struct.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/monitoredres;monitoredres"; -option java_multiple_files = true; -option java_outer_classname = "MonitoredResourceProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// An object that describes the schema of a -// [MonitoredResource][google.api.MonitoredResource] object using a type name -// and a set of labels. For example, the monitored resource descriptor for -// Google Compute Engine VM instances has a type of -// `"gce_instance"` and specifies the use of the labels `"instance_id"` and -// `"zone"` to identify particular VM instances. -// -// Different APIs can support different monitored resource types. APIs generally -// provide a `list` method that returns the monitored resource descriptors used -// by the API. -// -message MonitoredResourceDescriptor { - // Optional. The resource name of the monitored resource descriptor: - // `"projects/{project_id}/monitoredResourceDescriptors/{type}"` where - // {type} is the value of the `type` field in this object and - // {project_id} is a project ID that provides API-specific context for - // accessing the type. APIs that do not use project information can use the - // resource name format `"monitoredResourceDescriptors/{type}"`. - string name = 5; - - // Required. The monitored resource type. For example, the type - // `"cloudsql_database"` represents databases in Google Cloud SQL. - // For a list of types, see [Monitored resource - // types](https://cloud.google.com/monitoring/api/resources) - // and [Logging resource - // types](https://cloud.google.com/logging/docs/api/v2/resource-list). - string type = 1; - - // Optional. A concise name for the monitored resource type that might be - // displayed in user interfaces. It should be a Title Cased Noun Phrase, - // without any article or other determiners. For example, - // `"Google Cloud SQL Database"`. - string display_name = 2; - - // Optional. A detailed description of the monitored resource type that might - // be used in documentation. - string description = 3; - - // Required. A set of labels used to describe instances of this monitored - // resource type. For example, an individual Google Cloud SQL database is - // identified by values for the labels `"database_id"` and `"zone"`. - repeated LabelDescriptor labels = 4; - - // Optional. The launch stage of the monitored resource definition. - LaunchStage launch_stage = 7; -} - -// An object representing a resource that can be used for monitoring, logging, -// billing, or other purposes. Examples include virtual machine instances, -// databases, and storage devices such as disks. The `type` field identifies a -// [MonitoredResourceDescriptor][google.api.MonitoredResourceDescriptor] object -// that describes the resource's schema. Information in the `labels` field -// identifies the actual resource and its attributes according to the schema. -// For example, a particular Compute Engine VM instance could be represented by -// the following object, because the -// [MonitoredResourceDescriptor][google.api.MonitoredResourceDescriptor] for -// `"gce_instance"` has labels -// `"project_id"`, `"instance_id"` and `"zone"`: -// -// { "type": "gce_instance", -// "labels": { "project_id": "my-project", -// "instance_id": "12345678901234", -// "zone": "us-central1-a" }} -message MonitoredResource { - // Required. The monitored resource type. This field must match - // the `type` field of a - // [MonitoredResourceDescriptor][google.api.MonitoredResourceDescriptor] - // object. For example, the type of a Compute Engine VM instance is - // `gce_instance`. Some descriptors include the service name in the type; for - // example, the type of a Datastream stream is - // `datastream.googleapis.com/Stream`. - string type = 1; - - // Required. Values for all of the labels listed in the associated monitored - // resource descriptor. For example, Compute Engine VM instances use the - // labels `"project_id"`, `"instance_id"`, and `"zone"`. - map labels = 2; -} - -// Auxiliary metadata for a [MonitoredResource][google.api.MonitoredResource] -// object. [MonitoredResource][google.api.MonitoredResource] objects contain the -// minimum set of information to uniquely identify a monitored resource -// instance. There is some other useful auxiliary metadata. Monitoring and -// Logging use an ingestion pipeline to extract metadata for cloud resources of -// all types, and store the metadata in this message. -message MonitoredResourceMetadata { - // Output only. Values for predefined system metadata labels. - // System labels are a kind of metadata extracted by Google, including - // "machine_image", "vpc", "subnet_id", - // "security_group", "name", etc. - // System label values can be only strings, Boolean values, or a list of - // strings. For example: - // - // { "name": "my-test-instance", - // "security_group": ["a", "b", "c"], - // "spot_instance": false } - google.protobuf.Struct system_labels = 1; - - // Output only. A map of user-defined metadata labels. - map user_labels = 2; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/monitored_resource_pb2.py b/notification-service/venv/Lib/site-packages/google/api/monitored_resource_pb2.py deleted file mode 100644 index 51cc782..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/monitored_resource_pb2.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/monitored_resource.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 - -from google.api import label_pb2 as google_dot_api_dot_label__pb2 -from google.api import launch_stage_pb2 as google_dot_api_dot_launch__stage__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n#google/api/monitored_resource.proto\x12\ngoogle.api\x1a\x16google/api/label.proto\x1a\x1dgoogle/api/launch_stage.proto\x1a\x1cgoogle/protobuf/struct.proto"\xc0\x01\n\x1bMonitoredResourceDescriptor\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12+\n\x06labels\x18\x04 \x03(\x0b\x32\x1b.google.api.LabelDescriptor\x12-\n\x0claunch_stage\x18\x07 \x01(\x0e\x32\x17.google.api.LaunchStage"\x8b\x01\n\x11MonitoredResource\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x39\n\x06labels\x18\x02 \x03(\x0b\x32).google.api.MonitoredResource.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xca\x01\n\x19MonitoredResourceMetadata\x12.\n\rsystem_labels\x18\x01 \x01(\x0b\x32\x17.google.protobuf.Struct\x12J\n\x0buser_labels\x18\x02 \x03(\x0b\x32\x35.google.api.MonitoredResourceMetadata.UserLabelsEntry\x1a\x31\n\x0fUserLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42v\n\x0e\x63om.google.apiB\x16MonitoredResourceProtoP\x01ZCgoogle.golang.org/genproto/googleapis/api/monitoredres;monitoredres\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, "google.api.monitored_resource_pb2", _globals -) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\026MonitoredResourceProtoP\001ZCgoogle.golang.org/genproto/googleapis/api/monitoredres;monitoredres\242\002\004GAPI" - _globals["_MONITOREDRESOURCE_LABELSENTRY"]._options = None - _globals["_MONITOREDRESOURCE_LABELSENTRY"]._serialized_options = b"8\001" - _globals["_MONITOREDRESOURCEMETADATA_USERLABELSENTRY"]._options = None - _globals[ - "_MONITOREDRESOURCEMETADATA_USERLABELSENTRY" - ]._serialized_options = b"8\001" - _globals["_MONITOREDRESOURCEDESCRIPTOR"]._serialized_start = 137 - _globals["_MONITOREDRESOURCEDESCRIPTOR"]._serialized_end = 329 - _globals["_MONITOREDRESOURCE"]._serialized_start = 332 - _globals["_MONITOREDRESOURCE"]._serialized_end = 471 - _globals["_MONITOREDRESOURCE_LABELSENTRY"]._serialized_start = 426 - _globals["_MONITOREDRESOURCE_LABELSENTRY"]._serialized_end = 471 - _globals["_MONITOREDRESOURCEMETADATA"]._serialized_start = 474 - _globals["_MONITOREDRESOURCEMETADATA"]._serialized_end = 676 - _globals["_MONITOREDRESOURCEMETADATA_USERLABELSENTRY"]._serialized_start = 627 - _globals["_MONITOREDRESOURCEMETADATA_USERLABELSENTRY"]._serialized_end = 676 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/monitored_resource_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/monitored_resource_pb2.pyi deleted file mode 100644 index 17b13e5..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/monitored_resource_pb2.pyi +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import struct_pb2 as _struct_pb2 -from google.protobuf.internal import containers as _containers - -from google.api import label_pb2 as _label_pb2 -from google.api import launch_stage_pb2 as _launch_stage_pb2 - -DESCRIPTOR: _descriptor.FileDescriptor - -class MonitoredResourceDescriptor(_message.Message): - __slots__ = ( - "name", - "type", - "display_name", - "description", - "labels", - "launch_stage", - ) - NAME_FIELD_NUMBER: _ClassVar[int] - TYPE_FIELD_NUMBER: _ClassVar[int] - DISPLAY_NAME_FIELD_NUMBER: _ClassVar[int] - DESCRIPTION_FIELD_NUMBER: _ClassVar[int] - LABELS_FIELD_NUMBER: _ClassVar[int] - LAUNCH_STAGE_FIELD_NUMBER: _ClassVar[int] - name: str - type: str - display_name: str - description: str - labels: _containers.RepeatedCompositeFieldContainer[_label_pb2.LabelDescriptor] - launch_stage: _launch_stage_pb2.LaunchStage - def __init__( - self, - name: _Optional[str] = ..., - type: _Optional[str] = ..., - display_name: _Optional[str] = ..., - description: _Optional[str] = ..., - labels: _Optional[ - _Iterable[_Union[_label_pb2.LabelDescriptor, _Mapping]] - ] = ..., - launch_stage: _Optional[_Union[_launch_stage_pb2.LaunchStage, str]] = ..., - ) -> None: ... - -class MonitoredResource(_message.Message): - __slots__ = ("type", "labels") - class LabelsEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: str - def __init__( - self, key: _Optional[str] = ..., value: _Optional[str] = ... - ) -> None: ... - - TYPE_FIELD_NUMBER: _ClassVar[int] - LABELS_FIELD_NUMBER: _ClassVar[int] - type: str - labels: _containers.ScalarMap[str, str] - def __init__( - self, type: _Optional[str] = ..., labels: _Optional[_Mapping[str, str]] = ... - ) -> None: ... - -class MonitoredResourceMetadata(_message.Message): - __slots__ = ("system_labels", "user_labels") - class UserLabelsEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: str - def __init__( - self, key: _Optional[str] = ..., value: _Optional[str] = ... - ) -> None: ... - - SYSTEM_LABELS_FIELD_NUMBER: _ClassVar[int] - USER_LABELS_FIELD_NUMBER: _ClassVar[int] - system_labels: _struct_pb2.Struct - user_labels: _containers.ScalarMap[str, str] - def __init__( - self, - system_labels: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., - user_labels: _Optional[_Mapping[str, str]] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/monitoring.proto b/notification-service/venv/Lib/site-packages/google/api/monitoring.proto deleted file mode 100644 index b939a0c..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/monitoring.proto +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "MonitoringProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// Monitoring configuration of the service. -// -// The example below shows how to configure monitored resources and metrics -// for monitoring. In the example, a monitored resource and two metrics are -// defined. The `library.googleapis.com/book/returned_count` metric is sent -// to both producer and consumer projects, whereas the -// `library.googleapis.com/book/num_overdue` metric is only sent to the -// consumer project. -// -// monitored_resources: -// - type: library.googleapis.com/Branch -// display_name: "Library Branch" -// description: "A branch of a library." -// launch_stage: GA -// labels: -// - key: resource_container -// description: "The Cloud container (ie. project id) for the Branch." -// - key: location -// description: "The location of the library branch." -// - key: branch_id -// description: "The id of the branch." -// metrics: -// - name: library.googleapis.com/book/returned_count -// display_name: "Books Returned" -// description: "The count of books that have been returned." -// launch_stage: GA -// metric_kind: DELTA -// value_type: INT64 -// unit: "1" -// labels: -// - key: customer_id -// description: "The id of the customer." -// - name: library.googleapis.com/book/num_overdue -// display_name: "Books Overdue" -// description: "The current number of overdue books." -// launch_stage: GA -// metric_kind: GAUGE -// value_type: INT64 -// unit: "1" -// labels: -// - key: customer_id -// description: "The id of the customer." -// monitoring: -// producer_destinations: -// - monitored_resource: library.googleapis.com/Branch -// metrics: -// - library.googleapis.com/book/returned_count -// consumer_destinations: -// - monitored_resource: library.googleapis.com/Branch -// metrics: -// - library.googleapis.com/book/returned_count -// - library.googleapis.com/book/num_overdue -message Monitoring { - // Configuration of a specific monitoring destination (the producer project - // or the consumer project). - message MonitoringDestination { - // The monitored resource type. The type must be defined in - // [Service.monitored_resources][google.api.Service.monitored_resources] - // section. - string monitored_resource = 1; - - // Types of the metrics to report to this monitoring destination. - // Each type must be defined in - // [Service.metrics][google.api.Service.metrics] section. - repeated string metrics = 2; - } - - // Monitoring configurations for sending metrics to the producer project. - // There can be multiple producer destinations. A monitored resource type may - // appear in multiple monitoring destinations if different aggregations are - // needed for different sets of metrics associated with that monitored - // resource type. A monitored resource and metric pair may only be used once - // in the Monitoring configuration. - repeated MonitoringDestination producer_destinations = 1; - - // Monitoring configurations for sending metrics to the consumer project. - // There can be multiple consumer destinations. A monitored resource type may - // appear in multiple monitoring destinations if different aggregations are - // needed for different sets of metrics associated with that monitored - // resource type. A monitored resource and metric pair may only be used once - // in the Monitoring configuration. - repeated MonitoringDestination consumer_destinations = 2; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/monitoring_pb2.py b/notification-service/venv/Lib/site-packages/google/api/monitoring_pb2.py deleted file mode 100644 index d2fc328..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/monitoring_pb2.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/monitoring.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x1bgoogle/api/monitoring.proto\x12\ngoogle.api"\xec\x01\n\nMonitoring\x12K\n\x15producer_destinations\x18\x01 \x03(\x0b\x32,.google.api.Monitoring.MonitoringDestination\x12K\n\x15\x63onsumer_destinations\x18\x02 \x03(\x0b\x32,.google.api.Monitoring.MonitoringDestination\x1a\x44\n\x15MonitoringDestination\x12\x1a\n\x12monitored_resource\x18\x01 \x01(\t\x12\x0f\n\x07metrics\x18\x02 \x03(\tBq\n\x0e\x63om.google.apiB\x0fMonitoringProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, "google.api.monitoring_pb2", _globals -) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\017MonitoringProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_MONITORING"]._serialized_start = 44 - _globals["_MONITORING"]._serialized_end = 280 - _globals["_MONITORING_MONITORINGDESTINATION"]._serialized_start = 212 - _globals["_MONITORING_MONITORINGDESTINATION"]._serialized_end = 280 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/monitoring_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/monitoring_pb2.pyi deleted file mode 100644 index 6638ea8..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/monitoring_pb2.pyi +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor - -class Monitoring(_message.Message): - __slots__ = ("producer_destinations", "consumer_destinations") - class MonitoringDestination(_message.Message): - __slots__ = ("monitored_resource", "metrics") - MONITORED_RESOURCE_FIELD_NUMBER: _ClassVar[int] - METRICS_FIELD_NUMBER: _ClassVar[int] - monitored_resource: str - metrics: _containers.RepeatedScalarFieldContainer[str] - def __init__( - self, - monitored_resource: _Optional[str] = ..., - metrics: _Optional[_Iterable[str]] = ..., - ) -> None: ... - - PRODUCER_DESTINATIONS_FIELD_NUMBER: _ClassVar[int] - CONSUMER_DESTINATIONS_FIELD_NUMBER: _ClassVar[int] - producer_destinations: _containers.RepeatedCompositeFieldContainer[ - Monitoring.MonitoringDestination - ] - consumer_destinations: _containers.RepeatedCompositeFieldContainer[ - Monitoring.MonitoringDestination - ] - def __init__( - self, - producer_destinations: _Optional[ - _Iterable[_Union[Monitoring.MonitoringDestination, _Mapping]] - ] = ..., - consumer_destinations: _Optional[ - _Iterable[_Union[Monitoring.MonitoringDestination, _Mapping]] - ] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/policy.proto b/notification-service/venv/Lib/site-packages/google/api/policy.proto deleted file mode 100644 index c925fdc..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/policy.proto +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/protobuf/descriptor.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "PolicyProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -extend google.protobuf.FieldOptions { - // See [FieldPolicy][]. - google.api.FieldPolicy field_policy = 158361448; -} - -extend google.protobuf.MethodOptions { - // See [MethodPolicy][]. - google.api.MethodPolicy method_policy = 161893301; -} - -// Google API Policy Annotation -// -// This message defines a simple API policy annotation that can be used to -// annotate API request and response message fields with applicable policies. -// One field may have multiple applicable policies that must all be satisfied -// before a request can be processed. This policy annotation is used to -// generate the overall policy that will be used for automatic runtime -// policy enforcement and documentation generation. -message FieldPolicy { - // Selects one or more request or response message fields to apply this - // `FieldPolicy`. - // - // When a `FieldPolicy` is used in proto annotation, the selector must - // be left as empty. The service config generator will automatically fill - // the correct value. - // - // When a `FieldPolicy` is used in service config, the selector must be a - // comma-separated string with valid request or response field paths, - // such as "foo.bar" or "foo.bar,foo.baz". - string selector = 1; - - // Specifies the required permission(s) for the resource referred to by the - // field. It requires the field contains a valid resource reference, and - // the request must pass the permission checks to proceed. For example, - // "resourcemanager.projects.get". - string resource_permission = 2; - - // Specifies the resource type for the resource referred to by the field. - string resource_type = 3; -} - -// Defines policies applying to an RPC method. -message MethodPolicy { - // Selects a method to which these policies should be enforced, for example, - // "google.pubsub.v1.Subscriber.CreateSubscription". - // - // Refer to [selector][google.api.DocumentationRule.selector] for syntax - // details. - // - // NOTE: This field must not be set in the proto annotation. It will be - // automatically filled by the service config compiler . - string selector = 9; - - // Policies that are applicable to the request message. - repeated FieldPolicy request_policies = 2; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/policy_pb2.py b/notification-service/venv/Lib/site-packages/google/api/policy_pb2.py deleted file mode 100644 index f3721a8..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/policy_pb2.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/policy.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x17google/api/policy.proto\x12\ngoogle.api\x1a google/protobuf/descriptor.proto"S\n\x0b\x46ieldPolicy\x12\x10\n\x08selector\x18\x01 \x01(\t\x12\x1b\n\x13resource_permission\x18\x02 \x01(\t\x12\x15\n\rresource_type\x18\x03 \x01(\t"S\n\x0cMethodPolicy\x12\x10\n\x08selector\x18\t \x01(\t\x12\x31\n\x10request_policies\x18\x02 \x03(\x0b\x32\x17.google.api.FieldPolicy:O\n\x0c\x66ield_policy\x12\x1d.google.protobuf.FieldOptions\x18\xe8\xce\xc1K \x01(\x0b\x32\x17.google.api.FieldPolicy:R\n\rmethod_policy\x12\x1e.google.protobuf.MethodOptions\x18\xb5\x97\x99M \x01(\x0b\x32\x18.google.api.MethodPolicyBm\n\x0e\x63om.google.apiB\x0bPolicyProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.policy_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\013PolicyProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_FIELDPOLICY"]._serialized_start = 73 - _globals["_FIELDPOLICY"]._serialized_end = 156 - _globals["_METHODPOLICY"]._serialized_start = 158 - _globals["_METHODPOLICY"]._serialized_end = 241 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/policy_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/policy_pb2.pyi deleted file mode 100644 index 2a099f3..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/policy_pb2.pyi +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pb2 as _descriptor_pb2 -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor -FIELD_POLICY_FIELD_NUMBER: _ClassVar[int] -field_policy: _descriptor.FieldDescriptor -METHOD_POLICY_FIELD_NUMBER: _ClassVar[int] -method_policy: _descriptor.FieldDescriptor - -class FieldPolicy(_message.Message): - __slots__ = ("selector", "resource_permission", "resource_type") - SELECTOR_FIELD_NUMBER: _ClassVar[int] - RESOURCE_PERMISSION_FIELD_NUMBER: _ClassVar[int] - RESOURCE_TYPE_FIELD_NUMBER: _ClassVar[int] - selector: str - resource_permission: str - resource_type: str - def __init__( - self, - selector: _Optional[str] = ..., - resource_permission: _Optional[str] = ..., - resource_type: _Optional[str] = ..., - ) -> None: ... - -class MethodPolicy(_message.Message): - __slots__ = ("selector", "request_policies") - SELECTOR_FIELD_NUMBER: _ClassVar[int] - REQUEST_POLICIES_FIELD_NUMBER: _ClassVar[int] - selector: str - request_policies: _containers.RepeatedCompositeFieldContainer[FieldPolicy] - def __init__( - self, - selector: _Optional[str] = ..., - request_policies: _Optional[_Iterable[_Union[FieldPolicy, _Mapping]]] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/quota.proto b/notification-service/venv/Lib/site-packages/google/api/quota.proto deleted file mode 100644 index 29ae86e..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/quota.proto +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "QuotaProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// Quota configuration helps to achieve fairness and budgeting in service -// usage. -// -// The metric based quota configuration works this way: -// - The service configuration defines a set of metrics. -// - For API calls, the quota.metric_rules maps methods to metrics with -// corresponding costs. -// - The quota.limits defines limits on the metrics, which will be used for -// quota checks at runtime. -// -// An example quota configuration in yaml format: -// -// quota: -// limits: -// -// - name: apiWriteQpsPerProject -// metric: library.googleapis.com/write_calls -// unit: "1/min/{project}" # rate limit for consumer projects -// values: -// STANDARD: 10000 -// -// -// (The metric rules bind all methods to the read_calls metric, -// except for the UpdateBook and DeleteBook methods. These two methods -// are mapped to the write_calls metric, with the UpdateBook method -// consuming at twice rate as the DeleteBook method.) -// metric_rules: -// - selector: "*" -// metric_costs: -// library.googleapis.com/read_calls: 1 -// - selector: google.example.library.v1.LibraryService.UpdateBook -// metric_costs: -// library.googleapis.com/write_calls: 2 -// - selector: google.example.library.v1.LibraryService.DeleteBook -// metric_costs: -// library.googleapis.com/write_calls: 1 -// -// Corresponding Metric definition: -// -// metrics: -// - name: library.googleapis.com/read_calls -// display_name: Read requests -// metric_kind: DELTA -// value_type: INT64 -// -// - name: library.googleapis.com/write_calls -// display_name: Write requests -// metric_kind: DELTA -// value_type: INT64 -// -// -message Quota { - // List of QuotaLimit definitions for the service. - repeated QuotaLimit limits = 3; - - // List of MetricRule definitions, each one mapping a selected method to one - // or more metrics. - repeated MetricRule metric_rules = 4; -} - -// Bind API methods to metrics. Binding a method to a metric causes that -// metric's configured quota behaviors to apply to the method call. -message MetricRule { - // Selects the methods to which this rule applies. - // - // Refer to [selector][google.api.DocumentationRule.selector] for syntax - // details. - string selector = 1; - - // Metrics to update when the selected methods are called, and the associated - // cost applied to each metric. - // - // The key of the map is the metric name, and the values are the amount - // increased for the metric against which the quota limits are defined. - // The value must not be negative. - map metric_costs = 2; -} - -// `QuotaLimit` defines a specific limit that applies over a specified duration -// for a limit type. There can be at most one limit for a duration and limit -// type combination defined within a `QuotaGroup`. -message QuotaLimit { - // Name of the quota limit. - // - // The name must be provided, and it must be unique within the service. The - // name can only include alphanumeric characters as well as '-'. - // - // The maximum length of the limit name is 64 characters. - string name = 6; - - // Optional. User-visible, extended description for this quota limit. - // Should be used only when more context is needed to understand this limit - // than provided by the limit's display name (see: `display_name`). - string description = 2; - - // Default number of tokens that can be consumed during the specified - // duration. This is the number of tokens assigned when a client - // application developer activates the service for his/her project. - // - // Specifying a value of 0 will block all requests. This can be used if you - // are provisioning quota to selected consumers and blocking others. - // Similarly, a value of -1 will indicate an unlimited quota. No other - // negative values are allowed. - // - // Used by group-based quotas only. - int64 default_limit = 3; - - // Maximum number of tokens that can be consumed during the specified - // duration. Client application developers can override the default limit up - // to this maximum. If specified, this value cannot be set to a value less - // than the default limit. If not specified, it is set to the default limit. - // - // To allow clients to apply overrides with no upper bound, set this to -1, - // indicating unlimited maximum quota. - // - // Used by group-based quotas only. - int64 max_limit = 4; - - // Free tier value displayed in the Developers Console for this limit. - // The free tier is the number of tokens that will be subtracted from the - // billed amount when billing is enabled. - // This field can only be set on a limit with duration "1d", in a billable - // group; it is invalid on any other limit. If this field is not set, it - // defaults to 0, indicating that there is no free tier for this service. - // - // Used by group-based quotas only. - int64 free_tier = 7; - - // Duration of this limit in textual notation. Must be "100s" or "1d". - // - // Used by group-based quotas only. - string duration = 5; - - // The name of the metric this quota limit applies to. The quota limits with - // the same metric will be checked together during runtime. The metric must be - // defined within the service config. - string metric = 8; - - // Specify the unit of the quota limit. It uses the same syntax as - // [MetricDescriptor.unit][google.api.MetricDescriptor.unit]. The supported - // unit kinds are determined by the quota backend system. - // - // Here are some examples: - // * "1/min/{project}" for quota per minute per project. - // - // Note: the order of unit components is insignificant. - // The "1" at the beginning is required to follow the metric unit syntax. - string unit = 9; - - // Tiered limit values. You must specify this as a key:value pair, with an - // integer value that is the maximum number of requests allowed for the - // specified unit. Currently only STANDARD is supported. - map values = 10; - - // User-visible display name for this limit. - // Optional. If not set, the UI will provide a default display name based on - // the quota configuration. This field can be used to override the default - // display name generated from the configuration. - string display_name = 12; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/quota_pb2.py b/notification-service/venv/Lib/site-packages/google/api/quota_pb2.py deleted file mode 100644 index 1ce1bc0..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/quota_pb2.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/quota.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x16google/api/quota.proto\x12\ngoogle.api"]\n\x05Quota\x12&\n\x06limits\x18\x03 \x03(\x0b\x32\x16.google.api.QuotaLimit\x12,\n\x0cmetric_rules\x18\x04 \x03(\x0b\x32\x16.google.api.MetricRule"\x91\x01\n\nMetricRule\x12\x10\n\x08selector\x18\x01 \x01(\t\x12=\n\x0cmetric_costs\x18\x02 \x03(\x0b\x32\'.google.api.MetricRule.MetricCostsEntry\x1a\x32\n\x10MetricCostsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x03:\x02\x38\x01"\x95\x02\n\nQuotaLimit\x12\x0c\n\x04name\x18\x06 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x15\n\rdefault_limit\x18\x03 \x01(\x03\x12\x11\n\tmax_limit\x18\x04 \x01(\x03\x12\x11\n\tfree_tier\x18\x07 \x01(\x03\x12\x10\n\x08\x64uration\x18\x05 \x01(\t\x12\x0e\n\x06metric\x18\x08 \x01(\t\x12\x0c\n\x04unit\x18\t \x01(\t\x12\x32\n\x06values\x18\n \x03(\x0b\x32".google.api.QuotaLimit.ValuesEntry\x12\x14\n\x0c\x64isplay_name\x18\x0c \x01(\t\x1a-\n\x0bValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x03:\x02\x38\x01\x42l\n\x0e\x63om.google.apiB\nQuotaProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.quota_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\nQuotaProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_METRICRULE_METRICCOSTSENTRY"]._options = None - _globals["_METRICRULE_METRICCOSTSENTRY"]._serialized_options = b"8\001" - _globals["_QUOTALIMIT_VALUESENTRY"]._options = None - _globals["_QUOTALIMIT_VALUESENTRY"]._serialized_options = b"8\001" - _globals["_QUOTA"]._serialized_start = 38 - _globals["_QUOTA"]._serialized_end = 131 - _globals["_METRICRULE"]._serialized_start = 134 - _globals["_METRICRULE"]._serialized_end = 279 - _globals["_METRICRULE_METRICCOSTSENTRY"]._serialized_start = 229 - _globals["_METRICRULE_METRICCOSTSENTRY"]._serialized_end = 279 - _globals["_QUOTALIMIT"]._serialized_start = 282 - _globals["_QUOTALIMIT"]._serialized_end = 559 - _globals["_QUOTALIMIT_VALUESENTRY"]._serialized_start = 514 - _globals["_QUOTALIMIT_VALUESENTRY"]._serialized_end = 559 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/quota_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/quota_pb2.pyi deleted file mode 100644 index 3e7f0ee..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/quota_pb2.pyi +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor - -class Quota(_message.Message): - __slots__ = ("limits", "metric_rules") - LIMITS_FIELD_NUMBER: _ClassVar[int] - METRIC_RULES_FIELD_NUMBER: _ClassVar[int] - limits: _containers.RepeatedCompositeFieldContainer[QuotaLimit] - metric_rules: _containers.RepeatedCompositeFieldContainer[MetricRule] - def __init__( - self, - limits: _Optional[_Iterable[_Union[QuotaLimit, _Mapping]]] = ..., - metric_rules: _Optional[_Iterable[_Union[MetricRule, _Mapping]]] = ..., - ) -> None: ... - -class MetricRule(_message.Message): - __slots__ = ("selector", "metric_costs") - class MetricCostsEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: int - def __init__( - self, key: _Optional[str] = ..., value: _Optional[int] = ... - ) -> None: ... - - SELECTOR_FIELD_NUMBER: _ClassVar[int] - METRIC_COSTS_FIELD_NUMBER: _ClassVar[int] - selector: str - metric_costs: _containers.ScalarMap[str, int] - def __init__( - self, - selector: _Optional[str] = ..., - metric_costs: _Optional[_Mapping[str, int]] = ..., - ) -> None: ... - -class QuotaLimit(_message.Message): - __slots__ = ( - "name", - "description", - "default_limit", - "max_limit", - "free_tier", - "duration", - "metric", - "unit", - "values", - "display_name", - ) - class ValuesEntry(_message.Message): - __slots__ = ("key", "value") - KEY_FIELD_NUMBER: _ClassVar[int] - VALUE_FIELD_NUMBER: _ClassVar[int] - key: str - value: int - def __init__( - self, key: _Optional[str] = ..., value: _Optional[int] = ... - ) -> None: ... - - NAME_FIELD_NUMBER: _ClassVar[int] - DESCRIPTION_FIELD_NUMBER: _ClassVar[int] - DEFAULT_LIMIT_FIELD_NUMBER: _ClassVar[int] - MAX_LIMIT_FIELD_NUMBER: _ClassVar[int] - FREE_TIER_FIELD_NUMBER: _ClassVar[int] - DURATION_FIELD_NUMBER: _ClassVar[int] - METRIC_FIELD_NUMBER: _ClassVar[int] - UNIT_FIELD_NUMBER: _ClassVar[int] - VALUES_FIELD_NUMBER: _ClassVar[int] - DISPLAY_NAME_FIELD_NUMBER: _ClassVar[int] - name: str - description: str - default_limit: int - max_limit: int - free_tier: int - duration: str - metric: str - unit: str - values: _containers.ScalarMap[str, int] - display_name: str - def __init__( - self, - name: _Optional[str] = ..., - description: _Optional[str] = ..., - default_limit: _Optional[int] = ..., - max_limit: _Optional[int] = ..., - free_tier: _Optional[int] = ..., - duration: _Optional[str] = ..., - metric: _Optional[str] = ..., - unit: _Optional[str] = ..., - values: _Optional[_Mapping[str, int]] = ..., - display_name: _Optional[str] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/resource.proto b/notification-service/venv/Lib/site-packages/google/api/resource.proto deleted file mode 100644 index 2a5213b..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/resource.proto +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/protobuf/descriptor.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; -option java_multiple_files = true; -option java_outer_classname = "ResourceProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -extend google.protobuf.FieldOptions { - // An annotation that describes a resource reference, see - // [ResourceReference][]. - google.api.ResourceReference resource_reference = 1055; -} - -extend google.protobuf.FileOptions { - // An annotation that describes a resource definition without a corresponding - // message; see [ResourceDescriptor][]. - repeated google.api.ResourceDescriptor resource_definition = 1053; -} - -extend google.protobuf.MessageOptions { - // An annotation that describes a resource definition, see - // [ResourceDescriptor][]. - google.api.ResourceDescriptor resource = 1053; -} - -// A simple descriptor of a resource type. -// -// ResourceDescriptor annotates a resource message (either by means of a -// protobuf annotation or use in the service config), and associates the -// resource's schema, the resource type, and the pattern of the resource name. -// -// Example: -// -// message Topic { -// // Indicates this message defines a resource schema. -// // Declares the resource type in the format of {service}/{kind}. -// // For Kubernetes resources, the format is {api group}/{kind}. -// option (google.api.resource) = { -// type: "pubsub.googleapis.com/Topic" -// pattern: "projects/{project}/topics/{topic}" -// }; -// } -// -// The ResourceDescriptor Yaml config will look like: -// -// resources: -// - type: "pubsub.googleapis.com/Topic" -// pattern: "projects/{project}/topics/{topic}" -// -// Sometimes, resources have multiple patterns, typically because they can -// live under multiple parents. -// -// Example: -// -// message LogEntry { -// option (google.api.resource) = { -// type: "logging.googleapis.com/LogEntry" -// pattern: "projects/{project}/logs/{log}" -// pattern: "folders/{folder}/logs/{log}" -// pattern: "organizations/{organization}/logs/{log}" -// pattern: "billingAccounts/{billing_account}/logs/{log}" -// }; -// } -// -// The ResourceDescriptor Yaml config will look like: -// -// resources: -// - type: 'logging.googleapis.com/LogEntry' -// pattern: "projects/{project}/logs/{log}" -// pattern: "folders/{folder}/logs/{log}" -// pattern: "organizations/{organization}/logs/{log}" -// pattern: "billingAccounts/{billing_account}/logs/{log}" -message ResourceDescriptor { - // A description of the historical or future-looking state of the - // resource pattern. - enum History { - // The "unset" value. - HISTORY_UNSPECIFIED = 0; - - // The resource originally had one pattern and launched as such, and - // additional patterns were added later. - ORIGINALLY_SINGLE_PATTERN = 1; - - // The resource has one pattern, but the API owner expects to add more - // later. (This is the inverse of ORIGINALLY_SINGLE_PATTERN, and prevents - // that from being necessary once there are multiple patterns.) - FUTURE_MULTI_PATTERN = 2; - } - - // A flag representing a specific style that a resource claims to conform to. - enum Style { - // The unspecified value. Do not use. - STYLE_UNSPECIFIED = 0; - - // This resource is intended to be "declarative-friendly". - // - // Declarative-friendly resources must be more strictly consistent, and - // setting this to true communicates to tools that this resource should - // adhere to declarative-friendly expectations. - // - // Note: This is used by the API linter (linter.aip.dev) to enable - // additional checks. - DECLARATIVE_FRIENDLY = 1; - } - - // The resource type. It must be in the format of - // {service_name}/{resource_type_kind}. The `resource_type_kind` must be - // singular and must not include version numbers. - // - // Example: `storage.googleapis.com/Bucket` - // - // The value of the resource_type_kind must follow the regular expression - // /[A-Za-z][a-zA-Z0-9]+/. It should start with an upper case character and - // should use PascalCase (UpperCamelCase). The maximum number of - // characters allowed for the `resource_type_kind` is 100. - string type = 1; - - // Optional. The relative resource name pattern associated with this resource - // type. The DNS prefix of the full resource name shouldn't be specified here. - // - // The path pattern must follow the syntax, which aligns with HTTP binding - // syntax: - // - // Template = Segment { "/" Segment } ; - // Segment = LITERAL | Variable ; - // Variable = "{" LITERAL "}" ; - // - // Examples: - // - // - "projects/{project}/topics/{topic}" - // - "projects/{project}/knowledgeBases/{knowledge_base}" - // - // The components in braces correspond to the IDs for each resource in the - // hierarchy. It is expected that, if multiple patterns are provided, - // the same component name (e.g. "project") refers to IDs of the same - // type of resource. - repeated string pattern = 2; - - // Optional. The field on the resource that designates the resource name - // field. If omitted, this is assumed to be "name". - string name_field = 3; - - // Optional. The historical or future-looking state of the resource pattern. - // - // Example: - // - // // The InspectTemplate message originally only supported resource - // // names with organization, and project was added later. - // message InspectTemplate { - // option (google.api.resource) = { - // type: "dlp.googleapis.com/InspectTemplate" - // pattern: - // "organizations/{organization}/inspectTemplates/{inspect_template}" - // pattern: "projects/{project}/inspectTemplates/{inspect_template}" - // history: ORIGINALLY_SINGLE_PATTERN - // }; - // } - History history = 4; - - // The plural name used in the resource name and permission names, such as - // 'projects' for the resource name of 'projects/{project}' and the permission - // name of 'cloudresourcemanager.googleapis.com/projects.get'. One exception - // to this is for Nested Collections that have stuttering names, as defined - // in [AIP-122](https://google.aip.dev/122#nested-collections), where the - // collection ID in the resource name pattern does not necessarily directly - // match the `plural` value. - // - // It is the same concept of the `plural` field in k8s CRD spec - // https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ - // - // Note: The plural form is required even for singleton resources. See - // https://aip.dev/156 - string plural = 5; - - // The same concept of the `singular` field in k8s CRD spec - // https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ - // Such as "project" for the `resourcemanager.googleapis.com/Project` type. - string singular = 6; - - // Style flag(s) for this resource. - // These indicate that a resource is expected to conform to a given - // style. See the specific style flags for additional information. - repeated Style style = 10; -} - -// Defines a proto annotation that describes a string field that refers to -// an API resource. -message ResourceReference { - // The resource type that the annotated field references. - // - // Example: - // - // message Subscription { - // string topic = 2 [(google.api.resource_reference) = { - // type: "pubsub.googleapis.com/Topic" - // }]; - // } - // - // Occasionally, a field may reference an arbitrary resource. In this case, - // APIs use the special value * in their resource reference. - // - // Example: - // - // message GetIamPolicyRequest { - // string resource = 2 [(google.api.resource_reference) = { - // type: "*" - // }]; - // } - string type = 1; - - // The resource type of a child collection that the annotated field - // references. This is useful for annotating the `parent` field that - // doesn't have a fixed resource type. - // - // Example: - // - // message ListLogEntriesRequest { - // string parent = 1 [(google.api.resource_reference) = { - // child_type: "logging.googleapis.com/LogEntry" - // }; - // } - string child_type = 2; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/resource_pb2.py b/notification-service/venv/Lib/site-packages/google/api/resource_pb2.py deleted file mode 100644 index bea0139..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/resource_pb2.py +++ /dev/null @@ -1,54 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/resource.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x19google/api/resource.proto\x12\ngoogle.api\x1a google/protobuf/descriptor.proto"\xee\x02\n\x12ResourceDescriptor\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0f\n\x07pattern\x18\x02 \x03(\t\x12\x12\n\nname_field\x18\x03 \x01(\t\x12\x37\n\x07history\x18\x04 \x01(\x0e\x32&.google.api.ResourceDescriptor.History\x12\x0e\n\x06plural\x18\x05 \x01(\t\x12\x10\n\x08singular\x18\x06 \x01(\t\x12\x33\n\x05style\x18\n \x03(\x0e\x32$.google.api.ResourceDescriptor.Style"[\n\x07History\x12\x17\n\x13HISTORY_UNSPECIFIED\x10\x00\x12\x1d\n\x19ORIGINALLY_SINGLE_PATTERN\x10\x01\x12\x18\n\x14\x46UTURE_MULTI_PATTERN\x10\x02"8\n\x05Style\x12\x15\n\x11STYLE_UNSPECIFIED\x10\x00\x12\x18\n\x14\x44\x45\x43LARATIVE_FRIENDLY\x10\x01"5\n\x11ResourceReference\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x12\n\nchild_type\x18\x02 \x01(\t:Y\n\x12resource_reference\x12\x1d.google.protobuf.FieldOptions\x18\x9f\x08 \x01(\x0b\x32\x1d.google.api.ResourceReference:Z\n\x13resource_definition\x12\x1c.google.protobuf.FileOptions\x18\x9d\x08 \x03(\x0b\x32\x1e.google.api.ResourceDescriptor:R\n\x08resource\x12\x1f.google.protobuf.MessageOptions\x18\x9d\x08 \x01(\x0b\x32\x1e.google.api.ResourceDescriptorBk\n\x0e\x63om.google.apiB\rResourceProtoP\x01ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.resource_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\rResourceProtoP\001ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\242\002\004GAPI" - _globals["_RESOURCEDESCRIPTOR"]._serialized_start = 76 - _globals["_RESOURCEDESCRIPTOR"]._serialized_end = 442 - _globals["_RESOURCEDESCRIPTOR_HISTORY"]._serialized_start = 293 - _globals["_RESOURCEDESCRIPTOR_HISTORY"]._serialized_end = 384 - _globals["_RESOURCEDESCRIPTOR_STYLE"]._serialized_start = 386 - _globals["_RESOURCEDESCRIPTOR_STYLE"]._serialized_end = 442 - _globals["_RESOURCEREFERENCE"]._serialized_start = 444 - _globals["_RESOURCEREFERENCE"]._serialized_end = 497 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/resource_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/resource_pb2.pyi deleted file mode 100644 index 47675dc..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/resource_pb2.pyi +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pb2 as _descriptor_pb2 -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers -from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper - -DESCRIPTOR: _descriptor.FileDescriptor -RESOURCE_REFERENCE_FIELD_NUMBER: _ClassVar[int] -resource_reference: _descriptor.FieldDescriptor -RESOURCE_DEFINITION_FIELD_NUMBER: _ClassVar[int] -resource_definition: _descriptor.FieldDescriptor -RESOURCE_FIELD_NUMBER: _ClassVar[int] -resource: _descriptor.FieldDescriptor - -class ResourceDescriptor(_message.Message): - __slots__ = ( - "type", - "pattern", - "name_field", - "history", - "plural", - "singular", - "style", - ) - class History(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - HISTORY_UNSPECIFIED: _ClassVar[ResourceDescriptor.History] - ORIGINALLY_SINGLE_PATTERN: _ClassVar[ResourceDescriptor.History] - FUTURE_MULTI_PATTERN: _ClassVar[ResourceDescriptor.History] - - HISTORY_UNSPECIFIED: ResourceDescriptor.History - ORIGINALLY_SINGLE_PATTERN: ResourceDescriptor.History - FUTURE_MULTI_PATTERN: ResourceDescriptor.History - class Style(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): - __slots__ = () - STYLE_UNSPECIFIED: _ClassVar[ResourceDescriptor.Style] - DECLARATIVE_FRIENDLY: _ClassVar[ResourceDescriptor.Style] - - STYLE_UNSPECIFIED: ResourceDescriptor.Style - DECLARATIVE_FRIENDLY: ResourceDescriptor.Style - TYPE_FIELD_NUMBER: _ClassVar[int] - PATTERN_FIELD_NUMBER: _ClassVar[int] - NAME_FIELD_FIELD_NUMBER: _ClassVar[int] - HISTORY_FIELD_NUMBER: _ClassVar[int] - PLURAL_FIELD_NUMBER: _ClassVar[int] - SINGULAR_FIELD_NUMBER: _ClassVar[int] - STYLE_FIELD_NUMBER: _ClassVar[int] - type: str - pattern: _containers.RepeatedScalarFieldContainer[str] - name_field: str - history: ResourceDescriptor.History - plural: str - singular: str - style: _containers.RepeatedScalarFieldContainer[ResourceDescriptor.Style] - def __init__( - self, - type: _Optional[str] = ..., - pattern: _Optional[_Iterable[str]] = ..., - name_field: _Optional[str] = ..., - history: _Optional[_Union[ResourceDescriptor.History, str]] = ..., - plural: _Optional[str] = ..., - singular: _Optional[str] = ..., - style: _Optional[_Iterable[_Union[ResourceDescriptor.Style, str]]] = ..., - ) -> None: ... - -class ResourceReference(_message.Message): - __slots__ = ("type", "child_type") - TYPE_FIELD_NUMBER: _ClassVar[int] - CHILD_TYPE_FIELD_NUMBER: _ClassVar[int] - type: str - child_type: str - def __init__( - self, type: _Optional[str] = ..., child_type: _Optional[str] = ... - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/routing.proto b/notification-service/venv/Lib/site-packages/google/api/routing.proto deleted file mode 100644 index 020d32f..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/routing.proto +++ /dev/null @@ -1,465 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/protobuf/descriptor.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; -option java_multiple_files = true; -option java_outer_classname = "RoutingProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -extend google.protobuf.MethodOptions { - // See RoutingRule. - google.api.RoutingRule routing = 72295729; -} - -// Specifies the routing information that should be sent along with the request -// in the form of routing header. -// **NOTE:** All service configuration rules follow the "last one wins" order. -// -// The examples below will apply to an RPC which has the following request type: -// -// Message Definition: -// -// message Request { -// // The name of the Table -// // Values can be of the following formats: -// // - `projects//tables/` -// // - `projects//instances//tables/
` -// // - `region//zones//tables/
` -// string table_name = 1; -// -// // This value specifies routing for replication. -// // It can be in the following formats: -// // - `profiles/` -// // - a legacy `profile_id` that can be any string -// string app_profile_id = 2; -// } -// -// Example message: -// -// { -// table_name: projects/proj_foo/instances/instance_bar/table/table_baz, -// app_profile_id: profiles/prof_qux -// } -// -// The routing header consists of one or multiple key-value pairs. The order of -// the key-value pairs is undefined, the order of the `routing_parameters` in -// the `RoutingRule` only matters for the evaluation order of the path -// templates when `field` is the same. See the examples below for more details. -// -// Every key and value in the routing header must be percent-encoded, -// and joined together in the following format: `key1=value1&key2=value2`. -// The examples below skip the percent-encoding for readability. -// -// Example 1 -// -// Extracting a field from the request to put into the routing header -// unchanged, with the key equal to the field name. -// -// annotation: -// -// option (google.api.routing) = { -// // Take the `app_profile_id`. -// routing_parameters { -// field: "app_profile_id" -// } -// }; -// -// result: -// -// x-goog-request-params: app_profile_id=profiles/prof_qux -// -// Example 2 -// -// Extracting a field from the request to put into the routing header -// unchanged, with the key different from the field name. -// -// annotation: -// -// option (google.api.routing) = { -// // Take the `app_profile_id`, but name it `routing_id` in the header. -// routing_parameters { -// field: "app_profile_id" -// path_template: "{routing_id=**}" -// } -// }; -// -// result: -// -// x-goog-request-params: routing_id=profiles/prof_qux -// -// Example 3 -// -// Extracting a field from the request to put into the routing -// header, while matching a path template syntax on the field's value. -// -// NB: it is more useful to send nothing than to send garbage for the purpose -// of dynamic routing, since garbage pollutes cache. Thus the matching. -// -// Sub-example 3a -// -// The field matches the template. -// -// annotation: -// -// option (google.api.routing) = { -// // Take the `table_name`, if it's well-formed (with project-based -// // syntax). -// routing_parameters { -// field: "table_name" -// path_template: "{table_name=projects/*/instances/*/**}" -// } -// }; -// -// result: -// -// x-goog-request-params: -// table_name=projects/proj_foo/instances/instance_bar/table/table_baz -// -// Sub-example 3b -// -// The field does not match the template. -// -// annotation: -// -// option (google.api.routing) = { -// // Take the `table_name`, if it's well-formed (with region-based -// // syntax). -// routing_parameters { -// field: "table_name" -// path_template: "{table_name=regions/*/zones/*/**}" -// } -// }; -// -// result: -// -// -// -// Sub-example 3c -// -// Multiple alternative conflictingly named path templates are -// specified. The one that matches is used to construct the header. -// -// annotation: -// -// option (google.api.routing) = { -// // Take the `table_name`, if it's well-formed, whether -// // using the region- or projects-based syntax. -// -// routing_parameters { -// field: "table_name" -// path_template: "{table_name=regions/*/zones/*/**}" -// } -// routing_parameters { -// field: "table_name" -// path_template: "{table_name=projects/*/instances/*/**}" -// } -// }; -// -// result: -// -// x-goog-request-params: -// table_name=projects/proj_foo/instances/instance_bar/table/table_baz -// -// Example 4 -// -// Extracting a single routing header key-value pair by matching a -// template syntax on (a part of) a single request field. -// -// annotation: -// -// option (google.api.routing) = { -// // Take just the project id from the `table_name` field. -// routing_parameters { -// field: "table_name" -// path_template: "{routing_id=projects/*}/**" -// } -// }; -// -// result: -// -// x-goog-request-params: routing_id=projects/proj_foo -// -// Example 5 -// -// Extracting a single routing header key-value pair by matching -// several conflictingly named path templates on (parts of) a single request -// field. The last template to match "wins" the conflict. -// -// annotation: -// -// option (google.api.routing) = { -// // If the `table_name` does not have instances information, -// // take just the project id for routing. -// // Otherwise take project + instance. -// -// routing_parameters { -// field: "table_name" -// path_template: "{routing_id=projects/*}/**" -// } -// routing_parameters { -// field: "table_name" -// path_template: "{routing_id=projects/*/instances/*}/**" -// } -// }; -// -// result: -// -// x-goog-request-params: -// routing_id=projects/proj_foo/instances/instance_bar -// -// Example 6 -// -// Extracting multiple routing header key-value pairs by matching -// several non-conflicting path templates on (parts of) a single request field. -// -// Sub-example 6a -// -// Make the templates strict, so that if the `table_name` does not -// have an instance information, nothing is sent. -// -// annotation: -// -// option (google.api.routing) = { -// // The routing code needs two keys instead of one composite -// // but works only for the tables with the "project-instance" name -// // syntax. -// -// routing_parameters { -// field: "table_name" -// path_template: "{project_id=projects/*}/instances/*/**" -// } -// routing_parameters { -// field: "table_name" -// path_template: "projects/*/{instance_id=instances/*}/**" -// } -// }; -// -// result: -// -// x-goog-request-params: -// project_id=projects/proj_foo&instance_id=instances/instance_bar -// -// Sub-example 6b -// -// Make the templates loose, so that if the `table_name` does not -// have an instance information, just the project id part is sent. -// -// annotation: -// -// option (google.api.routing) = { -// // The routing code wants two keys instead of one composite -// // but will work with just the `project_id` for tables without -// // an instance in the `table_name`. -// -// routing_parameters { -// field: "table_name" -// path_template: "{project_id=projects/*}/**" -// } -// routing_parameters { -// field: "table_name" -// path_template: "projects/*/{instance_id=instances/*}/**" -// } -// }; -// -// result (is the same as 6a for our example message because it has the instance -// information): -// -// x-goog-request-params: -// project_id=projects/proj_foo&instance_id=instances/instance_bar -// -// Example 7 -// -// Extracting multiple routing header key-value pairs by matching -// several path templates on multiple request fields. -// -// NB: note that here there is no way to specify sending nothing if one of the -// fields does not match its template. E.g. if the `table_name` is in the wrong -// format, the `project_id` will not be sent, but the `routing_id` will be. -// The backend routing code has to be aware of that and be prepared to not -// receive a full complement of keys if it expects multiple. -// -// annotation: -// -// option (google.api.routing) = { -// // The routing needs both `project_id` and `routing_id` -// // (from the `app_profile_id` field) for routing. -// -// routing_parameters { -// field: "table_name" -// path_template: "{project_id=projects/*}/**" -// } -// routing_parameters { -// field: "app_profile_id" -// path_template: "{routing_id=**}" -// } -// }; -// -// result: -// -// x-goog-request-params: -// project_id=projects/proj_foo&routing_id=profiles/prof_qux -// -// Example 8 -// -// Extracting a single routing header key-value pair by matching -// several conflictingly named path templates on several request fields. The -// last template to match "wins" the conflict. -// -// annotation: -// -// option (google.api.routing) = { -// // The `routing_id` can be a project id or a region id depending on -// // the table name format, but only if the `app_profile_id` is not set. -// // If `app_profile_id` is set it should be used instead. -// -// routing_parameters { -// field: "table_name" -// path_template: "{routing_id=projects/*}/**" -// } -// routing_parameters { -// field: "table_name" -// path_template: "{routing_id=regions/*}/**" -// } -// routing_parameters { -// field: "app_profile_id" -// path_template: "{routing_id=**}" -// } -// }; -// -// result: -// -// x-goog-request-params: routing_id=profiles/prof_qux -// -// Example 9 -// -// Bringing it all together. -// -// annotation: -// -// option (google.api.routing) = { -// // For routing both `table_location` and a `routing_id` are needed. -// // -// // table_location can be either an instance id or a region+zone id. -// // -// // For `routing_id`, take the value of `app_profile_id` -// // - If it's in the format `profiles/`, send -// // just the `` part. -// // - If it's any other literal, send it as is. -// // If the `app_profile_id` is empty, and the `table_name` starts with -// // the project_id, send that instead. -// -// routing_parameters { -// field: "table_name" -// path_template: "projects/*/{table_location=instances/*}/tables/*" -// } -// routing_parameters { -// field: "table_name" -// path_template: "{table_location=regions/*/zones/*}/tables/*" -// } -// routing_parameters { -// field: "table_name" -// path_template: "{routing_id=projects/*}/**" -// } -// routing_parameters { -// field: "app_profile_id" -// path_template: "{routing_id=**}" -// } -// routing_parameters { -// field: "app_profile_id" -// path_template: "profiles/{routing_id=*}" -// } -// }; -// -// result: -// -// x-goog-request-params: -// table_location=instances/instance_bar&routing_id=prof_qux -message RoutingRule { - // A collection of Routing Parameter specifications. - // **NOTE:** If multiple Routing Parameters describe the same key - // (via the `path_template` field or via the `field` field when - // `path_template` is not provided), "last one wins" rule - // determines which Parameter gets used. - // See the examples for more details. - repeated RoutingParameter routing_parameters = 2; -} - -// A projection from an input message to the GRPC or REST header. -message RoutingParameter { - // A request field to extract the header key-value pair from. - string field = 1; - - // A pattern matching the key-value field. Optional. - // If not specified, the whole field specified in the `field` field will be - // taken as value, and its name used as key. If specified, it MUST contain - // exactly one named segment (along with any number of unnamed segments) The - // pattern will be matched over the field specified in the `field` field, then - // if the match is successful: - // - the name of the single named segment will be used as a header name, - // - the match value of the segment will be used as a header value; - // if the match is NOT successful, nothing will be sent. - // - // Example: - // - // -- This is a field in the request message - // | that the header value will be extracted from. - // | - // | -- This is the key name in the - // | | routing header. - // V | - // field: "table_name" v - // path_template: "projects/*/{table_location=instances/*}/tables/*" - // ^ ^ - // | | - // In the {} brackets is the pattern that -- | - // specifies what to extract from the | - // field as a value to be sent. | - // | - // The string in the field must match the whole pattern -- - // before brackets, inside brackets, after brackets. - // - // When looking at this specific example, we can see that: - // - A key-value pair with the key `table_location` - // and the value matching `instances/*` should be added - // to the x-goog-request-params routing header. - // - The value is extracted from the request message's `table_name` field - // if it matches the full pattern specified: - // `projects/*/instances/*/tables/*`. - // - // **NB:** If the `path_template` field is not provided, the key name is - // equal to the field name, and the whole field should be sent as a value. - // This makes the pattern for the field and the value functionally equivalent - // to `**`, and the configuration - // - // { - // field: "table_name" - // } - // - // is a functionally equivalent shorthand to: - // - // { - // field: "table_name" - // path_template: "{table_name=**}" - // } - // - // See Example 1 for more details. - string path_template = 2; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/routing_pb2.py b/notification-service/venv/Lib/site-packages/google/api/routing_pb2.py deleted file mode 100644 index e6fc71d..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/routing_pb2.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/routing.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x18google/api/routing.proto\x12\ngoogle.api\x1a google/protobuf/descriptor.proto"G\n\x0bRoutingRule\x12\x38\n\x12routing_parameters\x18\x02 \x03(\x0b\x32\x1c.google.api.RoutingParameter"8\n\x10RoutingParameter\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x15\n\rpath_template\x18\x02 \x01(\t:K\n\x07routing\x12\x1e.google.protobuf.MethodOptions\x18\xb1\xca\xbc" \x01(\x0b\x32\x17.google.api.RoutingRuleBj\n\x0e\x63om.google.apiB\x0cRoutingProtoP\x01ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.routing_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\014RoutingProtoP\001ZAgoogle.golang.org/genproto/googleapis/api/annotations;annotations\242\002\004GAPI" - _globals["_ROUTINGRULE"]._serialized_start = 74 - _globals["_ROUTINGRULE"]._serialized_end = 145 - _globals["_ROUTINGPARAMETER"]._serialized_start = 147 - _globals["_ROUTINGPARAMETER"]._serialized_end = 203 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/routing_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/routing_pb2.pyi deleted file mode 100644 index 8d83325..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/routing_pb2.pyi +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pb2 as _descriptor_pb2 -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor -ROUTING_FIELD_NUMBER: _ClassVar[int] -routing: _descriptor.FieldDescriptor - -class RoutingRule(_message.Message): - __slots__ = ("routing_parameters",) - ROUTING_PARAMETERS_FIELD_NUMBER: _ClassVar[int] - routing_parameters: _containers.RepeatedCompositeFieldContainer[RoutingParameter] - def __init__( - self, - routing_parameters: _Optional[ - _Iterable[_Union[RoutingParameter, _Mapping]] - ] = ..., - ) -> None: ... - -class RoutingParameter(_message.Message): - __slots__ = ("field", "path_template") - FIELD_FIELD_NUMBER: _ClassVar[int] - PATH_TEMPLATE_FIELD_NUMBER: _ClassVar[int] - field: str - path_template: str - def __init__( - self, field: _Optional[str] = ..., path_template: _Optional[str] = ... - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/service.proto b/notification-service/venv/Lib/site-packages/google/api/service.proto deleted file mode 100644 index 9952ca0..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/service.proto +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/api/auth.proto"; -import "google/api/backend.proto"; -import "google/api/billing.proto"; -import "google/api/client.proto"; -import "google/api/context.proto"; -import "google/api/control.proto"; -import "google/api/documentation.proto"; -import "google/api/endpoint.proto"; -import "google/api/http.proto"; -import "google/api/log.proto"; -import "google/api/logging.proto"; -import "google/api/metric.proto"; -import "google/api/monitored_resource.proto"; -import "google/api/monitoring.proto"; -import "google/api/quota.proto"; -import "google/api/source_info.proto"; -import "google/api/system_parameter.proto"; -import "google/api/usage.proto"; -import "google/protobuf/api.proto"; -import "google/protobuf/type.proto"; -import "google/protobuf/wrappers.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "ServiceProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// `Service` is the root object of Google API service configuration (service -// config). It describes the basic information about a logical service, -// such as the service name and the user-facing title, and delegates other -// aspects to sub-sections. Each sub-section is either a proto message or a -// repeated proto message that configures a specific aspect, such as auth. -// For more information, see each proto message definition. -// -// Example: -// -// type: google.api.Service -// name: calendar.googleapis.com -// title: Google Calendar API -// apis: -// - name: google.calendar.v3.Calendar -// -// visibility: -// rules: -// - selector: "google.calendar.v3.*" -// restriction: PREVIEW -// backend: -// rules: -// - selector: "google.calendar.v3.*" -// address: calendar.example.com -// -// authentication: -// providers: -// - id: google_calendar_auth -// jwks_uri: https://www.googleapis.com/oauth2/v1/certs -// issuer: https://securetoken.google.com -// rules: -// - selector: "*" -// requirements: -// provider_id: google_calendar_auth -message Service { - // The service name, which is a DNS-like logical identifier for the - // service, such as `calendar.googleapis.com`. The service name - // typically goes through DNS verification to make sure the owner - // of the service also owns the DNS name. - string name = 1; - - // The product title for this service, it is the name displayed in Google - // Cloud Console. - string title = 2; - - // The Google project that owns this service. - string producer_project_id = 22; - - // A unique ID for a specific instance of this message, typically assigned - // by the client for tracking purpose. Must be no longer than 63 characters - // and only lower case letters, digits, '.', '_' and '-' are allowed. If - // empty, the server may choose to generate one instead. - string id = 33; - - // A list of API interfaces exported by this service. Only the `name` field - // of the [google.protobuf.Api][google.protobuf.Api] needs to be provided by - // the configuration author, as the remaining fields will be derived from the - // IDL during the normalization process. It is an error to specify an API - // interface here which cannot be resolved against the associated IDL files. - repeated google.protobuf.Api apis = 3; - - // A list of all proto message types included in this API service. - // Types referenced directly or indirectly by the `apis` are automatically - // included. Messages which are not referenced but shall be included, such as - // types used by the `google.protobuf.Any` type, should be listed here by - // name by the configuration author. Example: - // - // types: - // - name: google.protobuf.Int32 - repeated google.protobuf.Type types = 4; - - // A list of all enum types included in this API service. Enums referenced - // directly or indirectly by the `apis` are automatically included. Enums - // which are not referenced but shall be included should be listed here by - // name by the configuration author. Example: - // - // enums: - // - name: google.someapi.v1.SomeEnum - repeated google.protobuf.Enum enums = 5; - - // Additional API documentation. - Documentation documentation = 6; - - // API backend configuration. - Backend backend = 8; - - // HTTP configuration. - Http http = 9; - - // Quota configuration. - Quota quota = 10; - - // Auth configuration. - Authentication authentication = 11; - - // Context configuration. - Context context = 12; - - // Configuration controlling usage of this service. - Usage usage = 15; - - // Configuration for network endpoints. If this is empty, then an endpoint - // with the same name as the service is automatically generated to service all - // defined APIs. - repeated Endpoint endpoints = 18; - - // Configuration for the service control plane. - Control control = 21; - - // Defines the logs used by this service. - repeated LogDescriptor logs = 23; - - // Defines the metrics used by this service. - repeated MetricDescriptor metrics = 24; - - // Defines the monitored resources used by this service. This is required - // by the `Service.monitoring` and `Service.logging` configurations. - repeated MonitoredResourceDescriptor monitored_resources = 25; - - // Billing configuration. - Billing billing = 26; - - // Logging configuration. - Logging logging = 27; - - // Monitoring configuration. - Monitoring monitoring = 28; - - // System parameter configuration. - SystemParameters system_parameters = 29; - - // Output only. The source information for this configuration if available. - SourceInfo source_info = 37; - - // Settings for [Google Cloud Client - // libraries](https://cloud.google.com/apis/docs/cloud-client-libraries) - // generated from APIs defined as protocol buffers. - Publishing publishing = 45; - - // Obsolete. Do not use. - // - // This field has no semantic meaning. The service config compiler always - // sets this field to `3`. - google.protobuf.UInt32Value config_version = 20; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/service_pb2.py b/notification-service/venv/Lib/site-packages/google/api/service_pb2.py deleted file mode 100644 index cc6f719..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/service_pb2.py +++ /dev/null @@ -1,71 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/service.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import api_pb2 as google_dot_protobuf_dot_api__pb2 -from google.protobuf import type_pb2 as google_dot_protobuf_dot_type__pb2 -from google.protobuf import wrappers_pb2 as google_dot_protobuf_dot_wrappers__pb2 - -from google.api import auth_pb2 as google_dot_api_dot_auth__pb2 -from google.api import backend_pb2 as google_dot_api_dot_backend__pb2 -from google.api import billing_pb2 as google_dot_api_dot_billing__pb2 -from google.api import client_pb2 as google_dot_api_dot_client__pb2 -from google.api import context_pb2 as google_dot_api_dot_context__pb2 -from google.api import control_pb2 as google_dot_api_dot_control__pb2 -from google.api import documentation_pb2 as google_dot_api_dot_documentation__pb2 -from google.api import endpoint_pb2 as google_dot_api_dot_endpoint__pb2 -from google.api import http_pb2 as google_dot_api_dot_http__pb2 -from google.api import log_pb2 as google_dot_api_dot_log__pb2 -from google.api import logging_pb2 as google_dot_api_dot_logging__pb2 -from google.api import metric_pb2 as google_dot_api_dot_metric__pb2 -from google.api import ( - monitored_resource_pb2 as google_dot_api_dot_monitored__resource__pb2, -) -from google.api import monitoring_pb2 as google_dot_api_dot_monitoring__pb2 -from google.api import quota_pb2 as google_dot_api_dot_quota__pb2 -from google.api import source_info_pb2 as google_dot_api_dot_source__info__pb2 -from google.api import system_parameter_pb2 as google_dot_api_dot_system__parameter__pb2 -from google.api import usage_pb2 as google_dot_api_dot_usage__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b"\n\x18google/api/service.proto\x12\ngoogle.api\x1a\x15google/api/auth.proto\x1a\x18google/api/backend.proto\x1a\x18google/api/billing.proto\x1a\x17google/api/client.proto\x1a\x18google/api/context.proto\x1a\x18google/api/control.proto\x1a\x1egoogle/api/documentation.proto\x1a\x19google/api/endpoint.proto\x1a\x15google/api/http.proto\x1a\x14google/api/log.proto\x1a\x18google/api/logging.proto\x1a\x17google/api/metric.proto\x1a#google/api/monitored_resource.proto\x1a\x1bgoogle/api/monitoring.proto\x1a\x16google/api/quota.proto\x1a\x1cgoogle/api/source_info.proto\x1a!google/api/system_parameter.proto\x1a\x16google/api/usage.proto\x1a\x19google/protobuf/api.proto\x1a\x1agoogle/protobuf/type.proto\x1a\x1egoogle/protobuf/wrappers.proto\"\x82\x08\n\x07Service\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05title\x18\x02 \x01(\t\x12\x1b\n\x13producer_project_id\x18\x16 \x01(\t\x12\n\n\x02id\x18! \x01(\t\x12\"\n\x04\x61pis\x18\x03 \x03(\x0b\x32\x14.google.protobuf.Api\x12$\n\x05types\x18\x04 \x03(\x0b\x32\x15.google.protobuf.Type\x12$\n\x05\x65nums\x18\x05 \x03(\x0b\x32\x15.google.protobuf.Enum\x12\x30\n\rdocumentation\x18\x06 \x01(\x0b\x32\x19.google.api.Documentation\x12$\n\x07\x62\x61\x63kend\x18\x08 \x01(\x0b\x32\x13.google.api.Backend\x12\x1e\n\x04http\x18\t \x01(\x0b\x32\x10.google.api.Http\x12 \n\x05quota\x18\n \x01(\x0b\x32\x11.google.api.Quota\x12\x32\n\x0e\x61uthentication\x18\x0b \x01(\x0b\x32\x1a.google.api.Authentication\x12$\n\x07\x63ontext\x18\x0c \x01(\x0b\x32\x13.google.api.Context\x12 \n\x05usage\x18\x0f \x01(\x0b\x32\x11.google.api.Usage\x12'\n\tendpoints\x18\x12 \x03(\x0b\x32\x14.google.api.Endpoint\x12$\n\x07\x63ontrol\x18\x15 \x01(\x0b\x32\x13.google.api.Control\x12'\n\x04logs\x18\x17 \x03(\x0b\x32\x19.google.api.LogDescriptor\x12-\n\x07metrics\x18\x18 \x03(\x0b\x32\x1c.google.api.MetricDescriptor\x12\x44\n\x13monitored_resources\x18\x19 \x03(\x0b\x32'.google.api.MonitoredResourceDescriptor\x12$\n\x07\x62illing\x18\x1a \x01(\x0b\x32\x13.google.api.Billing\x12$\n\x07logging\x18\x1b \x01(\x0b\x32\x13.google.api.Logging\x12*\n\nmonitoring\x18\x1c \x01(\x0b\x32\x16.google.api.Monitoring\x12\x37\n\x11system_parameters\x18\x1d \x01(\x0b\x32\x1c.google.api.SystemParameters\x12+\n\x0bsource_info\x18% \x01(\x0b\x32\x16.google.api.SourceInfo\x12*\n\npublishing\x18- \x01(\x0b\x32\x16.google.api.Publishing\x12\x34\n\x0e\x63onfig_version\x18\x14 \x01(\x0b\x32\x1c.google.protobuf.UInt32ValueBn\n\x0e\x63om.google.apiB\x0cServiceProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3" -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.service_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\014ServiceProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_SERVICE"]._serialized_start = 614 - _globals["_SERVICE"]._serialized_end = 1640 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/service_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/service_pb2.pyi deleted file mode 100644 index a2e79a4..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/service_pb2.pyi +++ /dev/null @@ -1,170 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import api_pb2 as _api_pb2 -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import type_pb2 as _type_pb2 -from google.protobuf import wrappers_pb2 as _wrappers_pb2 -from google.protobuf.internal import containers as _containers - -from google.api import auth_pb2 as _auth_pb2 -from google.api import backend_pb2 as _backend_pb2 -from google.api import billing_pb2 as _billing_pb2 -from google.api import client_pb2 as _client_pb2 -from google.api import context_pb2 as _context_pb2 -from google.api import control_pb2 as _control_pb2 -from google.api import documentation_pb2 as _documentation_pb2 -from google.api import endpoint_pb2 as _endpoint_pb2 -from google.api import http_pb2 as _http_pb2 -from google.api import log_pb2 as _log_pb2 -from google.api import logging_pb2 as _logging_pb2 -from google.api import metric_pb2 as _metric_pb2 -from google.api import monitored_resource_pb2 as _monitored_resource_pb2 -from google.api import monitoring_pb2 as _monitoring_pb2 -from google.api import quota_pb2 as _quota_pb2 -from google.api import source_info_pb2 as _source_info_pb2 -from google.api import system_parameter_pb2 as _system_parameter_pb2 -from google.api import usage_pb2 as _usage_pb2 - -DESCRIPTOR: _descriptor.FileDescriptor - -class Service(_message.Message): - __slots__ = ( - "name", - "title", - "producer_project_id", - "id", - "apis", - "types", - "enums", - "documentation", - "backend", - "http", - "quota", - "authentication", - "context", - "usage", - "endpoints", - "control", - "logs", - "metrics", - "monitored_resources", - "billing", - "logging", - "monitoring", - "system_parameters", - "source_info", - "publishing", - "config_version", - ) - NAME_FIELD_NUMBER: _ClassVar[int] - TITLE_FIELD_NUMBER: _ClassVar[int] - PRODUCER_PROJECT_ID_FIELD_NUMBER: _ClassVar[int] - ID_FIELD_NUMBER: _ClassVar[int] - APIS_FIELD_NUMBER: _ClassVar[int] - TYPES_FIELD_NUMBER: _ClassVar[int] - ENUMS_FIELD_NUMBER: _ClassVar[int] - DOCUMENTATION_FIELD_NUMBER: _ClassVar[int] - BACKEND_FIELD_NUMBER: _ClassVar[int] - HTTP_FIELD_NUMBER: _ClassVar[int] - QUOTA_FIELD_NUMBER: _ClassVar[int] - AUTHENTICATION_FIELD_NUMBER: _ClassVar[int] - CONTEXT_FIELD_NUMBER: _ClassVar[int] - USAGE_FIELD_NUMBER: _ClassVar[int] - ENDPOINTS_FIELD_NUMBER: _ClassVar[int] - CONTROL_FIELD_NUMBER: _ClassVar[int] - LOGS_FIELD_NUMBER: _ClassVar[int] - METRICS_FIELD_NUMBER: _ClassVar[int] - MONITORED_RESOURCES_FIELD_NUMBER: _ClassVar[int] - BILLING_FIELD_NUMBER: _ClassVar[int] - LOGGING_FIELD_NUMBER: _ClassVar[int] - MONITORING_FIELD_NUMBER: _ClassVar[int] - SYSTEM_PARAMETERS_FIELD_NUMBER: _ClassVar[int] - SOURCE_INFO_FIELD_NUMBER: _ClassVar[int] - PUBLISHING_FIELD_NUMBER: _ClassVar[int] - CONFIG_VERSION_FIELD_NUMBER: _ClassVar[int] - name: str - title: str - producer_project_id: str - id: str - apis: _containers.RepeatedCompositeFieldContainer[_api_pb2.Api] - types: _containers.RepeatedCompositeFieldContainer[_type_pb2.Type] - enums: _containers.RepeatedCompositeFieldContainer[_type_pb2.Enum] - documentation: _documentation_pb2.Documentation - backend: _backend_pb2.Backend - http: _http_pb2.Http - quota: _quota_pb2.Quota - authentication: _auth_pb2.Authentication - context: _context_pb2.Context - usage: _usage_pb2.Usage - endpoints: _containers.RepeatedCompositeFieldContainer[_endpoint_pb2.Endpoint] - control: _control_pb2.Control - logs: _containers.RepeatedCompositeFieldContainer[_log_pb2.LogDescriptor] - metrics: _containers.RepeatedCompositeFieldContainer[_metric_pb2.MetricDescriptor] - monitored_resources: _containers.RepeatedCompositeFieldContainer[ - _monitored_resource_pb2.MonitoredResourceDescriptor - ] - billing: _billing_pb2.Billing - logging: _logging_pb2.Logging - monitoring: _monitoring_pb2.Monitoring - system_parameters: _system_parameter_pb2.SystemParameters - source_info: _source_info_pb2.SourceInfo - publishing: _client_pb2.Publishing - config_version: _wrappers_pb2.UInt32Value - def __init__( - self, - name: _Optional[str] = ..., - title: _Optional[str] = ..., - producer_project_id: _Optional[str] = ..., - id: _Optional[str] = ..., - apis: _Optional[_Iterable[_Union[_api_pb2.Api, _Mapping]]] = ..., - types: _Optional[_Iterable[_Union[_type_pb2.Type, _Mapping]]] = ..., - enums: _Optional[_Iterable[_Union[_type_pb2.Enum, _Mapping]]] = ..., - documentation: _Optional[ - _Union[_documentation_pb2.Documentation, _Mapping] - ] = ..., - backend: _Optional[_Union[_backend_pb2.Backend, _Mapping]] = ..., - http: _Optional[_Union[_http_pb2.Http, _Mapping]] = ..., - quota: _Optional[_Union[_quota_pb2.Quota, _Mapping]] = ..., - authentication: _Optional[_Union[_auth_pb2.Authentication, _Mapping]] = ..., - context: _Optional[_Union[_context_pb2.Context, _Mapping]] = ..., - usage: _Optional[_Union[_usage_pb2.Usage, _Mapping]] = ..., - endpoints: _Optional[_Iterable[_Union[_endpoint_pb2.Endpoint, _Mapping]]] = ..., - control: _Optional[_Union[_control_pb2.Control, _Mapping]] = ..., - logs: _Optional[_Iterable[_Union[_log_pb2.LogDescriptor, _Mapping]]] = ..., - metrics: _Optional[ - _Iterable[_Union[_metric_pb2.MetricDescriptor, _Mapping]] - ] = ..., - monitored_resources: _Optional[ - _Iterable[ - _Union[_monitored_resource_pb2.MonitoredResourceDescriptor, _Mapping] - ] - ] = ..., - billing: _Optional[_Union[_billing_pb2.Billing, _Mapping]] = ..., - logging: _Optional[_Union[_logging_pb2.Logging, _Mapping]] = ..., - monitoring: _Optional[_Union[_monitoring_pb2.Monitoring, _Mapping]] = ..., - system_parameters: _Optional[ - _Union[_system_parameter_pb2.SystemParameters, _Mapping] - ] = ..., - source_info: _Optional[_Union[_source_info_pb2.SourceInfo, _Mapping]] = ..., - publishing: _Optional[_Union[_client_pb2.Publishing, _Mapping]] = ..., - config_version: _Optional[_Union[_wrappers_pb2.UInt32Value, _Mapping]] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/source_info.proto b/notification-service/venv/Lib/site-packages/google/api/source_info.proto deleted file mode 100644 index 1d4094e..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/source_info.proto +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/protobuf/any.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "SourceInfoProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// Source information used to create a Service Config -message SourceInfo { - // All files used during config generation. - repeated google.protobuf.Any source_files = 1; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/source_info_pb2.py b/notification-service/venv/Lib/site-packages/google/api/source_info_pb2.py deleted file mode 100644 index fd2c5cc..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/source_info_pb2.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/source_info.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x1cgoogle/api/source_info.proto\x12\ngoogle.api\x1a\x19google/protobuf/any.proto"8\n\nSourceInfo\x12*\n\x0csource_files\x18\x01 \x03(\x0b\x32\x14.google.protobuf.AnyBq\n\x0e\x63om.google.apiB\x0fSourceInfoProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, "google.api.source_info_pb2", _globals -) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\017SourceInfoProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_SOURCEINFO"]._serialized_start = 71 - _globals["_SOURCEINFO"]._serialized_end = 127 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/source_info_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/source_info_pb2.pyi deleted file mode 100644 index 3fe71d3..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/source_info_pb2.pyi +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import any_pb2 as _any_pb2 -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor - -class SourceInfo(_message.Message): - __slots__ = ("source_files",) - SOURCE_FILES_FIELD_NUMBER: _ClassVar[int] - source_files: _containers.RepeatedCompositeFieldContainer[_any_pb2.Any] - def __init__( - self, source_files: _Optional[_Iterable[_Union[_any_pb2.Any, _Mapping]]] = ... - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/system_parameter.proto b/notification-service/venv/Lib/site-packages/google/api/system_parameter.proto deleted file mode 100644 index 5ab1f37..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/system_parameter.proto +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "SystemParameterProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// ### System parameter configuration -// -// A system parameter is a special kind of parameter defined by the API -// system, not by an individual API. It is typically mapped to an HTTP header -// and/or a URL query parameter. This configuration specifies which methods -// change the names of the system parameters. -message SystemParameters { - // Define system parameters. - // - // The parameters defined here will override the default parameters - // implemented by the system. If this field is missing from the service - // config, default system parameters will be used. Default system parameters - // and names is implementation-dependent. - // - // Example: define api key for all methods - // - // system_parameters - // rules: - // - selector: "*" - // parameters: - // - name: api_key - // url_query_parameter: api_key - // - // - // Example: define 2 api key names for a specific method. - // - // system_parameters - // rules: - // - selector: "/ListShelves" - // parameters: - // - name: api_key - // http_header: Api-Key1 - // - name: api_key - // http_header: Api-Key2 - // - // **NOTE:** All service configuration rules follow "last one wins" order. - repeated SystemParameterRule rules = 1; -} - -// Define a system parameter rule mapping system parameter definitions to -// methods. -message SystemParameterRule { - // Selects the methods to which this rule applies. Use '*' to indicate all - // methods in all APIs. - // - // Refer to [selector][google.api.DocumentationRule.selector] for syntax - // details. - string selector = 1; - - // Define parameters. Multiple names may be defined for a parameter. - // For a given method call, only one of them should be used. If multiple - // names are used the behavior is implementation-dependent. - // If none of the specified names are present the behavior is - // parameter-dependent. - repeated SystemParameter parameters = 2; -} - -// Define a parameter's name and location. The parameter may be passed as either -// an HTTP header or a URL query parameter, and if both are passed the behavior -// is implementation-dependent. -message SystemParameter { - // Define the name of the parameter, such as "api_key" . It is case sensitive. - string name = 1; - - // Define the HTTP header name to use for the parameter. It is case - // insensitive. - string http_header = 2; - - // Define the URL query parameter name to use for the parameter. It is case - // sensitive. - string url_query_parameter = 3; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/system_parameter_pb2.py b/notification-service/venv/Lib/site-packages/google/api/system_parameter_pb2.py deleted file mode 100644 index d4a6909..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/system_parameter_pb2.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/system_parameter.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n!google/api/system_parameter.proto\x12\ngoogle.api"B\n\x10SystemParameters\x12.\n\x05rules\x18\x01 \x03(\x0b\x32\x1f.google.api.SystemParameterRule"X\n\x13SystemParameterRule\x12\x10\n\x08selector\x18\x01 \x01(\t\x12/\n\nparameters\x18\x02 \x03(\x0b\x32\x1b.google.api.SystemParameter"Q\n\x0fSystemParameter\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0bhttp_header\x18\x02 \x01(\t\x12\x1b\n\x13url_query_parameter\x18\x03 \x01(\tBv\n\x0e\x63om.google.apiB\x14SystemParameterProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, "google.api.system_parameter_pb2", _globals -) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\024SystemParameterProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_SYSTEMPARAMETERS"]._serialized_start = 49 - _globals["_SYSTEMPARAMETERS"]._serialized_end = 115 - _globals["_SYSTEMPARAMETERRULE"]._serialized_start = 117 - _globals["_SYSTEMPARAMETERRULE"]._serialized_end = 205 - _globals["_SYSTEMPARAMETER"]._serialized_start = 207 - _globals["_SYSTEMPARAMETER"]._serialized_end = 288 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/system_parameter_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/system_parameter_pb2.pyi deleted file mode 100644 index ef8e92a..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/system_parameter_pb2.pyi +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor - -class SystemParameters(_message.Message): - __slots__ = ("rules",) - RULES_FIELD_NUMBER: _ClassVar[int] - rules: _containers.RepeatedCompositeFieldContainer[SystemParameterRule] - def __init__( - self, rules: _Optional[_Iterable[_Union[SystemParameterRule, _Mapping]]] = ... - ) -> None: ... - -class SystemParameterRule(_message.Message): - __slots__ = ("selector", "parameters") - SELECTOR_FIELD_NUMBER: _ClassVar[int] - PARAMETERS_FIELD_NUMBER: _ClassVar[int] - selector: str - parameters: _containers.RepeatedCompositeFieldContainer[SystemParameter] - def __init__( - self, - selector: _Optional[str] = ..., - parameters: _Optional[_Iterable[_Union[SystemParameter, _Mapping]]] = ..., - ) -> None: ... - -class SystemParameter(_message.Message): - __slots__ = ("name", "http_header", "url_query_parameter") - NAME_FIELD_NUMBER: _ClassVar[int] - HTTP_HEADER_FIELD_NUMBER: _ClassVar[int] - URL_QUERY_PARAMETER_FIELD_NUMBER: _ClassVar[int] - name: str - http_header: str - url_query_parameter: str - def __init__( - self, - name: _Optional[str] = ..., - http_header: _Optional[str] = ..., - url_query_parameter: _Optional[str] = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/usage.proto b/notification-service/venv/Lib/site-packages/google/api/usage.proto deleted file mode 100644 index df1b93b..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/usage.proto +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; -option java_multiple_files = true; -option java_outer_classname = "UsageProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -// Configuration controlling usage of a service. -message Usage { - // Requirements that must be satisfied before a consumer project can use the - // service. Each requirement is of the form /; - // for example 'serviceusage.googleapis.com/billing-enabled'. - // - // For Google APIs, a Terms of Service requirement must be included here. - // Google Cloud APIs must include "serviceusage.googleapis.com/tos/cloud". - // Other Google APIs should include - // "serviceusage.googleapis.com/tos/universal". Additional ToS can be - // included based on the business needs. - repeated string requirements = 1; - - // A list of usage rules that apply to individual API methods. - // - // **NOTE:** All service configuration rules follow "last one wins" order. - repeated UsageRule rules = 6; - - // The full resource name of a channel used for sending notifications to the - // service producer. - // - // Google Service Management currently only supports - // [Google Cloud Pub/Sub](https://cloud.google.com/pubsub) as a notification - // channel. To use Google Cloud Pub/Sub as the channel, this must be the name - // of a Cloud Pub/Sub topic that uses the Cloud Pub/Sub topic name format - // documented in https://cloud.google.com/pubsub/docs/overview. - string producer_notification_channel = 7; -} - -// Usage configuration rules for the service. -message UsageRule { - // Selects the methods to which this rule applies. Use '*' to indicate all - // methods in all APIs. - // - // Refer to [selector][google.api.DocumentationRule.selector] for syntax - // details. - string selector = 1; - - // Use this rule to configure unregistered calls for the service. Unregistered - // calls are calls that do not contain consumer project identity. - // (Example: calls that do not contain an API key). - // - // WARNING: By default, API methods do not allow unregistered calls, and each - // method call must be identified by a consumer project identity. - bool allow_unregistered_calls = 2; - - // If true, the selected method should skip service control and the control - // plane features, such as quota and billing, will not be available. - // This flag is used by Google Cloud Endpoints to bypass checks for internal - // methods, such as service health check methods. - bool skip_service_control = 3; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/usage_pb2.py b/notification-service/venv/Lib/site-packages/google/api/usage_pb2.py deleted file mode 100644 index db6f52e..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/usage_pb2.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/usage.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x16google/api/usage.proto\x12\ngoogle.api"j\n\x05Usage\x12\x14\n\x0crequirements\x18\x01 \x03(\t\x12$\n\x05rules\x18\x06 \x03(\x0b\x32\x15.google.api.UsageRule\x12%\n\x1dproducer_notification_channel\x18\x07 \x01(\t"]\n\tUsageRule\x12\x10\n\x08selector\x18\x01 \x01(\t\x12 \n\x18\x61llow_unregistered_calls\x18\x02 \x01(\x08\x12\x1c\n\x14skip_service_control\x18\x03 \x01(\x08\x42l\n\x0e\x63om.google.apiB\nUsageProtoP\x01ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "google.api.usage_pb2", _globals) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\nUsageProtoP\001ZEgoogle.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig\242\002\004GAPI" - _globals["_USAGE"]._serialized_start = 38 - _globals["_USAGE"]._serialized_end = 144 - _globals["_USAGERULE"]._serialized_start = 146 - _globals["_USAGERULE"]._serialized_end = 239 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/usage_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/usage_pb2.pyi deleted file mode 100644 index 071daaf..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/usage_pb2.pyi +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor - -class Usage(_message.Message): - __slots__ = ("requirements", "rules", "producer_notification_channel") - REQUIREMENTS_FIELD_NUMBER: _ClassVar[int] - RULES_FIELD_NUMBER: _ClassVar[int] - PRODUCER_NOTIFICATION_CHANNEL_FIELD_NUMBER: _ClassVar[int] - requirements: _containers.RepeatedScalarFieldContainer[str] - rules: _containers.RepeatedCompositeFieldContainer[UsageRule] - producer_notification_channel: str - def __init__( - self, - requirements: _Optional[_Iterable[str]] = ..., - rules: _Optional[_Iterable[_Union[UsageRule, _Mapping]]] = ..., - producer_notification_channel: _Optional[str] = ..., - ) -> None: ... - -class UsageRule(_message.Message): - __slots__ = ("selector", "allow_unregistered_calls", "skip_service_control") - SELECTOR_FIELD_NUMBER: _ClassVar[int] - ALLOW_UNREGISTERED_CALLS_FIELD_NUMBER: _ClassVar[int] - SKIP_SERVICE_CONTROL_FIELD_NUMBER: _ClassVar[int] - selector: str - allow_unregistered_calls: bool - skip_service_control: bool - def __init__( - self, - selector: _Optional[str] = ..., - allow_unregistered_calls: bool = ..., - skip_service_control: bool = ..., - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api/visibility.proto b/notification-service/venv/Lib/site-packages/google/api/visibility.proto deleted file mode 100644 index fb5cac6..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/visibility.proto +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2026 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -syntax = "proto3"; - -package google.api; - -import "google/protobuf/descriptor.proto"; - -option go_package = "google.golang.org/genproto/googleapis/api/visibility;visibility"; -option java_multiple_files = true; -option java_outer_classname = "VisibilityProto"; -option java_package = "com.google.api"; -option objc_class_prefix = "GAPI"; - -extend google.protobuf.EnumOptions { - // See `VisibilityRule`. - google.api.VisibilityRule enum_visibility = 72295727; -} - -extend google.protobuf.EnumValueOptions { - // See `VisibilityRule`. - google.api.VisibilityRule value_visibility = 72295727; -} - -extend google.protobuf.FieldOptions { - // See `VisibilityRule`. - google.api.VisibilityRule field_visibility = 72295727; -} - -extend google.protobuf.MessageOptions { - // See `VisibilityRule`. - google.api.VisibilityRule message_visibility = 72295727; -} - -extend google.protobuf.MethodOptions { - // See `VisibilityRule`. - google.api.VisibilityRule method_visibility = 72295727; -} - -extend google.protobuf.ServiceOptions { - // See `VisibilityRule`. - google.api.VisibilityRule api_visibility = 72295727; -} - -// `Visibility` restricts service consumer's access to service elements, -// such as whether an application can call a visibility-restricted method. -// The restriction is expressed by applying visibility labels on service -// elements. The visibility labels are elsewhere linked to service consumers. -// -// A service can define multiple visibility labels, but a service consumer -// should be granted at most one visibility label. Multiple visibility -// labels for a single service consumer are not supported. -// -// If an element and all its parents have no visibility label, its visibility -// is unconditionally granted. -// -// Example: -// -// visibility: -// rules: -// - selector: google.calendar.Calendar.EnhancedSearch -// restriction: PREVIEW -// - selector: google.calendar.Calendar.Delegate -// restriction: INTERNAL -// -// Here, all methods are publicly visible except for the restricted methods -// EnhancedSearch and Delegate. -message Visibility { - // A list of visibility rules that apply to individual API elements. - // - // **NOTE:** All service configuration rules follow "last one wins" order. - repeated VisibilityRule rules = 1; -} - -// A visibility rule provides visibility configuration for an individual API -// element. -message VisibilityRule { - // Selects methods, messages, fields, enums, etc. to which this rule applies. - // - // Refer to [selector][google.api.DocumentationRule.selector] for syntax - // details. - string selector = 1; - - // A comma-separated list of visibility labels that apply to the `selector`. - // Any of the listed labels can be used to grant the visibility. - // - // If a rule has multiple labels, removing one of the labels but not all of - // them can break clients. - // - // Example: - // - // visibility: - // rules: - // - selector: google.calendar.Calendar.EnhancedSearch - // restriction: INTERNAL, PREVIEW - // - // Removing INTERNAL from this restriction will break clients that rely on - // this method and only had access to it through INTERNAL. - string restriction = 2; -} diff --git a/notification-service/venv/Lib/site-packages/google/api/visibility_pb2.py b/notification-service/venv/Lib/site-packages/google/api/visibility_pb2.py deleted file mode 100644 index 43dbdfd..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/visibility_pb2.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/api/visibility.proto -# Protobuf Python Version: 4.25.3 -"""Generated protocol buffer code.""" - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -from google.protobuf.internal import builder as _builder - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\x1bgoogle/api/visibility.proto\x12\ngoogle.api\x1a google/protobuf/descriptor.proto"7\n\nVisibility\x12)\n\x05rules\x18\x01 \x03(\x0b\x32\x1a.google.api.VisibilityRule"7\n\x0eVisibilityRule\x12\x10\n\x08selector\x18\x01 \x01(\t\x12\x13\n\x0brestriction\x18\x02 \x01(\t:T\n\x0f\x65num_visibility\x12\x1c.google.protobuf.EnumOptions\x18\xaf\xca\xbc" \x01(\x0b\x32\x1a.google.api.VisibilityRule:Z\n\x10value_visibility\x12!.google.protobuf.EnumValueOptions\x18\xaf\xca\xbc" \x01(\x0b\x32\x1a.google.api.VisibilityRule:V\n\x10\x66ield_visibility\x12\x1d.google.protobuf.FieldOptions\x18\xaf\xca\xbc" \x01(\x0b\x32\x1a.google.api.VisibilityRule:Z\n\x12message_visibility\x12\x1f.google.protobuf.MessageOptions\x18\xaf\xca\xbc" \x01(\x0b\x32\x1a.google.api.VisibilityRule:X\n\x11method_visibility\x12\x1e.google.protobuf.MethodOptions\x18\xaf\xca\xbc" \x01(\x0b\x32\x1a.google.api.VisibilityRule:V\n\x0e\x61pi_visibility\x12\x1f.google.protobuf.ServiceOptions\x18\xaf\xca\xbc" \x01(\x0b\x32\x1a.google.api.VisibilityRuleBk\n\x0e\x63om.google.apiB\x0fVisibilityProtoP\x01Z?google.golang.org/genproto/googleapis/api/visibility;visibility\xa2\x02\x04GAPIb\x06proto3' -) - -_globals = globals() -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages( - DESCRIPTOR, "google.api.visibility_pb2", _globals -) -if _descriptor._USE_C_DESCRIPTORS == False: - _globals["DESCRIPTOR"]._options = None - _globals[ - "DESCRIPTOR" - ]._serialized_options = b"\n\016com.google.apiB\017VisibilityProtoP\001Z?google.golang.org/genproto/googleapis/api/visibility;visibility\242\002\004GAPI" - _globals["_VISIBILITY"]._serialized_start = 77 - _globals["_VISIBILITY"]._serialized_end = 132 - _globals["_VISIBILITYRULE"]._serialized_start = 134 - _globals["_VISIBILITYRULE"]._serialized_end = 189 -# @@protoc_insertion_point(module_scope) diff --git a/notification-service/venv/Lib/site-packages/google/api/visibility_pb2.pyi b/notification-service/venv/Lib/site-packages/google/api/visibility_pb2.pyi deleted file mode 100644 index 8d8d491..0000000 --- a/notification-service/venv/Lib/site-packages/google/api/visibility_pb2.pyi +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import ClassVar as _ClassVar -from typing import Iterable as _Iterable -from typing import Mapping as _Mapping -from typing import Optional as _Optional -from typing import Union as _Union - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pb2 as _descriptor_pb2 -from google.protobuf import message as _message -from google.protobuf.internal import containers as _containers - -DESCRIPTOR: _descriptor.FileDescriptor -ENUM_VISIBILITY_FIELD_NUMBER: _ClassVar[int] -enum_visibility: _descriptor.FieldDescriptor -VALUE_VISIBILITY_FIELD_NUMBER: _ClassVar[int] -value_visibility: _descriptor.FieldDescriptor -FIELD_VISIBILITY_FIELD_NUMBER: _ClassVar[int] -field_visibility: _descriptor.FieldDescriptor -MESSAGE_VISIBILITY_FIELD_NUMBER: _ClassVar[int] -message_visibility: _descriptor.FieldDescriptor -METHOD_VISIBILITY_FIELD_NUMBER: _ClassVar[int] -method_visibility: _descriptor.FieldDescriptor -API_VISIBILITY_FIELD_NUMBER: _ClassVar[int] -api_visibility: _descriptor.FieldDescriptor - -class Visibility(_message.Message): - __slots__ = ("rules",) - RULES_FIELD_NUMBER: _ClassVar[int] - rules: _containers.RepeatedCompositeFieldContainer[VisibilityRule] - def __init__( - self, rules: _Optional[_Iterable[_Union[VisibilityRule, _Mapping]]] = ... - ) -> None: ... - -class VisibilityRule(_message.Message): - __slots__ = ("selector", "restriction") - SELECTOR_FIELD_NUMBER: _ClassVar[int] - RESTRICTION_FIELD_NUMBER: _ClassVar[int] - selector: str - restriction: str - def __init__( - self, selector: _Optional[str] = ..., restriction: _Optional[str] = ... - ) -> None: ... diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__init__.py b/notification-service/venv/Lib/site-packages/google/api_core/__init__.py deleted file mode 100644 index a52ffe8..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Google API Core. - -This package contains common code and utilities used by Google client libraries. -""" - -from google.api_core import _python_package_support -from google.api_core import _python_version_support -from google.api_core import version as api_core_version - -__version__ = api_core_version.__version__ - -# NOTE: Until dependent artifacts require this version of -# google.api_core, the functionality below must be made available -# manually in those artifacts. - -# expose dependency checks for external callers -check_python_version = _python_version_support.check_python_version -check_dependency_versions = _python_package_support.check_dependency_versions -parse_version_to_tuple = _python_package_support.parse_version_to_tuple -warn_deprecation_for_versions_less_than = ( - _python_package_support.warn_deprecation_for_versions_less_than -) -DependencyConstraint = _python_package_support.DependencyConstraint - -# perform version checks against api_core, and emit warnings if needed -check_python_version(package="google.api_core") -check_dependency_versions("google.api_core") diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 9bfabb4..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/_python_package_support.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/_python_package_support.cpython-312.pyc deleted file mode 100644 index cfebe0c..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/_python_package_support.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/_python_version_support.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/_python_version_support.cpython-312.pyc deleted file mode 100644 index 843e0c1..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/_python_version_support.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/_rest_streaming_base.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/_rest_streaming_base.cpython-312.pyc deleted file mode 100644 index 5081489..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/_rest_streaming_base.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/bidi.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/bidi.cpython-312.pyc deleted file mode 100644 index 512577b..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/bidi.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/bidi_async.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/bidi_async.cpython-312.pyc deleted file mode 100644 index ba243e1..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/bidi_async.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/bidi_base.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/bidi_base.cpython-312.pyc deleted file mode 100644 index 4dad660..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/bidi_base.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/client_info.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/client_info.cpython-312.pyc deleted file mode 100644 index 5d04097..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/client_info.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/client_logging.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/client_logging.cpython-312.pyc deleted file mode 100644 index 27c828a..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/client_logging.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/client_options.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/client_options.cpython-312.pyc deleted file mode 100644 index be7da7f..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/client_options.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/datetime_helpers.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/datetime_helpers.cpython-312.pyc deleted file mode 100644 index 8def365..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/datetime_helpers.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/exceptions.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/exceptions.cpython-312.pyc deleted file mode 100644 index 5942ea9..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/exceptions.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/extended_operation.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/extended_operation.cpython-312.pyc deleted file mode 100644 index 8984be8..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/extended_operation.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/general_helpers.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/general_helpers.cpython-312.pyc deleted file mode 100644 index 98db958..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/general_helpers.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/grpc_helpers.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/grpc_helpers.cpython-312.pyc deleted file mode 100644 index 20af595..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/grpc_helpers.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/grpc_helpers_async.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/grpc_helpers_async.cpython-312.pyc deleted file mode 100644 index 716dacb..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/grpc_helpers_async.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/iam.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/iam.cpython-312.pyc deleted file mode 100644 index bd241c3..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/iam.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/operation.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/operation.cpython-312.pyc deleted file mode 100644 index f695630..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/operation.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/operation_async.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/operation_async.cpython-312.pyc deleted file mode 100644 index 35251d0..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/operation_async.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/page_iterator.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/page_iterator.cpython-312.pyc deleted file mode 100644 index 0465e5b..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/page_iterator.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/page_iterator_async.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/page_iterator_async.cpython-312.pyc deleted file mode 100644 index bf48d3e..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/page_iterator_async.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/path_template.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/path_template.cpython-312.pyc deleted file mode 100644 index 684ea18..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/path_template.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/protobuf_helpers.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/protobuf_helpers.cpython-312.pyc deleted file mode 100644 index d8b2925..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/protobuf_helpers.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/rest_helpers.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/rest_helpers.cpython-312.pyc deleted file mode 100644 index 578dd58..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/rest_helpers.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/rest_streaming.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/rest_streaming.cpython-312.pyc deleted file mode 100644 index 1e0e54e..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/rest_streaming.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/rest_streaming_async.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/rest_streaming_async.cpython-312.pyc deleted file mode 100644 index 4da49ff..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/rest_streaming_async.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/retry_async.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/retry_async.cpython-312.pyc deleted file mode 100644 index 36563de..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/retry_async.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/timeout.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/timeout.cpython-312.pyc deleted file mode 100644 index 945f781..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/timeout.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/universe.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/universe.cpython-312.pyc deleted file mode 100644 index 22e1d07..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/universe.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/version.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/version.cpython-312.pyc deleted file mode 100644 index 2d19b2f..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/version.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/version_header.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/version_header.cpython-312.pyc deleted file mode 100644 index 76be9c3..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/__pycache__/version_header.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/_python_package_support.py b/notification-service/venv/Lib/site-packages/google/api_core/_python_package_support.py deleted file mode 100644 index b8732b6..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/_python_package_support.py +++ /dev/null @@ -1,227 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Code to check versions of dependencies used by Google Cloud Client Libraries.""" - -import warnings -from typing import Optional, Tuple - -from collections import namedtuple - -from ._python_version_support import ( - _flatten_message, - _get_distribution_and_import_packages, -) - -from importlib import metadata - -ParsedVersion = Tuple[int, ...] - -# Here we list all the packages for which we want to issue warnings -# about deprecated and unsupported versions. -DependencyConstraint = namedtuple( - "DependencyConstraint", - ["package_name", "minimum_fully_supported_version", "recommended_version"], -) -_PACKAGE_DEPENDENCY_WARNINGS = [ - DependencyConstraint( - "google.protobuf", - minimum_fully_supported_version="4.25.8", - recommended_version="6.x", - ) -] - - -DependencyVersion = namedtuple("DependencyVersion", ["version", "version_string"]) -# Version string we provide in a DependencyVersion when we can't determine the version of a -# package. -UNKNOWN_VERSION_STRING = "--" - - -def parse_version_to_tuple(version_string: str) -> ParsedVersion: - """Safely converts a semantic version string to a comparable tuple of integers. - - Example: "4.25.8" -> (4, 25, 8) - Ignores non-numeric parts and handles common version formats. - - Args: - version_string: Version string in the format "x.y.z" or "x.y.z" - - Returns: - Tuple of integers for the parsed version string. - """ - parts = [] - for part in version_string.split("."): - try: - parts.append(int(part)) - except ValueError: - # If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here. - # This is a simplification compared to 'packaging.parse_version', but sufficient - # for comparing strictly numeric semantic versions. - break - return tuple(parts) - - -def get_dependency_version( - dependency_name: str, -) -> DependencyVersion: - """Get the parsed version of an installed package dependency. - - This function checks for an installed package and returns its version - as a comparable tuple of integers object for safe comparison. - - Args: - dependency_name: The distribution name of the package (e.g., 'requests'). - - Returns: - A DependencyVersion namedtuple with `version` (a tuple of integers) and - `version_string` attributes, or `DependencyVersion(None, - UNKNOWN_VERSION_STRING)` if the package is not found or - another error occurs during version discovery. - - """ - try: - version_string: str = metadata.version(dependency_name) - parsed_version = parse_version_to_tuple(version_string) - return DependencyVersion(parsed_version, version_string) - except Exception: - # Catch exceptions from metadata.version() (e.g., PackageNotFoundError) - # or errors during parse_version_to_tuple - return DependencyVersion(None, UNKNOWN_VERSION_STRING) - - -def warn_deprecation_for_versions_less_than( - consumer_import_package: str, - dependency_import_package: str, - minimum_fully_supported_version: str, - recommended_version: Optional[str] = None, - message_template: Optional[str] = None, -): - """Issue any needed deprecation warnings for `dependency_import_package`. - - If `dependency_import_package` is installed at a version less than - `minimum_fully_supported_version`, this issues a warning using either a - default `message_template` or one provided by the user. The - default `message_template` informs the user that they will not receive - future updates for `consumer_import_package` if - `dependency_import_package` is somehow pinned to a version lower - than `minimum_fully_supported_version`. - - Args: - consumer_import_package: The import name of the package that - needs `dependency_import_package`. - dependency_import_package: The import name of the dependency to check. - minimum_fully_supported_version: The dependency_import_package version number - below which a deprecation warning will be logged. - recommended_version: If provided, the recommended next version, which - could be higher than `minimum_fully_supported_version`. - message_template: A custom default message template to replace - the default. This `message_template` is treated as an - f-string, where the following variables are defined: - `dependency_import_package`, `consumer_import_package` and - `dependency_distribution_package` and - `consumer_distribution_package` and `dependency_package`, - `consumer_package` , which contain the import packages, the - distribution packages, and pretty string with both the - distribution and import packages for the dependency and the - consumer, respectively; and `minimum_fully_supported_version`, - `version_used`, and `version_used_string`, which refer to supported - and currently-used versions of the dependency. - - """ - if ( - not consumer_import_package - or not dependency_import_package - or not minimum_fully_supported_version - ): # pragma: NO COVER - return - - dependency_version = get_dependency_version(dependency_import_package) - if not dependency_version.version: - return - - if dependency_version.version < parse_version_to_tuple( - minimum_fully_supported_version - ): - ( - dependency_package, - dependency_distribution_package, - ) = _get_distribution_and_import_packages(dependency_import_package) - ( - consumer_package, - consumer_distribution_package, - ) = _get_distribution_and_import_packages(consumer_import_package) - - recommendation = ( - " (we recommend {recommended_version})" if recommended_version else "" - ) - message_template = message_template or _flatten_message( - """ - DEPRECATION: Package {consumer_package} depends on - {dependency_package}, currently installed at version - {version_used_string}. Future updates to - {consumer_package} will require {dependency_package} at - version {minimum_fully_supported_version} or - higher{recommendation}. Please ensure that either (a) your - Python environment doesn't pin the version of - {dependency_package}, so that updates to - {consumer_package} can require the higher version, or (b) - you manually update your Python environment to use at - least version {minimum_fully_supported_version} of - {dependency_package}. - """ - ) - warnings.warn( - message_template.format( - consumer_import_package=consumer_import_package, - dependency_import_package=dependency_import_package, - consumer_distribution_package=consumer_distribution_package, - dependency_distribution_package=dependency_distribution_package, - dependency_package=dependency_package, - consumer_package=consumer_package, - minimum_fully_supported_version=minimum_fully_supported_version, - recommendation=recommendation, - version_used=dependency_version.version, - version_used_string=dependency_version.version_string, - ), - FutureWarning, - ) - - -def check_dependency_versions( - consumer_import_package: str, *package_dependency_warnings: DependencyConstraint -): - """Bundle checks for all package dependencies. - - This function can be called by all consumers of google.api_core, - to emit needed deprecation warnings for any of their - dependencies. The dependencies to check can be passed as arguments, or if - none are provided, it will default to the list in - `_PACKAGE_DEPENDENCY_WARNINGS`. - - Args: - consumer_import_package: The distribution name of the calling package, whose - dependencies we're checking. - *package_dependency_warnings: A variable number of DependencyConstraint - objects, each specifying a dependency to check. - """ - if not package_dependency_warnings: - package_dependency_warnings = tuple(_PACKAGE_DEPENDENCY_WARNINGS) - for package_info in package_dependency_warnings: - warn_deprecation_for_versions_less_than( - consumer_import_package, - package_info.package_name, - package_info.minimum_fully_supported_version, - recommended_version=package_info.recommended_version, - ) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/_python_version_support.py b/notification-service/venv/Lib/site-packages/google/api_core/_python_version_support.py deleted file mode 100644 index 66782bf..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/_python_version_support.py +++ /dev/null @@ -1,276 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Code to check Python versions supported by Google Cloud Client Libraries.""" - -import datetime -import enum -import functools -import logging -import warnings -import sys -import textwrap -from typing import Any, List, NamedTuple, Optional, Dict, Tuple - - -_LOGGER = logging.getLogger(__name__) - - -class PythonVersionStatus(enum.Enum): - """Support status of a Python version in this client library artifact release. - - "Support", in this context, means that this release of a client library - artifact is configured to run on the currently configured version of - Python. - """ - - PYTHON_VERSION_STATUS_UNSPECIFIED = "PYTHON_VERSION_STATUS_UNSPECIFIED" - - PYTHON_VERSION_SUPPORTED = "PYTHON_VERSION_SUPPORTED" - """This Python version is fully supported, so the artifact running on this - version will have all features and bug fixes.""" - - PYTHON_VERSION_DEPRECATED = "PYTHON_VERSION_DEPRECATED" - """This Python version is still supported, but support will end within a - year. At that time, there will be no more releases for this artifact - running under this Python version.""" - - PYTHON_VERSION_EOL = "PYTHON_VERSION_EOL" - """This Python version has reached its end of life in the Python community - (see https://devguide.python.org/versions/), and this artifact will cease - supporting this Python version within the next few releases.""" - - PYTHON_VERSION_UNSUPPORTED = "PYTHON_VERSION_UNSUPPORTED" - """This release of the client library artifact may not be the latest, since - current releases no longer support this Python version.""" - - -class VersionInfo(NamedTuple): - """Hold release and support date information for a Python version.""" - - version: str - python_beta: Optional[datetime.date] - python_start: datetime.date - python_eol: datetime.date - gapic_start: Optional[datetime.date] = None # unused - gapic_deprecation: Optional[datetime.date] = None - gapic_end: Optional[datetime.date] = None - dep_unpatchable_cve: Optional[datetime.date] = None # unused - - -PYTHON_VERSIONS: List[VersionInfo] = [ - # Refer to https://devguide.python.org/versions/ and the PEPs linked therefrom. - VersionInfo( - version="3.9", - python_beta=datetime.date(2020, 5, 18), - python_start=datetime.date(2020, 10, 5), - python_eol=datetime.date(2025, 10, 5), - gapic_end=datetime.date(2025, 10, 5) + datetime.timedelta(days=90), - ), - VersionInfo( - version="3.10", - python_beta=datetime.date(2021, 5, 3), - python_start=datetime.date(2021, 10, 4), - python_eol=datetime.date(2026, 10, 4), # TODO: specify day when announced - ), - VersionInfo( - version="3.11", - python_beta=datetime.date(2022, 5, 8), - python_start=datetime.date(2022, 10, 24), - python_eol=datetime.date(2027, 10, 24), # TODO: specify day when announced - ), - VersionInfo( - version="3.12", - python_beta=datetime.date(2023, 5, 22), - python_start=datetime.date(2023, 10, 2), - python_eol=datetime.date(2028, 10, 2), # TODO: specify day when announced - ), - VersionInfo( - version="3.13", - python_beta=datetime.date(2024, 5, 8), - python_start=datetime.date(2024, 10, 7), - python_eol=datetime.date(2029, 10, 7), # TODO: specify day when announced - ), - VersionInfo( - version="3.14", - python_beta=datetime.date(2025, 5, 7), - python_start=datetime.date(2025, 10, 7), - python_eol=datetime.date(2030, 10, 7), # TODO: specify day when announced - ), -] - -PYTHON_VERSION_INFO: Dict[Tuple[int, int], VersionInfo] = {} -for info in PYTHON_VERSIONS: - major, minor = map(int, info.version.split(".")) - PYTHON_VERSION_INFO[(major, minor)] = info - - -LOWEST_TRACKED_VERSION = min(PYTHON_VERSION_INFO.keys()) -_FAKE_PAST_DATE = datetime.date.min + datetime.timedelta(days=900) -_FAKE_PAST_VERSION = VersionInfo( - version="0.0", - python_beta=_FAKE_PAST_DATE, - python_start=_FAKE_PAST_DATE, - python_eol=_FAKE_PAST_DATE, -) -_FAKE_FUTURE_DATE = datetime.date.max - datetime.timedelta(days=900) -_FAKE_FUTURE_VERSION = VersionInfo( - version="999.0", - python_beta=_FAKE_FUTURE_DATE, - python_start=_FAKE_FUTURE_DATE, - python_eol=_FAKE_FUTURE_DATE, -) -DEPRECATION_WARNING_PERIOD = datetime.timedelta(days=365) -EOL_GRACE_PERIOD = datetime.timedelta(weeks=1) - - -def _flatten_message(text: str) -> str: - """Dedent a multi-line string and flatten it into a single line.""" - return " ".join(textwrap.dedent(text).strip().split()) - - -# TODO(https://github.com/googleapis/python-api-core/issues/835): -# Remove once we no longer support Python 3.9. -# `importlib.metadata.packages_distributions()` is only supported in Python 3.10 and newer -# https://docs.python.org/3/library/importlib.metadata.html#importlib.metadata.packages_distributions -if sys.version_info < (3, 10): - - def _get_pypi_package_name(module_name): # pragma: NO COVER - """Determine the PyPI package name for a given module name.""" - return None - -else: - from importlib import metadata - - @functools.cache - def _cached_packages_distributions(): - return metadata.packages_distributions() - - def _get_pypi_package_name(module_name): - """Determine the PyPI package name for a given module name.""" - try: - module_to_distributions = _cached_packages_distributions() - - if module_name in module_to_distributions: # pragma: NO COVER - return module_to_distributions[module_name][0] - except Exception as e: # pragma: NO COVER - _LOGGER.info( - "An error occurred while determining PyPI package name for %s: %s", - module_name, - e, - ) - - return None - - -def _get_distribution_and_import_packages(import_package: str) -> Tuple[str, Any]: - """Return a pretty string with distribution & import package names.""" - distribution_package = _get_pypi_package_name(import_package) - dependency_distribution_and_import_packages = ( - f"package {distribution_package} ({import_package})" - if distribution_package - else import_package - ) - return dependency_distribution_and_import_packages, distribution_package - - -def check_python_version( - package: str = "this package", today: Optional[datetime.date] = None -) -> PythonVersionStatus: - """Check the running Python version and issue a support warning if needed. - - Args: - today: The date to check against. Defaults to the current date. - - Returns: - The support status of the current Python version. - """ - today = today or datetime.date.today() - - python_version = sys.version_info - version_tuple = (python_version.major, python_version.minor) - py_version_str = sys.version.split()[0] - - version_info = PYTHON_VERSION_INFO.get(version_tuple) - - if not version_info: - if version_tuple < LOWEST_TRACKED_VERSION: - version_info = _FAKE_PAST_VERSION - else: - version_info = _FAKE_FUTURE_VERSION - - gapic_deprecation = version_info.gapic_deprecation or ( - version_info.python_eol - DEPRECATION_WARNING_PERIOD - ) - gapic_end = version_info.gapic_end or (version_info.python_eol + EOL_GRACE_PERIOD) - - def min_python(date: datetime.date) -> str: - """Find the minimum supported Python version for a given date.""" - for version, info in sorted(PYTHON_VERSION_INFO.items()): - if info.python_start <= date < info.python_eol: - return f"{version[0]}.{version[1]}" - return "at a currently supported version [https://devguide.python.org/versions]" - - # Resolve the pretty package label lazily so we avoid any work on - # the happy path (supported Python version, no warning needed). - def get_package_label(): - label, _ = _get_distribution_and_import_packages(package) - return label - - if gapic_end < today: - package_label = get_package_label() - message = _flatten_message( - f""" - You are using a non-supported Python version ({py_version_str}). - Google will not post any further updates to {package_label} - supporting this Python version. Please upgrade to the latest Python - version, or at least Python {min_python(today)}, and then update - {package_label}. - """ - ) - warnings.warn(message, FutureWarning) - return PythonVersionStatus.PYTHON_VERSION_UNSUPPORTED - - eol_date = version_info.python_eol + EOL_GRACE_PERIOD - if eol_date <= today <= gapic_end: - package_label = get_package_label() - message = _flatten_message( - f""" - You are using a Python version ({py_version_str}) - past its end of life. Google will update {package_label} - with critical bug fixes on a best-effort basis, but not - with any other fixes or features. Please upgrade - to the latest Python version, or at least Python - {min_python(today)}, and then update {package_label}. - """ - ) - warnings.warn(message, FutureWarning) - return PythonVersionStatus.PYTHON_VERSION_EOL - - if gapic_deprecation <= today <= gapic_end: - package_label = get_package_label() - message = _flatten_message( - f""" - You are using a Python version ({py_version_str}) which Google will - stop supporting in new releases of {package_label} once it reaches - its end of life ({version_info.python_eol}). Please upgrade to the - latest Python version, or at least Python - {min_python(version_info.python_eol)}, to continue receiving updates - for {package_label} past that date. - """ - ) - warnings.warn(message, FutureWarning) - return PythonVersionStatus.PYTHON_VERSION_DEPRECATED - - return PythonVersionStatus.PYTHON_VERSION_SUPPORTED diff --git a/notification-service/venv/Lib/site-packages/google/api_core/_rest_streaming_base.py b/notification-service/venv/Lib/site-packages/google/api_core/_rest_streaming_base.py deleted file mode 100644 index 3bc87a9..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/_rest_streaming_base.py +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Helpers for server-side streaming in REST.""" - -from collections import deque -import string -from typing import Deque, Union -import types - -import proto -import google.protobuf.message -from google.protobuf.json_format import Parse - - -class BaseResponseIterator: - """Base Iterator over REST API responses. This class should not be used directly. - - Args: - response_message_cls (Union[proto.Message, google.protobuf.message.Message]): A response - class expected to be returned from an API. - - Raises: - ValueError: If `response_message_cls` is not a subclass of `proto.Message` or `google.protobuf.message.Message`. - """ - - def __init__( - self, - response_message_cls: Union[proto.Message, google.protobuf.message.Message], - ): - self._response_message_cls = response_message_cls - # Contains a list of JSON responses ready to be sent to user. - self._ready_objs: Deque[str] = deque() - # Current JSON response being built. - self._obj = "" - # Keeps track of the nesting level within a JSON object. - self._level = 0 - # Keeps track whether HTTP response is currently sending values - # inside of a string value. - self._in_string = False - # Whether an escape symbol "\" was encountered. - self._escape_next = False - - self._grab = types.MethodType(self._create_grab(), self) - - def _process_chunk(self, chunk: str): - if self._level == 0: - if chunk[0] != "[": - raise ValueError( - "Can only parse array of JSON objects, instead got %s" % chunk - ) - for char in chunk: - if char == "{": - if self._level == 1: - # Level 1 corresponds to the outermost JSON object - # (i.e. the one we care about). - self._obj = "" - if not self._in_string: - self._level += 1 - self._obj += char - elif char == "}": - self._obj += char - if not self._in_string: - self._level -= 1 - if not self._in_string and self._level == 1: - self._ready_objs.append(self._obj) - elif char == '"': - # Helps to deal with an escaped quotes inside of a string. - if not self._escape_next: - self._in_string = not self._in_string - self._obj += char - elif char in string.whitespace: - if self._in_string: - self._obj += char - elif char == "[": - if self._level == 0: - self._level += 1 - else: - self._obj += char - elif char == "]": - if self._level == 1: - self._level -= 1 - else: - self._obj += char - else: - self._obj += char - self._escape_next = not self._escape_next if char == "\\" else False - - def _create_grab(self): - if issubclass(self._response_message_cls, proto.Message): - - def grab(this): - return this._response_message_cls.from_json( - this._ready_objs.popleft(), ignore_unknown_fields=True - ) - - return grab - elif issubclass(self._response_message_cls, google.protobuf.message.Message): - - def grab(this): - return Parse(this._ready_objs.popleft(), this._response_message_cls()) - - return grab - else: - raise ValueError( - "Response message class must be a subclass of proto.Message or google.protobuf.message.Message." - ) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/bidi.py b/notification-service/venv/Lib/site-packages/google/api_core/bidi.py deleted file mode 100644 index 7f45c2a..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/bidi.py +++ /dev/null @@ -1,735 +0,0 @@ -# Copyright 2017, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Helpers for synchronous bidirectional streaming RPCs.""" - -import collections -import datetime -import logging -import queue as queue_module -import threading -import time - -from google.api_core import exceptions -from google.api_core.bidi_base import BidiRpcBase - -_LOGGER = logging.getLogger(__name__) -_BIDIRECTIONAL_CONSUMER_NAME = "Thread-ConsumeBidirectionalStream" - - -class _RequestQueueGenerator(object): - """A helper for sending requests to a gRPC stream from a Queue. - - This generator takes requests off a given queue and yields them to gRPC. - - This helper is useful when you have an indeterminate, indefinite, or - otherwise open-ended set of requests to send through a request-streaming - (or bidirectional) RPC. - - - Example:: - - requests = request_queue_generator(q) - call = stub.StreamingRequest(iter(requests)) - requests.call = call - - for response in call: - print(response) - q.put(...) - - - Args: - queue (queue_module.Queue): The request queue. - period (float): The number of seconds to wait for items from the queue - before checking if the RPC is cancelled. In practice, this - determines the maximum amount of time the request consumption - thread will live after the RPC is cancelled. - initial_request (Union[protobuf.Message, - Callable[None, protobuf.Message]]): The initial request to - yield. This is done independently of the request queue to allow fo - easily restarting streams that require some initial configuration - request. - """ - - def __init__(self, queue, period=1, initial_request=None): - self._queue = queue - self._period = period - self._initial_request = initial_request - self.call = None - - def _is_active(self): - # Note: there is a possibility that this starts *before* the call - # property is set. So we have to check if self.call is set before - # seeing if it's active. We need to return True if self.call is None. - # See https://github.com/googleapis/python-api-core/issues/560. - return self.call is None or self.call.is_active() - - def __iter__(self): - # The reason this is necessary is because gRPC takes an iterator as the - # request for request-streaming RPCs. gRPC consumes this iterator in - # another thread to allow it to block while generating requests for - # the stream. However, if the generator blocks indefinitely gRPC will - # not be able to clean up the thread as it'll be blocked on - # `next(iterator)` and not be able to check the channel status to stop - # iterating. This helper mitigates that by waiting on the queue with - # a timeout and checking the RPC state before yielding. - # - # Finally, it allows for retrying without swapping queues because if - # it does pull an item off the queue when the RPC is inactive, it'll - # immediately put it back and then exit. This is necessary because - # yielding the item in this case will cause gRPC to discard it. In - # practice, this means that the order of messages is not guaranteed. - # If such a thing is necessary it would be easy to use a priority - # queue. - # - # Note that it is possible to accomplish this behavior without - # "spinning" (using a queue timeout). One possible way would be to use - # more threads to multiplex the grpc end event with the queue, another - # possible way is to use selectors and a custom event/queue object. - # Both of these approaches are significant from an engineering - # perspective for small benefit - the CPU consumed by spinning is - # pretty minuscule. - - if self._initial_request is not None: - if callable(self._initial_request): - yield self._initial_request() - else: - yield self._initial_request - - while True: - try: - item = self._queue.get(timeout=self._period) - except queue_module.Empty: - if not self._is_active(): - _LOGGER.debug( - "Empty queue and inactive call, exiting request " "generator." - ) - return - else: - # call is still active, keep waiting for queue items. - continue - - # The consumer explicitly sent "None", indicating that the request - # should end. - if item is None: - _LOGGER.debug("Cleanly exiting request generator.") - return - - if not self._is_active(): - # We have an item, but the call is closed. We should put the - # item back on the queue so that the next call can consume it. - self._queue.put(item) - _LOGGER.debug( - "Inactive call, replacing item on queue and exiting " - "request generator." - ) - return - - yield item - - -class _Throttle(object): - """A context manager limiting the total entries in a sliding time window. - - If more than ``access_limit`` attempts are made to enter the context manager - instance in the last ``time window`` interval, the exceeding requests block - until enough time elapses. - - The context manager instances are thread-safe and can be shared between - multiple threads. If multiple requests are blocked and waiting to enter, - the exact order in which they are allowed to proceed is not determined. - - Example:: - - max_three_per_second = _Throttle( - access_limit=3, time_window=datetime.timedelta(seconds=1) - ) - - for i in range(5): - with max_three_per_second as time_waited: - print("{}: Waited {} seconds to enter".format(i, time_waited)) - - Args: - access_limit (int): the maximum number of entries allowed in the time window - time_window (datetime.timedelta): the width of the sliding time window - """ - - def __init__(self, access_limit, time_window): - if access_limit < 1: - raise ValueError("access_limit argument must be positive") - - if time_window <= datetime.timedelta(0): - raise ValueError("time_window argument must be a positive timedelta") - - self._time_window = time_window - self._access_limit = access_limit - self._past_entries = collections.deque( - maxlen=access_limit - ) # least recent first - self._entry_lock = threading.Lock() - - def __enter__(self): - with self._entry_lock: - cutoff_time = datetime.datetime.now() - self._time_window - - # drop the entries that are too old, as they are no longer relevant - while self._past_entries and self._past_entries[0] < cutoff_time: - self._past_entries.popleft() - - if len(self._past_entries) < self._access_limit: - self._past_entries.append(datetime.datetime.now()) - return 0.0 # no waiting was needed - - to_wait = (self._past_entries[0] - cutoff_time).total_seconds() - time.sleep(to_wait) - - self._past_entries.append(datetime.datetime.now()) - return to_wait - - def __exit__(self, *_): - pass - - def __repr__(self): - return "{}(access_limit={}, time_window={})".format( - self.__class__.__name__, self._access_limit, repr(self._time_window) - ) - - -class BidiRpc(BidiRpcBase): - """A helper for consuming a bi-directional streaming RPC. - - This maps gRPC's built-in interface which uses a request iterator and a - response iterator into a socket-like :func:`send` and :func:`recv`. This - is a more useful pattern for long-running or asymmetric streams (streams - where there is not a direct correlation between the requests and - responses). - - Example:: - - initial_request = example_pb2.StreamingRpcRequest( - setting='example') - rpc = BidiRpc( - stub.StreamingRpc, - initial_request=initial_request, - metadata=[('name', 'value')] - ) - - rpc.open() - - while rpc.is_active(): - print(rpc.recv()) - rpc.send(example_pb2.StreamingRpcRequest( - data='example')) - - rpc.close() - - This does *not* retry the stream on errors. See :class:`ResumableBidiRpc`. - - Args: - start_rpc (grpc.StreamStreamMultiCallable): The gRPC method used to - start the RPC. - initial_request (Union[protobuf.Message, - Callable[None, protobuf.Message]]): The initial request to - yield. This is useful if an initial request is needed to start the - stream. - metadata (Sequence[Tuple(str, str)]): RPC metadata to include in - the request. - """ - - def _create_queue(self): - """Create a queue for requests.""" - return queue_module.Queue() - - def open(self): - """Opens the stream.""" - if self.is_active: - raise ValueError("Cannot open an already open stream.") - - request_generator = _RequestQueueGenerator( - self._request_queue, initial_request=self._initial_request - ) - try: - call = self._start_rpc(iter(request_generator), metadata=self._rpc_metadata) - except exceptions.GoogleAPICallError as exc: - # The original `grpc.RpcError` (which is usually also a `grpc.Call`) is - # available from the ``response`` property on the mapped exception. - self._on_call_done(exc.response) - raise - - request_generator.call = call - - # TODO: api_core should expose the future interface for wrapped - # callables as well. - if hasattr(call, "_wrapped"): # pragma: NO COVER - call._wrapped.add_done_callback(self._on_call_done) - else: - call.add_done_callback(self._on_call_done) - - self._request_generator = request_generator - self.call = call - - def close(self): - """Closes the stream.""" - if self.call is not None: - self.call.cancel() - - # Put None in request queue to signal termination. - self._request_queue.put(None) - self._request_generator = None - self._initial_request = None - self._callbacks = [] - # Don't set self.call to None. Keep it around so that send/recv can - # raise the error. - - def send(self, request): - """Queue a message to be sent on the stream. - - Send is non-blocking. - - If the underlying RPC has been closed, this will raise. - - Args: - request (protobuf.Message): The request to send. - """ - if self.call is None: - raise ValueError("Cannot send on an RPC stream that has never been opened.") - - # Don't use self.is_active(), as ResumableBidiRpc will overload it - # to mean something semantically different. - if self.call.is_active(): - self._request_queue.put(request) - else: - # calling next should cause the call to raise. - next(self.call) - - def recv(self): - """Wait for a message to be returned from the stream. - - Recv is blocking. - - If the underlying RPC has been closed, this will raise. - - Returns: - protobuf.Message: The received message. - """ - if self.call is None: - raise ValueError("Cannot recv on an RPC stream that has never been opened.") - - return next(self.call) - - @property - def is_active(self): - """True if this stream is currently open and active.""" - return self.call is not None and self.call.is_active() - - -def _never_terminate(future_or_error): - """By default, no errors cause BiDi termination.""" - return False - - -class ResumableBidiRpc(BidiRpc): - """A :class:`BidiRpc` that can automatically resume the stream on errors. - - It uses the ``should_recover`` arg to determine if it should re-establish - the stream on error. - - Example:: - - def should_recover(exc): - return ( - isinstance(exc, grpc.RpcError) and - exc.code() == grpc.StatusCode.UNAVAILABLE) - - initial_request = example_pb2.StreamingRpcRequest( - setting='example') - - metadata = [('header_name', 'value')] - - rpc = ResumableBidiRpc( - stub.StreamingRpc, - should_recover=should_recover, - initial_request=initial_request, - metadata=metadata - ) - - rpc.open() - - while rpc.is_active(): - print(rpc.recv()) - rpc.send(example_pb2.StreamingRpcRequest( - data='example')) - - Args: - start_rpc (grpc.StreamStreamMultiCallable): The gRPC method used to - start the RPC. - initial_request (Union[protobuf.Message, - Callable[None, protobuf.Message]]): The initial request to - yield. This is useful if an initial request is needed to start the - stream. - should_recover (Callable[[Exception], bool]): A function that returns - True if the stream should be recovered. This will be called - whenever an error is encountered on the stream. - should_terminate (Callable[[Exception], bool]): A function that returns - True if the stream should be terminated. This will be called - whenever an error is encountered on the stream. - metadata Sequence[Tuple(str, str)]: RPC metadata to include in - the request. - throttle_reopen (bool): If ``True``, throttling will be applied to - stream reopen calls. Defaults to ``False``. - """ - - def __init__( - self, - start_rpc, - should_recover, - should_terminate=_never_terminate, - initial_request=None, - metadata=None, - throttle_reopen=False, - ): - super(ResumableBidiRpc, self).__init__(start_rpc, initial_request, metadata) - self._should_recover = should_recover - self._should_terminate = should_terminate - self._operational_lock = threading.RLock() - self._finalized = False - self._finalize_lock = threading.Lock() - - if throttle_reopen: - self._reopen_throttle = _Throttle( - access_limit=5, time_window=datetime.timedelta(seconds=10) - ) - else: - self._reopen_throttle = None - - def _finalize(self, result): - with self._finalize_lock: - if self._finalized: - return - - for callback in self._callbacks: - callback(result) - - self._finalized = True - - def _on_call_done(self, future): - # Unlike the base class, we only execute the callbacks on a terminal - # error, not for errors that we can recover from. Note that grpc's - # "future" here is also a grpc.RpcError. - with self._operational_lock: - if self._should_terminate(future): - self._finalize(future) - elif not self._should_recover(future): - self._finalize(future) - else: - _LOGGER.debug("Re-opening stream from gRPC callback.") - self._reopen() - - def _reopen(self): - with self._operational_lock: - # Another thread already managed to re-open this stream. - if self.call is not None and self.call.is_active(): - _LOGGER.debug("Stream was already re-established.") - return - - self.call = None - # Request generator should exit cleanly since the RPC its bound to - # has exited. - self._request_generator = None - - # Note: we do not currently do any sort of backoff here. The - # assumption is that re-establishing the stream under normal - # circumstances will happen in intervals greater than 60s. - # However, it is possible in a degenerative case that the server - # closes the stream rapidly which would lead to thrashing here, - # but hopefully in those cases the server would return a non- - # retryable error. - - try: - if self._reopen_throttle: - with self._reopen_throttle: - self.open() - else: - self.open() - # If re-opening or re-calling the method fails for any reason, - # consider it a terminal error and finalize the stream. - except Exception as exc: - _LOGGER.debug("Failed to re-open stream due to %s", exc) - self._finalize(exc) - raise - - _LOGGER.info("Re-established stream") - - def _recoverable(self, method, *args, **kwargs): - """Wraps a method to recover the stream and retry on error. - - If a retryable error occurs while making the call, then the stream will - be re-opened and the method will be retried. This happens indefinitely - so long as the error is a retryable one. If an error occurs while - re-opening the stream, then this method will raise immediately and - trigger finalization of this object. - - Args: - method (Callable[..., Any]): The method to call. - args: The args to pass to the method. - kwargs: The kwargs to pass to the method. - """ - while True: - try: - return method(*args, **kwargs) - - except Exception as exc: - with self._operational_lock: - _LOGGER.debug("Call to retryable %r caused %s.", method, exc) - - if self._should_terminate(exc): - self.close() - _LOGGER.debug("Terminating %r due to %s.", method, exc) - self._finalize(exc) - break - - if not self._should_recover(exc): - self.close() - _LOGGER.debug("Not retrying %r due to %s.", method, exc) - self._finalize(exc) - raise exc - - _LOGGER.debug("Re-opening stream from retryable %r.", method) - self._reopen() - - def _send(self, request): - # Grab a reference to the RPC call. Because another thread (notably - # the gRPC error thread) can modify self.call (by invoking reopen), - # we should ensure our reference can not change underneath us. - # If self.call is modified (such as replaced with a new RPC call) then - # this will use the "old" RPC, which should result in the same - # exception passed into gRPC's error handler being raised here, which - # will be handled by the usual error handling in retryable. - with self._operational_lock: - call = self.call - - if call is None: - raise ValueError("Cannot send on an RPC that has never been opened.") - - # Don't use self.is_active(), as ResumableBidiRpc will overload it - # to mean something semantically different. - if call.is_active(): - self._request_queue.put(request) - pass - else: - # calling next should cause the call to raise. - next(call) - - def send(self, request): - return self._recoverable(self._send, request) - - def _recv(self): - with self._operational_lock: - call = self.call - - if call is None: - raise ValueError("Cannot recv on an RPC that has never been opened.") - - return next(call) - - def recv(self): - return self._recoverable(self._recv) - - def close(self): - self._finalize(None) - super(ResumableBidiRpc, self).close() - - @property - def is_active(self): - """bool: True if this stream is currently open and active.""" - # Use the operational lock. It's entirely possible for something - # to check the active state *while* the RPC is being retried. - # Also, use finalized to track the actual terminal state here. - # This is because if the stream is re-established by the gRPC thread - # it's technically possible to check this between when gRPC marks the - # RPC as inactive and when gRPC executes our callback that re-opens - # the stream. - with self._operational_lock: - return self.call is not None and not self._finalized - - -class BackgroundConsumer(object): - """A bi-directional stream consumer that runs in a separate thread. - - This maps the consumption of a stream into a callback-based model. It also - provides :func:`pause` and :func:`resume` to allow for flow-control. - - Example:: - - def should_recover(exc): - return ( - isinstance(exc, grpc.RpcError) and - exc.code() == grpc.StatusCode.UNAVAILABLE) - - initial_request = example_pb2.StreamingRpcRequest( - setting='example') - - rpc = ResumeableBidiRpc( - stub.StreamingRpc, - initial_request=initial_request, - should_recover=should_recover) - - def on_response(response): - print(response) - - consumer = BackgroundConsumer(rpc, on_response) - consumer.start() - - Note that error handling *must* be done by using the provided - ``bidi_rpc``'s ``add_done_callback``. This helper will automatically exit - whenever the RPC itself exits and will not provide any error details. - - Args: - bidi_rpc (BidiRpc): The RPC to consume. Should not have been - ``open()``ed yet. - on_response (Callable[[protobuf.Message], None]): The callback to - be called for every response on the stream. - on_fatal_exception (Callable[[Exception], None]): The callback to - be called on fatal errors during consumption. Default None. - """ - - def __init__(self, bidi_rpc, on_response, on_fatal_exception=None): - self._bidi_rpc = bidi_rpc - self._on_response = on_response - self._paused = False - self._on_fatal_exception = on_fatal_exception - self._wake = threading.Condition() - self._thread = None - self._operational_lock = threading.Lock() - - def _on_call_done(self, future): - # Resume the thread if it's paused, this prevents blocking forever - # when the RPC has terminated. - self.resume() - - def _thread_main(self, ready): - try: - ready.set() - self._bidi_rpc.add_done_callback(self._on_call_done) - self._bidi_rpc.open() - - while self._bidi_rpc.is_active: - # Do not allow the paused status to change at all during this - # section. There is a condition where we could be resumed - # between checking if we are paused and calling wake.wait(), - # which means that we will miss the notification to wake up - # (oops!) and wait for a notification that will never come. - # Keeping the lock throughout avoids that. - # In the future, we could use `Condition.wait_for` if we drop - # Python 2.7. - # See: https://github.com/googleapis/python-api-core/issues/211 - with self._wake: - while self._paused: - _LOGGER.debug("paused, waiting for waking.") - self._wake.wait() - _LOGGER.debug("woken.") - - _LOGGER.debug("waiting for recv.") - response = self._bidi_rpc.recv() - _LOGGER.debug("recved response.") - if self._on_response is not None: - self._on_response(response) - - except exceptions.GoogleAPICallError as exc: - _LOGGER.debug( - "%s caught error %s and will exit. Generally this is due to " - "the RPC itself being cancelled and the error will be " - "surfaced to the calling code.", - _BIDIRECTIONAL_CONSUMER_NAME, - exc, - exc_info=True, - ) - if self._on_fatal_exception is not None: - self._on_fatal_exception(exc) - - except Exception as exc: - _LOGGER.exception( - "%s caught unexpected exception %s and will exit.", - _BIDIRECTIONAL_CONSUMER_NAME, - exc, - ) - if self._on_fatal_exception is not None: - self._on_fatal_exception(exc) - - _LOGGER.info("%s exiting", _BIDIRECTIONAL_CONSUMER_NAME) - - def start(self): - """Start the background thread and begin consuming the thread.""" - with self._operational_lock: - ready = threading.Event() - thread = threading.Thread( - name=_BIDIRECTIONAL_CONSUMER_NAME, - target=self._thread_main, - args=(ready,), - daemon=True, - ) - thread.start() - # Other parts of the code rely on `thread.is_alive` which - # isn't sufficient to know if a thread is active, just that it may - # soon be active. This can cause races. Further protect - # against races by using a ready event and wait on it to be set. - ready.wait() - self._thread = thread - _LOGGER.debug("Started helper thread %s", thread.name) - - def stop(self): - """Stop consuming the stream and shutdown the background thread. - - NOTE: Cannot be called within `_thread_main`, since it is not - possible to join a thread to itself. - """ - with self._operational_lock: - self._bidi_rpc.close() - - if self._thread is not None: - # Resume the thread to wake it up in case it is sleeping. - self.resume() - # The daemonized thread may itself block, so don't wait - # for it longer than a second. - self._thread.join(1.0) - if self._thread.is_alive(): # pragma: NO COVER - _LOGGER.warning("Background thread did not exit.") - - self._thread = None - self._on_response = None - self._on_fatal_exception = None - - @property - def is_active(self): - """bool: True if the background thread is active.""" - return self._thread is not None and self._thread.is_alive() - - def pause(self): - """Pauses the response stream. - - This does *not* pause the request stream. - """ - with self._wake: - self._paused = True - - def resume(self): - """Resumes the response stream.""" - with self._wake: - self._paused = False - self._wake.notify_all() - - @property - def is_paused(self): - """bool: True if the response stream is paused.""" - return self._paused diff --git a/notification-service/venv/Lib/site-packages/google/api_core/bidi_async.py b/notification-service/venv/Lib/site-packages/google/api_core/bidi_async.py deleted file mode 100644 index 3770f69..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/bidi_async.py +++ /dev/null @@ -1,244 +0,0 @@ -# Copyright 2025, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Asynchronous bi-directional streaming RPC helpers.""" - -import asyncio -import logging -from typing import Callable, Optional, Union - -from grpc import aio - -from google.api_core import exceptions -from google.api_core.bidi_base import BidiRpcBase - -from google.protobuf.message import Message as ProtobufMessage - - -_LOGGER = logging.getLogger(__name__) - - -class _AsyncRequestQueueGenerator: - """_AsyncRequestQueueGenerator is a helper class for sending asynchronous - requests to a gRPC stream from a Queue. - - This generator takes asynchronous requests off a given `asyncio.Queue` and - yields them to gRPC. - - It's useful when you have an indeterminate, indefinite, or otherwise - open-ended set of requests to send through a request-streaming (or - bidirectional) RPC. - - Example:: - - requests = _AsyncRequestQueueGenerator(q) - call = await stub.StreamingRequest(requests) - requests.call = call - - async for response in call: - print(response) - await q.put(...) - - Args: - queue (asyncio.Queue): The request queue. - initial_request (Union[ProtobufMessage, - Callable[[], ProtobufMessage]]): The initial request to - yield. This is done independently of the request queue to allow for - easily restarting streams that require some initial configuration - request. - """ - - def __init__( - self, - queue: asyncio.Queue, - initial_request: Optional[ - Union[ProtobufMessage, Callable[[], ProtobufMessage]] - ] = None, - ) -> None: - self._queue = queue - self._initial_request = initial_request - self.call: Optional[aio.Call] = None - - def _is_active(self) -> bool: - """Returns true if the call is not set or not completed.""" - # Note: there is a possibility that this starts *before* the call - # property is set. So we have to check if self.call is set before - # seeing if it's active. We need to return True if self.call is None. - # See https://github.com/googleapis/python-api-core/issues/560. - return self.call is None or not self.call.done() - - async def __aiter__(self): - # The reason this is necessary is because it lets the user have - # control on when they would want to send requests proto messages - # instead of sending all of them initially. - # - # This is achieved via asynchronous queue (asyncio.Queue), - # gRPC awaits until there's a message in the queue. - # - # Finally, it allows for retrying without swapping queues because if - # it does pull an item off the queue when the RPC is inactive, it'll - # immediately put it back and then exit. This is necessary because - # yielding the item in this case will cause gRPC to discard it. In - # practice, this means that the order of messages is not guaranteed. - # If preserving order is necessary it would be easy to use a priority - # queue. - if self._initial_request is not None: - if callable(self._initial_request): - yield self._initial_request() - else: - yield self._initial_request - - while True: - item = await self._queue.get() - - # The consumer explicitly sent "None", indicating that the request - # should end. - if item is None: - _LOGGER.debug("Cleanly exiting request generator.") - return - - if not self._is_active(): - # We have an item, but the call is closed. We should put the - # item back on the queue so that the next call can consume it. - await self._queue.put(item) - _LOGGER.debug( - "Inactive call, replacing item on queue and exiting " - "request generator." - ) - return - - yield item - - -class AsyncBidiRpc(BidiRpcBase): - """A helper for consuming a async bi-directional streaming RPC. - - This maps gRPC's built-in interface which uses a request iterator and a - response iterator into a socket-like :func:`send` and :func:`recv`. This - is a more useful pattern for long-running or asymmetric streams (streams - where there is not a direct correlation between the requests and - responses). - - Example:: - - initial_request = example_pb2.StreamingRpcRequest( - setting='example') - rpc = AsyncBidiRpc( - stub.StreamingRpc, - initial_request=initial_request, - metadata=[('name', 'value')] - ) - - await rpc.open() - - while rpc.is_active: - print(await rpc.recv()) - await rpc.send(example_pb2.StreamingRpcRequest( - data='example')) - - await rpc.close() - - This does *not* retry the stream on errors. - - Args: - start_rpc (grpc.aio.StreamStreamMultiCallable): The gRPC method used to - start the RPC. - initial_request (Union[ProtobufMessage, - Callable[[], ProtobufMessage]]): The initial request to - yield. This is useful if an initial request is needed to start the - stream. - metadata (Sequence[Tuple(str, str)]): RPC metadata to include in - the request. - """ - - def _create_queue(self) -> asyncio.Queue: - """Create a queue for requests.""" - return asyncio.Queue() - - async def open(self) -> None: - """Opens the stream.""" - if self.is_active: - raise ValueError("Cannot open an already open stream.") - - request_generator = _AsyncRequestQueueGenerator( - self._request_queue, initial_request=self._initial_request - ) - try: - call = await self._start_rpc(request_generator, metadata=self._rpc_metadata) - except exceptions.GoogleAPICallError as exc: - # The original `grpc.aio.AioRpcError` (which is usually also a - # `grpc.aio.Call`) is available from the ``response`` property on - # the mapped exception. - self._on_call_done(exc.response) - raise - - request_generator.call = call - - # TODO: api_core should expose the future interface for wrapped - # callables as well. - if hasattr(call, "_wrapped"): # pragma: NO COVER - call._wrapped.add_done_callback(self._on_call_done) - else: - call.add_done_callback(self._on_call_done) - - self._request_generator = request_generator - self.call = call - - async def close(self) -> None: - """Closes the stream.""" - if self.call is not None: - self.call.cancel() - - # Put None in request queue to signal termination. - await self._request_queue.put(None) - self._request_generator = None - self._initial_request = None - self._callbacks = [] - # Don't set self.call to None. Keep it around so that send/recv can - # raise the error. - - async def send(self, request: ProtobufMessage) -> None: - """Queue a message to be sent on the stream. - - If the underlying RPC has been closed, this will raise. - - Args: - request (ProtobufMessage): The request to send. - """ - if self.call is None: - raise ValueError("Cannot send on an RPC stream that has never been opened.") - - if not self.call.done(): - await self._request_queue.put(request) - else: - # calling read should cause the call to raise. - await self.call.read() - - async def recv(self) -> ProtobufMessage: - """Wait for a message to be returned from the stream. - - If the underlying RPC has been closed, this will raise. - - Returns: - ProtobufMessage: The received message. - """ - if self.call is None: - raise ValueError("Cannot recv on an RPC stream that has never been opened.") - - return await self.call.read() - - @property - def is_active(self) -> bool: - """Whether the stream is currently open and active.""" - return self.call is not None and not self.call.done() diff --git a/notification-service/venv/Lib/site-packages/google/api_core/bidi_base.py b/notification-service/venv/Lib/site-packages/google/api_core/bidi_base.py deleted file mode 100644 index 9288fda..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/bidi_base.py +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright 2025, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# You may obtain a copy of the License at -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Base class for bi-directional streaming RPC helpers.""" - - -class BidiRpcBase: - """A base class for consuming a bi-directional streaming RPC. - - This maps gRPC's built-in interface which uses a request iterator and a - response iterator into a socket-like :func:`send` and :func:`recv`. This - is a more useful pattern for long-running or asymmetric streams (streams - where there is not a direct correlation between the requests and - responses). - - This does *not* retry the stream on errors. - - Args: - start_rpc (Union[grpc.StreamStreamMultiCallable, - grpc.aio.StreamStreamMultiCallable]): The gRPC method used - to start the RPC. - initial_request (Union[protobuf.Message, - Callable[[], protobuf.Message]]): The initial request to - yield. This is useful if an initial request is needed to start the - stream. - metadata (Sequence[Tuple(str, str)]): RPC metadata to include in - the request. - """ - - def __init__(self, start_rpc, initial_request=None, metadata=None): - self._start_rpc = start_rpc - self._initial_request = initial_request - self._rpc_metadata = metadata - self._request_queue = self._create_queue() - self._request_generator = None - self._callbacks = [] - self.call = None - - def _create_queue(self): - """Create a queue for requests.""" - raise NotImplementedError("`_create_queue` is not implemented.") - - def add_done_callback(self, callback): - """Adds a callback that will be called when the RPC terminates. - - This occurs when the RPC errors or is successfully terminated. - - Args: - callback (Union[Callable[[grpc.Future], None], Callable[[Any], None]]): - The callback to execute after gRPC call completed (success or - failure). - - For sync streaming gRPC: Callable[[grpc.Future], None] - - For async streaming gRPC: Callable[[Any], None] - """ - self._callbacks.append(callback) - - def _on_call_done(self, future): - # This occurs when the RPC errors or is successfully terminated. - # Note that grpc's "future" here can also be a grpc.RpcError. - # See note in https://github.com/grpc/grpc/issues/10885#issuecomment-302651331 - # that `grpc.RpcError` is also `grpc.Call`. - # for asynchronous gRPC call it would be `grpc.aio.AioRpcError` - - # Note: sync callbacks can be limiting for async code, because you can't - # await anything in a sync callback. - for callback in self._callbacks: - callback(future) - - @property - def is_active(self): - """True if the gRPC call is not done yet.""" - raise NotImplementedError("`is_active` is not implemented.") - - @property - def pending_requests(self): - """Estimate of the number of queued requests.""" - return self._request_queue.qsize() diff --git a/notification-service/venv/Lib/site-packages/google/api_core/client_info.py b/notification-service/venv/Lib/site-packages/google/api_core/client_info.py deleted file mode 100644 index f0678d2..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/client_info.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Helpers for providing client information. - -Client information is used to send information about the calling client, -such as the library and Python version, to API services. -""" - -import platform -from typing import Union - -from google.api_core import version as api_core_version - -_PY_VERSION = platform.python_version() -_API_CORE_VERSION = api_core_version.__version__ - -_GRPC_VERSION: Union[str, None] - -try: - import grpc - - _GRPC_VERSION = grpc.__version__ -except ImportError: # pragma: NO COVER - _GRPC_VERSION = None - - -class ClientInfo(object): - """Client information used to generate a user-agent for API calls. - - This user-agent information is sent along with API calls to allow the - receiving service to do analytics on which versions of Python and Google - libraries are being used. - - Args: - python_version (str): The Python interpreter version, for example, - ``'3.9.6'``. - grpc_version (Optional[str]): The gRPC library version. - api_core_version (str): The google-api-core library version. - gapic_version (Optional[str]): The version of gapic-generated client - library, if the library was generated by gapic. - client_library_version (Optional[str]): The version of the client - library, generally used if the client library was not generated - by gapic or if additional functionality was built on top of - a gapic client library. - user_agent (Optional[str]): Prefix to the user agent header. This is - used to supply information such as application name or partner tool. - Recommended format: ``application-or-tool-ID/major.minor.version``. - rest_version (Optional[str]): A string with labeled versions of the - dependencies used for REST transport. - protobuf_runtime_version (Optional[str]): The protobuf runtime version. - """ - - def __init__( - self, - python_version=_PY_VERSION, - grpc_version=_GRPC_VERSION, - api_core_version=_API_CORE_VERSION, - gapic_version=None, - client_library_version=None, - user_agent=None, - rest_version=None, - protobuf_runtime_version=None, - ): - self.python_version = python_version - self.grpc_version = grpc_version - self.api_core_version = api_core_version - self.gapic_version = gapic_version - self.client_library_version = client_library_version - self.user_agent = user_agent - self.rest_version = rest_version - self.protobuf_runtime_version = protobuf_runtime_version - - def to_user_agent(self): - """Returns the user-agent string for this client info.""" - - # Note: the order here is important as the internal metrics system - # expects these items to be in specific locations. - ua = "" - - if self.user_agent is not None: - ua += "{user_agent} " - - ua += "gl-python/{python_version} " - - if self.grpc_version is not None: - ua += "grpc/{grpc_version} " - - if self.rest_version is not None: - ua += "rest/{rest_version} " - - ua += "gax/{api_core_version} " - - if self.gapic_version is not None: - ua += "gapic/{gapic_version} " - - if self.client_library_version is not None: - ua += "gccl/{client_library_version} " - - if self.protobuf_runtime_version is not None: - ua += "pb/{protobuf_runtime_version} " - - return ua.format(**self.__dict__).strip() diff --git a/notification-service/venv/Lib/site-packages/google/api_core/client_logging.py b/notification-service/venv/Lib/site-packages/google/api_core/client_logging.py deleted file mode 100644 index 837e3e0..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/client_logging.py +++ /dev/null @@ -1,144 +0,0 @@ -import logging -import json -import os - -from typing import List, Optional - -_LOGGING_INITIALIZED = False -_BASE_LOGGER_NAME = "google" - -# Fields to be included in the StructuredLogFormatter. -# -# TODO(https://github.com/googleapis/python-api-core/issues/761): Update this list to support additional logging fields. -_recognized_logging_fields = [ - "httpRequest", - "rpcName", - "serviceName", - "credentialsType", - "credentialsInfo", - "universeDomain", - "request", - "response", - "metadata", - "retryAttempt", - "httpResponse", -] # Additional fields to be Logged. - - -def logger_configured(logger) -> bool: - """Determines whether `logger` has non-default configuration - - Args: - logger: The logger to check. - - Returns: - bool: Whether the logger has any non-default configuration. - """ - return ( - logger.handlers != [] or logger.level != logging.NOTSET or not logger.propagate - ) - - -def initialize_logging(): - """Initializes "google" loggers, partly based on the environment variable - - Initializes the "google" logger and any loggers (at the "google" - level or lower) specified by the environment variable - GOOGLE_SDK_PYTHON_LOGGING_SCOPE, as long as none of these loggers - were previously configured. If any such loggers (including the - "google" logger) are initialized, they are set to NOT propagate - log events up to their parent loggers. - - This initialization is executed only once, and hence the - environment variable is only processed the first time this - function is called. - """ - global _LOGGING_INITIALIZED - if _LOGGING_INITIALIZED: - return - scopes = os.getenv("GOOGLE_SDK_PYTHON_LOGGING_SCOPE", "") - setup_logging(scopes) - _LOGGING_INITIALIZED = True - - -def parse_logging_scopes(scopes: Optional[str] = None) -> List[str]: - """Returns a list of logger names. - - Splits the single string of comma-separated logger names into a list of individual logger name strings. - - Args: - scopes: The name of a single logger. (In the future, this will be a comma-separated list of multiple loggers.) - - Returns: - A list of all the logger names in scopes. - """ - if not scopes: - return [] - # TODO(https://github.com/googleapis/python-api-core/issues/759): check if the namespace is a valid namespace. - # TODO(b/380481951): Support logging multiple scopes. - # TODO(b/380483756): Raise or log a warning for an invalid scope. - namespaces = [scopes] - return namespaces - - -def configure_defaults(logger): - """Configures `logger` to emit structured info to stdout.""" - if not logger_configured(logger): - console_handler = logging.StreamHandler() - logger.setLevel("DEBUG") - logger.propagate = False - formatter = StructuredLogFormatter() - console_handler.setFormatter(formatter) - logger.addHandler(console_handler) - - -def setup_logging(scopes: str = ""): - """Sets up logging for the specified `scopes`. - - If the loggers specified in `scopes` have not been previously - configured, this will configure them to emit structured log - entries to stdout, and to not propagate their log events to their - parent loggers. Additionally, if the "google" logger (whether it - was specified in `scopes` or not) was not previously configured, - it will also configure it to not propagate log events to the root - logger. - - Args: - scopes: The name of a single logger. (In the future, this will be a comma-separated list of multiple loggers.) - - """ - - # only returns valid logger scopes (namespaces) - # this list has at most one element. - logger_names = parse_logging_scopes(scopes) - - for namespace in logger_names: - # This will either create a module level logger or get the reference of the base logger instantiated above. - logger = logging.getLogger(namespace) - - # Configure default settings. - configure_defaults(logger) - - # disable log propagation at base logger level to the root logger only if a base logger is not already configured via code changes. - base_logger = logging.getLogger(_BASE_LOGGER_NAME) - if not logger_configured(base_logger): - base_logger.propagate = False - - -# TODO(https://github.com/googleapis/python-api-core/issues/763): Expand documentation. -class StructuredLogFormatter(logging.Formatter): - # TODO(https://github.com/googleapis/python-api-core/issues/761): ensure that additional fields such as - # function name, file name, and line no. appear in a log output. - def format(self, record: logging.LogRecord): - log_obj = { - "timestamp": self.formatTime(record), - "severity": record.levelname, - "name": record.name, - "message": record.getMessage(), - } - - for field_name in _recognized_logging_fields: - value = getattr(record, field_name, None) - if value is not None: - log_obj[field_name] = value - return json.dumps(log_obj) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/client_options.py b/notification-service/venv/Lib/site-packages/google/api_core/client_options.py deleted file mode 100644 index 30bff48..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/client_options.py +++ /dev/null @@ -1,160 +0,0 @@ -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Client options class. - -Client options provide a consistent interface for user options to be defined -across clients. - -You can pass a client options object to a client. - -.. code-block:: python - - from google.api_core.client_options import ClientOptions - from google.cloud.vision_v1 import ImageAnnotatorClient - - def get_client_cert(): - # code to load client certificate and private key. - return client_cert_bytes, client_private_key_bytes - - options = ClientOptions(api_endpoint="foo.googleapis.com", - client_cert_source=get_client_cert) - - client = ImageAnnotatorClient(client_options=options) - -You can also pass a mapping object. - -.. code-block:: python - - from google.cloud.vision_v1 import ImageAnnotatorClient - - client = ImageAnnotatorClient( - client_options={ - "api_endpoint": "foo.googleapis.com", - "client_cert_source" : get_client_cert - }) - - -""" - -from typing import Callable, Mapping, Optional, Sequence, Tuple -import warnings - -from google.api_core import general_helpers - - -class ClientOptions(object): - """Client Options used to set options on clients. - - Args: - api_endpoint (Optional[str]): The desired API endpoint, e.g., - compute.googleapis.com - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A callback - which returns client certificate bytes and private key bytes both in - PEM format. ``client_cert_source`` and ``client_encrypted_cert_source`` - are mutually exclusive. - client_encrypted_cert_source (Optional[Callable[[], Tuple[str, str, bytes]]]): - A callback which returns client certificate file path, encrypted - private key file path, and the passphrase bytes.``client_cert_source`` - and ``client_encrypted_cert_source`` are mutually exclusive. - quota_project_id (Optional[str]): A project name that a client's - quota belongs to. - credentials_file (Optional[str]): Deprecated. A path to a file storing credentials. - ``credentials_file` and ``api_key`` are mutually exclusive. This argument will be - removed in the next major version of `google-api-core`. - - .. warning:: - Important: If you accept a credential configuration (credential JSON/File/Stream) - from an external source for authentication to Google Cloud Platform, you must - validate it before providing it to any Google API or client library. Providing an - unvalidated credential configuration to Google APIs or libraries can compromise - the security of your systems and data. For more information, refer to - `Validate credential configurations from external sources`_. - - .. _Validate credential configurations from external sources: - - https://cloud.google.com/docs/authentication/external/externally-sourced-credentials - scopes (Optional[Sequence[str]]): OAuth access token override scopes. - api_key (Optional[str]): Google API key. ``credentials_file`` and - ``api_key`` are mutually exclusive. - api_audience (Optional[str]): The intended audience for the API calls - to the service that will be set when using certain 3rd party - authentication flows. Audience is typically a resource identifier. - If not set, the service endpoint value will be used as a default. - An example of a valid ``api_audience`` is: "https://language.googleapis.com". - universe_domain (Optional[str]): The desired universe domain. This must match - the one in credentials. If not set, the default universe domain is - `googleapis.com`. If both `api_endpoint` and `universe_domain` are set, - then `api_endpoint` is used as the service endpoint. If `api_endpoint` is - not specified, the format will be `{service}.{universe_domain}`. - - Raises: - ValueError: If both ``client_cert_source`` and ``client_encrypted_cert_source`` - are provided, or both ``credentials_file`` and ``api_key`` are provided. - """ - - def __init__( - self, - api_endpoint: Optional[str] = None, - client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, - client_encrypted_cert_source: Optional[ - Callable[[], Tuple[str, str, bytes]] - ] = None, - quota_project_id: Optional[str] = None, - credentials_file: Optional[str] = None, - scopes: Optional[Sequence[str]] = None, - api_key: Optional[str] = None, - api_audience: Optional[str] = None, - universe_domain: Optional[str] = None, - ): - if credentials_file is not None: - warnings.warn(general_helpers._CREDENTIALS_FILE_WARNING, DeprecationWarning) - - if client_cert_source and client_encrypted_cert_source: - raise ValueError( - "client_cert_source and client_encrypted_cert_source are mutually exclusive" - ) - if api_key and credentials_file: - raise ValueError("api_key and credentials_file are mutually exclusive") - self.api_endpoint = api_endpoint - self.client_cert_source = client_cert_source - self.client_encrypted_cert_source = client_encrypted_cert_source - self.quota_project_id = quota_project_id - self.credentials_file = credentials_file - self.scopes = scopes - self.api_key = api_key - self.api_audience = api_audience - self.universe_domain = universe_domain - - def __repr__(self) -> str: - return "ClientOptions: " + repr(self.__dict__) - - -def from_dict(options: Mapping[str, object]) -> ClientOptions: - """Construct a client options object from a mapping object. - - Args: - options (collections.abc.Mapping): A mapping object with client options. - See the docstring for ClientOptions for details on valid arguments. - """ - - client_options = ClientOptions() - - for key, value in options.items(): - if hasattr(client_options, key): - setattr(client_options, key, value) - else: - raise ValueError("ClientOptions does not accept an option '" + key + "'") - - return client_options diff --git a/notification-service/venv/Lib/site-packages/google/api_core/datetime_helpers.py b/notification-service/venv/Lib/site-packages/google/api_core/datetime_helpers.py deleted file mode 100644 index c379230..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/datetime_helpers.py +++ /dev/null @@ -1,298 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Helpers for :mod:`datetime`.""" - -import calendar -import datetime -import re - -from google.protobuf import timestamp_pb2 - - -_UTC_EPOCH = datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc) -_RFC3339_MICROS = "%Y-%m-%dT%H:%M:%S.%fZ" -_RFC3339_NO_FRACTION = "%Y-%m-%dT%H:%M:%S" -# datetime.strptime cannot handle nanosecond precision: parse w/ regex -_RFC3339_NANOS = re.compile( - r""" - (?P - \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2} # YYYY-MM-DDTHH:MM:SS - ) - ( # Optional decimal part - \. # decimal point - (?P\d{1,9}) # nanoseconds, maybe truncated - )? - Z # Zulu -""", - re.VERBOSE, -) - - -def utcnow(): - """A :meth:`datetime.datetime.utcnow()` alias to allow mocking in tests.""" - return datetime.datetime.now(tz=datetime.timezone.utc).replace(tzinfo=None) - - -def to_milliseconds(value): - """Convert a zone-aware datetime to milliseconds since the unix epoch. - - Args: - value (datetime.datetime): The datetime to covert. - - Returns: - int: Milliseconds since the unix epoch. - """ - micros = to_microseconds(value) - return micros // 1000 - - -def from_microseconds(value): - """Convert timestamp in microseconds since the unix epoch to datetime. - - Args: - value (float): The timestamp to convert, in microseconds. - - Returns: - datetime.datetime: The datetime object equivalent to the timestamp in - UTC. - """ - return _UTC_EPOCH + datetime.timedelta(microseconds=value) - - -def to_microseconds(value): - """Convert a datetime to microseconds since the unix epoch. - - Args: - value (datetime.datetime): The datetime to covert. - - Returns: - int: Microseconds since the unix epoch. - """ - if not value.tzinfo: - value = value.replace(tzinfo=datetime.timezone.utc) - # Regardless of what timezone is on the value, convert it to UTC. - value = value.astimezone(datetime.timezone.utc) - # Convert the datetime to a microsecond timestamp. - return int(calendar.timegm(value.timetuple()) * 1e6) + value.microsecond - - -def from_iso8601_date(value): - """Convert a ISO8601 date string to a date. - - Args: - value (str): The ISO8601 date string. - - Returns: - datetime.date: A date equivalent to the date string. - """ - return datetime.datetime.strptime(value, "%Y-%m-%d").date() - - -def from_iso8601_time(value): - """Convert a zoneless ISO8601 time string to a time. - - Args: - value (str): The ISO8601 time string. - - Returns: - datetime.time: A time equivalent to the time string. - """ - return datetime.datetime.strptime(value, "%H:%M:%S").time() - - -def from_rfc3339(value): - """Convert an RFC3339-format timestamp to a native datetime. - - Supported formats include those without fractional seconds, or with - any fraction up to nanosecond precision. - - .. note:: - Python datetimes do not support nanosecond precision; this function - therefore truncates such values to microseconds. - - Args: - value (str): The RFC3339 string to convert. - - Returns: - datetime.datetime: The datetime object equivalent to the timestamp - in UTC. - - Raises: - ValueError: If the timestamp does not match the RFC3339 - regular expression. - """ - with_nanos = _RFC3339_NANOS.match(value) - - if with_nanos is None: - raise ValueError( - "Timestamp: {!r}, does not match pattern: {!r}".format( - value, _RFC3339_NANOS.pattern - ) - ) - - bare_seconds = datetime.datetime.strptime( - with_nanos.group("no_fraction"), _RFC3339_NO_FRACTION - ) - fraction = with_nanos.group("nanos") - - if fraction is None: - micros = 0 - else: - scale = 9 - len(fraction) - nanos = int(fraction) * (10**scale) - micros = nanos // 1000 - - return bare_seconds.replace(microsecond=micros, tzinfo=datetime.timezone.utc) - - -from_rfc3339_nanos = from_rfc3339 # from_rfc3339_nanos method was deprecated. - - -def to_rfc3339(value, ignore_zone=True): - """Convert a datetime to an RFC3339 timestamp string. - - Args: - value (datetime.datetime): - The datetime object to be converted to a string. - ignore_zone (bool): If True, then the timezone (if any) of the - datetime object is ignored and the datetime is treated as UTC. - - Returns: - str: The RFC3339 formatted string representing the datetime. - """ - if not ignore_zone and value.tzinfo is not None: - # Convert to UTC and remove the time zone info. - value = value.replace(tzinfo=None) - value.utcoffset() - - return value.strftime(_RFC3339_MICROS) - - -class DatetimeWithNanoseconds(datetime.datetime): - """Track nanosecond in addition to normal datetime attrs. - - Nanosecond can be passed only as a keyword argument. - """ - - __slots__ = ("_nanosecond",) - - # pylint: disable=arguments-differ - def __new__(cls, *args, **kw): - nanos = kw.pop("nanosecond", 0) - if nanos > 0: - if "microsecond" in kw: - raise TypeError("Specify only one of 'microsecond' or 'nanosecond'") - kw["microsecond"] = nanos // 1000 - inst = datetime.datetime.__new__(cls, *args, **kw) - inst._nanosecond = nanos or 0 - return inst - - # pylint: disable=arguments-differ - - @property - def nanosecond(self): - """Read-only: nanosecond precision.""" - return self._nanosecond - - def rfc3339(self): - """Return an RFC3339-compliant timestamp. - - Returns: - (str): Timestamp string according to RFC3339 spec. - """ - if self._nanosecond == 0: - return to_rfc3339(self) - nanos = str(self._nanosecond).rjust(9, "0").rstrip("0") - return "{}.{}Z".format(self.strftime(_RFC3339_NO_FRACTION), nanos) - - @classmethod - def from_rfc3339(cls, stamp): - """Parse RFC3339-compliant timestamp, preserving nanoseconds. - - Args: - stamp (str): RFC3339 stamp, with up to nanosecond precision - - Returns: - :class:`DatetimeWithNanoseconds`: - an instance matching the timestamp string - - Raises: - ValueError: if `stamp` does not match the expected format - """ - with_nanos = _RFC3339_NANOS.match(stamp) - if with_nanos is None: - raise ValueError( - "Timestamp: {}, does not match pattern: {}".format( - stamp, _RFC3339_NANOS.pattern - ) - ) - bare = datetime.datetime.strptime( - with_nanos.group("no_fraction"), _RFC3339_NO_FRACTION - ) - fraction = with_nanos.group("nanos") - if fraction is None: - nanos = 0 - else: - scale = 9 - len(fraction) - nanos = int(fraction) * (10**scale) - return cls( - bare.year, - bare.month, - bare.day, - bare.hour, - bare.minute, - bare.second, - nanosecond=nanos, - tzinfo=datetime.timezone.utc, - ) - - def timestamp_pb(self): - """Return a timestamp message. - - Returns: - (:class:`~google.protobuf.timestamp_pb2.Timestamp`): Timestamp message - """ - inst = ( - self - if self.tzinfo is not None - else self.replace(tzinfo=datetime.timezone.utc) - ) - delta = inst - _UTC_EPOCH - seconds = int(delta.total_seconds()) - nanos = self._nanosecond or self.microsecond * 1000 - return timestamp_pb2.Timestamp(seconds=seconds, nanos=nanos) - - @classmethod - def from_timestamp_pb(cls, stamp): - """Parse RFC3339-compliant timestamp, preserving nanoseconds. - - Args: - stamp (:class:`~google.protobuf.timestamp_pb2.Timestamp`): timestamp message - - Returns: - :class:`DatetimeWithNanoseconds`: - an instance matching the timestamp message - """ - microseconds = int(stamp.seconds * 1e6) - bare = from_microseconds(microseconds) - return cls( - bare.year, - bare.month, - bare.day, - bare.hour, - bare.minute, - bare.second, - nanosecond=stamp.nanos, - tzinfo=datetime.timezone.utc, - ) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/exceptions.py b/notification-service/venv/Lib/site-packages/google/api_core/exceptions.py deleted file mode 100644 index e17fa1d..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/exceptions.py +++ /dev/null @@ -1,669 +0,0 @@ -# Copyright 2014 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Exceptions raised by Google API core & clients. - -This module provides base classes for all errors raised by libraries based -on :mod:`google.api_core`, including both HTTP and gRPC clients. -""" - -from __future__ import absolute_import -from __future__ import unicode_literals - -import http.client -from typing import Optional, Dict -import warnings - -from google.rpc import error_details_pb2 - - -def _warn_could_not_import_grpcio_status(): - warnings.warn( - "Please install grpcio-status to obtain helpful grpc error messages.", - ImportWarning, - ) # pragma: NO COVER - - -try: - import grpc - - try: - from grpc_status import rpc_status - except ImportError: # pragma: NO COVER - _warn_could_not_import_grpcio_status() - rpc_status = None -except ImportError: # pragma: NO COVER - grpc = None - -# Lookup tables for mapping exceptions from HTTP and gRPC transports. -# Populated by _GoogleAPICallErrorMeta -_HTTP_CODE_TO_EXCEPTION: Dict[int, Exception] = {} -_GRPC_CODE_TO_EXCEPTION: Dict[int, Exception] = {} - -# Additional lookup table to map integer status codes to grpc status code -# grpc does not currently support initializing enums from ints -# i.e., grpc.StatusCode(5) raises an error -_INT_TO_GRPC_CODE = {} -if grpc is not None: # pragma: no branch - for x in grpc.StatusCode: - _INT_TO_GRPC_CODE[x.value[0]] = x - - -class GoogleAPIError(Exception): - """Base class for all exceptions raised by Google API Clients.""" - - pass - - -class DuplicateCredentialArgs(GoogleAPIError): - """Raised when multiple credentials are passed.""" - - pass - - -class RetryError(GoogleAPIError): - """Raised when a function has exhausted all of its available retries. - - Args: - message (str): The exception message. - cause (Exception): The last exception raised when retrying the - function. - """ - - def __init__(self, message, cause): - super(RetryError, self).__init__(message) - self.message = message - self._cause = cause - - @property - def cause(self): - """The last exception raised when retrying the function.""" - return self._cause - - def __str__(self): - return "{}, last exception: {}".format(self.message, self.cause) - - -class _GoogleAPICallErrorMeta(type): - """Metaclass for registering GoogleAPICallError subclasses.""" - - def __new__(mcs, name, bases, class_dict): - cls = type.__new__(mcs, name, bases, class_dict) - if cls.code is not None: - _HTTP_CODE_TO_EXCEPTION.setdefault(cls.code, cls) - if cls.grpc_status_code is not None: - _GRPC_CODE_TO_EXCEPTION.setdefault(cls.grpc_status_code, cls) - return cls - - -class GoogleAPICallError(GoogleAPIError, metaclass=_GoogleAPICallErrorMeta): - """Base class for exceptions raised by calling API methods. - - Args: - message (str): The exception message. - errors (Sequence[Any]): An optional list of error details. - details (Sequence[Any]): An optional list of objects defined in google.rpc.error_details. - response (Union[requests.Request, grpc.Call]): The response or - gRPC call metadata. - error_info (Union[error_details_pb2.ErrorInfo, None]): An optional object containing error info - (google.rpc.error_details.ErrorInfo). - """ - - code: Optional[int] = None - """Optional[int]: The HTTP status code associated with this error. - - This may be ``None`` if the exception does not have a direct mapping - to an HTTP error. - - See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html - """ - - grpc_status_code: Optional["grpc.StatusCode"] = None - """Optional[grpc.StatusCode]: The gRPC status code associated with this - error. - - This may be ``None`` if the exception does not match up to a gRPC error. - """ - - def __init__(self, message, errors=(), details=(), response=None, error_info=None): - super(GoogleAPICallError, self).__init__(message) - self.message = message - """str: The exception message.""" - self._errors = errors - self._details = details - self._response = response - self._error_info = error_info - - def __str__(self): - error_msg = "{} {}".format(self.code, self.message) - if self.details: - error_msg = "{} {}".format(error_msg, self.details) - # Note: This else condition can be removed once proposal A from - # b/284179390 is implemented. - else: - if self.errors: - errors = [ - f"{error.code}: {error.message}" - for error in self.errors - if hasattr(error, "code") and hasattr(error, "message") - ] - if errors: - error_msg = "{} {}".format(error_msg, "\n".join(errors)) - return error_msg - - @property - def reason(self): - """The reason of the error. - - Reference: - https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112 - - Returns: - Union[str, None]: An optional string containing reason of the error. - """ - return self._error_info.reason if self._error_info else None - - @property - def domain(self): - """The logical grouping to which the "reason" belongs. - - Reference: - https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112 - - Returns: - Union[str, None]: An optional string containing a logical grouping to which the "reason" belongs. - """ - return self._error_info.domain if self._error_info else None - - @property - def metadata(self): - """Additional structured details about this error. - - Reference: - https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112 - - Returns: - Union[Dict[str, str], None]: An optional object containing structured details about the error. - """ - return self._error_info.metadata if self._error_info else None - - @property - def errors(self): - """Detailed error information. - - Returns: - Sequence[Any]: A list of additional error details. - """ - return list(self._errors) - - @property - def details(self): - """Information contained in google.rpc.status.details. - - Reference: - https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto - https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto - - Returns: - Sequence[Any]: A list of structured objects from error_details.proto - """ - return list(self._details) - - @property - def response(self): - """Optional[Union[requests.Request, grpc.Call]]: The response or - gRPC call metadata.""" - return self._response - - -class Redirection(GoogleAPICallError): - """Base class for for all redirection (HTTP 3xx) responses.""" - - -class MovedPermanently(Redirection): - """Exception mapping a ``301 Moved Permanently`` response.""" - - code = http.client.MOVED_PERMANENTLY - - -class NotModified(Redirection): - """Exception mapping a ``304 Not Modified`` response.""" - - code = http.client.NOT_MODIFIED - - -class TemporaryRedirect(Redirection): - """Exception mapping a ``307 Temporary Redirect`` response.""" - - code = http.client.TEMPORARY_REDIRECT - - -class ResumeIncomplete(Redirection): - """Exception mapping a ``308 Resume Incomplete`` response. - - .. note:: :attr:`http.client.PERMANENT_REDIRECT` is ``308``, but Google - APIs differ in their use of this status code. - """ - - code = 308 - - -class ClientError(GoogleAPICallError): - """Base class for all client error (HTTP 4xx) responses.""" - - -class BadRequest(ClientError): - """Exception mapping a ``400 Bad Request`` response.""" - - code = http.client.BAD_REQUEST - - -class InvalidArgument(BadRequest): - """Exception mapping a :attr:`grpc.StatusCode.INVALID_ARGUMENT` error.""" - - grpc_status_code = grpc.StatusCode.INVALID_ARGUMENT if grpc is not None else None - - -class FailedPrecondition(BadRequest): - """Exception mapping a :attr:`grpc.StatusCode.FAILED_PRECONDITION` - error.""" - - grpc_status_code = grpc.StatusCode.FAILED_PRECONDITION if grpc is not None else None - - -class OutOfRange(BadRequest): - """Exception mapping a :attr:`grpc.StatusCode.OUT_OF_RANGE` error.""" - - grpc_status_code = grpc.StatusCode.OUT_OF_RANGE if grpc is not None else None - - -class Unauthorized(ClientError): - """Exception mapping a ``401 Unauthorized`` response.""" - - code = http.client.UNAUTHORIZED - - -class Unauthenticated(Unauthorized): - """Exception mapping a :attr:`grpc.StatusCode.UNAUTHENTICATED` error.""" - - grpc_status_code = grpc.StatusCode.UNAUTHENTICATED if grpc is not None else None - - -class Forbidden(ClientError): - """Exception mapping a ``403 Forbidden`` response.""" - - code = http.client.FORBIDDEN - - -class PermissionDenied(Forbidden): - """Exception mapping a :attr:`grpc.StatusCode.PERMISSION_DENIED` error.""" - - grpc_status_code = grpc.StatusCode.PERMISSION_DENIED if grpc is not None else None - - -class NotFound(ClientError): - """Exception mapping a ``404 Not Found`` response or a - :attr:`grpc.StatusCode.NOT_FOUND` error.""" - - code = http.client.NOT_FOUND - grpc_status_code = grpc.StatusCode.NOT_FOUND if grpc is not None else None - - -class MethodNotAllowed(ClientError): - """Exception mapping a ``405 Method Not Allowed`` response.""" - - code = http.client.METHOD_NOT_ALLOWED - - -class Conflict(ClientError): - """Exception mapping a ``409 Conflict`` response.""" - - code = http.client.CONFLICT - - -class AlreadyExists(Conflict): - """Exception mapping a :attr:`grpc.StatusCode.ALREADY_EXISTS` error.""" - - grpc_status_code = grpc.StatusCode.ALREADY_EXISTS if grpc is not None else None - - -class Aborted(Conflict): - """Exception mapping a :attr:`grpc.StatusCode.ABORTED` error.""" - - grpc_status_code = grpc.StatusCode.ABORTED if grpc is not None else None - - -class LengthRequired(ClientError): - """Exception mapping a ``411 Length Required`` response.""" - - code = http.client.LENGTH_REQUIRED - - -class PreconditionFailed(ClientError): - """Exception mapping a ``412 Precondition Failed`` response.""" - - code = http.client.PRECONDITION_FAILED - - -class RequestRangeNotSatisfiable(ClientError): - """Exception mapping a ``416 Request Range Not Satisfiable`` response.""" - - code = http.client.REQUESTED_RANGE_NOT_SATISFIABLE - - -class TooManyRequests(ClientError): - """Exception mapping a ``429 Too Many Requests`` response.""" - - code = http.client.TOO_MANY_REQUESTS - - -class ResourceExhausted(TooManyRequests): - """Exception mapping a :attr:`grpc.StatusCode.RESOURCE_EXHAUSTED` error.""" - - grpc_status_code = grpc.StatusCode.RESOURCE_EXHAUSTED if grpc is not None else None - - -class Cancelled(ClientError): - """Exception mapping a :attr:`grpc.StatusCode.CANCELLED` error.""" - - # This maps to HTTP status code 499. See - # https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto - code = 499 - grpc_status_code = grpc.StatusCode.CANCELLED if grpc is not None else None - - -class ServerError(GoogleAPICallError): - """Base for 5xx responses.""" - - -class InternalServerError(ServerError): - """Exception mapping a ``500 Internal Server Error`` response. or a - :attr:`grpc.StatusCode.INTERNAL` error.""" - - code = http.client.INTERNAL_SERVER_ERROR - grpc_status_code = grpc.StatusCode.INTERNAL if grpc is not None else None - - -class Unknown(ServerError): - """Exception mapping a :attr:`grpc.StatusCode.UNKNOWN` error.""" - - grpc_status_code = grpc.StatusCode.UNKNOWN if grpc is not None else None - - -class DataLoss(ServerError): - """Exception mapping a :attr:`grpc.StatusCode.DATA_LOSS` error.""" - - grpc_status_code = grpc.StatusCode.DATA_LOSS if grpc is not None else None - - -class MethodNotImplemented(ServerError): - """Exception mapping a ``501 Not Implemented`` response or a - :attr:`grpc.StatusCode.UNIMPLEMENTED` error.""" - - code = http.client.NOT_IMPLEMENTED - grpc_status_code = grpc.StatusCode.UNIMPLEMENTED if grpc is not None else None - - -class BadGateway(ServerError): - """Exception mapping a ``502 Bad Gateway`` response.""" - - code = http.client.BAD_GATEWAY - - -class ServiceUnavailable(ServerError): - """Exception mapping a ``503 Service Unavailable`` response or a - :attr:`grpc.StatusCode.UNAVAILABLE` error.""" - - code = http.client.SERVICE_UNAVAILABLE - grpc_status_code = grpc.StatusCode.UNAVAILABLE if grpc is not None else None - - -class GatewayTimeout(ServerError): - """Exception mapping a ``504 Gateway Timeout`` response.""" - - code = http.client.GATEWAY_TIMEOUT - - -class DeadlineExceeded(GatewayTimeout): - """Exception mapping a :attr:`grpc.StatusCode.DEADLINE_EXCEEDED` error.""" - - grpc_status_code = grpc.StatusCode.DEADLINE_EXCEEDED if grpc is not None else None - - -class AsyncRestUnsupportedParameterError(NotImplementedError): - """Raised when an unsupported parameter is configured against async rest transport.""" - - pass - - -def exception_class_for_http_status(status_code): - """Return the exception class for a specific HTTP status code. - - Args: - status_code (int): The HTTP status code. - - Returns: - :func:`type`: the appropriate subclass of :class:`GoogleAPICallError`. - """ - return _HTTP_CODE_TO_EXCEPTION.get(status_code, GoogleAPICallError) - - -def from_http_status(status_code, message, **kwargs): - """Create a :class:`GoogleAPICallError` from an HTTP status code. - - Args: - status_code (int): The HTTP status code. - message (str): The exception message. - kwargs: Additional arguments passed to the :class:`GoogleAPICallError` - constructor. - - Returns: - GoogleAPICallError: An instance of the appropriate subclass of - :class:`GoogleAPICallError`. - """ - error_class = exception_class_for_http_status(status_code) - error = error_class(message, **kwargs) - - if error.code is None: - error.code = status_code - - return error - - -def _format_rest_error_message(error, method, url): - method = method.upper() if method else None - message = "{method} {url}: {error}".format( - method=method, - url=url, - error=error, - ) - return message - - -# NOTE: We're moving away from `from_http_status` because it expects an aiohttp response compared -# to `format_http_response_error` which expects a more abstract response from google.auth and is -# compatible with both sync and async response types. -# TODO(https://github.com/googleapis/python-api-core/issues/691): Add type hint for response. -def format_http_response_error( - response, method: str, url: str, payload: Optional[Dict] = None -): - """Create a :class:`GoogleAPICallError` from a google auth rest response. - - Args: - response Union[google.auth.transport.Response, google.auth.aio.transport.Response]: The HTTP response. - method Optional(str): The HTTP request method. - url Optional(str): The HTTP request url. - payload Optional(dict): The HTTP response payload. If not passed in, it is read from response for a response type of google.auth.transport.Response. - - Returns: - GoogleAPICallError: An instance of the appropriate subclass of - :class:`GoogleAPICallError`, with the message and errors populated - from the response. - """ - payload = {} if not payload else payload - error_message = payload.get("error", {}).get("message", "unknown error") - errors = payload.get("error", {}).get("errors", ()) - # In JSON, details are already formatted in developer-friendly way. - details = payload.get("error", {}).get("details", ()) - error_info_list = list( - filter( - lambda detail: detail.get("@type", "") - == "type.googleapis.com/google.rpc.ErrorInfo", - details, - ) - ) - error_info = error_info_list[0] if error_info_list else None - message = _format_rest_error_message(error_message, method, url) - - exception = from_http_status( - response.status_code, - message, - errors=errors, - details=details, - response=response, - error_info=error_info, - ) - return exception - - -def from_http_response(response): - """Create a :class:`GoogleAPICallError` from a :class:`requests.Response`. - - Args: - response (requests.Response): The HTTP response. - - Returns: - GoogleAPICallError: An instance of the appropriate subclass of - :class:`GoogleAPICallError`, with the message and errors populated - from the response. - """ - try: - payload = response.json() - except ValueError: - payload = {"error": {"message": response.text or "unknown error"}} - return format_http_response_error( - response, response.request.method, response.request.url, payload - ) - - -def exception_class_for_grpc_status(status_code): - """Return the exception class for a specific :class:`grpc.StatusCode`. - - Args: - status_code (grpc.StatusCode): The gRPC status code. - - Returns: - :func:`type`: the appropriate subclass of :class:`GoogleAPICallError`. - """ - return _GRPC_CODE_TO_EXCEPTION.get(status_code, GoogleAPICallError) - - -def from_grpc_status(status_code, message, **kwargs): - """Create a :class:`GoogleAPICallError` from a :class:`grpc.StatusCode`. - - Args: - status_code (Union[grpc.StatusCode, int]): The gRPC status code. - message (str): The exception message. - kwargs: Additional arguments passed to the :class:`GoogleAPICallError` - constructor. - - Returns: - GoogleAPICallError: An instance of the appropriate subclass of - :class:`GoogleAPICallError`. - """ - - if isinstance(status_code, int): - status_code = _INT_TO_GRPC_CODE.get(status_code, status_code) - - error_class = exception_class_for_grpc_status(status_code) - error = error_class(message, **kwargs) - - if error.grpc_status_code is None: - error.grpc_status_code = status_code - - return error - - -def _is_informative_grpc_error(rpc_exc): - return hasattr(rpc_exc, "code") and hasattr(rpc_exc, "details") - - -def _parse_grpc_error_details(rpc_exc): - if not rpc_status: # pragma: NO COVER - _warn_could_not_import_grpcio_status() - return [], None - try: - status = rpc_status.from_call(rpc_exc) - except NotImplementedError: # workaround - return [], None - - if not status: - return [], None - - possible_errors = [ - error_details_pb2.BadRequest, - error_details_pb2.PreconditionFailure, - error_details_pb2.QuotaFailure, - error_details_pb2.ErrorInfo, - error_details_pb2.RetryInfo, - error_details_pb2.ResourceInfo, - error_details_pb2.RequestInfo, - error_details_pb2.DebugInfo, - error_details_pb2.Help, - error_details_pb2.LocalizedMessage, - ] - error_info = None - error_details = [] - for detail in status.details: - matched_detail_cls = list( - filter(lambda x: detail.Is(x.DESCRIPTOR), possible_errors) - ) - # If nothing matched, use detail directly. - if len(matched_detail_cls) == 0: - info = detail - else: - info = matched_detail_cls[0]() - detail.Unpack(info) - error_details.append(info) - if isinstance(info, error_details_pb2.ErrorInfo): - error_info = info - return error_details, error_info - - -def from_grpc_error(rpc_exc): - """Create a :class:`GoogleAPICallError` from a :class:`grpc.RpcError`. - - Args: - rpc_exc (grpc.RpcError): The gRPC error. - - Returns: - GoogleAPICallError: An instance of the appropriate subclass of - :class:`GoogleAPICallError`. - """ - # NOTE(lidiz) All gRPC error shares the parent class grpc.RpcError. - # However, check for grpc.RpcError breaks backward compatibility. - if ( - grpc is not None and isinstance(rpc_exc, grpc.Call) - ) or _is_informative_grpc_error(rpc_exc): - details, err_info = _parse_grpc_error_details(rpc_exc) - return from_grpc_status( - rpc_exc.code(), - rpc_exc.details(), - errors=(rpc_exc,), - details=details, - response=rpc_exc, - error_info=err_info, - ) - else: - return GoogleAPICallError(str(rpc_exc), errors=(rpc_exc,), response=rpc_exc) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/extended_operation.py b/notification-service/venv/Lib/site-packages/google/api_core/extended_operation.py deleted file mode 100644 index d474632..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/extended_operation.py +++ /dev/null @@ -1,225 +0,0 @@ -# Copyright 2022 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Futures for extended long-running operations returned from Google Cloud APIs. - -These futures can be used to synchronously wait for the result of a -long-running operations using :meth:`ExtendedOperation.result`: - -.. code-block:: python - - extended_operation = my_api_client.long_running_method() - - extended_operation.result() - -Or asynchronously using callbacks and :meth:`Operation.add_done_callback`: - -.. code-block:: python - - extended_operation = my_api_client.long_running_method() - - def my_callback(ex_op): - print(f"Operation {ex_op.name} completed") - - extended_operation.add_done_callback(my_callback) - -""" - -import threading - -from google.api_core import exceptions -from google.api_core.future import polling - - -class ExtendedOperation(polling.PollingFuture): - """An ExtendedOperation future for interacting with a Google API Long-Running Operation. - - Args: - extended_operation (proto.Message): The initial operation. - refresh (Callable[[], type(extended_operation)]): A callable that returns - the latest state of the operation. - cancel (Callable[[], None]): A callable that tries to cancel the operation. - polling Optional(google.api_core.retry.Retry): The configuration used - for polling. This can be used to control how often :meth:`done` - is polled. If the ``timeout`` argument to :meth:`result` is - specified it will override the ``polling.timeout`` property. - retry Optional(google.api_core.retry.Retry): DEPRECATED use ``polling`` - instead. If specified it will override ``polling`` parameter to - maintain backward compatibility. - - Note: Most long-running API methods use google.api_core.operation.Operation - This class is a wrapper for a subset of methods that use alternative - Long-Running Operation (LRO) semantics. - - Note: there is not a concrete type the extended operation must be. - It MUST have fields that correspond to the following, POSSIBLY WITH DIFFERENT NAMES: - * name: str - * status: Union[str, bool, enum.Enum] - * error_code: int - * error_message: str - """ - - def __init__( - self, - extended_operation, - refresh, - cancel, - polling=polling.DEFAULT_POLLING, - **kwargs, - ): - super().__init__(polling=polling, **kwargs) - self._extended_operation = extended_operation - self._refresh = refresh - self._cancel = cancel - # Note: the extended operation does not give a good way to indicate cancellation. - # We make do with manually tracking cancellation and checking for doneness. - self._cancelled = False - self._completion_lock = threading.Lock() - # Invoke in case the operation came back already complete. - self._handle_refreshed_operation() - - # Note: the following four properties MUST be overridden in a subclass - # if, and only if, the fields in the corresponding extended operation message - # have different names. - # - # E.g. we have an extended operation class that looks like - # - # class MyOperation(proto.Message): - # moniker = proto.Field(proto.STRING, number=1) - # status_msg = proto.Field(proto.STRING, number=2) - # optional http_error_code = proto.Field(proto.INT32, number=3) - # optional http_error_msg = proto.Field(proto.STRING, number=4) - # - # the ExtendedOperation subclass would provide property overrides that map - # to these (poorly named) fields. - @property - def name(self): - return self._extended_operation.name - - @property - def status(self): - return self._extended_operation.status - - @property - def error_code(self): - return self._extended_operation.error_code - - @property - def error_message(self): - return self._extended_operation.error_message - - def __getattr__(self, name): - return getattr(self._extended_operation, name) - - def done(self, retry=None): - self._refresh_and_update(retry) - return self._extended_operation.done - - def cancel(self): - if self.done(): - return False - - self._cancel() - self._cancelled = True - return True - - def cancelled(self): - # TODO(dovs): there is not currently a good way to determine whether the - # operation has been cancelled. - # The best we can do is manually keep track of cancellation - # and check for doneness. - if not self._cancelled: - return False - - self._refresh_and_update() - return self._extended_operation.done - - def _refresh_and_update(self, retry=None): - if not self._extended_operation.done: - self._extended_operation = ( - self._refresh(retry=retry) if retry else self._refresh() - ) - self._handle_refreshed_operation() - - def _handle_refreshed_operation(self): - with self._completion_lock: - if not self._extended_operation.done: - return - - if self.error_code and self.error_message: - # Note: `errors` can be removed once proposal A from - # b/284179390 is implemented. - errors = [] - if hasattr(self, "error") and hasattr(self.error, "errors"): - errors = self.error.errors - exception = exceptions.from_http_status( - status_code=self.error_code, - message=self.error_message, - response=self._extended_operation, - errors=errors, - ) - self.set_exception(exception) - elif self.error_code or self.error_message: - exception = exceptions.GoogleAPICallError( - f"Unexpected error {self.error_code}: {self.error_message}" - ) - self.set_exception(exception) - else: - # Extended operations have no payload. - self.set_result(None) - - @classmethod - def make(cls, refresh, cancel, extended_operation, **kwargs): - """ - Return an instantiated ExtendedOperation (or child) that wraps - * a refresh callable - * a cancel callable (can be a no-op) - * an initial result - - .. note:: - It is the caller's responsibility to set up refresh and cancel - with their correct request argument. - The reason for this is that the services that use Extended Operations - have rpcs that look something like the following: - - // service.proto - service MyLongService { - rpc StartLongTask(StartLongTaskRequest) returns (ExtendedOperation) { - option (google.cloud.operation_service) = "CustomOperationService"; - } - } - - service CustomOperationService { - rpc Get(GetOperationRequest) returns (ExtendedOperation) { - option (google.cloud.operation_polling_method) = true; - } - } - - Any info needed for the poll, e.g. a name, path params, etc. - is held in the request, which the initial client method is in a much - better position to make made because the caller made the initial request. - - TL;DR: the caller sets up closures for refresh and cancel that carry - the properly configured requests. - - Args: - refresh (Callable[Optional[Retry]][type(extended_operation)]): A callable that - returns the latest state of the operation. - cancel (Callable[][Any]): A callable that tries to cancel the operation - on a best effort basis. - extended_operation (Any): The initial response of the long running method. - See the docstring for ExtendedOperation.__init__ for requirements on - the type and fields of extended_operation - """ - return cls(extended_operation, refresh, cancel, **kwargs) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/future/__init__.py b/notification-service/venv/Lib/site-packages/google/api_core/future/__init__.py deleted file mode 100644 index 3768b2c..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/future/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2017, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Futures for dealing with asynchronous operations.""" - -from google.api_core.future.base import Future - -__all__ = ["Future"] diff --git a/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 79dc2dd..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/_helpers.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/_helpers.cpython-312.pyc deleted file mode 100644 index d2df943..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/_helpers.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/async_future.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/async_future.cpython-312.pyc deleted file mode 100644 index 6fdb7b4..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/async_future.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/base.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/base.cpython-312.pyc deleted file mode 100644 index 3a65a4b..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/base.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/polling.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/polling.cpython-312.pyc deleted file mode 100644 index ad42c1b..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/future/__pycache__/polling.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/future/_helpers.py b/notification-service/venv/Lib/site-packages/google/api_core/future/_helpers.py deleted file mode 100644 index 9e88ca9..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/future/_helpers.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2017, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Private helpers for futures.""" - -import logging -import threading - - -_LOGGER = logging.getLogger(__name__) - - -def start_daemon_thread(*args, **kwargs): - """Starts a thread and marks it as a daemon thread.""" - thread = threading.Thread(*args, **kwargs) - thread.daemon = True - thread.start() - return thread - - -def safe_invoke_callback(callback, *args, **kwargs): - """Invoke a callback, swallowing and logging any exceptions.""" - # pylint: disable=bare-except - # We intentionally want to swallow all exceptions. - try: - return callback(*args, **kwargs) - except Exception: - _LOGGER.exception("Error while executing Future callback.") diff --git a/notification-service/venv/Lib/site-packages/google/api_core/future/async_future.py b/notification-service/venv/Lib/site-packages/google/api_core/future/async_future.py deleted file mode 100644 index 325ee9c..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/future/async_future.py +++ /dev/null @@ -1,162 +0,0 @@ -# Copyright 2020, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""AsyncIO implementation of the abstract base Future class.""" - -import asyncio - -from google.api_core import exceptions -from google.api_core import retry -from google.api_core import retry_async -from google.api_core.future import base - - -class _OperationNotComplete(Exception): - """Private exception used for polling via retry.""" - - pass - - -RETRY_PREDICATE = retry.if_exception_type( - _OperationNotComplete, - exceptions.TooManyRequests, - exceptions.InternalServerError, - exceptions.BadGateway, -) -DEFAULT_RETRY = retry_async.AsyncRetry(predicate=RETRY_PREDICATE) - - -class AsyncFuture(base.Future): - """A Future that polls peer service to self-update. - - The :meth:`done` method should be implemented by subclasses. The polling - behavior will repeatedly call ``done`` until it returns True. - - .. note:: - - Privacy here is intended to prevent the final class from - overexposing, not to prevent subclasses from accessing methods. - - Args: - retry (google.api_core.retry.Retry): The retry configuration used - when polling. This can be used to control how often :meth:`done` - is polled. Regardless of the retry's ``deadline``, it will be - overridden by the ``timeout`` argument to :meth:`result`. - """ - - def __init__(self, retry=DEFAULT_RETRY): - super().__init__() - self._retry = retry - self._future = asyncio.get_event_loop().create_future() - self._background_task = None - - async def done(self, retry=DEFAULT_RETRY): - """Checks to see if the operation is complete. - - Args: - retry (google.api_core.retry.Retry): (Optional) How to retry the RPC. - - Returns: - bool: True if the operation is complete, False otherwise. - """ - # pylint: disable=redundant-returns-doc, missing-raises-doc - raise NotImplementedError() - - async def _done_or_raise(self): - """Check if the future is done and raise if it's not.""" - result = await self.done() - if not result: - raise _OperationNotComplete() - - async def running(self): - """True if the operation is currently running.""" - result = await self.done() - return not result - - async def _blocking_poll(self, timeout=None): - """Poll and await for the Future to be resolved. - - Args: - timeout (int): - How long (in seconds) to wait for the operation to complete. - If None, wait indefinitely. - """ - if self._future.done(): - return - - retry_ = self._retry.with_timeout(timeout) - - try: - await retry_(self._done_or_raise)() - except exceptions.RetryError: - raise asyncio.TimeoutError( - "Operation did not complete within the designated " "timeout." - ) - - async def result(self, timeout=None): - """Get the result of the operation. - - Args: - timeout (int): - How long (in seconds) to wait for the operation to complete. - If None, wait indefinitely. - - Returns: - google.protobuf.Message: The Operation's result. - - Raises: - google.api_core.GoogleAPICallError: If the operation errors or if - the timeout is reached before the operation completes. - """ - await self._blocking_poll(timeout=timeout) - return self._future.result() - - async def exception(self, timeout=None): - """Get the exception from the operation. - - Args: - timeout (int): How long to wait for the operation to complete. - If None, wait indefinitely. - - Returns: - Optional[google.api_core.GoogleAPICallError]: The operation's - error. - """ - await self._blocking_poll(timeout=timeout) - return self._future.exception() - - def add_done_callback(self, fn): - """Add a callback to be executed when the operation is complete. - - If the operation is completed, the callback will be scheduled onto the - event loop. Otherwise, the callback will be stored and invoked when the - future is done. - - Args: - fn (Callable[Future]): The callback to execute when the operation - is complete. - """ - if self._background_task is None: - self._background_task = asyncio.get_event_loop().create_task( - self._blocking_poll() - ) - self._future.add_done_callback(fn) - - def set_result(self, result): - """Set the Future's result.""" - self._future.set_result(result) - - def set_exception(self, exception): - """Set the Future's exception.""" - self._future.set_exception(exception) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/future/base.py b/notification-service/venv/Lib/site-packages/google/api_core/future/base.py deleted file mode 100644 index f300586..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/future/base.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright 2017, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Abstract and helper bases for Future implementations.""" - -import abc - - -class Future(object, metaclass=abc.ABCMeta): - # pylint: disable=missing-docstring - # We inherit the interfaces here from concurrent.futures. - - """Future interface. - - This interface is based on :class:`concurrent.futures.Future`. - """ - - @abc.abstractmethod - def cancel(self): - raise NotImplementedError() - - @abc.abstractmethod - def cancelled(self): - raise NotImplementedError() - - @abc.abstractmethod - def running(self): - raise NotImplementedError() - - @abc.abstractmethod - def done(self): - raise NotImplementedError() - - @abc.abstractmethod - def result(self, timeout=None): - raise NotImplementedError() - - @abc.abstractmethod - def exception(self, timeout=None): - raise NotImplementedError() - - @abc.abstractmethod - def add_done_callback(self, fn): - # pylint: disable=invalid-name - raise NotImplementedError() - - @abc.abstractmethod - def set_result(self, result): - raise NotImplementedError() - - @abc.abstractmethod - def set_exception(self, exception): - raise NotImplementedError() diff --git a/notification-service/venv/Lib/site-packages/google/api_core/future/polling.py b/notification-service/venv/Lib/site-packages/google/api_core/future/polling.py deleted file mode 100644 index f1e2a18..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/future/polling.py +++ /dev/null @@ -1,323 +0,0 @@ -# Copyright 2017, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Abstract and helper bases for Future implementations.""" - -import abc -import concurrent.futures - -from google.api_core import exceptions -from google.api_core import retry as retries -from google.api_core.future import _helpers -from google.api_core.future import base - - -class _OperationNotComplete(Exception): - """Private exception used for polling via retry.""" - - pass - - -# DEPRECATED as it conflates RPC retry and polling concepts into one. -# Use POLLING_PREDICATE instead to configure polling. -RETRY_PREDICATE = retries.if_exception_type( - _OperationNotComplete, - exceptions.TooManyRequests, - exceptions.InternalServerError, - exceptions.BadGateway, - exceptions.ServiceUnavailable, -) - -# DEPRECATED: use DEFAULT_POLLING to configure LRO polling logic. Construct -# Retry object using its default values as a baseline for any custom retry logic -# (not to be confused with polling logic). -DEFAULT_RETRY = retries.Retry(predicate=RETRY_PREDICATE) - -# POLLING_PREDICATE is supposed to poll only on _OperationNotComplete. -# Any RPC-specific errors (like ServiceUnavailable) will be handled -# by retry logic (not to be confused with polling logic) which is triggered for -# every polling RPC independently of polling logic but within its context. -POLLING_PREDICATE = retries.if_exception_type( - _OperationNotComplete, -) - -# Default polling configuration -DEFAULT_POLLING = retries.Retry( - predicate=POLLING_PREDICATE, - initial=1.0, # seconds - maximum=20.0, # seconds - multiplier=1.5, - timeout=900, # seconds -) - - -class PollingFuture(base.Future): - """A Future that needs to poll some service to check its status. - - The :meth:`done` method should be implemented by subclasses. The polling - behavior will repeatedly call ``done`` until it returns True. - - The actual polling logic is encapsulated in :meth:`result` method. See - documentation for that method for details on how polling works. - - .. note:: - - Privacy here is intended to prevent the final class from - overexposing, not to prevent subclasses from accessing methods. - - Args: - polling (google.api_core.retry.Retry): The configuration used for polling. - This parameter controls how often :meth:`done` is polled. If the - ``timeout`` argument is specified in :meth:`result` method it will - override the ``polling.timeout`` property. - retry (google.api_core.retry.Retry): DEPRECATED use ``polling`` instead. - If set, it will override ``polling`` parameter for backward - compatibility. - """ - - _DEFAULT_VALUE = object() - - def __init__(self, polling=DEFAULT_POLLING, **kwargs): - super(PollingFuture, self).__init__() - self._polling = kwargs.get("retry", polling) - self._result = None - self._exception = None - self._result_set = False - """bool: Set to True when the result has been set via set_result or - set_exception.""" - self._polling_thread = None - self._done_callbacks = [] - - @abc.abstractmethod - def done(self, retry=None): - """Checks to see if the operation is complete. - - Args: - retry (google.api_core.retry.Retry): (Optional) How to retry the - polling RPC (to not be confused with polling configuration. See - the documentation for :meth:`result` for details). - - Returns: - bool: True if the operation is complete, False otherwise. - """ - # pylint: disable=redundant-returns-doc, missing-raises-doc - raise NotImplementedError() - - def _done_or_raise(self, retry=None): - """Check if the future is done and raise if it's not.""" - if not self.done(retry=retry): - raise _OperationNotComplete() - - def running(self): - """True if the operation is currently running.""" - return not self.done() - - def _blocking_poll(self, timeout=_DEFAULT_VALUE, retry=None, polling=None): - """Poll and wait for the Future to be resolved.""" - - if self._result_set: - return - - polling = polling or self._polling - if timeout is not PollingFuture._DEFAULT_VALUE: - polling = polling.with_timeout(timeout) - - try: - polling(self._done_or_raise)(retry=retry) - except exceptions.RetryError: - raise concurrent.futures.TimeoutError( - f"Operation did not complete within the designated timeout of " - f"{polling.timeout} seconds." - ) - - def result(self, timeout=_DEFAULT_VALUE, retry=None, polling=None): - """Get the result of the operation. - - This method will poll for operation status periodically, blocking if - necessary. If you just want to make sure that this method does not block - for more than X seconds and you do not care about the nitty-gritty of - how this method operates, just call it with ``result(timeout=X)``. The - other parameters are for advanced use only. - - Every call to this method is controlled by the following three - parameters, each of which has a specific, distinct role, even though all three - may look very similar: ``timeout``, ``retry`` and ``polling``. In most - cases users do not need to specify any custom values for any of these - parameters and may simply rely on default ones instead. - - If you choose to specify custom parameters, please make sure you've - read the documentation below carefully. - - First, please check :class:`google.api_core.retry.Retry` - class documentation for the proper definition of timeout and deadline - terms and for the definition the three different types of timeouts. - This class operates in terms of Retry Timeout and Polling Timeout. It - does not let customizing RPC timeout and the user is expected to rely on - default behavior for it. - - The roles of each argument of this method are as follows: - - ``timeout`` (int): (Optional) The Polling Timeout as defined in - :class:`google.api_core.retry.Retry`. If the operation does not complete - within this timeout an exception will be thrown. This parameter affects - neither Retry Timeout nor RPC Timeout. - - ``retry`` (google.api_core.retry.Retry): (Optional) How to retry the - polling RPC. The ``retry.timeout`` property of this parameter is the - Retry Timeout as defined in :class:`google.api_core.retry.Retry`. - This parameter defines ONLY how the polling RPC call is retried - (i.e. what to do if the RPC we used for polling returned an error). It - does NOT define how the polling is done (i.e. how frequently and for - how long to call the polling RPC); use the ``polling`` parameter for that. - If a polling RPC throws and error and retrying it fails, the whole - future fails with the corresponding exception. If you want to tune which - server response error codes are not fatal for operation polling, use this - parameter to control that (``retry.predicate`` in particular). - - ``polling`` (google.api_core.retry.Retry): (Optional) How often and - for how long to call the polling RPC periodically (i.e. what to do if - a polling rpc returned successfully but its returned result indicates - that the long running operation is not completed yet, so we need to - check it again at some point in future). This parameter does NOT define - how to retry each individual polling RPC in case of an error; use the - ``retry`` parameter for that. The ``polling.timeout`` of this parameter - is Polling Timeout as defined in as defined in - :class:`google.api_core.retry.Retry`. - - For each of the arguments, there are also default values in place, which - will be used if a user does not specify their own. The default values - for the three parameters are not to be confused with the default values - for the corresponding arguments in this method (those serve as "not set" - markers for the resolution logic). - - If ``timeout`` is provided (i.e.``timeout is not _DEFAULT VALUE``; note - the ``None`` value means "infinite timeout"), it will be used to control - the actual Polling Timeout. Otherwise, the ``polling.timeout`` value - will be used instead (see below for how the ``polling`` config itself - gets resolved). In other words, this parameter effectively overrides - the ``polling.timeout`` value if specified. This is so to preserve - backward compatibility. - - If ``retry`` is provided (i.e. ``retry is not None``) it will be used to - control retry behavior for the polling RPC and the ``retry.timeout`` - will determine the Retry Timeout. If not provided, the - polling RPC will be called with whichever default retry config was - specified for the polling RPC at the moment of the construction of the - polling RPC's client. For example, if the polling RPC is - ``operations_client.get_operation()``, the ``retry`` parameter will be - controlling its retry behavior (not polling behavior) and, if not - specified, that specific method (``operations_client.get_operation()``) - will be retried according to the default retry config provided during - creation of ``operations_client`` client instead. This argument exists - mainly for backward compatibility; users are very unlikely to ever need - to set this parameter explicitly. - - If ``polling`` is provided (i.e. ``polling is not None``), it will be used - to control the overall polling behavior and ``polling.timeout`` will - control Polling Timeout unless it is overridden by ``timeout`` parameter - as described above. If not provided, the``polling`` parameter specified - during construction of this future (the ``polling`` argument in the - constructor) will be used instead. Note: since the ``timeout`` argument may - override ``polling.timeout`` value, this parameter should be viewed as - coupled with the ``timeout`` parameter as described above. - - Args: - timeout (int): (Optional) How long (in seconds) to wait for the - operation to complete. If None, wait indefinitely. - retry (google.api_core.retry.Retry): (Optional) How to retry the - polling RPC. This defines ONLY how the polling RPC call is - retried (i.e. what to do if the RPC we used for polling returned - an error). It does NOT define how the polling is done (i.e. how - frequently and for how long to call the polling RPC). - polling (google.api_core.retry.Retry): (Optional) How often and - for how long to call polling RPC periodically. This parameter - does NOT define how to retry each individual polling RPC call - (use the ``retry`` parameter for that). - - Returns: - google.protobuf.Message: The Operation's result. - - Raises: - google.api_core.GoogleAPICallError: If the operation errors or if - the timeout is reached before the operation completes. - """ - - self._blocking_poll(timeout=timeout, retry=retry, polling=polling) - - if self._exception is not None: - # pylint: disable=raising-bad-type - # Pylint doesn't recognize that this is valid in this case. - raise self._exception - - return self._result - - def exception(self, timeout=_DEFAULT_VALUE): - """Get the exception from the operation, blocking if necessary. - - See the documentation for the :meth:`result` method for details on how - this method operates, as both ``result`` and this method rely on the - exact same polling logic. The only difference is that this method does - not accept ``retry`` and ``polling`` arguments but relies on the default ones - instead. - - Args: - timeout (int): How long to wait for the operation to complete. - If None, wait indefinitely. - - Returns: - Optional[google.api_core.GoogleAPICallError]: The operation's - error. - """ - self._blocking_poll(timeout=timeout) - return self._exception - - def add_done_callback(self, fn): - """Add a callback to be executed when the operation is complete. - - If the operation is not already complete, this will start a helper - thread to poll for the status of the operation in the background. - - Args: - fn (Callable[Future]): The callback to execute when the operation - is complete. - """ - if self._result_set: - _helpers.safe_invoke_callback(fn, self) - return - - self._done_callbacks.append(fn) - - if self._polling_thread is None: - # The polling thread will exit on its own as soon as the operation - # is done. - self._polling_thread = _helpers.start_daemon_thread( - target=self._blocking_poll - ) - - def _invoke_callbacks(self, *args, **kwargs): - """Invoke all done callbacks.""" - for callback in self._done_callbacks: - _helpers.safe_invoke_callback(callback, *args, **kwargs) - - def set_result(self, result): - """Set the Future's result.""" - self._result = result - self._result_set = True - self._invoke_callbacks(self) - - def set_exception(self, exception): - """Set the Future's exception.""" - self._exception = exception - self._result_set = True - self._invoke_callbacks(self) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__init__.py b/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__init__.py deleted file mode 100644 index e5b7ad3..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__init__.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from google.api_core.gapic_v1 import client_info -from google.api_core.gapic_v1 import config -from google.api_core.gapic_v1 import config_async -from google.api_core.gapic_v1 import method -from google.api_core.gapic_v1 import method_async -from google.api_core.gapic_v1 import routing_header - -__all__ = [ - "client_info", - "config", - "config_async", - "method", - "method_async", - "routing_header", -] diff --git a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index db132e0..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/client_info.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/client_info.cpython-312.pyc deleted file mode 100644 index 09b506c..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/client_info.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/config.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/config.cpython-312.pyc deleted file mode 100644 index 5e8af3d..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/config.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/config_async.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/config_async.cpython-312.pyc deleted file mode 100644 index db5a40f..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/config_async.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/method.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/method.cpython-312.pyc deleted file mode 100644 index 8af706b..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/method.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/method_async.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/method_async.cpython-312.pyc deleted file mode 100644 index 8acff7c..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/method_async.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/routing_header.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/routing_header.cpython-312.pyc deleted file mode 100644 index 6bb159e..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/__pycache__/routing_header.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/client_info.py b/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/client_info.py deleted file mode 100644 index 4b3b564..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/client_info.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Helpers for providing client information. - -Client information is used to send information about the calling client, -such as the library and Python version, to API services. -""" - -from google.api_core import client_info - - -METRICS_METADATA_KEY = "x-goog-api-client" - - -class ClientInfo(client_info.ClientInfo): - """Client information used to generate a user-agent for API calls. - - This user-agent information is sent along with API calls to allow the - receiving service to do analytics on which versions of Python and Google - libraries are being used. - - Args: - python_version (str): The Python interpreter version, for example, - ``'3.9.6'``. - grpc_version (Optional[str]): The gRPC library version. - api_core_version (str): The google-api-core library version. - gapic_version (Optional[str]): The version of gapic-generated client - library, if the library was generated by gapic. - client_library_version (Optional[str]): The version of the client - library, generally used if the client library was not generated - by gapic or if additional functionality was built on top of - a gapic client library. - user_agent (Optional[str]): Prefix to the user agent header. This is - used to supply information such as application name or partner tool. - Recommended format: ``application-or-tool-ID/major.minor.version``. - rest_version (Optional[str]): A string with labeled versions of the - dependencies used for REST transport. - protobuf_runtime_version (Optional[str]): The protobuf runtime version. - """ - - def to_grpc_metadata(self): - """Returns the gRPC metadata for this client info.""" - return (METRICS_METADATA_KEY, self.to_user_agent()) - - -DEFAULT_CLIENT_INFO = ClientInfo() diff --git a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/config.py b/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/config.py deleted file mode 100644 index 36b50d9..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/config.py +++ /dev/null @@ -1,175 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Helpers for loading gapic configuration data. - -The Google API generator creates supplementary configuration for each RPC -method to tell the client library how to deal with retries and timeouts. -""" - -import collections - -import grpc - -from google.api_core import exceptions -from google.api_core import retry -from google.api_core import timeout - - -_MILLIS_PER_SECOND = 1000.0 - - -def _exception_class_for_grpc_status_name(name): - """Returns the Google API exception class for a gRPC error code name. - - DEPRECATED: use ``exceptions.exception_class_for_grpc_status`` method - directly instead. - - Args: - name (str): The name of the gRPC status code, for example, - ``UNAVAILABLE``. - - Returns: - :func:`type`: The appropriate subclass of - :class:`google.api_core.exceptions.GoogleAPICallError`. - """ - return exceptions.exception_class_for_grpc_status(getattr(grpc.StatusCode, name)) - - -def _retry_from_retry_config(retry_params, retry_codes, retry_impl=retry.Retry): - """Creates a Retry object given a gapic retry configuration. - - DEPRECATED: instantiate retry and timeout classes directly instead. - - Args: - retry_params (dict): The retry parameter values, for example:: - - { - "initial_retry_delay_millis": 1000, - "retry_delay_multiplier": 2.5, - "max_retry_delay_millis": 120000, - "initial_rpc_timeout_millis": 120000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 120000, - "total_timeout_millis": 600000 - } - - retry_codes (sequence[str]): The list of retryable gRPC error code - names. - - Returns: - google.api_core.retry.Retry: The default retry object for the method. - """ - exception_classes = [ - _exception_class_for_grpc_status_name(code) for code in retry_codes - ] - return retry_impl( - retry.if_exception_type(*exception_classes), - initial=(retry_params["initial_retry_delay_millis"] / _MILLIS_PER_SECOND), - maximum=(retry_params["max_retry_delay_millis"] / _MILLIS_PER_SECOND), - multiplier=retry_params["retry_delay_multiplier"], - deadline=retry_params["total_timeout_millis"] / _MILLIS_PER_SECOND, - ) - - -def _timeout_from_retry_config(retry_params): - """Creates a ExponentialTimeout object given a gapic retry configuration. - - DEPRECATED: instantiate retry and timeout classes directly instead. - - Args: - retry_params (dict): The retry parameter values, for example:: - - { - "initial_retry_delay_millis": 1000, - "retry_delay_multiplier": 2.5, - "max_retry_delay_millis": 120000, - "initial_rpc_timeout_millis": 120000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 120000, - "total_timeout_millis": 600000 - } - - Returns: - google.api_core.retry.ExponentialTimeout: The default time object for - the method. - """ - return timeout.ExponentialTimeout( - initial=(retry_params["initial_rpc_timeout_millis"] / _MILLIS_PER_SECOND), - maximum=(retry_params["max_rpc_timeout_millis"] / _MILLIS_PER_SECOND), - multiplier=retry_params["rpc_timeout_multiplier"], - deadline=(retry_params["total_timeout_millis"] / _MILLIS_PER_SECOND), - ) - - -MethodConfig = collections.namedtuple("MethodConfig", ["retry", "timeout"]) - - -def parse_method_configs(interface_config, retry_impl=retry.Retry): - """Creates default retry and timeout objects for each method in a gapic - interface config. - - DEPRECATED: instantiate retry and timeout classes directly instead. - - Args: - interface_config (Mapping): The interface config section of the full - gapic library config. For example, If the full configuration has - an interface named ``google.example.v1.ExampleService`` you would - pass in just that interface's configuration, for example - ``gapic_config['interfaces']['google.example.v1.ExampleService']``. - retry_impl (Callable): The constructor that creates a retry decorator - that will be applied to the method based on method configs. - - Returns: - Mapping[str, MethodConfig]: A mapping of RPC method names to their - configuration. - """ - # Grab all the retry codes - retry_codes_map = { - name: retry_codes - for name, retry_codes in interface_config.get("retry_codes", {}).items() - } - - # Grab all of the retry params - retry_params_map = { - name: retry_params - for name, retry_params in interface_config.get("retry_params", {}).items() - } - - # Iterate through all the API methods and create a flat MethodConfig - # instance for each one. - method_configs = {} - - for method_name, method_params in interface_config.get("methods", {}).items(): - retry_params_name = method_params.get("retry_params_name") - - if retry_params_name is not None: - retry_params = retry_params_map[retry_params_name] - retry_ = _retry_from_retry_config( - retry_params, - retry_codes_map[method_params["retry_codes_name"]], - retry_impl, - ) - timeout_ = _timeout_from_retry_config(retry_params) - - # No retry config, so this is a non-retryable method. - else: - retry_ = None - timeout_ = timeout.ConstantTimeout( - method_params["timeout_millis"] / _MILLIS_PER_SECOND - ) - - method_configs[method_name] = MethodConfig(retry=retry_, timeout=timeout_) - - return method_configs diff --git a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/config_async.py b/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/config_async.py deleted file mode 100644 index 13d6a48..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/config_async.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""AsyncIO helpers for loading gapic configuration data. - -The Google API generator creates supplementary configuration for each RPC -method to tell the client library how to deal with retries and timeouts. -""" - -from google.api_core import retry_async -from google.api_core.gapic_v1 import config -from google.api_core.gapic_v1.config import MethodConfig # noqa: F401 - - -def parse_method_configs(interface_config): - """Creates default retry and timeout objects for each method in a gapic - interface config with AsyncIO semantics. - - Args: - interface_config (Mapping): The interface config section of the full - gapic library config. For example, If the full configuration has - an interface named ``google.example.v1.ExampleService`` you would - pass in just that interface's configuration, for example - ``gapic_config['interfaces']['google.example.v1.ExampleService']``. - - Returns: - Mapping[str, MethodConfig]: A mapping of RPC method names to their - configuration. - """ - return config.parse_method_configs( - interface_config, retry_impl=retry_async.AsyncRetry - ) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/method.py b/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/method.py deleted file mode 100644 index b4481ca..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/method.py +++ /dev/null @@ -1,250 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Helpers for wrapping low-level gRPC methods with common functionality. - -This is used by gapic clients to provide common error mapping, retry, timeout, -compression, pagination, and long-running operations to gRPC methods. -""" - -import enum -import functools - -from google.api_core import grpc_helpers -from google.api_core.gapic_v1 import client_info -from google.api_core.timeout import TimeToDeadlineTimeout - -USE_DEFAULT_METADATA = object() - - -class _MethodDefault(enum.Enum): - # Uses enum so that pytype/mypy knows that this is the only possible value. - # https://stackoverflow.com/a/60605919/101923 - _DEFAULT_VALUE = object() - - -DEFAULT = _MethodDefault._DEFAULT_VALUE -"""Sentinel value indicating that a retry, timeout, or compression argument was unspecified, -so the default should be used.""" - - -def _is_not_none_or_false(value): - return value is not None and value is not False - - -def _apply_decorators(func, decorators): - """Apply a list of decorators to a given function. - - ``decorators`` may contain items that are ``None`` or ``False`` which will - be ignored. - """ - filtered_decorators = filter(_is_not_none_or_false, reversed(decorators)) - - for decorator in filtered_decorators: - func = decorator(func) - - return func - - -class _GapicCallable(object): - """Callable that applies retry, timeout, and metadata logic. - - Args: - target (Callable): The low-level RPC method. - retry (google.api_core.retry.Retry): The default retry for the - callable. If ``None``, this callable will not retry by default - timeout (google.api_core.timeout.Timeout): The default timeout for the - callable (i.e. duration of time within which an RPC must terminate - after its start, not to be confused with deadline). If ``None``, - this callable will not specify a timeout argument to the low-level - RPC method. - compression (grpc.Compression): The default compression for the callable. - If ``None``, this callable will not specify a compression argument - to the low-level RPC method. - metadata (Sequence[Tuple[str, str]]): Additional metadata that is - provided to the RPC method on every invocation. This is merged with - any metadata specified during invocation. If ``None``, no - additional metadata will be passed to the RPC method. - """ - - def __init__( - self, - target, - retry, - timeout, - compression, - metadata=None, - ): - self._target = target - self._retry = retry - self._timeout = timeout - self._compression = compression - self._metadata = metadata - - def __call__( - self, *args, timeout=DEFAULT, retry=DEFAULT, compression=DEFAULT, **kwargs - ): - """Invoke the low-level RPC with retry, timeout, compression, and metadata.""" - - if retry is DEFAULT: - retry = self._retry - - if timeout is DEFAULT: - timeout = self._timeout - - if compression is DEFAULT: - compression = self._compression - - if isinstance(timeout, (int, float)): - timeout = TimeToDeadlineTimeout(timeout=timeout) - - # Apply all applicable decorators. - wrapped_func = _apply_decorators(self._target, [retry, timeout]) - - # Add the user agent metadata to the call. - if self._metadata is not None: - metadata = kwargs.get("metadata", []) - # Due to the nature of invocation, None should be treated the same - # as not specified. - if metadata is None: - metadata = [] - metadata = list(metadata) - metadata.extend(self._metadata) - kwargs["metadata"] = metadata - if self._compression is not None: - kwargs["compression"] = compression - - return wrapped_func(*args, **kwargs) - - -def wrap_method( - func, - default_retry=None, - default_timeout=None, - default_compression=None, - client_info=client_info.DEFAULT_CLIENT_INFO, - *, - with_call=False, -): - """Wrap an RPC method with common behavior. - - This applies common error wrapping, retry, timeout, and compression behavior to a function. - The wrapped function will take optional ``retry``, ``timeout``, and ``compression`` - arguments. - - For example:: - - import google.api_core.gapic_v1.method - from google.api_core import retry - from google.api_core import timeout - from grpc import Compression - - # The original RPC method. - def get_topic(name, timeout=None): - request = publisher_v2.GetTopicRequest(name=name) - return publisher_stub.GetTopic(request, timeout=timeout) - - default_retry = retry.Retry(deadline=60) - default_timeout = timeout.Timeout(deadline=60) - default_compression = Compression.NoCompression - wrapped_get_topic = google.api_core.gapic_v1.method.wrap_method( - get_topic, default_retry) - - # Execute get_topic with default retry and timeout: - response = wrapped_get_topic() - - # Execute get_topic without doing any retying but with the default - # timeout: - response = wrapped_get_topic(retry=None) - - # Execute get_topic but only retry on 5xx errors: - my_retry = retry.Retry(retry.if_exception_type( - exceptions.InternalServerError)) - response = wrapped_get_topic(retry=my_retry) - - The way this works is by late-wrapping the given function with the retry - and timeout decorators. Essentially, when ``wrapped_get_topic()`` is - called: - - * ``get_topic()`` is first wrapped with the ``timeout`` into - ``get_topic_with_timeout``. - * ``get_topic_with_timeout`` is wrapped with the ``retry`` into - ``get_topic_with_timeout_and_retry()``. - * The final ``get_topic_with_timeout_and_retry`` is called passing through - the ``args`` and ``kwargs``. - - The callstack is therefore:: - - method.__call__() -> - Retry.__call__() -> - Timeout.__call__() -> - wrap_errors() -> - get_topic() - - Note that if ``timeout`` or ``retry`` is ``None``, then they are not - applied to the function. For example, - ``wrapped_get_topic(timeout=None, retry=None)`` is more or less - equivalent to just calling ``get_topic`` but with error re-mapping. - - Args: - func (Callable[Any]): The function to wrap. It should accept an - optional ``timeout`` argument. If ``metadata`` is not ``None``, it - should accept a ``metadata`` argument. - default_retry (Optional[google.api_core.Retry]): The default retry - strategy. If ``None``, the method will not retry by default. - default_timeout (Optional[google.api_core.Timeout]): The default - timeout strategy. Can also be specified as an int or float. If - ``None``, the method will not have timeout specified by default. - default_compression (Optional[grpc.Compression]): The default - grpc.Compression. If ``None``, the method will not have - compression specified by default. - client_info - (Optional[google.api_core.gapic_v1.client_info.ClientInfo]): - Client information used to create a user-agent string that's - passed as gRPC metadata to the method. If unspecified, then - a sane default will be used. If ``None``, then no user agent - metadata will be provided to the RPC method. - with_call (bool): If True, wrapped grpc.UnaryUnaryMulticallables will - return a tuple of (response, grpc.Call) instead of just the response. - This is useful for extracting trailing metadata from unary calls. - Defaults to False. - - Returns: - Callable: A new callable that takes optional ``retry``, ``timeout``, - and ``compression`` - arguments and applies the common error mapping, retry, timeout, compression, - and metadata behavior to the low-level RPC method. - """ - if with_call: - try: - func = func.with_call - except AttributeError as exc: - raise ValueError( - "with_call=True is only supported for unary calls." - ) from exc - func = grpc_helpers.wrap_errors(func) - if client_info is not None: - user_agent_metadata = [client_info.to_grpc_metadata()] - else: - user_agent_metadata = None - - return functools.wraps(func)( - _GapicCallable( - func, - default_retry, - default_timeout, - default_compression, - metadata=user_agent_metadata, - ) - ) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/method_async.py b/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/method_async.py deleted file mode 100644 index c0f38c0..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/method_async.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""AsyncIO helpers for wrapping gRPC methods with common functionality. - -This is used by gapic clients to provide common error mapping, retry, timeout, -compression, pagination, and long-running operations to gRPC methods. -""" - -import functools - -from google.api_core import grpc_helpers_async -from google.api_core.gapic_v1 import client_info -from google.api_core.gapic_v1.method import _GapicCallable -from google.api_core.gapic_v1.method import DEFAULT # noqa: F401 -from google.api_core.gapic_v1.method import USE_DEFAULT_METADATA # noqa: F401 - -_DEFAULT_ASYNC_TRANSPORT_KIND = "grpc_asyncio" - - -def wrap_method( - func, - default_retry=None, - default_timeout=None, - default_compression=None, - client_info=client_info.DEFAULT_CLIENT_INFO, - kind=_DEFAULT_ASYNC_TRANSPORT_KIND, -): - """Wrap an async RPC method with common behavior. - - Returns: - Callable: A new callable that takes optional ``retry``, ``timeout``, - and ``compression`` arguments and applies the common error mapping, - retry, timeout, metadata, and compression behavior to the low-level RPC method. - """ - if kind == _DEFAULT_ASYNC_TRANSPORT_KIND: - func = grpc_helpers_async.wrap_errors(func) - - metadata = [client_info.to_grpc_metadata()] if client_info is not None else None - - return functools.wraps(func)( - _GapicCallable( - func, - default_retry, - default_timeout, - default_compression, - metadata=metadata, - ) - ) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/routing_header.py b/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/routing_header.py deleted file mode 100644 index c0c6f64..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/gapic_v1/routing_header.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Helpers for constructing routing headers. - -These headers are used by Google infrastructure to determine how to route -requests, especially for services that are regional. - -Generally, these headers are specified as gRPC metadata. -""" - -import functools -from enum import Enum -from urllib.parse import urlencode - -ROUTING_METADATA_KEY = "x-goog-request-params" -# This is the value for the `maxsize` argument of @functools.lru_cache -# https://docs.python.org/3/library/functools.html#functools.lru_cache -# This represents the number of recent function calls to store. -ROUTING_PARAM_CACHE_SIZE = 32 - - -def to_routing_header(params, qualified_enums=True): - """Returns a routing header string for the given request parameters. - - Args: - params (Mapping[str, str | bytes | Enum]): A dictionary containing the request - parameters used for routing. - qualified_enums (bool): Whether to represent enum values - as their type-qualified symbol names instead of as their - unqualified symbol names. - - Returns: - str: The routing header string. - """ - tuples = params.items() if isinstance(params, dict) else params - if not qualified_enums: - tuples = [(x[0], x[1].name) if isinstance(x[1], Enum) else x for x in tuples] - return "&".join([_urlencode_param(*t) for t in tuples]) - - -def to_grpc_metadata(params, qualified_enums=True): - """Returns the gRPC metadata containing the routing headers for the given - request parameters. - - Args: - params (Mapping[str, str | bytes | Enum]): A dictionary containing the request - parameters used for routing. - qualified_enums (bool): Whether to represent enum values - as their type-qualified symbol names instead of as their - unqualified symbol names. - - Returns: - Tuple(str, str): The gRPC metadata containing the routing header key - and value. - """ - return (ROUTING_METADATA_KEY, to_routing_header(params, qualified_enums)) - - -# use caching to avoid repeated computation -@functools.lru_cache(maxsize=ROUTING_PARAM_CACHE_SIZE) -def _urlencode_param(key, value): - """Cacheable wrapper over urlencode - - Args: - key (str): The key of the parameter to encode. - value (str | bytes | Enum): The value of the parameter to encode. - - Returns: - str: The encoded parameter. - """ - return urlencode( - {key: value}, - # Per Google API policy (go/api-url-encoding), / is not encoded. - safe="/", - ) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/general_helpers.py b/notification-service/venv/Lib/site-packages/google/api_core/general_helpers.py deleted file mode 100644 index 0628229..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/general_helpers.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This import for backward compatibility only. -from functools import wraps # noqa: F401 pragma: NO COVER - -_CREDENTIALS_FILE_WARNING = """\ -The `credentials_file` argument is deprecated because of a potential security risk. - -The `google.auth.load_credentials_from_file` method does not validate the credential -configuration. The security risk occurs when a credential configuration is accepted -from a source that is not under your control and used without validation on your side. - -If you know that you will be loading credential configurations of a -specific type, it is recommended to use a credential-type-specific -load method. - -This will ensure that an unexpected credential type with potential for -malicious intent is not loaded unintentionally. You might still have to do -validation for certain credential types. Please follow the recommendations -for that method. For example, if you want to load only service accounts, -you can create the service account credentials explicitly: - -``` -from google.cloud.vision_v1 import ImageAnnotatorClient -from google.oauth2 import service_account - -credentials = service_account.Credentials.from_service_account_file(filename) -client = ImageAnnotatorClient(credentials=credentials) -``` - -If you are loading your credential configuration from an untrusted source and have -not mitigated the risks (e.g. by validating the configuration yourself), make -these changes as soon as possible to prevent security risks to your environment. - -Regardless of the method used, it is always your responsibility to validate -configurations received from external sources. - -Refer to https://cloud.google.com/docs/authentication/external/externally-sourced-credentials -for more details. -""" diff --git a/notification-service/venv/Lib/site-packages/google/api_core/grpc_helpers.py b/notification-service/venv/Lib/site-packages/google/api_core/grpc_helpers.py deleted file mode 100644 index 30ba19c..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/grpc_helpers.py +++ /dev/null @@ -1,614 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Helpers for :mod:`grpc`.""" -import collections -import functools -from typing import Generic, Iterator, Optional, TypeVar -import warnings - -import google.auth -import google.auth.credentials -import google.auth.transport.grpc -import google.auth.transport.requests -import google.protobuf -import grpc - -from google.api_core import exceptions, general_helpers - - -# The list of gRPC Callable interfaces that return iterators. -_STREAM_WRAP_CLASSES = (grpc.UnaryStreamMultiCallable, grpc.StreamStreamMultiCallable) - -# denotes the proto response type for grpc calls -P = TypeVar("P") - - -def _patch_callable_name(callable_): - """Fix-up gRPC callable attributes. - - gRPC callable lack the ``__name__`` attribute which causes - :func:`functools.wraps` to error. This adds the attribute if needed. - """ - if not hasattr(callable_, "__name__"): - callable_.__name__ = callable_.__class__.__name__ - - -def _wrap_unary_errors(callable_): - """Map errors for Unary-Unary and Stream-Unary gRPC callables.""" - _patch_callable_name(callable_) - - @functools.wraps(callable_) - def error_remapped_callable(*args, **kwargs): - try: - return callable_(*args, **kwargs) - except grpc.RpcError as exc: - raise exceptions.from_grpc_error(exc) from exc - - return error_remapped_callable - - -class _StreamingResponseIterator(Generic[P], grpc.Call): - def __init__(self, wrapped, prefetch_first_result=True): - self._wrapped = wrapped - - # This iterator is used in a retry context, and returned outside after init. - # gRPC will not throw an exception until the stream is consumed, so we need - # to retrieve the first result, in order to fail, in order to trigger a retry. - try: - if prefetch_first_result: - self._stored_first_result = next(self._wrapped) - except TypeError: - # It is possible the wrapped method isn't an iterable (a grpc.Call - # for instance). If this happens don't store the first result. - pass - except StopIteration: - # ignore stop iteration at this time. This should be handled outside of retry. - pass - - def __iter__(self) -> Iterator[P]: - """This iterator is also an iterable that returns itself.""" - return self - - def __next__(self) -> P: - """Get the next response from the stream. - - Returns: - protobuf.Message: A single response from the stream. - """ - try: - if hasattr(self, "_stored_first_result"): - result = self._stored_first_result - del self._stored_first_result - return result - return next(self._wrapped) - except grpc.RpcError as exc: - # If the stream has already returned data, we cannot recover here. - raise exceptions.from_grpc_error(exc) from exc - - # grpc.Call & grpc.RpcContext interface - - def add_callback(self, callback): - return self._wrapped.add_callback(callback) - - def cancel(self): - return self._wrapped.cancel() - - def code(self): - return self._wrapped.code() - - def details(self): - return self._wrapped.details() - - def initial_metadata(self): - return self._wrapped.initial_metadata() - - def is_active(self): - return self._wrapped.is_active() - - def time_remaining(self): - return self._wrapped.time_remaining() - - def trailing_metadata(self): - return self._wrapped.trailing_metadata() - - -# public type alias denoting the return type of streaming gapic calls -GrpcStream = _StreamingResponseIterator[P] - - -def _wrap_stream_errors(callable_): - """Wrap errors for Unary-Stream and Stream-Stream gRPC callables. - - The callables that return iterators require a bit more logic to re-map - errors when iterating. This wraps both the initial invocation and the - iterator of the return value to re-map errors. - """ - _patch_callable_name(callable_) - - @functools.wraps(callable_) - def error_remapped_callable(*args, **kwargs): - try: - result = callable_(*args, **kwargs) - # Auto-fetching the first result causes PubSub client's streaming pull - # to hang when re-opening the stream, thus we need examine the hacky - # hidden flag to see if pre-fetching is disabled. - # https://github.com/googleapis/python-pubsub/issues/93#issuecomment-630762257 - prefetch_first = getattr(callable_, "_prefetch_first_result_", True) - return _StreamingResponseIterator( - result, prefetch_first_result=prefetch_first - ) - except grpc.RpcError as exc: - raise exceptions.from_grpc_error(exc) from exc - - return error_remapped_callable - - -def wrap_errors(callable_): - """Wrap a gRPC callable and map :class:`grpc.RpcErrors` to friendly error - classes. - - Errors raised by the gRPC callable are mapped to the appropriate - :class:`google.api_core.exceptions.GoogleAPICallError` subclasses. - The original `grpc.RpcError` (which is usually also a `grpc.Call`) is - available from the ``response`` property on the mapped exception. This - is useful for extracting metadata from the original error. - - Args: - callable_ (Callable): A gRPC callable. - - Returns: - Callable: The wrapped gRPC callable. - """ - if isinstance(callable_, _STREAM_WRAP_CLASSES): - return _wrap_stream_errors(callable_) - else: - return _wrap_unary_errors(callable_) - - -def _create_composite_credentials( - credentials=None, - credentials_file=None, - default_scopes=None, - scopes=None, - ssl_credentials=None, - quota_project_id=None, - default_host=None, -): - """Create the composite credentials for secure channels. - - Args: - credentials (google.auth.credentials.Credentials): The credentials. If - not specified, then this function will attempt to ascertain the - credentials from the environment using :func:`google.auth.default`. - credentials_file (str): Deprecated. A file with credentials that can be loaded with - :func:`google.auth.load_credentials_from_file`. This argument is - mutually exclusive with credentials. This argument will be - removed in the next major version of `google-api-core`. - - .. warning:: - Important: If you accept a credential configuration (credential JSON/File/Stream) - from an external source for authentication to Google Cloud Platform, you must - validate it before providing it to any Google API or client library. Providing an - unvalidated credential configuration to Google APIs or libraries can compromise - the security of your systems and data. For more information, refer to - `Validate credential configurations from external sources`_. - - .. _Validate credential configurations from external sources: - - https://cloud.google.com/docs/authentication/external/externally-sourced-credentials - default_scopes (Sequence[str]): A optional list of scopes needed for this - service. These are only used when credentials are not specified and - are passed to :func:`google.auth.default`. - scopes (Sequence[str]): A optional list of scopes needed for this - service. These are only used when credentials are not specified and - are passed to :func:`google.auth.default`. - ssl_credentials (grpc.ChannelCredentials): Optional SSL channel - credentials. This can be used to specify different certificates. - quota_project_id (str): An optional project to use for billing and quota. - default_host (str): The default endpoint. e.g., "pubsub.googleapis.com". - - Returns: - grpc.ChannelCredentials: The composed channel credentials object. - - Raises: - google.api_core.DuplicateCredentialArgs: If both a credentials object and credentials_file are passed. - """ - if credentials_file is not None: - warnings.warn(general_helpers._CREDENTIALS_FILE_WARNING, DeprecationWarning) - - if credentials and credentials_file: - raise exceptions.DuplicateCredentialArgs( - "'credentials' and 'credentials_file' are mutually exclusive." - ) - - if credentials_file: - credentials, _ = google.auth.load_credentials_from_file( - credentials_file, scopes=scopes, default_scopes=default_scopes - ) - elif credentials: - credentials = google.auth.credentials.with_scopes_if_required( - credentials, scopes=scopes, default_scopes=default_scopes - ) - else: - credentials, _ = google.auth.default( - scopes=scopes, default_scopes=default_scopes - ) - - if quota_project_id and isinstance( - credentials, google.auth.credentials.CredentialsWithQuotaProject - ): - credentials = credentials.with_quota_project(quota_project_id) - - request = google.auth.transport.requests.Request() - - # Create the metadata plugin for inserting the authorization header. - metadata_plugin = google.auth.transport.grpc.AuthMetadataPlugin( - credentials, - request, - default_host=default_host, - ) - - # Create a set of grpc.CallCredentials using the metadata plugin. - google_auth_credentials = grpc.metadata_call_credentials(metadata_plugin) - - # if `ssl_credentials` is set, use `grpc.composite_channel_credentials` instead of - # `grpc.compute_engine_channel_credentials` as the former supports passing - # `ssl_credentials` via `channel_credentials` which is needed for mTLS. - if ssl_credentials: - # Combine the ssl credentials and the authorization credentials. - # See https://grpc.github.io/grpc/python/grpc.html#grpc.composite_channel_credentials - return grpc.composite_channel_credentials( - ssl_credentials, google_auth_credentials - ) - else: - # Use grpc.compute_engine_channel_credentials in order to support Direct Path. - # See https://grpc.github.io/grpc/python/grpc.html#grpc.compute_engine_channel_credentials - # TODO(https://github.com/googleapis/python-api-core/issues/598): - # Although `grpc.compute_engine_channel_credentials` returns channel credentials - # outside of a Google Compute Engine environment (GCE), we should determine if - # there is a way to reliably detect a GCE environment so that - # `grpc.compute_engine_channel_credentials` is not called outside of GCE. - return grpc.compute_engine_channel_credentials(google_auth_credentials) - - -def create_channel( - target, - credentials=None, - scopes=None, - ssl_credentials=None, - credentials_file=None, - quota_project_id=None, - default_scopes=None, - default_host=None, - compression=None, - attempt_direct_path: Optional[bool] = False, - **kwargs, -): - """Create a secure channel with credentials. - - Args: - target (str): The target service address in the format 'hostname:port'. - credentials (google.auth.credentials.Credentials): The credentials. If - not specified, then this function will attempt to ascertain the - credentials from the environment using :func:`google.auth.default`. - scopes (Sequence[str]): A optional list of scopes needed for this - service. These are only used when credentials are not specified and - are passed to :func:`google.auth.default`. - ssl_credentials (grpc.ChannelCredentials): Optional SSL channel - credentials. This can be used to specify different certificates. - credentials_file (str): A file with credentials that can be loaded with - :func:`google.auth.load_credentials_from_file`. This argument is - mutually exclusive with credentials. - - .. warning:: - Important: If you accept a credential configuration (credential JSON/File/Stream) - from an external source for authentication to Google Cloud Platform, you must - validate it before providing it to any Google API or client library. Providing an - unvalidated credential configuration to Google APIs or libraries can compromise - the security of your systems and data. For more information, refer to - `Validate credential configurations from external sources`_. - - .. _Validate credential configurations from external sources: - - https://cloud.google.com/docs/authentication/external/externally-sourced-credentials - quota_project_id (str): An optional project to use for billing and quota. - default_scopes (Sequence[str]): Default scopes passed by a Google client - library. Use 'scopes' for user-defined scopes. - default_host (str): The default endpoint. e.g., "pubsub.googleapis.com". - compression (grpc.Compression): An optional value indicating the - compression method to be used over the lifetime of the channel. - attempt_direct_path (Optional[bool]): If set, Direct Path will be attempted - when the request is made. Direct Path is only available within a Google - Compute Engine (GCE) environment and provides a proxyless connection - which increases the available throughput, reduces latency, and increases - reliability. Note: - - - This argument should only be set in a GCE environment and for Services - that are known to support Direct Path. - - If this argument is set outside of GCE, then this request will fail - unless the back-end service happens to have configured fall-back to DNS. - - If the request causes a `ServiceUnavailable` response, it is recommended - that the client repeat the request with `attempt_direct_path` set to - `False` as the Service may not support Direct Path. - - Using `ssl_credentials` with `attempt_direct_path` set to `True` will - result in `ValueError` as this combination is not yet supported. - - kwargs: Additional key-word args passed to - :func:`grpc.secure_channel`. - - Returns: - grpc.Channel: The created channel. - - Raises: - google.api_core.DuplicateCredentialArgs: If both a credentials object and credentials_file are passed. - ValueError: If `ssl_credentials` is set and `attempt_direct_path` is set to `True`. - """ - - # If `ssl_credentials` is set and `attempt_direct_path` is set to `True`, - # raise ValueError as this is not yet supported. - # See https://github.com/googleapis/python-api-core/issues/590 - if ssl_credentials and attempt_direct_path: - raise ValueError("Using ssl_credentials with Direct Path is not supported") - - composite_credentials = _create_composite_credentials( - credentials=credentials, - credentials_file=credentials_file, - default_scopes=default_scopes, - scopes=scopes, - ssl_credentials=ssl_credentials, - quota_project_id=quota_project_id, - default_host=default_host, - ) - - if attempt_direct_path: - target = _modify_target_for_direct_path(target) - - return grpc.secure_channel( - target, composite_credentials, compression=compression, **kwargs - ) - - -def _modify_target_for_direct_path(target: str) -> str: - """ - Given a target, return a modified version which is compatible with Direct Path. - - Args: - target (str): The target service address in the format 'hostname[:port]' or - 'dns://hostname[:port]'. - - Returns: - target (str): The target service address which is converted into a format compatible with Direct Path. - If the target contains `dns:///` or does not contain `:///`, the target will be converted in - a format compatible with Direct Path; otherwise the original target will be returned as the - original target may already denote Direct Path. - """ - - # A DNS prefix may be included with the target to indicate the endpoint is living in the Internet, - # outside of Google Cloud Platform. - dns_prefix = "dns:///" - # Remove "dns:///" if `attempt_direct_path` is set to True as - # the Direct Path prefix `google-c2p:///` will be used instead. - target = target.replace(dns_prefix, "") - - direct_path_separator = ":///" - if direct_path_separator not in target: - target_without_port = target.split(":")[0] - # Modify the target to use Direct Path by adding the `google-c2p:///` prefix - target = f"google-c2p{direct_path_separator}{target_without_port}" - return target - - -_MethodCall = collections.namedtuple( - "_MethodCall", ("request", "timeout", "metadata", "credentials", "compression") -) - -_ChannelRequest = collections.namedtuple("_ChannelRequest", ("method", "request")) - - -class _CallableStub(object): - """Stub for the grpc.*MultiCallable interfaces.""" - - def __init__(self, method, channel): - self._method = method - self._channel = channel - self.response = None - """Union[protobuf.Message, Callable[protobuf.Message], exception]: - The response to give when invoking this callable. If this is a - callable, it will be invoked with the request protobuf. If it's an - exception, the exception will be raised when this is invoked. - """ - self.responses = None - """Iterator[ - Union[protobuf.Message, Callable[protobuf.Message], exception]]: - An iterator of responses. If specified, self.response will be populated - on each invocation by calling ``next(self.responses)``.""" - self.requests = [] - """List[protobuf.Message]: All requests sent to this callable.""" - self.calls = [] - """List[Tuple]: All invocations of this callable. Each tuple is the - request, timeout, metadata, compression, and credentials.""" - - def __call__( - self, request, timeout=None, metadata=None, credentials=None, compression=None - ): - self._channel.requests.append(_ChannelRequest(self._method, request)) - self.calls.append( - _MethodCall(request, timeout, metadata, credentials, compression) - ) - self.requests.append(request) - - response = self.response - if self.responses is not None: - if response is None: - response = next(self.responses) - else: - raise ValueError( - "{method}.response and {method}.responses are mutually " - "exclusive.".format(method=self._method) - ) - - if callable(response): - return response(request) - - if isinstance(response, Exception): - raise response - - if response is not None: - return response - - raise ValueError('Method stub for "{}" has no response.'.format(self._method)) - - -def _simplify_method_name(method): - """Simplifies a gRPC method name. - - When gRPC invokes the channel to create a callable, it gives a full - method name like "/google.pubsub.v1.Publisher/CreateTopic". This - returns just the name of the method, in this case "CreateTopic". - - Args: - method (str): The name of the method. - - Returns: - str: The simplified name of the method. - """ - return method.rsplit("/", 1).pop() - - -class ChannelStub(grpc.Channel): - """A testing stub for the grpc.Channel interface. - - This can be used to test any client that eventually uses a gRPC channel - to communicate. By passing in a channel stub, you can configure which - responses are returned and track which requests are made. - - For example: - - .. code-block:: python - - channel_stub = grpc_helpers.ChannelStub() - client = FooClient(channel=channel_stub) - - channel_stub.GetFoo.response = foo_pb2.Foo(name='bar') - - foo = client.get_foo(labels=['baz']) - - assert foo.name == 'bar' - assert channel_stub.GetFoo.requests[0].labels = ['baz'] - - Each method on the stub can be accessed and configured on the channel. - Here's some examples of various configurations: - - .. code-block:: python - - # Return a basic response: - - channel_stub.GetFoo.response = foo_pb2.Foo(name='bar') - assert client.get_foo().name == 'bar' - - # Raise an exception: - channel_stub.GetFoo.response = NotFound('...') - - with pytest.raises(NotFound): - client.get_foo() - - # Use a sequence of responses: - channel_stub.GetFoo.responses = iter([ - foo_pb2.Foo(name='bar'), - foo_pb2.Foo(name='baz'), - ]) - - assert client.get_foo().name == 'bar' - assert client.get_foo().name == 'baz' - - # Use a callable - - def on_get_foo(request): - return foo_pb2.Foo(name='bar' + request.id) - - channel_stub.GetFoo.response = on_get_foo - - assert client.get_foo(id='123').name == 'bar123' - """ - - def __init__(self, responses=[]): - self.requests = [] - """Sequence[Tuple[str, protobuf.Message]]: A list of all requests made - on this channel in order. The tuple is of method name, request - message.""" - self._method_stubs = {} - - def _stub_for_method(self, method): - method = _simplify_method_name(method) - self._method_stubs[method] = _CallableStub(method, self) - return self._method_stubs[method] - - def __getattr__(self, key): - try: - return self._method_stubs[key] - except KeyError: - raise AttributeError - - def unary_unary( - self, - method, - request_serializer=None, - response_deserializer=None, - _registered_method=False, - ): - """grpc.Channel.unary_unary implementation.""" - return self._stub_for_method(method) - - def unary_stream( - self, - method, - request_serializer=None, - response_deserializer=None, - _registered_method=False, - ): - """grpc.Channel.unary_stream implementation.""" - return self._stub_for_method(method) - - def stream_unary( - self, - method, - request_serializer=None, - response_deserializer=None, - _registered_method=False, - ): - """grpc.Channel.stream_unary implementation.""" - return self._stub_for_method(method) - - def stream_stream( - self, - method, - request_serializer=None, - response_deserializer=None, - _registered_method=False, - ): - """grpc.Channel.stream_stream implementation.""" - return self._stub_for_method(method) - - def subscribe(self, callback, try_to_connect=False): - """grpc.Channel.subscribe implementation.""" - pass - - def unsubscribe(self, callback): - """grpc.Channel.unsubscribe implementation.""" - pass - - def close(self): - """grpc.Channel.close implementation.""" - pass diff --git a/notification-service/venv/Lib/site-packages/google/api_core/grpc_helpers_async.py b/notification-service/venv/Lib/site-packages/google/api_core/grpc_helpers_async.py deleted file mode 100644 index 9e1ad11..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/grpc_helpers_async.py +++ /dev/null @@ -1,348 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""AsyncIO helpers for :mod:`grpc` supporting 3.7+. - -Please combine more detailed docstring in grpc_helpers.py to use following -functions. This module is implementing the same surface with AsyncIO semantics. -""" - -import asyncio -import functools -import warnings - -from typing import AsyncGenerator, Generic, Iterator, Optional, TypeVar - -import grpc -from grpc import aio - -from google.api_core import exceptions, general_helpers, grpc_helpers - -# denotes the proto response type for grpc calls -P = TypeVar("P") - -# NOTE(lidiz) Alternatively, we can hack "__getattribute__" to perform -# automatic patching for us. But that means the overhead of creating an -# extra Python function spreads to every single send and receive. - - -class _WrappedCall(aio.Call): - def __init__(self): - self._call = None - - def with_call(self, call): - """Supplies the call object separately to keep __init__ clean.""" - self._call = call - return self - - async def initial_metadata(self): - return await self._call.initial_metadata() - - async def trailing_metadata(self): - return await self._call.trailing_metadata() - - async def code(self): - return await self._call.code() - - async def details(self): - return await self._call.details() - - def cancelled(self): - return self._call.cancelled() - - def done(self): - return self._call.done() - - def time_remaining(self): - return self._call.time_remaining() - - def cancel(self): - return self._call.cancel() - - def add_done_callback(self, callback): - self._call.add_done_callback(callback) - - async def wait_for_connection(self): - try: - await self._call.wait_for_connection() - except grpc.RpcError as rpc_error: - raise exceptions.from_grpc_error(rpc_error) from rpc_error - - -class _WrappedUnaryResponseMixin(Generic[P], _WrappedCall): - def __await__(self) -> Iterator[P]: - try: - response = yield from self._call.__await__() - return response - except grpc.RpcError as rpc_error: - raise exceptions.from_grpc_error(rpc_error) from rpc_error - - -class _WrappedStreamResponseMixin(Generic[P], _WrappedCall): - def __init__(self): - self._wrapped_async_generator = None - - async def read(self) -> P: - try: - return await self._call.read() - except grpc.RpcError as rpc_error: - raise exceptions.from_grpc_error(rpc_error) from rpc_error - - async def _wrapped_aiter(self) -> AsyncGenerator[P, None]: - try: - # NOTE(lidiz) coverage doesn't understand the exception raised from - # __anext__ method. It is covered by test case: - # test_wrap_stream_errors_aiter_non_rpc_error - async for response in self._call: # pragma: no branch - yield response - except grpc.RpcError as rpc_error: - raise exceptions.from_grpc_error(rpc_error) from rpc_error - - def __aiter__(self) -> AsyncGenerator[P, None]: - if not self._wrapped_async_generator: - self._wrapped_async_generator = self._wrapped_aiter() - return self._wrapped_async_generator - - -class _WrappedStreamRequestMixin(_WrappedCall): - async def write(self, request): - try: - await self._call.write(request) - except grpc.RpcError as rpc_error: - raise exceptions.from_grpc_error(rpc_error) from rpc_error - - async def done_writing(self): - try: - await self._call.done_writing() - except grpc.RpcError as rpc_error: - raise exceptions.from_grpc_error(rpc_error) from rpc_error - - -# NOTE(lidiz) Implementing each individual class separately, so we don't -# expose any API that should not be seen. E.g., __aiter__ in unary-unary -# RPC, or __await__ in stream-stream RPC. -class _WrappedUnaryUnaryCall(_WrappedUnaryResponseMixin[P], aio.UnaryUnaryCall): - """Wrapped UnaryUnaryCall to map exceptions.""" - - -class _WrappedUnaryStreamCall(_WrappedStreamResponseMixin[P], aio.UnaryStreamCall): - """Wrapped UnaryStreamCall to map exceptions.""" - - -class _WrappedStreamUnaryCall( - _WrappedUnaryResponseMixin[P], _WrappedStreamRequestMixin, aio.StreamUnaryCall -): - """Wrapped StreamUnaryCall to map exceptions.""" - - -class _WrappedStreamStreamCall( - _WrappedStreamRequestMixin, _WrappedStreamResponseMixin[P], aio.StreamStreamCall -): - """Wrapped StreamStreamCall to map exceptions.""" - - -# public type alias denoting the return type of async streaming gapic calls -GrpcAsyncStream = _WrappedStreamResponseMixin -# public type alias denoting the return type of unary gapic calls -AwaitableGrpcCall = _WrappedUnaryResponseMixin - - -def _wrap_unary_errors(callable_): - """Map errors for Unary-Unary async callables.""" - - @functools.wraps(callable_) - def error_remapped_callable(*args, **kwargs): - call = callable_(*args, **kwargs) - return _WrappedUnaryUnaryCall().with_call(call) - - return error_remapped_callable - - -def _wrap_stream_errors(callable_, wrapper_type): - """Map errors for streaming RPC async callables.""" - - @functools.wraps(callable_) - async def error_remapped_callable(*args, **kwargs): - call = callable_(*args, **kwargs) - call = wrapper_type().with_call(call) - await call.wait_for_connection() - return call - - return error_remapped_callable - - -def wrap_errors(callable_): - """Wrap a gRPC async callable and map :class:`grpc.RpcErrors` to - friendly error classes. - - Errors raised by the gRPC callable are mapped to the appropriate - :class:`google.api_core.exceptions.GoogleAPICallError` subclasses. The - original `grpc.RpcError` (which is usually also a `grpc.Call`) is - available from the ``response`` property on the mapped exception. This - is useful for extracting metadata from the original error. - - Args: - callable_ (Callable): A gRPC callable. - - Returns: Callable: The wrapped gRPC callable. - """ - grpc_helpers._patch_callable_name(callable_) - - if isinstance(callable_, aio.UnaryStreamMultiCallable): - return _wrap_stream_errors(callable_, _WrappedUnaryStreamCall) - elif isinstance(callable_, aio.StreamUnaryMultiCallable): - return _wrap_stream_errors(callable_, _WrappedStreamUnaryCall) - elif isinstance(callable_, aio.StreamStreamMultiCallable): - return _wrap_stream_errors(callable_, _WrappedStreamStreamCall) - else: - return _wrap_unary_errors(callable_) - - -def create_channel( - target, - credentials=None, - scopes=None, - ssl_credentials=None, - credentials_file=None, - quota_project_id=None, - default_scopes=None, - default_host=None, - compression=None, - attempt_direct_path: Optional[bool] = False, - **kwargs, -): - """Create an AsyncIO secure channel with credentials. - - Args: - target (str): The target service address in the format 'hostname:port'. - credentials (google.auth.credentials.Credentials): The credentials. If - not specified, then this function will attempt to ascertain the - credentials from the environment using :func:`google.auth.default`. - scopes (Sequence[str]): A optional list of scopes needed for this - service. These are only used when credentials are not specified and - are passed to :func:`google.auth.default`. - ssl_credentials (grpc.ChannelCredentials): Optional SSL channel - credentials. This can be used to specify different certificates. - credentials_file (str): Deprecated. A file with credentials that can be loaded with - :func:`google.auth.load_credentials_from_file`. This argument is - mutually exclusive with credentials. This argument will be - removed in the next major version of `google-api-core`. - - .. warning:: - Important: If you accept a credential configuration (credential JSON/File/Stream) - from an external source for authentication to Google Cloud Platform, you must - validate it before providing it to any Google API or client library. Providing an - unvalidated credential configuration to Google APIs or libraries can compromise - the security of your systems and data. For more information, refer to - `Validate credential configurations from external sources`_. - - .. _Validate credential configurations from external sources: - - https://cloud.google.com/docs/authentication/external/externally-sourced-credentials - quota_project_id (str): An optional project to use for billing and quota. - default_scopes (Sequence[str]): Default scopes passed by a Google client - library. Use 'scopes' for user-defined scopes. - default_host (str): The default endpoint. e.g., "pubsub.googleapis.com". - compression (grpc.Compression): An optional value indicating the - compression method to be used over the lifetime of the channel. - attempt_direct_path (Optional[bool]): If set, Direct Path will be attempted - when the request is made. Direct Path is only available within a Google - Compute Engine (GCE) environment and provides a proxyless connection - which increases the available throughput, reduces latency, and increases - reliability. Note: - - - This argument should only be set in a GCE environment and for Services - that are known to support Direct Path. - - If this argument is set outside of GCE, then this request will fail - unless the back-end service happens to have configured fall-back to DNS. - - If the request causes a `ServiceUnavailable` response, it is recommended - that the client repeat the request with `attempt_direct_path` set to - `False` as the Service may not support Direct Path. - - Using `ssl_credentials` with `attempt_direct_path` set to `True` will - result in `ValueError` as this combination is not yet supported. - - kwargs: Additional key-word args passed to :func:`aio.secure_channel`. - - Returns: - aio.Channel: The created channel. - - Raises: - google.api_core.DuplicateCredentialArgs: If both a credentials object and credentials_file are passed. - ValueError: If `ssl_credentials` is set and `attempt_direct_path` is set to `True`. - """ - - if credentials_file is not None: - warnings.warn(general_helpers._CREDENTIALS_FILE_WARNING, DeprecationWarning) - - # If `ssl_credentials` is set and `attempt_direct_path` is set to `True`, - # raise ValueError as this is not yet supported. - # See https://github.com/googleapis/python-api-core/issues/590 - if ssl_credentials and attempt_direct_path: - raise ValueError("Using ssl_credentials with Direct Path is not supported") - - composite_credentials = grpc_helpers._create_composite_credentials( - credentials=credentials, - credentials_file=credentials_file, - scopes=scopes, - default_scopes=default_scopes, - ssl_credentials=ssl_credentials, - quota_project_id=quota_project_id, - default_host=default_host, - ) - - if attempt_direct_path: - target = grpc_helpers._modify_target_for_direct_path(target) - - return aio.secure_channel( - target, composite_credentials, compression=compression, **kwargs - ) - - -class FakeUnaryUnaryCall(_WrappedUnaryUnaryCall): - """Fake implementation for unary-unary RPCs. - - It is a dummy object for response message. Supply the intended response - upon the initialization, and the coroutine will return the exact response - message. - """ - - def __init__(self, response=object()): - self.response = response - self._future = asyncio.get_event_loop().create_future() - self._future.set_result(self.response) - - def __await__(self): - response = yield from self._future.__await__() - return response - - -class FakeStreamUnaryCall(_WrappedStreamUnaryCall): - """Fake implementation for stream-unary RPCs. - - It is a dummy object for response message. Supply the intended response - upon the initialization, and the coroutine will return the exact response - message. - """ - - def __init__(self, response=object()): - self.response = response - self._future = asyncio.get_event_loop().create_future() - self._future.set_result(self.response) - - def __await__(self): - response = yield from self._future.__await__() - return response - - async def wait_for_connection(self): - pass diff --git a/notification-service/venv/Lib/site-packages/google/api_core/iam.py b/notification-service/venv/Lib/site-packages/google/api_core/iam.py deleted file mode 100644 index 4437c70..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/iam.py +++ /dev/null @@ -1,427 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Non-API-specific IAM policy definitions - -For allowed roles / permissions, see: -https://cloud.google.com/iam/docs/understanding-roles - -Example usage: - -.. code-block:: python - - # ``get_iam_policy`` returns a :class:'~google.api_core.iam.Policy`. - policy = resource.get_iam_policy(requested_policy_version=3) - - phred = "user:phred@example.com" - admin_group = "group:admins@groups.example.com" - account = "serviceAccount:account-1234@accounts.example.com" - - policy.version = 3 - policy.bindings = [ - { - "role": "roles/owner", - "members": {phred, admin_group, account} - }, - { - "role": "roles/editor", - "members": {"allAuthenticatedUsers"} - }, - { - "role": "roles/viewer", - "members": {"allUsers"} - "condition": { - "title": "request_time", - "description": "Requests made before 2021-01-01T00:00:00Z", - "expression": "request.time < timestamp(\"2021-01-01T00:00:00Z\")" - } - } - ] - - resource.set_iam_policy(policy) -""" - -import collections -import collections.abc -import operator -import warnings - -# Generic IAM roles - -OWNER_ROLE = "roles/owner" -"""Generic role implying all rights to an object.""" - -EDITOR_ROLE = "roles/editor" -"""Generic role implying rights to modify an object.""" - -VIEWER_ROLE = "roles/viewer" -"""Generic role implying rights to access an object.""" - -_ASSIGNMENT_DEPRECATED_MSG = """\ -Assigning to '{}' is deprecated. Use the `policy.bindings` property to modify bindings instead.""" - -_DICT_ACCESS_MSG = """\ -Dict access is not supported on policies with version > 1 or with conditional bindings.""" - - -class InvalidOperationException(Exception): - """Raised when trying to use Policy class as a dict.""" - - pass - - -class Policy(collections.abc.MutableMapping): - """IAM Policy - - Args: - etag (Optional[str]): ETag used to identify a unique of the policy - version (Optional[int]): The syntax schema version of the policy. - - Note: - Using conditions in bindings requires the policy's version to be set - to `3` or greater, depending on the versions that are currently supported. - - Accessing the policy using dict operations will raise InvalidOperationException - when the policy's version is set to 3. - - Use the policy.bindings getter/setter to retrieve and modify the policy's bindings. - - See: - IAM Policy https://cloud.google.com/iam/reference/rest/v1/Policy - Policy versions https://cloud.google.com/iam/docs/policies#versions - Conditions overview https://cloud.google.com/iam/docs/conditions-overview. - """ - - _OWNER_ROLES = (OWNER_ROLE,) - """Roles mapped onto our ``owners`` attribute.""" - - _EDITOR_ROLES = (EDITOR_ROLE,) - """Roles mapped onto our ``editors`` attribute.""" - - _VIEWER_ROLES = (VIEWER_ROLE,) - """Roles mapped onto our ``viewers`` attribute.""" - - def __init__(self, etag=None, version=None): - self.etag = etag - self.version = version - self._bindings = [] - - def __iter__(self): - self.__check_version__() - # Exclude bindings with no members - return (binding["role"] for binding in self._bindings if binding["members"]) - - def __len__(self): - self.__check_version__() - # Exclude bindings with no members - return len(list(self.__iter__())) - - def __getitem__(self, key): - self.__check_version__() - for b in self._bindings: - if b["role"] == key: - return b["members"] - # If the binding does not yet exist, create one - # NOTE: This will create bindings with no members - # which are ignored by __iter__ and __len__ - new_binding = {"role": key, "members": set()} - self._bindings.append(new_binding) - return new_binding["members"] - - def __setitem__(self, key, value): - self.__check_version__() - value = set(value) - for binding in self._bindings: - if binding["role"] == key: - binding["members"] = value - return - self._bindings.append({"role": key, "members": value}) - - def __delitem__(self, key): - self.__check_version__() - for b in self._bindings: - if b["role"] == key: - self._bindings.remove(b) - return - raise KeyError(key) - - def __check_version__(self): - """Raise InvalidOperationException if version is greater than 1 or policy contains conditions.""" - raise_version = self.version is not None and self.version > 1 - - if raise_version or self._contains_conditions(): - raise InvalidOperationException(_DICT_ACCESS_MSG) - - def _contains_conditions(self): - for b in self._bindings: - if b.get("condition") is not None: - return True - return False - - @property - def bindings(self): - """The policy's list of bindings. - - A binding is specified by a dictionary with keys: - - * role (str): Role that is assigned to `members`. - - * members (:obj:`set` of str): Specifies the identities associated to this binding. - - * condition (:obj:`dict` of str:str): Specifies a condition under which this binding will apply. - - * title (str): Title for the condition. - - * description (:obj:str, optional): Description of the condition. - - * expression: A CEL expression. - - Type: - :obj:`list` of :obj:`dict` - - See: - Policy versions https://cloud.google.com/iam/docs/policies#versions - Conditions overview https://cloud.google.com/iam/docs/conditions-overview. - - Example: - - .. code-block:: python - - USER = "user:phred@example.com" - ADMIN_GROUP = "group:admins@groups.example.com" - SERVICE_ACCOUNT = "serviceAccount:account-1234@accounts.example.com" - CONDITION = { - "title": "request_time", - "description": "Requests made before 2021-01-01T00:00:00Z", # Optional - "expression": "request.time < timestamp(\"2021-01-01T00:00:00Z\")" - } - - # Set policy's version to 3 before setting bindings containing conditions. - policy.version = 3 - - policy.bindings = [ - { - "role": "roles/viewer", - "members": {USER, ADMIN_GROUP, SERVICE_ACCOUNT}, - "condition": CONDITION - }, - ... - ] - """ - return self._bindings - - @bindings.setter - def bindings(self, bindings): - self._bindings = bindings - - @property - def owners(self): - """Legacy access to owner role. - - Raise InvalidOperationException if version is greater than 1 or policy contains conditions. - - DEPRECATED: use `policy.bindings` to access bindings instead. - """ - result = set() - for role in self._OWNER_ROLES: - for member in self.get(role, ()): - result.add(member) - return frozenset(result) - - @owners.setter - def owners(self, value): - """Update owners. - - Raise InvalidOperationException if version is greater than 1 or policy contains conditions. - - DEPRECATED: use `policy.bindings` to access bindings instead. - """ - warnings.warn( - _ASSIGNMENT_DEPRECATED_MSG.format("owners", OWNER_ROLE), DeprecationWarning - ) - self[OWNER_ROLE] = value - - @property - def editors(self): - """Legacy access to editor role. - - Raise InvalidOperationException if version is greater than 1 or policy contains conditions. - - DEPRECATED: use `policy.bindings` to access bindings instead. - """ - result = set() - for role in self._EDITOR_ROLES: - for member in self.get(role, ()): - result.add(member) - return frozenset(result) - - @editors.setter - def editors(self, value): - """Update editors. - - Raise InvalidOperationException if version is greater than 1 or policy contains conditions. - - DEPRECATED: use `policy.bindings` to modify bindings instead. - """ - warnings.warn( - _ASSIGNMENT_DEPRECATED_MSG.format("editors", EDITOR_ROLE), - DeprecationWarning, - ) - self[EDITOR_ROLE] = value - - @property - def viewers(self): - """Legacy access to viewer role. - - Raise InvalidOperationException if version is greater than 1 or policy contains conditions. - - DEPRECATED: use `policy.bindings` to modify bindings instead. - """ - result = set() - for role in self._VIEWER_ROLES: - for member in self.get(role, ()): - result.add(member) - return frozenset(result) - - @viewers.setter - def viewers(self, value): - """Update viewers. - - Raise InvalidOperationException if version is greater than 1 or policy contains conditions. - - DEPRECATED: use `policy.bindings` to modify bindings instead. - """ - warnings.warn( - _ASSIGNMENT_DEPRECATED_MSG.format("viewers", VIEWER_ROLE), - DeprecationWarning, - ) - self[VIEWER_ROLE] = value - - @staticmethod - def user(email): - """Factory method for a user member. - - Args: - email (str): E-mail for this particular user. - - Returns: - str: A member string corresponding to the given user. - """ - return "user:%s" % (email,) - - @staticmethod - def service_account(email): - """Factory method for a service account member. - - Args: - email (str): E-mail for this particular service account. - - Returns: - str: A member string corresponding to the given service account. - - """ - return "serviceAccount:%s" % (email,) - - @staticmethod - def group(email): - """Factory method for a group member. - - Args: - email (str): An id or e-mail for this particular group. - - Returns: - str: A member string corresponding to the given group. - """ - return "group:%s" % (email,) - - @staticmethod - def domain(domain): - """Factory method for a domain member. - - Args: - domain (str): The domain for this member. - - Returns: - str: A member string corresponding to the given domain. - """ - return "domain:%s" % (domain,) - - @staticmethod - def all_users(): - """Factory method for a member representing all users. - - Returns: - str: A member string representing all users. - """ - return "allUsers" - - @staticmethod - def authenticated_users(): - """Factory method for a member representing all authenticated users. - - Returns: - str: A member string representing all authenticated users. - """ - return "allAuthenticatedUsers" - - @classmethod - def from_api_repr(cls, resource): - """Factory: create a policy from a JSON resource. - - Args: - resource (dict): policy resource returned by ``getIamPolicy`` API. - - Returns: - :class:`Policy`: the parsed policy - """ - version = resource.get("version") - etag = resource.get("etag") - policy = cls(etag, version) - policy.bindings = resource.get("bindings", []) - - for binding in policy.bindings: - binding["members"] = set(binding.get("members", ())) - - return policy - - def to_api_repr(self): - """Render a JSON policy resource. - - Returns: - dict: a resource to be passed to the ``setIamPolicy`` API. - """ - resource = {} - - if self.etag is not None: - resource["etag"] = self.etag - - if self.version is not None: - resource["version"] = self.version - - if self._bindings and len(self._bindings) > 0: - bindings = [] - for binding in self._bindings: - members = binding.get("members") - if members: - new_binding = {"role": binding["role"], "members": sorted(members)} - condition = binding.get("condition") - if condition: - new_binding["condition"] = condition - bindings.append(new_binding) - - if bindings: - # Sort bindings by role - key = operator.itemgetter("role") - resource["bindings"] = sorted(bindings, key=key) - - return resource diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operation.py b/notification-service/venv/Lib/site-packages/google/api_core/operation.py deleted file mode 100644 index 5206243..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operation.py +++ /dev/null @@ -1,365 +0,0 @@ -# Copyright 2016 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Futures for long-running operations returned from Google Cloud APIs. - -These futures can be used to synchronously wait for the result of a -long-running operation using :meth:`Operation.result`: - - -.. code-block:: python - - operation = my_api_client.long_running_method() - result = operation.result() - -Or asynchronously using callbacks and :meth:`Operation.add_done_callback`: - -.. code-block:: python - - operation = my_api_client.long_running_method() - - def my_callback(future): - result = future.result() - - operation.add_done_callback(my_callback) - -""" - -import functools -import threading - -from google.api_core import exceptions -from google.api_core import protobuf_helpers -from google.api_core.future import polling -from google.longrunning import operations_pb2 -from google.protobuf import json_format -from google.rpc import code_pb2 - - -class Operation(polling.PollingFuture): - """A Future for interacting with a Google API Long-Running Operation. - - Args: - operation (google.longrunning.operations_pb2.Operation): The - initial operation. - refresh (Callable[[], ~.api_core.operation.Operation]): A callable that - returns the latest state of the operation. - cancel (Callable[[], None]): A callable that tries to cancel - the operation. - result_type (func:`type`): The protobuf type for the operation's - result. - metadata_type (func:`type`): The protobuf type for the operation's - metadata. - polling (google.api_core.retry.Retry): The configuration used for polling. - This parameter controls how often :meth:`done` is polled. If the - ``timeout`` argument is specified in the :meth:`result` method, it will - override the ``polling.timeout`` property. - retry (google.api_core.retry.Retry): DEPRECATED: use ``polling`` instead. - If specified it will override ``polling`` parameter to maintain - backward compatibility. - """ - - def __init__( - self, - operation, - refresh, - cancel, - result_type, - metadata_type=None, - polling=polling.DEFAULT_POLLING, - **kwargs, - ): - super(Operation, self).__init__(polling=polling, **kwargs) - self._operation = operation - self._refresh = refresh - self._cancel = cancel - self._result_type = result_type - self._metadata_type = metadata_type - self._completion_lock = threading.Lock() - # Invoke this in case the operation came back already complete. - self._set_result_from_operation() - - @property - def operation(self): - """google.longrunning.Operation: The current long-running operation.""" - return self._operation - - @property - def metadata(self): - """google.protobuf.Message: the current operation metadata.""" - if not self._operation.HasField("metadata"): - return None - - return protobuf_helpers.from_any_pb( - self._metadata_type, self._operation.metadata - ) - - @classmethod - def deserialize(self, payload): - """Deserialize a ``google.longrunning.Operation`` protocol buffer. - - Args: - payload (bytes): A serialized operation protocol buffer. - - Returns: - ~.operations_pb2.Operation: An Operation protobuf object. - """ - return operations_pb2.Operation.FromString(payload) - - def _set_result_from_operation(self): - """Set the result or exception from the operation if it is complete.""" - # This must be done in a lock to prevent the polling thread - # and main thread from both executing the completion logic - # at the same time. - with self._completion_lock: - # If the operation isn't complete or if the result has already been - # set, do not call set_result/set_exception again. - # Note: self._result_set is set to True in set_result and - # set_exception, in case those methods are invoked directly. - if not self._operation.done or self._result_set: - return - - if self._operation.HasField("response"): - response = protobuf_helpers.from_any_pb( - self._result_type, self._operation.response - ) - self.set_result(response) - elif self._operation.HasField("error"): - exception = exceptions.from_grpc_status( - status_code=self._operation.error.code, - message=self._operation.error.message, - errors=(self._operation.error,), - response=self._operation, - ) - self.set_exception(exception) - else: - exception = exceptions.GoogleAPICallError( - "Unexpected state: Long-running operation had neither " - "response nor error set." - ) - self.set_exception(exception) - - def _refresh_and_update(self, retry=None): - """Refresh the operation and update the result if needed. - - Args: - retry (google.api_core.retry.Retry): (Optional) How to retry the RPC. - """ - # If the currently cached operation is done, no need to make another - # RPC as it will not change once done. - if not self._operation.done: - self._operation = self._refresh(retry=retry) if retry else self._refresh() - self._set_result_from_operation() - - def done(self, retry=None): - """Checks to see if the operation is complete. - - Args: - retry (google.api_core.retry.Retry): (Optional) How to retry the RPC. - - Returns: - bool: True if the operation is complete, False otherwise. - """ - self._refresh_and_update(retry) - return self._operation.done - - def cancel(self): - """Attempt to cancel the operation. - - Returns: - bool: True if the cancel RPC was made, False if the operation is - already complete. - """ - if self.done(): - return False - - self._cancel() - return True - - def cancelled(self): - """True if the operation was cancelled.""" - self._refresh_and_update() - return ( - self._operation.HasField("error") - and self._operation.error.code == code_pb2.CANCELLED - ) - - -def _refresh_http(api_request, operation_name, retry=None): - """Refresh an operation using a JSON/HTTP client. - - Args: - api_request (Callable): A callable used to make an API request. This - should generally be - :meth:`google.cloud._http.Connection.api_request`. - operation_name (str): The name of the operation. - retry (google.api_core.retry.Retry): (Optional) retry policy - - Returns: - google.longrunning.operations_pb2.Operation: The operation. - """ - path = "operations/{}".format(operation_name) - - if retry is not None: - api_request = retry(api_request) - - api_response = api_request(method="GET", path=path) - return json_format.ParseDict(api_response, operations_pb2.Operation()) - - -def _cancel_http(api_request, operation_name): - """Cancel an operation using a JSON/HTTP client. - - Args: - api_request (Callable): A callable used to make an API request. This - should generally be - :meth:`google.cloud._http.Connection.api_request`. - operation_name (str): The name of the operation. - """ - path = "operations/{}:cancel".format(operation_name) - api_request(method="POST", path=path) - - -def from_http_json(operation, api_request, result_type, **kwargs): - """Create an operation future using a HTTP/JSON client. - - This interacts with the long-running operations `service`_ (specific - to a given API) via `HTTP/JSON`_. - - .. _HTTP/JSON: https://cloud.google.com/speech/reference/rest/\ - v1beta1/operations#Operation - - Args: - operation (dict): Operation as a dictionary. - api_request (Callable): A callable used to make an API request. This - should generally be - :meth:`google.cloud._http.Connection.api_request`. - result_type (:func:`type`): The protobuf result type. - kwargs: Keyword args passed into the :class:`Operation` constructor. - - Returns: - ~.api_core.operation.Operation: The operation future to track the given - operation. - """ - operation_proto = json_format.ParseDict(operation, operations_pb2.Operation()) - refresh = functools.partial(_refresh_http, api_request, operation_proto.name) - cancel = functools.partial(_cancel_http, api_request, operation_proto.name) - return Operation(operation_proto, refresh, cancel, result_type, **kwargs) - - -def _refresh_grpc(operations_stub, operation_name, retry=None): - """Refresh an operation using a gRPC client. - - Args: - operations_stub (google.longrunning.operations_pb2.OperationsStub): - The gRPC operations stub. - operation_name (str): The name of the operation. - retry (google.api_core.retry.Retry): (Optional) retry policy - - Returns: - google.longrunning.operations_pb2.Operation: The operation. - """ - request_pb = operations_pb2.GetOperationRequest(name=operation_name) - - rpc = operations_stub.GetOperation - if retry is not None: - rpc = retry(rpc) - - return rpc(request_pb) - - -def _cancel_grpc(operations_stub, operation_name): - """Cancel an operation using a gRPC client. - - Args: - operations_stub (google.longrunning.operations_pb2.OperationsStub): - The gRPC operations stub. - operation_name (str): The name of the operation. - """ - request_pb = operations_pb2.CancelOperationRequest(name=operation_name) - operations_stub.CancelOperation(request_pb) - - -def from_grpc(operation, operations_stub, result_type, grpc_metadata=None, **kwargs): - """Create an operation future using a gRPC client. - - This interacts with the long-running operations `service`_ (specific - to a given API) via gRPC. - - .. _service: https://github.com/googleapis/googleapis/blob/\ - 050400df0fdb16f63b63e9dee53819044bffc857/\ - google/longrunning/operations.proto#L38 - - Args: - operation (google.longrunning.operations_pb2.Operation): The operation. - operations_stub (google.longrunning.operations_pb2.OperationsStub): - The operations stub. - result_type (:func:`type`): The protobuf result type. - grpc_metadata (Optional[List[Tuple[str, str]]]): Additional metadata to pass - to the rpc. - kwargs: Keyword args passed into the :class:`Operation` constructor. - - Returns: - ~.api_core.operation.Operation: The operation future to track the given - operation. - """ - refresh = functools.partial( - _refresh_grpc, - operations_stub, - operation.name, - metadata=grpc_metadata, - ) - cancel = functools.partial( - _cancel_grpc, - operations_stub, - operation.name, - metadata=grpc_metadata, - ) - return Operation(operation, refresh, cancel, result_type, **kwargs) - - -def from_gapic(operation, operations_client, result_type, grpc_metadata=None, **kwargs): - """Create an operation future from a gapic client. - - This interacts with the long-running operations `service`_ (specific - to a given API) via a gapic client. - - .. _service: https://github.com/googleapis/googleapis/blob/\ - 050400df0fdb16f63b63e9dee53819044bffc857/\ - google/longrunning/operations.proto#L38 - - Args: - operation (google.longrunning.operations_pb2.Operation): The operation. - operations_client (google.api_core.operations_v1.OperationsClient): - The operations client. - result_type (:func:`type`): The protobuf result type. - grpc_metadata (Optional[List[Tuple[str, str]]]): Additional metadata to pass - to the rpc. - kwargs: Keyword args passed into the :class:`Operation` constructor. - - Returns: - ~.api_core.operation.Operation: The operation future to track the given - operation. - """ - refresh = functools.partial( - operations_client.get_operation, - operation.name, - metadata=grpc_metadata, - ) - cancel = functools.partial( - operations_client.cancel_operation, - operation.name, - metadata=grpc_metadata, - ) - return Operation(operation, refresh, cancel, result_type, **kwargs) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operation_async.py b/notification-service/venv/Lib/site-packages/google/api_core/operation_async.py deleted file mode 100644 index 2fd341d..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operation_async.py +++ /dev/null @@ -1,225 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""AsyncIO futures for long-running operations returned from Google Cloud APIs. - -These futures can be used to await for the result of a long-running operation -using :meth:`AsyncOperation.result`: - - -.. code-block:: python - - operation = my_api_client.long_running_method() - result = await operation.result() - -Or asynchronously using callbacks and :meth:`Operation.add_done_callback`: - -.. code-block:: python - - operation = my_api_client.long_running_method() - - def my_callback(future): - result = await future.result() - - operation.add_done_callback(my_callback) - -""" - -import functools -import threading - -from google.api_core import exceptions -from google.api_core import protobuf_helpers -from google.api_core.future import async_future -from google.longrunning import operations_pb2 -from google.rpc import code_pb2 - - -class AsyncOperation(async_future.AsyncFuture): - """A Future for interacting with a Google API Long-Running Operation. - - Args: - operation (google.longrunning.operations_pb2.Operation): The - initial operation. - refresh (Callable[[], ~.api_core.operation.Operation]): A callable that - returns the latest state of the operation. - cancel (Callable[[], None]): A callable that tries to cancel - the operation. - result_type (func:`type`): The protobuf type for the operation's - result. - metadata_type (func:`type`): The protobuf type for the operation's - metadata. - retry (google.api_core.retry.Retry): The retry configuration used - when polling. This can be used to control how often :meth:`done` - is polled. Regardless of the retry's ``deadline``, it will be - overridden by the ``timeout`` argument to :meth:`result`. - """ - - def __init__( - self, - operation, - refresh, - cancel, - result_type, - metadata_type=None, - retry=async_future.DEFAULT_RETRY, - ): - super().__init__(retry=retry) - self._operation = operation - self._refresh = refresh - self._cancel = cancel - self._result_type = result_type - self._metadata_type = metadata_type - self._completion_lock = threading.Lock() - # Invoke this in case the operation came back already complete. - self._set_result_from_operation() - - @property - def operation(self): - """google.longrunning.Operation: The current long-running operation.""" - return self._operation - - @property - def metadata(self): - """google.protobuf.Message: the current operation metadata.""" - if not self._operation.HasField("metadata"): - return None - - return protobuf_helpers.from_any_pb( - self._metadata_type, self._operation.metadata - ) - - @classmethod - def deserialize(cls, payload): - """Deserialize a ``google.longrunning.Operation`` protocol buffer. - - Args: - payload (bytes): A serialized operation protocol buffer. - - Returns: - ~.operations_pb2.Operation: An Operation protobuf object. - """ - return operations_pb2.Operation.FromString(payload) - - def _set_result_from_operation(self): - """Set the result or exception from the operation if it is complete.""" - # This must be done in a lock to prevent the async_future thread - # and main thread from both executing the completion logic - # at the same time. - with self._completion_lock: - # If the operation isn't complete or if the result has already been - # set, do not call set_result/set_exception again. - if not self._operation.done or self._future.done(): - return - - if self._operation.HasField("response"): - response = protobuf_helpers.from_any_pb( - self._result_type, self._operation.response - ) - self.set_result(response) - elif self._operation.HasField("error"): - exception = exceptions.GoogleAPICallError( - self._operation.error.message, - errors=(self._operation.error,), - response=self._operation, - ) - self.set_exception(exception) - else: - exception = exceptions.GoogleAPICallError( - "Unexpected state: Long-running operation had neither " - "response nor error set." - ) - self.set_exception(exception) - - async def _refresh_and_update(self, retry=async_future.DEFAULT_RETRY): - """Refresh the operation and update the result if needed. - - Args: - retry (google.api_core.retry.Retry): (Optional) How to retry the RPC. - """ - # If the currently cached operation is done, no need to make another - # RPC as it will not change once done. - if not self._operation.done: - self._operation = await self._refresh(retry=retry) - self._set_result_from_operation() - - async def done(self, retry=async_future.DEFAULT_RETRY): - """Checks to see if the operation is complete. - - Args: - retry (google.api_core.retry.Retry): (Optional) How to retry the RPC. - - Returns: - bool: True if the operation is complete, False otherwise. - """ - await self._refresh_and_update(retry) - return self._operation.done - - async def cancel(self): - """Attempt to cancel the operation. - - Returns: - bool: True if the cancel RPC was made, False if the operation is - already complete. - """ - result = await self.done() - if result: - return False - else: - await self._cancel() - return True - - async def cancelled(self): - """True if the operation was cancelled.""" - await self._refresh_and_update() - return ( - self._operation.HasField("error") - and self._operation.error.code == code_pb2.CANCELLED - ) - - -def from_gapic(operation, operations_client, result_type, grpc_metadata=None, **kwargs): - """Create an operation future from a gapic client. - - This interacts with the long-running operations `service`_ (specific - to a given API) via a gapic client. - - .. _service: https://github.com/googleapis/googleapis/blob/\ - 050400df0fdb16f63b63e9dee53819044bffc857/\ - google/longrunning/operations.proto#L38 - - Args: - operation (google.longrunning.operations_pb2.Operation): The operation. - operations_client (google.api_core.operations_v1.OperationsClient): - The operations client. - result_type (:func:`type`): The protobuf result type. - grpc_metadata (Optional[List[Tuple[str, str]]]): Additional metadata to pass - to the rpc. - kwargs: Keyword args passed into the :class:`Operation` constructor. - - Returns: - ~.api_core.operation.Operation: The operation future to track the given - operation. - """ - refresh = functools.partial( - operations_client.get_operation, - operation.name, - metadata=grpc_metadata, - ) - cancel = functools.partial( - operations_client.cancel_operation, - operation.name, - metadata=grpc_metadata, - ) - return AsyncOperation(operation, refresh, cancel, result_type, **kwargs) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__init__.py b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__init__.py deleted file mode 100644 index 4db32a4..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__init__.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Package for interacting with the google.longrunning.operations meta-API.""" - -from google.api_core.operations_v1.abstract_operations_client import AbstractOperationsClient -from google.api_core.operations_v1.operations_async_client import OperationsAsyncClient -from google.api_core.operations_v1.operations_client import OperationsClient -from google.api_core.operations_v1.transports.rest import OperationsRestTransport - -__all__ = [ - "AbstractOperationsClient", - "OperationsAsyncClient", - "OperationsClient", - "OperationsRestTransport" -] - -try: - from google.api_core.operations_v1.transports.rest_asyncio import ( - AsyncOperationsRestTransport, - ) - from google.api_core.operations_v1.operations_rest_client_async import AsyncOperationsRestClient - - __all__ += ["AsyncOperationsRestClient", "AsyncOperationsRestTransport"] -except ImportError: - # This import requires the `async_rest` extra. - # Don't raise an exception if `AsyncOperationsRestTransport` cannot be imported - # as other transports are still available. - pass diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index f62e7a5..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/abstract_operations_base_client.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/abstract_operations_base_client.cpython-312.pyc deleted file mode 100644 index cd8ef7b..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/abstract_operations_base_client.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/abstract_operations_client.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/abstract_operations_client.cpython-312.pyc deleted file mode 100644 index 758bb76..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/abstract_operations_client.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/operations_async_client.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/operations_async_client.cpython-312.pyc deleted file mode 100644 index b49c54f..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/operations_async_client.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/operations_client.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/operations_client.cpython-312.pyc deleted file mode 100644 index 2bd01de..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/operations_client.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/operations_client_config.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/operations_client_config.cpython-312.pyc deleted file mode 100644 index ff79cd3..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/operations_client_config.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/operations_rest_client_async.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/operations_rest_client_async.cpython-312.pyc deleted file mode 100644 index 727cd1c..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/operations_rest_client_async.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/pagers.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/pagers.cpython-312.pyc deleted file mode 100644 index 44aa4f7..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/pagers.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/pagers_async.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/pagers_async.cpython-312.pyc deleted file mode 100644 index a3c04d7..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/pagers_async.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/pagers_base.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/pagers_base.cpython-312.pyc deleted file mode 100644 index f0f7ac0..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/__pycache__/pagers_base.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/abstract_operations_base_client.py b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/abstract_operations_base_client.py deleted file mode 100644 index f62f60b..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/abstract_operations_base_client.py +++ /dev/null @@ -1,376 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from collections import OrderedDict -import os -import re -from typing import Dict, Optional, Type, Union - -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core.operations_v1.transports.base import ( - DEFAULT_CLIENT_INFO, - OperationsTransport, -) -from google.api_core.operations_v1.transports.rest import OperationsRestTransport - -try: - from google.api_core.operations_v1.transports.rest_asyncio import ( - AsyncOperationsRestTransport, - ) - - HAS_ASYNC_REST_DEPENDENCIES = True -except ImportError as e: - HAS_ASYNC_REST_DEPENDENCIES = False - ASYNC_REST_EXCEPTION = e - -from google.auth import credentials as ga_credentials # type: ignore -from google.auth.exceptions import MutualTLSChannelError # type: ignore -from google.auth.transport import mtls # type: ignore - - -class AbstractOperationsBaseClientMeta(type): - """Metaclass for the Operations Base client. - - This provides base class-level methods for building and retrieving - support objects (e.g. transport) without polluting the client instance - objects. - """ - - _transport_registry = OrderedDict() # type: Dict[str, Type[OperationsTransport]] - _transport_registry["rest"] = OperationsRestTransport - if HAS_ASYNC_REST_DEPENDENCIES: - _transport_registry["rest_asyncio"] = AsyncOperationsRestTransport - - def get_transport_class( - cls, - label: Optional[str] = None, - ) -> Type[OperationsTransport]: - """Returns an appropriate transport class. - - Args: - label: The name of the desired transport. If none is - provided, then the first transport in the registry is used. - - Returns: - The transport class to use. - """ - # If a specific transport is requested, return that one. - if ( - label == "rest_asyncio" and not HAS_ASYNC_REST_DEPENDENCIES - ): # pragma: NO COVER - raise ASYNC_REST_EXCEPTION - - if label: - return cls._transport_registry[label] - - # No transport is requested; return the default (that is, the first one - # in the dictionary). - return next(iter(cls._transport_registry.values())) - - -class AbstractOperationsBaseClient(metaclass=AbstractOperationsBaseClientMeta): - """Manages long-running operations with an API service. - - When an API method normally takes long time to complete, it can be - designed to return [Operation][google.api_core.operations_v1.Operation] to the - client, and the client can use this interface to receive the real - response asynchronously by polling the operation resource, or pass - the operation resource to another API (such as Google Cloud Pub/Sub - API) to receive the response. Any API service that returns - long-running operations should implement the ``Operations`` - interface so developers can have a consistent client experience. - """ - - @staticmethod - def _get_default_mtls_endpoint(api_endpoint): - """Converts api endpoint to mTLS endpoint. - - Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to - "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. - Args: - api_endpoint (Optional[str]): the api endpoint to convert. - Returns: - str: converted mTLS api endpoint. - """ - if not api_endpoint: - return api_endpoint - - mtls_endpoint_re = re.compile( - r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" - ) - - m = mtls_endpoint_re.match(api_endpoint) - name, mtls, sandbox, googledomain = m.groups() - if mtls or not googledomain: - return api_endpoint - - if sandbox: - return api_endpoint.replace( - "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" - ) - - return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") - - DEFAULT_ENDPOINT = "longrunning.googleapis.com" - DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore - DEFAULT_ENDPOINT - ) - - @classmethod - def from_service_account_info(cls, info: dict, *args, **kwargs): - """ - This class method should be overridden by the subclasses. - - Args: - info (dict): The service account private key info. - args: Additional arguments to pass to the constructor. - kwargs: Additional arguments to pass to the constructor. - - Raises: - NotImplementedError: If the method is called on the base class. - """ - raise NotImplementedError("`from_service_account_info` is not implemented.") - - @classmethod - def from_service_account_file(cls, filename: str, *args, **kwargs): - """ - This class method should be overridden by the subclasses. - - Args: - filename (str): The path to the service account private key json - file. - args: Additional arguments to pass to the constructor. - kwargs: Additional arguments to pass to the constructor. - - Raises: - NotImplementedError: If the method is called on the base class. - """ - raise NotImplementedError("`from_service_account_file` is not implemented.") - - from_service_account_json = from_service_account_file - - @property - def transport(self) -> OperationsTransport: - """Returns the transport used by the client instance. - - Returns: - OperationsTransport: The transport used by the client - instance. - """ - return self._transport - - @staticmethod - def common_billing_account_path( - billing_account: str, - ) -> str: - """Returns a fully-qualified billing_account string.""" - return "billingAccounts/{billing_account}".format( - billing_account=billing_account, - ) - - @staticmethod - def parse_common_billing_account_path(path: str) -> Dict[str, str]: - """Parse a billing_account path into its component segments.""" - m = re.match(r"^billingAccounts/(?P.+?)$", path) - return m.groupdict() if m else {} - - @staticmethod - def common_folder_path( - folder: str, - ) -> str: - """Returns a fully-qualified folder string.""" - return "folders/{folder}".format( - folder=folder, - ) - - @staticmethod - def parse_common_folder_path(path: str) -> Dict[str, str]: - """Parse a folder path into its component segments.""" - m = re.match(r"^folders/(?P.+?)$", path) - return m.groupdict() if m else {} - - @staticmethod - def common_organization_path( - organization: str, - ) -> str: - """Returns a fully-qualified organization string.""" - return "organizations/{organization}".format( - organization=organization, - ) - - @staticmethod - def parse_common_organization_path(path: str) -> Dict[str, str]: - """Parse a organization path into its component segments.""" - m = re.match(r"^organizations/(?P.+?)$", path) - return m.groupdict() if m else {} - - @staticmethod - def common_project_path( - project: str, - ) -> str: - """Returns a fully-qualified project string.""" - return "projects/{project}".format( - project=project, - ) - - @staticmethod - def parse_common_project_path(path: str) -> Dict[str, str]: - """Parse a project path into its component segments.""" - m = re.match(r"^projects/(?P.+?)$", path) - return m.groupdict() if m else {} - - @staticmethod - def common_location_path( - project: str, - location: str, - ) -> str: - """Returns a fully-qualified location string.""" - return "projects/{project}/locations/{location}".format( - project=project, - location=location, - ) - - @staticmethod - def parse_common_location_path(path: str) -> Dict[str, str]: - """Parse a location path into its component segments.""" - m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) - return m.groupdict() if m else {} - - def __init__( - self, - *, - credentials: Optional[ga_credentials.Credentials] = None, - transport: Union[str, OperationsTransport, None] = None, - client_options: Optional[client_options_lib.ClientOptions] = None, - client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, - ) -> None: - """Instantiates the operations client. - - Args: - credentials (Optional[google.auth.credentials.Credentials]): The - authorization credentials to attach to requests. These - credentials identify the application to the service; if none - are specified, the client will attempt to ascertain the - credentials from the environment. - transport (Union[str, OperationsTransport]): The - transport to use. If set to None, a transport is chosen - automatically. - client_options (google.api_core.client_options.ClientOptions): Custom options for the - client. It won't take effect if a ``transport`` instance is provided. - (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT - environment variable can also be used to override the endpoint: - "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint) and "auto" (auto switch to the - default mTLS endpoint if client certificate is present, this is - the default value). However, the ``api_endpoint`` property takes - precedence if provided. - (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable - is "true", then the ``client_cert_source`` property can be used - to provide client certificate for mutual TLS transport. If - not provided, the default SSL client certificate will be used if - present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not - set, no client certificate will be used. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - - Raises: - google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport - creation failed for any reason. - """ - if isinstance(client_options, dict): - client_options = client_options_lib.from_dict(client_options) - if client_options is None: - client_options = client_options_lib.ClientOptions() - - # Create SSL credentials for mutual TLS if needed. - if hasattr(mtls, "should_use_client_cert"): - use_client_cert = mtls.should_use_client_cert() - else: - # if unsupported, fallback to reading from env var - use_client_cert_str = os.getenv( - "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false" - ).lower() - if use_client_cert_str not in ("true", "false"): - raise ValueError( - "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be" - " either `true` or `false`" - ) - use_client_cert = use_client_cert_str == "true" - client_cert_source_func = None - is_mtls = False - if use_client_cert: - if client_options.client_cert_source: - is_mtls = True - client_cert_source_func = client_options.client_cert_source - else: - is_mtls = mtls.has_default_client_cert_source() - if is_mtls: - client_cert_source_func = mtls.default_client_cert_source() - else: - client_cert_source_func = None - - # Figure out which api endpoint to use. - if client_options.api_endpoint is not None: - api_endpoint = client_options.api_endpoint - else: - use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") - if use_mtls_env == "never": - api_endpoint = self.DEFAULT_ENDPOINT - elif use_mtls_env == "always": - api_endpoint = self.DEFAULT_MTLS_ENDPOINT - elif use_mtls_env == "auto": - if is_mtls: - api_endpoint = self.DEFAULT_MTLS_ENDPOINT - else: - api_endpoint = self.DEFAULT_ENDPOINT - else: - raise MutualTLSChannelError( - "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " - "values: never, auto, always" - ) - - # Save or instantiate the transport. - # Ordinarily, we provide the transport, but allowing a custom transport - # instance provides an extensibility point for unusual situations. - if isinstance(transport, OperationsTransport): - # transport is a OperationsTransport instance. - if credentials or client_options.credentials_file: - raise ValueError( - "When providing a transport instance, " - "provide its credentials directly." - ) - if client_options.scopes: - raise ValueError( - "When providing a transport instance, provide its scopes " - "directly." - ) - self._transport = transport - else: - Transport = type(self).get_transport_class(transport) - self._transport = Transport( - credentials=credentials, - credentials_file=client_options.credentials_file, - host=api_endpoint, - scopes=client_options.scopes, - client_cert_source_for_mtls=client_cert_source_func, - quota_project_id=client_options.quota_project_id, - client_info=client_info, - always_use_jwt_access=True, - ) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/abstract_operations_client.py b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/abstract_operations_client.py deleted file mode 100644 index fc44536..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/abstract_operations_client.py +++ /dev/null @@ -1,387 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -from typing import Optional, Sequence, Tuple, Union - -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import retry as retries # type: ignore -from google.api_core.operations_v1 import pagers -from google.api_core.operations_v1.transports.base import ( - DEFAULT_CLIENT_INFO, - OperationsTransport, -) -from google.api_core.operations_v1.abstract_operations_base_client import ( - AbstractOperationsBaseClient, -) -from google.auth import credentials as ga_credentials # type: ignore -from google.longrunning import operations_pb2 -from google.oauth2 import service_account # type: ignore -import grpc - -OptionalRetry = Union[retries.Retry, object] - - -class AbstractOperationsClient(AbstractOperationsBaseClient): - """Manages long-running operations with an API service. - - When an API method normally takes long time to complete, it can be - designed to return [Operation][google.api_core.operations_v1.Operation] to the - client, and the client can use this interface to receive the real - response asynchronously by polling the operation resource, or pass - the operation resource to another API (such as Google Cloud Pub/Sub - API) to receive the response. Any API service that returns - long-running operations should implement the ``Operations`` - interface so developers can have a consistent client experience. - """ - - def __init__( - self, - *, - credentials: Optional[ga_credentials.Credentials] = None, - transport: Union[str, OperationsTransport, None] = None, - client_options: Optional[client_options_lib.ClientOptions] = None, - client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, - ) -> None: - """Instantiates the operations client. - - Args: - credentials (Optional[google.auth.credentials.Credentials]): The - authorization credentials to attach to requests. These - credentials identify the application to the service; if none - are specified, the client will attempt to ascertain the - credentials from the environment. - transport (Union[str, OperationsTransport]): The - transport to use. If set to None, a transport is chosen - automatically. - client_options (google.api_core.client_options.ClientOptions): Custom options for the - client. It won't take effect if a ``transport`` instance is provided. - (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT - environment variable can also be used to override the endpoint: - "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint) and "auto" (auto switch to the - default mTLS endpoint if client certificate is present, this is - the default value). However, the ``api_endpoint`` property takes - precedence if provided. - (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable - is "true", then the ``client_cert_source`` property can be used - to provide client certificate for mutual TLS transport. If - not provided, the default SSL client certificate will be used if - present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not - set, no client certificate will be used. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - - Raises: - google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport - creation failed for any reason. - """ - super().__init__( - credentials=credentials, - transport=transport, - client_options=client_options, - client_info=client_info, - ) - - @classmethod - def from_service_account_info(cls, info: dict, *args, **kwargs): - """Creates an instance of this client using the provided credentials - info. - - Args: - info (dict): The service account private key info. - args: Additional arguments to pass to the constructor. - kwargs: Additional arguments to pass to the constructor. - - Returns: - AbstractOperationsClient: The constructed client. - """ - credentials = service_account.Credentials.from_service_account_info(info) - kwargs["credentials"] = credentials - return cls(*args, **kwargs) - - @classmethod - def from_service_account_file(cls, filename: str, *args, **kwargs): - """Creates an instance of this client using the provided credentials - file. - - Args: - filename (str): The path to the service account private key json - file. - args: Additional arguments to pass to the constructor. - kwargs: Additional arguments to pass to the constructor. - - Returns: - AbstractOperationsClient: The constructed client. - """ - credentials = service_account.Credentials.from_service_account_file(filename) - kwargs["credentials"] = credentials - return cls(*args, **kwargs) - - from_service_account_json = from_service_account_file - - def list_operations( - self, - name: str, - filter_: Optional[str] = None, - *, - page_size: Optional[int] = None, - page_token: Optional[str] = None, - retry: OptionalRetry = gapic_v1.method.DEFAULT, - timeout: Optional[float] = None, - compression: Optional[grpc.Compression] = gapic_v1.method.DEFAULT, - metadata: Sequence[Tuple[str, str]] = (), - ) -> pagers.ListOperationsPager: - r"""Lists operations that match the specified filter in the request. - If the server doesn't support this method, it returns - ``UNIMPLEMENTED``. - - NOTE: the ``name`` binding allows API services to override the - binding to use different resource name schemes, such as - ``users/*/operations``. To override the binding, API services - can add a binding such as ``"/v1/{name=users/*}/operations"`` to - their service configuration. For backwards compatibility, the - default name includes the operations collection id, however - overriding users must ensure the name binding is the parent - resource, without the operations collection id. - - Args: - name (str): - The name of the operation's parent - resource. - filter_ (str): - The standard list filter. - This corresponds to the ``filter`` field - on the ``request`` instance; if ``request`` is provided, this - should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, - should be retried. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - - Returns: - google.api_core.operations_v1.pagers.ListOperationsPager: - The response message for - [Operations.ListOperations][google.api_core.operations_v1.Operations.ListOperations]. - - Iterating over this object will yield results and - resolve additional pages automatically. - - """ - # Create a protobuf request object. - request = operations_pb2.ListOperationsRequest(name=name, filter=filter_) - if page_size is not None: - request.page_size = page_size - if page_token is not None: - request.page_token = page_token - - # Wrap the RPC method; this adds retry and timeout information, - # and friendly error handling. - rpc = self._transport._wrapped_methods[self._transport.list_operations] - - # Certain fields should be provided within the metadata header; - # add these here. - metadata = tuple(metadata or ()) + ( - gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), - ) - - # Send the request. - response = rpc( - request, - retry=retry, - timeout=timeout, - compression=compression, - metadata=metadata, - ) - - # This method is paged; wrap the response in a pager, which provides - # an `__iter__` convenience method. - response = pagers.ListOperationsPager( - method=rpc, - request=request, - response=response, - metadata=metadata, - ) - - # Done; return the response. - return response - - def get_operation( - self, - name: str, - *, - retry: OptionalRetry = gapic_v1.method.DEFAULT, - timeout: Optional[float] = None, - compression: Optional[grpc.Compression] = gapic_v1.method.DEFAULT, - metadata: Sequence[Tuple[str, str]] = (), - ) -> operations_pb2.Operation: - r"""Gets the latest state of a long-running operation. - Clients can use this method to poll the operation result - at intervals as recommended by the API service. - - Args: - name (str): - The name of the operation resource. - retry (google.api_core.retry.Retry): Designation of what errors, if any, - should be retried. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - - Returns: - google.longrunning.operations_pb2.Operation: - This resource represents a long- - running operation that is the result of a - network API call. - - """ - - request = operations_pb2.GetOperationRequest(name=name) - - # Wrap the RPC method; this adds retry and timeout information, - # and friendly error handling. - rpc = self._transport._wrapped_methods[self._transport.get_operation] - - # Certain fields should be provided within the metadata header; - # add these here. - metadata = tuple(metadata or ()) + ( - gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), - ) - - # Send the request. - response = rpc( - request, - retry=retry, - timeout=timeout, - compression=compression, - metadata=metadata, - ) - - # Done; return the response. - return response - - def delete_operation( - self, - name: str, - *, - retry: OptionalRetry = gapic_v1.method.DEFAULT, - timeout: Optional[float] = None, - compression: Optional[grpc.Compression] = gapic_v1.method.DEFAULT, - metadata: Sequence[Tuple[str, str]] = (), - ) -> None: - r"""Deletes a long-running operation. This method indicates that the - client is no longer interested in the operation result. It does - not cancel the operation. If the server doesn't support this - method, it returns ``google.rpc.Code.UNIMPLEMENTED``. - - Args: - name (str): - The name of the operation resource to - be deleted. - - This corresponds to the ``name`` field - on the ``request`` instance; if ``request`` is provided, this - should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, - should be retried. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - """ - # Create the request object. - request = operations_pb2.DeleteOperationRequest(name=name) - - # Wrap the RPC method; this adds retry and timeout information, - # and friendly error handling. - rpc = self._transport._wrapped_methods[self._transport.delete_operation] - - # Certain fields should be provided within the metadata header; - # add these here. - metadata = tuple(metadata or ()) + ( - gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), - ) - - # Send the request. - rpc( - request, - retry=retry, - timeout=timeout, - compression=compression, - metadata=metadata, - ) - - def cancel_operation( - self, - name: Optional[str] = None, - *, - retry: OptionalRetry = gapic_v1.method.DEFAULT, - timeout: Optional[float] = None, - compression: Optional[grpc.Compression] = gapic_v1.method.DEFAULT, - metadata: Sequence[Tuple[str, str]] = (), - ) -> None: - r"""Starts asynchronous cancellation on a long-running operation. - The server makes a best effort to cancel the operation, but - success is not guaranteed. If the server doesn't support this - method, it returns ``google.rpc.Code.UNIMPLEMENTED``. Clients - can use - [Operations.GetOperation][google.api_core.operations_v1.Operations.GetOperation] - or other methods to check whether the cancellation succeeded or - whether the operation completed despite cancellation. On - successful cancellation, the operation is not deleted; instead, - it becomes an operation with an - [Operation.error][google.api_core.operations_v1.Operation.error] value with - a [google.rpc.Status.code][google.rpc.Status.code] of 1, - corresponding to ``Code.CANCELLED``. - - Args: - name (str): - The name of the operation resource to - be cancelled. - - This corresponds to the ``name`` field - on the ``request`` instance; if ``request`` is provided, this - should not be set. - retry (google.api_core.retry.Retry): Designation of what errors, if any, - should be retried. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - """ - # Create the request object. - request = operations_pb2.CancelOperationRequest(name=name) - - # Wrap the RPC method; this adds retry and timeout information, - # and friendly error handling. - rpc = self._transport._wrapped_methods[self._transport.cancel_operation] - - # Certain fields should be provided within the metadata header; - # add these here. - metadata = tuple(metadata or ()) + ( - gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), - ) - - # Send the request. - rpc( - request, - retry=retry, - timeout=timeout, - compression=compression, - metadata=metadata, - ) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/operations_async_client.py b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/operations_async_client.py deleted file mode 100644 index a60c717..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/operations_async_client.py +++ /dev/null @@ -1,364 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""An async client for the google.longrunning.operations meta-API. - -.. _Google API Style Guide: - https://cloud.google.com/apis/design/design_pattern - s#long_running_operations -.. _google/longrunning/operations.proto: - https://github.com/googleapis/googleapis/blob/master/google/longrunning - /operations.proto -""" - -import functools - -from google.api_core import exceptions as core_exceptions -from google.api_core import gapic_v1, page_iterator_async -from google.api_core import retry_async as retries -from google.api_core import timeout as timeouts -from google.longrunning import operations_pb2 -from grpc import Compression - - -class OperationsAsyncClient: - """Async client for interacting with long-running operations. - - Args: - channel (aio.Channel): The gRPC AsyncIO channel associated with the - service that implements the ``google.longrunning.operations`` - interface. - client_config (dict): - A dictionary of call options for each method. If not specified - the default configuration is used. - """ - - def __init__(self, channel, client_config=None): - # Create the gRPC client stub with gRPC AsyncIO channel. - self.operations_stub = operations_pb2.OperationsStub(channel) - - default_retry = retries.AsyncRetry( - initial=0.1, # seconds - maximum=60.0, # seconds - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - timeout=600.0, # seconds - ) - default_timeout = timeouts.TimeToDeadlineTimeout(timeout=600.0) - - default_compression = Compression.NoCompression - - self._get_operation = gapic_v1.method_async.wrap_method( - self.operations_stub.GetOperation, - default_retry=default_retry, - default_timeout=default_timeout, - default_compression=default_compression, - ) - - self._list_operations = gapic_v1.method_async.wrap_method( - self.operations_stub.ListOperations, - default_retry=default_retry, - default_timeout=default_timeout, - default_compression=default_compression, - ) - - self._cancel_operation = gapic_v1.method_async.wrap_method( - self.operations_stub.CancelOperation, - default_retry=default_retry, - default_timeout=default_timeout, - default_compression=default_compression, - ) - - self._delete_operation = gapic_v1.method_async.wrap_method( - self.operations_stub.DeleteOperation, - default_retry=default_retry, - default_timeout=default_timeout, - default_compression=default_compression, - ) - - async def get_operation( - self, - name, - retry=gapic_v1.method_async.DEFAULT, - timeout=gapic_v1.method_async.DEFAULT, - compression=gapic_v1.method_async.DEFAULT, - metadata=None, - ): - """Gets the latest state of a long-running operation. - - Clients can use this method to poll the operation result at intervals - as recommended by the API service. - - Example: - >>> from google.api_core import operations_v1 - >>> api = operations_v1.OperationsClient() - >>> name = '' - >>> response = await api.get_operation(name) - - Args: - name (str): The name of the operation resource. - retry (google.api_core.retry.Retry): The retry strategy to use - when invoking the RPC. If unspecified, the default retry from - the client configuration will be used. If ``None``, then this - method will not retry the RPC at all. - timeout (float): The amount of time in seconds to wait for the RPC - to complete. Note that if ``retry`` is used, this timeout - applies to each individual attempt and the overall time it - takes for this method to complete may be longer. If - unspecified, the the default timeout in the client - configuration is used. If ``None``, then the RPC method will - not time out. - compression (grpc.Compression): An element of grpc.compression - e.g. grpc.compression.Gzip. - metadata (Optional[List[Tuple[str, str]]]): - Additional gRPC metadata. - - Returns: - google.longrunning.operations_pb2.Operation: The state of the - operation. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If an error occurred - while invoking the RPC, the appropriate ``GoogleAPICallError`` - subclass will be raised. - """ - request = operations_pb2.GetOperationRequest(name=name) - - # Add routing header - metadata = metadata or [] - metadata.append(gapic_v1.routing_header.to_grpc_metadata({"name": name})) - - return await self._get_operation( - request, - retry=retry, - timeout=timeout, - compression=compression, - metadata=metadata, - ) - - async def list_operations( - self, - name, - filter_, - retry=gapic_v1.method_async.DEFAULT, - timeout=gapic_v1.method_async.DEFAULT, - compression=gapic_v1.method_async.DEFAULT, - metadata=None, - ): - """ - Lists operations that match the specified filter in the request. - - Example: - >>> from google.api_core import operations_v1 - >>> api = operations_v1.OperationsClient() - >>> name = '' - >>> - >>> # Iterate over all results - >>> for operation in await api.list_operations(name): - >>> # process operation - >>> pass - >>> - >>> # Or iterate over results one page at a time - >>> iter = await api.list_operations(name) - >>> for page in iter.pages: - >>> for operation in page: - >>> # process operation - >>> pass - - Args: - name (str): The name of the operation collection. - filter_ (str): The standard list filter. - retry (google.api_core.retry.Retry): The retry strategy to use - when invoking the RPC. If unspecified, the default retry from - the client configuration will be used. If ``None``, then this - method will not retry the RPC at all. - timeout (float): The amount of time in seconds to wait for the RPC - to complete. Note that if ``retry`` is used, this timeout - applies to each individual attempt and the overall time it - takes for this method to complete may be longer. If - unspecified, the the default timeout in the client - configuration is used. If ``None``, then the RPC method will - not time out. - compression (grpc.Compression): An element of grpc.compression - e.g. grpc.compression.Gzip. - metadata (Optional[List[Tuple[str, str]]]): Additional gRPC - metadata. - - Returns: - google.api_core.page_iterator.Iterator: An iterator that yields - :class:`google.longrunning.operations_pb2.Operation` instances. - - Raises: - google.api_core.exceptions.MethodNotImplemented: If the server - does not support this method. Services are not required to - implement this method. - google.api_core.exceptions.GoogleAPICallError: If an error occurred - while invoking the RPC, the appropriate ``GoogleAPICallError`` - subclass will be raised. - """ - # Create the request object. - request = operations_pb2.ListOperationsRequest(name=name, filter=filter_) - - # Add routing header - metadata = metadata or [] - metadata.append(gapic_v1.routing_header.to_grpc_metadata({"name": name})) - - # Create the method used to fetch pages - method = functools.partial( - self._list_operations, - retry=retry, - timeout=timeout, - compression=compression, - metadata=metadata, - ) - - iterator = page_iterator_async.AsyncGRPCIterator( - client=None, - method=method, - request=request, - items_field="operations", - request_token_field="page_token", - response_token_field="next_page_token", - ) - - return iterator - - async def cancel_operation( - self, - name, - retry=gapic_v1.method_async.DEFAULT, - timeout=gapic_v1.method_async.DEFAULT, - compression=gapic_v1.method_async.DEFAULT, - metadata=None, - ): - """Starts asynchronous cancellation on a long-running operation. - - The server makes a best effort to cancel the operation, but success is - not guaranteed. Clients can use :meth:`get_operation` or service- - specific methods to check whether the cancellation succeeded or whether - the operation completed despite cancellation. On successful - cancellation, the operation is not deleted; instead, it becomes an - operation with an ``Operation.error`` value with a - ``google.rpc.Status.code`` of ``1``, corresponding to - ``Code.CANCELLED``. - - Example: - >>> from google.api_core import operations_v1 - >>> api = operations_v1.OperationsClient() - >>> name = '' - >>> api.cancel_operation(name) - - Args: - name (str): The name of the operation resource to be cancelled. - retry (google.api_core.retry.Retry): The retry strategy to use - when invoking the RPC. If unspecified, the default retry from - the client configuration will be used. If ``None``, then this - method will not retry the RPC at all. - timeout (float): The amount of time in seconds to wait for the RPC - to complete. Note that if ``retry`` is used, this timeout - applies to each individual attempt and the overall time it - takes for this method to complete may be longer. If - unspecified, the the default timeout in the client - configuration is used. If ``None``, then the RPC method will - not time out. - - Raises: - google.api_core.exceptions.MethodNotImplemented: If the server - does not support this method. Services are not required to - implement this method. - google.api_core.exceptions.GoogleAPICallError: If an error occurred - while invoking the RPC, the appropriate ``GoogleAPICallError`` - subclass will be raised. - compression (grpc.Compression): An element of grpc.compression - e.g. grpc.compression.Gzip. - metadata (Optional[List[Tuple[str, str]]]): Additional gRPC - metadata. - """ - # Create the request object. - request = operations_pb2.CancelOperationRequest(name=name) - - # Add routing header - metadata = metadata or [] - metadata.append(gapic_v1.routing_header.to_grpc_metadata({"name": name})) - - await self._cancel_operation( - request, - retry=retry, - timeout=timeout, - compression=compression, - metadata=metadata, - ) - - async def delete_operation( - self, - name, - retry=gapic_v1.method_async.DEFAULT, - timeout=gapic_v1.method_async.DEFAULT, - compression=gapic_v1.method_async.DEFAULT, - metadata=None, - ): - """Deletes a long-running operation. - - This method indicates that the client is no longer interested in the - operation result. It does not cancel the operation. - - Example: - >>> from google.api_core import operations_v1 - >>> api = operations_v1.OperationsClient() - >>> name = '' - >>> api.delete_operation(name) - - Args: - name (str): The name of the operation resource to be deleted. - retry (google.api_core.retry.Retry): The retry strategy to use - when invoking the RPC. If unspecified, the default retry from - the client configuration will be used. If ``None``, then this - method will not retry the RPC at all. - timeout (float): The amount of time in seconds to wait for the RPC - to complete. Note that if ``retry`` is used, this timeout - applies to each individual attempt and the overall time it - takes for this method to complete may be longer. If - unspecified, the the default timeout in the client - configuration is used. If ``None``, then the RPC method will - not time out. - compression (grpc.Compression): An element of grpc.compression - e.g. grpc.compression.Gzip. - metadata (Optional[List[Tuple[str, str]]]): Additional gRPC - metadata. - - Raises: - google.api_core.exceptions.MethodNotImplemented: If the server - does not support this method. Services are not required to - implement this method. - google.api_core.exceptions.GoogleAPICallError: If an error occurred - while invoking the RPC, the appropriate ``GoogleAPICallError`` - subclass will be raised. - """ - # Create the request object. - request = operations_pb2.DeleteOperationRequest(name=name) - - # Add routing header - metadata = metadata or [] - metadata.append(gapic_v1.routing_header.to_grpc_metadata({"name": name})) - - await self._delete_operation( - request, - retry=retry, - timeout=timeout, - compression=compression, - metadata=metadata, - ) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/operations_client.py b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/operations_client.py deleted file mode 100644 index d1d3fd5..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/operations_client.py +++ /dev/null @@ -1,378 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""A client for the google.longrunning.operations meta-API. - -This is a client that deals with long-running operations that follow the -pattern outlined by the `Google API Style Guide`_. - -When an API method normally takes long time to complete, it can be designed to -return ``Operation`` to the client, and the client can use this interface to -receive the real response asynchronously by polling the operation resource to -receive the response. - -It is not a separate service, but rather an interface implemented by a larger -service. The protocol-level definition is available at -`google/longrunning/operations.proto`_. Typically, this will be constructed -automatically by another client class to deal with operations. - -.. _Google API Style Guide: - https://cloud.google.com/apis/design/design_pattern - s#long_running_operations -.. _google/longrunning/operations.proto: - https://github.com/googleapis/googleapis/blob/master/google/longrunning - /operations.proto -""" - -import functools - -from google.api_core import exceptions as core_exceptions -from google.api_core import gapic_v1 -from google.api_core import page_iterator -from google.api_core import retry as retries -from google.api_core import timeout as timeouts -from google.longrunning import operations_pb2 -from grpc import Compression - - -class OperationsClient(object): - """Client for interacting with long-running operations within a service. - - Args: - channel (grpc.Channel): The gRPC channel associated with the service - that implements the ``google.longrunning.operations`` interface. - client_config (dict): - A dictionary of call options for each method. If not specified - the default configuration is used. - """ - - def __init__(self, channel, client_config=None): - # Create the gRPC client stub. - self.operations_stub = operations_pb2.OperationsStub(channel) - - default_retry = retries.Retry( - initial=0.1, # seconds - maximum=60.0, # seconds - multiplier=1.3, - predicate=retries.if_exception_type( - core_exceptions.DeadlineExceeded, - core_exceptions.ServiceUnavailable, - ), - timeout=600.0, # seconds - ) - default_timeout = timeouts.TimeToDeadlineTimeout(timeout=600.0) - - default_compression = Compression.NoCompression - - self._get_operation = gapic_v1.method.wrap_method( - self.operations_stub.GetOperation, - default_retry=default_retry, - default_timeout=default_timeout, - default_compression=default_compression, - ) - - self._list_operations = gapic_v1.method.wrap_method( - self.operations_stub.ListOperations, - default_retry=default_retry, - default_timeout=default_timeout, - default_compression=default_compression, - ) - - self._cancel_operation = gapic_v1.method.wrap_method( - self.operations_stub.CancelOperation, - default_retry=default_retry, - default_timeout=default_timeout, - default_compression=default_compression, - ) - - self._delete_operation = gapic_v1.method.wrap_method( - self.operations_stub.DeleteOperation, - default_retry=default_retry, - default_timeout=default_timeout, - default_compression=default_compression, - ) - - # Service calls - def get_operation( - self, - name, - retry=gapic_v1.method.DEFAULT, - timeout=gapic_v1.method.DEFAULT, - compression=gapic_v1.method.DEFAULT, - metadata=None, - ): - """Gets the latest state of a long-running operation. - - Clients can use this method to poll the operation result at intervals - as recommended by the API service. - - Example: - >>> from google.api_core import operations_v1 - >>> api = operations_v1.OperationsClient() - >>> name = '' - >>> response = api.get_operation(name) - - Args: - name (str): The name of the operation resource. - retry (google.api_core.retry.Retry): The retry strategy to use - when invoking the RPC. If unspecified, the default retry from - the client configuration will be used. If ``None``, then this - method will not retry the RPC at all. - timeout (float): The amount of time in seconds to wait for the RPC - to complete. Note that if ``retry`` is used, this timeout - applies to each individual attempt and the overall time it - takes for this method to complete may be longer. If - unspecified, the the default timeout in the client - configuration is used. If ``None``, then the RPC method will - not time out. - compression (grpc.Compression): An element of grpc.compression - e.g. grpc.compression.Gzip. - metadata (Optional[List[Tuple[str, str]]]): - Additional gRPC metadata. - - Returns: - google.longrunning.operations_pb2.Operation: The state of the - operation. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If an error occurred - while invoking the RPC, the appropriate ``GoogleAPICallError`` - subclass will be raised. - """ - request = operations_pb2.GetOperationRequest(name=name) - - # Add routing header - metadata = metadata or [] - metadata.append(gapic_v1.routing_header.to_grpc_metadata({"name": name})) - - return self._get_operation( - request, - retry=retry, - timeout=timeout, - compression=compression, - metadata=metadata, - ) - - def list_operations( - self, - name, - filter_, - retry=gapic_v1.method.DEFAULT, - timeout=gapic_v1.method.DEFAULT, - compression=gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Lists operations that match the specified filter in the request. - - Example: - >>> from google.api_core import operations_v1 - >>> api = operations_v1.OperationsClient() - >>> name = '' - >>> - >>> # Iterate over all results - >>> for operation in api.list_operations(name): - >>> # process operation - >>> pass - >>> - >>> # Or iterate over results one page at a time - >>> iter = api.list_operations(name) - >>> for page in iter.pages: - >>> for operation in page: - >>> # process operation - >>> pass - - Args: - name (str): The name of the operation collection. - filter_ (str): The standard list filter. - retry (google.api_core.retry.Retry): The retry strategy to use - when invoking the RPC. If unspecified, the default retry from - the client configuration will be used. If ``None``, then this - method will not retry the RPC at all. - timeout (float): The amount of time in seconds to wait for the RPC - to complete. Note that if ``retry`` is used, this timeout - applies to each individual attempt and the overall time it - takes for this method to complete may be longer. If - unspecified, the the default timeout in the client - configuration is used. If ``None``, then the RPC method will - not time out. - compression (grpc.Compression): An element of grpc.compression - e.g. grpc.compression.Gzip. - metadata (Optional[List[Tuple[str, str]]]): Additional gRPC - metadata. - - Returns: - google.api_core.page_iterator.Iterator: An iterator that yields - :class:`google.longrunning.operations_pb2.Operation` instances. - - Raises: - google.api_core.exceptions.MethodNotImplemented: If the server - does not support this method. Services are not required to - implement this method. - google.api_core.exceptions.GoogleAPICallError: If an error occurred - while invoking the RPC, the appropriate ``GoogleAPICallError`` - subclass will be raised. - """ - # Create the request object. - request = operations_pb2.ListOperationsRequest(name=name, filter=filter_) - - # Add routing header - metadata = metadata or [] - metadata.append(gapic_v1.routing_header.to_grpc_metadata({"name": name})) - - # Create the method used to fetch pages - method = functools.partial( - self._list_operations, - retry=retry, - timeout=timeout, - compression=compression, - metadata=metadata, - ) - - iterator = page_iterator.GRPCIterator( - client=None, - method=method, - request=request, - items_field="operations", - request_token_field="page_token", - response_token_field="next_page_token", - ) - - return iterator - - def cancel_operation( - self, - name, - retry=gapic_v1.method.DEFAULT, - timeout=gapic_v1.method.DEFAULT, - compression=gapic_v1.method.DEFAULT, - metadata=None, - ): - """Starts asynchronous cancellation on a long-running operation. - - The server makes a best effort to cancel the operation, but success is - not guaranteed. Clients can use :meth:`get_operation` or service- - specific methods to check whether the cancellation succeeded or whether - the operation completed despite cancellation. On successful - cancellation, the operation is not deleted; instead, it becomes an - operation with an ``Operation.error`` value with a - ``google.rpc.Status.code`` of ``1``, corresponding to - ``Code.CANCELLED``. - - Example: - >>> from google.api_core import operations_v1 - >>> api = operations_v1.OperationsClient() - >>> name = '' - >>> api.cancel_operation(name) - - Args: - name (str): The name of the operation resource to be cancelled. - retry (google.api_core.retry.Retry): The retry strategy to use - when invoking the RPC. If unspecified, the default retry from - the client configuration will be used. If ``None``, then this - method will not retry the RPC at all. - timeout (float): The amount of time in seconds to wait for the RPC - to complete. Note that if ``retry`` is used, this timeout - applies to each individual attempt and the overall time it - takes for this method to complete may be longer. If - unspecified, the the default timeout in the client - configuration is used. If ``None``, then the RPC method will - not time out. - compression (grpc.Compression): An element of grpc.compression - e.g. grpc.compression.Gzip. - metadata (Optional[List[Tuple[str, str]]]): Additional gRPC - metadata. - - Raises: - google.api_core.exceptions.MethodNotImplemented: If the server - does not support this method. Services are not required to - implement this method. - google.api_core.exceptions.GoogleAPICallError: If an error occurred - while invoking the RPC, the appropriate ``GoogleAPICallError`` - subclass will be raised. - """ - # Create the request object. - request = operations_pb2.CancelOperationRequest(name=name) - - # Add routing header - metadata = metadata or [] - metadata.append(gapic_v1.routing_header.to_grpc_metadata({"name": name})) - - self._cancel_operation( - request, - retry=retry, - timeout=timeout, - compression=compression, - metadata=metadata, - ) - - def delete_operation( - self, - name, - retry=gapic_v1.method.DEFAULT, - timeout=gapic_v1.method.DEFAULT, - compression=gapic_v1.method.DEFAULT, - metadata=None, - ): - """Deletes a long-running operation. - - This method indicates that the client is no longer interested in the - operation result. It does not cancel the operation. - - Example: - >>> from google.api_core import operations_v1 - >>> api = operations_v1.OperationsClient() - >>> name = '' - >>> api.delete_operation(name) - - Args: - name (str): The name of the operation resource to be deleted. - retry (google.api_core.retry.Retry): The retry strategy to use - when invoking the RPC. If unspecified, the default retry from - the client configuration will be used. If ``None``, then this - method will not retry the RPC at all. - timeout (float): The amount of time in seconds to wait for the RPC - to complete. Note that if ``retry`` is used, this timeout - applies to each individual attempt and the overall time it - takes for this method to complete may be longer. If - unspecified, the the default timeout in the client - configuration is used. If ``None``, then the RPC method will - not time out. - compression (grpc.Compression): An element of grpc.compression - e.g. grpc.compression.Gzip. - metadata (Optional[List[Tuple[str, str]]]): Additional gRPC - metadata. - - Raises: - google.api_core.exceptions.MethodNotImplemented: If the server - does not support this method. Services are not required to - implement this method. - google.api_core.exceptions.GoogleAPICallError: If an error occurred - while invoking the RPC, the appropriate ``GoogleAPICallError`` - subclass will be raised. - """ - # Create the request object. - request = operations_pb2.DeleteOperationRequest(name=name) - - # Add routing header - metadata = metadata or [] - metadata.append(gapic_v1.routing_header.to_grpc_metadata({"name": name})) - - self._delete_operation( - request, - retry=retry, - timeout=timeout, - compression=compression, - metadata=metadata, - ) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/operations_client_config.py b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/operations_client_config.py deleted file mode 100644 index 3ad3548..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/operations_client_config.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""gapic configuration for the google.longrunning.operations client.""" - -# DEPRECATED: retry and timeout classes are instantiated directly -config = { - "interfaces": { - "google.longrunning.Operations": { - "retry_codes": { - "idempotent": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], - "non_idempotent": [], - }, - "retry_params": { - "default": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 20000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 600000, - "total_timeout_millis": 600000, - } - }, - "methods": { - "GetOperation": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "ListOperations": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "CancelOperation": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "DeleteOperation": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - }, - } - } -} diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/operations_rest_client_async.py b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/operations_rest_client_async.py deleted file mode 100644 index 7ab0cd3..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/operations_rest_client_async.py +++ /dev/null @@ -1,345 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -from typing import Optional, Sequence, Tuple, Union - -from google.api_core import client_options as client_options_lib # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core.operations_v1 import pagers_async as pagers -from google.api_core.operations_v1.transports.base import ( - DEFAULT_CLIENT_INFO, - OperationsTransport, -) -from google.api_core.operations_v1.abstract_operations_base_client import ( - AbstractOperationsBaseClient, -) -from google.longrunning import operations_pb2 - -try: - from google.auth.aio import credentials as ga_credentials # type: ignore -except ImportError as e: # pragma: NO COVER - raise ImportError( - "The `async_rest` extra of `google-api-core` is required to use long-running operations. Install it by running " - "`pip install google-api-core[async_rest]`." - ) from e - - -class AsyncOperationsRestClient(AbstractOperationsBaseClient): - """Manages long-running operations with a REST API service for the asynchronous client. - - When an API method normally takes long time to complete, it can be - designed to return [Operation][google.api_core.operations_v1.Operation] to the - client, and the client can use this interface to receive the real - response asynchronously by polling the operation resource, or pass - the operation resource to another API (such as Google Cloud Pub/Sub - API) to receive the response. Any API service that returns - long-running operations should implement the ``Operations`` - interface so developers can have a consistent client experience. - """ - - def __init__( - self, - *, - credentials: Optional[ga_credentials.Credentials] = None, - transport: Union[str, OperationsTransport, None] = None, - client_options: Optional[client_options_lib.ClientOptions] = None, - client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, - ) -> None: - """Instantiates the operations client. - - Args: - credentials (Optional[google.auth.aio.credentials.Credentials]): The - authorization credentials to attach to requests. These - credentials identify the application to the service; if none - are specified, the client will attempt to ascertain the - credentials from the environment. - transport (Union[str, OperationsTransport]): The - transport to use. If set to None, this defaults to 'rest_asyncio'. - client_options (google.api_core.client_options.ClientOptions): Custom options for the - client. It won't take effect if a ``transport`` instance is provided. - (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT - environment variable can also be used to override the endpoint: - "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint) and "auto" (auto switch to the - default mTLS endpoint if client certificate is present, this is - the default value). However, the ``api_endpoint`` property takes - precedence if provided. - (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable - is "true", then the ``client_cert_source`` property can be used - to provide client certificate for mutual TLS transport. If - not provided, the default SSL client certificate will be used if - present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not - set, no client certificate will be used. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - - Raises: - google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport - creation failed for any reason. - """ - super().__init__( - credentials=credentials, # type: ignore - # NOTE: If a transport is not provided, we force the client to use the async - # REST transport. - transport=transport or "rest_asyncio", - client_options=client_options, - client_info=client_info, - ) - - async def get_operation( - self, - name: str, - *, - # TODO(https://github.com/googleapis/python-api-core/issues/722): Leverage `retry` - # to allow configuring retryable error codes. - retry=gapic_v1.method_async.DEFAULT, - timeout: Optional[float] = None, - metadata: Sequence[Tuple[str, str]] = (), - ) -> operations_pb2.Operation: - r"""Gets the latest state of a long-running operation. - Clients can use this method to poll the operation result - at intervals as recommended by the API service. - - Args: - name (str): - The name of the operation resource. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - - Returns: - google.longrunning.operations_pb2.Operation: - This resource represents a long- - running operation that is the result of a - network API call. - - """ - - request = operations_pb2.GetOperationRequest(name=name) - - # Wrap the RPC method; this adds retry and timeout information, - # and friendly error handling. - rpc = self._transport._wrapped_methods[self._transport.get_operation] - - # Certain fields should be provided within the metadata header; - # add these here. - metadata = tuple(metadata or ()) + ( - gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), - ) - - # Send the request. - response = await rpc( - request, - retry=retry, - timeout=timeout, - metadata=metadata, - ) - - # Done; return the response. - return response - - async def list_operations( - self, - name: str, - filter_: Optional[str] = None, - *, - page_size: Optional[int] = None, - page_token: Optional[str] = None, - # TODO(https://github.com/googleapis/python-api-core/issues/722): Leverage `retry` - # to allow configuring retryable error codes. - retry=gapic_v1.method_async.DEFAULT, - timeout: Optional[float] = None, - metadata: Sequence[Tuple[str, str]] = (), - ) -> pagers.ListOperationsAsyncPager: - r"""Lists operations that match the specified filter in the request. - If the server doesn't support this method, it returns - ``UNIMPLEMENTED``. - - NOTE: the ``name`` binding allows API services to override the - binding to use different resource name schemes, such as - ``users/*/operations``. To override the binding, API services - can add a binding such as ``"/v1/{name=users/*}/operations"`` to - their service configuration. For backwards compatibility, the - default name includes the operations collection id, however - overriding users must ensure the name binding is the parent - resource, without the operations collection id. - - Args: - name (str): - The name of the operation's parent - resource. - filter_ (str): - The standard list filter. - This corresponds to the ``filter`` field - on the ``request`` instance; if ``request`` is provided, this - should not be set. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - - Returns: - google.api_core.operations_v1.pagers.ListOperationsPager: - The response message for - [Operations.ListOperations][google.api_core.operations_v1.Operations.ListOperations]. - - Iterating over this object will yield results and - resolve additional pages automatically. - - """ - # Create a protobuf request object. - request = operations_pb2.ListOperationsRequest(name=name, filter=filter_) - if page_size is not None: - request.page_size = page_size - if page_token is not None: - request.page_token = page_token - - # Wrap the RPC method; this adds retry and timeout information, - # and friendly error handling. - rpc = self._transport._wrapped_methods[self._transport.list_operations] - - # Certain fields should be provided within the metadata header; - # add these here. - metadata = tuple(metadata or ()) + ( - gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), - ) - - # Send the request. - response = await rpc( - request, - retry=retry, - timeout=timeout, - metadata=metadata, - ) - - # This method is paged; wrap the response in a pager, which provides - # an `__iter__` convenience method. - response = pagers.ListOperationsAsyncPager( - method=rpc, - request=request, - response=response, - metadata=metadata, - ) - - # Done; return the response. - return response - - async def delete_operation( - self, - name: str, - *, - # TODO(https://github.com/googleapis/python-api-core/issues/722): Leverage `retry` - # to allow configuring retryable error codes. - retry=gapic_v1.method_async.DEFAULT, - timeout: Optional[float] = None, - metadata: Sequence[Tuple[str, str]] = (), - ) -> None: - r"""Deletes a long-running operation. This method indicates that the - client is no longer interested in the operation result. It does - not cancel the operation. If the server doesn't support this - method, it returns ``google.rpc.Code.UNIMPLEMENTED``. - - Args: - name (str): - The name of the operation resource to - be deleted. - - This corresponds to the ``name`` field - on the ``request`` instance; if ``request`` is provided, this - should not be set. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - """ - # Create the request object. - request = operations_pb2.DeleteOperationRequest(name=name) - - # Wrap the RPC method; this adds retry and timeout information, - # and friendly error handling. - rpc = self._transport._wrapped_methods[self._transport.delete_operation] - - # Certain fields should be provided within the metadata header; - # add these here. - metadata = tuple(metadata or ()) + ( - gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), - ) - - # Send the request. - await rpc( - request, - retry=retry, - timeout=timeout, - metadata=metadata, - ) - - async def cancel_operation( - self, - name: Optional[str] = None, - *, - # TODO(https://github.com/googleapis/python-api-core/issues/722): Leverage `retry` - # to allow configuring retryable error codes. - retry=gapic_v1.method_async.DEFAULT, - timeout: Optional[float] = None, - metadata: Sequence[Tuple[str, str]] = (), - ) -> None: - r"""Starts asynchronous cancellation on a long-running operation. - The server makes a best effort to cancel the operation, but - success is not guaranteed. If the server doesn't support this - method, it returns ``google.rpc.Code.UNIMPLEMENTED``. Clients - can use - [Operations.GetOperation][google.api_core.operations_v1.Operations.GetOperation] - or other methods to check whether the cancellation succeeded or - whether the operation completed despite cancellation. On - successful cancellation, the operation is not deleted; instead, - it becomes an operation with an - [Operation.error][google.api_core.operations_v1.Operation.error] value with - a [google.rpc.Status.code][google.rpc.Status.code] of 1, - corresponding to ``Code.CANCELLED``. - - Args: - name (str): - The name of the operation resource to - be cancelled. - - This corresponds to the ``name`` field - on the ``request`` instance; if ``request`` is provided, this - should not be set. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - """ - # Create the request object. - request = operations_pb2.CancelOperationRequest(name=name) - - # Wrap the RPC method; this adds retry and timeout information, - # and friendly error handling. - rpc = self._transport._wrapped_methods[self._transport.cancel_operation] - - # Certain fields should be provided within the metadata header; - # add these here. - metadata = tuple(metadata or ()) + ( - gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), - ) - - # Send the request. - await rpc( - request, - retry=retry, - timeout=timeout, - metadata=metadata, - ) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/pagers.py b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/pagers.py deleted file mode 100644 index 76efd59..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/pagers.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -from typing import ( - Callable, - Iterator, - Sequence, - Tuple, -) - -from google.longrunning import operations_pb2 -from google.api_core.operations_v1.pagers_base import ListOperationsPagerBase - - -class ListOperationsPager(ListOperationsPagerBase): - """A pager for iterating through ``list_operations`` requests. - - This class thinly wraps an initial - :class:`google.longrunning.operations_pb2.ListOperationsResponse` object, and - provides an ``__iter__`` method to iterate through its - ``operations`` field. - - If there are more pages, the ``__iter__`` method will make additional - ``ListOperations`` requests and continue to iterate - through the ``operations`` field on the - corresponding responses. - - All the usual :class:`google.longrunning.operations_pb2.ListOperationsResponse` - attributes are available on the pager. If multiple requests are made, only - the most recent response is retained, and thus used for attribute lookup. - """ - - def __init__( - self, - method: Callable[..., operations_pb2.ListOperationsResponse], - request: operations_pb2.ListOperationsRequest, - response: operations_pb2.ListOperationsResponse, - *, - metadata: Sequence[Tuple[str, str]] = (), - ): - super().__init__( - method=method, request=request, response=response, metadata=metadata - ) - - @property - def pages(self) -> Iterator[operations_pb2.ListOperationsResponse]: - yield self._response - while self._response.next_page_token: - self._request.page_token = self._response.next_page_token - self._response = self._method(self._request, metadata=self._metadata) - yield self._response - - def __iter__(self) -> Iterator[operations_pb2.Operation]: - for page in self.pages: - yield from page.operations diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/pagers_async.py b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/pagers_async.py deleted file mode 100644 index 4bb7f8c..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/pagers_async.py +++ /dev/null @@ -1,71 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -from typing import ( - Callable, - AsyncIterator, - Sequence, - Tuple, -) - -from google.longrunning import operations_pb2 -from google.api_core.operations_v1.pagers_base import ListOperationsPagerBase - - -class ListOperationsAsyncPager(ListOperationsPagerBase): - """A pager for iterating through ``list_operations`` requests. - - This class thinly wraps an initial - :class:`google.longrunning.operations_pb2.ListOperationsResponse` object, and - provides an ``__iter__`` method to iterate through its - ``operations`` field. - - If there are more pages, the ``__iter__`` method will make additional - ``ListOperations`` requests and continue to iterate - through the ``operations`` field on the - corresponding responses. - - All the usual :class:`google.longrunning.operations_pb2.ListOperationsResponse` - attributes are available on the pager. If multiple requests are made, only - the most recent response is retained, and thus used for attribute lookup. - """ - - def __init__( - self, - method: Callable[..., operations_pb2.ListOperationsResponse], - request: operations_pb2.ListOperationsRequest, - response: operations_pb2.ListOperationsResponse, - *, - metadata: Sequence[Tuple[str, str]] = (), - ): - super().__init__( - method=method, request=request, response=response, metadata=metadata - ) - - @property - async def pages(self) -> AsyncIterator[operations_pb2.ListOperationsResponse]: - yield self._response - while self._response.next_page_token: - self._request.page_token = self._response.next_page_token - self._response = await self._method(self._request, metadata=self._metadata) - yield self._response - - def __aiter__(self) -> AsyncIterator[operations_pb2.Operation]: - async def async_generator(): - async for page in self.pages: - for operation in page.operations: - yield operation - - return async_generator() diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/pagers_base.py b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/pagers_base.py deleted file mode 100644 index 5ef8384..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/pagers_base.py +++ /dev/null @@ -1,73 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -from typing import ( - Any, - Callable, - Sequence, - Tuple, -) - -from google.longrunning import operations_pb2 - - -class ListOperationsPagerBase: - """A pager for iterating through ``list_operations`` requests. - - This class thinly wraps an initial - :class:`google.longrunning.operations_pb2.ListOperationsResponse` object, and - provides an ``__iter__`` method to iterate through its - ``operations`` field. - - If there are more pages, the ``__iter__`` method will make additional - ``ListOperations`` requests and continue to iterate - through the ``operations`` field on the - corresponding responses. - - All the usual :class:`google.longrunning.operations_pb2.ListOperationsResponse` - attributes are available on the pager. If multiple requests are made, only - the most recent response is retained, and thus used for attribute lookup. - """ - - def __init__( - self, - method: Callable[..., operations_pb2.ListOperationsResponse], - request: operations_pb2.ListOperationsRequest, - response: operations_pb2.ListOperationsResponse, - *, - metadata: Sequence[Tuple[str, str]] = (), - ): - """Instantiate the pager. - - Args: - method (Callable): The method that was originally called, and - which instantiated this pager. - request (google.longrunning.operations_pb2.ListOperationsRequest): - The initial request object. - response (google.longrunning.operations_pb2.ListOperationsResponse): - The initial response object. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - """ - self._method = method - self._request = request - self._response = response - self._metadata = metadata - - def __getattr__(self, name: str) -> Any: - return getattr(self._response, name) - - def __repr__(self) -> str: - return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__init__.py b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__init__.py deleted file mode 100644 index 8c24ce6..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__init__.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -from collections import OrderedDict -from typing import cast, Dict, Tuple - -from .base import OperationsTransport -from .rest import OperationsRestTransport - -# Compile a registry of transports. -_transport_registry: Dict[str, OperationsTransport] = OrderedDict() -_transport_registry["rest"] = cast(OperationsTransport, OperationsRestTransport) - -__all__: Tuple[str, ...] = ("OperationsTransport", "OperationsRestTransport") - -try: - from .rest_asyncio import AsyncOperationsRestTransport - - __all__ += ("AsyncOperationsRestTransport",) - _transport_registry["rest_asyncio"] = cast( - OperationsTransport, AsyncOperationsRestTransport - ) -except ImportError: - # This import requires the `async_rest` extra. - # Don't raise an exception if `AsyncOperationsRestTransport` cannot be imported - # as other transports are still available. - pass diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__pycache__/__init__.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index f627c29..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__pycache__/__init__.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__pycache__/base.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__pycache__/base.cpython-312.pyc deleted file mode 100644 index a018e88..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__pycache__/base.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__pycache__/rest.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__pycache__/rest.cpython-312.pyc deleted file mode 100644 index 8367beb..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__pycache__/rest.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__pycache__/rest_asyncio.cpython-312.pyc b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__pycache__/rest_asyncio.cpython-312.pyc deleted file mode 100644 index 600df9c..0000000 Binary files a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/__pycache__/rest_asyncio.cpython-312.pyc and /dev/null differ diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/base.py b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/base.py deleted file mode 100644 index 2d78809..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/base.py +++ /dev/null @@ -1,303 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -import abc -import re -from typing import Awaitable, Callable, Optional, Sequence, Union -import warnings - -import google.auth # type: ignore -from google.auth import credentials as ga_credentials # type: ignore -from google.longrunning import operations_pb2 -from google.oauth2 import service_account # type: ignore -import google.protobuf -from google.protobuf import empty_pb2, json_format # type: ignore -from grpc import Compression - -import google.api_core # type: ignore -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import general_helpers -from google.api_core import retry as retries # type: ignore -from google.api_core import version - -PROTOBUF_VERSION = google.protobuf.__version__ - -DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( - gapic_version=version.__version__, -) - - -class OperationsTransport(abc.ABC): - """Abstract transport class for Operations.""" - - AUTH_SCOPES = () - - DEFAULT_HOST: str = "longrunning.googleapis.com" - - def __init__( - self, - *, - host: str = DEFAULT_HOST, - # TODO(https://github.com/googleapis/python-api-core/issues/709): update type hint for credentials to include `google.auth.aio.Credentials`. - credentials: Optional[ga_credentials.Credentials] = None, - credentials_file: Optional[str] = None, - scopes: Optional[Sequence[str]] = None, - quota_project_id: Optional[str] = None, - client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, - always_use_jwt_access: Optional[bool] = False, - url_scheme="https", - **kwargs, - ) -> None: - """Instantiate the transport. - - Args: - host (Optional[str]): - The hostname to connect to. - credentials (Optional[google.auth.credentials.Credentials]): The - authorization credentials to attach to requests. These - credentials identify the application to the service; if none - are specified, the client will attempt to ascertain the - credentials from the environment. - credentials_file (Optional[str]): Deprecated. A file with credentials that can - be loaded with :func:`google.auth.load_credentials_from_file`. - This argument is mutually exclusive with credentials. This argument will be - removed in the next major version of `google-api-core`. - - .. warning:: - Important: If you accept a credential configuration (credential JSON/File/Stream) - from an external source for authentication to Google Cloud Platform, you must - validate it before providing it to any Google API or client library. Providing an - unvalidated credential configuration to Google APIs or libraries can compromise - the security of your systems and data. For more information, refer to - `Validate credential configurations from external sources`_. - - .. _Validate credential configurations from external sources: - - https://cloud.google.com/docs/authentication/external/externally-sourced-credentials - scopes (Optional[Sequence[str]]): A list of scopes. - quota_project_id (Optional[str]): An optional project to use for billing - and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - always_use_jwt_access (Optional[bool]): Whether self signed JWT should - be used for service account credentials. - url_scheme: the protocol scheme for the API endpoint. Normally - "https", but for testing or local servers, - "http" can be specified. - """ - if credentials_file is not None: - warnings.warn(general_helpers._CREDENTIALS_FILE_WARNING, DeprecationWarning) - - maybe_url_match = re.match("^(?Phttp(?:s)?://)?(?P.*)$", host) - if maybe_url_match is None: - raise ValueError( - f"Unexpected hostname structure: {host}" - ) # pragma: NO COVER - - url_match_items = maybe_url_match.groupdict() - - host = f"{url_scheme}://{host}" if not url_match_items["scheme"] else host - - # Save the hostname. Default to port 443 (HTTPS) if none is specified. - if ":" not in host: - host += ":443" # pragma: NO COVER - self._host = host - - # Save the scopes. - self._scopes = scopes - - # If no credentials are provided, then determine the appropriate - # defaults. - if credentials and credentials_file: - raise core_exceptions.DuplicateCredentialArgs( - "'credentials_file' and 'credentials' are mutually exclusive" - ) - - if credentials_file is not None: - credentials, _ = google.auth.load_credentials_from_file( - credentials_file, - scopes=scopes, - quota_project_id=quota_project_id, - default_scopes=self.AUTH_SCOPES, - ) - - elif credentials is None: - credentials, _ = google.auth.default( - scopes=scopes, - quota_project_id=quota_project_id, - default_scopes=self.AUTH_SCOPES, - ) - - # If the credentials are service account credentials, then always try to use self signed JWT. - if ( - always_use_jwt_access - and isinstance(credentials, service_account.Credentials) - and hasattr(service_account.Credentials, "with_always_use_jwt_access") - ): - credentials = credentials.with_always_use_jwt_access(True) - - # Save the credentials. - self._credentials = credentials - - def _prep_wrapped_messages(self, client_info): - # Precompute the wrapped methods. - self._wrapped_methods = { - self.list_operations: gapic_v1.method.wrap_method( - self.list_operations, - default_retry=retries.Retry( - initial=0.5, - maximum=10.0, - multiplier=2.0, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=10.0, - ), - default_timeout=10.0, - default_compression=Compression.NoCompression, - client_info=client_info, - ), - self.get_operation: gapic_v1.method.wrap_method( - self.get_operation, - default_retry=retries.Retry( - initial=0.5, - maximum=10.0, - multiplier=2.0, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=10.0, - ), - default_timeout=10.0, - default_compression=Compression.NoCompression, - client_info=client_info, - ), - self.delete_operation: gapic_v1.method.wrap_method( - self.delete_operation, - default_retry=retries.Retry( - initial=0.5, - maximum=10.0, - multiplier=2.0, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=10.0, - ), - default_timeout=10.0, - default_compression=Compression.NoCompression, - client_info=client_info, - ), - self.cancel_operation: gapic_v1.method.wrap_method( - self.cancel_operation, - default_retry=retries.Retry( - initial=0.5, - maximum=10.0, - multiplier=2.0, - predicate=retries.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=10.0, - ), - default_timeout=10.0, - default_compression=Compression.NoCompression, - client_info=client_info, - ), - } - - def close(self): - """Closes resources associated with the transport. - - .. warning:: - Only call this method if the transport is NOT shared - with other clients - this may cause errors in other clients! - """ - raise NotImplementedError() - - def _convert_protobuf_message_to_dict( - self, message: google.protobuf.message.Message - ): - r"""Converts protobuf message to a dictionary. - - When the dictionary is encoded to JSON, it conforms to proto3 JSON spec. - - Args: - message(google.protobuf.message.Message): The protocol buffers message - instance to serialize. - - Returns: - A dict representation of the protocol buffer message. - """ - # TODO(https://github.com/googleapis/python-api-core/issues/643): For backwards compatibility - # with protobuf 3.x 4.x, Remove once support for protobuf 3.x and 4.x is dropped. - if PROTOBUF_VERSION[0:2] in ["3.", "4."]: - result = json_format.MessageToDict( - message, - preserving_proto_field_name=True, - including_default_value_fields=True, # type: ignore # backward compatibility - ) - else: - result = json_format.MessageToDict( - message, - preserving_proto_field_name=True, - always_print_fields_with_no_presence=True, - ) - - return result - - @property - def list_operations( - self, - ) -> Callable[ - [operations_pb2.ListOperationsRequest], - Union[ - operations_pb2.ListOperationsResponse, - Awaitable[operations_pb2.ListOperationsResponse], - ], - ]: - raise NotImplementedError() - - @property - def get_operation( - self, - ) -> Callable[ - [operations_pb2.GetOperationRequest], - Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], - ]: - raise NotImplementedError() - - @property - def delete_operation( - self, - ) -> Callable[ - [operations_pb2.DeleteOperationRequest], - Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]], - ]: - raise NotImplementedError() - - @property - def cancel_operation( - self, - ) -> Callable[ - [operations_pb2.CancelOperationRequest], - Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]], - ]: - raise NotImplementedError() - - -__all__ = ("OperationsTransport",) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/rest.py b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/rest.py deleted file mode 100644 index 62f34d6..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/rest.py +++ /dev/null @@ -1,492 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -from typing import Callable, Dict, Optional, Sequence, Tuple, Union -import warnings - -from google.auth import credentials as ga_credentials # type: ignore -from google.auth.transport.requests import AuthorizedSession # type: ignore -from google.longrunning import operations_pb2 # type: ignore -import google.protobuf -from google.protobuf import empty_pb2 # type: ignore -from google.protobuf import json_format # type: ignore -import grpc -from requests import __version__ as requests_version - -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import general_helpers -from google.api_core import path_template # type: ignore -from google.api_core import rest_helpers # type: ignore -from google.api_core import retry as retries # type: ignore - -from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO -from .base import OperationsTransport - -PROTOBUF_VERSION = google.protobuf.__version__ - -OptionalRetry = Union[retries.Retry, object] - -DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( - gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, - grpc_version=None, - rest_version=f"requests@{requests_version}", -) - - -class OperationsRestTransport(OperationsTransport): - """REST backend transport for Operations. - - Manages long-running operations with an API service. - - When an API method normally takes long time to complete, it can be - designed to return [Operation][google.api_core.operations_v1.Operation] to the - client, and the client can use this interface to receive the real - response asynchronously by polling the operation resource, or pass - the operation resource to another API (such as Google Cloud Pub/Sub - API) to receive the response. Any API service that returns - long-running operations should implement the ``Operations`` - interface so developers can have a consistent client experience. - - This class defines the same methods as the primary client, so the - primary client can load the underlying transport implementation - and call it. - - It sends JSON representations of protocol buffers over HTTP/1.1 - """ - - def __init__( - self, - *, - host: str = "longrunning.googleapis.com", - credentials: Optional[ga_credentials.Credentials] = None, - credentials_file: Optional[str] = None, - scopes: Optional[Sequence[str]] = None, - client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, - quota_project_id: Optional[str] = None, - client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, - always_use_jwt_access: Optional[bool] = False, - url_scheme: str = "https", - http_options: Optional[Dict] = None, - path_prefix: str = "v1", - ) -> None: - """Instantiate the transport. - - Args: - host (Optional[str]): - The hostname to connect to. - credentials (Optional[google.auth.credentials.Credentials]): The - authorization credentials to attach to requests. These - credentials identify the application to the service; if none - are specified, the client will attempt to ascertain the - credentials from the environment. - - credentials_file (Optional[str]): Deprecated. A file with credentials that can - be loaded with :func:`google.auth.load_credentials_from_file`. - This argument is ignored if ``channel`` is provided. This argument will be - removed in the next major version of `google-api-core`. - - .. warning:: - Important: If you accept a credential configuration (credential JSON/File/Stream) - from an external source for authentication to Google Cloud Platform, you must - validate it before providing it to any Google API or client library. Providing an - unvalidated credential configuration to Google APIs or libraries can compromise - the security of your systems and data. For more information, refer to - `Validate credential configuration from external sources`_. - - .. _Validate credential configuration from external sources: - - https://cloud.google.com/docs/authentication/external/externally-sourced-credentials - scopes (Optional(Sequence[str])): A list of scopes. This argument is - ignored if ``channel`` is provided. - client_cert_source_for_mtls (Callable[[], Tuple[bytes, bytes]]): Client - certificate to configure mutual TLS HTTP channel. It is ignored - if ``channel`` is provided. - quota_project_id (Optional[str]): An optional project to use for billing - and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - always_use_jwt_access (Optional[bool]): Whether self signed JWT should - be used for service account credentials. - url_scheme: the protocol scheme for the API endpoint. Normally - "https", but for testing or local servers, - "http" can be specified. - http_options: a dictionary of http_options for transcoding, to override - the defaults from operations.proto. Each method has an entry - with the corresponding http rules as value. - path_prefix: path prefix (usually represents API version). Set to - "v1" by default. - - """ - if credentials_file is not None: - warnings.warn(general_helpers._CREDENTIALS_FILE_WARNING, DeprecationWarning) - - # Run the base constructor - # TODO(yon-mg): resolve other ctor params i.e. scopes, quota, etc. - # TODO: When custom host (api_endpoint) is set, `scopes` must *also* be set on the - # credentials object - super().__init__( - host=host, - credentials=credentials, - client_info=client_info, - always_use_jwt_access=always_use_jwt_access, - ) - self._session = AuthorizedSession( - self._credentials, default_host=self.DEFAULT_HOST - ) - if client_cert_source_for_mtls: - self._session.configure_mtls_channel(client_cert_source_for_mtls) - # TODO(https://github.com/googleapis/python-api-core/issues/720): Add wrap logic directly to the property methods for callables. - self._prep_wrapped_messages(client_info) - self._http_options = http_options or {} - self._path_prefix = path_prefix - - def _list_operations( - self, - request: operations_pb2.ListOperationsRequest, - *, - # TODO(https://github.com/googleapis/python-api-core/issues/723): Leverage `retry` - # to allow configuring retryable error codes. - retry: OptionalRetry = gapic_v1.method.DEFAULT, - timeout: Optional[float] = None, - compression: Optional[grpc.Compression] = gapic_v1.method.DEFAULT, - metadata: Sequence[Tuple[str, str]] = (), - ) -> operations_pb2.ListOperationsResponse: - r"""Call the list operations method over HTTP. - - Args: - request (~.operations_pb2.ListOperationsRequest): - The request object. The request message for - [Operations.ListOperations][google.api_core.operations_v1.Operations.ListOperations]. - - retry (google.api_core.retry.Retry): Designation of what errors, if any, - should be retried. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - - Returns: - ~.operations_pb2.ListOperationsResponse: - The response message for - [Operations.ListOperations][google.api_core.operations_v1.Operations.ListOperations]. - - """ - - http_options = [ - { - "method": "get", - "uri": "/{}/{{name=**}}/operations".format(self._path_prefix), - }, - ] - if "google.longrunning.Operations.ListOperations" in self._http_options: - http_options = self._http_options[ - "google.longrunning.Operations.ListOperations" - ] - - request_kwargs = self._convert_protobuf_message_to_dict(request) - transcoded_request = path_template.transcode(http_options, **request_kwargs) - - uri = transcoded_request["uri"] - method = transcoded_request["method"] - - # Jsonify the query params - query_params_request = operations_pb2.ListOperationsRequest() - json_format.ParseDict(transcoded_request["query_params"], query_params_request) - query_params = json_format.MessageToDict( - query_params_request, - preserving_proto_field_name=False, - use_integers_for_enums=False, - ) - - # Send the request - headers = dict(metadata) - headers["Content-Type"] = "application/json" - # TODO(https://github.com/googleapis/python-api-core/issues/721): Update incorrect use of `uri`` variable name. - response = getattr(self._session, method)( - "{host}{uri}".format(host=self._host, uri=uri), - timeout=timeout, - headers=headers, - params=rest_helpers.flatten_query_params(query_params), - ) - - # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception - # subclass. - if response.status_code >= 400: - raise core_exceptions.from_http_response(response) - - # Return the response - api_response = operations_pb2.ListOperationsResponse() - json_format.Parse(response.content, api_response, ignore_unknown_fields=False) - return api_response - - def _get_operation( - self, - request: operations_pb2.GetOperationRequest, - *, - # TODO(https://github.com/googleapis/python-api-core/issues/723): Leverage `retry` - # to allow configuring retryable error codes. - retry: OptionalRetry = gapic_v1.method.DEFAULT, - timeout: Optional[float] = None, - compression: Optional[grpc.Compression] = gapic_v1.method.DEFAULT, - metadata: Sequence[Tuple[str, str]] = (), - ) -> operations_pb2.Operation: - r"""Call the get operation method over HTTP. - - Args: - request (~.operations_pb2.GetOperationRequest): - The request object. The request message for - [Operations.GetOperation][google.api_core.operations_v1.Operations.GetOperation]. - - retry (google.api_core.retry.Retry): Designation of what errors, if any, - should be retried. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - - Returns: - ~.operations_pb2.Operation: - This resource represents a long- - running operation that is the result of a - network API call. - - """ - - http_options = [ - { - "method": "get", - "uri": "/{}/{{name=**/operations/*}}".format(self._path_prefix), - }, - ] - if "google.longrunning.Operations.GetOperation" in self._http_options: - http_options = self._http_options[ - "google.longrunning.Operations.GetOperation" - ] - - request_kwargs = self._convert_protobuf_message_to_dict(request) - transcoded_request = path_template.transcode(http_options, **request_kwargs) - - uri = transcoded_request["uri"] - method = transcoded_request["method"] - - # Jsonify the query params - query_params_request = operations_pb2.GetOperationRequest() - json_format.ParseDict(transcoded_request["query_params"], query_params_request) - query_params = json_format.MessageToDict( - query_params_request, - preserving_proto_field_name=False, - use_integers_for_enums=False, - ) - - # Send the request - headers = dict(metadata) - headers["Content-Type"] = "application/json" - # TODO(https://github.com/googleapis/python-api-core/issues/721): Update incorrect use of `uri`` variable name. - response = getattr(self._session, method)( - "{host}{uri}".format(host=self._host, uri=uri), - timeout=timeout, - headers=headers, - params=rest_helpers.flatten_query_params(query_params), - ) - - # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception - # subclass. - if response.status_code >= 400: - raise core_exceptions.from_http_response(response) - - # Return the response - api_response = operations_pb2.Operation() - json_format.Parse(response.content, api_response, ignore_unknown_fields=False) - return api_response - - def _delete_operation( - self, - request: operations_pb2.DeleteOperationRequest, - *, - # TODO(https://github.com/googleapis/python-api-core/issues/723): Leverage `retry` - # to allow configuring retryable error codes. - retry: OptionalRetry = gapic_v1.method.DEFAULT, - timeout: Optional[float] = None, - compression: Optional[grpc.Compression] = gapic_v1.method.DEFAULT, - metadata: Sequence[Tuple[str, str]] = (), - ) -> empty_pb2.Empty: - r"""Call the delete operation method over HTTP. - - Args: - request (~.operations_pb2.DeleteOperationRequest): - The request object. The request message for - [Operations.DeleteOperation][google.api_core.operations_v1.Operations.DeleteOperation]. - - retry (google.api_core.retry.Retry): Designation of what errors, if any, - should be retried. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - """ - - http_options = [ - { - "method": "delete", - "uri": "/{}/{{name=**/operations/*}}".format(self._path_prefix), - }, - ] - if "google.longrunning.Operations.DeleteOperation" in self._http_options: - http_options = self._http_options[ - "google.longrunning.Operations.DeleteOperation" - ] - - request_kwargs = self._convert_protobuf_message_to_dict(request) - transcoded_request = path_template.transcode(http_options, **request_kwargs) - - uri = transcoded_request["uri"] - method = transcoded_request["method"] - - # Jsonify the query params - query_params_request = operations_pb2.DeleteOperationRequest() - json_format.ParseDict(transcoded_request["query_params"], query_params_request) - query_params = json_format.MessageToDict( - query_params_request, - preserving_proto_field_name=False, - use_integers_for_enums=False, - ) - - # Send the request - headers = dict(metadata) - headers["Content-Type"] = "application/json" - # TODO(https://github.com/googleapis/python-api-core/issues/721): Update incorrect use of `uri`` variable name. - response = getattr(self._session, method)( - "{host}{uri}".format(host=self._host, uri=uri), - timeout=timeout, - headers=headers, - params=rest_helpers.flatten_query_params(query_params), - ) - - # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception - # subclass. - if response.status_code >= 400: - raise core_exceptions.from_http_response(response) - - return empty_pb2.Empty() - - def _cancel_operation( - self, - request: operations_pb2.CancelOperationRequest, - *, - # TODO(https://github.com/googleapis/python-api-core/issues/723): Leverage `retry` - # to allow configuring retryable error codes. - retry: OptionalRetry = gapic_v1.method.DEFAULT, - timeout: Optional[float] = None, - compression: Optional[grpc.Compression] = gapic_v1.method.DEFAULT, - metadata: Sequence[Tuple[str, str]] = (), - ) -> empty_pb2.Empty: - r"""Call the cancel operation method over HTTP. - - Args: - request (~.operations_pb2.CancelOperationRequest): - The request object. The request message for - [Operations.CancelOperation][google.api_core.operations_v1.Operations.CancelOperation]. - - retry (google.api_core.retry.Retry): Designation of what errors, if any, - should be retried. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - """ - - http_options = [ - { - "method": "post", - "uri": "/{}/{{name=**/operations/*}}:cancel".format(self._path_prefix), - "body": "*", - }, - ] - if "google.longrunning.Operations.CancelOperation" in self._http_options: - http_options = self._http_options[ - "google.longrunning.Operations.CancelOperation" - ] - - request_kwargs = self._convert_protobuf_message_to_dict(request) - transcoded_request = path_template.transcode(http_options, **request_kwargs) - - # Jsonify the request body - body_request = operations_pb2.CancelOperationRequest() - json_format.ParseDict(transcoded_request["body"], body_request) - body = json_format.MessageToDict( - body_request, - preserving_proto_field_name=False, - use_integers_for_enums=False, - ) - uri = transcoded_request["uri"] - method = transcoded_request["method"] - - # Jsonify the query params - query_params_request = operations_pb2.CancelOperationRequest() - json_format.ParseDict(transcoded_request["query_params"], query_params_request) - query_params = json_format.MessageToDict( - query_params_request, - preserving_proto_field_name=False, - use_integers_for_enums=False, - ) - - # Send the request - headers = dict(metadata) - headers["Content-Type"] = "application/json" - # TODO(https://github.com/googleapis/python-api-core/issues/721): Update incorrect use of `uri`` variable name. - response = getattr(self._session, method)( - "{host}{uri}".format(host=self._host, uri=uri), - timeout=timeout, - headers=headers, - params=rest_helpers.flatten_query_params(query_params), - data=body, - ) - - # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception - # subclass. - if response.status_code >= 400: - raise core_exceptions.from_http_response(response) - - return empty_pb2.Empty() - - @property - def list_operations( - self, - ) -> Callable[ - [operations_pb2.ListOperationsRequest], operations_pb2.ListOperationsResponse - ]: - return self._list_operations - - @property - def get_operation( - self, - ) -> Callable[[operations_pb2.GetOperationRequest], operations_pb2.Operation]: - return self._get_operation - - @property - def delete_operation( - self, - ) -> Callable[[operations_pb2.DeleteOperationRequest], empty_pb2.Empty]: - return self._delete_operation - - @property - def cancel_operation( - self, - ) -> Callable[[operations_pb2.CancelOperationRequest], empty_pb2.Empty]: - return self._cancel_operation - - -__all__ = ("OperationsRestTransport",) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/rest_asyncio.py b/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/rest_asyncio.py deleted file mode 100644 index 6fa9f56..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/operations_v1/transports/rest_asyncio.py +++ /dev/null @@ -1,581 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2024 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -import json -from typing import Any, Callable, Coroutine, Dict, Optional, Sequence, Tuple -import warnings - -from google.auth import __version__ as auth_version - -try: - from google.auth.aio.transport.sessions import AsyncAuthorizedSession # type: ignore -except ImportError as e: # pragma: NO COVER - raise ImportError( - "The `async_rest` extra of `google-api-core` is required to use long-running operations. Install it by running " - "`pip install google-api-core[async_rest]`." - ) from e - -from google.api_core import exceptions as core_exceptions # type: ignore -from google.api_core import gapic_v1 # type: ignore -from google.api_core import general_helpers -from google.api_core import path_template # type: ignore -from google.api_core import rest_helpers # type: ignore -from google.api_core import retry_async as retries_async # type: ignore -from google.auth.aio import credentials as ga_credentials_async # type: ignore -from google.longrunning import operations_pb2 # type: ignore -from google.protobuf import empty_pb2 # type: ignore -from google.protobuf import json_format # type: ignore - -from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO, OperationsTransport - -DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( - gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, - grpc_version=None, - rest_version=f"google-auth@{auth_version}", -) - - -class AsyncOperationsRestTransport(OperationsTransport): - """Asynchronous REST backend transport for Operations. - - Manages async long-running operations with an API service. - - When an API method normally takes long time to complete, it can be - designed to return [Operation][google.api_core.operations_v1.Operation] to the - client, and the client can use this interface to receive the real - response asynchronously by polling the operation resource, or pass - the operation resource to another API (such as Google Cloud Pub/Sub - API) to receive the response. Any API service that returns - long-running operations should implement the ``Operations`` - interface so developers can have a consistent client experience. - - This class defines the same methods as the primary client, so the - primary client can load the underlying transport implementation - and call it. - - It sends JSON representations of protocol buffers over HTTP/1.1 - """ - - def __init__( - self, - *, - host: str = "longrunning.googleapis.com", - credentials: Optional[ga_credentials_async.Credentials] = None, - credentials_file: Optional[str] = None, - scopes: Optional[Sequence[str]] = None, - client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, - quota_project_id: Optional[str] = None, - client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, - always_use_jwt_access: Optional[bool] = False, - url_scheme: str = "https", - http_options: Optional[Dict] = None, - path_prefix: str = "v1", - # TODO(https://github.com/googleapis/python-api-core/issues/715): Add docstring for `credentials_file` to async REST transport. - # TODO(https://github.com/googleapis/python-api-core/issues/716): Add docstring for `scopes` to async REST transport. - # TODO(https://github.com/googleapis/python-api-core/issues/717): Add docstring for `quota_project_id` to async REST transport. - # TODO(https://github.com/googleapis/python-api-core/issues/718): Add docstring for `client_cert_source` to async REST transport. - ) -> None: - """Instantiate the transport. - - Args: - host (Optional[str]): - The hostname to connect to. - credentials (Optional[google.auth.aio.credentials.Credentials]): The - authorization credentials to attach to requests. These - credentials identify the application to the service; if none - are specified, the client will attempt to ascertain the - credentials from the environment. - credentials_file (Optional[str]): Deprecated. A file with credentials that can - be loaded with :func:`google.auth.load_credentials_from_file`. - This argument is ignored if ``channel`` is provided. This argument will be - removed in the next major version of `google-api-core`. - - .. warning:: - Important: If you accept a credential configuration (credential JSON/File/Stream) - from an external source for authentication to Google Cloud Platform, you must - validate it before providing it to any Google API or client library. Providing an - unvalidated credential configuration to Google APIs or libraries can compromise - the security of your systems and data. For more information, refer to - `Validate credential configurations from external sources`_. - - .. _Validate credential configurations from external sources: - - https://cloud.google.com/docs/authentication/external/externally-sourced-credentials - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - always_use_jwt_access (Optional[bool]): Whether self signed JWT should - be used for service account credentials. - url_scheme: the protocol scheme for the API endpoint. Normally - "https", but for testing or local servers, - "http" can be specified. - http_options: a dictionary of http_options for transcoding, to override - the defaults from operations.proto. Each method has an entry - with the corresponding http rules as value. - path_prefix: path prefix (usually represents API version). Set to - "v1" by default. - - """ - if credentials_file is not None: - warnings.warn(general_helpers._CREDENTIALS_FILE_WARNING, DeprecationWarning) - - unsupported_params = { - # TODO(https://github.com/googleapis/python-api-core/issues/715): Add support for `credentials_file` to async REST transport. - "google.api_core.client_options.ClientOptions.credentials_file": credentials_file, - # TODO(https://github.com/googleapis/python-api-core/issues/716): Add support for `scopes` to async REST transport. - "google.api_core.client_options.ClientOptions.scopes": scopes, - # TODO(https://github.com/googleapis/python-api-core/issues/717): Add support for `quota_project_id` to async REST transport. - "google.api_core.client_options.ClientOptions.quota_project_id": quota_project_id, - # TODO(https://github.com/googleapis/python-api-core/issues/718): Add support for `client_cert_source` to async REST transport. - "google.api_core.client_options.ClientOptions.client_cert_source": client_cert_source_for_mtls, - # TODO(https://github.com/googleapis/python-api-core/issues/718): Add support for `client_cert_source` to async REST transport. - "google.api_core.client_options.ClientOptions.client_cert_source": client_cert_source_for_mtls, - } - provided_unsupported_params = [ - name for name, value in unsupported_params.items() if value is not None - ] - if provided_unsupported_params: - raise core_exceptions.AsyncRestUnsupportedParameterError( - f"The following provided parameters are not supported for `transport=rest_asyncio`: {', '.join(provided_unsupported_params)}" - ) - - super().__init__( - host=host, - # TODO(https://github.com/googleapis/python-api-core/issues/709): Remove `type: ignore` when the linked issue is resolved. - credentials=credentials, # type: ignore - client_info=client_info, - # TODO(https://github.com/googleapis/python-api-core/issues/725): Set always_use_jwt_access token when supported. - always_use_jwt_access=False, - ) - # TODO(https://github.com/googleapis/python-api-core/issues/708): add support for - # `default_host` in AsyncAuthorizedSession for feature parity with the synchronous - # code. - # TODO(https://github.com/googleapis/python-api-core/issues/709): Remove `type: ignore` when the linked issue is resolved. - self._session = AsyncAuthorizedSession(self._credentials) # type: ignore - # TODO(https://github.com/googleapis/python-api-core/issues/720): Add wrap logic directly to the property methods for callables. - self._prep_wrapped_messages(client_info) - self._http_options = http_options or {} - self._path_prefix = path_prefix - - def _prep_wrapped_messages(self, client_info): - # Precompute the wrapped methods. - self._wrapped_methods = { - self.list_operations: gapic_v1.method_async.wrap_method( - self.list_operations, - default_retry=retries_async.AsyncRetry( - initial=0.5, - maximum=10.0, - multiplier=2.0, - predicate=retries_async.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=10.0, - ), - default_timeout=10.0, - client_info=client_info, - kind="rest_asyncio", - ), - self.get_operation: gapic_v1.method_async.wrap_method( - self.get_operation, - default_retry=retries_async.AsyncRetry( - initial=0.5, - maximum=10.0, - multiplier=2.0, - predicate=retries_async.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=10.0, - ), - default_timeout=10.0, - client_info=client_info, - kind="rest_asyncio", - ), - self.delete_operation: gapic_v1.method_async.wrap_method( - self.delete_operation, - default_retry=retries_async.AsyncRetry( - initial=0.5, - maximum=10.0, - multiplier=2.0, - predicate=retries_async.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=10.0, - ), - default_timeout=10.0, - client_info=client_info, - kind="rest_asyncio", - ), - self.cancel_operation: gapic_v1.method_async.wrap_method( - self.cancel_operation, - default_retry=retries_async.AsyncRetry( - initial=0.5, - maximum=10.0, - multiplier=2.0, - predicate=retries_async.if_exception_type( - core_exceptions.ServiceUnavailable, - ), - deadline=10.0, - ), - default_timeout=10.0, - client_info=client_info, - kind="rest_asyncio", - ), - } - - async def _list_operations( - self, - request: operations_pb2.ListOperationsRequest, - *, - # TODO(https://github.com/googleapis/python-api-core/issues/722): Leverage `retry` - # to allow configuring retryable error codes. - retry=gapic_v1.method_async.DEFAULT, - timeout: Optional[float] = None, - metadata: Sequence[Tuple[str, str]] = (), - ) -> operations_pb2.ListOperationsResponse: - r"""Asynchronously call the list operations method over HTTP. - - Args: - request (~.operations_pb2.ListOperationsRequest): - The request object. The request message for - [Operations.ListOperations][google.api_core.operations_v1.Operations.ListOperations]. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - - Returns: - ~.operations_pb2.ListOperationsResponse: - The response message for - [Operations.ListOperations][google.api_core.operations_v1.Operations.ListOperations]. - - """ - - http_options = [ - { - "method": "get", - "uri": "/{}/{{name=**}}/operations".format(self._path_prefix), - }, - ] - if "google.longrunning.Operations.ListOperations" in self._http_options: - http_options = self._http_options[ - "google.longrunning.Operations.ListOperations" - ] - - request_kwargs = self._convert_protobuf_message_to_dict(request) - transcoded_request = path_template.transcode(http_options, **request_kwargs) - - uri = transcoded_request["uri"] - method = transcoded_request["method"] - - # Jsonify the query params - query_params_request = operations_pb2.ListOperationsRequest() - json_format.ParseDict(transcoded_request["query_params"], query_params_request) - query_params = json_format.MessageToDict( - query_params_request, - preserving_proto_field_name=False, - use_integers_for_enums=False, - ) - - # Send the request - headers = dict(metadata) - headers["Content-Type"] = "application/json" - # TODO(https://github.com/googleapis/python-api-core/issues/721): Update incorrect use of `uri`` variable name. - response = await getattr(self._session, method)( - "{host}{uri}".format(host=self._host, uri=uri), - timeout=timeout, - headers=headers, - params=rest_helpers.flatten_query_params(query_params), - ) - content = await response.read() - - # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception - # subclass. - if response.status_code >= 400: - payload = json.loads(content.decode("utf-8")) - request_url = "{host}{uri}".format(host=self._host, uri=uri) - raise core_exceptions.format_http_response_error(response, method, request_url, payload) # type: ignore - - # Return the response - api_response = operations_pb2.ListOperationsResponse() - json_format.Parse(content, api_response, ignore_unknown_fields=False) - return api_response - - async def _get_operation( - self, - request: operations_pb2.GetOperationRequest, - *, - # TODO(https://github.com/googleapis/python-api-core/issues/722): Leverage `retry` - # to allow configuring retryable error codes. - retry=gapic_v1.method_async.DEFAULT, - timeout: Optional[float] = None, - metadata: Sequence[Tuple[str, str]] = (), - ) -> operations_pb2.Operation: - r"""Asynchronously call the get operation method over HTTP. - - Args: - request (~.operations_pb2.GetOperationRequest): - The request object. The request message for - [Operations.GetOperation][google.api_core.operations_v1.Operations.GetOperation]. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - - Returns: - ~.operations_pb2.Operation: - This resource represents a long- - running operation that is the result of a - network API call. - - """ - - http_options = [ - { - "method": "get", - "uri": "/{}/{{name=**/operations/*}}".format(self._path_prefix), - }, - ] - if "google.longrunning.Operations.GetOperation" in self._http_options: - http_options = self._http_options[ - "google.longrunning.Operations.GetOperation" - ] - - request_kwargs = self._convert_protobuf_message_to_dict(request) - transcoded_request = path_template.transcode(http_options, **request_kwargs) - - uri = transcoded_request["uri"] - method = transcoded_request["method"] - - # Jsonify the query params - query_params_request = operations_pb2.GetOperationRequest() - json_format.ParseDict(transcoded_request["query_params"], query_params_request) - query_params = json_format.MessageToDict( - query_params_request, - preserving_proto_field_name=False, - use_integers_for_enums=False, - ) - - # Send the request - headers = dict(metadata) - headers["Content-Type"] = "application/json" - # TODO(https://github.com/googleapis/python-api-core/issues/721): Update incorrect use of `uri`` variable name. - response = await getattr(self._session, method)( - "{host}{uri}".format(host=self._host, uri=uri), - timeout=timeout, - headers=headers, - params=rest_helpers.flatten_query_params(query_params), - ) - content = await response.read() - - # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception - # subclass. - if response.status_code >= 400: - payload = json.loads(content.decode("utf-8")) - request_url = "{host}{uri}".format(host=self._host, uri=uri) - raise core_exceptions.format_http_response_error(response, method, request_url, payload) # type: ignore - - # Return the response - api_response = operations_pb2.Operation() - json_format.Parse(content, api_response, ignore_unknown_fields=False) - return api_response - - async def _delete_operation( - self, - request: operations_pb2.DeleteOperationRequest, - *, - # TODO(https://github.com/googleapis/python-api-core/issues/722): Leverage `retry` - # to allow configuring retryable error codes. - retry=gapic_v1.method_async.DEFAULT, - timeout: Optional[float] = None, - metadata: Sequence[Tuple[str, str]] = (), - ) -> empty_pb2.Empty: - r"""Asynchronously call the delete operation method over HTTP. - - Args: - request (~.operations_pb2.DeleteOperationRequest): - The request object. The request message for - [Operations.DeleteOperation][google.api_core.operations_v1.Operations.DeleteOperation]. - - retry (google.api_core.retry.Retry): Designation of what errors, if any, - should be retried. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - """ - - http_options = [ - { - "method": "delete", - "uri": "/{}/{{name=**/operations/*}}".format(self._path_prefix), - }, - ] - if "google.longrunning.Operations.DeleteOperation" in self._http_options: - http_options = self._http_options[ - "google.longrunning.Operations.DeleteOperation" - ] - - request_kwargs = self._convert_protobuf_message_to_dict(request) - transcoded_request = path_template.transcode(http_options, **request_kwargs) - - uri = transcoded_request["uri"] - method = transcoded_request["method"] - - # Jsonify the query params - query_params_request = operations_pb2.DeleteOperationRequest() - json_format.ParseDict(transcoded_request["query_params"], query_params_request) - query_params = json_format.MessageToDict( - query_params_request, - preserving_proto_field_name=False, - use_integers_for_enums=False, - ) - - # Send the request - headers = dict(metadata) - headers["Content-Type"] = "application/json" - # TODO(https://github.com/googleapis/python-api-core/issues/721): Update incorrect use of `uri`` variable name. - response = await getattr(self._session, method)( - "{host}{uri}".format(host=self._host, uri=uri), - timeout=timeout, - headers=headers, - params=rest_helpers.flatten_query_params(query_params), - ) - - # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception - # subclass. - if response.status_code >= 400: - content = await response.read() - payload = json.loads(content.decode("utf-8")) - request_url = "{host}{uri}".format(host=self._host, uri=uri) - raise core_exceptions.format_http_response_error(response, method, request_url, payload) # type: ignore - - return empty_pb2.Empty() - - async def _cancel_operation( - self, - request: operations_pb2.CancelOperationRequest, - *, - # TODO(https://github.com/googleapis/python-api-core/issues/722): Leverage `retry` - # to allow configuring retryable error codes. - retry=gapic_v1.method_async.DEFAULT, - timeout: Optional[float] = None, - metadata: Sequence[Tuple[str, str]] = (), - # TODO(https://github.com/googleapis/python-api-core/issues/722): Add `retry` parameter - # to allow configuring retryable error codes. - ) -> empty_pb2.Empty: - r"""Asynchronously call the cancel operation method over HTTP. - - Args: - request (~.operations_pb2.CancelOperationRequest): - The request object. The request message for - [Operations.CancelOperation][google.api_core.operations_v1.Operations.CancelOperation]. - timeout (float): The timeout for this request. - metadata (Sequence[Tuple[str, str]]): Strings which should be - sent along with the request as metadata. - """ - - http_options = [ - { - "method": "post", - "uri": "/{}/{{name=**/operations/*}}:cancel".format(self._path_prefix), - "body": "*", - }, - ] - if "google.longrunning.Operations.CancelOperation" in self._http_options: - http_options = self._http_options[ - "google.longrunning.Operations.CancelOperation" - ] - - request_kwargs = self._convert_protobuf_message_to_dict(request) - transcoded_request = path_template.transcode(http_options, **request_kwargs) - - # Jsonify the request body - body_request = operations_pb2.CancelOperationRequest() - json_format.ParseDict(transcoded_request["body"], body_request) - body = json_format.MessageToDict( - body_request, - preserving_proto_field_name=False, - use_integers_for_enums=False, - ) - uri = transcoded_request["uri"] - method = transcoded_request["method"] - - # Jsonify the query params - query_params_request = operations_pb2.CancelOperationRequest() - json_format.ParseDict(transcoded_request["query_params"], query_params_request) - query_params = json_format.MessageToDict( - query_params_request, - preserving_proto_field_name=False, - use_integers_for_enums=False, - ) - - # Send the request - headers = dict(metadata) - headers["Content-Type"] = "application/json" - # TODO(https://github.com/googleapis/python-api-core/issues/721): Update incorrect use of `uri`` variable name. - response = await getattr(self._session, method)( - "{host}{uri}".format(host=self._host, uri=uri), - timeout=timeout, - headers=headers, - params=rest_helpers.flatten_query_params(query_params), - data=body, - ) - - # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception - # subclass. - if response.status_code >= 400: - content = await response.read() - payload = json.loads(content.decode("utf-8")) - request_url = "{host}{uri}".format(host=self._host, uri=uri) - raise core_exceptions.format_http_response_error(response, method, request_url, payload) # type: ignore - - return empty_pb2.Empty() - - @property - def list_operations( - self, - ) -> Callable[ - [operations_pb2.ListOperationsRequest], - Coroutine[Any, Any, operations_pb2.ListOperationsResponse], - ]: - return self._list_operations - - @property - def get_operation( - self, - ) -> Callable[ - [operations_pb2.GetOperationRequest], - Coroutine[Any, Any, operations_pb2.Operation], - ]: - return self._get_operation - - @property - def delete_operation( - self, - ) -> Callable[ - [operations_pb2.DeleteOperationRequest], Coroutine[Any, Any, empty_pb2.Empty] - ]: - return self._delete_operation - - @property - def cancel_operation( - self, - ) -> Callable[ - [operations_pb2.CancelOperationRequest], Coroutine[Any, Any, empty_pb2.Empty] - ]: - return self._cancel_operation - - -__all__ = ("AsyncOperationsRestTransport",) diff --git a/notification-service/venv/Lib/site-packages/google/api_core/page_iterator.py b/notification-service/venv/Lib/site-packages/google/api_core/page_iterator.py deleted file mode 100644 index 23761ec..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/page_iterator.py +++ /dev/null @@ -1,571 +0,0 @@ -# Copyright 2015 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Iterators for paging through paged API methods. - -These iterators simplify the process of paging through API responses -where the request takes a page token and the response is a list of results with -a token for the next page. See `list pagination`_ in the Google API Style Guide -for more details. - -.. _list pagination: - https://cloud.google.com/apis/design/design_patterns#list_pagination - -API clients that have methods that follow the list pagination pattern can -return an :class:`.Iterator`. You can use this iterator to get **all** of -the results across all pages:: - - >>> results_iterator = client.list_resources() - >>> list(results_iterator) # Convert to a list (consumes all values). - -Or you can walk your way through items and call off the search early if -you find what you're looking for (resulting in possibly fewer requests):: - - >>> for resource in results_iterator: - ... print(resource.name) - ... if not resource.is_valid: - ... break - -At any point, you may check the number of items consumed by referencing the -``num_results`` property of the iterator:: - - >>> for my_item in results_iterator: - ... if results_iterator.num_results >= 10: - ... break - -When iterating, not every new item will send a request to the server. -To iterate based on each page of items (where a page corresponds to -a request):: - - >>> for page in results_iterator.pages: - ... print('=' * 20) - ... print(' Page number: {:d}'.format(iterator.page_number)) - ... print(' Items in page: {:d}'.format(page.num_items)) - ... print(' First item: {!r}'.format(next(page))) - ... print('Items remaining: {:d}'.format(page.remaining)) - ... print('Next page token: {}'.format(iterator.next_page_token)) - ==================== - Page number: 1 - Items in page: 1 - First item: - Items remaining: 0 - Next page token: eav1OzQB0OM8rLdGXOEsyQWSG - ==================== - Page number: 2 - Items in page: 19 - First item: - Items remaining: 18 - Next page token: None - -Then, for each page you can get all the resources on that page by iterating -through it or using :func:`list`:: - - >>> list(page) - [ - , - , - , - ] -""" - -import abc - - -class Page(object): - """Single page of results in an iterator. - - Args: - parent (google.api_core.page_iterator.Iterator): The iterator that owns - the current page. - items (Sequence[Any]): An iterable (that also defines __len__) of items - from a raw API response. - item_to_value (Callable[google.api_core.page_iterator.Iterator, Any]): - Callable to convert an item from the type in the raw API response - into the native object. Will be called with the iterator and a - single item. - raw_page Optional[google.protobuf.message.Message]: - The raw page response. - """ - - def __init__(self, parent, items, item_to_value, raw_page=None): - self._parent = parent - self._num_items = len(items) - self._remaining = self._num_items - self._item_iter = iter(items) - self._item_to_value = item_to_value - self._raw_page = raw_page - - @property - def raw_page(self): - """google.protobuf.message.Message""" - return self._raw_page - - @property - def num_items(self): - """int: Total items in the page.""" - return self._num_items - - @property - def remaining(self): - """int: Remaining items in the page.""" - return self._remaining - - def __iter__(self): - """The :class:`Page` is an iterator of items.""" - return self - - def __next__(self): - """Get the next value in the page.""" - item = next(self._item_iter) - result = self._item_to_value(self._parent, item) - # Since we've successfully got the next value from the - # iterator, we update the number of remaining. - self._remaining -= 1 - return result - - -def _item_to_value_identity(iterator, item): - """An item to value transformer that returns the item un-changed.""" - # pylint: disable=unused-argument - # We are conforming to the interface defined by Iterator. - return item - - -class Iterator(object, metaclass=abc.ABCMeta): - """A generic class for iterating through API list responses. - - Args: - client(google.cloud.client.Client): The API client. - item_to_value (Callable[google.api_core.page_iterator.Iterator, Any]): - Callable to convert an item from the type in the raw API response - into the native object. Will be called with the iterator and a - single item. - page_token (str): A token identifying a page in a result set to start - fetching results from. - max_results (int): The maximum number of results to fetch. - """ - - def __init__( - self, - client, - item_to_value=_item_to_value_identity, - page_token=None, - max_results=None, - ): - self._started = False - self.__active_iterator = None - - self.client = client - """Optional[Any]: The client that created this iterator.""" - self.item_to_value = item_to_value - """Callable[Iterator, Any]: Callable to convert an item from the type - in the raw API response into the native object. Will be called with - the iterator and a - single item. - """ - self.max_results = max_results - """int: The maximum number of results to fetch""" - - # The attributes below will change over the life of the iterator. - self.page_number = 0 - """int: The current page of results.""" - self.next_page_token = page_token - """str: The token for the next page of results. If this is set before - the iterator starts, it effectively offsets the iterator to a - specific starting point.""" - self.num_results = 0 - """int: The total number of results fetched so far.""" - - @property - def pages(self): - """Iterator of pages in the response. - - returns: - types.GeneratorType[google.api_core.page_iterator.Page]: A - generator of page instances. - - raises: - ValueError: If the iterator has already been started. - """ - if self._started: - raise ValueError("Iterator has already started", self) - self._started = True - return self._page_iter(increment=True) - - def _items_iter(self): - """Iterator for each item returned.""" - for page in self._page_iter(increment=False): - for item in page: - self.num_results += 1 - yield item - - def __iter__(self): - """Iterator for each item returned. - - Returns: - types.GeneratorType[Any]: A generator of items from the API. - - Raises: - ValueError: If the iterator has already been started. - """ - if self._started: - raise ValueError("Iterator has already started", self) - self._started = True - return self._items_iter() - - def __next__(self): - if self.__active_iterator is None: - self.__active_iterator = iter(self) - return next(self.__active_iterator) - - def _page_iter(self, increment): - """Generator of pages of API responses. - - Args: - increment (bool): Flag indicating if the total number of results - should be incremented on each page. This is useful since a page - iterator will want to increment by results per page while an - items iterator will want to increment per item. - - Yields: - Page: each page of items from the API. - """ - page = self._next_page() - while page is not None: - self.page_number += 1 - if increment: - self.num_results += page.num_items - yield page - page = self._next_page() - - @abc.abstractmethod - def _next_page(self): - """Get the next page in the iterator. - - This does nothing and is intended to be over-ridden by subclasses - to return the next :class:`Page`. - - Raises: - NotImplementedError: Always, this method is abstract. - """ - raise NotImplementedError - - -def _do_nothing_page_start(iterator, page, response): - """Helper to provide custom behavior after a :class:`Page` is started. - - This is a do-nothing stand-in as the default value. - - Args: - iterator (Iterator): An iterator that holds some request info. - page (Page): The page that was just created. - response (Any): The API response for a page. - """ - # pylint: disable=unused-argument - pass - - -class HTTPIterator(Iterator): - """A generic class for iterating through HTTP/JSON API list responses. - - To make an iterator work, you'll need to provide a way to convert a JSON - item returned from the API into the object of your choice (via - ``item_to_value``). You also may need to specify a custom ``items_key`` so - that a given response (containing a page of results) can be parsed into an - iterable page of the actual objects you want. - - Args: - client (google.cloud.client.Client): The API client. - api_request (Callable): The function to use to make API requests. - Generally, this will be - :meth:`google.cloud._http.JSONConnection.api_request`. - path (str): The method path to query for the list of items. - item_to_value (Callable[google.api_core.page_iterator.Iterator, Any]): - Callable to convert an item from the type in the JSON response into - a native object. Will be called with the iterator and a single - item. - items_key (str): The key in the API response where the list of items - can be found. - page_token (str): A token identifying a page in a result set to start - fetching results from. - page_size (int): The maximum number of results to fetch per page - max_results (int): The maximum number of results to fetch - extra_params (dict): Extra query string parameters for the - API call. - page_start (Callable[ - google.api_core.page_iterator.Iterator, - google.api_core.page_iterator.Page, dict]): Callable to provide - any special behavior after a new page has been created. Assumed - signature takes the :class:`.Iterator` that started the page, - the :class:`.Page` that was started and the dictionary containing - the page response. - next_token (str): The name of the field used in the response for page - tokens. - - .. autoattribute:: pages - """ - - _DEFAULT_ITEMS_KEY = "items" - _PAGE_TOKEN = "pageToken" - _MAX_RESULTS = "maxResults" - _NEXT_TOKEN = "nextPageToken" - _RESERVED_PARAMS = frozenset([_PAGE_TOKEN]) - _HTTP_METHOD = "GET" - - def __init__( - self, - client, - api_request, - path, - item_to_value, - items_key=_DEFAULT_ITEMS_KEY, - page_token=None, - page_size=None, - max_results=None, - extra_params=None, - page_start=_do_nothing_page_start, - next_token=_NEXT_TOKEN, - ): - super(HTTPIterator, self).__init__( - client, item_to_value, page_token=page_token, max_results=max_results - ) - self.api_request = api_request - self.path = path - self._items_key = items_key - self.extra_params = extra_params - self._page_size = page_size - self._page_start = page_start - self._next_token = next_token - # Verify inputs / provide defaults. - if self.extra_params is None: - self.extra_params = {} - self._verify_params() - - def _verify_params(self): - """Verifies the parameters don't use any reserved parameter. - - Raises: - ValueError: If a reserved parameter is used. - """ - reserved_in_use = self._RESERVED_PARAMS.intersection(self.extra_params) - if reserved_in_use: - raise ValueError("Using a reserved parameter", reserved_in_use) - - def _next_page(self): - """Get the next page in the iterator. - - Returns: - Optional[Page]: The next page in the iterator or :data:`None` if - there are no pages left. - """ - if self._has_next_page(): - response = self._get_next_page_response() - items = response.get(self._items_key, ()) - page = Page(self, items, self.item_to_value, raw_page=response) - self._page_start(self, page, response) - self.next_page_token = response.get(self._next_token) - return page - else: - return None - - def _has_next_page(self): - """Determines whether or not there are more pages with results. - - Returns: - bool: Whether the iterator has more pages. - """ - if self.page_number == 0: - return True - - if self.max_results is not None: - if self.num_results >= self.max_results: - return False - - return self.next_page_token is not None - - def _get_query_params(self): - """Getter for query parameters for the next request. - - Returns: - dict: A dictionary of query parameters. - """ - result = {} - if self.next_page_token is not None: - result[self._PAGE_TOKEN] = self.next_page_token - - page_size = None - if self.max_results is not None: - page_size = self.max_results - self.num_results - if self._page_size is not None: - page_size = min(page_size, self._page_size) - elif self._page_size is not None: - page_size = self._page_size - - if page_size is not None: - result[self._MAX_RESULTS] = page_size - - result.update(self.extra_params) - return result - - def _get_next_page_response(self): - """Requests the next page from the path provided. - - Returns: - dict: The parsed JSON response of the next page's contents. - - Raises: - ValueError: If the HTTP method is not ``GET`` or ``POST``. - """ - params = self._get_query_params() - if self._HTTP_METHOD == "GET": - return self.api_request( - method=self._HTTP_METHOD, path=self.path, query_params=params - ) - elif self._HTTP_METHOD == "POST": - return self.api_request( - method=self._HTTP_METHOD, path=self.path, data=params - ) - else: - raise ValueError("Unexpected HTTP method", self._HTTP_METHOD) - - -class _GAXIterator(Iterator): - """A generic class for iterating through Cloud gRPC APIs list responses. - - Any: - client (google.cloud.client.Client): The API client. - page_iter (google.gax.PageIterator): A GAX page iterator to be wrapped - to conform to the :class:`Iterator` interface. - item_to_value (Callable[Iterator, Any]): Callable to convert an item - from the protobuf response into a native object. Will - be called with the iterator and a single item. - max_results (int): The maximum number of results to fetch. - - .. autoattribute:: pages - """ - - def __init__(self, client, page_iter, item_to_value, max_results=None): - super(_GAXIterator, self).__init__( - client, - item_to_value, - page_token=page_iter.page_token, - max_results=max_results, - ) - self._gax_page_iter = page_iter - - def _next_page(self): - """Get the next page in the iterator. - - Wraps the response from the :class:`~google.gax.PageIterator` in a - :class:`Page` instance and captures some state at each page. - - Returns: - Optional[Page]: The next page in the iterator or :data:`None` if - there are no pages left. - """ - try: - items = next(self._gax_page_iter) - page = Page(self, items, self.item_to_value) - self.next_page_token = self._gax_page_iter.page_token or None - return page - except StopIteration: - return None - - -class GRPCIterator(Iterator): - """A generic class for iterating through gRPC list responses. - - .. note:: The class does not take a ``page_token`` argument because it can - just be specified in the ``request``. - - Args: - client (google.cloud.client.Client): The API client. This unused by - this class, but kept to satisfy the :class:`Iterator` interface. - method (Callable[protobuf.Message]): A bound gRPC method that should - take a single message for the request. - request (protobuf.Message): The request message. - items_field (str): The field in the response message that has the - items for the page. - item_to_value (Callable[GRPCIterator, Any]): Callable to convert an - item from the type in the JSON response into a native object. Will - be called with the iterator and a single item. - request_token_field (str): The field in the request message used to - specify the page token. - response_token_field (str): The field in the response message that has - the token for the next page. - max_results (int): The maximum number of results to fetch. - - .. autoattribute:: pages - """ - - _DEFAULT_REQUEST_TOKEN_FIELD = "page_token" - _DEFAULT_RESPONSE_TOKEN_FIELD = "next_page_token" - - def __init__( - self, - client, - method, - request, - items_field, - item_to_value=_item_to_value_identity, - request_token_field=_DEFAULT_REQUEST_TOKEN_FIELD, - response_token_field=_DEFAULT_RESPONSE_TOKEN_FIELD, - max_results=None, - ): - super(GRPCIterator, self).__init__( - client, item_to_value, max_results=max_results - ) - self._method = method - self._request = request - self._items_field = items_field - self._request_token_field = request_token_field - self._response_token_field = response_token_field - - def _next_page(self): - """Get the next page in the iterator. - - Returns: - Page: The next page in the iterator or :data:`None` if - there are no pages left. - """ - if not self._has_next_page(): - return None - - if self.next_page_token is not None: - setattr(self._request, self._request_token_field, self.next_page_token) - - response = self._method(self._request) - - self.next_page_token = getattr(response, self._response_token_field) - items = getattr(response, self._items_field) - page = Page(self, items, self.item_to_value, raw_page=response) - - return page - - def _has_next_page(self): - """Determines whether or not there are more pages with results. - - Returns: - bool: Whether the iterator has more pages. - """ - if self.page_number == 0: - return True - - if self.max_results is not None: - if self.num_results >= self.max_results: - return False - - # Note: intentionally a falsy check instead of a None check. The RPC - # can return an empty string indicating no more pages. - return True if self.next_page_token else False diff --git a/notification-service/venv/Lib/site-packages/google/api_core/page_iterator_async.py b/notification-service/venv/Lib/site-packages/google/api_core/page_iterator_async.py deleted file mode 100644 index c072575..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/page_iterator_async.py +++ /dev/null @@ -1,285 +0,0 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""AsyncIO iterators for paging through paged API methods. - -These iterators simplify the process of paging through API responses -where the request takes a page token and the response is a list of results with -a token for the next page. See `list pagination`_ in the Google API Style Guide -for more details. - -.. _list pagination: - https://cloud.google.com/apis/design/design_patterns#list_pagination - -API clients that have methods that follow the list pagination pattern can -return an :class:`.AsyncIterator`: - - >>> results_iterator = await client.list_resources() - -Or you can walk your way through items and call off the search early if -you find what you're looking for (resulting in possibly fewer requests):: - - >>> async for resource in results_iterator: - ... print(resource.name) - ... if not resource.is_valid: - ... break - -At any point, you may check the number of items consumed by referencing the -``num_results`` property of the iterator:: - - >>> async for my_item in results_iterator: - ... if results_iterator.num_results >= 10: - ... break - -When iterating, not every new item will send a request to the server. -To iterate based on each page of items (where a page corresponds to -a request):: - - >>> async for page in results_iterator.pages: - ... print('=' * 20) - ... print(' Page number: {:d}'.format(iterator.page_number)) - ... print(' Items in page: {:d}'.format(page.num_items)) - ... print(' First item: {!r}'.format(next(page))) - ... print('Items remaining: {:d}'.format(page.remaining)) - ... print('Next page token: {}'.format(iterator.next_page_token)) - ==================== - Page number: 1 - Items in page: 1 - First item: - Items remaining: 0 - Next page token: eav1OzQB0OM8rLdGXOEsyQWSG - ==================== - Page number: 2 - Items in page: 19 - First item: - Items remaining: 18 - Next page token: None -""" - -import abc - -from google.api_core.page_iterator import Page - - -def _item_to_value_identity(iterator, item): - """An item to value transformer that returns the item un-changed.""" - # pylint: disable=unused-argument - # We are conforming to the interface defined by Iterator. - return item - - -class AsyncIterator(abc.ABC): - """A generic class for iterating through API list responses. - - Args: - client(google.cloud.client.Client): The API client. - item_to_value (Callable[google.api_core.page_iterator_async.AsyncIterator, Any]): - Callable to convert an item from the type in the raw API response - into the native object. Will be called with the iterator and a - single item. - page_token (str): A token identifying a page in a result set to start - fetching results from. - max_results (int): The maximum number of results to fetch. - """ - - def __init__( - self, - client, - item_to_value=_item_to_value_identity, - page_token=None, - max_results=None, - ): - self._started = False - self.__active_aiterator = None - - self.client = client - """Optional[Any]: The client that created this iterator.""" - self.item_to_value = item_to_value - """Callable[Iterator, Any]: Callable to convert an item from the type - in the raw API response into the native object. Will be called with - the iterator and a - single item. - """ - self.max_results = max_results - """int: The maximum number of results to fetch.""" - - # The attributes below will change over the life of the iterator. - self.page_number = 0 - """int: The current page of results.""" - self.next_page_token = page_token - """str: The token for the next page of results. If this is set before - the iterator starts, it effectively offsets the iterator to a - specific starting point.""" - self.num_results = 0 - """int: The total number of results fetched so far.""" - - @property - def pages(self): - """Iterator of pages in the response. - - returns: - types.GeneratorType[google.api_core.page_iterator.Page]: A - generator of page instances. - - raises: - ValueError: If the iterator has already been started. - """ - if self._started: - raise ValueError("Iterator has already started", self) - self._started = True - return self._page_aiter(increment=True) - - async def _items_aiter(self): - """Iterator for each item returned.""" - async for page in self._page_aiter(increment=False): - for item in page: - self.num_results += 1 - yield item - - def __aiter__(self): - """Iterator for each item returned. - - Returns: - types.GeneratorType[Any]: A generator of items from the API. - - Raises: - ValueError: If the iterator has already been started. - """ - if self._started: - raise ValueError("Iterator has already started", self) - self._started = True - return self._items_aiter() - - async def __anext__(self): - if self.__active_aiterator is None: - self.__active_aiterator = self.__aiter__() - return await self.__active_aiterator.__anext__() - - async def _page_aiter(self, increment): - """Generator of pages of API responses. - - Args: - increment (bool): Flag indicating if the total number of results - should be incremented on each page. This is useful since a page - iterator will want to increment by results per page while an - items iterator will want to increment per item. - - Yields: - Page: each page of items from the API. - """ - page = await self._next_page() - while page is not None: - self.page_number += 1 - if increment: - self.num_results += page.num_items - yield page - page = await self._next_page() - - @abc.abstractmethod - async def _next_page(self): - """Get the next page in the iterator. - - This does nothing and is intended to be over-ridden by subclasses - to return the next :class:`Page`. - - Raises: - NotImplementedError: Always, this method is abstract. - """ - raise NotImplementedError - - -class AsyncGRPCIterator(AsyncIterator): - """A generic class for iterating through gRPC list responses. - - .. note:: The class does not take a ``page_token`` argument because it can - just be specified in the ``request``. - - Args: - client (google.cloud.client.Client): The API client. This unused by - this class, but kept to satisfy the :class:`Iterator` interface. - method (Callable[protobuf.Message]): A bound gRPC method that should - take a single message for the request. - request (protobuf.Message): The request message. - items_field (str): The field in the response message that has the - items for the page. - item_to_value (Callable[GRPCIterator, Any]): Callable to convert an - item from the type in the JSON response into a native object. Will - be called with the iterator and a single item. - request_token_field (str): The field in the request message used to - specify the page token. - response_token_field (str): The field in the response message that has - the token for the next page. - max_results (int): The maximum number of results to fetch. - - .. autoattribute:: pages - """ - - _DEFAULT_REQUEST_TOKEN_FIELD = "page_token" - _DEFAULT_RESPONSE_TOKEN_FIELD = "next_page_token" - - def __init__( - self, - client, - method, - request, - items_field, - item_to_value=_item_to_value_identity, - request_token_field=_DEFAULT_REQUEST_TOKEN_FIELD, - response_token_field=_DEFAULT_RESPONSE_TOKEN_FIELD, - max_results=None, - ): - super().__init__(client, item_to_value, max_results=max_results) - self._method = method - self._request = request - self._items_field = items_field - self._request_token_field = request_token_field - self._response_token_field = response_token_field - - async def _next_page(self): - """Get the next page in the iterator. - - Returns: - Page: The next page in the iterator or :data:`None` if - there are no pages left. - """ - if not self._has_next_page(): - return None - - if self.next_page_token is not None: - setattr(self._request, self._request_token_field, self.next_page_token) - - response = await self._method(self._request) - - self.next_page_token = getattr(response, self._response_token_field) - items = getattr(response, self._items_field) - page = Page(self, items, self.item_to_value, raw_page=response) - - return page - - def _has_next_page(self): - """Determines whether or not there are more pages with results. - - Returns: - bool: Whether the iterator has more pages. - """ - if self.page_number == 0: - return True - - # Note: intentionally a falsy check instead of a None check. The RPC - # can return an empty string indicating no more pages. - if self.max_results is not None: - if self.num_results >= self.max_results: - return False - - return True if self.next_page_token else False diff --git a/notification-service/venv/Lib/site-packages/google/api_core/path_template.py b/notification-service/venv/Lib/site-packages/google/api_core/path_template.py deleted file mode 100644 index b8ebb2a..0000000 --- a/notification-service/venv/Lib/site-packages/google/api_core/path_template.py +++ /dev/null @@ -1,346 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Expand and validate URL path templates. - -This module provides the :func:`expand` and :func:`validate` functions for -interacting with Google-style URL `path templates`_ which are commonly used -in Google APIs for `resource names`_. - -.. _path templates: https://github.com/googleapis/googleapis/blob - /57e2d376ac7ef48681554204a3ba78a414f2c533/google/api/http.proto#L212 -.. _resource names: https://cloud.google.com/apis/design/resource_names -""" - -from __future__ import unicode_literals - -from collections import deque -import copy -import functools -import re - -# Regular expression for extracting variable parts from a path template. -# The variables can be expressed as: -# -# - "*": a single-segment positional variable, for example: "books/*" -# - "**": a multi-segment positional variable, for example: "shelf/**/book/*" -# - "{name}": a single-segment wildcard named variable, for example -# "books/{name}" -# - "{name=*}: same as above. -# - "{name=**}": a multi-segment wildcard named variable, for example -# "shelf/{name=**}" -# - "{name=/path/*/**}": a multi-segment named variable with a sub-template. -_VARIABLE_RE = re.compile( - r""" - ( # Capture the entire variable expression - (?P\*\*?) # Match & capture * and ** positional variables. - | - # Match & capture named variables {name} - { - (?P[^/]+?) - # Optionally match and capture the named variable's template. - (?:=(?P