diff --git a/gcp/api/osv_service_v1_pb2.py b/gcp/api/osv_service_v1_pb2.py index b8d6466bc11..6dc55ecc8b8 100644 --- a/gcp/api/osv_service_v1_pb2.py +++ b/gcp/api/osv_service_v1_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: osv_service_v1.proto -# Protobuf Python Version: 5.26.1 +# Protobuf Python Version: 4.25.1 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -21,15 +21,15 @@ _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'osv_service_v1_pb2', _globals) -if not _descriptor._USE_C_DESCRIPTORS: - DESCRIPTOR._loaded_options = None - _globals['_OSV'].methods_by_name['GetVulnById']._loaded_options = None +if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None + _globals['_OSV'].methods_by_name['GetVulnById']._options = None _globals['_OSV'].methods_by_name['GetVulnById']._serialized_options = b'\202\323\344\223\002\020\022\016/v1/vulns/{id}' - _globals['_OSV'].methods_by_name['QueryAffected']._loaded_options = None + _globals['_OSV'].methods_by_name['QueryAffected']._options = None _globals['_OSV'].methods_by_name['QueryAffected']._serialized_options = b'\202\323\344\223\002\022\"\t/v1/query:\005query' - _globals['_OSV'].methods_by_name['QueryAffectedBatch']._loaded_options = None + _globals['_OSV'].methods_by_name['QueryAffectedBatch']._options = None _globals['_OSV'].methods_by_name['QueryAffectedBatch']._serialized_options = b'\202\323\344\223\002\027\"\016/v1/querybatch:\005query' - _globals['_OSV'].methods_by_name['DetermineVersion']._loaded_options = None + _globals['_OSV'].methods_by_name['DetermineVersion']._options = None _globals['_OSV'].methods_by_name['DetermineVersion']._serialized_options = b'\202\323\344\223\002)\" /v1experimental/determineversion:\005query' _globals['_VULNERABILITYLIST']._serialized_start=87 _globals['_VULNERABILITYLIST']._serialized_end=166 diff --git a/gcp/api/osv_service_v1_pb2.pyi b/gcp/api/osv_service_v1_pb2.pyi new file mode 100644 index 00000000000..fcaa5899dc5 --- /dev/null +++ b/gcp/api/osv_service_v1_pb2.pyi @@ -0,0 +1,368 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +Copyright 2021 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 builtins +import collections.abc +import google.protobuf.descriptor +import google.protobuf.internal.containers +import google.protobuf.internal.enum_type_wrapper +import google.protobuf.message +import osv.vulnerability_pb2 +import sys +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class VulnerabilityList(google.protobuf.message.Message): + """A list of Vulnerability entries.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + VULNS_FIELD_NUMBER: builtins.int + NEXT_PAGE_TOKEN_FIELD_NUMBER: builtins.int + next_page_token: builtins.str + @property + def vulns(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[osv.vulnerability_pb2.Vulnerability]: ... + def __init__( + self, + *, + vulns: collections.abc.Iterable[osv.vulnerability_pb2.Vulnerability] | None = ..., + next_page_token: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["next_page_token", b"next_page_token", "vulns", b"vulns"]) -> None: ... + +global___VulnerabilityList = VulnerabilityList + +@typing.final +class BatchVulnerabilityList(google.protobuf.message.Message): + """Batched lists of Vulnerability entries.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + RESULTS_FIELD_NUMBER: builtins.int + @property + def results(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___VulnerabilityList]: ... + def __init__( + self, + *, + results: collections.abc.Iterable[global___VulnerabilityList] | None = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["results", b"results"]) -> None: ... + +global___BatchVulnerabilityList = BatchVulnerabilityList + +@typing.final +class Query(google.protobuf.message.Message): + """Query format.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + COMMIT_FIELD_NUMBER: builtins.int + VERSION_FIELD_NUMBER: builtins.int + PACKAGE_FIELD_NUMBER: builtins.int + PAGE_TOKEN_FIELD_NUMBER: builtins.int + commit: builtins.str + """The commit hash to query for. If specified, `version` should not be set.""" + version: builtins.str + """The version string to query for. A fuzzy match is done against upstream + versions. If specified, `commit` should not be set. + """ + page_token: builtins.str + @property + def package(self) -> osv.vulnerability_pb2.Package: + """The package to query against. When a `commit` hash is given, this is + optional. + """ + + def __init__( + self, + *, + commit: builtins.str = ..., + version: builtins.str = ..., + package: osv.vulnerability_pb2.Package | None = ..., + page_token: builtins.str = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["commit", b"commit", "package", b"package", "param", b"param", "version", b"version"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["commit", b"commit", "package", b"package", "page_token", b"page_token", "param", b"param", "version", b"version"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["param", b"param"]) -> typing.Literal["commit", "version"] | None: ... + +global___Query = Query + +@typing.final +class BatchQuery(google.protobuf.message.Message): + """Batch query format.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + QUERIES_FIELD_NUMBER: builtins.int + @property + def queries(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Query]: + """The queries that form this batch query.""" + + def __init__( + self, + *, + queries: collections.abc.Iterable[global___Query] | None = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["queries", b"queries"]) -> None: ... + +global___BatchQuery = BatchQuery + +@typing.final +class GetVulnByIdParameters(google.protobuf.message.Message): + """Parameters for GetBugById.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + ID_FIELD_NUMBER: builtins.int + id: builtins.str + def __init__( + self, + *, + id: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["id", b"id"]) -> None: ... + +global___GetVulnByIdParameters = GetVulnByIdParameters + +@typing.final +class QueryAffectedParameters(google.protobuf.message.Message): + """Parameters for QueryAffected.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + QUERY_FIELD_NUMBER: builtins.int + @property + def query(self) -> global___Query: ... + def __init__( + self, + *, + query: global___Query | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["query", b"query"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["query", b"query"]) -> None: ... + +global___QueryAffectedParameters = QueryAffectedParameters + +@typing.final +class QueryAffectedBatchParameters(google.protobuf.message.Message): + """Parameters for QueryAffectedBatch.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + QUERY_FIELD_NUMBER: builtins.int + @property + def query(self) -> global___BatchQuery: ... + def __init__( + self, + *, + query: global___BatchQuery | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["query", b"query"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["query", b"query"]) -> None: ... + +global___QueryAffectedBatchParameters = QueryAffectedBatchParameters + +@typing.final +class DetermineVersionParameters(google.protobuf.message.Message): + """Parameters for DetermineVersion.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + QUERY_FIELD_NUMBER: builtins.int + @property + def query(self) -> global___VersionQuery: ... + def __init__( + self, + *, + query: global___VersionQuery | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["query", b"query"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["query", b"query"]) -> None: ... + +global___DetermineVersionParameters = DetermineVersionParameters + +@typing.final +class VersionQuery(google.protobuf.message.Message): + """The version query.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAME_FIELD_NUMBER: builtins.int + FILE_HASHES_FIELD_NUMBER: builtins.int + name: builtins.str + """The name of the dependency. Can be empty.""" + @property + def file_hashes(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___FileHash]: ... + def __init__( + self, + *, + name: builtins.str = ..., + file_hashes: collections.abc.Iterable[global___FileHash] | None = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["file_hashes", b"file_hashes", "name", b"name"]) -> None: ... + +global___VersionQuery = VersionQuery + +@typing.final +class FileHash(google.protobuf.message.Message): + """Information about the files in the repository + to identify the version. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _HashType: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _HashTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[FileHash._HashType.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + MD5: FileHash._HashType.ValueType # 0 + + class HashType(_HashType, metaclass=_HashTypeEnumTypeWrapper): ... + MD5: FileHash.HashType.ValueType # 0 + + FILE_PATH_FIELD_NUMBER: builtins.int + HASH_TYPE_FIELD_NUMBER: builtins.int + HASH_FIELD_NUMBER: builtins.int + file_path: builtins.str + """The file path inside the repository, relative to the repository root.""" + hash_type: global___FileHash.HashType.ValueType + hash: builtins.bytes + def __init__( + self, + *, + file_path: builtins.str = ..., + hash_type: global___FileHash.HashType.ValueType = ..., + hash: builtins.bytes = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["file_path", b"file_path", "hash", b"hash", "hash_type", b"hash_type"]) -> None: ... + +global___FileHash = FileHash + +@typing.final +class VersionMatchList(google.protobuf.message.Message): + """Result of DetmineVersion.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + MATCHES_FIELD_NUMBER: builtins.int + @property + def matches(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___VersionMatch]: ... + def __init__( + self, + *, + matches: collections.abc.Iterable[global___VersionMatch] | None = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["matches", b"matches"]) -> None: ... + +global___VersionMatchList = VersionMatchList + +@typing.final +class VersionMatch(google.protobuf.message.Message): + """Match information for the provided VersionQuery.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + SCORE_FIELD_NUMBER: builtins.int + REPO_INFO_FIELD_NUMBER: builtins.int + OSV_IDENTIFIER_FIELD_NUMBER: builtins.int + CPE23_FIELD_NUMBER: builtins.int + MINIMUM_FILE_MATCHES_FIELD_NUMBER: builtins.int + ESTIMATED_DIFF_FILES_FIELD_NUMBER: builtins.int + score: builtins.float + """Score in the interval (0.0, 1.0] with 1.0 being a perfect match.""" + cpe23: builtins.str + """CPE 2.3.""" + minimum_file_matches: builtins.int + """Definite number of files that have matched.""" + estimated_diff_files: builtins.int + """Estimated number of files that are different.""" + @property + def repo_info(self) -> global___VersionRepositoryInformation: + """Information about the upstream repository.""" + + @property + def osv_identifier(self) -> osv.vulnerability_pb2.Package: + """The OSV identifier.""" + + def __init__( + self, + *, + score: builtins.float = ..., + repo_info: global___VersionRepositoryInformation | None = ..., + osv_identifier: osv.vulnerability_pb2.Package | None = ..., + cpe23: builtins.str = ..., + minimum_file_matches: builtins.int = ..., + estimated_diff_files: builtins.int = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["osv_identifier", b"osv_identifier", "repo_info", b"repo_info"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["cpe23", b"cpe23", "estimated_diff_files", b"estimated_diff_files", "minimum_file_matches", b"minimum_file_matches", "osv_identifier", b"osv_identifier", "repo_info", b"repo_info", "score", b"score"]) -> None: ... + +global___VersionMatch = VersionMatch + +@typing.final +class VersionRepositoryInformation(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _RepoType: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _RepoTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[VersionRepositoryInformation._RepoType.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + UNSPECIFIED: VersionRepositoryInformation._RepoType.ValueType # 0 + GIT: VersionRepositoryInformation._RepoType.ValueType # 1 + + class RepoType(_RepoType, metaclass=_RepoTypeEnumTypeWrapper): ... + UNSPECIFIED: VersionRepositoryInformation.RepoType.ValueType # 0 + GIT: VersionRepositoryInformation.RepoType.ValueType # 1 + + TYPE_FIELD_NUMBER: builtins.int + ADDRESS_FIELD_NUMBER: builtins.int + TAG_FIELD_NUMBER: builtins.int + VERSION_FIELD_NUMBER: builtins.int + COMMIT_FIELD_NUMBER: builtins.int + type: global___VersionRepositoryInformation.RepoType.ValueType + address: builtins.str + """Source address of the repository.""" + tag: builtins.str + """Commit tag""" + version: builtins.str + """Parsed version from commit tag""" + commit: builtins.str + """Commit hash hex.""" + def __init__( + self, + *, + type: global___VersionRepositoryInformation.RepoType.ValueType = ..., + address: builtins.str = ..., + tag: builtins.str = ..., + version: builtins.str = ..., + commit: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["address", b"address", "commit", b"commit", "tag", b"tag", "type", b"type", "version", b"version"]) -> None: ... + +global___VersionRepositoryInformation = VersionRepositoryInformation diff --git a/gcp/api/osv_service_v1_pb2_grpc.py b/gcp/api/osv_service_v1_pb2_grpc.py index 6df3c17b669..d2d89a68ab3 100644 --- a/gcp/api/osv_service_v1_pb2_grpc.py +++ b/gcp/api/osv_service_v1_pb2_grpc.py @@ -1,35 +1,10 @@ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! """Client and server classes corresponding to protobuf-defined services.""" import grpc -import warnings from osv import vulnerability_pb2 as osv_dot_vulnerability__pb2 import osv_service_v1_pb2 as osv__service__v1__pb2 -GRPC_GENERATED_VERSION = '1.64.1' -GRPC_VERSION = grpc.__version__ -EXPECTED_ERROR_RELEASE = '1.65.0' -SCHEDULED_RELEASE_DATE = 'June 25, 2024' -_version_not_supported = False - -try: - from grpc._utilities import first_version_is_lower - _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) -except ImportError: - _version_not_supported = True - -if _version_not_supported: - warnings.warn( - f'The grpc package installed is at version {GRPC_VERSION},' - + f' but the generated code in osv_service_v1_pb2_grpc.py depends on' - + f' grpcio>={GRPC_GENERATED_VERSION}.' - + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' - + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' - + f' This warning will become an error in {EXPECTED_ERROR_RELEASE},' - + f' scheduled for release on {SCHEDULED_RELEASE_DATE}.', - RuntimeWarning - ) - class OSVStub(object): """Open source vulnerability database. @@ -45,22 +20,22 @@ def __init__(self, channel): '/osv.v1.OSV/GetVulnById', request_serializer=osv__service__v1__pb2.GetVulnByIdParameters.SerializeToString, response_deserializer=osv_dot_vulnerability__pb2.Vulnerability.FromString, - _registered_method=True) + ) self.QueryAffected = channel.unary_unary( '/osv.v1.OSV/QueryAffected', request_serializer=osv__service__v1__pb2.QueryAffectedParameters.SerializeToString, response_deserializer=osv__service__v1__pb2.VulnerabilityList.FromString, - _registered_method=True) + ) self.QueryAffectedBatch = channel.unary_unary( '/osv.v1.OSV/QueryAffectedBatch', request_serializer=osv__service__v1__pb2.QueryAffectedBatchParameters.SerializeToString, response_deserializer=osv__service__v1__pb2.BatchVulnerabilityList.FromString, - _registered_method=True) + ) self.DetermineVersion = channel.unary_unary( '/osv.v1.OSV/DetermineVersion', request_serializer=osv__service__v1__pb2.DetermineVersionParameters.SerializeToString, response_deserializer=osv__service__v1__pb2.VersionMatchList.FromString, - _registered_method=True) + ) class OSVServicer(object): @@ -125,7 +100,6 @@ def add_OSVServicer_to_server(servicer, server): generic_handler = grpc.method_handlers_generic_handler( 'osv.v1.OSV', rpc_method_handlers) server.add_generic_rpc_handlers((generic_handler,)) - server.add_registered_method_handlers('osv.v1.OSV', rpc_method_handlers) # This class is part of an EXPERIMENTAL API. @@ -144,21 +118,11 @@ def GetVulnById(request, wait_for_ready=None, timeout=None, metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/osv.v1.OSV/GetVulnById', + return grpc.experimental.unary_unary(request, target, '/osv.v1.OSV/GetVulnById', osv__service__v1__pb2.GetVulnByIdParameters.SerializeToString, osv_dot_vulnerability__pb2.Vulnerability.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def QueryAffected(request, @@ -171,21 +135,11 @@ def QueryAffected(request, wait_for_ready=None, timeout=None, metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/osv.v1.OSV/QueryAffected', + return grpc.experimental.unary_unary(request, target, '/osv.v1.OSV/QueryAffected', osv__service__v1__pb2.QueryAffectedParameters.SerializeToString, osv__service__v1__pb2.VulnerabilityList.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def QueryAffectedBatch(request, @@ -198,21 +152,11 @@ def QueryAffectedBatch(request, wait_for_ready=None, timeout=None, metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/osv.v1.OSV/QueryAffectedBatch', + return grpc.experimental.unary_unary(request, target, '/osv.v1.OSV/QueryAffectedBatch', osv__service__v1__pb2.QueryAffectedBatchParameters.SerializeToString, osv__service__v1__pb2.BatchVulnerabilityList.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def DetermineVersion(request, @@ -225,18 +169,8 @@ def DetermineVersion(request, wait_for_ready=None, timeout=None, metadata=None): - return grpc.experimental.unary_unary( - request, - target, - '/osv.v1.OSV/DetermineVersion', + return grpc.experimental.unary_unary(request, target, '/osv.v1.OSV/DetermineVersion', osv__service__v1__pb2.DetermineVersionParameters.SerializeToString, osv__service__v1__pb2.VersionMatchList.FromString, - options, - channel_credentials, - insecure, - call_credentials, - compression, - wait_for_ready, - timeout, - metadata, - _registered_method=True) + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/gcp/api/poetry.lock b/gcp/api/poetry.lock index 8e4c1909c6b..e90274ad985 100644 --- a/gcp/api/poetry.lock +++ b/gcp/api/poetry.lock @@ -65,78 +65,78 @@ files = [ [[package]] name = "cffi" -version = "1.17.0" +version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" files = [ - {file = "cffi-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb"}, - {file = "cffi-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f"}, - {file = "cffi-1.17.0-cp310-cp310-win32.whl", hash = "sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc"}, - {file = "cffi-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb"}, - {file = "cffi-1.17.0-cp311-cp311-win32.whl", hash = "sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9"}, - {file = "cffi-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885"}, - {file = "cffi-1.17.0-cp312-cp312-win32.whl", hash = "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492"}, - {file = "cffi-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4"}, - {file = "cffi-1.17.0-cp313-cp313-win32.whl", hash = "sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a"}, - {file = "cffi-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7"}, - {file = "cffi-1.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c"}, - {file = "cffi-1.17.0-cp38-cp38-win32.whl", hash = "sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499"}, - {file = "cffi-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4"}, - {file = "cffi-1.17.0-cp39-cp39-win32.whl", hash = "sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb"}, - {file = "cffi-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29"}, - {file = "cffi-1.17.0.tar.gz", hash = "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, ] [package.dependencies] @@ -812,6 +812,21 @@ files = [ {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] +[[package]] +name = "mypy-protobuf" +version = "3.6.0" +description = "Generate mypy stub files from protobuf specs" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-protobuf-3.6.0.tar.gz", hash = "sha256:02f242eb3409f66889f2b1a3aa58356ec4d909cdd0f93115622e9e70366eca3c"}, + {file = "mypy_protobuf-3.6.0-py3-none-any.whl", hash = "sha256:56176e4d569070e7350ea620262478b49b7efceba4103d468448f1d21492fd6c"}, +] + +[package.dependencies] +protobuf = ">=4.25.3" +types-protobuf = ">=4.24" + [[package]] name = "opentelemetry-api" version = "1.27.0" @@ -886,19 +901,19 @@ pyparsing = ">=2.0.2" [[package]] name = "platformdirs" -version = "4.2.2" +version = "4.3.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, - {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, + {file = "platformdirs-4.3.2-py3-none-any.whl", hash = "sha256:eb1c8582560b34ed4ba105009a4badf7f6f85768b30126f351328507b2beb617"}, + {file = "platformdirs-4.3.2.tar.gz", hash = "sha256:9e5e27a08aa095dd127b9f2e764d74254f482fef22b0970773bfba79d091ab8c"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -type = ["mypy (>=1.8)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] [[package]] name = "proto-plus" @@ -1332,13 +1347,13 @@ files = [ [[package]] name = "setuptools" -version = "74.1.1" +version = "74.1.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-74.1.1-py3-none-any.whl", hash = "sha256:fc91b5f89e392ef5b77fe143b17e32f65d3024744fba66dc3afe07201684d766"}, - {file = "setuptools-74.1.1.tar.gz", hash = "sha256:2353af060c06388be1cecbf5953dcdb1f38362f87a2356c480b6b4d5fcfc8847"}, + {file = "setuptools-74.1.2-py3-none-any.whl", hash = "sha256:5f4c08aa4d3ebcb57a50c33b1b07e94315d7fc7230f7115e47fc99776c8ce308"}, + {file = "setuptools-74.1.2.tar.gz", hash = "sha256:95b40ed940a1c67eb70fc099094bd6e99c6ee7c23aa2306f4d2697ba7916f9c6"}, ] [package.extras] @@ -1372,6 +1387,17 @@ files = [ {file = "tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79"}, ] +[[package]] +name = "types-protobuf" +version = "5.27.0.20240907" +description = "Typing stubs for protobuf" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-protobuf-5.27.0.20240907.tar.gz", hash = "sha256:bb6f90f66b18d4d1c75667b6586334b0573a6fcee5eb0142a7348a765a7cbadc"}, + {file = "types_protobuf-5.27.0.20240907-py3-none-any.whl", hash = "sha256:5443270534cc8072909ef7ad9e1421ccff924ca658749a6396c0c43d64c32676"}, +] + [[package]] name = "urllib3" version = "2.2.2" @@ -1506,4 +1532,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "02961e990f6033875f823a460833d9ccf4a18d747498aa170611ad074241f242" +content-hash = "ba882a87cceb578615108c25d664bdb48b23dc2e87ecf94bf5c049b53a64cc54" diff --git a/gcp/api/pyproject.toml b/gcp/api/pyproject.toml index b3b2cac5a74..51dda5e838e 100644 --- a/gcp/api/pyproject.toml +++ b/gcp/api/pyproject.toml @@ -18,6 +18,7 @@ osv = { path = "../../", develop = true } [tool.poetry.dev-dependencies] grpcio-tools = "*" +mypy-protobuf = "^3.6.0" yapf = "*" pylint = "*" diff --git a/gcp/api/server.py b/gcp/api/server.py index 3272dd6ce08..f054694fbb8 100644 --- a/gcp/api/server.py +++ b/gcp/api/server.py @@ -15,7 +15,6 @@ import argparse import codecs -import concurrent from dataclasses import dataclass from datetime import datetime, timedelta import math @@ -25,7 +24,8 @@ import os import threading import time -from typing import Callable, List +import concurrent.futures +from typing import Callable from collections import defaultdict @@ -44,6 +44,7 @@ from osv import ecosystems from osv import semver_index from osv import purl_helpers +from osv import vulnerability_pb2 from osv.logs import setup_gcp_logging from gcp.api import osv_service_v1_pb2 from gcp.api import osv_service_v1_pb2_grpc @@ -94,6 +95,13 @@ # Prefix for the _TAG_PREFIX = "refs/tags/" +# ---- +# Type Aliases: + +ToResponseCallable = Callable[[osv.Bug], vulnerability_pb2.Vulnerability] + +# ---- + _ndb_client = ndb.Client() @@ -154,7 +162,7 @@ class OSVServicer(osv_service_v1_pb2_grpc.OSVServicer, @trace_filter.log_trace def GetVulnById(self, request, context: grpc.ServicerContext): """Return a `Vulnerability` object for a given OSV ID.""" - bug: osv.Bug = osv.Bug.get_by_id(request.id) + bug = osv.Bug.get_by_id(request.id) if not bug or bug.status == osv.BugStatus.UNPROCESSED: context.abort(grpc.StatusCode.NOT_FOUND, 'Bug not found.') return None @@ -207,7 +215,8 @@ def QueryAffected(self, request, context: grpc.ServicerContext): total_responses=ResponsesCount(0)) try: - results, next_page_token = do_query(request.query, query_context).result() + results, next_page_token = do_query( + request.query, query_context).result() # type: ignore except InvalidArgument: # Currently cannot think of any other way # this can be raised other than invalid cursor @@ -490,7 +499,7 @@ def should_skip_bucket(path: str) -> bool: def process_buckets( - file_results: List[osv.FileResult]) -> List[osv.RepoIndexBucket]: + file_results: list[osv.FileResult]) -> list[osv.RepoIndexBucket]: """ Create buckets in the same process as indexer to generate the same bucket hashes @@ -504,18 +513,19 @@ def process_buckets( buckets[int.from_bytes(fr.hash[:2], byteorder='big') % _BUCKET_SIZE].append( fr.hash) - results: list[osv.RepoIndexBucket] = [None] * _BUCKET_SIZE - for bucket_idx, bucket in enumerate(buckets): + results: list[osv.RepoIndexBucket] = [] + for bucket in buckets: bucket.sort() hasher = hashlib.md5() for v in bucket: hasher.update(v) - results[bucket_idx] = osv.RepoIndexBucket( - node_hash=hasher.digest(), - files_contained=len(bucket), - ) + results.append( + osv.RepoIndexBucket( + node_hash=hasher.digest(), + files_contained=len(bucket), + )) return results @@ -535,7 +545,8 @@ def build_determine_version_result( # Only interested in our maximum number of results bucket_match_items = bucket_match_items[:min( _MAX_DETERMINE_VER_RESULTS_TO_RETURN, len(bucket_match_items))] - idx_futures = ndb.get_multi_async([b[0] for b in bucket_match_items]) + idx_futures = ndb.get_multi_async([b[0] for b in bucket_match_items + ]) # type: ignore output = [] # Apply bitwise NOT to the user bitmap @@ -661,7 +672,7 @@ def determine_version(version_query: osv_service_v1_pb2.VersionQuery, continue for index_bucket in result: - parent_key = index_bucket.key.parent() + parent_key = index_bucket.key.parent() # type: ignore file_match_count[parent_key] += index_bucket.files_contained bucket_match_count[parent_key] += 1 @@ -677,7 +688,7 @@ def determine_version(version_query: osv_service_v1_pb2.VersionQuery, @ndb.tasklet -def do_query(query, +def do_query(query: osv_service_v1_pb2.Query, context: QueryContext, include_details=True) -> tuple[list, str | None]: """Do a query.""" @@ -722,11 +733,12 @@ def do_query(query, 'version specified in params and purl query', ) - def to_response(b): + def to_response(b: osv.Bug): # Skip retrieving aliases from to_vulnerability(). # Retrieve it asynchronously later. return bug_to_response(b, include_details) + bugs: list[vulnerability_pb2.Vulnerability] if query.WhichOneof('param') == 'commit': try: commit_bytes = codecs.decode(query.commit, 'hex') @@ -760,7 +772,9 @@ def to_response(b): else: context.service_context.abort(grpc.StatusCode.INVALID_ARGUMENT, 'Invalid query.') - return None + # This will never be reached, and is just here for the type checker, + # to know that control flow breaks here. + raise ValueError # Asynchronously retrieve computed aliases and related ids here # to prevent significant query time increase for packages with @@ -773,7 +787,7 @@ def to_response(b): related.append(osv.get_related_async(bug.id)) for i, alias in enumerate(aliases): - alias_group = yield alias + alias_group: osv.AliasGroup = yield alias if not alias_group: continue alias_ids = sorted(list(set(alias_group.bug_ids) - {bugs[i].id})) @@ -783,7 +797,7 @@ def to_response(b): bugs[i].modified.FromDatetime(modified_time) for i, related_ids in enumerate(related): - related_bug_ids = yield related_ids + related_bug_ids: list[str] = yield related_ids bugs[i].related[:] = sorted( list(set(related_bug_ids + list(bugs[i].related)))) @@ -803,7 +817,9 @@ def to_response(b): return bugs, next_page_token_str -def bug_to_response(bug, include_details=True, include_alias=False): +def bug_to_response(bug: osv.Bug, + include_details=True, + include_alias=False) -> vulnerability_pb2.Vulnerability: """Convert a Bug entity to a response object.""" if include_details: return bug.to_vulnerability( @@ -813,9 +829,13 @@ def bug_to_response(bug, include_details=True, include_alias=False): @ndb.tasklet -def _get_bugs(bug_ids, to_response=bug_to_response): +def _get_bugs( + bug_ids: list[str], + to_response: ToResponseCallable = bug_to_response +) -> list[vulnerability_pb2.Vulnerability]: """Get bugs from bug ids.""" - bugs = ndb.get_multi_async([ndb.Key(osv.Bug, bug_id) for bug_id in bug_ids]) + bugs = ndb.get_multi_async([ndb.Key(osv.Bug, bug_id) for bug_id in bug_ids + ]) # type: ignore responses = [] for future_bug in bugs: @@ -838,9 +858,11 @@ def _datastore_normalized_purl(purl: PackageURL): @ndb.tasklet -def query_by_commit(context: QueryContext, - commit: bytes, - to_response: Callable = bug_to_response) -> list: +def query_by_commit( + context: QueryContext, + commit: bytes, + to_response: ToResponseCallable = bug_to_response +) -> list[vulnerability_pb2.Vulnerability]: """ Perform a query by commit. @@ -914,7 +936,8 @@ def _clean_purl(purl: PackageURL): # No qualifiers, and our PURLs never have versions, so just match name return purl_query.name == purl_db.name - if purl_db.qualifiers: + if (purl_db.qualifiers and isinstance(purl_db.qualifiers, dict) and + isinstance(purl_query.qualifiers, dict)): # A arch of 'source' matches all other architectures if purl_db.qualifiers['arch'] == 'source': purl_db.qualifiers['arch'] = purl_query.qualifiers['arch'] @@ -922,13 +945,14 @@ def _clean_purl(purl: PackageURL): return purl_query == purl_db -def _is_semver_affected(affected_packages, package_name, ecosystem, - purl: PackageURL | None, version): +def _is_semver_affected(affected_packages: list[osv.AffectedPackage], + package_name: str | None, ecosystem: str | None, + purl: PackageURL | None, version_str: str): """Returns whether or not the given version is within an affected SEMVER range. """ - version = semver_index.parse(version) + version = semver_index.parse(version_str) affected = False for affected_package in affected_packages: @@ -1005,7 +1029,7 @@ def _is_version_affected(affected_packages, @ndb.tasklet def _query_by_semver(context: QueryContext, query: ndb.Query, package_name: str | None, ecosystem: str | None, - purl: PackageURL | None, version: str): + purl: PackageURL | None, version: str) -> list[osv.Bug]: """ Perform a query by semver version. @@ -1027,8 +1051,8 @@ def _query_by_semver(context: QueryContext, query: ndb.Query, return [] results = [] - query = query.filter( - osv.Bug.semver_fixed_indexes > semver_index.normalize(version)) + query = query.filter(osv.Bug.semver_fixed_indexes + > semver_index.normalize(version)) # type: ignore context.query_counter += 1 if context.should_skip_query(): @@ -1058,7 +1082,7 @@ def _query_by_generic_version( ecosystem: str | None, purl: PackageURL | None, version: str, -): +) -> list[osv.Bug]: """ Query by generic version. @@ -1104,13 +1128,13 @@ def _query_by_generic_version( def query_by_generic_helper(context: QueryContext, base_query: ndb.Query, package_name: str | None, ecosystem: str | None, purl: PackageURL | None, version: str, - is_normalized): + is_normalized: bool) -> list[osv.Bug]: """ Helper function for query_by_generic. This function can be called multiple times. """ query: ndb.Query = base_query.filter(osv.Bug.affected_fuzzy == version) - results = [] + results: list[osv.Bug] = [] context.query_counter += 1 if context.should_skip_query(): return [] @@ -1121,7 +1145,7 @@ def query_by_generic_helper(context: QueryContext, base_query: ndb.Query, if context.should_break_page(len(results)): context.save_cursor_at_page_break(it) break - bug = it.next() + bug: osv.Bug = it.next() # type: ignore if _is_version_affected( bug.affected_packages, package_name, @@ -1135,12 +1159,14 @@ def query_by_generic_helper(context: QueryContext, base_query: ndb.Query, @ndb.tasklet -def query_by_version(context: QueryContext, - package_name: str | None, - ecosystem: str | None, - purl: PackageURL | None, - version: str, - to_response: Callable = bug_to_response): +def query_by_version( + context: QueryContext, + package_name: str | None, + ecosystem: str | None, + purl: PackageURL | None, + version: str, + to_response: ToResponseCallable = bug_to_response +) -> list[vulnerability_pb2.Vulnerability]: """ Query by (fuzzy) version. @@ -1176,13 +1202,16 @@ def query_by_version(context: QueryContext, else: return [] + ecosystem_info = None if ecosystem: query = query.filter(osv.Bug.ecosystem == ecosystem) + ecosystem_info = ecosystems.get(ecosystem) if purl: purl_ecosystem = purl_helpers.purl_to_ecosystem(purl.type) if purl_ecosystem: ecosystem = purl_ecosystem + ecosystem_info = ecosystems.get(ecosystem) ecosystem_info = ecosystems.get(ecosystem) is_semver = ecosystem_info and ecosystem_info.is_semver @@ -1233,7 +1262,7 @@ def query_by_version(context: QueryContext, @ndb.tasklet def _query_by_comparing_versions(context: QueryContext, query: ndb.Query, package_name: str, ecosystem: str, - version: str) -> list: + version: str) -> list[osv.Bug]: """ Query by comparing versions. @@ -1248,7 +1277,7 @@ def _query_by_comparing_versions(context: QueryContext, query: ndb.Query, Returns: list of osv.Bugs """ - bugs = [] + bugs: list[osv.Bug] = [] context.query_counter += 1 if context.should_skip_query(): @@ -1264,17 +1293,17 @@ def _query_by_comparing_versions(context: QueryContext, query: ndb.Query, context.save_cursor_at_page_break(it) break - bug: osv.Bug = it.next() - for affected_package in bug.affected_packages: + # next() will never return None as we check for has next above. + bug: osv.Bug = it.next() # type: ignore + for affected_package in bug.affected_packages: # type: ignore affected_package: osv.AffectedPackage - package = affected_package.package - package: osv.Package + package: osv.Package = affected_package.package # type: ignore # If the queried ecosystem has no release specified (e.g., "Debian"), # compare against packages in all releases (e.g., "Debian:X"). # Otherwise, only compare within # the specified release (e.g., "Debian:11"). - package_ecosystem = package.ecosystem + package_ecosystem: str = package.ecosystem # type: ignore if not has_release: # Extracts ecosystem name for broader comparison (e.g., "Debian") package_ecosystem = package_ecosystem.split(':')[0] @@ -1298,9 +1327,10 @@ def _query_by_comparing_versions(context: QueryContext, query: ndb.Query, @ndb.tasklet -def query_by_package(context: QueryContext, package_name: str | None, - ecosystem: str | None, purl: PackageURL | None, - to_response: Callable) -> list: +def query_by_package( + context: QueryContext, package_name: str | None, ecosystem: str | None, + purl: PackageURL | None, + to_response: ToResponseCallable) -> list[vulnerability_pb2.Vulnerability]: """ Query by package. @@ -1348,7 +1378,7 @@ def query_by_package(context: QueryContext, package_name: str | None, context.save_cursor_at_page_break(it) break - bug: osv.Bug = it.next() + bug: osv.Bug = it.next() # type: ignore if purl: affected = False @@ -1472,9 +1502,7 @@ def main(): args = parser.parse_args() port = args.port if not port: - port = os.environ.get('PORT') - if not port: - port = 8000 + port = int(os.environ.get('PORT', '8000')) serve(port, args.local) diff --git a/gcp/api/v1/README.md b/gcp/api/v1/README.md index e5833e94b19..4a7394751be 100644 --- a/gcp/api/v1/README.md +++ b/gcp/api/v1/README.md @@ -20,6 +20,7 @@ python3 -m grpc_tools.protoc \ --go_out=../../../tools/indexer-api-caller/ \ --go_opt=Mosv/vulnerability.proto=github.com/google/osv/proto \ --go_opt=Mosv_service_v1.proto=github.com/google/osv/api/proto \ + --mypy_out=../ \ osv_service_v1.proto ``` diff --git a/gcp/api/v1/api_descriptor.pb b/gcp/api/v1/api_descriptor.pb index 8a0c1e373a8..1e13230c653 100644 Binary files a/gcp/api/v1/api_descriptor.pb and b/gcp/api/v1/api_descriptor.pb differ diff --git a/osv/__init__.py b/osv/__init__.py index e836fede8e4..45e00d7e271 100644 --- a/osv/__init__.py +++ b/osv/__init__.py @@ -18,4 +18,5 @@ from .repos import * from .sources import * from .models import * +from .model_helpers import * from .ecosystems import * diff --git a/osv/build_protos.sh b/osv/build_protos.sh index 84ef28f14d8..8343d03b07c 100755 --- a/osv/build_protos.sh +++ b/osv/build_protos.sh @@ -15,4 +15,4 @@ cd ../ -python -m grpc_tools.protoc --python_out=. --proto_path=. osv/vulnerability.proto +python -m grpc_tools.protoc --python_out=. --mypy_out=. --proto_path=. osv/vulnerability.proto diff --git a/osv/ecosystems/helper_base.py b/osv/ecosystems/helper_base.py index 7ede5fd8f0f..3ac11ba2092 100644 --- a/osv/ecosystems/helper_base.py +++ b/osv/ecosystems/helper_base.py @@ -15,6 +15,7 @@ from abc import ABC, abstractmethod import bisect +from typing import Any import requests from urllib.parse import quote @@ -57,7 +58,7 @@ def next_version(self, package, version): return None @abstractmethod - def sort_key(self, version): + def sort_key(self, version: str) -> Any: """Sort key.""" def sort_versions(self, versions): diff --git a/osv/model_helpers.py b/osv/model_helpers.py new file mode 100644 index 00000000000..a802c384755 --- /dev/null +++ b/osv/model_helpers.py @@ -0,0 +1,78 @@ +# Copyright 2021 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. +"""Datastore types.""" + +import datetime + +from google.cloud import ndb + +# pylint: disable=relative-beyond-top-level +from .models import AliasGroup, AffectedEvent, SourceRepository, Bug +from . import ecosystems + + +def utcnow(): + """For mocking.""" + return datetime.datetime.utcnow() + + +def get_source_repository(source_name: str) -> SourceRepository: + """Get source repository.""" + return SourceRepository.get_by_id(source_name) # type: ignore + + +def sorted_events(ecosystem, range_type, events) -> list[AffectedEvent]: + """Sort events.""" + if range_type == 'GIT': + # No need to sort. + return events + + if range_type == 'SEMVER': + ecosystem_helper = ecosystems.SemverEcosystem() + else: + ecosystem_helper = ecosystems.get(ecosystem) + + if ecosystem_helper is None or not ecosystem_helper.supports_ordering: + raise ValueError('Unsupported ecosystem ' + ecosystem) + + # Remove any magic '0' values. + sorted_copy = [] + zero_event = None + for event in events: + if event.value == '0': + zero_event = event + continue + + sorted_copy.append(event) + + sorted_copy.sort(key=lambda e: ecosystem_helper.sort_key(e.value)) + if zero_event: + sorted_copy.insert(0, zero_event) + + return sorted_copy + + +@ndb.tasklet +def get_aliases_async(bug_id: str) -> ndb.Future: + """Gets aliases asynchronously.""" + alias_group = yield AliasGroup.query(AliasGroup.bug_ids == bug_id).get_async() + return alias_group + + +@ndb.tasklet +def get_related_async(bug_id: str) -> ndb.Future: + """Gets related bugs asynchronously.""" + related_bugs = yield Bug.query(Bug.related == bug_id).fetch_async() + related_bug_ids = [bug.db_id for bug in related_bugs] + return related_bug_ids diff --git a/osv/models.py b/osv/models.py index 400b31ee46c..1a312025996 100644 --- a/osv/models.py +++ b/osv/models.py @@ -13,14 +13,14 @@ # limitations under the License. """Datastore types.""" -import datetime +from datetime import datetime import enum import logging import re import os from urllib.parse import urlparse -from typing import List +from typing import Self from google.cloud import ndb from google.protobuf import json_format @@ -65,7 +65,9 @@ def _check_valid_event_type(prop, value): def utcnow(): """For mocking.""" - return datetime.datetime.utcnow() + # The alternative mentioned in the deprecation notice + # does not behave in the same way? Tests fail. + return datetime.utcnow() def _get_purl_indexes(affected_packages): @@ -87,8 +89,8 @@ def _repo_name(repo_url: str) -> str: return name -def _maybe_strip_repo_prefixes(versions: List[str], - repo_urls: List[str]) -> str: +def _maybe_strip_repo_prefixes(versions: list[str], + repo_urls: list[str]) -> str: """Try to strip the repo name from tags prior to normalizing. There are some particularly regex-unfriendly tag names that prefix the @@ -110,7 +112,7 @@ def _maybe_strip_repo_prefixes(versions: List[str], class IDCounter(ndb.Model): """Counter for ID allocations.""" # Next ID to allocate. - next_id = ndb.IntegerProperty() + next_id: int = ndb.IntegerProperty() class AffectedCommits(ndb.Model): @@ -118,81 +120,82 @@ class AffectedCommits(ndb.Model): MAX_COMMITS_PER_ENTITY = 10000 # The main bug ID. - bug_id = ndb.StringProperty() + bug_id: str = ndb.StringProperty() # The commit hash. - commits = ndb.BlobProperty(repeated=True, indexed=True) + commits: list[bytes] = ndb.BlobProperty(repeated=True, indexed=True) # Whether or not the bug is public. - public = ndb.BooleanProperty() + public: bool = ndb.BooleanProperty() # The page for this batch of commits. - page = ndb.IntegerProperty(indexed=False) + page: int = ndb.IntegerProperty(indexed=False) class RegressResult(ndb.Model): """Regression results.""" # The commit hash. - commit = ndb.StringProperty(default='') + commit: str = ndb.StringProperty(default='') # Vulnerability summary. - summary = ndb.TextProperty() + summary: str = ndb.TextProperty() # Vulnerability details. - details = ndb.TextProperty() + details: str = ndb.TextProperty() # Error (if any). - error = ndb.StringProperty() + error: str = ndb.StringProperty() # OSS-Fuzz issue ID. - issue_id = ndb.StringProperty() + issue_id: str = ndb.StringProperty() # Project for the bug. - project = ndb.StringProperty() + project: str = ndb.StringProperty() # Package ecosystem for the project. - ecosystem = ndb.StringProperty() + ecosystem: str = ndb.StringProperty() # Repo URL. - repo_url = ndb.StringProperty() + repo_url: str = ndb.StringProperty() # Severity of the bug. - severity = ndb.StringProperty(validator=_check_valid_severity) + severity: str = ndb.StringProperty(validator=_check_valid_severity) # Reference URLs. - reference_urls = ndb.StringProperty(repeated=True) + reference_urls: list[str] = ndb.StringProperty(repeated=True) # Source timestamp. - timestamp = ndb.DateTimeProperty() + timestamp: datetime = ndb.DateTimeProperty() class FixResult(ndb.Model): """Fix results.""" # The commit hash. - commit = ndb.StringProperty(default='') + commit: str = ndb.StringProperty(default='') # Vulnerability summary. - summary = ndb.TextProperty() + summary: str = ndb.TextProperty() # Vulnerability details. - details = ndb.TextProperty() + details: str = ndb.TextProperty() # Error (if any). - error = ndb.StringProperty() + error: str = ndb.StringProperty() # OSS-Fuzz issue ID. - issue_id = ndb.StringProperty() + issue_id: str = ndb.StringProperty() # Project for the bug. - project = ndb.StringProperty() + project: str = ndb.StringProperty() # Package ecosystem for the project. - ecosystem = ndb.StringProperty() + ecosystem: str = ndb.StringProperty() # Repo URL. - repo_url = ndb.StringProperty() + repo_url: str = ndb.StringProperty() # Severity of the bug. - severity = ndb.StringProperty(validator=_check_valid_severity) + severity: str = ndb.StringProperty(validator=_check_valid_severity) # Reference URLs. - reference_urls = ndb.StringProperty(repeated=True) + reference_urls: list[str] = ndb.StringProperty(repeated=True) # Source timestamp. - timestamp = ndb.DateTimeProperty() + timestamp: datetime = ndb.DateTimeProperty() class AffectedEvent(ndb.Model): """Affected event.""" - type = ndb.StringProperty(validator=_check_valid_event_type) - value = ndb.StringProperty() + type: str = ndb.StringProperty(validator=_check_valid_event_type) + value: str = ndb.StringProperty() class AffectedRange2(ndb.Model): """Affected range.""" # Type of range. - type = ndb.StringProperty(validator=_check_valid_range_type) + type: str = ndb.StringProperty(validator=_check_valid_range_type) # Repo URL. - repo_url = ndb.StringProperty() + repo_url: str = ndb.StringProperty() # Events. - events = ndb.LocalStructuredProperty(AffectedEvent, repeated=True) + events: list[AffectedEvent] = ndb.LocalStructuredProperty( + AffectedEvent, repeated=True) class SourceOfTruth(enum.IntEnum): @@ -206,38 +209,40 @@ class SourceOfTruth(enum.IntEnum): class Package(ndb.Model): """Package.""" - ecosystem = ndb.StringProperty() - name = ndb.StringProperty() - purl = ndb.StringProperty() + ecosystem: str = ndb.StringProperty() + name: str = ndb.StringProperty() + purl: str = ndb.StringProperty() class Severity(ndb.Model): """Severity.""" - type = ndb.StringProperty() - score = ndb.StringProperty() + type: str = ndb.StringProperty() + score: str = ndb.StringProperty() class AffectedPackage(ndb.Model): """Affected packages.""" # The affected package identifier. - package = ndb.StructuredProperty(Package) + package: Package = ndb.StructuredProperty(Package) # The list of affected ranges. - ranges = ndb.LocalStructuredProperty(AffectedRange2, repeated=True) + ranges: list[AffectedRange2] = ndb.LocalStructuredProperty( + AffectedRange2, repeated=True) # The list of explicit affected versions. - versions = ndb.TextProperty(repeated=True) + versions: list[str] = ndb.TextProperty(repeated=True) # Database specific metadata. - database_specific = ndb.JsonProperty() + database_specific: dict = ndb.JsonProperty() # Ecosystem specific metadata. - ecosystem_specific = ndb.JsonProperty() + ecosystem_specific: dict = ndb.JsonProperty() # Severity of the bug. - severities = ndb.LocalStructuredProperty(Severity, repeated=True) + severities: list[Severity] = ndb.LocalStructuredProperty( + Severity, repeated=True) class Credit(ndb.Model): """Credits.""" - name = ndb.StringProperty() - contact = ndb.StringProperty(repeated=True) - type = ndb.StringProperty() + name: str = ndb.StringProperty() + contact: list[str] = ndb.StringProperty(repeated=True) + type: str = ndb.StringProperty() class Bug(ndb.Model): @@ -248,70 +253,72 @@ class Bug(ndb.Model): # Display ID as used by the source database. The full qualified database that # OSV tracks this as may be different. - db_id = ndb.StringProperty() + db_id: str = ndb.StringProperty() # Other IDs this bug is known as. - aliases = ndb.StringProperty(repeated=True) + aliases: list[str] = ndb.StringProperty(repeated=True) # Related IDs. - related = ndb.StringProperty(repeated=True) + related: list[str] = ndb.StringProperty(repeated=True) # Status of the bug. - status = ndb.IntegerProperty() + status: int = ndb.IntegerProperty() # Timestamp when Bug was allocated. - timestamp = ndb.DateTimeProperty() + timestamp: datetime = ndb.DateTimeProperty() # When the entry was last edited. - last_modified = ndb.DateTimeProperty() + last_modified: datetime = ndb.DateTimeProperty() # Last modified field of the original imported file - import_last_modified = ndb.DateTimeProperty() + import_last_modified: datetime = ndb.DateTimeProperty() # When the entry was withdrawn. - withdrawn = ndb.DateTimeProperty() + withdrawn: datetime = ndb.DateTimeProperty() # The source identifier. # For OSS-Fuzz, this oss-fuzz:. # For others this is :. - source_id = ndb.StringProperty() + source_id: str = ndb.StringProperty() # The main fixed commit (from bisection). - fixed = ndb.StringProperty(default='') + fixed: str = ndb.StringProperty(default='') # The main regressing commit (from bisection). - regressed = ndb.StringProperty(default='') + regressed: str = ndb.StringProperty(default='') # List of affected versions. - affected = ndb.TextProperty(repeated=True) + affected: list[str] = ndb.TextProperty(repeated=True) # List of normalized versions indexed for fuzzy matching. - affected_fuzzy = ndb.StringProperty(repeated=True) + affected_fuzzy: list[str] = ndb.StringProperty(repeated=True) # OSS-Fuzz issue ID. - issue_id = ndb.StringProperty() + issue_id: str = ndb.StringProperty() # Package URL for this package. - purl = ndb.StringProperty(repeated=True) + purl: list[str] = ndb.StringProperty(repeated=True) # Project/package name for the bug. - project = ndb.StringProperty(repeated=True) + project: list[str] = ndb.StringProperty(repeated=True) # Package ecosystem for the project. - ecosystem = ndb.StringProperty(repeated=True) + ecosystem: list[str] = ndb.StringProperty(repeated=True) # Summary for the bug. - summary = ndb.TextProperty() + summary: str = ndb.TextProperty() # Vulnerability details. - details = ndb.TextProperty() + details: str = ndb.TextProperty() # Severity of the bug. - severities = ndb.LocalStructuredProperty(Severity, repeated=True) + severities: list[Severity] = ndb.LocalStructuredProperty( + Severity, repeated=True) # Credits for the bug. - credits = ndb.LocalStructuredProperty(Credit, repeated=True) + credits: list[Credit] = ndb.LocalStructuredProperty(Credit, repeated=True) # Whether or not the bug is public (OSS-Fuzz only). - public = ndb.BooleanProperty() + public: bool = ndb.BooleanProperty() # Reference URL types (dict of url -> type). - reference_url_types = ndb.JsonProperty() + reference_url_types: dict = ndb.JsonProperty() # Search indices (auto-populated) - search_indices = ndb.StringProperty(repeated=True) + search_indices: list[str] = ndb.StringProperty(repeated=True) # Whether or not the bug has any affected versions (auto-populated). - has_affected = ndb.BooleanProperty() + has_affected: bool = ndb.BooleanProperty() # Source of truth for this Bug. - source_of_truth = ndb.IntegerProperty(default=SourceOfTruth.INTERNAL) + source_of_truth: SourceOfTruth = ndb.IntegerProperty( + default=SourceOfTruth.INTERNAL) # Whether the bug is fixed (indexed for querying). - is_fixed = ndb.BooleanProperty() + is_fixed: bool = ndb.BooleanProperty() # Database specific. - database_specific = ndb.JsonProperty() + database_specific: dict = ndb.JsonProperty() # Normalized SEMVER fixed indexes for querying. - semver_fixed_indexes = ndb.StringProperty(repeated=True) + semver_fixed_indexes: list[str] = ndb.StringProperty(repeated=True) # Affected packages and versions. - affected_packages = ndb.LocalStructuredProperty( + affected_packages: list[AffectedPackage] = ndb.LocalStructuredProperty( AffectedPackage, repeated=True) # The source of this Bug. - source = ndb.StringProperty() + source: str = ndb.StringProperty() def id(self): """Get the bug ID.""" @@ -335,7 +342,7 @@ def repo_url(self): return None @classmethod - def get_by_id(cls, vuln_id, *args, **kwargs): + def get_by_id(cls, vuln_id, *args, **kwargs) -> Self | None: """Overridden get_by_id to handle OSV allocated IDs.""" result = cls.query(cls.db_id == vuln_id).get() if result: @@ -760,41 +767,41 @@ def to_vulnerability_async(self, include_source=False): class RepoIndex(ndb.Model): """RepoIndex entry""" # The dependency name - name = ndb.StringProperty() + name: str = ndb.StringProperty() # The base cpe without the version - base_cpe = ndb.StringProperty() + base_cpe: str = ndb.StringProperty() # The repository commit - commit = ndb.BlobProperty() + commit: bytes = ndb.BlobProperty() # The source address - repo_addr = ndb.StringProperty() + repo_addr: str = ndb.StringProperty() # The scanned file extensions - file_exts = ndb.StringProperty(repeated=True) + file_exts: list[str] = ndb.StringProperty(repeated=True) # The hash algorithm used - file_hash_type = ndb.StringProperty() + file_hash_type: str = ndb.StringProperty() # The repository type - repo_type = ndb.StringProperty() + repo_type: str = ndb.StringProperty() # A bitmap of which buckets are empty - empty_bucket_bitmap = ndb.BlobProperty() + empty_bucket_bitmap: bytes = ndb.BlobProperty() # Number of files in this repo - file_count = ndb.IntegerProperty() + file_count: int = ndb.IntegerProperty() # Tag name of the source - tag = ndb.StringProperty() + tag: str = ndb.StringProperty() class FileResult(ndb.Model): """FileResult entry containing the path and hash""" # The hash value of the file - hash = ndb.BlobProperty(indexed=True) + hash: bytes = ndb.BlobProperty(indexed=True) # The file path - path = ndb.TextProperty() + path: str = ndb.TextProperty() class RepoIndexBucket(ndb.Model): """RepoIndexResult entries containing the actual hash values""" # The file results per file - node_hash = ndb.BlobProperty(indexed=True) + node_hash: bytes = ndb.BlobProperty(indexed=True) # number of files this hash represents - files_contained = ndb.IntegerProperty() + files_contained: int = ndb.IntegerProperty() class SourceRepositoryType(enum.IntEnum): @@ -807,48 +814,48 @@ class SourceRepositoryType(enum.IntEnum): class SourceRepository(ndb.Model): """Source repository.""" # The SourceRepositoryType of the repository. - type = ndb.IntegerProperty() + type: int = ndb.IntegerProperty() # The name of the source. - name = ndb.StringProperty() + name: str = ndb.StringProperty() # The repo URL for the source for SourceRepositoryType.GIT. - repo_url = ndb.StringProperty() + repo_url: str = ndb.StringProperty() # The username to use for SSH auth for SourceRepositoryType.GIT. - repo_username = ndb.StringProperty() + repo_username: str = ndb.StringProperty() # Optional branch for repo for SourceRepositoryType.GIT. - repo_branch = ndb.StringProperty() + repo_branch: str = ndb.StringProperty() # The API endpoint for SourceRepositoryType.REST_ENDPOINT. - rest_api_url = ndb.StringProperty() + rest_api_url: str = ndb.StringProperty() # Bucket name for SourceRepositoryType.BUCKET. - bucket = ndb.StringProperty() + bucket: str = ndb.StringProperty() # Vulnerability data not under this path is ignored by the importer. - directory_path = ndb.StringProperty() + directory_path: str = ndb.StringProperty() # Last synced hash for SourceRepositoryType.GIT. - last_synced_hash = ndb.StringProperty() + last_synced_hash: str = ndb.StringProperty() # Last date recurring updates were requested. - last_update_date = ndb.DateTimeProperty() + last_update_date: datetime = ndb.DateTimeProperty() # Patterns of files to exclude (regex). - ignore_patterns = ndb.StringProperty(repeated=True) + ignore_patterns: list[str] = ndb.StringProperty(repeated=True) # Whether this repository is editable. - editable = ndb.BooleanProperty(default=False) + editable: bool = ndb.BooleanProperty(default=False) # Default extension. - extension = ndb.StringProperty(default='.yaml') + extension: str = ndb.StringProperty(default='.yaml') # Key path within each file to store the vulnerability. - key_path = ndb.StringProperty() + key_path: str = ndb.StringProperty() # If true, don't analyze any Git ranges. - ignore_git = ndb.BooleanProperty(default=False) + ignore_git: bool = ndb.BooleanProperty(default=False) # Whether to detect cherypicks or not (slow for large repos). - detect_cherrypicks = ndb.BooleanProperty(default=True) + detect_cherrypicks: bool = ndb.BooleanProperty(default=True) # Whether to populate "affected[].versions" from Git ranges. - versions_from_repo = ndb.BooleanProperty(default=True) + versions_from_repo: bool = ndb.BooleanProperty(default=True) # Ignore last import time once (SourceRepositoryType.BUCKET). - ignore_last_import_time = ndb.BooleanProperty(default=False) + ignore_last_import_time: bool = ndb.BooleanProperty(default=False) # HTTP link prefix to individual OSV source records. - link = ndb.StringProperty() + link: str = ndb.StringProperty() # HTTP link prefix to individual vulnerability records for humans. - human_link = ndb.StringProperty() + human_link: str = ndb.StringProperty() # DB prefix, if the database allocates its own. # https://ossf.github.io/osv-schema/#id-modified-fields - db_prefix = ndb.StringProperty(repeated=True) + db_prefix: list[str] = ndb.StringProperty(repeated=True) def ignore_file(self, file_path): """Return whether or not we should be ignoring a file.""" @@ -870,18 +877,18 @@ def _pre_put_hook(self): # pylint: disable=arguments-differ class AliasGroup(ndb.Model): """Alias group.""" - bug_ids = ndb.StringProperty(repeated=True) - last_modified = ndb.DateTimeProperty() + bug_ids: list[str] = ndb.StringProperty(repeated=True) + last_modified: datetime = ndb.DateTimeProperty() class AliasAllowListEntry(ndb.Model): """Alias group allow list entry.""" - bug_id = ndb.StringProperty() + bug_id: str = ndb.StringProperty() class AliasDenyListEntry(ndb.Model): """Alias group deny list entry.""" - bug_id = ndb.StringProperty() + bug_id: str = ndb.StringProperty() def get_source_repository(source_name): @@ -889,7 +896,7 @@ def get_source_repository(source_name): return SourceRepository.get_by_id(source_name) -def sorted_events(ecosystem, range_type, events): +def sorted_events(ecosystem, range_type, events) -> list[AffectedEvent]: """Sort events.""" if range_type == 'GIT': # No need to sort. @@ -921,14 +928,14 @@ def sorted_events(ecosystem, range_type, events): @ndb.tasklet -def get_aliases_async(bug_id): +def get_aliases_async(bug_id) -> ndb.Future: """Gets aliases asynchronously.""" alias_group = yield AliasGroup.query(AliasGroup.bug_ids == bug_id).get_async() return alias_group @ndb.tasklet -def get_related_async(bug_id): +def get_related_async(bug_id) -> ndb.Future: """Gets related bugs asynchronously.""" related_bugs = yield Bug.query(Bug.related == bug_id).fetch_async() related_bug_ids = [bug.db_id for bug in related_bugs] diff --git a/osv/semver_index.py b/osv/semver_index.py index 369962995d8..b8a4f5040ba 100644 --- a/osv/semver_index.py +++ b/osv/semver_index.py @@ -80,7 +80,7 @@ def _coerce_suffix(suffix): return pre + build + match.group(3) -def coerce(version): +def coerce(version: str): """Coerce a potentially invalid semver into valid semver.""" version = _strip_leading_v(version) version_pattern = re.compile(r'^(\d+)(\.\d+)?(\.\d+)?(.*)$') @@ -99,7 +99,7 @@ def is_valid(version): return semver.Version.is_valid(_strip_leading_v(version)) -def parse(version): +def parse(version: str): """Parse a SemVer.""" return semver.Version.parse(coerce(version)) diff --git a/osv/vulnerability_pb2.py b/osv/vulnerability_pb2.py index cfd062cc9ac..9916ad35fe8 100644 --- a/osv/vulnerability_pb2.py +++ b/osv/vulnerability_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: osv/vulnerability.proto -# Protobuf Python Version: 4.25.0 +# Protobuf Python Version: 4.25.1 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool diff --git a/osv/vulnerability_pb2.pyi b/osv/vulnerability_pb2.pyi new file mode 100644 index 00000000000..e5faa50861a --- /dev/null +++ b/osv/vulnerability_pb2.pyi @@ -0,0 +1,520 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +Copyright 2021 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 builtins +import collections.abc +import google.protobuf.descriptor +import google.protobuf.internal.containers +import google.protobuf.internal.enum_type_wrapper +import google.protobuf.message +import google.protobuf.struct_pb2 +import google.protobuf.timestamp_pb2 +import sys +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class Commit(google.protobuf.message.Message): + """Commit reference. + + In some rare cases, this may refer to a small range of commits rather than an + exact commit (to accomodate for automated systems). In such cases, the + semantics are as follows: + + - If this is referring to a commit which introduces a vulnerability, then + *any* commits in the range is assumed to cause the vulnerability. + + - If this is referring to a commit which fixes a vulnerability, then *all* + commits in the range is assumed to cause the vulnerability. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _RepoType: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _RepoTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Commit._RepoType.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + UNSPECIFIED: Commit._RepoType.ValueType # 0 + GIT: Commit._RepoType.ValueType # 1 + + class RepoType(_RepoType, metaclass=_RepoTypeEnumTypeWrapper): + """The repository type.""" + + UNSPECIFIED: Commit.RepoType.ValueType # 0 + GIT: Commit.RepoType.ValueType # 1 + + REPO_TYPE_FIELD_NUMBER: builtins.int + REPO_URL_FIELD_NUMBER: builtins.int + COMMIT_FIELD_NUMBER: builtins.int + repo_type: global___Commit.RepoType.ValueType + """Required. The type of the repo.""" + repo_url: builtins.str + """Required. The publicly accessible URL of the repo that can be directly + passed to clone commands. + """ + commit: builtins.str + """Required. The commit identifier (e.g. git SHA). In some cases where the + exact commit fails to be determined by automation, this may be a small + range in the form "A:B" which means the commit range from A (exclusive) to + B (inclusive). + """ + def __init__( + self, + *, + repo_type: global___Commit.RepoType.ValueType = ..., + repo_url: builtins.str = ..., + commit: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["commit", b"commit", "repo_type", b"repo_type", "repo_url", b"repo_url"]) -> None: ... + +global___Commit = Commit + +@typing.final +class Package(google.protobuf.message.Message): + """Package information and version.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NAME_FIELD_NUMBER: builtins.int + ECOSYSTEM_FIELD_NUMBER: builtins.int + PURL_FIELD_NUMBER: builtins.int + name: builtins.str + """Required. Name of the package. Should match the name used in the package + ecosystem (e.g. the npm package name). For C/C++ projects integrated in + OSS-Fuzz, this is the name used for the integration. + """ + ecosystem: builtins.str + """Required. The ecosystem for this package. + For the complete list of valid ecosystem names, see + . + """ + purl: builtins.str + """Optional. The package URL for this package.""" + def __init__( + self, + *, + name: builtins.str = ..., + ecosystem: builtins.str = ..., + purl: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["ecosystem", b"ecosystem", "name", b"name", "purl", b"purl"]) -> None: ... + +global___Package = Package + +@typing.final +class Event(google.protobuf.message.Message): + """Version events.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + INTRODUCED_FIELD_NUMBER: builtins.int + FIXED_FIELD_NUMBER: builtins.int + LIMIT_FIELD_NUMBER: builtins.int + LAST_AFFECTED_FIELD_NUMBER: builtins.int + introduced: builtins.str + """The earliest version/commit where this vulnerability + was introduced in. + """ + fixed: builtins.str + """The version/commit that this vulnerability was fixed in.""" + limit: builtins.str + """The limit to apply to the range.""" + last_affected: builtins.str + """The last affected version.""" + def __init__( + self, + *, + introduced: builtins.str = ..., + fixed: builtins.str = ..., + limit: builtins.str = ..., + last_affected: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["fixed", b"fixed", "introduced", b"introduced", "last_affected", b"last_affected", "limit", b"limit"]) -> None: ... + +global___Event = Event + +@typing.final +class Range(google.protobuf.message.Message): + """Affected ranges.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Type: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _TypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Range._Type.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + UNSPECIFIED: Range._Type.ValueType # 0 + GIT: Range._Type.ValueType # 1 + SEMVER: Range._Type.ValueType # 2 + ECOSYSTEM: Range._Type.ValueType # 3 + + class Type(_Type, metaclass=_TypeEnumTypeWrapper): + """Type of the version information.""" + + UNSPECIFIED: Range.Type.ValueType # 0 + GIT: Range.Type.ValueType # 1 + SEMVER: Range.Type.ValueType # 2 + ECOSYSTEM: Range.Type.ValueType # 3 + + TYPE_FIELD_NUMBER: builtins.int + REPO_FIELD_NUMBER: builtins.int + EVENTS_FIELD_NUMBER: builtins.int + type: global___Range.Type.ValueType + """Required. The type of version information.""" + repo: builtins.str + """Required if type is GIT. The publicly accessible URL of the repo that can + be directly passed to clone commands. + """ + @property + def events(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Event]: + """Required. Version event information.""" + + def __init__( + self, + *, + type: global___Range.Type.ValueType = ..., + repo: builtins.str = ..., + events: collections.abc.Iterable[global___Event] | None = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["events", b"events", "repo", b"repo", "type", b"type"]) -> None: ... + +global___Range = Range + +@typing.final +class Affected(google.protobuf.message.Message): + """Affected versions and commits.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + PACKAGE_FIELD_NUMBER: builtins.int + RANGES_FIELD_NUMBER: builtins.int + VERSIONS_FIELD_NUMBER: builtins.int + ECOSYSTEM_SPECIFIC_FIELD_NUMBER: builtins.int + DATABASE_SPECIFIC_FIELD_NUMBER: builtins.int + SEVERITY_FIELD_NUMBER: builtins.int + @property + def package(self) -> global___Package: + """Optional. Package information.""" + + @property + def ranges(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Range]: + """Required. Range information.""" + + @property + def versions(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """Optional. List of affected versions.""" + + @property + def ecosystem_specific(self) -> google.protobuf.struct_pb2.Struct: + """Optional. JSON object holding additional information about the + vulnerability as defined by the ecosystem for which the record applies. + """ + + @property + def database_specific(self) -> google.protobuf.struct_pb2.Struct: + """Optional. JSON object holding additional information about the + vulnerability as defined by the database for which the record applies. + """ + + @property + def severity(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Severity]: + """Optional. Severity of the vulnerability for this package.""" + + def __init__( + self, + *, + package: global___Package | None = ..., + ranges: collections.abc.Iterable[global___Range] | None = ..., + versions: collections.abc.Iterable[builtins.str] | None = ..., + ecosystem_specific: google.protobuf.struct_pb2.Struct | None = ..., + database_specific: google.protobuf.struct_pb2.Struct | None = ..., + severity: collections.abc.Iterable[global___Severity] | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["database_specific", b"database_specific", "ecosystem_specific", b"ecosystem_specific", "package", b"package"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["database_specific", b"database_specific", "ecosystem_specific", b"ecosystem_specific", "package", b"package", "ranges", b"ranges", "severity", b"severity", "versions", b"versions"]) -> None: ... + +global___Affected = Affected + +@typing.final +class Severity(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Type: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _TypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Severity._Type.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + UNSPECIFIED: Severity._Type.ValueType # 0 + CVSS_V3: Severity._Type.ValueType # 1 + CVSS_V2: Severity._Type.ValueType # 2 + CVSS_V4: Severity._Type.ValueType # 3 + + class Type(_Type, metaclass=_TypeEnumTypeWrapper): + """Type of the severity.""" + + UNSPECIFIED: Severity.Type.ValueType # 0 + CVSS_V3: Severity.Type.ValueType # 1 + CVSS_V2: Severity.Type.ValueType # 2 + CVSS_V4: Severity.Type.ValueType # 3 + + TYPE_FIELD_NUMBER: builtins.int + SCORE_FIELD_NUMBER: builtins.int + type: global___Severity.Type.ValueType + """The type of this severity entry.""" + score: builtins.str + """The quantitative score.""" + def __init__( + self, + *, + type: global___Severity.Type.ValueType = ..., + score: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["score", b"score", "type", b"type"]) -> None: ... + +global___Severity = Severity + +@typing.final +class Credit(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Type: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _TypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Credit._Type.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + UNSPECIFIED: Credit._Type.ValueType # 0 + OTHER: Credit._Type.ValueType # 1 + FINDER: Credit._Type.ValueType # 2 + REPORTER: Credit._Type.ValueType # 3 + ANALYST: Credit._Type.ValueType # 4 + COORDINATOR: Credit._Type.ValueType # 5 + REMEDIATION_DEVELOPER: Credit._Type.ValueType # 6 + REMEDIATION_REVIEWER: Credit._Type.ValueType # 7 + REMEDIATION_VERIFIER: Credit._Type.ValueType # 8 + TOOL: Credit._Type.ValueType # 9 + SPONSOR: Credit._Type.ValueType # 10 + + class Type(_Type, metaclass=_TypeEnumTypeWrapper): ... + UNSPECIFIED: Credit.Type.ValueType # 0 + OTHER: Credit.Type.ValueType # 1 + FINDER: Credit.Type.ValueType # 2 + REPORTER: Credit.Type.ValueType # 3 + ANALYST: Credit.Type.ValueType # 4 + COORDINATOR: Credit.Type.ValueType # 5 + REMEDIATION_DEVELOPER: Credit.Type.ValueType # 6 + REMEDIATION_REVIEWER: Credit.Type.ValueType # 7 + REMEDIATION_VERIFIER: Credit.Type.ValueType # 8 + TOOL: Credit.Type.ValueType # 9 + SPONSOR: Credit.Type.ValueType # 10 + + NAME_FIELD_NUMBER: builtins.int + CONTACT_FIELD_NUMBER: builtins.int + TYPE_FIELD_NUMBER: builtins.int + name: builtins.str + """The name to give credit to.""" + type: global___Credit.Type.ValueType + """Optional. The type or role of the individual or entity being credited.""" + @property + def contact(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """Contact methods (URLs).""" + + def __init__( + self, + *, + name: builtins.str = ..., + contact: collections.abc.Iterable[builtins.str] | None = ..., + type: global___Credit.Type.ValueType = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["contact", b"contact", "name", b"name", "type", b"type"]) -> None: ... + +global___Credit = Credit + +@typing.final +class Reference(google.protobuf.message.Message): + """Reference URL.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Type: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _TypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Reference._Type.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + NONE: Reference._Type.ValueType # 0 + """Next ID = 11.""" + ADVISORY: Reference._Type.ValueType # 2 + ARTICLE: Reference._Type.ValueType # 6 + DETECTION: Reference._Type.ValueType # 9 + DISCUSSION: Reference._Type.ValueType # 8 + EVIDENCE: Reference._Type.ValueType # 7 + FIX: Reference._Type.ValueType # 4 + INTRODUCED: Reference._Type.ValueType # 10 + PACKAGE: Reference._Type.ValueType # 5 + REPORT: Reference._Type.ValueType # 3 + WEB: Reference._Type.ValueType # 1 + + class Type(_Type, metaclass=_TypeEnumTypeWrapper): ... + NONE: Reference.Type.ValueType # 0 + """Next ID = 11.""" + ADVISORY: Reference.Type.ValueType # 2 + ARTICLE: Reference.Type.ValueType # 6 + DETECTION: Reference.Type.ValueType # 9 + DISCUSSION: Reference.Type.ValueType # 8 + EVIDENCE: Reference.Type.ValueType # 7 + FIX: Reference.Type.ValueType # 4 + INTRODUCED: Reference.Type.ValueType # 10 + PACKAGE: Reference.Type.ValueType # 5 + REPORT: Reference.Type.ValueType # 3 + WEB: Reference.Type.ValueType # 1 + + TYPE_FIELD_NUMBER: builtins.int + URL_FIELD_NUMBER: builtins.int + type: global___Reference.Type.ValueType + """Required. The type of the reference.""" + url: builtins.str + """Required. The URL.""" + def __init__( + self, + *, + type: global___Reference.Type.ValueType = ..., + url: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["type", b"type", "url", b"url"]) -> None: ... + +global___Reference = Reference + +@typing.final +class Vulnerability(google.protobuf.message.Message): + """A vulnerability entry. + The protobuf representation is *NOT* stable and only used for implementing + the JSON based API. + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + SCHEMA_VERSION_FIELD_NUMBER: builtins.int + ID_FIELD_NUMBER: builtins.int + PUBLISHED_FIELD_NUMBER: builtins.int + MODIFIED_FIELD_NUMBER: builtins.int + WITHDRAWN_FIELD_NUMBER: builtins.int + ALIASES_FIELD_NUMBER: builtins.int + RELATED_FIELD_NUMBER: builtins.int + SUMMARY_FIELD_NUMBER: builtins.int + DETAILS_FIELD_NUMBER: builtins.int + AFFECTED_FIELD_NUMBER: builtins.int + REFERENCES_FIELD_NUMBER: builtins.int + DATABASE_SPECIFIC_FIELD_NUMBER: builtins.int + SEVERITY_FIELD_NUMBER: builtins.int + CREDITS_FIELD_NUMBER: builtins.int + schema_version: builtins.str + """The OSV schema version.""" + id: builtins.str + """The `id` field is a unique identifier for the vulnerability entry. It is a + string of the format `-`, where `DB` names the database and + `ENTRYID` is in the format used by the database. For example: + “OSV-2020-111”, “CVE-2021-3114”, or “GHSA-vp9c-fpxx-744v”. + """ + summary: builtins.str + """Required. One line human readable summary for the vulnerability. It is + recommended to keep this under 120 characters. + """ + details: builtins.str + """Required. Any additional human readable details for the vulnerability.""" + @property + def published(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The RFC3339 timestamp indicating when this entry was published.""" + + @property + def modified(self) -> google.protobuf.timestamp_pb2.Timestamp: + """The RFC3339 timestamp indicating when this entry was last modified.""" + + @property + def withdrawn(self) -> google.protobuf.timestamp_pb2.Timestamp: + """Optional. The RFC3339 timestamp indicating when this entry is considered to + be withdrawn. + """ + + @property + def aliases(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """Optional. IDs for the same vulnerability in other databases.""" + + @property + def related(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: + """Optional. List of IDs of closely related vulnerabilities, such as the same + problem in alternate ecosystems. + """ + + @property + def affected(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Affected]: + """Required. Affected commit ranges and versions.""" + + @property + def references(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Reference]: + """Optional. URLs to more information/advisories (including the + scheme e.g "https://"). + """ + + @property + def database_specific(self) -> google.protobuf.struct_pb2.Struct: + """Optional. JSON object holding additional information about the + vulnerability as defined by the database for which the record applies. + """ + + @property + def severity(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Severity]: + """Optional. Severity of the vulnerability.""" + + @property + def credits(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Credit]: + """Optional. Credits for the vulnerability.""" + + def __init__( + self, + *, + schema_version: builtins.str = ..., + id: builtins.str = ..., + published: google.protobuf.timestamp_pb2.Timestamp | None = ..., + modified: google.protobuf.timestamp_pb2.Timestamp | None = ..., + withdrawn: google.protobuf.timestamp_pb2.Timestamp | None = ..., + aliases: collections.abc.Iterable[builtins.str] | None = ..., + related: collections.abc.Iterable[builtins.str] | None = ..., + summary: builtins.str = ..., + details: builtins.str = ..., + affected: collections.abc.Iterable[global___Affected] | None = ..., + references: collections.abc.Iterable[global___Reference] | None = ..., + database_specific: google.protobuf.struct_pb2.Struct | None = ..., + severity: collections.abc.Iterable[global___Severity] | None = ..., + credits: collections.abc.Iterable[global___Credit] | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["database_specific", b"database_specific", "modified", b"modified", "published", b"published", "withdrawn", b"withdrawn"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["affected", b"affected", "aliases", b"aliases", "credits", b"credits", "database_specific", b"database_specific", "details", b"details", "id", b"id", "modified", b"modified", "published", b"published", "references", b"references", "related", b"related", "schema_version", b"schema_version", "severity", b"severity", "summary", b"summary", "withdrawn", b"withdrawn"]) -> None: ... + +global___Vulnerability = Vulnerability diff --git a/poetry.lock b/poetry.lock index 0362ed43d10..8e53e49c4e0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "astroid" @@ -65,78 +65,78 @@ files = [ [[package]] name = "cffi" -version = "1.17.0" +version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" files = [ - {file = "cffi-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb"}, - {file = "cffi-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f"}, - {file = "cffi-1.17.0-cp310-cp310-win32.whl", hash = "sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc"}, - {file = "cffi-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb"}, - {file = "cffi-1.17.0-cp311-cp311-win32.whl", hash = "sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9"}, - {file = "cffi-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885"}, - {file = "cffi-1.17.0-cp312-cp312-win32.whl", hash = "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492"}, - {file = "cffi-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4"}, - {file = "cffi-1.17.0-cp313-cp313-win32.whl", hash = "sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a"}, - {file = "cffi-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7"}, - {file = "cffi-1.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c"}, - {file = "cffi-1.17.0-cp38-cp38-win32.whl", hash = "sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499"}, - {file = "cffi-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4"}, - {file = "cffi-1.17.0-cp39-cp39-win32.whl", hash = "sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb"}, - {file = "cffi-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29"}, - {file = "cffi-1.17.0.tar.gz", hash = "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, ] [package.dependencies] @@ -782,6 +782,21 @@ files = [ {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] +[[package]] +name = "mypy-protobuf" +version = "3.6.0" +description = "Generate mypy stub files from protobuf specs" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-protobuf-3.6.0.tar.gz", hash = "sha256:02f242eb3409f66889f2b1a3aa58356ec4d909cdd0f93115622e9e70366eca3c"}, + {file = "mypy_protobuf-3.6.0-py3-none-any.whl", hash = "sha256:56176e4d569070e7350ea620262478b49b7efceba4103d468448f1d21492fd6c"}, +] + +[package.dependencies] +protobuf = ">=4.25.3" +types-protobuf = ">=4.24" + [[package]] name = "opentelemetry-api" version = "1.27.0" @@ -813,19 +828,19 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" [[package]] name = "platformdirs" -version = "4.2.2" +version = "4.3.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, - {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, + {file = "platformdirs-4.3.2-py3-none-any.whl", hash = "sha256:eb1c8582560b34ed4ba105009a4badf7f6f85768b30126f351328507b2beb617"}, + {file = "platformdirs-4.3.2.tar.gz", hash = "sha256:9e5e27a08aa095dd127b9f2e764d74254f482fef22b0970773bfba79d091ab8c"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -type = ["mypy (>=1.8)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] [[package]] name = "proto-plus" @@ -1259,13 +1274,13 @@ files = [ [[package]] name = "setuptools" -version = "74.1.1" +version = "74.1.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-74.1.1-py3-none-any.whl", hash = "sha256:fc91b5f89e392ef5b77fe143b17e32f65d3024744fba66dc3afe07201684d766"}, - {file = "setuptools-74.1.1.tar.gz", hash = "sha256:2353af060c06388be1cecbf5953dcdb1f38362f87a2356c480b6b4d5fcfc8847"}, + {file = "setuptools-74.1.2-py3-none-any.whl", hash = "sha256:5f4c08aa4d3ebcb57a50c33b1b07e94315d7fc7230f7115e47fc99776c8ce308"}, + {file = "setuptools-74.1.2.tar.gz", hash = "sha256:95b40ed940a1c67eb70fc099094bd6e99c6ee7c23aa2306f4d2697ba7916f9c6"}, ] [package.extras] @@ -1299,6 +1314,17 @@ files = [ {file = "tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79"}, ] +[[package]] +name = "types-protobuf" +version = "5.27.0.20240907" +description = "Typing stubs for protobuf" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-protobuf-5.27.0.20240907.tar.gz", hash = "sha256:bb6f90f66b18d4d1c75667b6586334b0573a6fcee5eb0142a7348a765a7cbadc"}, + {file = "types_protobuf-5.27.0.20240907-py3-none-any.whl", hash = "sha256:5443270534cc8072909ef7ad9e1421ccff924ca658749a6396c0c43d64c32676"}, +] + [[package]] name = "urllib3" version = "2.2.2" @@ -1433,4 +1459,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "75de6400ddef55dacce3925c9f8d88b739b4100c80747279091a0d59174c4796" +content-hash = "4a08ff8078fad3a261e8e9e3be2f49aa7a3099d627dfcc5fdad40a5b48e89f11" diff --git a/pyproject.toml b/pyproject.toml index 8277ecf9fd2..e59f4293018 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,6 +28,12 @@ requests = "^2.32" yapf = "*" pylint = "*" grpcio-tools = "*" +mypy-protobuf = "^3.6.0" + +[tool.pyright] +executionEnvironments = [ + { root = "osv/models.py", reportAssignmentType = "none" }, +] [build-system] requires = ["poetry-core"] diff --git a/tools/api-performance-test/.gitignore b/tools/api-performance-test/.gitignore new file mode 100644 index 00000000000..a58010f74b5 --- /dev/null +++ b/tools/api-performance-test/.gitignore @@ -0,0 +1 @@ +all_bugs