diff --git a/Dockerfile b/Dockerfile index 70f273929ea96159f264cebddc7ca590dcee2f3a..203773a905d618598501c403ff355cdbacb96a6a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -166,6 +166,15 @@ RUN python3.12 -m venv /app/.venv \ && rm -rf /tmp/usdsearch-wheels \ && chown -R 1000:1000 /app/.venv +# hf-storage-api — see docker/Dockerfile.hf-space's own copy of this block +# for the full explanation (identical here; this variant serves the same +# corpus/storage backend, just with a different SigLIP2 backend). +COPY docker/hf-space/hf-storage-api/hf_storage_api /app/hf-storage-api/src/hf_storage_api +COPY docker/hf-space/hf-storage-api/generated /app/hf-storage-api/generated +RUN GRPCIO_VERSION=$(/app/.venv/bin/pip show grpcio | sed -n 's/^Version: //p') \ + && env -u PYTHONPATH /app/.venv/bin/pip install --no-cache-dir "grpcio-health-checking==${GRPCIO_VERSION}" \ + && chown -R 1000:1000 /app/hf-storage-api + COPY --from=opensearch-src --chown=1000:1000 /usr/share/opensearch /usr/share/opensearch RUN /usr/share/opensearch/bin/opensearch-plugin remove opensearch-performance-analyzer @@ -216,6 +225,14 @@ COPY docker/hf-space/nginx.conf.template /etc/nginx/hf-space.conf.template COPY services/explorer/dist /usr/share/nginx/explorer +# Explorer download stopgap — see docker/Dockerfile.hf-space's copy of this block. +ARG DOWNLOAD_ENABLED=false +RUN if [ "$DOWNLOAD_ENABLED" = "true" ]; then \ + f=$(grep -l 'ENABLE_DOWNLOADS:!' /usr/share/nginx/explorer/static/js/main.*.js) \ + && sed -i 's/ENABLE_DOWNLOADS:!1/ENABLE_DOWNLOADS:!0/' $f \ + && grep -q 'ENABLE_DOWNLOADS:!0' $f; \ + fi + COPY --chown=1000:1000 pipeline /app/hf-space-pipeline/pipeline ARG ARTIFACT_S3_URI @@ -238,7 +255,13 @@ ARG ES_NAME ARG S3_STORAGE_BUCKET_NAME ARG S3_STORAGE_REGION_NAME=us-west-2 ARG STORAGE_BACKEND_TYPE=s3 -ENV STORAGE_BACKEND_TYPE=${STORAGE_BACKEND_TYPE} \ +# DOWNLOAD_ENABLED / HF_TOKEN / STORAGE_API_* — see +# docker/Dockerfile.hf-space's own copies of these comments for the full +# explanation. +ARG DOWNLOAD_ENABLED=false +ENV HF_TOKEN= \ + DOWNLOAD_ENABLED=${DOWNLOAD_ENABLED} \ + STORAGE_BACKEND_TYPE=${STORAGE_BACKEND_TYPE} \ S3_STORAGE_BUCKET_NAME=${S3_STORAGE_BUCKET_NAME} \ S3_STORAGE_REGION_NAME=${S3_STORAGE_REGION_NAME} \ opensearch_host=http://localhost:9200 \ @@ -262,6 +285,10 @@ ENV STORAGE_BACKEND_TYPE=${STORAGE_BACKEND_TYPE} \ HYBRID_SEARCH_SCORING_CONFIG_VECTOR_FIELDS="{\"siglip2-embedding.embedding\":{\"enabled\":true,\"weight\":1,\"field_name\":\"siglip2-embedding.embedding\",\"dimension\":1536}}" \ USDSEARCH_URL_MAPPING_MODE=rules \ USDSEARCH_URL_MAPPING_RULES="[{\"internal\": \"hf://huggingface.co/datasets/nvidia/srp-staging-controlled/\", \"public\": \"https://huggingface.co/datasets/nvidia/srp-staging-controlled/blob/main/\"}]" \ + STORAGE_API_GRPC_ENDPOINT=localhost:50051 \ + STORAGE_API_SSL=false \ + STORAGE_API_IGNORE_FILE_FOLDER_API=true \ + STORAGE_API_THUMBNAIL_METADATA_FIELDS="[\"hf:thumbnail_url\"]" \ SIGLIP2_TRITON_SERVER_URL=localhost:8001 \ TRITON_SERVER_URL=localhost:8001 \ SIGLIP2_TRITON_SERVER_SSL=false \ diff --git a/docker/hf-space/hf-storage-api/SOURCE.txt b/docker/hf-space/hf-storage-api/SOURCE.txt new file mode 100644 index 0000000000000000000000000000000000000000..e8b81f75fe02dbf165fc66ddad57714cc1d54ead --- /dev/null +++ b/docker/hf-space/hf-storage-api/SOURCE.txt @@ -0,0 +1,6 @@ +# Generated by scripts/extract_hf_storage_api.sh — do not hand-edit. +source_image=nvcr.io/m3sujtetvf5w/usdsearch/hf-storage-api:71b7537 +regenerated_against_protobuf=6.33.6 +regenerated_against_grpcio_tools=1.80.0 +regenerated_from_constraints=docker/hf-space/wheels/constraints.txt +extracted_at=2026-09-29T13:00:16Z diff --git a/docker/hf-space/hf-storage-api/constraints-hf-storage-api.txt b/docker/hf-space/hf-storage-api/constraints-hf-storage-api.txt new file mode 100644 index 0000000000000000000000000000000000000000..e8e5bd76f8124882e86ec463d36a3868c74bca7c --- /dev/null +++ b/docker/hf-space/hf-storage-api/constraints-hf-storage-api.txt @@ -0,0 +1,19 @@ +annotated-types==0.8.0 +anyio==4.15.1 +certifi==2026.7.22 +grpcio==1.84.0 +grpcio-health-checking==1.84.0 +grpcio-tools==1.84.0 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.20 +packaging==26.3 +protobuf==7.36.2 +pydantic==2.13.5 +pydantic_core==2.46.5 +pydantic-settings==2.15.0 +python-dotenv==1.2.3 +PyYAML==6.0.3 +typing_extensions==4.16.0 +typing-inspection==0.4.4 diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/notifications/consumer/v1beta/event_consumer_pb2.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/notifications/consumer/v1beta/event_consumer_pb2.py new file mode 100644 index 0000000000000000000000000000000000000000..deb5a692ea0c786b3767ce4da64f9148e5011968 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/notifications/consumer/v1beta/event_consumer_pb2.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: nvidia/omniverse/notifications/consumer/v1beta/event_consumer.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'nvidia/omniverse/notifications/consumer/v1beta/event_consumer.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\nCnvidia/omniverse/notifications/consumer/v1beta/event_consumer.proto\x12.nvidia.omniverse.notifications.consumer.v1beta\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"e\n\x1c\x43onsumeDurableEventsResponse\x12\x45\n\x06\x65vents\x18\x01 \x03(\x0b\x32\x35.nvidia.omniverse.notifications.consumer.v1beta.Event\"\x81\x01\n\x1f\x43onsumeNonDurableEventsResponse\x12\x45\n\x06\x65vents\x18\x01 \x03(\x0b\x32\x35.nvidia.omniverse.notifications.consumer.v1beta.Event\x12\x17\n\x0freconnect_token\x18\x02 \x01(\t\"/\n\x1b\x43onsumeDurableEventsRequest\x12\x10\n\x08queue_id\x18\x01 \x01(\t\"\x83\x02\n\x1e\x43onsumeNonDurableEventsRequest\x12R\n\rfilter_groups\x18\x01 \x03(\x0b\x32;.nvidia.omniverse.notifications.consumer.v1beta.FilterGroup\x12\x1c\n\x0freconnect_token\x18\x02 \x01(\tH\x00\x88\x01\x01\x12[\n\x16previous_filter_groups\x18\x03 \x03(\x0b\x32;.nvidia.omniverse.notifications.consumer.v1beta.FilterGroupB\x12\n\x10_reconnect_token\"o\n\x19\x43reateDurableQueueRequest\x12R\n\rfilter_groups\x18\x01 \x03(\x0b\x32;.nvidia.omniverse.notifications.consumer.v1beta.FilterGroup\".\n\x1a\x43reateDurableQueueResponse\x12\x10\n\x08queue_id\x18\x01 \x01(\t\"-\n\x19\x44\x65leteDurableQueueRequest\x12\x10\n\x08queue_id\x18\x01 \x01(\t\"\xe1\x01\n\x19UpdateDurableQueueRequest\x12\x10\n\x08queue_id\x18\x01 \x01(\t\x12Z\n\x15\x63urrent_filter_groups\x18\x02 \x03(\x0b\x32;.nvidia.omniverse.notifications.consumer.v1beta.FilterGroup\x12V\n\x11new_filter_groups\x18\x03 \x03(\x0b\x32;.nvidia.omniverse.notifications.consumer.v1beta.FilterGroup\"\x1c\n\x1a\x44\x65leteDurableQueueResponse\"\x1c\n\x1aUpdateDurableQueueResponse\"\xc4\x01\n\x05\x45vent\x12\x12\n\nevent_type\x18\x01 \x01(\t\x12\x1a\n\x12principal_identity\x18\x02 \x01(\t\x12/\n\x0boccurred_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0cpublished_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12(\n\x07message\x18\x05 \x01(\x0b\x32\x17.google.protobuf.Struct\"r\n\x0b\x46ilterGroup\x12\x12\n\nevent_type\x18\x01 \x01(\t\x12O\n\x07\x66ilters\x18\x02 \x03(\x0b\x32>.nvidia.omniverse.notifications.consumer.v1beta.ResourceFilter\"\x8b\x02\n\x0eResourceFilter\x12^\n\x0b\x66ilter_type\x18\x01 \x01(\x0e\x32I.nvidia.omniverse.notifications.consumer.v1beta.ResourceFilter.FilterType\x12\x13\n\x0bresource_id\x18\x02 \x01(\t\"\x83\x01\n\nFilterType\x12\x1b\n\x17\x46ILTER_TYPE_UNSPECIFIED\x10\x00\x12\x12\n\x0e\x46ILTER_TYPE_EQ\x10\x01\x12 \n\x1c\x46ILTER_TYPE_STARTS_WITH_LAZY\x10\x02\x12\"\n\x1e\x46ILTER_TYPE_STARTS_WITH_GREEDY\x10\x03\x32\xa1\x07\n\x14\x45ventConsumerService\x12\xb5\x01\n\x14\x43onsumeDurableEvents\x12K.nvidia.omniverse.notifications.consumer.v1beta.ConsumeDurableEventsRequest\x1aL.nvidia.omniverse.notifications.consumer.v1beta.ConsumeDurableEventsResponse\"\x00\x30\x01\x12\xc0\x01\n\x17\x43onsumeNonDurableEvents\x12N.nvidia.omniverse.notifications.consumer.v1beta.ConsumeNonDurableEventsRequest\x1aO.nvidia.omniverse.notifications.consumer.v1beta.ConsumeNonDurableEventsResponse\"\x00(\x01\x30\x01\x12\xad\x01\n\x12\x43reateDurableQueue\x12I.nvidia.omniverse.notifications.consumer.v1beta.CreateDurableQueueRequest\x1aJ.nvidia.omniverse.notifications.consumer.v1beta.CreateDurableQueueResponse\"\x00\x12\xad\x01\n\x12\x44\x65leteDurableQueue\x12I.nvidia.omniverse.notifications.consumer.v1beta.DeleteDurableQueueRequest\x1aJ.nvidia.omniverse.notifications.consumer.v1beta.DeleteDurableQueueResponse\"\x00\x12\xad\x01\n\x12UpdateDurableQueue\x12I.nvidia.omniverse.notifications.consumer.v1beta.UpdateDurableQueueRequest\x1aJ.nvidia.omniverse.notifications.consumer.v1beta.UpdateDurableQueueResponse\"\x00\x42\x85\x01\n2com.nvidia.omniverse.notifications.consumer.v1betaB\x12\x45ventConsumerProtoP\x01Z9github.com/nvidia/omniverse/notifications/consumer/v1betab\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nvidia.omniverse.notifications.consumer.v1beta.event_consumer_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n2com.nvidia.omniverse.notifications.consumer.v1betaB\022EventConsumerProtoP\001Z9github.com/nvidia/omniverse/notifications/consumer/v1beta' + _globals['_CONSUMEDURABLEEVENTSRESPONSE']._serialized_start=182 + _globals['_CONSUMEDURABLEEVENTSRESPONSE']._serialized_end=283 + _globals['_CONSUMENONDURABLEEVENTSRESPONSE']._serialized_start=286 + _globals['_CONSUMENONDURABLEEVENTSRESPONSE']._serialized_end=415 + _globals['_CONSUMEDURABLEEVENTSREQUEST']._serialized_start=417 + _globals['_CONSUMEDURABLEEVENTSREQUEST']._serialized_end=464 + _globals['_CONSUMENONDURABLEEVENTSREQUEST']._serialized_start=467 + _globals['_CONSUMENONDURABLEEVENTSREQUEST']._serialized_end=726 + _globals['_CREATEDURABLEQUEUEREQUEST']._serialized_start=728 + _globals['_CREATEDURABLEQUEUEREQUEST']._serialized_end=839 + _globals['_CREATEDURABLEQUEUERESPONSE']._serialized_start=841 + _globals['_CREATEDURABLEQUEUERESPONSE']._serialized_end=887 + _globals['_DELETEDURABLEQUEUEREQUEST']._serialized_start=889 + _globals['_DELETEDURABLEQUEUEREQUEST']._serialized_end=934 + _globals['_UPDATEDURABLEQUEUEREQUEST']._serialized_start=937 + _globals['_UPDATEDURABLEQUEUEREQUEST']._serialized_end=1162 + _globals['_DELETEDURABLEQUEUERESPONSE']._serialized_start=1164 + _globals['_DELETEDURABLEQUEUERESPONSE']._serialized_end=1192 + _globals['_UPDATEDURABLEQUEUERESPONSE']._serialized_start=1194 + _globals['_UPDATEDURABLEQUEUERESPONSE']._serialized_end=1222 + _globals['_EVENT']._serialized_start=1225 + _globals['_EVENT']._serialized_end=1421 + _globals['_FILTERGROUP']._serialized_start=1423 + _globals['_FILTERGROUP']._serialized_end=1537 + _globals['_RESOURCEFILTER']._serialized_start=1540 + _globals['_RESOURCEFILTER']._serialized_end=1807 + _globals['_RESOURCEFILTER_FILTERTYPE']._serialized_start=1676 + _globals['_RESOURCEFILTER_FILTERTYPE']._serialized_end=1807 + _globals['_EVENTCONSUMERSERVICE']._serialized_start=1810 + _globals['_EVENTCONSUMERSERVICE']._serialized_end=2739 +# @@protoc_insertion_point(module_scope) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/notifications/consumer/v1beta/event_consumer_pb2.pyi b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/notifications/consumer/v1beta/event_consumer_pb2.pyi new file mode 100644 index 0000000000000000000000000000000000000000..61c54146480ca0eae4397dab1ad98bd21beab783 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/notifications/consumer/v1beta/event_consumer_pb2.pyi @@ -0,0 +1,118 @@ +import datetime + +from google.protobuf import struct_pb2 as _struct_pb2 +from google.protobuf import timestamp_pb2 as _timestamp_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class ConsumeDurableEventsResponse(_message.Message): + __slots__ = ("events",) + EVENTS_FIELD_NUMBER: _ClassVar[int] + events: _containers.RepeatedCompositeFieldContainer[Event] + def __init__(self, events: _Optional[_Iterable[_Union[Event, _Mapping]]] = ...) -> None: ... + +class ConsumeNonDurableEventsResponse(_message.Message): + __slots__ = ("events", "reconnect_token") + EVENTS_FIELD_NUMBER: _ClassVar[int] + RECONNECT_TOKEN_FIELD_NUMBER: _ClassVar[int] + events: _containers.RepeatedCompositeFieldContainer[Event] + reconnect_token: str + def __init__(self, events: _Optional[_Iterable[_Union[Event, _Mapping]]] = ..., reconnect_token: _Optional[str] = ...) -> None: ... + +class ConsumeDurableEventsRequest(_message.Message): + __slots__ = ("queue_id",) + QUEUE_ID_FIELD_NUMBER: _ClassVar[int] + queue_id: str + def __init__(self, queue_id: _Optional[str] = ...) -> None: ... + +class ConsumeNonDurableEventsRequest(_message.Message): + __slots__ = ("filter_groups", "reconnect_token", "previous_filter_groups") + FILTER_GROUPS_FIELD_NUMBER: _ClassVar[int] + RECONNECT_TOKEN_FIELD_NUMBER: _ClassVar[int] + PREVIOUS_FILTER_GROUPS_FIELD_NUMBER: _ClassVar[int] + filter_groups: _containers.RepeatedCompositeFieldContainer[FilterGroup] + reconnect_token: str + previous_filter_groups: _containers.RepeatedCompositeFieldContainer[FilterGroup] + def __init__(self, filter_groups: _Optional[_Iterable[_Union[FilterGroup, _Mapping]]] = ..., reconnect_token: _Optional[str] = ..., previous_filter_groups: _Optional[_Iterable[_Union[FilterGroup, _Mapping]]] = ...) -> None: ... + +class CreateDurableQueueRequest(_message.Message): + __slots__ = ("filter_groups",) + FILTER_GROUPS_FIELD_NUMBER: _ClassVar[int] + filter_groups: _containers.RepeatedCompositeFieldContainer[FilterGroup] + def __init__(self, filter_groups: _Optional[_Iterable[_Union[FilterGroup, _Mapping]]] = ...) -> None: ... + +class CreateDurableQueueResponse(_message.Message): + __slots__ = ("queue_id",) + QUEUE_ID_FIELD_NUMBER: _ClassVar[int] + queue_id: str + def __init__(self, queue_id: _Optional[str] = ...) -> None: ... + +class DeleteDurableQueueRequest(_message.Message): + __slots__ = ("queue_id",) + QUEUE_ID_FIELD_NUMBER: _ClassVar[int] + queue_id: str + def __init__(self, queue_id: _Optional[str] = ...) -> None: ... + +class UpdateDurableQueueRequest(_message.Message): + __slots__ = ("queue_id", "current_filter_groups", "new_filter_groups") + QUEUE_ID_FIELD_NUMBER: _ClassVar[int] + CURRENT_FILTER_GROUPS_FIELD_NUMBER: _ClassVar[int] + NEW_FILTER_GROUPS_FIELD_NUMBER: _ClassVar[int] + queue_id: str + current_filter_groups: _containers.RepeatedCompositeFieldContainer[FilterGroup] + new_filter_groups: _containers.RepeatedCompositeFieldContainer[FilterGroup] + def __init__(self, queue_id: _Optional[str] = ..., current_filter_groups: _Optional[_Iterable[_Union[FilterGroup, _Mapping]]] = ..., new_filter_groups: _Optional[_Iterable[_Union[FilterGroup, _Mapping]]] = ...) -> None: ... + +class DeleteDurableQueueResponse(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class UpdateDurableQueueResponse(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class Event(_message.Message): + __slots__ = ("event_type", "principal_identity", "occurred_at", "published_at", "message") + EVENT_TYPE_FIELD_NUMBER: _ClassVar[int] + PRINCIPAL_IDENTITY_FIELD_NUMBER: _ClassVar[int] + OCCURRED_AT_FIELD_NUMBER: _ClassVar[int] + PUBLISHED_AT_FIELD_NUMBER: _ClassVar[int] + MESSAGE_FIELD_NUMBER: _ClassVar[int] + event_type: str + principal_identity: str + occurred_at: _timestamp_pb2.Timestamp + published_at: _timestamp_pb2.Timestamp + message: _struct_pb2.Struct + def __init__(self, event_type: _Optional[str] = ..., principal_identity: _Optional[str] = ..., occurred_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., published_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., message: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... + +class FilterGroup(_message.Message): + __slots__ = ("event_type", "filters") + EVENT_TYPE_FIELD_NUMBER: _ClassVar[int] + FILTERS_FIELD_NUMBER: _ClassVar[int] + event_type: str + filters: _containers.RepeatedCompositeFieldContainer[ResourceFilter] + def __init__(self, event_type: _Optional[str] = ..., filters: _Optional[_Iterable[_Union[ResourceFilter, _Mapping]]] = ...) -> None: ... + +class ResourceFilter(_message.Message): + __slots__ = ("filter_type", "resource_id") + class FilterType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + FILTER_TYPE_UNSPECIFIED: _ClassVar[ResourceFilter.FilterType] + FILTER_TYPE_EQ: _ClassVar[ResourceFilter.FilterType] + FILTER_TYPE_STARTS_WITH_LAZY: _ClassVar[ResourceFilter.FilterType] + FILTER_TYPE_STARTS_WITH_GREEDY: _ClassVar[ResourceFilter.FilterType] + FILTER_TYPE_UNSPECIFIED: ResourceFilter.FilterType + FILTER_TYPE_EQ: ResourceFilter.FilterType + FILTER_TYPE_STARTS_WITH_LAZY: ResourceFilter.FilterType + FILTER_TYPE_STARTS_WITH_GREEDY: ResourceFilter.FilterType + FILTER_TYPE_FIELD_NUMBER: _ClassVar[int] + RESOURCE_ID_FIELD_NUMBER: _ClassVar[int] + filter_type: ResourceFilter.FilterType + resource_id: str + def __init__(self, filter_type: _Optional[_Union[ResourceFilter.FilterType, str]] = ..., resource_id: _Optional[str] = ...) -> None: ... diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/notifications/consumer/v1beta/event_consumer_pb2_grpc.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/notifications/consumer/v1beta/event_consumer_pb2_grpc.py new file mode 100644 index 0000000000000000000000000000000000000000..9fb9b45a7186da3f592c7e279281ab6e626422fa --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/notifications/consumer/v1beta/event_consumer_pb2_grpc.py @@ -0,0 +1,269 @@ +# 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 nvidia.omniverse.notifications.consumer.v1beta import event_consumer_pb2 as nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2 + +GRPC_GENERATED_VERSION = '1.80.0' +GRPC_VERSION = grpc.__version__ +_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: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in nvidia/omniverse/notifications/consumer/v1beta/event_consumer_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}.' + ) + + +class EventConsumerServiceStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.ConsumeDurableEvents = channel.unary_stream( + '/nvidia.omniverse.notifications.consumer.v1beta.EventConsumerService/ConsumeDurableEvents', + request_serializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.ConsumeDurableEventsRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.ConsumeDurableEventsResponse.FromString, + _registered_method=True) + self.ConsumeNonDurableEvents = channel.stream_stream( + '/nvidia.omniverse.notifications.consumer.v1beta.EventConsumerService/ConsumeNonDurableEvents', + request_serializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.ConsumeNonDurableEventsRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.ConsumeNonDurableEventsResponse.FromString, + _registered_method=True) + self.CreateDurableQueue = channel.unary_unary( + '/nvidia.omniverse.notifications.consumer.v1beta.EventConsumerService/CreateDurableQueue', + request_serializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.CreateDurableQueueRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.CreateDurableQueueResponse.FromString, + _registered_method=True) + self.DeleteDurableQueue = channel.unary_unary( + '/nvidia.omniverse.notifications.consumer.v1beta.EventConsumerService/DeleteDurableQueue', + request_serializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.DeleteDurableQueueRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.DeleteDurableQueueResponse.FromString, + _registered_method=True) + self.UpdateDurableQueue = channel.unary_unary( + '/nvidia.omniverse.notifications.consumer.v1beta.EventConsumerService/UpdateDurableQueue', + request_serializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.UpdateDurableQueueRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.UpdateDurableQueueResponse.FromString, + _registered_method=True) + + +class EventConsumerServiceServicer(object): + """Missing associated documentation comment in .proto file.""" + + def ConsumeDurableEvents(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ConsumeNonDurableEvents(self, request_iterator, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def CreateDurableQueue(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def DeleteDurableQueue(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def UpdateDurableQueue(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_EventConsumerServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'ConsumeDurableEvents': grpc.unary_stream_rpc_method_handler( + servicer.ConsumeDurableEvents, + request_deserializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.ConsumeDurableEventsRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.ConsumeDurableEventsResponse.SerializeToString, + ), + 'ConsumeNonDurableEvents': grpc.stream_stream_rpc_method_handler( + servicer.ConsumeNonDurableEvents, + request_deserializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.ConsumeNonDurableEventsRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.ConsumeNonDurableEventsResponse.SerializeToString, + ), + 'CreateDurableQueue': grpc.unary_unary_rpc_method_handler( + servicer.CreateDurableQueue, + request_deserializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.CreateDurableQueueRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.CreateDurableQueueResponse.SerializeToString, + ), + 'DeleteDurableQueue': grpc.unary_unary_rpc_method_handler( + servicer.DeleteDurableQueue, + request_deserializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.DeleteDurableQueueRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.DeleteDurableQueueResponse.SerializeToString, + ), + 'UpdateDurableQueue': grpc.unary_unary_rpc_method_handler( + servicer.UpdateDurableQueue, + request_deserializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.UpdateDurableQueueRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.UpdateDurableQueueResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'nvidia.omniverse.notifications.consumer.v1beta.EventConsumerService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('nvidia.omniverse.notifications.consumer.v1beta.EventConsumerService', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class EventConsumerService(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def ConsumeDurableEvents(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/nvidia.omniverse.notifications.consumer.v1beta.EventConsumerService/ConsumeDurableEvents', + nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.ConsumeDurableEventsRequest.SerializeToString, + nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.ConsumeDurableEventsResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ConsumeNonDurableEvents(request_iterator, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.stream_stream( + request_iterator, + target, + '/nvidia.omniverse.notifications.consumer.v1beta.EventConsumerService/ConsumeNonDurableEvents', + nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.ConsumeNonDurableEventsRequest.SerializeToString, + nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.ConsumeNonDurableEventsResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def CreateDurableQueue(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.notifications.consumer.v1beta.EventConsumerService/CreateDurableQueue', + nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.CreateDurableQueueRequest.SerializeToString, + nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.CreateDurableQueueResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def DeleteDurableQueue(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.notifications.consumer.v1beta.EventConsumerService/DeleteDurableQueue', + nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.DeleteDurableQueueRequest.SerializeToString, + nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.DeleteDurableQueueResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def UpdateDurableQueue(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.notifications.consumer.v1beta.EventConsumerService/UpdateDurableQueue', + nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.UpdateDurableQueueRequest.SerializeToString, + nvidia_dot_omniverse_dot_notifications_dot_consumer_dot_v1beta_dot_event__consumer__pb2.UpdateDurableQueueResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1alpha/capabilities_pb2.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1alpha/capabilities_pb2.py new file mode 100644 index 0000000000000000000000000000000000000000..87191bb5c38b212cf9410d1294ce454c63079e2a --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1alpha/capabilities_pb2.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: nvidia/omniverse/storage/capabilities/v1alpha/capabilities.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'nvidia/omniverse/storage/capabilities/v1alpha/capabilities.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n@nvidia/omniverse/storage/capabilities/v1alpha/capabilities.proto\x12-nvidia.omniverse.storage.capabilities.v1alpha\"\x15\n\x13ListServicesRequest\"e\n\x14ListServicesResponse\x12M\n\x08services\x18\x01 \x03(\x0b\x32;.nvidia.omniverse.storage.capabilities.v1alpha.ServiceEntry\">\n\x0cServiceEntry\x12\x14\n\x0cservice_name\x18\x01 \x01(\t\x12\x18\n\x10service_versions\x18\x02 \x03(\t\"\x1e\n\x1cListTopLevelAddressesRequest\"s\n\x1dListTopLevelAddressesResponse\x12R\n\x05items\x18\x01 \x03(\x0b\x32\x43.nvidia.omniverse.storage.capabilities.v1alpha.TopLevelAddressEntry\"\x13\n\x11ListRoutesRequest\"Y\n\x12ListRoutesResponse\x12\x43\n\x05items\x18\x01 \x03(\x0b\x32\x34.nvidia.omniverse.storage.capabilities.v1alpha.Route\"1\n\x14TopLevelAddressEntry\x12\x19\n\x11top_level_address\x18\x01 \x01(\t\"1\n\x05Route\x12\x1a\n\x10wildcard_pattern\x18\x01 \x01(\tH\x00\x42\x0c\n\nroute_type2\xf8\x03\n\x13\x43\x61pabilitiesService\x12\x97\x01\n\x0cListServices\x12\x42.nvidia.omniverse.storage.capabilities.v1alpha.ListServicesRequest\x1a\x43.nvidia.omniverse.storage.capabilities.v1alpha.ListServicesResponse\x12\xb2\x01\n\x15ListTopLevelAddresses\x12K.nvidia.omniverse.storage.capabilities.v1alpha.ListTopLevelAddressesRequest\x1aL.nvidia.omniverse.storage.capabilities.v1alpha.ListTopLevelAddressesResponse\x12\x91\x01\n\nListRoutes\x12@.nvidia.omniverse.storage.capabilities.v1alpha.ListRoutesRequest\x1a\x41.nvidia.omniverse.storage.capabilities.v1alpha.ListRoutesResponseB\x8a\x01\n1com.nvidia.omniverse.storage.capabilities.v1alphaB\x11\x43\x61pabilitiesProtoP\x01Z@pb.api.nvidia.com/omniverse/storage/capabilities/v1alpha;storageb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nvidia.omniverse.storage.capabilities.v1alpha.capabilities_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n1com.nvidia.omniverse.storage.capabilities.v1alphaB\021CapabilitiesProtoP\001Z@pb.api.nvidia.com/omniverse/storage/capabilities/v1alpha;storage' + _globals['_LISTSERVICESREQUEST']._serialized_start=115 + _globals['_LISTSERVICESREQUEST']._serialized_end=136 + _globals['_LISTSERVICESRESPONSE']._serialized_start=138 + _globals['_LISTSERVICESRESPONSE']._serialized_end=239 + _globals['_SERVICEENTRY']._serialized_start=241 + _globals['_SERVICEENTRY']._serialized_end=303 + _globals['_LISTTOPLEVELADDRESSESREQUEST']._serialized_start=305 + _globals['_LISTTOPLEVELADDRESSESREQUEST']._serialized_end=335 + _globals['_LISTTOPLEVELADDRESSESRESPONSE']._serialized_start=337 + _globals['_LISTTOPLEVELADDRESSESRESPONSE']._serialized_end=452 + _globals['_LISTROUTESREQUEST']._serialized_start=454 + _globals['_LISTROUTESREQUEST']._serialized_end=473 + _globals['_LISTROUTESRESPONSE']._serialized_start=475 + _globals['_LISTROUTESRESPONSE']._serialized_end=564 + _globals['_TOPLEVELADDRESSENTRY']._serialized_start=566 + _globals['_TOPLEVELADDRESSENTRY']._serialized_end=615 + _globals['_ROUTE']._serialized_start=617 + _globals['_ROUTE']._serialized_end=666 + _globals['_CAPABILITIESSERVICE']._serialized_start=669 + _globals['_CAPABILITIESSERVICE']._serialized_end=1173 +# @@protoc_insertion_point(module_scope) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1alpha/capabilities_pb2.pyi b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1alpha/capabilities_pb2.pyi new file mode 100644 index 0000000000000000000000000000000000000000..b6ae2729e112a8a45c8572e2d6f769b9387b14ff --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1alpha/capabilities_pb2.pyi @@ -0,0 +1,57 @@ +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class ListServicesRequest(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class ListServicesResponse(_message.Message): + __slots__ = ("services",) + SERVICES_FIELD_NUMBER: _ClassVar[int] + services: _containers.RepeatedCompositeFieldContainer[ServiceEntry] + def __init__(self, services: _Optional[_Iterable[_Union[ServiceEntry, _Mapping]]] = ...) -> None: ... + +class ServiceEntry(_message.Message): + __slots__ = ("service_name", "service_versions") + SERVICE_NAME_FIELD_NUMBER: _ClassVar[int] + SERVICE_VERSIONS_FIELD_NUMBER: _ClassVar[int] + service_name: str + service_versions: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, service_name: _Optional[str] = ..., service_versions: _Optional[_Iterable[str]] = ...) -> None: ... + +class ListTopLevelAddressesRequest(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class ListTopLevelAddressesResponse(_message.Message): + __slots__ = ("items",) + ITEMS_FIELD_NUMBER: _ClassVar[int] + items: _containers.RepeatedCompositeFieldContainer[TopLevelAddressEntry] + def __init__(self, items: _Optional[_Iterable[_Union[TopLevelAddressEntry, _Mapping]]] = ...) -> None: ... + +class ListRoutesRequest(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class ListRoutesResponse(_message.Message): + __slots__ = ("items",) + ITEMS_FIELD_NUMBER: _ClassVar[int] + items: _containers.RepeatedCompositeFieldContainer[Route] + def __init__(self, items: _Optional[_Iterable[_Union[Route, _Mapping]]] = ...) -> None: ... + +class TopLevelAddressEntry(_message.Message): + __slots__ = ("top_level_address",) + TOP_LEVEL_ADDRESS_FIELD_NUMBER: _ClassVar[int] + top_level_address: str + def __init__(self, top_level_address: _Optional[str] = ...) -> None: ... + +class Route(_message.Message): + __slots__ = ("wildcard_pattern",) + WILDCARD_PATTERN_FIELD_NUMBER: _ClassVar[int] + wildcard_pattern: str + def __init__(self, wildcard_pattern: _Optional[str] = ...) -> None: ... diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1alpha/capabilities_pb2_grpc.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1alpha/capabilities_pb2_grpc.py new file mode 100644 index 0000000000000000000000000000000000000000..f663eae6a51b47770d0200bec3a00014a70d0a08 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1alpha/capabilities_pb2_grpc.py @@ -0,0 +1,183 @@ +# 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 nvidia.omniverse.storage.capabilities.v1alpha import capabilities_pb2 as nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2 + +GRPC_GENERATED_VERSION = '1.80.0' +GRPC_VERSION = grpc.__version__ +_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: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in nvidia/omniverse/storage/capabilities/v1alpha/capabilities_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}.' + ) + + +class CapabilitiesServiceStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.ListServices = channel.unary_unary( + '/nvidia.omniverse.storage.capabilities.v1alpha.CapabilitiesService/ListServices', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListServicesRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListServicesResponse.FromString, + _registered_method=True) + self.ListTopLevelAddresses = channel.unary_unary( + '/nvidia.omniverse.storage.capabilities.v1alpha.CapabilitiesService/ListTopLevelAddresses', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListTopLevelAddressesRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListTopLevelAddressesResponse.FromString, + _registered_method=True) + self.ListRoutes = channel.unary_unary( + '/nvidia.omniverse.storage.capabilities.v1alpha.CapabilitiesService/ListRoutes', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListRoutesRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListRoutesResponse.FromString, + _registered_method=True) + + +class CapabilitiesServiceServicer(object): + """Missing associated documentation comment in .proto file.""" + + def ListServices(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ListTopLevelAddresses(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ListRoutes(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_CapabilitiesServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'ListServices': grpc.unary_unary_rpc_method_handler( + servicer.ListServices, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListServicesRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListServicesResponse.SerializeToString, + ), + 'ListTopLevelAddresses': grpc.unary_unary_rpc_method_handler( + servicer.ListTopLevelAddresses, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListTopLevelAddressesRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListTopLevelAddressesResponse.SerializeToString, + ), + 'ListRoutes': grpc.unary_unary_rpc_method_handler( + servicer.ListRoutes, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListRoutesRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListRoutesResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'nvidia.omniverse.storage.capabilities.v1alpha.CapabilitiesService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('nvidia.omniverse.storage.capabilities.v1alpha.CapabilitiesService', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class CapabilitiesService(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def ListServices(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.capabilities.v1alpha.CapabilitiesService/ListServices', + nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListServicesRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListServicesResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ListTopLevelAddresses(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.capabilities.v1alpha.CapabilitiesService/ListTopLevelAddresses', + nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListTopLevelAddressesRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListTopLevelAddressesResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ListRoutes(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.capabilities.v1alpha.CapabilitiesService/ListRoutes', + nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListRoutesRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1alpha_dot_capabilities__pb2.ListRoutesResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1beta/capabilities_pb2.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1beta/capabilities_pb2.py new file mode 100644 index 0000000000000000000000000000000000000000..b3c9b41395a7e1ea1ebb5e7a2f27f1e713578f81 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1beta/capabilities_pb2.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: nvidia/omniverse/storage/capabilities/v1beta/capabilities.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'nvidia/omniverse/storage/capabilities/v1beta/capabilities.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n?nvidia/omniverse/storage/capabilities/v1beta/capabilities.proto\x12,nvidia.omniverse.storage.capabilities.v1beta\"\x15\n\x13ListServicesRequest\"d\n\x14ListServicesResponse\x12L\n\x08services\x18\x01 \x03(\x0b\x32:.nvidia.omniverse.storage.capabilities.v1beta.ServiceEntry\">\n\x0cServiceEntry\x12\x14\n\x0cservice_name\x18\x01 \x01(\t\x12\x18\n\x10service_versions\x18\x02 \x03(\t\"\x1e\n\x1cListTopLevelAddressesRequest\"r\n\x1dListTopLevelAddressesResponse\x12Q\n\x05items\x18\x01 \x03(\x0b\x32\x42.nvidia.omniverse.storage.capabilities.v1beta.TopLevelAddressEntry\"1\n\x14TopLevelAddressEntry\x12\x19\n\x11top_level_address\x18\x01 \x01(\t2\xe0\x02\n\x13\x43\x61pabilitiesService\x12\x95\x01\n\x0cListServices\x12\x41.nvidia.omniverse.storage.capabilities.v1beta.ListServicesRequest\x1a\x42.nvidia.omniverse.storage.capabilities.v1beta.ListServicesResponse\x12\xb0\x01\n\x15ListTopLevelAddresses\x12J.nvidia.omniverse.storage.capabilities.v1beta.ListTopLevelAddressesRequest\x1aK.nvidia.omniverse.storage.capabilities.v1beta.ListTopLevelAddressesResponseB\x88\x01\n0com.nvidia.omniverse.storage.capabilities.v1betaB\x11\x43\x61pabilitiesProtoP\x01Z?pb.api.nvidia.com/omniverse/storage/capabilities/v1beta;storageb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nvidia.omniverse.storage.capabilities.v1beta.capabilities_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n0com.nvidia.omniverse.storage.capabilities.v1betaB\021CapabilitiesProtoP\001Z?pb.api.nvidia.com/omniverse/storage/capabilities/v1beta;storage' + _globals['_LISTSERVICESREQUEST']._serialized_start=113 + _globals['_LISTSERVICESREQUEST']._serialized_end=134 + _globals['_LISTSERVICESRESPONSE']._serialized_start=136 + _globals['_LISTSERVICESRESPONSE']._serialized_end=236 + _globals['_SERVICEENTRY']._serialized_start=238 + _globals['_SERVICEENTRY']._serialized_end=300 + _globals['_LISTTOPLEVELADDRESSESREQUEST']._serialized_start=302 + _globals['_LISTTOPLEVELADDRESSESREQUEST']._serialized_end=332 + _globals['_LISTTOPLEVELADDRESSESRESPONSE']._serialized_start=334 + _globals['_LISTTOPLEVELADDRESSESRESPONSE']._serialized_end=448 + _globals['_TOPLEVELADDRESSENTRY']._serialized_start=450 + _globals['_TOPLEVELADDRESSENTRY']._serialized_end=499 + _globals['_CAPABILITIESSERVICE']._serialized_start=502 + _globals['_CAPABILITIESSERVICE']._serialized_end=854 +# @@protoc_insertion_point(module_scope) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1beta/capabilities_pb2.pyi b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1beta/capabilities_pb2.pyi new file mode 100644 index 0000000000000000000000000000000000000000..26e9561b381eb90dcc1048dd218f3fa6deedc5d8 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1beta/capabilities_pb2.pyi @@ -0,0 +1,41 @@ +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class ListServicesRequest(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class ListServicesResponse(_message.Message): + __slots__ = ("services",) + SERVICES_FIELD_NUMBER: _ClassVar[int] + services: _containers.RepeatedCompositeFieldContainer[ServiceEntry] + def __init__(self, services: _Optional[_Iterable[_Union[ServiceEntry, _Mapping]]] = ...) -> None: ... + +class ServiceEntry(_message.Message): + __slots__ = ("service_name", "service_versions") + SERVICE_NAME_FIELD_NUMBER: _ClassVar[int] + SERVICE_VERSIONS_FIELD_NUMBER: _ClassVar[int] + service_name: str + service_versions: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, service_name: _Optional[str] = ..., service_versions: _Optional[_Iterable[str]] = ...) -> None: ... + +class ListTopLevelAddressesRequest(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class ListTopLevelAddressesResponse(_message.Message): + __slots__ = ("items",) + ITEMS_FIELD_NUMBER: _ClassVar[int] + items: _containers.RepeatedCompositeFieldContainer[TopLevelAddressEntry] + def __init__(self, items: _Optional[_Iterable[_Union[TopLevelAddressEntry, _Mapping]]] = ...) -> None: ... + +class TopLevelAddressEntry(_message.Message): + __slots__ = ("top_level_address",) + TOP_LEVEL_ADDRESS_FIELD_NUMBER: _ClassVar[int] + top_level_address: str + def __init__(self, top_level_address: _Optional[str] = ...) -> None: ... diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1beta/capabilities_pb2_grpc.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1beta/capabilities_pb2_grpc.py new file mode 100644 index 0000000000000000000000000000000000000000..95a53e628db8051f273298c70191b8020ec13037 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/capabilities/v1beta/capabilities_pb2_grpc.py @@ -0,0 +1,140 @@ +# 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 nvidia.omniverse.storage.capabilities.v1beta import capabilities_pb2 as nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1beta_dot_capabilities__pb2 + +GRPC_GENERATED_VERSION = '1.80.0' +GRPC_VERSION = grpc.__version__ +_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: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in nvidia/omniverse/storage/capabilities/v1beta/capabilities_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}.' + ) + + +class CapabilitiesServiceStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.ListServices = channel.unary_unary( + '/nvidia.omniverse.storage.capabilities.v1beta.CapabilitiesService/ListServices', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1beta_dot_capabilities__pb2.ListServicesRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1beta_dot_capabilities__pb2.ListServicesResponse.FromString, + _registered_method=True) + self.ListTopLevelAddresses = channel.unary_unary( + '/nvidia.omniverse.storage.capabilities.v1beta.CapabilitiesService/ListTopLevelAddresses', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1beta_dot_capabilities__pb2.ListTopLevelAddressesRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1beta_dot_capabilities__pb2.ListTopLevelAddressesResponse.FromString, + _registered_method=True) + + +class CapabilitiesServiceServicer(object): + """Missing associated documentation comment in .proto file.""" + + def ListServices(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ListTopLevelAddresses(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_CapabilitiesServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'ListServices': grpc.unary_unary_rpc_method_handler( + servicer.ListServices, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1beta_dot_capabilities__pb2.ListServicesRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1beta_dot_capabilities__pb2.ListServicesResponse.SerializeToString, + ), + 'ListTopLevelAddresses': grpc.unary_unary_rpc_method_handler( + servicer.ListTopLevelAddresses, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1beta_dot_capabilities__pb2.ListTopLevelAddressesRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1beta_dot_capabilities__pb2.ListTopLevelAddressesResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'nvidia.omniverse.storage.capabilities.v1beta.CapabilitiesService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('nvidia.omniverse.storage.capabilities.v1beta.CapabilitiesService', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class CapabilitiesService(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def ListServices(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.capabilities.v1beta.CapabilitiesService/ListServices', + nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1beta_dot_capabilities__pb2.ListServicesRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1beta_dot_capabilities__pb2.ListServicesResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ListTopLevelAddresses(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.capabilities.v1beta.CapabilitiesService/ListTopLevelAddresses', + nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1beta_dot_capabilities__pb2.ListTopLevelAddressesRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_capabilities_dot_v1beta_dot_capabilities__pb2.ListTopLevelAddressesResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1alpha/filefolder_service_pb2.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1alpha/filefolder_service_pb2.py new file mode 100644 index 0000000000000000000000000000000000000000..21f63b5c82d26c46d93b95d5cd918447deb26efb --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1alpha/filefolder_service_pb2.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: nvidia/omniverse/storage/filefolder/v1alpha/filefolder_service.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'nvidia/omniverse/storage/filefolder/v1alpha/filefolder_service.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from nvidia.omniverse.storage.fileobject.v1alpha import fileobject_pb2 as nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\nDnvidia/omniverse/storage/filefolder/v1alpha/filefolder_service.proto\x12+nvidia.omniverse.storage.filefolder.v1alpha\x1apb.api.nvidia.com/omniverse/storage/filefolder/v1alpha;storageb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nvidia.omniverse.storage.filefolder.v1alpha.filefolder_service_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n/com.nvidia.omniverse.storage.filefolder.v1alphaB\026FilefolderServiceProtoP\001Z>pb.api.nvidia.com/omniverse/storage/filefolder/v1alpha;storage' + _globals['_FOLDERMODE']._serialized_start=1308 + _globals['_FOLDERMODE']._serialized_end=1423 + _globals['_LISTREQUEST']._serialized_start=179 + _globals['_LISTREQUEST']._serialized_end=268 + _globals['_LISTRESPONSE']._serialized_start=271 + _globals['_LISTRESPONSE']._serialized_end=406 + _globals['_LISTSTATREQUEST']._serialized_start=408 + _globals['_LISTSTATREQUEST']._serialized_end=501 + _globals['_LISTSTATRESPONSE']._serialized_start=504 + _globals['_LISTSTATRESPONSE']._serialized_end=683 + _globals['_DELETEFOLDERREQUEST']._serialized_start=685 + _globals['_DELETEFOLDERREQUEST']._serialized_end=782 + _globals['_DELETEFOLDERRESPONSE']._serialized_start=784 + _globals['_DELETEFOLDERRESPONSE']._serialized_end=806 + _globals['_CREATEFOLDERREQUEST']._serialized_start=808 + _globals['_CREATEFOLDERREQUEST']._serialized_end=905 + _globals['_CREATEFOLDERRESPONSE']._serialized_start=907 + _globals['_CREATEFOLDERRESPONSE']._serialized_end=929 + _globals['_LISTITEM']._serialized_start=932 + _globals['_LISTITEM']._serialized_end=1073 + _globals['_GETFOLDERMODEREQUEST']._serialized_start=1075 + _globals['_GETFOLDERMODEREQUEST']._serialized_end=1173 + _globals['_GETFOLDERMODERESPONSE']._serialized_start=1175 + _globals['_GETFOLDERMODERESPONSE']._serialized_end=1276 + _globals['_FOLDERADDRESS']._serialized_start=1278 + _globals['_FOLDERADDRESS']._serialized_end=1306 + _globals['_FILEFOLDERSERVICE']._serialized_start=1426 + _globals['_FILEFOLDERSERVICE']._serialized_end=2165 +# @@protoc_insertion_point(module_scope) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1alpha/filefolder_service_pb2.pyi b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1alpha/filefolder_service_pb2.pyi new file mode 100644 index 0000000000000000000000000000000000000000..66496374377cec4f8ecf743862aeb0a3ab57bd4f --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1alpha/filefolder_service_pb2.pyi @@ -0,0 +1,94 @@ +from nvidia.omniverse.storage.fileobject.v1alpha import fileobject_pb2 as _fileobject_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class FolderMode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + FOLDER_MODE_UNSPECIFIED: _ClassVar[FolderMode] + FOLDER_MODE_NATIVE: _ClassVar[FolderMode] + FOLDER_MODE_NO_EMPTY: _ClassVar[FolderMode] + FOLDER_MODE_HYBRID: _ClassVar[FolderMode] +FOLDER_MODE_UNSPECIFIED: FolderMode +FOLDER_MODE_NATIVE: FolderMode +FOLDER_MODE_NO_EMPTY: FolderMode +FOLDER_MODE_HYBRID: FolderMode + +class ListRequest(_message.Message): + __slots__ = ("folder",) + FOLDER_FIELD_NUMBER: _ClassVar[int] + folder: FolderAddress + def __init__(self, folder: _Optional[_Union[FolderAddress, _Mapping]] = ...) -> None: ... + +class ListResponse(_message.Message): + __slots__ = ("subfolder_addresses", "sub_resource_addresses") + SUBFOLDER_ADDRESSES_FIELD_NUMBER: _ClassVar[int] + SUB_RESOURCE_ADDRESSES_FIELD_NUMBER: _ClassVar[int] + subfolder_addresses: _containers.RepeatedCompositeFieldContainer[FolderAddress] + sub_resource_addresses: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, subfolder_addresses: _Optional[_Iterable[_Union[FolderAddress, _Mapping]]] = ..., sub_resource_addresses: _Optional[_Iterable[str]] = ...) -> None: ... + +class ListStatRequest(_message.Message): + __slots__ = ("folder",) + FOLDER_FIELD_NUMBER: _ClassVar[int] + folder: FolderAddress + def __init__(self, folder: _Optional[_Union[FolderAddress, _Mapping]] = ...) -> None: ... + +class ListStatResponse(_message.Message): + __slots__ = ("subfolder_addresses", "entries") + SUBFOLDER_ADDRESSES_FIELD_NUMBER: _ClassVar[int] + ENTRIES_FIELD_NUMBER: _ClassVar[int] + subfolder_addresses: _containers.RepeatedCompositeFieldContainer[FolderAddress] + entries: _containers.RepeatedCompositeFieldContainer[ListItem] + def __init__(self, subfolder_addresses: _Optional[_Iterable[_Union[FolderAddress, _Mapping]]] = ..., entries: _Optional[_Iterable[_Union[ListItem, _Mapping]]] = ...) -> None: ... + +class DeleteFolderRequest(_message.Message): + __slots__ = ("folder",) + FOLDER_FIELD_NUMBER: _ClassVar[int] + folder: FolderAddress + def __init__(self, folder: _Optional[_Union[FolderAddress, _Mapping]] = ...) -> None: ... + +class DeleteFolderResponse(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class CreateFolderRequest(_message.Message): + __slots__ = ("folder",) + FOLDER_FIELD_NUMBER: _ClassVar[int] + folder: FolderAddress + def __init__(self, folder: _Optional[_Union[FolderAddress, _Mapping]] = ...) -> None: ... + +class CreateFolderResponse(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class ListItem(_message.Message): + __slots__ = ("resource_address", "resource_info") + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + RESOURCE_INFO_FIELD_NUMBER: _ClassVar[int] + resource_address: str + resource_info: _fileobject_pb2.ResourceInfo + def __init__(self, resource_address: _Optional[str] = ..., resource_info: _Optional[_Union[_fileobject_pb2.ResourceInfo, _Mapping]] = ...) -> None: ... + +class GetFolderModeRequest(_message.Message): + __slots__ = ("folder",) + FOLDER_FIELD_NUMBER: _ClassVar[int] + folder: FolderAddress + def __init__(self, folder: _Optional[_Union[FolderAddress, _Mapping]] = ...) -> None: ... + +class GetFolderModeResponse(_message.Message): + __slots__ = ("folder_mode",) + FOLDER_MODE_FIELD_NUMBER: _ClassVar[int] + folder_mode: FolderMode + def __init__(self, folder_mode: _Optional[_Union[FolderMode, str]] = ...) -> None: ... + +class FolderAddress(_message.Message): + __slots__ = ("uri",) + URI_FIELD_NUMBER: _ClassVar[int] + uri: str + def __init__(self, uri: _Optional[str] = ...) -> None: ... diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1alpha/filefolder_service_pb2_grpc.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1alpha/filefolder_service_pb2_grpc.py new file mode 100644 index 0000000000000000000000000000000000000000..42dfc0ec7740a74077eb269b4acef065c1ca9062 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1alpha/filefolder_service_pb2_grpc.py @@ -0,0 +1,269 @@ +# 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 nvidia.omniverse.storage.filefolder.v1alpha import filefolder_service_pb2 as nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2 + +GRPC_GENERATED_VERSION = '1.80.0' +GRPC_VERSION = grpc.__version__ +_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: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in nvidia/omniverse/storage/filefolder/v1alpha/filefolder_service_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}.' + ) + + +class FileFolderServiceStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.CreateFolder = channel.unary_unary( + '/nvidia.omniverse.storage.filefolder.v1alpha.FileFolderService/CreateFolder', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.CreateFolderRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.CreateFolderResponse.FromString, + _registered_method=True) + self.GetFolderMode = channel.unary_unary( + '/nvidia.omniverse.storage.filefolder.v1alpha.FileFolderService/GetFolderMode', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.GetFolderModeRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.GetFolderModeResponse.FromString, + _registered_method=True) + self.List = channel.unary_stream( + '/nvidia.omniverse.storage.filefolder.v1alpha.FileFolderService/List', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.ListRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.ListResponse.FromString, + _registered_method=True) + self.ListStat = channel.unary_stream( + '/nvidia.omniverse.storage.filefolder.v1alpha.FileFolderService/ListStat', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.ListStatRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.ListStatResponse.FromString, + _registered_method=True) + self.DeleteFolder = channel.unary_unary( + '/nvidia.omniverse.storage.filefolder.v1alpha.FileFolderService/DeleteFolder', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.DeleteFolderRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.DeleteFolderResponse.FromString, + _registered_method=True) + + +class FileFolderServiceServicer(object): + """Missing associated documentation comment in .proto file.""" + + def CreateFolder(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetFolderMode(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def List(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ListStat(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def DeleteFolder(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_FileFolderServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'CreateFolder': grpc.unary_unary_rpc_method_handler( + servicer.CreateFolder, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.CreateFolderRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.CreateFolderResponse.SerializeToString, + ), + 'GetFolderMode': grpc.unary_unary_rpc_method_handler( + servicer.GetFolderMode, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.GetFolderModeRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.GetFolderModeResponse.SerializeToString, + ), + 'List': grpc.unary_stream_rpc_method_handler( + servicer.List, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.ListRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.ListResponse.SerializeToString, + ), + 'ListStat': grpc.unary_stream_rpc_method_handler( + servicer.ListStat, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.ListStatRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.ListStatResponse.SerializeToString, + ), + 'DeleteFolder': grpc.unary_unary_rpc_method_handler( + servicer.DeleteFolder, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.DeleteFolderRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.DeleteFolderResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'nvidia.omniverse.storage.filefolder.v1alpha.FileFolderService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('nvidia.omniverse.storage.filefolder.v1alpha.FileFolderService', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class FileFolderService(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def CreateFolder(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.filefolder.v1alpha.FileFolderService/CreateFolder', + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.CreateFolderRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.CreateFolderResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetFolderMode(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.filefolder.v1alpha.FileFolderService/GetFolderMode', + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.GetFolderModeRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.GetFolderModeResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def List(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/nvidia.omniverse.storage.filefolder.v1alpha.FileFolderService/List', + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.ListRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.ListResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ListStat(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/nvidia.omniverse.storage.filefolder.v1alpha.FileFolderService/ListStat', + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.ListStatRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.ListStatResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def DeleteFolder(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.filefolder.v1alpha.FileFolderService/DeleteFolder', + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.DeleteFolderRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1alpha_dot_filefolder__service__pb2.DeleteFolderResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1beta/filefolder_service_pb2.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1beta/filefolder_service_pb2.py new file mode 100644 index 0000000000000000000000000000000000000000..0caac8e0ffeb148cf1f5d67853a80e47dd09bcbc --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1beta/filefolder_service_pb2.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: nvidia/omniverse/storage/filefolder/v1beta/filefolder_service.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'nvidia/omniverse/storage/filefolder/v1beta/filefolder_service.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from nvidia.omniverse.storage.fileobject.v1beta import fileobject_pb2 as nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\nCnvidia/omniverse/storage/filefolder/v1beta/filefolder_service.proto\x12*nvidia.omniverse.storage.filefolder.v1beta\x1a;nvidia/omniverse/storage/fileobject/v1beta/fileobject.proto\"X\n\x0bListRequest\x12I\n\x06\x66older\x18\x01 \x01(\x0b\x32\x39.nvidia.omniverse.storage.filefolder.v1beta.FolderAddress\"\x86\x01\n\x0cListResponse\x12V\n\x13subfolder_addresses\x18\x01 \x03(\x0b\x32\x39.nvidia.omniverse.storage.filefolder.v1beta.FolderAddress\x12\x1e\n\x16sub_resource_addresses\x18\x02 \x03(\t\"\\\n\x0fListStatRequest\x12I\n\x06\x66older\x18\x01 \x01(\x0b\x32\x39.nvidia.omniverse.storage.filefolder.v1beta.FolderAddress\"\xb1\x01\n\x10ListStatResponse\x12V\n\x13subfolder_addresses\x18\x01 \x03(\x0b\x32\x39.nvidia.omniverse.storage.filefolder.v1beta.FolderAddress\x12\x45\n\x07\x65ntries\x18\x02 \x03(\x0b\x32\x34.nvidia.omniverse.storage.filefolder.v1beta.ListItem\"`\n\x13\x44\x65leteFolderRequest\x12I\n\x06\x66older\x18\x01 \x01(\x0b\x32\x39.nvidia.omniverse.storage.filefolder.v1beta.FolderAddress\"\x16\n\x14\x44\x65leteFolderResponse\"\x8c\x01\n\x08ListItem\x12\x18\n\x10resource_address\x18\x01 \x01(\t\x12T\n\rresource_info\x18\x02 \x01(\x0b\x32\x38.nvidia.omniverse.storage.fileobject.v1beta.ResourceInfoH\x00\x88\x01\x01\x42\x10\n\x0e_resource_info\"\x1c\n\rFolderAddress\x12\x0b\n\x03uri\x18\x01 \x01(\t2\xae\x03\n\x11\x46ileFolderService\x12{\n\x04List\x12\x37.nvidia.omniverse.storage.filefolder.v1beta.ListRequest\x1a\x38.nvidia.omniverse.storage.filefolder.v1beta.ListResponse0\x01\x12\x87\x01\n\x08ListStat\x12;.nvidia.omniverse.storage.filefolder.v1beta.ListStatRequest\x1a<.nvidia.omniverse.storage.filefolder.v1beta.ListStatResponse0\x01\x12\x91\x01\n\x0c\x44\x65leteFolder\x12?.nvidia.omniverse.storage.filefolder.v1beta.DeleteFolderRequest\x1a@.nvidia.omniverse.storage.filefolder.v1beta.DeleteFolderResponseB\x89\x01\n.com.nvidia.omniverse.storage.filefolder.v1betaB\x16\x46ilefolderServiceProtoP\x01Z=pb.api.nvidia.com/omniverse/storage/filefolder/v1beta;storageb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nvidia.omniverse.storage.filefolder.v1beta.filefolder_service_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n.com.nvidia.omniverse.storage.filefolder.v1betaB\026FilefolderServiceProtoP\001Z=pb.api.nvidia.com/omniverse/storage/filefolder/v1beta;storage' + _globals['_LISTREQUEST']._serialized_start=176 + _globals['_LISTREQUEST']._serialized_end=264 + _globals['_LISTRESPONSE']._serialized_start=267 + _globals['_LISTRESPONSE']._serialized_end=401 + _globals['_LISTSTATREQUEST']._serialized_start=403 + _globals['_LISTSTATREQUEST']._serialized_end=495 + _globals['_LISTSTATRESPONSE']._serialized_start=498 + _globals['_LISTSTATRESPONSE']._serialized_end=675 + _globals['_DELETEFOLDERREQUEST']._serialized_start=677 + _globals['_DELETEFOLDERREQUEST']._serialized_end=773 + _globals['_DELETEFOLDERRESPONSE']._serialized_start=775 + _globals['_DELETEFOLDERRESPONSE']._serialized_end=797 + _globals['_LISTITEM']._serialized_start=800 + _globals['_LISTITEM']._serialized_end=940 + _globals['_FOLDERADDRESS']._serialized_start=942 + _globals['_FOLDERADDRESS']._serialized_end=970 + _globals['_FILEFOLDERSERVICE']._serialized_start=973 + _globals['_FILEFOLDERSERVICE']._serialized_end=1403 +# @@protoc_insertion_point(module_scope) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1beta/filefolder_service_pb2.pyi b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1beta/filefolder_service_pb2.pyi new file mode 100644 index 0000000000000000000000000000000000000000..fc32a87b0d914f114483d5f5414291a7165edf45 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1beta/filefolder_service_pb2.pyi @@ -0,0 +1,60 @@ +from nvidia.omniverse.storage.fileobject.v1beta import fileobject_pb2 as _fileobject_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class ListRequest(_message.Message): + __slots__ = ("folder",) + FOLDER_FIELD_NUMBER: _ClassVar[int] + folder: FolderAddress + def __init__(self, folder: _Optional[_Union[FolderAddress, _Mapping]] = ...) -> None: ... + +class ListResponse(_message.Message): + __slots__ = ("subfolder_addresses", "sub_resource_addresses") + SUBFOLDER_ADDRESSES_FIELD_NUMBER: _ClassVar[int] + SUB_RESOURCE_ADDRESSES_FIELD_NUMBER: _ClassVar[int] + subfolder_addresses: _containers.RepeatedCompositeFieldContainer[FolderAddress] + sub_resource_addresses: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, subfolder_addresses: _Optional[_Iterable[_Union[FolderAddress, _Mapping]]] = ..., sub_resource_addresses: _Optional[_Iterable[str]] = ...) -> None: ... + +class ListStatRequest(_message.Message): + __slots__ = ("folder",) + FOLDER_FIELD_NUMBER: _ClassVar[int] + folder: FolderAddress + def __init__(self, folder: _Optional[_Union[FolderAddress, _Mapping]] = ...) -> None: ... + +class ListStatResponse(_message.Message): + __slots__ = ("subfolder_addresses", "entries") + SUBFOLDER_ADDRESSES_FIELD_NUMBER: _ClassVar[int] + ENTRIES_FIELD_NUMBER: _ClassVar[int] + subfolder_addresses: _containers.RepeatedCompositeFieldContainer[FolderAddress] + entries: _containers.RepeatedCompositeFieldContainer[ListItem] + def __init__(self, subfolder_addresses: _Optional[_Iterable[_Union[FolderAddress, _Mapping]]] = ..., entries: _Optional[_Iterable[_Union[ListItem, _Mapping]]] = ...) -> None: ... + +class DeleteFolderRequest(_message.Message): + __slots__ = ("folder",) + FOLDER_FIELD_NUMBER: _ClassVar[int] + folder: FolderAddress + def __init__(self, folder: _Optional[_Union[FolderAddress, _Mapping]] = ...) -> None: ... + +class DeleteFolderResponse(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class ListItem(_message.Message): + __slots__ = ("resource_address", "resource_info") + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + RESOURCE_INFO_FIELD_NUMBER: _ClassVar[int] + resource_address: str + resource_info: _fileobject_pb2.ResourceInfo + def __init__(self, resource_address: _Optional[str] = ..., resource_info: _Optional[_Union[_fileobject_pb2.ResourceInfo, _Mapping]] = ...) -> None: ... + +class FolderAddress(_message.Message): + __slots__ = ("uri",) + URI_FIELD_NUMBER: _ClassVar[int] + uri: str + def __init__(self, uri: _Optional[str] = ...) -> None: ... diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1beta/filefolder_service_pb2_grpc.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1beta/filefolder_service_pb2_grpc.py new file mode 100644 index 0000000000000000000000000000000000000000..0a3451de9e257e0a648f3f8ddb233cdde1058aa0 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/filefolder/v1beta/filefolder_service_pb2_grpc.py @@ -0,0 +1,183 @@ +# 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 nvidia.omniverse.storage.filefolder.v1beta import filefolder_service_pb2 as nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2 + +GRPC_GENERATED_VERSION = '1.80.0' +GRPC_VERSION = grpc.__version__ +_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: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in nvidia/omniverse/storage/filefolder/v1beta/filefolder_service_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}.' + ) + + +class FileFolderServiceStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.List = channel.unary_stream( + '/nvidia.omniverse.storage.filefolder.v1beta.FileFolderService/List', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.ListRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.ListResponse.FromString, + _registered_method=True) + self.ListStat = channel.unary_stream( + '/nvidia.omniverse.storage.filefolder.v1beta.FileFolderService/ListStat', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.ListStatRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.ListStatResponse.FromString, + _registered_method=True) + self.DeleteFolder = channel.unary_unary( + '/nvidia.omniverse.storage.filefolder.v1beta.FileFolderService/DeleteFolder', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.DeleteFolderRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.DeleteFolderResponse.FromString, + _registered_method=True) + + +class FileFolderServiceServicer(object): + """Missing associated documentation comment in .proto file.""" + + def List(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ListStat(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def DeleteFolder(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_FileFolderServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'List': grpc.unary_stream_rpc_method_handler( + servicer.List, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.ListRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.ListResponse.SerializeToString, + ), + 'ListStat': grpc.unary_stream_rpc_method_handler( + servicer.ListStat, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.ListStatRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.ListStatResponse.SerializeToString, + ), + 'DeleteFolder': grpc.unary_unary_rpc_method_handler( + servicer.DeleteFolder, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.DeleteFolderRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.DeleteFolderResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'nvidia.omniverse.storage.filefolder.v1beta.FileFolderService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('nvidia.omniverse.storage.filefolder.v1beta.FileFolderService', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class FileFolderService(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def List(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/nvidia.omniverse.storage.filefolder.v1beta.FileFolderService/List', + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.ListRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.ListResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ListStat(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/nvidia.omniverse.storage.filefolder.v1beta.FileFolderService/ListStat', + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.ListStatRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.ListStatResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def DeleteFolder(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.filefolder.v1beta.FileFolderService/DeleteFolder', + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.DeleteFolderRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_filefolder_dot_v1beta_dot_filefolder__service__pb2.DeleteFolderResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_pb2.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_pb2.py new file mode 100644 index 0000000000000000000000000000000000000000..d20006e7dacaed42a9db684e888d6ea9d4a70ceb --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_pb2.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: nvidia/omniverse/storage/fileobject/v1alpha/fileobject.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'nvidia/omniverse/storage/fileobject/v1alpha/fileobject.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\npb.api.nvidia.com/omniverse/storage/fileobject/v1alpha;storageb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nvidia.omniverse.storage.fileobject.v1alpha.fileobject_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n/com.nvidia.omniverse.storage.fileobject.v1alphaB\017FileobjectProtoP\001Z>pb.api.nvidia.com/omniverse/storage/fileobject/v1alpha;storage' + _globals['_REDIRECT'].fields_by_name['method']._loaded_options = None + _globals['_REDIRECT'].fields_by_name['method']._serialized_options = b'\030\001' + _globals['_CHUNK']._serialized_start=142 + _globals['_CHUNK']._serialized_end=164 + _globals['_METADATA']._serialized_start=167 + _globals['_METADATA']._serialized_end=323 + _globals['_HEADER']._serialized_start=325 + _globals['_HEADER']._serialized_end=362 + _globals['_REDIRECT']._serialized_start=365 + _globals['_REDIRECT']._serialized_end=505 + _globals['_ADDRESSINFO']._serialized_start=507 + _globals['_ADDRESSINFO']._serialized_end=619 + _globals['_RESOURCEINFO']._serialized_start=622 + _globals['_RESOURCEINFO']._serialized_end=799 + _globals['_RESOURCEIDENTITY']._serialized_start=801 + _globals['_RESOURCEIDENTITY']._serialized_end=845 +# @@protoc_insertion_point(module_scope) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_pb2.pyi b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_pb2.pyi new file mode 100644 index 0000000000000000000000000000000000000000..89157c2f0df4683b31f7ec6e213dc14edd957582 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_pb2.pyi @@ -0,0 +1,64 @@ +import datetime + +from google.protobuf import timestamp_pb2 as _timestamp_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class Chunk(_message.Message): + __slots__ = ("chunk",) + CHUNK_FIELD_NUMBER: _ClassVar[int] + chunk: bytes + def __init__(self, chunk: _Optional[bytes] = ...) -> None: ... + +class Metadata(_message.Message): + __slots__ = ("data_object_size", "last_modified_timestamp") + DATA_OBJECT_SIZE_FIELD_NUMBER: _ClassVar[int] + LAST_MODIFIED_TIMESTAMP_FIELD_NUMBER: _ClassVar[int] + data_object_size: int + last_modified_timestamp: _timestamp_pb2.Timestamp + def __init__(self, data_object_size: _Optional[int] = ..., last_modified_timestamp: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ...) -> None: ... + +class Header(_message.Message): + __slots__ = ("name", "value") + NAME_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + name: str + value: str + def __init__(self, name: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + +class Redirect(_message.Message): + __slots__ = ("redirect_target_url", "method", "additional_headers") + REDIRECT_TARGET_URL_FIELD_NUMBER: _ClassVar[int] + METHOD_FIELD_NUMBER: _ClassVar[int] + ADDITIONAL_HEADERS_FIELD_NUMBER: _ClassVar[int] + redirect_target_url: str + method: str + additional_headers: _containers.RepeatedCompositeFieldContainer[Header] + def __init__(self, redirect_target_url: _Optional[str] = ..., method: _Optional[str] = ..., additional_headers: _Optional[_Iterable[_Union[Header, _Mapping]]] = ...) -> None: ... + +class AddressInfo(_message.Message): + __slots__ = ("resource_address", "metadata") + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + METADATA_FIELD_NUMBER: _ClassVar[int] + resource_address: str + metadata: Metadata + def __init__(self, resource_address: _Optional[str] = ..., metadata: _Optional[_Union[Metadata, _Mapping]] = ...) -> None: ... + +class ResourceInfo(_message.Message): + __slots__ = ("resource_identity", "metadata") + RESOURCE_IDENTITY_FIELD_NUMBER: _ClassVar[int] + METADATA_FIELD_NUMBER: _ClassVar[int] + resource_identity: ResourceIdentity + metadata: Metadata + def __init__(self, resource_identity: _Optional[_Union[ResourceIdentity, _Mapping]] = ..., metadata: _Optional[_Union[Metadata, _Mapping]] = ...) -> None: ... + +class ResourceIdentity(_message.Message): + __slots__ = ("encoded_identity",) + ENCODED_IDENTITY_FIELD_NUMBER: _ClassVar[int] + encoded_identity: str + def __init__(self, encoded_identity: _Optional[str] = ...) -> None: ... diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_pb2_grpc.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_pb2_grpc.py new file mode 100644 index 0000000000000000000000000000000000000000..1b0e6396578d7f1c536c301c555386c419ead806 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_pb2_grpc.py @@ -0,0 +1,24 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + + +GRPC_GENERATED_VERSION = '1.80.0' +GRPC_VERSION = grpc.__version__ +_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: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in nvidia/omniverse/storage/fileobject/v1alpha/fileobject_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}.' + ) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_service_pb2.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_service_pb2.py new file mode 100644 index 0000000000000000000000000000000000000000..185e493909479d2e0136ece117716ce2e6485292 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_service_pb2.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: nvidia/omniverse/storage/fileobject/v1alpha/fileobject_service.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'nvidia/omniverse/storage/fileobject/v1alpha/fileobject_service.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from nvidia.omniverse.storage.fileobject.v1alpha import fileobject_pb2 as nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\nDnvidia/omniverse/storage/fileobject/v1alpha/fileobject_service.proto\x12+nvidia.omniverse.storage.fileobject.v1alpha\x1a\n\"GetOptimisticLockingSupportRequest\x12\x18\n\x10resource_address\x18\x01 \x01(\t\"\x84\x01\n#GetOptimisticLockingSupportResponse\x12\x16\n\x0esupports_write\x18\x01 \x01(\x08\x12\x17\n\x0fsupports_delete\x18\x02 \x01(\x08\x12\x15\n\rsupports_copy\x18\x03 \x01(\x08\x12\x15\n\rsupports_move\x18\x04 \x01(\x08*y\n\x12\x44ownloadPreference\x12#\n\x1f\x44OWNLOAD_PREFERENCE_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x44OWNLOAD_PREFERENCE_BODY\x10\x01\x12 \n\x1c\x44OWNLOAD_PREFERENCE_REDIRECT\x10\x02*\x92\x01\n\x10UploadPreference\x12!\n\x1dUPLOAD_PREFERENCE_UNSPECIFIED\x10\x00\x12\x1a\n\x16UPLOAD_PREFERENCE_BODY\x10\x01\x12\x1e\n\x1aUPLOAD_PREFERENCE_REDIRECT\x10\x02\x12\x1f\n\x1bUPLOAD_PREFERENCE_MULTIPART\x10\x03*\\\n\x0cUploadMethod\x12\x1d\n\x19UPLOAD_METHOD_UNSPECIFIED\x10\x00\x12\x16\n\x12UPLOAD_METHOD_POST\x10\x01\x12\x15\n\x11UPLOAD_METHOD_PUT\x10\x02\x32\xd6\x10\n\x11\x46ileObjectService\x12\x8c\x01\n\tEnumerate\x12=.nvidia.omniverse.storage.fileobject.v1alpha.EnumerateRequest\x1a>.nvidia.omniverse.storage.fileobject.v1alpha.EnumerateResponse0\x01\x12{\n\x04Stat\x12\x38.nvidia.omniverse.storage.fileobject.v1alpha.StatRequest\x1a\x39.nvidia.omniverse.storage.fileobject.v1alpha.StatResponse\x12}\n\x04Read\x12\x38.nvidia.omniverse.storage.fileobject.v1alpha.ReadRequest\x1a\x39.nvidia.omniverse.storage.fileobject.v1alpha.ReadResponse0\x01\x12\x9e\x01\n\x0fReadFromAddress\x12\x43.nvidia.omniverse.storage.fileobject.v1alpha.ReadFromAddressRequest\x1a\x44.nvidia.omniverse.storage.fileobject.v1alpha.ReadFromAddressResponse0\x01\x12\xa5\x01\n\x12\x46\x65tchWriteTypeInfo\x12\x46.nvidia.omniverse.storage.fileobject.v1alpha.FetchWriteTypeInfoRequest\x1aG.nvidia.omniverse.storage.fileobject.v1alpha.FetchWriteTypeInfoResponse\x12\x82\x01\n\x05Write\x12\x39.nvidia.omniverse.storage.fileobject.v1alpha.WriteRequest\x1a:.nvidia.omniverse.storage.fileobject.v1alpha.WriteResponse(\x01\x30\x01\x12\xb1\x01\n\x16\x43ompleteRedirectUpload\x12J.nvidia.omniverse.storage.fileobject.v1alpha.CompleteRedirectUploadRequest\x1aK.nvidia.omniverse.storage.fileobject.v1alpha.CompleteRedirectUploadResponse\x12\x8d\x01\n\nUploadPart\x12>.nvidia.omniverse.storage.fileobject.v1alpha.UploadPartRequest\x1a?.nvidia.omniverse.storage.fileobject.v1alpha.UploadPartResponse\x12\xb4\x01\n\x17\x43ompleteMultipartUpload\x12K.nvidia.omniverse.storage.fileobject.v1alpha.CompleteMultipartUploadRequest\x1aL.nvidia.omniverse.storage.fileobject.v1alpha.CompleteMultipartUploadResponse\x12\xab\x01\n\x14\x41\x62ortMultipartUpload\x12H.nvidia.omniverse.storage.fileobject.v1alpha.AbortMultipartUploadRequest\x1aI.nvidia.omniverse.storage.fileobject.v1alpha.AbortMultipartUploadResponse\x12\x81\x01\n\x06\x44\x65lete\x12:.nvidia.omniverse.storage.fileobject.v1alpha.DeleteRequest\x1a;.nvidia.omniverse.storage.fileobject.v1alpha.DeleteResponse\x12{\n\x04\x43opy\x12\x38.nvidia.omniverse.storage.fileobject.v1alpha.CopyRequest\x1a\x39.nvidia.omniverse.storage.fileobject.v1alpha.CopyResponse\x12{\n\x04Move\x12\x38.nvidia.omniverse.storage.fileobject.v1alpha.MoveRequest\x1a\x39.nvidia.omniverse.storage.fileobject.v1alpha.MoveResponse\x12\xc0\x01\n\x1bGetOptimisticLockingSupport\x12O.nvidia.omniverse.storage.fileobject.v1alpha.GetOptimisticLockingSupportRequest\x1aP.nvidia.omniverse.storage.fileobject.v1alpha.GetOptimisticLockingSupportResponseB\x8b\x01\n/com.nvidia.omniverse.storage.fileobject.v1alphaB\x16\x46ileobjectServiceProtoP\x01Z>pb.api.nvidia.com/omniverse/storage/fileobject/v1alpha;storageb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nvidia.omniverse.storage.fileobject.v1alpha.fileobject_service_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n/com.nvidia.omniverse.storage.fileobject.v1alphaB\026FileobjectServiceProtoP\001Z>pb.api.nvidia.com/omniverse/storage/fileobject/v1alpha;storage' + _globals['_DOWNLOADPREFERENCE']._serialized_start=5578 + _globals['_DOWNLOADPREFERENCE']._serialized_end=5699 + _globals['_UPLOADPREFERENCE']._serialized_start=5702 + _globals['_UPLOADPREFERENCE']._serialized_end=5848 + _globals['_UPLOADMETHOD']._serialized_start=5850 + _globals['_UPLOADMETHOD']._serialized_end=5942 + _globals['_ENUMERATEREQUEST']._serialized_start=179 + _globals['_ENUMERATEREQUEST']._serialized_end=223 + _globals['_ENUMERATERESPONSE']._serialized_start=225 + _globals['_ENUMERATERESPONSE']._serialized_end=317 + _globals['_STATREQUEST']._serialized_start=319 + _globals['_STATREQUEST']._serialized_end=358 + _globals['_STATRESPONSE']._serialized_start=360 + _globals['_STATRESPONSE']._serialized_end=456 + _globals['_READREQUEST']._serialized_start=459 + _globals['_READREQUEST']._serialized_end=685 + _globals['_READRESPONSE']._serialized_start=688 + _globals['_READRESPONSE']._serialized_end=935 + _globals['_READFROMADDRESSREQUEST']._serialized_start=938 + _globals['_READFROMADDRESSREQUEST']._serialized_end=1111 + _globals['_READFROMADDRESSRESPONSE']._serialized_start=1114 + _globals['_READFROMADDRESSRESPONSE']._serialized_end=1381 + _globals['_FETCHWRITETYPEINFOREQUEST']._serialized_start=1383 + _globals['_FETCHWRITETYPEINFOREQUEST']._serialized_end=1448 + _globals['_WRITETYPEFORSIZEINTERVAL']._serialized_start=1451 + _globals['_WRITETYPEFORSIZEINTERVAL']._serialized_end=1641 + _globals['_FETCHWRITETYPEINFORESPONSE']._serialized_start=1644 + _globals['_FETCHWRITETYPEINFORESPONSE']._serialized_end=1773 + _globals['_WRITEREQUEST']._serialized_start=1776 + _globals['_WRITEREQUEST']._serialized_end=1961 + _globals['_WRITEPARAMETERS']._serialized_start=1964 + _globals['_WRITEPARAMETERS']._serialized_end=2277 + _globals['_WRITEREDIRECTPROPERTIES']._serialized_start=2280 + _globals['_WRITEREDIRECTPROPERTIES']._serialized_end=2523 + _globals['_WRITECHUNKSACCEPTED']._serialized_start=2525 + _globals['_WRITECHUNKSACCEPTED']._serialized_end=2546 + _globals['_WRITERESPONSE']._serialized_start=2549 + _globals['_WRITERESPONSE']._serialized_end=2970 + _globals['_COMPLETEREDIRECTUPLOADREQUEST']._serialized_start=2973 + _globals['_COMPLETEREDIRECTUPLOADREQUEST']._serialized_end=3123 + _globals['_COMPLETEREDIRECTUPLOADRESPONSE']._serialized_start=3125 + _globals['_COMPLETEREDIRECTUPLOADRESPONSE']._serialized_end=3239 + _globals['_CREATEMULTIPARTUPLOADRESPONSE']._serialized_start=3242 + _globals['_CREATEMULTIPARTUPLOADRESPONSE']._serialized_end=3581 + _globals['_UPLOADPARTREQUEST']._serialized_start=3584 + _globals['_UPLOADPARTREQUEST']._serialized_end=3721 + _globals['_UPLOADPARTRESPONSE']._serialized_start=3723 + _globals['_UPLOADPARTRESPONSE']._serialized_end=3843 + _globals['_COMPLETEDUPLOADPART']._serialized_start=3845 + _globals['_COMPLETEDUPLOADPART']._serialized_end=3957 + _globals['_COMPLETEMULTIPARTUPLOADREQUEST']._serialized_start=3960 + _globals['_COMPLETEMULTIPARTUPLOADREQUEST']._serialized_end=4130 + _globals['_COMPLETEMULTIPARTUPLOADRESPONSE']._serialized_start=4132 + _globals['_COMPLETEMULTIPARTUPLOADRESPONSE']._serialized_end=4247 + _globals['_ABORTMULTIPARTUPLOADREQUEST']._serialized_start=4249 + _globals['_ABORTMULTIPARTUPLOADREQUEST']._serialized_end=4335 + _globals['_ABORTMULTIPARTUPLOADRESPONSE']._serialized_start=4337 + _globals['_ABORTMULTIPARTUPLOADRESPONSE']._serialized_end=4367 + _globals['_DELETEREQUEST']._serialized_start=4370 + _globals['_DELETEREQUEST']._serialized_end=4526 + _globals['_DELETERESPONSE']._serialized_start=4528 + _globals['_DELETERESPONSE']._serialized_end=4544 + _globals['_COPYREQUEST']._serialized_start=4547 + _globals['_COPYREQUEST']._serialized_end=4810 + _globals['_COPYRESPONSE']._serialized_start=4812 + _globals['_COPYRESPONSE']._serialized_end=4916 + _globals['_MOVEREQUEST']._serialized_start=4919 + _globals['_MOVEREQUEST']._serialized_end=5271 + _globals['_MOVERESPONSE']._serialized_start=5273 + _globals['_MOVERESPONSE']._serialized_end=5377 + _globals['_GETOPTIMISTICLOCKINGSUPPORTREQUEST']._serialized_start=5379 + _globals['_GETOPTIMISTICLOCKINGSUPPORTREQUEST']._serialized_end=5441 + _globals['_GETOPTIMISTICLOCKINGSUPPORTRESPONSE']._serialized_start=5444 + _globals['_GETOPTIMISTICLOCKINGSUPPORTRESPONSE']._serialized_end=5576 + _globals['_FILEOBJECTSERVICE']._serialized_start=5945 + _globals['_FILEOBJECTSERVICE']._serialized_end=8079 +# @@protoc_insertion_point(module_scope) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_service_pb2.pyi b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_service_pb2.pyi new file mode 100644 index 0000000000000000000000000000000000000000..f230d33c4db951a6ad00675f0df1c5f5de93f3eb --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_service_pb2.pyi @@ -0,0 +1,314 @@ +from nvidia.omniverse.storage.fileobject.v1alpha import fileobject_pb2 as _fileobject_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class DownloadPreference(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + DOWNLOAD_PREFERENCE_UNSPECIFIED: _ClassVar[DownloadPreference] + DOWNLOAD_PREFERENCE_BODY: _ClassVar[DownloadPreference] + DOWNLOAD_PREFERENCE_REDIRECT: _ClassVar[DownloadPreference] + +class UploadPreference(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + UPLOAD_PREFERENCE_UNSPECIFIED: _ClassVar[UploadPreference] + UPLOAD_PREFERENCE_BODY: _ClassVar[UploadPreference] + UPLOAD_PREFERENCE_REDIRECT: _ClassVar[UploadPreference] + UPLOAD_PREFERENCE_MULTIPART: _ClassVar[UploadPreference] + +class UploadMethod(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + UPLOAD_METHOD_UNSPECIFIED: _ClassVar[UploadMethod] + UPLOAD_METHOD_POST: _ClassVar[UploadMethod] + UPLOAD_METHOD_PUT: _ClassVar[UploadMethod] +DOWNLOAD_PREFERENCE_UNSPECIFIED: DownloadPreference +DOWNLOAD_PREFERENCE_BODY: DownloadPreference +DOWNLOAD_PREFERENCE_REDIRECT: DownloadPreference +UPLOAD_PREFERENCE_UNSPECIFIED: UploadPreference +UPLOAD_PREFERENCE_BODY: UploadPreference +UPLOAD_PREFERENCE_REDIRECT: UploadPreference +UPLOAD_PREFERENCE_MULTIPART: UploadPreference +UPLOAD_METHOD_UNSPECIFIED: UploadMethod +UPLOAD_METHOD_POST: UploadMethod +UPLOAD_METHOD_PUT: UploadMethod + +class EnumerateRequest(_message.Message): + __slots__ = ("resource_address",) + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + resource_address: str + def __init__(self, resource_address: _Optional[str] = ...) -> None: ... + +class EnumerateResponse(_message.Message): + __slots__ = ("items",) + ITEMS_FIELD_NUMBER: _ClassVar[int] + items: _containers.RepeatedCompositeFieldContainer[_fileobject_pb2.AddressInfo] + def __init__(self, items: _Optional[_Iterable[_Union[_fileobject_pb2.AddressInfo, _Mapping]]] = ...) -> None: ... + +class StatRequest(_message.Message): + __slots__ = ("resource_address",) + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + resource_address: str + def __init__(self, resource_address: _Optional[str] = ...) -> None: ... + +class StatResponse(_message.Message): + __slots__ = ("resource_info",) + RESOURCE_INFO_FIELD_NUMBER: _ClassVar[int] + resource_info: _fileobject_pb2.ResourceInfo + def __init__(self, resource_info: _Optional[_Union[_fileobject_pb2.ResourceInfo, _Mapping]] = ...) -> None: ... + +class ReadRequest(_message.Message): + __slots__ = ("resource_identity", "download_preference") + RESOURCE_IDENTITY_FIELD_NUMBER: _ClassVar[int] + DOWNLOAD_PREFERENCE_FIELD_NUMBER: _ClassVar[int] + resource_identity: _fileobject_pb2.ResourceIdentity + download_preference: DownloadPreference + def __init__(self, resource_identity: _Optional[_Union[_fileobject_pb2.ResourceIdentity, _Mapping]] = ..., download_preference: _Optional[_Union[DownloadPreference, str]] = ...) -> None: ... + +class ReadResponse(_message.Message): + __slots__ = ("metadata", "chunk", "redirect") + METADATA_FIELD_NUMBER: _ClassVar[int] + CHUNK_FIELD_NUMBER: _ClassVar[int] + REDIRECT_FIELD_NUMBER: _ClassVar[int] + metadata: _fileobject_pb2.Metadata + chunk: _fileobject_pb2.Chunk + redirect: _fileobject_pb2.Redirect + def __init__(self, metadata: _Optional[_Union[_fileobject_pb2.Metadata, _Mapping]] = ..., chunk: _Optional[_Union[_fileobject_pb2.Chunk, _Mapping]] = ..., redirect: _Optional[_Union[_fileobject_pb2.Redirect, _Mapping]] = ...) -> None: ... + +class ReadFromAddressRequest(_message.Message): + __slots__ = ("resource_address", "download_preference") + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + DOWNLOAD_PREFERENCE_FIELD_NUMBER: _ClassVar[int] + resource_address: str + download_preference: DownloadPreference + def __init__(self, resource_address: _Optional[str] = ..., download_preference: _Optional[_Union[DownloadPreference, str]] = ...) -> None: ... + +class ReadFromAddressResponse(_message.Message): + __slots__ = ("resource_info", "chunk", "redirect") + RESOURCE_INFO_FIELD_NUMBER: _ClassVar[int] + CHUNK_FIELD_NUMBER: _ClassVar[int] + REDIRECT_FIELD_NUMBER: _ClassVar[int] + resource_info: _fileobject_pb2.ResourceInfo + chunk: _fileobject_pb2.Chunk + redirect: _fileobject_pb2.Redirect + def __init__(self, resource_info: _Optional[_Union[_fileobject_pb2.ResourceInfo, _Mapping]] = ..., chunk: _Optional[_Union[_fileobject_pb2.Chunk, _Mapping]] = ..., redirect: _Optional[_Union[_fileobject_pb2.Redirect, _Mapping]] = ...) -> None: ... + +class FetchWriteTypeInfoRequest(_message.Message): + __slots__ = ("destination_resource_address",) + DESTINATION_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + destination_resource_address: str + def __init__(self, destination_resource_address: _Optional[str] = ...) -> None: ... + +class WriteTypeForSizeInterval(_message.Message): + __slots__ = ("minimum_data_object_size", "maximum_data_object_size", "preferred_upload_method") + MINIMUM_DATA_OBJECT_SIZE_FIELD_NUMBER: _ClassVar[int] + MAXIMUM_DATA_OBJECT_SIZE_FIELD_NUMBER: _ClassVar[int] + PREFERRED_UPLOAD_METHOD_FIELD_NUMBER: _ClassVar[int] + minimum_data_object_size: int + maximum_data_object_size: int + preferred_upload_method: UploadPreference + def __init__(self, minimum_data_object_size: _Optional[int] = ..., maximum_data_object_size: _Optional[int] = ..., preferred_upload_method: _Optional[_Union[UploadPreference, str]] = ...) -> None: ... + +class FetchWriteTypeInfoResponse(_message.Message): + __slots__ = ("write_type_intervals",) + WRITE_TYPE_INTERVALS_FIELD_NUMBER: _ClassVar[int] + write_type_intervals: _containers.RepeatedCompositeFieldContainer[WriteTypeForSizeInterval] + def __init__(self, write_type_intervals: _Optional[_Iterable[_Union[WriteTypeForSizeInterval, _Mapping]]] = ...) -> None: ... + +class WriteRequest(_message.Message): + __slots__ = ("params", "chunk") + PARAMS_FIELD_NUMBER: _ClassVar[int] + CHUNK_FIELD_NUMBER: _ClassVar[int] + params: WriteParameters + chunk: _fileobject_pb2.Chunk + def __init__(self, params: _Optional[_Union[WriteParameters, _Mapping]] = ..., chunk: _Optional[_Union[_fileobject_pb2.Chunk, _Mapping]] = ...) -> None: ... + +class WriteParameters(_message.Message): + __slots__ = ("destination_resource_address", "previous_version", "data_object_size", "upload_preference") + DESTINATION_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + PREVIOUS_VERSION_FIELD_NUMBER: _ClassVar[int] + DATA_OBJECT_SIZE_FIELD_NUMBER: _ClassVar[int] + UPLOAD_PREFERENCE_FIELD_NUMBER: _ClassVar[int] + destination_resource_address: str + previous_version: _fileobject_pb2.ResourceIdentity + data_object_size: int + upload_preference: UploadPreference + def __init__(self, destination_resource_address: _Optional[str] = ..., previous_version: _Optional[_Union[_fileobject_pb2.ResourceIdentity, _Mapping]] = ..., data_object_size: _Optional[int] = ..., upload_preference: _Optional[_Union[UploadPreference, str]] = ...) -> None: ... + +class WriteRedirectProperties(_message.Message): + __slots__ = ("redirect_target_url", "method", "additional_headers", "completion_header_names") + REDIRECT_TARGET_URL_FIELD_NUMBER: _ClassVar[int] + METHOD_FIELD_NUMBER: _ClassVar[int] + ADDITIONAL_HEADERS_FIELD_NUMBER: _ClassVar[int] + COMPLETION_HEADER_NAMES_FIELD_NUMBER: _ClassVar[int] + redirect_target_url: str + method: UploadMethod + additional_headers: _containers.RepeatedCompositeFieldContainer[_fileobject_pb2.Header] + completion_header_names: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, redirect_target_url: _Optional[str] = ..., method: _Optional[_Union[UploadMethod, str]] = ..., additional_headers: _Optional[_Iterable[_Union[_fileobject_pb2.Header, _Mapping]]] = ..., completion_header_names: _Optional[_Iterable[str]] = ...) -> None: ... + +class WriteChunksAccepted(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class WriteResponse(_message.Message): + __slots__ = ("write_chunks_accepted", "resource_info", "write_redirect", "multipart_upload") + WRITE_CHUNKS_ACCEPTED_FIELD_NUMBER: _ClassVar[int] + RESOURCE_INFO_FIELD_NUMBER: _ClassVar[int] + WRITE_REDIRECT_FIELD_NUMBER: _ClassVar[int] + MULTIPART_UPLOAD_FIELD_NUMBER: _ClassVar[int] + write_chunks_accepted: WriteChunksAccepted + resource_info: _fileobject_pb2.ResourceInfo + write_redirect: WriteRedirectProperties + multipart_upload: CreateMultipartUploadResponse + def __init__(self, write_chunks_accepted: _Optional[_Union[WriteChunksAccepted, _Mapping]] = ..., resource_info: _Optional[_Union[_fileobject_pb2.ResourceInfo, _Mapping]] = ..., write_redirect: _Optional[_Union[WriteRedirectProperties, _Mapping]] = ..., multipart_upload: _Optional[_Union[CreateMultipartUploadResponse, _Mapping]] = ...) -> None: ... + +class CompleteRedirectUploadRequest(_message.Message): + __slots__ = ("destination_resource_address", "additional_headers") + DESTINATION_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + ADDITIONAL_HEADERS_FIELD_NUMBER: _ClassVar[int] + destination_resource_address: str + additional_headers: _containers.RepeatedCompositeFieldContainer[_fileobject_pb2.Header] + def __init__(self, destination_resource_address: _Optional[str] = ..., additional_headers: _Optional[_Iterable[_Union[_fileobject_pb2.Header, _Mapping]]] = ...) -> None: ... + +class CompleteRedirectUploadResponse(_message.Message): + __slots__ = ("resource_info",) + RESOURCE_INFO_FIELD_NUMBER: _ClassVar[int] + resource_info: _fileobject_pb2.ResourceInfo + def __init__(self, resource_info: _Optional[_Union[_fileobject_pb2.ResourceInfo, _Mapping]] = ...) -> None: ... + +class CreateMultipartUploadResponse(_message.Message): + __slots__ = ("upload_id", "first_part_write_redirect", "maximum_parts_number", "minimum_size_per_part", "maximum_size_per_part") + UPLOAD_ID_FIELD_NUMBER: _ClassVar[int] + FIRST_PART_WRITE_REDIRECT_FIELD_NUMBER: _ClassVar[int] + MAXIMUM_PARTS_NUMBER_FIELD_NUMBER: _ClassVar[int] + MINIMUM_SIZE_PER_PART_FIELD_NUMBER: _ClassVar[int] + MAXIMUM_SIZE_PER_PART_FIELD_NUMBER: _ClassVar[int] + upload_id: str + first_part_write_redirect: WriteRedirectProperties + maximum_parts_number: int + minimum_size_per_part: int + maximum_size_per_part: int + def __init__(self, upload_id: _Optional[str] = ..., first_part_write_redirect: _Optional[_Union[WriteRedirectProperties, _Mapping]] = ..., maximum_parts_number: _Optional[int] = ..., minimum_size_per_part: _Optional[int] = ..., maximum_size_per_part: _Optional[int] = ...) -> None: ... + +class UploadPartRequest(_message.Message): + __slots__ = ("upload_id", "destination_resource_address", "part_number", "part_count") + UPLOAD_ID_FIELD_NUMBER: _ClassVar[int] + DESTINATION_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + PART_NUMBER_FIELD_NUMBER: _ClassVar[int] + PART_COUNT_FIELD_NUMBER: _ClassVar[int] + upload_id: str + destination_resource_address: str + part_number: int + part_count: int + def __init__(self, upload_id: _Optional[str] = ..., destination_resource_address: _Optional[str] = ..., part_number: _Optional[int] = ..., part_count: _Optional[int] = ...) -> None: ... + +class UploadPartResponse(_message.Message): + __slots__ = ("part_write_redirects",) + PART_WRITE_REDIRECTS_FIELD_NUMBER: _ClassVar[int] + part_write_redirects: _containers.RepeatedCompositeFieldContainer[WriteRedirectProperties] + def __init__(self, part_write_redirects: _Optional[_Iterable[_Union[WriteRedirectProperties, _Mapping]]] = ...) -> None: ... + +class CompletedUploadPart(_message.Message): + __slots__ = ("part_number", "headers") + PART_NUMBER_FIELD_NUMBER: _ClassVar[int] + HEADERS_FIELD_NUMBER: _ClassVar[int] + part_number: int + headers: _containers.RepeatedCompositeFieldContainer[_fileobject_pb2.Header] + def __init__(self, part_number: _Optional[int] = ..., headers: _Optional[_Iterable[_Union[_fileobject_pb2.Header, _Mapping]]] = ...) -> None: ... + +class CompleteMultipartUploadRequest(_message.Message): + __slots__ = ("upload_id", "destination_resource_address", "parts") + UPLOAD_ID_FIELD_NUMBER: _ClassVar[int] + DESTINATION_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + PARTS_FIELD_NUMBER: _ClassVar[int] + upload_id: str + destination_resource_address: str + parts: _containers.RepeatedCompositeFieldContainer[CompletedUploadPart] + def __init__(self, upload_id: _Optional[str] = ..., destination_resource_address: _Optional[str] = ..., parts: _Optional[_Iterable[_Union[CompletedUploadPart, _Mapping]]] = ...) -> None: ... + +class CompleteMultipartUploadResponse(_message.Message): + __slots__ = ("resource_info",) + RESOURCE_INFO_FIELD_NUMBER: _ClassVar[int] + resource_info: _fileobject_pb2.ResourceInfo + def __init__(self, resource_info: _Optional[_Union[_fileobject_pb2.ResourceInfo, _Mapping]] = ...) -> None: ... + +class AbortMultipartUploadRequest(_message.Message): + __slots__ = ("upload_id", "destination_resource_address") + UPLOAD_ID_FIELD_NUMBER: _ClassVar[int] + DESTINATION_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + upload_id: str + destination_resource_address: str + def __init__(self, upload_id: _Optional[str] = ..., destination_resource_address: _Optional[str] = ...) -> None: ... + +class AbortMultipartUploadResponse(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class DeleteRequest(_message.Message): + __slots__ = ("resource_address", "previous_version") + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + PREVIOUS_VERSION_FIELD_NUMBER: _ClassVar[int] + resource_address: str + previous_version: _fileobject_pb2.ResourceIdentity + def __init__(self, resource_address: _Optional[str] = ..., previous_version: _Optional[_Union[_fileobject_pb2.ResourceIdentity, _Mapping]] = ...) -> None: ... + +class DeleteResponse(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class CopyRequest(_message.Message): + __slots__ = ("source_resource_identity", "destination_resource_address", "previous_version") + SOURCE_RESOURCE_IDENTITY_FIELD_NUMBER: _ClassVar[int] + DESTINATION_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + PREVIOUS_VERSION_FIELD_NUMBER: _ClassVar[int] + source_resource_identity: _fileobject_pb2.ResourceIdentity + destination_resource_address: str + previous_version: _fileobject_pb2.ResourceIdentity + def __init__(self, source_resource_identity: _Optional[_Union[_fileobject_pb2.ResourceIdentity, _Mapping]] = ..., destination_resource_address: _Optional[str] = ..., previous_version: _Optional[_Union[_fileobject_pb2.ResourceIdentity, _Mapping]] = ...) -> None: ... + +class CopyResponse(_message.Message): + __slots__ = ("resource_identity",) + RESOURCE_IDENTITY_FIELD_NUMBER: _ClassVar[int] + resource_identity: _fileobject_pb2.ResourceIdentity + def __init__(self, resource_identity: _Optional[_Union[_fileobject_pb2.ResourceIdentity, _Mapping]] = ...) -> None: ... + +class MoveRequest(_message.Message): + __slots__ = ("source_resource_address", "source_previous_version", "destination_resource_address", "destination_previous_version") + SOURCE_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + SOURCE_PREVIOUS_VERSION_FIELD_NUMBER: _ClassVar[int] + DESTINATION_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + DESTINATION_PREVIOUS_VERSION_FIELD_NUMBER: _ClassVar[int] + source_resource_address: str + source_previous_version: _fileobject_pb2.ResourceIdentity + destination_resource_address: str + destination_previous_version: _fileobject_pb2.ResourceIdentity + def __init__(self, source_resource_address: _Optional[str] = ..., source_previous_version: _Optional[_Union[_fileobject_pb2.ResourceIdentity, _Mapping]] = ..., destination_resource_address: _Optional[str] = ..., destination_previous_version: _Optional[_Union[_fileobject_pb2.ResourceIdentity, _Mapping]] = ...) -> None: ... + +class MoveResponse(_message.Message): + __slots__ = ("resource_identity",) + RESOURCE_IDENTITY_FIELD_NUMBER: _ClassVar[int] + resource_identity: _fileobject_pb2.ResourceIdentity + def __init__(self, resource_identity: _Optional[_Union[_fileobject_pb2.ResourceIdentity, _Mapping]] = ...) -> None: ... + +class GetOptimisticLockingSupportRequest(_message.Message): + __slots__ = ("resource_address",) + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + resource_address: str + def __init__(self, resource_address: _Optional[str] = ...) -> None: ... + +class GetOptimisticLockingSupportResponse(_message.Message): + __slots__ = ("supports_write", "supports_delete", "supports_copy", "supports_move") + SUPPORTS_WRITE_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_DELETE_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_COPY_FIELD_NUMBER: _ClassVar[int] + SUPPORTS_MOVE_FIELD_NUMBER: _ClassVar[int] + supports_write: bool + supports_delete: bool + supports_copy: bool + supports_move: bool + def __init__(self, supports_write: bool = ..., supports_delete: bool = ..., supports_copy: bool = ..., supports_move: bool = ...) -> None: ... diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_service_pb2_grpc.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_service_pb2_grpc.py new file mode 100644 index 0000000000000000000000000000000000000000..993436b505e67c121e41728121ef2c5951208919 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1alpha/fileobject_service_pb2_grpc.py @@ -0,0 +1,656 @@ +# 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 nvidia.omniverse.storage.fileobject.v1alpha import fileobject_service_pb2 as nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2 + +GRPC_GENERATED_VERSION = '1.80.0' +GRPC_VERSION = grpc.__version__ +_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: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in nvidia/omniverse/storage/fileobject/v1alpha/fileobject_service_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}.' + ) + + +class FileObjectServiceStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.Enumerate = channel.unary_stream( + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/Enumerate', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.EnumerateRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.EnumerateResponse.FromString, + _registered_method=True) + self.Stat = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/Stat', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.StatRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.StatResponse.FromString, + _registered_method=True) + self.Read = channel.unary_stream( + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/Read', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.ReadRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.ReadResponse.FromString, + _registered_method=True) + self.ReadFromAddress = channel.unary_stream( + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/ReadFromAddress', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.ReadFromAddressRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.ReadFromAddressResponse.FromString, + _registered_method=True) + self.FetchWriteTypeInfo = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/FetchWriteTypeInfo', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.FetchWriteTypeInfoRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.FetchWriteTypeInfoResponse.FromString, + _registered_method=True) + self.Write = channel.stream_stream( + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/Write', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.WriteRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.WriteResponse.FromString, + _registered_method=True) + self.CompleteRedirectUpload = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/CompleteRedirectUpload', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CompleteRedirectUploadRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CompleteRedirectUploadResponse.FromString, + _registered_method=True) + self.UploadPart = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/UploadPart', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.UploadPartRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.UploadPartResponse.FromString, + _registered_method=True) + self.CompleteMultipartUpload = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/CompleteMultipartUpload', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CompleteMultipartUploadRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CompleteMultipartUploadResponse.FromString, + _registered_method=True) + self.AbortMultipartUpload = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/AbortMultipartUpload', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.AbortMultipartUploadRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.AbortMultipartUploadResponse.FromString, + _registered_method=True) + self.Delete = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/Delete', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.DeleteRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.DeleteResponse.FromString, + _registered_method=True) + self.Copy = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/Copy', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CopyRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CopyResponse.FromString, + _registered_method=True) + self.Move = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/Move', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.MoveRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.MoveResponse.FromString, + _registered_method=True) + self.GetOptimisticLockingSupport = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/GetOptimisticLockingSupport', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.GetOptimisticLockingSupportRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.GetOptimisticLockingSupportResponse.FromString, + _registered_method=True) + + +class FileObjectServiceServicer(object): + """Missing associated documentation comment in .proto file.""" + + def Enumerate(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Stat(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Read(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ReadFromAddress(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def FetchWriteTypeInfo(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Write(self, request_iterator, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def CompleteRedirectUpload(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def UploadPart(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def CompleteMultipartUpload(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def AbortMultipartUpload(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Delete(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Copy(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Move(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetOptimisticLockingSupport(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_FileObjectServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'Enumerate': grpc.unary_stream_rpc_method_handler( + servicer.Enumerate, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.EnumerateRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.EnumerateResponse.SerializeToString, + ), + 'Stat': grpc.unary_unary_rpc_method_handler( + servicer.Stat, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.StatRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.StatResponse.SerializeToString, + ), + 'Read': grpc.unary_stream_rpc_method_handler( + servicer.Read, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.ReadRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.ReadResponse.SerializeToString, + ), + 'ReadFromAddress': grpc.unary_stream_rpc_method_handler( + servicer.ReadFromAddress, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.ReadFromAddressRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.ReadFromAddressResponse.SerializeToString, + ), + 'FetchWriteTypeInfo': grpc.unary_unary_rpc_method_handler( + servicer.FetchWriteTypeInfo, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.FetchWriteTypeInfoRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.FetchWriteTypeInfoResponse.SerializeToString, + ), + 'Write': grpc.stream_stream_rpc_method_handler( + servicer.Write, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.WriteRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.WriteResponse.SerializeToString, + ), + 'CompleteRedirectUpload': grpc.unary_unary_rpc_method_handler( + servicer.CompleteRedirectUpload, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CompleteRedirectUploadRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CompleteRedirectUploadResponse.SerializeToString, + ), + 'UploadPart': grpc.unary_unary_rpc_method_handler( + servicer.UploadPart, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.UploadPartRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.UploadPartResponse.SerializeToString, + ), + 'CompleteMultipartUpload': grpc.unary_unary_rpc_method_handler( + servicer.CompleteMultipartUpload, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CompleteMultipartUploadRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CompleteMultipartUploadResponse.SerializeToString, + ), + 'AbortMultipartUpload': grpc.unary_unary_rpc_method_handler( + servicer.AbortMultipartUpload, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.AbortMultipartUploadRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.AbortMultipartUploadResponse.SerializeToString, + ), + 'Delete': grpc.unary_unary_rpc_method_handler( + servicer.Delete, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.DeleteRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.DeleteResponse.SerializeToString, + ), + 'Copy': grpc.unary_unary_rpc_method_handler( + servicer.Copy, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CopyRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CopyResponse.SerializeToString, + ), + 'Move': grpc.unary_unary_rpc_method_handler( + servicer.Move, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.MoveRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.MoveResponse.SerializeToString, + ), + 'GetOptimisticLockingSupport': grpc.unary_unary_rpc_method_handler( + servicer.GetOptimisticLockingSupport, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.GetOptimisticLockingSupportRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.GetOptimisticLockingSupportResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class FileObjectService(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def Enumerate(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/Enumerate', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.EnumerateRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.EnumerateResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Stat(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/Stat', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.StatRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.StatResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Read(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/Read', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.ReadRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.ReadResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ReadFromAddress(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/ReadFromAddress', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.ReadFromAddressRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.ReadFromAddressResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def FetchWriteTypeInfo(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/FetchWriteTypeInfo', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.FetchWriteTypeInfoRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.FetchWriteTypeInfoResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Write(request_iterator, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.stream_stream( + request_iterator, + target, + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/Write', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.WriteRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.WriteResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def CompleteRedirectUpload(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/CompleteRedirectUpload', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CompleteRedirectUploadRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CompleteRedirectUploadResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def UploadPart(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/UploadPart', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.UploadPartRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.UploadPartResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def CompleteMultipartUpload(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/CompleteMultipartUpload', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CompleteMultipartUploadRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CompleteMultipartUploadResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def AbortMultipartUpload(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/AbortMultipartUpload', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.AbortMultipartUploadRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.AbortMultipartUploadResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Delete(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/Delete', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.DeleteRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.DeleteResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Copy(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/Copy', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CopyRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.CopyResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Move(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/Move', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.MoveRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.MoveResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetOptimisticLockingSupport(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1alpha.FileObjectService/GetOptimisticLockingSupport', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.GetOptimisticLockingSupportRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__service__pb2.GetOptimisticLockingSupportResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_pb2.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_pb2.py new file mode 100644 index 0000000000000000000000000000000000000000..92ebc4e1d8906101d1afd1fcf9bcddf2f4accb3d --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_pb2.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: nvidia/omniverse/storage/fileobject/v1beta/fileobject.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'nvidia/omniverse/storage/fileobject/v1beta/fileobject.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n;nvidia/omniverse/storage/fileobject/v1beta/fileobject.proto\x12*nvidia.omniverse.storage.fileobject.v1beta\x1a\x1fgoogle/protobuf/timestamp.proto\"\x16\n\x05\x43hunk\x12\r\n\x05\x63hunk\x18\x01 \x01(\x0c\"\x9c\x01\n\x08Metadata\x12\x1d\n\x10\x64\x61ta_object_size\x18\x01 \x01(\x04H\x00\x88\x01\x01\x12@\n\x17last_modified_timestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x01\x88\x01\x01\x42\x13\n\x11_data_object_sizeB\x1a\n\x18_last_modified_timestamp\"%\n\x06Header\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\"\x8b\x01\n\x08Redirect\x12\x1b\n\x13redirect_target_url\x18\x01 \x01(\t\x12\x12\n\x06method\x18\x02 \x01(\tB\x02\x18\x01\x12N\n\x12\x61\x64\x64itional_headers\x18\x03 \x03(\x0b\x32\x32.nvidia.omniverse.storage.fileobject.v1beta.Header\"o\n\x0b\x41\x64\x64ressInfo\x12\x18\n\x10resource_address\x18\x01 \x01(\t\x12\x46\n\x08metadata\x18\x02 \x01(\x0b\x32\x34.nvidia.omniverse.storage.fileobject.v1beta.Metadata\"\xaf\x01\n\x0cResourceInfo\x12W\n\x11resource_identity\x18\x01 \x01(\x0b\x32<.nvidia.omniverse.storage.fileobject.v1beta.ResourceIdentity\x12\x46\n\x08metadata\x18\x02 \x01(\x0b\x32\x34.nvidia.omniverse.storage.fileobject.v1beta.Metadata\",\n\x10ResourceIdentity\x12\x18\n\x10\x65ncoded_identity\x18\x01 \x01(\tB\x82\x01\n.com.nvidia.omniverse.storage.fileobject.v1betaB\x0f\x46ileobjectProtoP\x01Z=pb.api.nvidia.com/omniverse/storage/fileobject/v1beta;storageb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nvidia.omniverse.storage.fileobject.v1beta.fileobject_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n.com.nvidia.omniverse.storage.fileobject.v1betaB\017FileobjectProtoP\001Z=pb.api.nvidia.com/omniverse/storage/fileobject/v1beta;storage' + _globals['_REDIRECT'].fields_by_name['method']._loaded_options = None + _globals['_REDIRECT'].fields_by_name['method']._serialized_options = b'\030\001' + _globals['_CHUNK']._serialized_start=140 + _globals['_CHUNK']._serialized_end=162 + _globals['_METADATA']._serialized_start=165 + _globals['_METADATA']._serialized_end=321 + _globals['_HEADER']._serialized_start=323 + _globals['_HEADER']._serialized_end=360 + _globals['_REDIRECT']._serialized_start=363 + _globals['_REDIRECT']._serialized_end=502 + _globals['_ADDRESSINFO']._serialized_start=504 + _globals['_ADDRESSINFO']._serialized_end=615 + _globals['_RESOURCEINFO']._serialized_start=618 + _globals['_RESOURCEINFO']._serialized_end=793 + _globals['_RESOURCEIDENTITY']._serialized_start=795 + _globals['_RESOURCEIDENTITY']._serialized_end=839 +# @@protoc_insertion_point(module_scope) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_pb2.pyi b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_pb2.pyi new file mode 100644 index 0000000000000000000000000000000000000000..89157c2f0df4683b31f7ec6e213dc14edd957582 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_pb2.pyi @@ -0,0 +1,64 @@ +import datetime + +from google.protobuf import timestamp_pb2 as _timestamp_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class Chunk(_message.Message): + __slots__ = ("chunk",) + CHUNK_FIELD_NUMBER: _ClassVar[int] + chunk: bytes + def __init__(self, chunk: _Optional[bytes] = ...) -> None: ... + +class Metadata(_message.Message): + __slots__ = ("data_object_size", "last_modified_timestamp") + DATA_OBJECT_SIZE_FIELD_NUMBER: _ClassVar[int] + LAST_MODIFIED_TIMESTAMP_FIELD_NUMBER: _ClassVar[int] + data_object_size: int + last_modified_timestamp: _timestamp_pb2.Timestamp + def __init__(self, data_object_size: _Optional[int] = ..., last_modified_timestamp: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ...) -> None: ... + +class Header(_message.Message): + __slots__ = ("name", "value") + NAME_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + name: str + value: str + def __init__(self, name: _Optional[str] = ..., value: _Optional[str] = ...) -> None: ... + +class Redirect(_message.Message): + __slots__ = ("redirect_target_url", "method", "additional_headers") + REDIRECT_TARGET_URL_FIELD_NUMBER: _ClassVar[int] + METHOD_FIELD_NUMBER: _ClassVar[int] + ADDITIONAL_HEADERS_FIELD_NUMBER: _ClassVar[int] + redirect_target_url: str + method: str + additional_headers: _containers.RepeatedCompositeFieldContainer[Header] + def __init__(self, redirect_target_url: _Optional[str] = ..., method: _Optional[str] = ..., additional_headers: _Optional[_Iterable[_Union[Header, _Mapping]]] = ...) -> None: ... + +class AddressInfo(_message.Message): + __slots__ = ("resource_address", "metadata") + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + METADATA_FIELD_NUMBER: _ClassVar[int] + resource_address: str + metadata: Metadata + def __init__(self, resource_address: _Optional[str] = ..., metadata: _Optional[_Union[Metadata, _Mapping]] = ...) -> None: ... + +class ResourceInfo(_message.Message): + __slots__ = ("resource_identity", "metadata") + RESOURCE_IDENTITY_FIELD_NUMBER: _ClassVar[int] + METADATA_FIELD_NUMBER: _ClassVar[int] + resource_identity: ResourceIdentity + metadata: Metadata + def __init__(self, resource_identity: _Optional[_Union[ResourceIdentity, _Mapping]] = ..., metadata: _Optional[_Union[Metadata, _Mapping]] = ...) -> None: ... + +class ResourceIdentity(_message.Message): + __slots__ = ("encoded_identity",) + ENCODED_IDENTITY_FIELD_NUMBER: _ClassVar[int] + encoded_identity: str + def __init__(self, encoded_identity: _Optional[str] = ...) -> None: ... diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_pb2_grpc.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_pb2_grpc.py new file mode 100644 index 0000000000000000000000000000000000000000..627e7f9706c0948fcf785e4c435cb60a6c7fd61e --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_pb2_grpc.py @@ -0,0 +1,24 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + + +GRPC_GENERATED_VERSION = '1.80.0' +GRPC_VERSION = grpc.__version__ +_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: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in nvidia/omniverse/storage/fileobject/v1beta/fileobject_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}.' + ) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_service_pb2.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_service_pb2.py new file mode 100644 index 0000000000000000000000000000000000000000..eea7fec5877a5550cef8b1f66a6575d911579dce --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_service_pb2.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: nvidia/omniverse/storage/fileobject/v1beta/fileobject_service.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'nvidia/omniverse/storage/fileobject/v1beta/fileobject_service.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from nvidia.omniverse.storage.fileobject.v1beta import fileobject_pb2 as nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\nCnvidia/omniverse/storage/fileobject/v1beta/fileobject_service.proto\x12*nvidia.omniverse.storage.fileobject.v1beta\x1a;nvidia/omniverse/storage/fileobject/v1beta/fileobject.proto\",\n\x10\x45numerateRequest\x12\x18\n\x10resource_address\x18\x01 \x01(\t\"[\n\x11\x45numerateResponse\x12\x46\n\x05items\x18\x01 \x03(\x0b\x32\x37.nvidia.omniverse.storage.fileobject.v1beta.AddressInfo\"\'\n\x0bStatRequest\x12\x18\n\x10resource_address\x18\x01 \x01(\t\"_\n\x0cStatResponse\x12O\n\rresource_info\x18\x01 \x01(\x0b\x32\x38.nvidia.omniverse.storage.fileobject.v1beta.ResourceInfo\"\xe0\x01\n\x0bReadRequest\x12W\n\x11resource_identity\x18\x01 \x01(\x0b\x32<.nvidia.omniverse.storage.fileobject.v1beta.ResourceIdentity\x12`\n\x13\x64ownload_preference\x18\x02 \x01(\x0e\x32>.nvidia.omniverse.storage.fileobject.v1beta.DownloadPreferenceH\x00\x88\x01\x01\x42\x16\n\x14_download_preference\"\xf4\x01\n\x0cReadResponse\x12H\n\x08metadata\x18\x01 \x01(\x0b\x32\x34.nvidia.omniverse.storage.fileobject.v1beta.MetadataH\x00\x12\x42\n\x05\x63hunk\x18\x02 \x01(\x0b\x32\x31.nvidia.omniverse.storage.fileobject.v1beta.ChunkH\x00\x12H\n\x08redirect\x18\x03 \x01(\x0b\x32\x34.nvidia.omniverse.storage.fileobject.v1beta.RedirectH\x00\x42\x0c\n\nreply_type\"\xac\x01\n\x16ReadFromAddressRequest\x12\x18\n\x10resource_address\x18\x01 \x01(\t\x12`\n\x13\x64ownload_preference\x18\x02 \x01(\x0e\x32>.nvidia.omniverse.storage.fileobject.v1beta.DownloadPreferenceH\x00\x88\x01\x01\x42\x16\n\x14_download_preference\"\x88\x02\n\x17ReadFromAddressResponse\x12Q\n\rresource_info\x18\x01 \x01(\x0b\x32\x38.nvidia.omniverse.storage.fileobject.v1beta.ResourceInfoH\x00\x12\x42\n\x05\x63hunk\x18\x02 \x01(\x0b\x32\x31.nvidia.omniverse.storage.fileobject.v1beta.ChunkH\x00\x12H\n\x08redirect\x18\x03 \x01(\x0b\x32\x34.nvidia.omniverse.storage.fileobject.v1beta.RedirectH\x00\x42\x0c\n\nreply_type\"A\n\x19\x46\x65tchWriteTypeInfoRequest\x12$\n\x1c\x64\x65stination_resource_address\x18\x01 \x01(\t\"\xbd\x01\n\x18WriteTypeForSizeInterval\x12 \n\x18minimum_data_object_size\x18\x01 \x01(\x04\x12 \n\x18maximum_data_object_size\x18\x02 \x01(\x04\x12]\n\x17preferred_upload_method\x18\x03 \x01(\x0e\x32<.nvidia.omniverse.storage.fileobject.v1beta.UploadPreference\"\x80\x01\n\x1a\x46\x65tchWriteTypeInfoResponse\x12\x62\n\x14write_type_intervals\x18\x01 \x03(\x0b\x32\x44.nvidia.omniverse.storage.fileobject.v1beta.WriteTypeForSizeInterval\"\xb7\x01\n\x0cWriteRequest\x12M\n\x06params\x18\x01 \x01(\x0b\x32;.nvidia.omniverse.storage.fileobject.v1beta.WriteParametersH\x00\x12\x42\n\x05\x63hunk\x18\x02 \x01(\x0b\x32\x31.nvidia.omniverse.storage.fileobject.v1beta.ChunkH\x00\x42\x14\n\x12write_request_type\"\xb7\x02\n\x0fWriteParameters\x12$\n\x1c\x64\x65stination_resource_address\x18\x01 \x01(\t\x12[\n\x10previous_version\x18\x02 \x01(\x0b\x32<.nvidia.omniverse.storage.fileobject.v1beta.ResourceIdentityH\x00\x88\x01\x01\x12\x18\n\x10\x64\x61ta_object_size\x18\x03 \x01(\x04\x12\\\n\x11upload_preference\x18\x04 \x01(\x0e\x32<.nvidia.omniverse.storage.fileobject.v1beta.UploadPreferenceH\x01\x88\x01\x01\x42\x13\n\x11_previous_versionB\x14\n\x12_upload_preference\"\xf1\x01\n\x17WriteRedirectProperties\x12\x1b\n\x13redirect_target_url\x18\x01 \x01(\t\x12H\n\x06method\x18\x02 \x01(\x0e\x32\x38.nvidia.omniverse.storage.fileobject.v1beta.UploadMethod\x12N\n\x12\x61\x64\x64itional_headers\x18\x03 \x03(\x0b\x32\x32.nvidia.omniverse.storage.fileobject.v1beta.Header\x12\x1f\n\x17\x63ompletion_header_names\x18\x04 \x03(\t\"\x15\n\x13WriteChunksAccepted\"\xa1\x03\n\rWriteResponse\x12`\n\x15write_chunks_accepted\x18\x01 \x01(\x0b\x32?.nvidia.omniverse.storage.fileobject.v1beta.WriteChunksAcceptedH\x00\x12Q\n\rresource_info\x18\x02 \x01(\x0b\x32\x38.nvidia.omniverse.storage.fileobject.v1beta.ResourceInfoH\x00\x12]\n\x0ewrite_redirect\x18\x03 \x01(\x0b\x32\x43.nvidia.omniverse.storage.fileobject.v1beta.WriteRedirectPropertiesH\x00\x12\x65\n\x10multipart_upload\x18\x04 \x01(\x0b\x32I.nvidia.omniverse.storage.fileobject.v1beta.CreateMultipartUploadResponseH\x00\x42\x15\n\x13write_response_type\"\x95\x01\n\x1d\x43ompleteRedirectUploadRequest\x12$\n\x1c\x64\x65stination_resource_address\x18\x01 \x01(\t\x12N\n\x12\x61\x64\x64itional_headers\x18\x02 \x03(\x0b\x32\x32.nvidia.omniverse.storage.fileobject.v1beta.Header\"q\n\x1e\x43ompleteRedirectUploadResponse\x12O\n\rresource_info\x18\x01 \x01(\x0b\x32\x38.nvidia.omniverse.storage.fileobject.v1beta.ResourceInfo\"\xd2\x02\n\x1d\x43reateMultipartUploadResponse\x12\x11\n\tupload_id\x18\x01 \x01(\t\x12\x66\n\x19\x66irst_part_write_redirect\x18\x02 \x01(\x0b\x32\x43.nvidia.omniverse.storage.fileobject.v1beta.WriteRedirectProperties\x12!\n\x14maximum_parts_number\x18\x03 \x01(\rH\x00\x88\x01\x01\x12\"\n\x15minimum_size_per_part\x18\x04 \x01(\x04H\x01\x88\x01\x01\x12\"\n\x15maximum_size_per_part\x18\x05 \x01(\x04H\x02\x88\x01\x01\x42\x17\n\x15_maximum_parts_numberB\x18\n\x16_minimum_size_per_partB\x18\n\x16_maximum_size_per_part\"\x89\x01\n\x11UploadPartRequest\x12\x11\n\tupload_id\x18\x01 \x01(\t\x12$\n\x1c\x64\x65stination_resource_address\x18\x02 \x01(\t\x12\x13\n\x0bpart_number\x18\x03 \x01(\r\x12\x17\n\npart_count\x18\x04 \x01(\rH\x00\x88\x01\x01\x42\r\n\x0b_part_count\"w\n\x12UploadPartResponse\x12\x61\n\x14part_write_redirects\x18\x01 \x03(\x0b\x32\x43.nvidia.omniverse.storage.fileobject.v1beta.WriteRedirectProperties\"o\n\x13\x43ompletedUploadPart\x12\x13\n\x0bpart_number\x18\x01 \x01(\r\x12\x43\n\x07headers\x18\x02 \x03(\x0b\x32\x32.nvidia.omniverse.storage.fileobject.v1beta.Header\"\xa9\x01\n\x1e\x43ompleteMultipartUploadRequest\x12\x11\n\tupload_id\x18\x01 \x01(\t\x12$\n\x1c\x64\x65stination_resource_address\x18\x02 \x01(\t\x12N\n\x05parts\x18\x03 \x03(\x0b\x32?.nvidia.omniverse.storage.fileobject.v1beta.CompletedUploadPart\"r\n\x1f\x43ompleteMultipartUploadResponse\x12O\n\rresource_info\x18\x01 \x01(\x0b\x32\x38.nvidia.omniverse.storage.fileobject.v1beta.ResourceInfo\"V\n\x1b\x41\x62ortMultipartUploadRequest\x12\x11\n\tupload_id\x18\x01 \x01(\t\x12$\n\x1c\x64\x65stination_resource_address\x18\x02 \x01(\t\"\x1e\n\x1c\x41\x62ortMultipartUploadResponse\"\x9b\x01\n\rDeleteRequest\x12\x18\n\x10resource_address\x18\x01 \x01(\t\x12[\n\x10previous_version\x18\x02 \x01(\x0b\x32<.nvidia.omniverse.storage.fileobject.v1beta.ResourceIdentityH\x00\x88\x01\x01\x42\x13\n\x11_previous_version\"\x10\n\x0e\x44\x65leteResponse*y\n\x12\x44ownloadPreference\x12#\n\x1f\x44OWNLOAD_PREFERENCE_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x44OWNLOAD_PREFERENCE_BODY\x10\x01\x12 \n\x1c\x44OWNLOAD_PREFERENCE_REDIRECT\x10\x02*\x92\x01\n\x10UploadPreference\x12!\n\x1dUPLOAD_PREFERENCE_UNSPECIFIED\x10\x00\x12\x1a\n\x16UPLOAD_PREFERENCE_BODY\x10\x01\x12\x1e\n\x1aUPLOAD_PREFERENCE_REDIRECT\x10\x02\x12\x1f\n\x1bUPLOAD_PREFERENCE_MULTIPART\x10\x03*\\\n\x0cUploadMethod\x12\x1d\n\x19UPLOAD_METHOD_UNSPECIFIED\x10\x00\x12\x16\n\x12UPLOAD_METHOD_POST\x10\x01\x12\x15\n\x11UPLOAD_METHOD_PUT\x10\x02\x32\x82\r\n\x11\x46ileObjectService\x12\x8a\x01\n\tEnumerate\x12<.nvidia.omniverse.storage.fileobject.v1beta.EnumerateRequest\x1a=.nvidia.omniverse.storage.fileobject.v1beta.EnumerateResponse0\x01\x12y\n\x04Stat\x12\x37.nvidia.omniverse.storage.fileobject.v1beta.StatRequest\x1a\x38.nvidia.omniverse.storage.fileobject.v1beta.StatResponse\x12{\n\x04Read\x12\x37.nvidia.omniverse.storage.fileobject.v1beta.ReadRequest\x1a\x38.nvidia.omniverse.storage.fileobject.v1beta.ReadResponse0\x01\x12\x9c\x01\n\x0fReadFromAddress\x12\x42.nvidia.omniverse.storage.fileobject.v1beta.ReadFromAddressRequest\x1a\x43.nvidia.omniverse.storage.fileobject.v1beta.ReadFromAddressResponse0\x01\x12\xa3\x01\n\x12\x46\x65tchWriteTypeInfo\x12\x45.nvidia.omniverse.storage.fileobject.v1beta.FetchWriteTypeInfoRequest\x1a\x46.nvidia.omniverse.storage.fileobject.v1beta.FetchWriteTypeInfoResponse\x12\x80\x01\n\x05Write\x12\x38.nvidia.omniverse.storage.fileobject.v1beta.WriteRequest\x1a\x39.nvidia.omniverse.storage.fileobject.v1beta.WriteResponse(\x01\x30\x01\x12\xaf\x01\n\x16\x43ompleteRedirectUpload\x12I.nvidia.omniverse.storage.fileobject.v1beta.CompleteRedirectUploadRequest\x1aJ.nvidia.omniverse.storage.fileobject.v1beta.CompleteRedirectUploadResponse\x12\x8b\x01\n\nUploadPart\x12=.nvidia.omniverse.storage.fileobject.v1beta.UploadPartRequest\x1a>.nvidia.omniverse.storage.fileobject.v1beta.UploadPartResponse\x12\xb2\x01\n\x17\x43ompleteMultipartUpload\x12J.nvidia.omniverse.storage.fileobject.v1beta.CompleteMultipartUploadRequest\x1aK.nvidia.omniverse.storage.fileobject.v1beta.CompleteMultipartUploadResponse\x12\xa9\x01\n\x14\x41\x62ortMultipartUpload\x12G.nvidia.omniverse.storage.fileobject.v1beta.AbortMultipartUploadRequest\x1aH.nvidia.omniverse.storage.fileobject.v1beta.AbortMultipartUploadResponse\x12\x7f\n\x06\x44\x65lete\x12\x39.nvidia.omniverse.storage.fileobject.v1beta.DeleteRequest\x1a:.nvidia.omniverse.storage.fileobject.v1beta.DeleteResponseB\x89\x01\n.com.nvidia.omniverse.storage.fileobject.v1betaB\x16\x46ileobjectServiceProtoP\x01Z=pb.api.nvidia.com/omniverse/storage/fileobject/v1beta;storageb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nvidia.omniverse.storage.fileobject.v1beta.fileobject_service_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n.com.nvidia.omniverse.storage.fileobject.v1betaB\026FileobjectServiceProtoP\001Z=pb.api.nvidia.com/omniverse/storage/fileobject/v1beta;storage' + _globals['_DOWNLOADPREFERENCE']._serialized_start=4512 + _globals['_DOWNLOADPREFERENCE']._serialized_end=4633 + _globals['_UPLOADPREFERENCE']._serialized_start=4636 + _globals['_UPLOADPREFERENCE']._serialized_end=4782 + _globals['_UPLOADMETHOD']._serialized_start=4784 + _globals['_UPLOADMETHOD']._serialized_end=4876 + _globals['_ENUMERATEREQUEST']._serialized_start=176 + _globals['_ENUMERATEREQUEST']._serialized_end=220 + _globals['_ENUMERATERESPONSE']._serialized_start=222 + _globals['_ENUMERATERESPONSE']._serialized_end=313 + _globals['_STATREQUEST']._serialized_start=315 + _globals['_STATREQUEST']._serialized_end=354 + _globals['_STATRESPONSE']._serialized_start=356 + _globals['_STATRESPONSE']._serialized_end=451 + _globals['_READREQUEST']._serialized_start=454 + _globals['_READREQUEST']._serialized_end=678 + _globals['_READRESPONSE']._serialized_start=681 + _globals['_READRESPONSE']._serialized_end=925 + _globals['_READFROMADDRESSREQUEST']._serialized_start=928 + _globals['_READFROMADDRESSREQUEST']._serialized_end=1100 + _globals['_READFROMADDRESSRESPONSE']._serialized_start=1103 + _globals['_READFROMADDRESSRESPONSE']._serialized_end=1367 + _globals['_FETCHWRITETYPEINFOREQUEST']._serialized_start=1369 + _globals['_FETCHWRITETYPEINFOREQUEST']._serialized_end=1434 + _globals['_WRITETYPEFORSIZEINTERVAL']._serialized_start=1437 + _globals['_WRITETYPEFORSIZEINTERVAL']._serialized_end=1626 + _globals['_FETCHWRITETYPEINFORESPONSE']._serialized_start=1629 + _globals['_FETCHWRITETYPEINFORESPONSE']._serialized_end=1757 + _globals['_WRITEREQUEST']._serialized_start=1760 + _globals['_WRITEREQUEST']._serialized_end=1943 + _globals['_WRITEPARAMETERS']._serialized_start=1946 + _globals['_WRITEPARAMETERS']._serialized_end=2257 + _globals['_WRITEREDIRECTPROPERTIES']._serialized_start=2260 + _globals['_WRITEREDIRECTPROPERTIES']._serialized_end=2501 + _globals['_WRITECHUNKSACCEPTED']._serialized_start=2503 + _globals['_WRITECHUNKSACCEPTED']._serialized_end=2524 + _globals['_WRITERESPONSE']._serialized_start=2527 + _globals['_WRITERESPONSE']._serialized_end=2944 + _globals['_COMPLETEREDIRECTUPLOADREQUEST']._serialized_start=2947 + _globals['_COMPLETEREDIRECTUPLOADREQUEST']._serialized_end=3096 + _globals['_COMPLETEREDIRECTUPLOADRESPONSE']._serialized_start=3098 + _globals['_COMPLETEREDIRECTUPLOADRESPONSE']._serialized_end=3211 + _globals['_CREATEMULTIPARTUPLOADRESPONSE']._serialized_start=3214 + _globals['_CREATEMULTIPARTUPLOADRESPONSE']._serialized_end=3552 + _globals['_UPLOADPARTREQUEST']._serialized_start=3555 + _globals['_UPLOADPARTREQUEST']._serialized_end=3692 + _globals['_UPLOADPARTRESPONSE']._serialized_start=3694 + _globals['_UPLOADPARTRESPONSE']._serialized_end=3813 + _globals['_COMPLETEDUPLOADPART']._serialized_start=3815 + _globals['_COMPLETEDUPLOADPART']._serialized_end=3926 + _globals['_COMPLETEMULTIPARTUPLOADREQUEST']._serialized_start=3929 + _globals['_COMPLETEMULTIPARTUPLOADREQUEST']._serialized_end=4098 + _globals['_COMPLETEMULTIPARTUPLOADRESPONSE']._serialized_start=4100 + _globals['_COMPLETEMULTIPARTUPLOADRESPONSE']._serialized_end=4214 + _globals['_ABORTMULTIPARTUPLOADREQUEST']._serialized_start=4216 + _globals['_ABORTMULTIPARTUPLOADREQUEST']._serialized_end=4302 + _globals['_ABORTMULTIPARTUPLOADRESPONSE']._serialized_start=4304 + _globals['_ABORTMULTIPARTUPLOADRESPONSE']._serialized_end=4334 + _globals['_DELETEREQUEST']._serialized_start=4337 + _globals['_DELETEREQUEST']._serialized_end=4492 + _globals['_DELETERESPONSE']._serialized_start=4494 + _globals['_DELETERESPONSE']._serialized_end=4510 + _globals['_FILEOBJECTSERVICE']._serialized_start=4879 + _globals['_FILEOBJECTSERVICE']._serialized_end=6545 +# @@protoc_insertion_point(module_scope) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_service_pb2.pyi b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_service_pb2.pyi new file mode 100644 index 0000000000000000000000000000000000000000..0521608aea94ca055391a1d8b4e54165b33e097c --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_service_pb2.pyi @@ -0,0 +1,262 @@ +from nvidia.omniverse.storage.fileobject.v1beta import fileobject_pb2 as _fileobject_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class DownloadPreference(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + DOWNLOAD_PREFERENCE_UNSPECIFIED: _ClassVar[DownloadPreference] + DOWNLOAD_PREFERENCE_BODY: _ClassVar[DownloadPreference] + DOWNLOAD_PREFERENCE_REDIRECT: _ClassVar[DownloadPreference] + +class UploadPreference(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + UPLOAD_PREFERENCE_UNSPECIFIED: _ClassVar[UploadPreference] + UPLOAD_PREFERENCE_BODY: _ClassVar[UploadPreference] + UPLOAD_PREFERENCE_REDIRECT: _ClassVar[UploadPreference] + UPLOAD_PREFERENCE_MULTIPART: _ClassVar[UploadPreference] + +class UploadMethod(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + UPLOAD_METHOD_UNSPECIFIED: _ClassVar[UploadMethod] + UPLOAD_METHOD_POST: _ClassVar[UploadMethod] + UPLOAD_METHOD_PUT: _ClassVar[UploadMethod] +DOWNLOAD_PREFERENCE_UNSPECIFIED: DownloadPreference +DOWNLOAD_PREFERENCE_BODY: DownloadPreference +DOWNLOAD_PREFERENCE_REDIRECT: DownloadPreference +UPLOAD_PREFERENCE_UNSPECIFIED: UploadPreference +UPLOAD_PREFERENCE_BODY: UploadPreference +UPLOAD_PREFERENCE_REDIRECT: UploadPreference +UPLOAD_PREFERENCE_MULTIPART: UploadPreference +UPLOAD_METHOD_UNSPECIFIED: UploadMethod +UPLOAD_METHOD_POST: UploadMethod +UPLOAD_METHOD_PUT: UploadMethod + +class EnumerateRequest(_message.Message): + __slots__ = ("resource_address",) + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + resource_address: str + def __init__(self, resource_address: _Optional[str] = ...) -> None: ... + +class EnumerateResponse(_message.Message): + __slots__ = ("items",) + ITEMS_FIELD_NUMBER: _ClassVar[int] + items: _containers.RepeatedCompositeFieldContainer[_fileobject_pb2.AddressInfo] + def __init__(self, items: _Optional[_Iterable[_Union[_fileobject_pb2.AddressInfo, _Mapping]]] = ...) -> None: ... + +class StatRequest(_message.Message): + __slots__ = ("resource_address",) + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + resource_address: str + def __init__(self, resource_address: _Optional[str] = ...) -> None: ... + +class StatResponse(_message.Message): + __slots__ = ("resource_info",) + RESOURCE_INFO_FIELD_NUMBER: _ClassVar[int] + resource_info: _fileobject_pb2.ResourceInfo + def __init__(self, resource_info: _Optional[_Union[_fileobject_pb2.ResourceInfo, _Mapping]] = ...) -> None: ... + +class ReadRequest(_message.Message): + __slots__ = ("resource_identity", "download_preference") + RESOURCE_IDENTITY_FIELD_NUMBER: _ClassVar[int] + DOWNLOAD_PREFERENCE_FIELD_NUMBER: _ClassVar[int] + resource_identity: _fileobject_pb2.ResourceIdentity + download_preference: DownloadPreference + def __init__(self, resource_identity: _Optional[_Union[_fileobject_pb2.ResourceIdentity, _Mapping]] = ..., download_preference: _Optional[_Union[DownloadPreference, str]] = ...) -> None: ... + +class ReadResponse(_message.Message): + __slots__ = ("metadata", "chunk", "redirect") + METADATA_FIELD_NUMBER: _ClassVar[int] + CHUNK_FIELD_NUMBER: _ClassVar[int] + REDIRECT_FIELD_NUMBER: _ClassVar[int] + metadata: _fileobject_pb2.Metadata + chunk: _fileobject_pb2.Chunk + redirect: _fileobject_pb2.Redirect + def __init__(self, metadata: _Optional[_Union[_fileobject_pb2.Metadata, _Mapping]] = ..., chunk: _Optional[_Union[_fileobject_pb2.Chunk, _Mapping]] = ..., redirect: _Optional[_Union[_fileobject_pb2.Redirect, _Mapping]] = ...) -> None: ... + +class ReadFromAddressRequest(_message.Message): + __slots__ = ("resource_address", "download_preference") + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + DOWNLOAD_PREFERENCE_FIELD_NUMBER: _ClassVar[int] + resource_address: str + download_preference: DownloadPreference + def __init__(self, resource_address: _Optional[str] = ..., download_preference: _Optional[_Union[DownloadPreference, str]] = ...) -> None: ... + +class ReadFromAddressResponse(_message.Message): + __slots__ = ("resource_info", "chunk", "redirect") + RESOURCE_INFO_FIELD_NUMBER: _ClassVar[int] + CHUNK_FIELD_NUMBER: _ClassVar[int] + REDIRECT_FIELD_NUMBER: _ClassVar[int] + resource_info: _fileobject_pb2.ResourceInfo + chunk: _fileobject_pb2.Chunk + redirect: _fileobject_pb2.Redirect + def __init__(self, resource_info: _Optional[_Union[_fileobject_pb2.ResourceInfo, _Mapping]] = ..., chunk: _Optional[_Union[_fileobject_pb2.Chunk, _Mapping]] = ..., redirect: _Optional[_Union[_fileobject_pb2.Redirect, _Mapping]] = ...) -> None: ... + +class FetchWriteTypeInfoRequest(_message.Message): + __slots__ = ("destination_resource_address",) + DESTINATION_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + destination_resource_address: str + def __init__(self, destination_resource_address: _Optional[str] = ...) -> None: ... + +class WriteTypeForSizeInterval(_message.Message): + __slots__ = ("minimum_data_object_size", "maximum_data_object_size", "preferred_upload_method") + MINIMUM_DATA_OBJECT_SIZE_FIELD_NUMBER: _ClassVar[int] + MAXIMUM_DATA_OBJECT_SIZE_FIELD_NUMBER: _ClassVar[int] + PREFERRED_UPLOAD_METHOD_FIELD_NUMBER: _ClassVar[int] + minimum_data_object_size: int + maximum_data_object_size: int + preferred_upload_method: UploadPreference + def __init__(self, minimum_data_object_size: _Optional[int] = ..., maximum_data_object_size: _Optional[int] = ..., preferred_upload_method: _Optional[_Union[UploadPreference, str]] = ...) -> None: ... + +class FetchWriteTypeInfoResponse(_message.Message): + __slots__ = ("write_type_intervals",) + WRITE_TYPE_INTERVALS_FIELD_NUMBER: _ClassVar[int] + write_type_intervals: _containers.RepeatedCompositeFieldContainer[WriteTypeForSizeInterval] + def __init__(self, write_type_intervals: _Optional[_Iterable[_Union[WriteTypeForSizeInterval, _Mapping]]] = ...) -> None: ... + +class WriteRequest(_message.Message): + __slots__ = ("params", "chunk") + PARAMS_FIELD_NUMBER: _ClassVar[int] + CHUNK_FIELD_NUMBER: _ClassVar[int] + params: WriteParameters + chunk: _fileobject_pb2.Chunk + def __init__(self, params: _Optional[_Union[WriteParameters, _Mapping]] = ..., chunk: _Optional[_Union[_fileobject_pb2.Chunk, _Mapping]] = ...) -> None: ... + +class WriteParameters(_message.Message): + __slots__ = ("destination_resource_address", "previous_version", "data_object_size", "upload_preference") + DESTINATION_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + PREVIOUS_VERSION_FIELD_NUMBER: _ClassVar[int] + DATA_OBJECT_SIZE_FIELD_NUMBER: _ClassVar[int] + UPLOAD_PREFERENCE_FIELD_NUMBER: _ClassVar[int] + destination_resource_address: str + previous_version: _fileobject_pb2.ResourceIdentity + data_object_size: int + upload_preference: UploadPreference + def __init__(self, destination_resource_address: _Optional[str] = ..., previous_version: _Optional[_Union[_fileobject_pb2.ResourceIdentity, _Mapping]] = ..., data_object_size: _Optional[int] = ..., upload_preference: _Optional[_Union[UploadPreference, str]] = ...) -> None: ... + +class WriteRedirectProperties(_message.Message): + __slots__ = ("redirect_target_url", "method", "additional_headers", "completion_header_names") + REDIRECT_TARGET_URL_FIELD_NUMBER: _ClassVar[int] + METHOD_FIELD_NUMBER: _ClassVar[int] + ADDITIONAL_HEADERS_FIELD_NUMBER: _ClassVar[int] + COMPLETION_HEADER_NAMES_FIELD_NUMBER: _ClassVar[int] + redirect_target_url: str + method: UploadMethod + additional_headers: _containers.RepeatedCompositeFieldContainer[_fileobject_pb2.Header] + completion_header_names: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, redirect_target_url: _Optional[str] = ..., method: _Optional[_Union[UploadMethod, str]] = ..., additional_headers: _Optional[_Iterable[_Union[_fileobject_pb2.Header, _Mapping]]] = ..., completion_header_names: _Optional[_Iterable[str]] = ...) -> None: ... + +class WriteChunksAccepted(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class WriteResponse(_message.Message): + __slots__ = ("write_chunks_accepted", "resource_info", "write_redirect", "multipart_upload") + WRITE_CHUNKS_ACCEPTED_FIELD_NUMBER: _ClassVar[int] + RESOURCE_INFO_FIELD_NUMBER: _ClassVar[int] + WRITE_REDIRECT_FIELD_NUMBER: _ClassVar[int] + MULTIPART_UPLOAD_FIELD_NUMBER: _ClassVar[int] + write_chunks_accepted: WriteChunksAccepted + resource_info: _fileobject_pb2.ResourceInfo + write_redirect: WriteRedirectProperties + multipart_upload: CreateMultipartUploadResponse + def __init__(self, write_chunks_accepted: _Optional[_Union[WriteChunksAccepted, _Mapping]] = ..., resource_info: _Optional[_Union[_fileobject_pb2.ResourceInfo, _Mapping]] = ..., write_redirect: _Optional[_Union[WriteRedirectProperties, _Mapping]] = ..., multipart_upload: _Optional[_Union[CreateMultipartUploadResponse, _Mapping]] = ...) -> None: ... + +class CompleteRedirectUploadRequest(_message.Message): + __slots__ = ("destination_resource_address", "additional_headers") + DESTINATION_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + ADDITIONAL_HEADERS_FIELD_NUMBER: _ClassVar[int] + destination_resource_address: str + additional_headers: _containers.RepeatedCompositeFieldContainer[_fileobject_pb2.Header] + def __init__(self, destination_resource_address: _Optional[str] = ..., additional_headers: _Optional[_Iterable[_Union[_fileobject_pb2.Header, _Mapping]]] = ...) -> None: ... + +class CompleteRedirectUploadResponse(_message.Message): + __slots__ = ("resource_info",) + RESOURCE_INFO_FIELD_NUMBER: _ClassVar[int] + resource_info: _fileobject_pb2.ResourceInfo + def __init__(self, resource_info: _Optional[_Union[_fileobject_pb2.ResourceInfo, _Mapping]] = ...) -> None: ... + +class CreateMultipartUploadResponse(_message.Message): + __slots__ = ("upload_id", "first_part_write_redirect", "maximum_parts_number", "minimum_size_per_part", "maximum_size_per_part") + UPLOAD_ID_FIELD_NUMBER: _ClassVar[int] + FIRST_PART_WRITE_REDIRECT_FIELD_NUMBER: _ClassVar[int] + MAXIMUM_PARTS_NUMBER_FIELD_NUMBER: _ClassVar[int] + MINIMUM_SIZE_PER_PART_FIELD_NUMBER: _ClassVar[int] + MAXIMUM_SIZE_PER_PART_FIELD_NUMBER: _ClassVar[int] + upload_id: str + first_part_write_redirect: WriteRedirectProperties + maximum_parts_number: int + minimum_size_per_part: int + maximum_size_per_part: int + def __init__(self, upload_id: _Optional[str] = ..., first_part_write_redirect: _Optional[_Union[WriteRedirectProperties, _Mapping]] = ..., maximum_parts_number: _Optional[int] = ..., minimum_size_per_part: _Optional[int] = ..., maximum_size_per_part: _Optional[int] = ...) -> None: ... + +class UploadPartRequest(_message.Message): + __slots__ = ("upload_id", "destination_resource_address", "part_number", "part_count") + UPLOAD_ID_FIELD_NUMBER: _ClassVar[int] + DESTINATION_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + PART_NUMBER_FIELD_NUMBER: _ClassVar[int] + PART_COUNT_FIELD_NUMBER: _ClassVar[int] + upload_id: str + destination_resource_address: str + part_number: int + part_count: int + def __init__(self, upload_id: _Optional[str] = ..., destination_resource_address: _Optional[str] = ..., part_number: _Optional[int] = ..., part_count: _Optional[int] = ...) -> None: ... + +class UploadPartResponse(_message.Message): + __slots__ = ("part_write_redirects",) + PART_WRITE_REDIRECTS_FIELD_NUMBER: _ClassVar[int] + part_write_redirects: _containers.RepeatedCompositeFieldContainer[WriteRedirectProperties] + def __init__(self, part_write_redirects: _Optional[_Iterable[_Union[WriteRedirectProperties, _Mapping]]] = ...) -> None: ... + +class CompletedUploadPart(_message.Message): + __slots__ = ("part_number", "headers") + PART_NUMBER_FIELD_NUMBER: _ClassVar[int] + HEADERS_FIELD_NUMBER: _ClassVar[int] + part_number: int + headers: _containers.RepeatedCompositeFieldContainer[_fileobject_pb2.Header] + def __init__(self, part_number: _Optional[int] = ..., headers: _Optional[_Iterable[_Union[_fileobject_pb2.Header, _Mapping]]] = ...) -> None: ... + +class CompleteMultipartUploadRequest(_message.Message): + __slots__ = ("upload_id", "destination_resource_address", "parts") + UPLOAD_ID_FIELD_NUMBER: _ClassVar[int] + DESTINATION_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + PARTS_FIELD_NUMBER: _ClassVar[int] + upload_id: str + destination_resource_address: str + parts: _containers.RepeatedCompositeFieldContainer[CompletedUploadPart] + def __init__(self, upload_id: _Optional[str] = ..., destination_resource_address: _Optional[str] = ..., parts: _Optional[_Iterable[_Union[CompletedUploadPart, _Mapping]]] = ...) -> None: ... + +class CompleteMultipartUploadResponse(_message.Message): + __slots__ = ("resource_info",) + RESOURCE_INFO_FIELD_NUMBER: _ClassVar[int] + resource_info: _fileobject_pb2.ResourceInfo + def __init__(self, resource_info: _Optional[_Union[_fileobject_pb2.ResourceInfo, _Mapping]] = ...) -> None: ... + +class AbortMultipartUploadRequest(_message.Message): + __slots__ = ("upload_id", "destination_resource_address") + UPLOAD_ID_FIELD_NUMBER: _ClassVar[int] + DESTINATION_RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + upload_id: str + destination_resource_address: str + def __init__(self, upload_id: _Optional[str] = ..., destination_resource_address: _Optional[str] = ...) -> None: ... + +class AbortMultipartUploadResponse(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class DeleteRequest(_message.Message): + __slots__ = ("resource_address", "previous_version") + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + PREVIOUS_VERSION_FIELD_NUMBER: _ClassVar[int] + resource_address: str + previous_version: _fileobject_pb2.ResourceIdentity + def __init__(self, resource_address: _Optional[str] = ..., previous_version: _Optional[_Union[_fileobject_pb2.ResourceIdentity, _Mapping]] = ...) -> None: ... + +class DeleteResponse(_message.Message): + __slots__ = () + def __init__(self) -> None: ... diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_service_pb2_grpc.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_service_pb2_grpc.py new file mode 100644 index 0000000000000000000000000000000000000000..411410edac0151ee74df92955e04b539742bd1cc --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/fileobject/v1beta/fileobject_service_pb2_grpc.py @@ -0,0 +1,527 @@ +# 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 nvidia.omniverse.storage.fileobject.v1beta import fileobject_service_pb2 as nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2 + +GRPC_GENERATED_VERSION = '1.80.0' +GRPC_VERSION = grpc.__version__ +_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: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in nvidia/omniverse/storage/fileobject/v1beta/fileobject_service_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}.' + ) + + +class FileObjectServiceStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.Enumerate = channel.unary_stream( + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/Enumerate', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.EnumerateRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.EnumerateResponse.FromString, + _registered_method=True) + self.Stat = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/Stat', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.StatRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.StatResponse.FromString, + _registered_method=True) + self.Read = channel.unary_stream( + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/Read', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.ReadRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.ReadResponse.FromString, + _registered_method=True) + self.ReadFromAddress = channel.unary_stream( + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/ReadFromAddress', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.ReadFromAddressRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.ReadFromAddressResponse.FromString, + _registered_method=True) + self.FetchWriteTypeInfo = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/FetchWriteTypeInfo', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.FetchWriteTypeInfoRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.FetchWriteTypeInfoResponse.FromString, + _registered_method=True) + self.Write = channel.stream_stream( + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/Write', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.WriteRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.WriteResponse.FromString, + _registered_method=True) + self.CompleteRedirectUpload = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/CompleteRedirectUpload', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.CompleteRedirectUploadRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.CompleteRedirectUploadResponse.FromString, + _registered_method=True) + self.UploadPart = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/UploadPart', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.UploadPartRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.UploadPartResponse.FromString, + _registered_method=True) + self.CompleteMultipartUpload = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/CompleteMultipartUpload', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.CompleteMultipartUploadRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.CompleteMultipartUploadResponse.FromString, + _registered_method=True) + self.AbortMultipartUpload = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/AbortMultipartUpload', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.AbortMultipartUploadRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.AbortMultipartUploadResponse.FromString, + _registered_method=True) + self.Delete = channel.unary_unary( + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/Delete', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.DeleteRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.DeleteResponse.FromString, + _registered_method=True) + + +class FileObjectServiceServicer(object): + """Missing associated documentation comment in .proto file.""" + + def Enumerate(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Stat(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Read(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ReadFromAddress(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def FetchWriteTypeInfo(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Write(self, request_iterator, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def CompleteRedirectUpload(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def UploadPart(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def CompleteMultipartUpload(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def AbortMultipartUpload(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Delete(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_FileObjectServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'Enumerate': grpc.unary_stream_rpc_method_handler( + servicer.Enumerate, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.EnumerateRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.EnumerateResponse.SerializeToString, + ), + 'Stat': grpc.unary_unary_rpc_method_handler( + servicer.Stat, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.StatRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.StatResponse.SerializeToString, + ), + 'Read': grpc.unary_stream_rpc_method_handler( + servicer.Read, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.ReadRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.ReadResponse.SerializeToString, + ), + 'ReadFromAddress': grpc.unary_stream_rpc_method_handler( + servicer.ReadFromAddress, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.ReadFromAddressRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.ReadFromAddressResponse.SerializeToString, + ), + 'FetchWriteTypeInfo': grpc.unary_unary_rpc_method_handler( + servicer.FetchWriteTypeInfo, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.FetchWriteTypeInfoRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.FetchWriteTypeInfoResponse.SerializeToString, + ), + 'Write': grpc.stream_stream_rpc_method_handler( + servicer.Write, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.WriteRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.WriteResponse.SerializeToString, + ), + 'CompleteRedirectUpload': grpc.unary_unary_rpc_method_handler( + servicer.CompleteRedirectUpload, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.CompleteRedirectUploadRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.CompleteRedirectUploadResponse.SerializeToString, + ), + 'UploadPart': grpc.unary_unary_rpc_method_handler( + servicer.UploadPart, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.UploadPartRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.UploadPartResponse.SerializeToString, + ), + 'CompleteMultipartUpload': grpc.unary_unary_rpc_method_handler( + servicer.CompleteMultipartUpload, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.CompleteMultipartUploadRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.CompleteMultipartUploadResponse.SerializeToString, + ), + 'AbortMultipartUpload': grpc.unary_unary_rpc_method_handler( + servicer.AbortMultipartUpload, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.AbortMultipartUploadRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.AbortMultipartUploadResponse.SerializeToString, + ), + 'Delete': grpc.unary_unary_rpc_method_handler( + servicer.Delete, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.DeleteRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.DeleteResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'nvidia.omniverse.storage.fileobject.v1beta.FileObjectService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('nvidia.omniverse.storage.fileobject.v1beta.FileObjectService', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class FileObjectService(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def Enumerate(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/Enumerate', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.EnumerateRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.EnumerateResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Stat(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/Stat', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.StatRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.StatResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Read(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/Read', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.ReadRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.ReadResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def ReadFromAddress(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/ReadFromAddress', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.ReadFromAddressRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.ReadFromAddressResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def FetchWriteTypeInfo(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/FetchWriteTypeInfo', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.FetchWriteTypeInfoRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.FetchWriteTypeInfoResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Write(request_iterator, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.stream_stream( + request_iterator, + target, + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/Write', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.WriteRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.WriteResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def CompleteRedirectUpload(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/CompleteRedirectUpload', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.CompleteRedirectUploadRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.CompleteRedirectUploadResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def UploadPart(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/UploadPart', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.UploadPartRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.UploadPartResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def CompleteMultipartUpload(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/CompleteMultipartUpload', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.CompleteMultipartUploadRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.CompleteMultipartUploadResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def AbortMultipartUpload(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/AbortMultipartUpload', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.AbortMultipartUploadRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.AbortMultipartUploadResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Delete(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.fileobject.v1beta.FileObjectService/Delete', + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.DeleteRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__service__pb2.DeleteResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/metadata/v1alpha/metadata_pb2.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/metadata/v1alpha/metadata_pb2.py new file mode 100644 index 0000000000000000000000000000000000000000..439207226eb8a81ff2d79c28ba66505f23e46d42 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/metadata/v1alpha/metadata_pb2.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: nvidia/omniverse/storage/metadata/v1alpha/metadata.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'nvidia/omniverse/storage/metadata/v1alpha/metadata.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n8nvidia/omniverse/storage/metadata/v1alpha/metadata.proto\x12)nvidia.omniverse.storage.metadata.v1alpha\x1a\x1cgoogle/protobuf/struct.proto\"=\n\x12GetMetadataRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x1a\n\x12user_metadata_keys\x18\x02 \x03(\t\"\xf1\x01\n\x13GetMetadataResponse\x12g\n\ruser_metadata\x18\x01 \x03(\x0b\x32P.nvidia.omniverse.storage.metadata.v1alpha.GetMetadataResponse.UserMetadataEntry\x1aq\n\x11UserMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12K\n\x05value\x18\x02 \x01(\x0b\x32<.nvidia.omniverse.storage.metadata.v1alpha.UserMetadataValue:\x02\x38\x01\"\x9c\x01\n\x15UpdateMetadataRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x19\n\x11user_metadata_key\x18\x02 \x01(\t\x12-\n\ruser_metadata\x18\x03 \x01(\x0b\x32\x16.google.protobuf.Value\x12\x1a\n\rexpected_etag\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_expected_etag\"&\n\x16UpdateMetadataResponse\x12\x0c\n\x04\x65tag\x18\x01 \x01(\t\"m\n\x15\x44\x65leteMetadataRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x19\n\x11user_metadata_key\x18\x02 \x01(\t\x12\x1a\n\rexpected_etag\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_expected_etag\"\x18\n\x16\x44\x65leteMetadataResponse\"H\n\x11UserMetadataValue\x12%\n\x05value\x18\x01 \x01(\x0b\x32\x16.google.protobuf.Value\x12\x0c\n\x04\x65tag\x18\x02 \x01(\t2\xd0\x03\n\x0fMetadataService\x12\x8c\x01\n\x0bGetMetadata\x12=.nvidia.omniverse.storage.metadata.v1alpha.GetMetadataRequest\x1a>.nvidia.omniverse.storage.metadata.v1alpha.GetMetadataResponse\x12\x95\x01\n\x0eUpdateMetadata\x12@.nvidia.omniverse.storage.metadata.v1alpha.UpdateMetadataRequest\x1a\x41.nvidia.omniverse.storage.metadata.v1alpha.UpdateMetadataResponse\x12\x95\x01\n\x0e\x44\x65leteMetadata\x12@.nvidia.omniverse.storage.metadata.v1alpha.DeleteMetadataRequest\x1a\x41.nvidia.omniverse.storage.metadata.v1alpha.DeleteMetadataResponseB~\n-com.nvidia.omniverse.storage.metadata.v1alphaB\rMetadataProtoP\x01Z None: ... + +class GetMetadataResponse(_message.Message): + __slots__ = ("user_metadata",) + class UserMetadataEntry(_message.Message): + __slots__ = ("key", "value") + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: UserMetadataValue + def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[UserMetadataValue, _Mapping]] = ...) -> None: ... + USER_METADATA_FIELD_NUMBER: _ClassVar[int] + user_metadata: _containers.MessageMap[str, UserMetadataValue] + def __init__(self, user_metadata: _Optional[_Mapping[str, UserMetadataValue]] = ...) -> None: ... + +class UpdateMetadataRequest(_message.Message): + __slots__ = ("uri", "user_metadata_key", "user_metadata", "expected_etag") + URI_FIELD_NUMBER: _ClassVar[int] + USER_METADATA_KEY_FIELD_NUMBER: _ClassVar[int] + USER_METADATA_FIELD_NUMBER: _ClassVar[int] + EXPECTED_ETAG_FIELD_NUMBER: _ClassVar[int] + uri: str + user_metadata_key: str + user_metadata: _struct_pb2.Value + expected_etag: str + def __init__(self, uri: _Optional[str] = ..., user_metadata_key: _Optional[str] = ..., user_metadata: _Optional[_Union[_struct_pb2.Value, _Mapping]] = ..., expected_etag: _Optional[str] = ...) -> None: ... + +class UpdateMetadataResponse(_message.Message): + __slots__ = ("etag",) + ETAG_FIELD_NUMBER: _ClassVar[int] + etag: str + def __init__(self, etag: _Optional[str] = ...) -> None: ... + +class DeleteMetadataRequest(_message.Message): + __slots__ = ("uri", "user_metadata_key", "expected_etag") + URI_FIELD_NUMBER: _ClassVar[int] + USER_METADATA_KEY_FIELD_NUMBER: _ClassVar[int] + EXPECTED_ETAG_FIELD_NUMBER: _ClassVar[int] + uri: str + user_metadata_key: str + expected_etag: str + def __init__(self, uri: _Optional[str] = ..., user_metadata_key: _Optional[str] = ..., expected_etag: _Optional[str] = ...) -> None: ... + +class DeleteMetadataResponse(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + +class UserMetadataValue(_message.Message): + __slots__ = ("value", "etag") + VALUE_FIELD_NUMBER: _ClassVar[int] + ETAG_FIELD_NUMBER: _ClassVar[int] + value: _struct_pb2.Value + etag: str + def __init__(self, value: _Optional[_Union[_struct_pb2.Value, _Mapping]] = ..., etag: _Optional[str] = ...) -> None: ... diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/metadata/v1alpha/metadata_pb2_grpc.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/metadata/v1alpha/metadata_pb2_grpc.py new file mode 100644 index 0000000000000000000000000000000000000000..21c74d93b5a9816a80320c23fa80fc1a9a610a77 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/metadata/v1alpha/metadata_pb2_grpc.py @@ -0,0 +1,183 @@ +# 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 nvidia.omniverse.storage.metadata.v1alpha import metadata_pb2 as nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2 + +GRPC_GENERATED_VERSION = '1.80.0' +GRPC_VERSION = grpc.__version__ +_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: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in nvidia/omniverse/storage/metadata/v1alpha/metadata_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}.' + ) + + +class MetadataServiceStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.GetMetadata = channel.unary_unary( + '/nvidia.omniverse.storage.metadata.v1alpha.MetadataService/GetMetadata', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.GetMetadataRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.GetMetadataResponse.FromString, + _registered_method=True) + self.UpdateMetadata = channel.unary_unary( + '/nvidia.omniverse.storage.metadata.v1alpha.MetadataService/UpdateMetadata', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.UpdateMetadataRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.UpdateMetadataResponse.FromString, + _registered_method=True) + self.DeleteMetadata = channel.unary_unary( + '/nvidia.omniverse.storage.metadata.v1alpha.MetadataService/DeleteMetadata', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.DeleteMetadataRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.DeleteMetadataResponse.FromString, + _registered_method=True) + + +class MetadataServiceServicer(object): + """Missing associated documentation comment in .proto file.""" + + def GetMetadata(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def UpdateMetadata(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def DeleteMetadata(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_MetadataServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'GetMetadata': grpc.unary_unary_rpc_method_handler( + servicer.GetMetadata, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.GetMetadataRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.GetMetadataResponse.SerializeToString, + ), + 'UpdateMetadata': grpc.unary_unary_rpc_method_handler( + servicer.UpdateMetadata, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.UpdateMetadataRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.UpdateMetadataResponse.SerializeToString, + ), + 'DeleteMetadata': grpc.unary_unary_rpc_method_handler( + servicer.DeleteMetadata, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.DeleteMetadataRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.DeleteMetadataResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'nvidia.omniverse.storage.metadata.v1alpha.MetadataService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('nvidia.omniverse.storage.metadata.v1alpha.MetadataService', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class MetadataService(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def GetMetadata(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.metadata.v1alpha.MetadataService/GetMetadata', + nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.GetMetadataRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.GetMetadataResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def UpdateMetadata(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.metadata.v1alpha.MetadataService/UpdateMetadata', + nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.UpdateMetadataRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.UpdateMetadataResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def DeleteMetadata(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/nvidia.omniverse.storage.metadata.v1alpha.MetadataService/DeleteMetadata', + nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.DeleteMetadataRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_metadata_dot_v1alpha_dot_metadata__pb2.DeleteMetadataResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1alpha/versioning_pb2.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1alpha/versioning_pb2.py new file mode 100644 index 0000000000000000000000000000000000000000..a7d25320018e6c2bbc0f0c40c2d0dba7f5569bdf --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1alpha/versioning_pb2.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: nvidia/omniverse/storage/versioning/v1alpha/versioning.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'nvidia/omniverse/storage/versioning/v1alpha/versioning.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from nvidia.omniverse.storage.fileobject.v1alpha import fileobject_pb2 as nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1alpha_dot_fileobject__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\npb.api.nvidia.com/omniverse/storage/versioning/v1alpha;storageb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nvidia.omniverse.storage.versioning.v1alpha.versioning_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n/com.nvidia.omniverse.storage.versioning.v1alphaB\017VersioningProtoP\001Z>pb.api.nvidia.com/omniverse/storage/versioning/v1alpha;storage' + _globals['_VERSIONSORDER']._serialized_start=605 + _globals['_VERSIONSORDER']._serialized_end=745 + _globals['_ENUMERATEVERSIONSREQUEST']._serialized_start=171 + _globals['_ENUMERATEVERSIONSREQUEST']._serialized_end=223 + _globals['_ENUMERATEVERSIONSRESPONSE']._serialized_start=226 + _globals['_ENUMERATEVERSIONSRESPONSE']._serialized_end=410 + _globals['_VERSIONINFO']._serialized_start=413 + _globals['_VERSIONINFO']._serialized_end=602 + _globals['_VERSIONINGSERVICE']._serialized_start=748 + _globals['_VERSIONINGSERVICE']._serialized_end=934 +# @@protoc_insertion_point(module_scope) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1alpha/versioning_pb2.pyi b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1alpha/versioning_pb2.pyi new file mode 100644 index 0000000000000000000000000000000000000000..979507659e296aa1745856161e72dbe1a7efdceb --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1alpha/versioning_pb2.pyi @@ -0,0 +1,44 @@ +from nvidia.omniverse.storage.fileobject.v1alpha import fileobject_pb2 as _fileobject_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class VersionsOrder(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + VERSIONS_ORDER_UNSPECIFIED: _ClassVar[VersionsOrder] + VERSIONS_ORDER_NEWEST_FIRST: _ClassVar[VersionsOrder] + VERSIONS_ORDER_OLDEST_FIRST: _ClassVar[VersionsOrder] + VERSIONS_ORDER_BY_KEY: _ClassVar[VersionsOrder] +VERSIONS_ORDER_UNSPECIFIED: VersionsOrder +VERSIONS_ORDER_NEWEST_FIRST: VersionsOrder +VERSIONS_ORDER_OLDEST_FIRST: VersionsOrder +VERSIONS_ORDER_BY_KEY: VersionsOrder + +class EnumerateVersionsRequest(_message.Message): + __slots__ = ("resource_address",) + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + resource_address: str + def __init__(self, resource_address: _Optional[str] = ...) -> None: ... + +class EnumerateVersionsResponse(_message.Message): + __slots__ = ("items", "versions_order") + ITEMS_FIELD_NUMBER: _ClassVar[int] + VERSIONS_ORDER_FIELD_NUMBER: _ClassVar[int] + items: _containers.RepeatedCompositeFieldContainer[VersionInfo] + versions_order: VersionsOrder + def __init__(self, items: _Optional[_Iterable[_Union[VersionInfo, _Mapping]]] = ..., versions_order: _Optional[_Union[VersionsOrder, str]] = ...) -> None: ... + +class VersionInfo(_message.Message): + __slots__ = ("resource_info", "sorting_key", "resource_address") + RESOURCE_INFO_FIELD_NUMBER: _ClassVar[int] + SORTING_KEY_FIELD_NUMBER: _ClassVar[int] + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + resource_info: _fileobject_pb2.ResourceInfo + sorting_key: str + resource_address: str + def __init__(self, resource_info: _Optional[_Union[_fileobject_pb2.ResourceInfo, _Mapping]] = ..., sorting_key: _Optional[str] = ..., resource_address: _Optional[str] = ...) -> None: ... diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1alpha/versioning_pb2_grpc.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1alpha/versioning_pb2_grpc.py new file mode 100644 index 0000000000000000000000000000000000000000..836c97d87315f7cc3abd6bc616170e322464bcb8 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1alpha/versioning_pb2_grpc.py @@ -0,0 +1,97 @@ +# 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 nvidia.omniverse.storage.versioning.v1alpha import versioning_pb2 as nvidia_dot_omniverse_dot_storage_dot_versioning_dot_v1alpha_dot_versioning__pb2 + +GRPC_GENERATED_VERSION = '1.80.0' +GRPC_VERSION = grpc.__version__ +_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: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in nvidia/omniverse/storage/versioning/v1alpha/versioning_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}.' + ) + + +class VersioningServiceStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.EnumerateVersions = channel.unary_stream( + '/nvidia.omniverse.storage.versioning.v1alpha.VersioningService/EnumerateVersions', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_versioning_dot_v1alpha_dot_versioning__pb2.EnumerateVersionsRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_versioning_dot_v1alpha_dot_versioning__pb2.EnumerateVersionsResponse.FromString, + _registered_method=True) + + +class VersioningServiceServicer(object): + """Missing associated documentation comment in .proto file.""" + + def EnumerateVersions(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_VersioningServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'EnumerateVersions': grpc.unary_stream_rpc_method_handler( + servicer.EnumerateVersions, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_versioning_dot_v1alpha_dot_versioning__pb2.EnumerateVersionsRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_versioning_dot_v1alpha_dot_versioning__pb2.EnumerateVersionsResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'nvidia.omniverse.storage.versioning.v1alpha.VersioningService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('nvidia.omniverse.storage.versioning.v1alpha.VersioningService', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class VersioningService(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def EnumerateVersions(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/nvidia.omniverse.storage.versioning.v1alpha.VersioningService/EnumerateVersions', + nvidia_dot_omniverse_dot_storage_dot_versioning_dot_v1alpha_dot_versioning__pb2.EnumerateVersionsRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_versioning_dot_v1alpha_dot_versioning__pb2.EnumerateVersionsResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1beta/versioning_pb2.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1beta/versioning_pb2.py new file mode 100644 index 0000000000000000000000000000000000000000..70e1a5014d0c580c42f59929e9eebca09608362f --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1beta/versioning_pb2.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: nvidia/omniverse/storage/versioning/v1beta/versioning.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'nvidia/omniverse/storage/versioning/v1beta/versioning.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from nvidia.omniverse.storage.fileobject.v1beta import fileobject_pb2 as nvidia_dot_omniverse_dot_storage_dot_fileobject_dot_v1beta_dot_fileobject__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n;nvidia/omniverse/storage/versioning/v1beta/versioning.proto\x12*nvidia.omniverse.storage.versioning.v1beta\x1a;nvidia/omniverse/storage/fileobject/v1beta/fileobject.proto\"4\n\x18\x45numerateVersionsRequest\x12\x18\n\x10resource_address\x18\x01 \x01(\t\"\xb6\x01\n\x19\x45numerateVersionsResponse\x12\x46\n\x05items\x18\x01 \x03(\x0b\x32\x37.nvidia.omniverse.storage.versioning.v1beta.VersionInfo\x12Q\n\x0eversions_order\x18\x02 \x01(\x0e\x32\x39.nvidia.omniverse.storage.versioning.v1beta.VersionsOrder\"\x88\x01\n\x0bVersionInfo\x12O\n\rresource_info\x18\x01 \x01(\x0b\x32\x38.nvidia.omniverse.storage.fileobject.v1beta.ResourceInfo\x12\x18\n\x0bsorting_key\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_sorting_key*\x8c\x01\n\rVersionsOrder\x12\x1e\n\x1aVERSIONS_ORDER_UNSPECIFIED\x10\x00\x12\x1f\n\x1bVERSIONS_ORDER_NEWEST_FIRST\x10\x01\x12\x1f\n\x1bVERSIONS_ORDER_OLDEST_FIRST\x10\x02\x12\x19\n\x15VERSIONS_ORDER_BY_KEY\x10\x03\x32\xb8\x01\n\x11VersioningService\x12\xa2\x01\n\x11\x45numerateVersions\x12\x44.nvidia.omniverse.storage.versioning.v1beta.EnumerateVersionsRequest\x1a\x45.nvidia.omniverse.storage.versioning.v1beta.EnumerateVersionsResponse0\x01\x42\x82\x01\n.com.nvidia.omniverse.storage.versioning.v1betaB\x0fVersioningProtoP\x01Z=pb.api.nvidia.com/omniverse/storage/versioning/v1beta;storageb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nvidia.omniverse.storage.versioning.v1beta.versioning_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n.com.nvidia.omniverse.storage.versioning.v1betaB\017VersioningProtoP\001Z=pb.api.nvidia.com/omniverse/storage/versioning/v1beta;storage' + _globals['_VERSIONSORDER']._serialized_start=547 + _globals['_VERSIONSORDER']._serialized_end=687 + _globals['_ENUMERATEVERSIONSREQUEST']._serialized_start=168 + _globals['_ENUMERATEVERSIONSREQUEST']._serialized_end=220 + _globals['_ENUMERATEVERSIONSRESPONSE']._serialized_start=223 + _globals['_ENUMERATEVERSIONSRESPONSE']._serialized_end=405 + _globals['_VERSIONINFO']._serialized_start=408 + _globals['_VERSIONINFO']._serialized_end=544 + _globals['_VERSIONINGSERVICE']._serialized_start=690 + _globals['_VERSIONINGSERVICE']._serialized_end=874 +# @@protoc_insertion_point(module_scope) diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1beta/versioning_pb2.pyi b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1beta/versioning_pb2.pyi new file mode 100644 index 0000000000000000000000000000000000000000..870c76cc1825fd3c3ec41f295503aaeff8437004 --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1beta/versioning_pb2.pyi @@ -0,0 +1,42 @@ +from nvidia.omniverse.storage.fileobject.v1beta import fileobject_pb2 as _fileobject_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class VersionsOrder(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + VERSIONS_ORDER_UNSPECIFIED: _ClassVar[VersionsOrder] + VERSIONS_ORDER_NEWEST_FIRST: _ClassVar[VersionsOrder] + VERSIONS_ORDER_OLDEST_FIRST: _ClassVar[VersionsOrder] + VERSIONS_ORDER_BY_KEY: _ClassVar[VersionsOrder] +VERSIONS_ORDER_UNSPECIFIED: VersionsOrder +VERSIONS_ORDER_NEWEST_FIRST: VersionsOrder +VERSIONS_ORDER_OLDEST_FIRST: VersionsOrder +VERSIONS_ORDER_BY_KEY: VersionsOrder + +class EnumerateVersionsRequest(_message.Message): + __slots__ = ("resource_address",) + RESOURCE_ADDRESS_FIELD_NUMBER: _ClassVar[int] + resource_address: str + def __init__(self, resource_address: _Optional[str] = ...) -> None: ... + +class EnumerateVersionsResponse(_message.Message): + __slots__ = ("items", "versions_order") + ITEMS_FIELD_NUMBER: _ClassVar[int] + VERSIONS_ORDER_FIELD_NUMBER: _ClassVar[int] + items: _containers.RepeatedCompositeFieldContainer[VersionInfo] + versions_order: VersionsOrder + def __init__(self, items: _Optional[_Iterable[_Union[VersionInfo, _Mapping]]] = ..., versions_order: _Optional[_Union[VersionsOrder, str]] = ...) -> None: ... + +class VersionInfo(_message.Message): + __slots__ = ("resource_info", "sorting_key") + RESOURCE_INFO_FIELD_NUMBER: _ClassVar[int] + SORTING_KEY_FIELD_NUMBER: _ClassVar[int] + resource_info: _fileobject_pb2.ResourceInfo + sorting_key: str + def __init__(self, resource_info: _Optional[_Union[_fileobject_pb2.ResourceInfo, _Mapping]] = ..., sorting_key: _Optional[str] = ...) -> None: ... diff --git a/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1beta/versioning_pb2_grpc.py b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1beta/versioning_pb2_grpc.py new file mode 100644 index 0000000000000000000000000000000000000000..e583d0b2171379285b0d7bbbba59554e43dcedaf --- /dev/null +++ b/docker/hf-space/hf-storage-api/generated/nvidia/omniverse/storage/versioning/v1beta/versioning_pb2_grpc.py @@ -0,0 +1,97 @@ +# 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 nvidia.omniverse.storage.versioning.v1beta import versioning_pb2 as nvidia_dot_omniverse_dot_storage_dot_versioning_dot_v1beta_dot_versioning__pb2 + +GRPC_GENERATED_VERSION = '1.80.0' +GRPC_VERSION = grpc.__version__ +_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: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + ' but the generated code in nvidia/omniverse/storage/versioning/v1beta/versioning_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}.' + ) + + +class VersioningServiceStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.EnumerateVersions = channel.unary_stream( + '/nvidia.omniverse.storage.versioning.v1beta.VersioningService/EnumerateVersions', + request_serializer=nvidia_dot_omniverse_dot_storage_dot_versioning_dot_v1beta_dot_versioning__pb2.EnumerateVersionsRequest.SerializeToString, + response_deserializer=nvidia_dot_omniverse_dot_storage_dot_versioning_dot_v1beta_dot_versioning__pb2.EnumerateVersionsResponse.FromString, + _registered_method=True) + + +class VersioningServiceServicer(object): + """Missing associated documentation comment in .proto file.""" + + def EnumerateVersions(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_VersioningServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'EnumerateVersions': grpc.unary_stream_rpc_method_handler( + servicer.EnumerateVersions, + request_deserializer=nvidia_dot_omniverse_dot_storage_dot_versioning_dot_v1beta_dot_versioning__pb2.EnumerateVersionsRequest.FromString, + response_serializer=nvidia_dot_omniverse_dot_storage_dot_versioning_dot_v1beta_dot_versioning__pb2.EnumerateVersionsResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'nvidia.omniverse.storage.versioning.v1beta.VersioningService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('nvidia.omniverse.storage.versioning.v1beta.VersioningService', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class VersioningService(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def EnumerateVersions(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/nvidia.omniverse.storage.versioning.v1beta.VersioningService/EnumerateVersions', + nvidia_dot_omniverse_dot_storage_dot_versioning_dot_v1beta_dot_versioning__pb2.EnumerateVersionsRequest.SerializeToString, + nvidia_dot_omniverse_dot_storage_dot_versioning_dot_v1beta_dot_versioning__pb2.EnumerateVersionsResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/__init__.py b/docker/hf-space/hf-storage-api/hf_storage_api/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8d4fea02715283728bb32e78a6a3175ccab60b0f --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/__init__.py @@ -0,0 +1,6 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Read-only Omniverse Storage API gRPC server backed by HuggingFace datasets.""" + +__version__ = "0.1.0" diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/__main__.py b/docker/hf-space/hf-storage-api/hf_storage_api/__main__.py new file mode 100644 index 0000000000000000000000000000000000000000..46f62ed3fe77007bc6dc9173599278017d265ded --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/__main__.py @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""``python -m hf_storage_api``.""" + +from __future__ import annotations + +import asyncio + +from .server import serve + + +def main() -> None: + asyncio.run(serve()) + + +if __name__ == "__main__": + main() diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/addressing.py b/docker/hf-space/hf-storage-api/hf_storage_api/addressing.py new file mode 100644 index 0000000000000000000000000000000000000000..6966f91e8f8484d4a8a202ecdc1918f56f146a5a --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/addressing.py @@ -0,0 +1,159 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Addresses <-> (repo, path). + +Emitted addresses are ``https://`` by default and mirror HuggingFace's own URL +layout, so a pinned address *is* the public URL rather than something that has to +be rewritten into one (plan §6.1). ``HF_ADAPTER_URI_SCHEME=hf`` restores the +synthetic ``hf://`` namespace. + +Parse loose, emit strict (plan §2.4). The client does not normalise the root +before sending it: ``Enumerate`` receives ``STORAGE_API_BASE_URI`` verbatim +(typically with no trailing slash) while ``ListStat`` receives +``rstrip('/') + '/'``. Both must resolve to the same root. Everything this module +*emits*, on the other hand, obeys the rule the client keys off: folder addresses +end in ``/``, asset addresses do not (contract doc §3.3). +""" + +from __future__ import annotations + +from dataclasses import dataclass +from urllib.parse import unquote, urlsplit + +# HF repo types and their URL infix. Datasets and spaces are namespaced in the +# URL; models sit at the bare root. +REPO_TYPE_PREFIX = {"dataset": "datasets", "space": "spaces", "model": ""} + +# Accepted inbound regardless of which scheme we emit. `hf` stays here after the +# switch to `https` so an address minted by an earlier deployment — persisted in +# a USD Search index, or pasted into a Kit session — still resolves. +INBOUND_SCHEMES = frozenset({"hf", "https", "http"}) + +DEFAULT_SCHEME = "https" + + +@dataclass(frozen=True) +class Address: + """A parsed address.""" + + host: str + repo_type: str + repo_id: str # "/" + path: str # repo-relative, no leading slash; "" for the repo root + is_folder: bool # the address carried a trailing slash + revision: str | None = None # from a `/resolve//` segment, when present + + @property + def repo_key(self) -> str: + return f"{self.repo_type}:{self.repo_id}" + + +class AddressError(ValueError): + """The address is not a well-formed address in our namespace.""" + + +def parse(address: str, *, scheme: str = DEFAULT_SCHEME, revision_in_uri: bool = True) -> Address: + """Parse a ``https://host/datasets//[/resolve/][/]``. + + Accepts a root with or without a trailing slash, and with or without the + ``/resolve//`` segment — parse loose, emit strict (plan §2.4). Raises + :class:`AddressError` for anything that is not addressable here; the caller + maps that to ``INVALID_ARGUMENT`` (plan §5.3). + + ``revision_in_uri=False`` turns the ``resolve`` segment back into an ordinary + path component, for the pathological repo with a top-level folder by that + name. + """ + if not address: + raise AddressError("empty address") + + split = urlsplit(address) + # Every scheme in INBOUND_SCHEMES is accepted alongside the configured one. + # Emitted addresses mirror HuggingFace's URL layout exactly, so all of these + # forms name the same object — and a consumer handed a public URL (from + # metadata, or from a public-url rewrite) will hand it straight back to us + # expecting it to work. Parse loose, emit strict. + if split.scheme != scheme and split.scheme not in INBOUND_SCHEMES: + raise AddressError(f"expected scheme {scheme!r}, got {split.scheme!r} in {address!r}") + if not split.netloc: + raise AddressError(f"missing host in {address!r}") + + is_folder = split.path.endswith("/") + # unquote so a percent-encoded address (STORAGE_API_APPLY_URL_QUOTE=true) + # compares equal to a plain one. + segments = [unquote(s) for s in split.path.split("/") if s] + + repo_type = "model" + for rtype, prefix in REPO_TYPE_PREFIX.items(): + if prefix and segments[:1] == [prefix]: + repo_type, segments = rtype, segments[1:] + break + + if len(segments) < 2: + raise AddressError(f"address does not name a repo (/): {address!r}") + + repo_id = f"{segments[0]}/{segments[1]}" + rest = segments[2:] + + # `/resolve//` mirrors HuggingFace's own URL layout, so an + # address can be turned into its public HTTPS form by swapping the scheme. + revision: str | None = None + if revision_in_uri and len(rest) >= 2 and rest[0] == "resolve": + revision, rest = rest[1], rest[2:] + + return Address( + host=split.netloc, + repo_type=repo_type, + repo_id=repo_id, + path="/".join(rest), + is_folder=is_folder, + revision=revision, + ) + + +def try_parse(address: str, *, scheme: str = DEFAULT_SCHEME, revision_in_uri: bool = True) -> Address | None: + try: + return parse(address, scheme=scheme, revision_in_uri=revision_in_uri) + except AddressError: + return None + + +def build( + *, + host: str, + repo_type: str, + repo_id: str, + path: str = "", + is_folder: bool = False, + scheme: str = DEFAULT_SCHEME, + revision: str | None = None, +) -> str: + """Emit a canonical address. Folders end in ``/``; assets never do. + + With the default ``https`` scheme and a ``revision``, the result is byte-identical + to HuggingFace's own resolve URL. *Without* a revision it is HTTPS-shaped but not + a fetchable HF URL — HF requires a ``/resolve//`` or ``/blob//`` segment. + It still round-trips through :func:`parse`, which is what this service needs of it; + see the plan's §6.1 on pairing ``https`` with ``URI_REVISION_MODE``. + """ + prefix = REPO_TYPE_PREFIX.get(repo_type, "") + ref = f"resolve/{revision}" if revision else "" + parts = [p for p in (prefix, repo_id, ref, path.strip("/")) if p] + out = f"{scheme}://{host}/" + "/".join(parts) + if is_folder and not out.endswith("/"): + out += "/" + return out + + +def is_within(path: str, folder: str) -> bool: + """Is ``path`` the folder itself or something underneath it? + + Boundary-aware: ``sm_box_a01`` does not contain ``sm_box_a01_extra/x.usd``. + This is the access-boundary predicate of plan §8.4, so it must not degrade to + a bare ``startswith``. + """ + folder = folder.strip("/") + if not folder: + return True + return path == folder or path.startswith(folder + "/") diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/auth.py b/docker/hf-space/hf-storage-api/hf_storage_api/auth.py new file mode 100644 index 0000000000000000000000000000000000000000..3e8bfca5ef388419a8a1ef2bd4c7563a7cb169cb --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/auth.py @@ -0,0 +1,58 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Inbound gRPC auth (plan §6.4). + +The client sends whatever ``get_grpc_request_metadata()`` produces — a bearer +token from ``STORAGE_API_TOKEN`` / ``_TOKEN_FILE`` / OpenID. Kit sends the same +header via ``OMNI_STORAGE_AUTHORIZATION``. We check a shared secret so the HF +token is not effectively public to anything that can reach the gRPC port. + +Nothing is exempt except the health service — ``ListServices`` in particular +doubles as the client's ``check_connection()``, so exempting *that* would leave +an unauthenticated probe of what this server serves. +""" + +from __future__ import annotations + +import logging +import secrets + +import grpc + +from .health import METHOD_PREFIX as HEALTH_PREFIX + +logger = logging.getLogger(__name__) + + +class BearerAuthInterceptor(grpc.aio.ServerInterceptor): + def __init__(self, expected_token: str | None) -> None: + self._expected = expected_token + + async def intercept_service(self, continuation, handler_call_details): + if self._expected is None: + return await continuation(handler_call_details) + + # The health service is the one exemption, and it is forced: a Kubernetes + # probe cannot present a bearer token. It discloses only SERVING / + # NOT_SERVING, never anything about the dataset. + if handler_call_details.method.startswith(HEALTH_PREFIX): + return await continuation(handler_call_details) + + metadata = dict(handler_call_details.invocation_metadata or ()) + header = metadata.get("authorization", "") + token = header[7:] if header.lower().startswith("bearer ") else header + + # Constant-time compare: this is a shared secret, not a hash. + if token and secrets.compare_digest(token, self._expected): + return await continuation(handler_call_details) + + logger.warning("rejected unauthenticated call to %s", handler_call_details.method) + return _abort_handler(grpc.StatusCode.UNAUTHENTICATED, "missing or invalid bearer token") + + +def _abort_handler(code: grpc.StatusCode, detail: str) -> grpc.RpcMethodHandler: + async def abort(request, context): + await context.abort(code, detail) + + return grpc.unary_unary_rpc_method_handler(abort) diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/cache.py b/docker/hf-space/hf-storage-api/hf_storage_api/cache.py new file mode 100644 index 0000000000000000000000000000000000000000..f6f491a6a959c7fa025071469ab3381ae2c72399 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/cache.py @@ -0,0 +1,172 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""TTL + LRU cache with single-flight loading (plan §5.2). + +Single-flight is not optional here. A crawl ``Enumerate``s and then ``Stat``s +every item, and a thumbnail probe fires up to four ``Stat``s per asset for +candidate ``.thumbs`` paths — all against the same folder, concurrently. Without +collapsing concurrent loads of one key onto a single upstream request, laziness +turns one preload into a burst of duplicates. +""" + +from __future__ import annotations + +import asyncio +import time +from collections import OrderedDict +from collections.abc import Awaitable, Callable, Hashable +from dataclasses import dataclass, field +from typing import Generic, TypeVar + +K = TypeVar("K", bound=Hashable) +V = TypeVar("V") + + +class Missing: + """A cached negative result. + + Distinct from ``None`` so a miss can be cached and served without re-hitting + HuggingFace: the thumbnail probe generates a steady stream of legitimate + misses that would otherwise be upstream traffic every time. + """ + + __slots__ = () + + def __bool__(self) -> bool: + return False + + +MISSING = Missing() + + +@dataclass +class CacheStats: + hits: int = 0 + misses: int = 0 + loads: int = 0 + negative_hits: int = 0 + evictions: int = 0 + + @property + def hit_rate(self) -> float: + total = self.hits + self.misses + return self.hits / total if total else 0.0 + + +@dataclass +class _Entry(Generic[V]): + value: V | Missing + expires_at: float + + +class SingleFlightCache(Generic[K, V]): + """Async cache: at most one in-flight load per key, TTL + LRU eviction.""" + + def __init__( + self, + *, + ttl: float, + negative_ttl: float, + max_size: int, + clock: Callable[[], float] = time.monotonic, + ) -> None: + self._ttl = ttl + self._negative_ttl = negative_ttl + self._max_size = max_size + self._clock = clock + self._entries: OrderedDict[K, _Entry[V]] = OrderedDict() + self._inflight: dict[K, asyncio.Future[V | Missing]] = {} + self.stats = CacheStats() + + def _get_live(self, key: K) -> _Entry[V] | None: + entry = self._entries.get(key) + if entry is None: + return None + if entry.expires_at <= self._clock(): + del self._entries[key] + return None + self._entries.move_to_end(key) + return entry + + def peek(self, key: K) -> V | Missing | None: + """Return a cached value without loading. ``None`` means "not cached".""" + entry = self._get_live(key) + return entry.value if entry else None + + def put(self, key: K, value: V | Missing) -> None: + ttl = self._negative_ttl if isinstance(value, Missing) else self._ttl + self._entries[key] = _Entry(value=value, expires_at=self._clock() + ttl) + self._entries.move_to_end(key) + while len(self._entries) > self._max_size: + self._entries.popitem(last=False) + self.stats.evictions += 1 + + async def get(self, key: K, loader: Callable[[], Awaitable[V | Missing]]) -> V | Missing: + """Return the cached value, or load it — once, however many callers race.""" + entry = self._get_live(key) + if entry is not None: + self.stats.hits += 1 + if isinstance(entry.value, Missing): + self.stats.negative_hits += 1 + return entry.value + + self.stats.misses += 1 + + inflight = self._inflight.get(key) + if inflight is not None: + # Someone else is already loading this key: wait for their result + # rather than issuing a duplicate upstream request. + return await asyncio.shield(inflight) + + future: asyncio.Future[V | Missing] = asyncio.get_running_loop().create_future() + self._inflight[key] = future + try: + self.stats.loads += 1 + value = await loader() + except BaseException as exc: + # Failures are not cached — a transient 503 must not pin a miss for + # the whole TTL. + if not future.done(): + future.set_exception(exc) + raise + else: + self.put(key, value) + if not future.done(): + future.set_result(value) + return value + finally: + self._inflight.pop(key, None) + # Nobody may be awaiting a failed future; keep the loop quiet about it. + if future.done() and future.exception() is not None: + future.exception() + + def clear(self) -> None: + self._entries.clear() + + def __len__(self) -> int: + return len(self._entries) + + +@dataclass +class TokenBucket: + """Simple rate limiter for upstream calls (plan §8.5).""" + + rate: float + capacity: float + _tokens: float = field(default=0.0, init=False) + _updated: float = field(default=0.0, init=False) + + def __post_init__(self) -> None: + self._tokens = self.capacity + self._updated = time.monotonic() + + async def acquire(self) -> None: + while True: + now = time.monotonic() + self._tokens = min(self.capacity, self._tokens + (now - self._updated) * self.rate) + self._updated = now + if self._tokens >= 1: + self._tokens -= 1 + return + await asyncio.sleep((1 - self._tokens) / self.rate) diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/catalog/__init__.py b/docker/hf-space/hf-storage-api/hf_storage_api/catalog/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..52a7a9daf028f654d6a02f65c99cc609a57b492f --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/catalog/__init__.py @@ -0,0 +1,2 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/catalog/loader.py b/docker/hf-space/hf-storage-api/hf_storage_api/catalog/loader.py new file mode 100644 index 0000000000000000000000000000000000000000..dc70aa044d133b565b4a6494adafb6cd7d93d5d9 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/catalog/loader.py @@ -0,0 +1,282 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Catalog loading: ``file`` | ``url`` | ``discover`` (plan §6.3). + +Reload is atomic — build off to the side, swap the reference. A failed refresh +logs and keeps serving the last good catalog: never fail a crawl because GitHub +blipped. + +Every transport is polled, not just ``url``: a catalog file is mounted from a +ConfigMap or written by the catalog-sync sidecar, and both change under a running +process (sidecar plan §3). +""" + +from __future__ import annotations + +import asyncio +import hashlib +import logging +from pathlib import Path + +import httpx +import yaml + +from ..hf.client import HFClient +from ..settings import Settings +from .model import Catalog, LayoutConfig, RepoConfig +from .urllist import UrlListError, looks_like_url_list, normalize_asset_urls, parse_url_list + +logger = logging.getLogger(__name__) + + +class CatalogError(Exception): + pass + + +def parse_catalog(raw: str) -> Catalog: + data = yaml.safe_load(raw) + if not isinstance(data, dict): + raise CatalogError("catalog must be a YAML mapping") + catalog = Catalog.model_validate(data) + try: + # `assets:` entries may be full HuggingFace URLs as well as folder names. + return normalize_asset_urls(catalog) + except UrlListError as exc: + raise CatalogError(str(exc)) from exc + + +def parse_text(text: str, *, fmt: str = "auto", layout: LayoutConfig | None = None) -> Catalog: + """Parse catalog text, picking the format when asked to. + + Transport (file/url) and format (yaml/url-list) are independent: a URL list + is just as likely to live in a GitHub repo as a YAML catalog is. Shared with + the catalog-sync sidecar so that what it accepts and what the service accepts + cannot drift apart. + """ + if fmt == "auto": + fmt = "url-list" if looks_like_url_list(text) else "yaml" + + if fmt == "url-list": + try: + return parse_url_list(text, layout=layout) + except UrlListError as exc: + raise CatalogError(str(exc)) from exc + return parse_catalog(text) + + +class CatalogLoader: + """Loads the catalog and keeps it fresh, holding the last good copy.""" + + def __init__(self, settings: Settings, hf: HFClient) -> None: + self._settings = settings + self._hf = hf + self._etag: str | None = None + self._last_good: Catalog | None = None + self._task: asyncio.Task | None = None + # What the catalog file looked like last time we read it: a cheap + # (mtime, size) gate in front of an authoritative content digest. + self._stat: tuple[int, int] | None = None + self._digest: str | None = None + + @property + def current(self) -> Catalog | None: + return self._last_good + + async def load(self) -> Catalog: + """Load once. Raises on the first load; later failures keep the last good.""" + try: + text = await self._fetch_text() + if text is None: # 304 Not Modified + return self._last_good # type: ignore[return-value] + catalog = self._parse(text) + except Exception as exc: + if self._last_good is None: + raise + logger.warning("catalog refresh failed (%s); keeping the last good copy", exc) + return self._last_good + + if self._settings.catalog_source == "discover" or any(r.discover is not None for r in catalog.repos): + catalog = await self._discover(catalog) + + validate_catalog(catalog) + self._last_good = catalog + logger.info( + "catalog loaded: %d repo(s), %d asset(s)", + len(catalog.repos), + sum(len(r.assets) for r in catalog.repos), + ) + return catalog + + async def _fetch_text(self) -> str | None: + """Fetch the raw catalog. ``None`` means "unchanged since last time".""" + source = self._settings.catalog_source + if source in ("file", "discover"): + return self._read_file() + + headers = {"If-None-Match": self._etag} if self._etag else {} + async with httpx.AsyncClient(timeout=self._settings.http_timeout) as client: + response = await client.get(self._settings.catalog_url or "", headers=headers) + if response.status_code == 304 and self._last_good is not None: + logger.debug("catalog unchanged (304)") + return None + response.raise_for_status() + self._etag = response.headers.get("ETag") + return response.text + + def _read_file(self) -> str | None: + """Read the catalog file, or ``None`` when its contents have not changed. + + Two gates, because they answer different questions. ``stat()`` is what + makes polling free — it is the only syscall in the steady state. The + digest is what makes it *correct*: a ConfigMap resync and a sidecar + republishing an unchanged file both move the mtime without changing a + byte, and rebuilding the catalog for that is pure churn. + + Both are updated before the content is parsed, deliberately: identical + bytes that failed to parse must not be retried every interval, or one + bad file becomes one log line per tick forever. + """ + path = self._settings.catalog_path + if path is None: # pragma: no cover - Settings validates this + raise CatalogError("catalog_path is unset") + path = Path(path) + + info = path.stat() + stamp = (info.st_mtime_ns, info.st_size) + if self._last_good is not None and stamp == self._stat: + return None + self._stat = stamp + + text = path.read_text(encoding="utf-8") + digest = hashlib.sha256(text.encode("utf-8")).hexdigest() + if self._last_good is not None and digest == self._digest: + logger.debug("catalog file touched but unchanged (%s)", path) + return None + self._digest = digest + return text + + def _parse(self, text: str) -> Catalog: + return parse_text( + text, + fmt=self._settings.catalog_format, + layout=self._settings.layout_defaults(), + ) + + async def _discover(self, catalog: Catalog) -> Catalog: + """Fill in ``assets`` by walking each repo for folders carrying the marker. + + This is the one repo-wide read in the service, and it is a *catalog* + build rather than an asset preload: it keeps only folder names, never the + per-file entries, which stay lazy (plan §6.3). + """ + repos: list[RepoConfig] = [] + for repo in catalog.repos: + if repo.assets or repo.discover is None: + repos.append(repo) + continue + layout = catalog.layout_for(repo) + entries = await self._hf.list_tree( + repo.repo_type, + repo.repo_id, + repo.revision, + repo.discover.root, + recursive=True, + token=repo.token, + ) + if layout.catalog_kind == "wrapp": + # The marker's filename varies per asset (`.{folder}.wrapp`), and + # it lives in the *version* subfolder — so each version is + # discovered as its own asset, and multiple versions of one + # asset simply coexist as distinct catalog entries (plan §6.3). + suffix = repo.discover.marker or layout.marker_suffix + assets = sorted( + { + entry.path.rsplit("/", 1)[0] + for entry in entries + if entry.is_file and entry.path.endswith(suffix) and "/" in entry.path + } + ) + else: + marker = repo.discover.marker or layout.marker + assets = sorted( + { + entry.path[: -(len(marker) + 1)] + for entry in entries + if entry.is_file and entry.path.endswith("/" + marker) + } + ) + logger.info("discovered %d asset folder(s) in %s", len(assets), repo.repo_id) + repos.append(repo.model_copy(update={"assets": assets})) + return catalog.model_copy(update={"repos": repos}) + + async def start_refresh(self, on_reload) -> None: + """Refresh on an interval, handing each *new* catalog to ``on_reload``. + + Polled for every transport, including ``file``. A mounted catalog is not + a static one: a ConfigMap is updated in place and the catalog-sync + sidecar rewrites its target on a schedule. Before this, a rewritten file + was silently ignored until the pod restarted — the asset set stayed at + whatever it was at boot while everything upstream reported success. + + ``discover`` re-walks the repo only when the file that names the repos + changed. A repo-wide tree read on a timer is a much bigger promise than + this loop should make on its own (plan §5.2). + + Polling rather than watching: ``stat()`` behaves the same on an + ``emptyDir`` file replaced by ``os.replace``, on a ConfigMap's symlink + swap and on a developer's bind mount. Watch semantics differ across all + three. + """ + if self._settings.catalog_refresh_seconds <= 0: + logger.info("catalog refresh disabled") + return + + async def loop() -> None: + current = self._last_good + while True: + await asyncio.sleep(self._settings.catalog_refresh_seconds) + try: + catalog = await self.load() + except Exception: # noqa: BLE001 - a refresh must never kill the server + logger.exception("catalog refresh failed") + continue + # `load` returns the *same object* when nothing changed, so this + # is an exact "is there new content" test rather than a guess. + if catalog is not current: + current = catalog + on_reload(catalog) + + self._task = asyncio.create_task(loop()) + + async def stop(self) -> None: + if self._task is not None: + self._task.cancel() + try: + await self._task + except asyncio.CancelledError: + pass + self._task = None + + +def validate_catalog(catalog: Catalog) -> None: + """Reject a catalog that would serve nothing, or serve it ambiguously. + + Public because the catalog-sync sidecar gates on exactly this before it + publishes a file the service will later load: a check living in only one of + the two processes is a check the other one gets to disagree with, and the + disagreement surfaces as a crash-loop after the sidecar reported success. + """ + if not catalog.repos: + raise CatalogError("catalog lists no repos") + seen: set[str] = set() + for repo in catalog.repos: + if "/" not in repo.repo_id: + raise CatalogError(f"repo_id must be /: {repo.repo_id!r}") + if repo.key in seen: + raise CatalogError(f"duplicate repo in catalog: {repo.repo_id!r}") + seen.add(repo.key) + if not repo.assets and repo.discover is None: + raise CatalogError( + f"repo {repo.repo_id!r} lists no assets and no discover block — it would serve nothing" + ) diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/catalog/model.py b/docker/hf-space/hf-storage-api/hf_storage_api/catalog/model.py new file mode 100644 index 0000000000000000000000000000000000000000..b1eba261e289914c2692b9015f40c2d4d432aae1 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/catalog/model.py @@ -0,0 +1,174 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""The catalog: which repos, which asset folders, and how one folder is laid out. + +The catalog is the only eagerly-loaded state (plan §5.2) and it is the access +boundary (§8.4): a path that is not inside one of its asset folders is +``NOT_FOUND``, decided without any HuggingFace call. +""" + +from __future__ import annotations + +from typing import Literal + +from pydantic import BaseModel, Field, model_validator + +DEFAULT_HOST = "huggingface.co" + +# Defaults below are written for `catalog_kind="manifest"` (nvidia/simready-assets). +# `catalog_kind="wrapp"` (nvidia/srp-staging-controlled) and `catalog_kind= +# "package_entry"` (nvidia/SimReady-Internal) each swap in their own defaults for +# the fields they read differently — see `LayoutConfig._apply_kind_defaults`. +_MANIFEST_DEFAULTS = { + "manifest": "com.nvidia.simready.packaging.json", + "metadata": "{data_dir}/{asset_name}.json", + "content_fallback": "{data_dir}/{asset_name}.usd", + "thumbs_dir": "{data_dir}/.thumbs", + "marker": "com.nvidia.simready.packaging.json", +} +_WRAPP_DEFAULTS = { + "manifest": "metadata.json", + "metadata": "{stem}.json", + "content_fallback": "{stem}.usd", + "thumbs_dir": ".thumbs", + "marker": "com.nvidia.simready.packaging.json", # unused by `wrapp` (marker_suffix instead) +} +# `package_entry.json` plays double duty: it is both the discovery marker and the +# root-USD pointer (its `usd` field), the same way `.wrapp` is for `wrapp` — see +# `store.py:_resolve_root_usd`. `manifest`/`metadata` are repurposed for the +# two-tier `GetMetadata` merge (plan docs/plans/simready-internal-catalog-kind.md +# §2.3): `delivery.json` (validation status, lower priority) under `asset.json` +# (business metadata, higher priority) — both fixed filenames at the asset +# folder's root, so `data_dir` is unused by this kind. +_PACKAGE_ENTRY_DEFAULTS = { + "manifest": "delivery.json", + "metadata": "asset.json", + "content_fallback": "{data_dir}/{asset_name}.usd", # unused — see §2.2's fallback + "thumbs_dir": "{data_dir}/.thumbs", # unused — this kind uses `thumbnail` instead + "marker": "package_entry.json", +} + + +class LayoutConfig(BaseModel): + """How to read one asset folder. Every path is relative to the asset folder + and every one of them is a fallback — a missing optional file is not an error + (plan §6.3). + + ``catalog_kind`` picks which HuggingFace layout convention this repo uses — + it is a *layout* switch, not to be confused with HF's own ``repo_type`` + (dataset/model/space) on :class:`RepoConfig`: + + - ``manifest`` (default) — nvidia/simready-assets. A fixed-name marker file + (``com.nvidia.simready.packaging.json``) per asset folder; the root USD + comes from an optional ``root_usd_index`` sidecar, else the naming + convention. + - ``wrapp`` — nvidia/srp-staging-controlled. Each *version* subfolder + (``//``) carries a ``..wrapp`` catalog + manifest, so a version is discovered as its own asset — multiple versions + of one asset coexist as distinct addresses, nothing extra required. The + root USD comes from ``output_manifest``'s ``output`` map instead of a + root-USD index file. + - ``package_entry`` — nvidia/SimReady-Internal. A fixed-name marker file + (``package_entry.json``) per asset folder whose own ``usd`` field *is* the + root-USD pointer — no separate index sidecar. Metadata is a fixed two-tier + merge (``delivery.json`` under ``asset.json``) instead of + ``{data_dir}``-templated filenames, and the thumbnail is a fixed file + (``thumbnail.png``) at the asset folder's root rather than a + ``.thumbs//`` convention — see ``thumbnail`` below. + """ + + catalog_kind: Literal["manifest", "wrapp", "package_entry"] = "manifest" + manifest: str = _MANIFEST_DEFAULTS["manifest"] + root_usd_index: str = ".metadata/com.nvidia.simready.root_usds.json" + data_dir: str = "simready_usd" + metadata: str = _MANIFEST_DEFAULTS["metadata"] + content_fallback: str = _MANIFEST_DEFAULTS["content_fallback"] + thumbs_dir: str = _MANIFEST_DEFAULTS["thumbs_dir"] + marker: str = _MANIFEST_DEFAULTS["marker"] + # `wrapp` only: the wrapp filename varies per asset (`.{folder}.wrapp`), so + # discovery matches it by suffix instead of an exact name (plan §6.3). + marker_suffix: str = ".wrapp" + # `wrapp` only: fixed-name sidecar whose `output` map is `{stem: root_usd}`. + output_manifest: str = "metadata.json" + # `package_entry` only: a fixed file at the asset folder's root, in place of + # the nucleus `.thumbs//` convention `thumbs_dir` assumes. `None` for + # `manifest`/`wrapp`, which keep today's nucleus-only lookup. + thumbnail: str | None = None + + @model_validator(mode="after") + def _apply_kind_defaults(self) -> LayoutConfig: + """Swap in this ``catalog_kind``'s defaults for fields left unset by the + caller. + + A field is "left unset" here if it still equals the ``manifest``-kind + default — the only signal available once pydantic has already applied + class-level defaults. An explicit override in the catalog always wins. + """ + defaults = {"wrapp": _WRAPP_DEFAULTS, "package_entry": _PACKAGE_ENTRY_DEFAULTS}.get(self.catalog_kind) + if defaults is None: + return self + for field, manifest_default in _MANIFEST_DEFAULTS.items(): + if getattr(self, field) == manifest_default: + setattr(self, field, defaults[field]) + if self.catalog_kind == "wrapp" and self.data_dir == "simready_usd": + self.data_dir = "" + if self.catalog_kind == "package_entry": + if self.data_dir == "simready_usd": + self.data_dir = "" + if self.thumbnail is None: + self.thumbnail = "thumbnail.png" + return self + + def render(self, template: str, asset_name: str, *, stem: str | None = None) -> str: + """Resolve ``{asset_name}`` / ``{data_dir}`` / ``{stem}`` for one asset. + + ``stem`` is the short per-asset name used in filenames under + ``catalog_kind="wrapp"`` (e.g. ``sm_IV_pole_a01_01``), which differs + from ``asset_name`` — the full folder path used for addressing — + whenever that path carries a version segment. Defaults to + ``asset_name`` for ``catalog_kind="manifest"``, where the two coincide. + """ + return template.format( + asset_name=asset_name, data_dir=self.data_dir, stem=stem if stem is not None else asset_name + ) + + +class DiscoverConfig(BaseModel): + root: str = "" + marker: str | None = None + + +class RepoConfig(BaseModel): + repo_id: str + repo_type: str = "dataset" + revision: str = "main" + endpoint: str | None = None # overrides the catalog-level endpoint + token: str | None = None # overrides the service token, for cross-org catalogs + assets: list[str] = Field(default_factory=list) + discover: DiscoverConfig | None = None + layout: LayoutConfig | None = None # overrides the catalog-level layout + + @property + def key(self) -> str: + return f"{self.repo_type}:{self.repo_id}" + + +class Catalog(BaseModel): + """A parsed catalog. Immutable in practice: reloads build a new one and swap + the reference (plan §6.3).""" + + endpoint: str = f"https://{DEFAULT_HOST}" + repos: list[RepoConfig] = Field(default_factory=list) + layout: LayoutConfig = Field(default_factory=LayoutConfig) + + def layout_for(self, repo: RepoConfig) -> LayoutConfig: + return repo.layout or self.layout + + def repo(self, repo_type: str, repo_id: str) -> RepoConfig | None: + key = f"{repo_type}:{repo_id}" + return next((r for r in self.repos if r.key == key), None) + + def host(self, repo: RepoConfig) -> str: + endpoint = repo.endpoint or self.endpoint + return endpoint.split("://", 1)[-1].rstrip("/") diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/catalog/urllist.py b/docker/hf-space/hf-storage-api/hf_storage_api/catalog/urllist.py new file mode 100644 index 0000000000000000000000000000000000000000..0454f319df3104d5b029d43c74cacae7f9accb21 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/catalog/urllist.py @@ -0,0 +1,203 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Build a catalog from a plain list of HuggingFace file URLs. + +This is the input format the original ask described — "the initial list of asset +URLs comes from a config file (alternatively fetched from a GitHub repo)" — and +it is strictly richer than the YAML catalog's ``assets:`` list, because each line +already encodes the repo, the repo type, the pinned revision *and* the asset +folder:: + + https://huggingface.co /datasets /nvidia/simready-assets /resolve/ // + └─── endpoint ───┘ └─ type ─┘ └───── repo_id ─────┘ └─ revision ─┘ └── folder ──┘ + +So a whole :class:`~hf_storage_api.catalog.model.Catalog` is derivable from the +list, with no YAML at all. + +**Each line must point at a file sitting at the asset folder's root** — the +manifest, in practice. The asset folder is that file's parent directory; a URL +pointing deeper (at the root USD, say) would yield the wrong folder, so those are +rejected rather than silently mis-parsed. +""" + +from __future__ import annotations + +import logging +import posixpath +from collections import OrderedDict +from urllib.parse import unquote, urlsplit + +from .model import DEFAULT_HOST, Catalog, LayoutConfig, RepoConfig + +logger = logging.getLogger(__name__) + +# The web UI hands out /blob/ links and the API /resolve/ ones; both address the +# same file, so accept either rather than making someone hand-edit 18 URLs. +_REF_SEGMENTS = ("resolve", "blob", "raw") + +_REPO_TYPE_BY_PREFIX = {"datasets": "dataset", "spaces": "space"} + +_CONTENT_SUFFIXES = (".usd", ".usda", ".usdc", ".usdz") + + +class UrlListError(ValueError): + """The list is not parseable as HuggingFace file URLs.""" + + +def looks_like_url_list(text: str) -> bool: + """Does this content look like a URL list rather than a YAML catalog?""" + for line in text.splitlines(): + stripped = line.strip() + if not stripped or stripped.startswith("#"): + continue + return stripped.startswith(("http://", "https://")) + return False + + +def _parse_line(line: str) -> tuple[str, str, str, str, str, str]: + """-> (endpoint, repo_type, repo_id, revision, folder, filename).""" + split = urlsplit(line) + if split.scheme not in ("http", "https") or not split.netloc: + raise UrlListError(f"not an absolute http(s) URL: {line!r}") + + segments = [unquote(s) for s in split.path.split("/") if s] + + repo_type = "model" + if segments and segments[0] in _REPO_TYPE_BY_PREFIX: + repo_type = _REPO_TYPE_BY_PREFIX[segments[0]] + segments = segments[1:] + + # //// + if len(segments) < 5 or segments[2] not in _REF_SEGMENTS: + raise UrlListError(f"expected ...///resolve// in {line!r}") + + repo_id = f"{segments[0]}/{segments[1]}" + revision = segments[3] + path = "/".join(segments[4:]) + folder, filename = posixpath.split(path) + + if not folder: + raise UrlListError(f"{line!r} points at a file in the repo root, so it names no asset folder") + if filename.lower().endswith(_CONTENT_SUFFIXES): + # Parent-of-a-USD is the data dir, not the asset folder — deriving from it + # would silently produce a catalog that serves the wrong subtree. + raise UrlListError( + f"{line!r} points at a USD file; the list must reference each asset's " + f"manifest at the asset-folder root, not its content" + ) + + return f"{split.scheme}://{split.netloc}", repo_type, repo_id, revision, folder, filename + + +def normalize_asset_urls(catalog: Catalog) -> Catalog: + """Let a YAML ``assets:`` entry be a full HuggingFace URL, not just a folder. + + The two catalog formats then accept the same lines, so a list of asset URLs + can be pasted straight into a YAML catalog when you also need something YAML + -only (a per-repo layout, a per-repo token). Without this, a pasted URL would + be taken as a literal folder name and every path under it would 404 at request + time rather than failing at load time. + """ + repos = [] + for repo in catalog.repos: + if not any(a.startswith(("http://", "https://")) for a in repo.assets): + repos.append(repo) + continue + + folders: list[str] = [] + for entry in repo.assets: + if not entry.startswith(("http://", "https://")): + folders.append(entry) + continue + _, repo_type, repo_id, revision, folder, _ = _parse_line(entry) + if (repo_type, repo_id) != (repo.repo_type, repo.repo_id): + raise UrlListError( + f"{entry!r} addresses {repo_type} {repo_id!r}, but it is listed under " + f"{repo.repo_type} {repo.repo_id!r}" + ) + if revision != repo.revision: + # Adopting it silently would make `revision:` a lie for the other + # entries; say which one to change. + raise UrlListError( + f"{entry!r} pins revision {revision!r}, but the repo is configured " + f"with revision {repo.revision!r} — set `revision: {revision}`" + ) + folders.append(folder) + repos.append(repo.model_copy(update={"assets": folders})) + return catalog.model_copy(update={"repos": repos}) + + +def parse_url_list(text: str, *, layout: LayoutConfig | None = None) -> Catalog: + """Turn a newline-separated list of HF file URLs into a catalog. + + Blank lines and ``#`` comments are ignored. Lines are grouped into one + :class:`RepoConfig` per (endpoint, repo type, repo id, revision). + """ + layout = layout or LayoutConfig() + grouped: OrderedDict[tuple[str, str, str, str], set[str]] = OrderedDict() + manifests: set[str] = set() + endpoints: set[str] = set() + + for number, raw in enumerate(text.splitlines(), start=1): + line = raw.strip() + if not line or line.startswith("#"): + continue + try: + endpoint, repo_type, repo_id, revision, folder, filename = _parse_line(line) + except UrlListError as exc: + raise UrlListError(f"line {number}: {exc}") from exc + grouped.setdefault((endpoint, repo_type, repo_id, revision), set()).add(folder) + manifests.add(filename) + endpoints.add(endpoint) + + if not grouped: + raise UrlListError("the URL list is empty") + + # One repo at two revisions cannot be served under one URI namespace: the + # revision is configuration, not part of the address, so both would collide on + # the same base_key. The `@` escape hatch is plan §6.1 / checklist 4.4. + by_repo: dict[tuple[str, str, str], list[str]] = {} + for endpoint, repo_type, repo_id, revision in grouped: + by_repo.setdefault((endpoint, repo_type, repo_id), []).append(revision) + for (_, _, repo_id), revisions in by_repo.items(): + if len(revisions) > 1: + raise UrlListError( + f"{repo_id} appears at {len(revisions)} revisions ({', '.join(sorted(revisions))}); " + f"one URI namespace can only serve one revision per repo" + ) + + # The list names the manifest, so it also tells us the layout's marker — but + # only adopt it when the list agrees with itself and differs from the default. + inferred: LayoutConfig | None = None + if len(manifests) == 1: + manifest = next(iter(manifests)) + if manifest != layout.manifest: + inferred = layout.model_copy(update={"manifest": manifest, "marker": manifest}) + logger.info("inferred layout.manifest=%s from the URL list", manifest) + elif len(manifests) > 1: + logger.warning( + "URL list references %d different filenames (%s); keeping the configured layout", + len(manifests), + ", ".join(sorted(manifests)[:3]), + ) + + catalog_endpoint = next(iter(endpoints)) if len(endpoints) == 1 else f"https://{DEFAULT_HOST}" + repos = [ + RepoConfig( + repo_id=repo_id, + repo_type=repo_type, + revision=revision, + # Only pin a per-repo endpoint when the list spans several hosts. + endpoint=endpoint if len(endpoints) > 1 else None, + assets=sorted(folders), + ) + for (endpoint, repo_type, repo_id, revision), folders in grouped.items() + ] + + logger.info("URL list: %d repo(s), %d asset(s)", len(repos), sum(len(r.assets) for r in repos)) + return Catalog( + endpoint=catalog_endpoint, + repos=repos, + layout=inferred or layout, + ) diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/__init__.py b/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..0caebeb0b83f0e91f3477577b0e9e63e3921b6e6 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/__init__.py @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Fetch the asset list from where it is authored and publish it for the service. + +A separate process — an init container and then a sidecar — sharing this image +with the server but nothing else. See ``docs/plans/github-catalog-sidecar.md``. + +Two sources, one publish path: + +* :mod:`.github` — the GitHub Contents API, which can list a directory and pin a + ref (sidecar plan §2.2); +* :mod:`.http_source` — any URL that serves the list, with an optional + credential. This is how GitLab is read, and it is deliberately generic: the + alternative was a second forge's pagination, media types and error codes in + here (sidecar plan §13). + +Why a process rather than a fourth transport inside ``CatalogLoader``: + +* the way asset URLs are sourced is the part expected to change, and a sidecar + absorbs that without touching the process that answers RPCs (sidecar plan + §8-A) — the second source above is that prediction coming true; +* it keeps the source credential out of the serving process; +* it gives somewhere to *validate before publishing*. The service's last-good + fallback covers a failed fetch; it does not cover a successful fetch of a bad + file, which becomes the access boundary the instant it lands (plan §8.4). + +The validation is the service's own parser, imported rather than reimplemented: +a sidecar that accepts a file the server then rejects is a crash-loop reported +as a success. +""" + +from .publish import CatalogRejected, Publication, publish, review +from .settings import CatalogSyncSettings +from .source import SourceAuthError, SourceError, SourceNotFound, SourceUnavailable + +__all__ = [ + "CatalogRejected", + "CatalogSyncSettings", + "Publication", + "SourceAuthError", + "SourceError", + "SourceNotFound", + "SourceUnavailable", + "publish", + "review", +] diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/__main__.py b/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/__main__.py new file mode 100644 index 0000000000000000000000000000000000000000..4a115f440fd475ee37b76a92ff3540bfe9260c3d --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/__main__.py @@ -0,0 +1,177 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Entry point for the catalog-sync init container and sidecar. + +:: + + python -m hf_storage_api.catalog_sync --once # init container: fetch or fail + python -m hf_storage_api.catalog_sync # sidecar: fetch, then poll + +The two differ only in what a failure means, and that asymmetry is deliberate +(sidecar plan §2.6). At startup there is no last-good file, so failing loudly is +the only honest option: a pod that comes up with no catalog serves ``NOT_FOUND`` +for everything, which looks like a HuggingFace outage. Once a good file exists, +the plan's standing rule applies — never fail a crawl because the source blipped. + +Which source is read is settings' business, not this module's: everything below +is written against ``fetch``/``describe``, so adding a third source does not +touch the publish path or the failure policy. +""" + +from __future__ import annotations + +import argparse +import asyncio +import logging +import signal +import sys + +from ..catalog.loader import CatalogError +from .github import GitHubClient +from .http_source import HttpClient +from .publish import CatalogRejected, known_etags, publish, review +from .settings import CatalogSyncSettings +from .source import SourceError + +logger = logging.getLogger("hf_storage_api.catalog_sync") + +EXIT_OK = 0 +EXIT_FETCH = 1 # could not read the source +EXIT_INVALID = 2 # read it, and it must not be served + + +async def sync_once(settings: CatalogSyncSettings, client: GitHubClient | HttpClient) -> bool: + """One fetch/validate/publish pass. ``False`` means "nothing had changed".""" + target = settings.catalog_sync_target + sources = settings.sources + fetched = await client.fetch(sources, known=known_etags(target)) + if fetched is None: + return False + + catalog = review( + fetched.text, + allowed_repos=settings.allowed_repos, + min_assets=settings.catalog_min_assets, + ) + published = publish( + fetched.text, + target, + catalog=catalog, + etags=fetched.etags, + source=client.describe(sources), + ) + if not published.written: + return False + + logger.info( + "published %d asset(s) across %s to %s from %s [%s]", + published.asset_count, + ", ".join(published.repo_ids), + target, + client.source, + ", ".join(f"{path}@{_stamp(etag)}" for path, etag in sorted(published.etags.items())), + ) + return True + + +def _stamp(etag: str) -> str: + """Which version was published, short enough to read in a log line. + + On GitHub the etag *is* the git blob sha (sidecar plan §1.4), so this prints + one. Elsewhere it is whatever validator the server chose; it still answers + "did this change" when compared against `catalog.meta.json`. + """ + return etag.strip('W/"')[:12] + + +def build_client(settings: CatalogSyncSettings) -> GitHubClient | HttpClient: + """The source named by the settings (sidecar plan §13).""" + if settings.source_kind == "http": + return HttpClient( + token=settings.resolve_token(), + auth=settings.catalog_http_auth, + timeout=settings.catalog_sync_timeout, + ) + return GitHubClient( + api=settings.catalog_github_api, + repo=settings.catalog_github_repo, + ref=settings.catalog_github_ref, + token=settings.resolve_token(), + timeout=settings.catalog_sync_timeout, + ) + + +async def run(settings: CatalogSyncSettings, *, once: bool) -> int: + client = build_client(settings) + stop = _stop_event() + try: + while True: + try: + if not await sync_once(settings, client): + logger.debug("no change") + except SourceError as exc: + if once: + logger.error("could not read the asset list: %s", exc) + return EXIT_FETCH + logger.warning("catalog sync failed (%s); keeping the published copy", exc) + except (CatalogError, CatalogRejected) as exc: + # Loud, and never fatal once something good is already published: + # the previous file keeps serving while someone fixes the source. + logger.error("refusing to publish the fetched list: %s", exc) + if once: + return EXIT_INVALID + + if once: + return EXIT_OK + try: + await asyncio.wait_for(stop.wait(), timeout=settings.catalog_sync_interval) + except asyncio.TimeoutError: + continue + logger.info("stopping") + return EXIT_OK + finally: + await client.aclose() + + +def _stop_event() -> asyncio.Event: + """SIGTERM ends the loop between passes rather than mid-publish.""" + stop = asyncio.Event() + loop = asyncio.get_running_loop() + for sig in (signal.SIGINT, signal.SIGTERM): + try: + loop.add_signal_handler(sig, stop.set) + except NotImplementedError: # pragma: no cover - not POSIX + pass + return stop + + +def main(argv: list[str] | None = None) -> int: + parser = argparse.ArgumentParser( + prog="python -m hf_storage_api.catalog_sync", + description="Fetch the asset list from its source and publish it for the service to read.", + ) + parser.add_argument( + "--once", + action="store_true", + help="fetch, validate, publish and exit — the init-container mode", + ) + args = parser.parse_args(argv) + + try: + settings = CatalogSyncSettings() + except ValueError as exc: + # A misconfigured sidecar must not look like an unreachable GitHub. + print(f"catalog-sync is misconfigured: {exc}", file=sys.stderr) + return EXIT_INVALID + + logging.basicConfig( + level=settings.log_level.upper(), + format="%(asctime)s %(levelname)s %(name)s %(message)s", + ) + once = args.once or settings.catalog_sync_interval <= 0 + return asyncio.run(run(settings, once=once)) + + +if __name__ == "__main__": # pragma: no cover + raise SystemExit(main()) diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/github.py b/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/github.py new file mode 100644 index 0000000000000000000000000000000000000000..7e237be35996f7c85f7cbe545aadf72498b1fe6d --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/github.py @@ -0,0 +1,234 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Reading files out of a private GitHub repo (sidecar plan §2.2). + +The Contents API rather than ``raw.githubusercontent.com``: it is the documented +way to authenticate with a header, it answers conditional requests, and it makes +a directory listable. Verified against the real private repo on 2026-08-24 +(sidecar plan §1.4): + +* ``Accept: application/vnd.github.raw`` returns the file's **bytes**. Without it + the same call returns JSON with a base64 ``content`` field. +* The ``ETag`` **is the git blob sha**, so it doubles as provenance. +* ``If-None-Match`` yields ``304`` and costs no rate-limit quota. +* A **directory** answers with a JSON array *even under the raw media type*, so + file and directory are distinguishable from the response alone, with no extra + probe call. + +The retry policy, the exception hierarchy and the fetched-file shapes are shared +with the other source (:mod:`.source`); only the classification below is +GitHub's own. +""" + +from __future__ import annotations + +import json +import logging +from dataclasses import dataclass +from typing import Any + +import httpx + +from .source import ( + RETRY_STATUSES, + Answer, + Fetched, + Requester, + Source, + SourceAuthError, + SourceError, + SourceNotFound, + SourceUnavailable, + retry_after, + usable_token, +) + +logger = logging.getLogger(__name__) + +# The hierarchy is shared — a caller catching one of these wants "the source +# could not be read", not "GitHub specifically could not be read". The aliases +# keep this module readable at the `raise` sites. +GitHubError = SourceError +GitHubAuthError = SourceAuthError +GitHubNotFound = SourceNotFound +GitHubUnavailable = SourceUnavailable + +TOKEN_SETTING = "HF_ADAPTER_CATALOG_GITHUB_TOKEN" + +_ACCEPT = "application/vnd.github.raw" +_API_VERSION = "2022-11-28" + +__all__ = [ + "RETRY_STATUSES", + "Fetched", + "GitHubAuthError", + "GitHubClient", + "GitHubError", + "GitHubNotFound", + "GitHubUnavailable", + "Source", + "retry_after", +] + + +@dataclass(frozen=True) +class _Answer(Answer): + """A Contents API response. ``listing`` is set iff the path is a directory.""" + + listing: list[dict[str, Any]] | None = None + + +class GitHubClient: + """Reads the configured paths out of one repo at one ref.""" + + def __init__( + self, + *, + api: str, + repo: str, + ref: str, + token: str | None = None, + timeout: float = 30.0, + max_retries: int = 3, + backoff_base: float = 0.5, + client: httpx.AsyncClient | None = None, + ) -> None: + self._api = api.rstrip("/") + self._repo = repo + self._ref = ref + self._token = token + self._http = Requester( + label="GitHub", + timeout=timeout, + max_retries=max_retries, + backoff_base=backoff_base, + client=client, + ) + + async def aclose(self) -> None: + await self._http.aclose() + + @property + def source(self) -> str: + return f"{self._repo}@{self._ref}" + + def describe(self, paths: list[str]) -> dict[str, object]: + """What to record in ``catalog.meta.json`` about where this came from.""" + return {"repo": self._repo, "ref": self._ref, "paths": list(paths)} + + # -- request plumbing ----------------------------------------------------- + + def _headers(self, etag: str | None) -> dict[str, str]: + headers = {"Accept": _ACCEPT, "X-GitHub-Api-Version": _API_VERSION} + if self._token: + headers["Authorization"] = f"Bearer {usable_token(self._token, setting=TOKEN_SETTING)}" + if etag: + headers["If-None-Match"] = etag + return headers + + def _url(self, path: str) -> str: + return f"{self._api}/repos/{self._repo}/contents/{path}" + + async def _get(self, path: str, *, etag: str | None = None) -> _Answer: + url = self._url(path) + # 401/403/404 come back unretried, to be classified below: they are + # configuration, not weather. + response = await self._http.get(url, headers=self._headers(etag), params={"ref": self._ref}) + return self._classify(response, url) + + def _classify(self, response: httpx.Response, url: str) -> _Answer: + etag = response.headers.get("ETag") + if response.status_code == 304: + return _Answer(not_modified=True, etag=etag) + if response.status_code in (401, 403): + raise GitHubAuthError( + f"{response.status_code} from {url}: " + + ( + f"check {TOKEN_SETTING} — a fine-grained PAT expires, and this is what that looks like" + if self._token + else f"no token is set; a private repo needs {TOKEN_SETTING}, and an " + "anonymous caller is rate limited to 60 requests an hour" + ) + ) + if response.status_code == 404: + raise GitHubNotFound( + f"404 from {url}: check the repo, path and ref" + + ("" if self._token else " — a private repo read without a token answers this way") + ) + if response.status_code >= 400: + raise GitHubUnavailable(f"{response.status_code} from {url}: {response.text[:200]}") + + listing = _as_listing(response) + if listing is not None: + return _Answer(listing=listing, etag=etag) + return _Answer(text=response.text, etag=etag) + + # -- the one call --------------------------------------------------------- + + async def fetch(self, paths: list[str], *, known: dict[str, str] | None = None) -> Fetched | None: + """Resolve ``paths`` to their contents, or ``None`` when nothing changed. + + ``known`` maps a file path to the blob sha it was last published at. + Only files are conditionally fetched: a directory listing that answered + ``304`` would tell us its membership is unchanged while handing back no + children, so there would be nothing to fetch. A configured path absent + from ``known`` is therefore fetched unconditionally, which is one request + against a 5000/hr budget. + + ``None`` comes back only when *every* resolved path answered ``304`` + **and** the set of resolved paths is itself unchanged — a file appearing + in or vanishing from a directory changes the catalog even when every + surviving file is byte-identical. + + When anything did change the whole file is rebuilt, so paths that + answered ``304`` are re-fetched unconditionally. That spends an extra + round trip in exactly the case that is rare (sidecar plan §0.1), and it + keeps this free of a content cache that would have to survive a restart + to be worth having. + """ + known = known or {} + resolved: list[tuple[str, _Answer]] = [] + + for path in paths: + answer = await self._get(path, etag=known.get(path)) + if answer.listing is None: + resolved.append((path, answer)) + continue + if not answer.listing: + logger.warning("%s is an empty directory in %s", path, self.source) + # Sorted rather than left in GitHub's order: the published file has to + # be byte-stable across runs, or every poll looks like a change. + for child in sorted(_files_in(answer.listing), key=lambda entry: entry["path"]): + child_path = child["path"] + resolved.append((child_path, await self._get(child_path, etag=known.get(child_path)))) + + if not resolved: + raise GitHubNotFound(f"{paths} resolved to no files in {self.source}") + + if known and {path for path, _ in resolved} == set(known): + if all(answer.not_modified for _, answer in resolved): + logger.debug("source unchanged: %d file(s) answered 304", len(resolved)) + return None + + sources = [] + for path, answer in resolved: + if answer.not_modified: + answer = await self._get(path) + sources.append(Source(path=path, text=answer.text or "", etag=answer.etag)) + return Fetched(sources=tuple(sources)) + + +def _files_in(listing: list[dict[str, Any]]) -> list[dict[str, Any]]: + return [entry for entry in listing if entry.get("type") == "file"] + + +def _as_listing(response: httpx.Response) -> list[dict[str, Any]] | None: + """A directory answers with a JSON array even under the raw media type.""" + if "json" not in response.headers.get("Content-Type", ""): + return None + try: + payload = json.loads(response.text) + except ValueError: # pragma: no cover - a JSON content type carrying non-JSON + return None + return payload if isinstance(payload, list) else None diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/http_source.py b/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/http_source.py new file mode 100644 index 0000000000000000000000000000000000000000..59aa82be8988a33b6909b649329ea864f3aa540f --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/http_source.py @@ -0,0 +1,207 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Reading the asset list from a plain URL, with a credential (sidecar plan §13). + +The generic source: one ``GET`` per configured URL, an optional auth header, and +``ETag``/``If-None-Match`` for the unchanged case. No vendor API — which is the +point. It reaches GitLab, an artifact store, or anything else that will serve the +list over HTTPS, without this process learning a second forge's pagination, +media types and error codes. + +**Why not just point ``HF_ADAPTER_CATALOG_URL`` at it.** That transport lives in +the server and has no validation gate: a successful fetch of a bad file becomes +the access boundary the instant it lands (plan §8.4). Here the same fetch is +followed by the server's own parser, the repo allowlist and the asset floor +before anything is published. The credential also stays out of the process that +answers RPCs (sidecar plan §0.1). + +Verified against ``gitlab-master.nvidia.com`` on 2026-08-25: + +* ``…/-/raw//`` answers ``200 text/plain`` with an ``ETag``, and + ``If-None-Match`` against it yields a real ``304`` — but only in the strong + form, which is what :func:`_strong` exists for. Read that before touching the + conditional path; it is the difference between an hourly poll costing nothing + and re-downloading the list forever. +* ``Cache-Control: max-age=60`` — polling faster than that buys nothing, same as + GitHub's Contents API. +* The GitLab **API** raw endpoint (``/api/v4/projects/:id/repository/files``) + sends *no* ``ETag`` and ignores ``If-None-Match``, so the web raw route is the + one to configure. Provenance is then the ETag rather than a blob sha; the + published record in ``catalog.meta.json`` says which. +""" + +from __future__ import annotations + +import logging +from typing import Literal + +import httpx + +from .source import ( + Answer, + Fetched, + Requester, + Source, + SourceAuthError, + SourceNotFound, + SourceUnavailable, + usable_token, +) + +logger = logging.getLogger(__name__) + +TOKEN_SETTING = "HF_ADAPTER_CATALOG_HTTP_TOKEN" + +AuthStyle = Literal["bearer", "private-token"] + +# GitLab and GitHub both want a token in a header, and disagree about which one. +# A header *name* knob would let a values file invent one that means nothing; two +# named styles cover every host this is meant for and stay checkable. +_HEADER = {"bearer": "Authorization", "private-token": "PRIVATE-TOKEN"} +_PREFIX = {"bearer": "Bearer ", "private-token": ""} + +__all__ = ["HttpClient"] + + +class HttpClient: + """Fetches each configured URL, conditionally when we have an ``ETag``.""" + + def __init__( + self, + *, + token: str | None = None, + auth: AuthStyle = "bearer", + timeout: float = 30.0, + max_retries: int = 3, + backoff_base: float = 0.5, + client: httpx.AsyncClient | None = None, + ) -> None: + self._token = token + self._auth: AuthStyle = auth + self._http = Requester( + label="catalog source", + timeout=timeout, + max_retries=max_retries, + backoff_base=backoff_base, + client=client, + ) + + async def aclose(self) -> None: + await self._http.aclose() + + @property + def source(self) -> str: + return "the configured URL(s)" + + def describe(self, urls: list[str]) -> dict[str, object]: + """What to record in ``catalog.meta.json`` about where this came from.""" + return {"urls": list(urls)} + + # -- request plumbing ----------------------------------------------------- + + def _headers(self, etag: str | None) -> dict[str, str]: + headers: dict[str, str] = {} + if self._token: + token = usable_token(self._token, setting=TOKEN_SETTING) + headers[_HEADER[self._auth]] = f"{_PREFIX[self._auth]}{token}" + if etag: + headers["If-None-Match"] = _strong(etag) + return headers + + async def _get(self, url: str, *, etag: str | None = None) -> Answer: + response = await self._http.get(url, headers=self._headers(etag)) + return self._classify(response, url) + + def _classify(self, response: httpx.Response, url: str) -> Answer: + etag = response.headers.get("ETag") + if response.status_code == 304: + return Answer(not_modified=True, etag=etag) + if response.status_code in (401, 403): + raise SourceAuthError( + f"{response.status_code} from {url}: " + + ( + f"check {TOKEN_SETTING} — tokens expire, and this is what that " + f"looks like. HF_ADAPTER_CATALOG_HTTP_AUTH={self._auth} decides which " + "header it is sent in; GitLab wants `private-token`" + if self._token + else f"no credential is set; a private source needs {TOKEN_SETTING}" + ) + ) + if response.status_code == 404: + raise SourceNotFound( + f"404 from {url}: check the URL, including the branch or tag in it" + + ("" if self._token else " — a private source read without a credential answers this way") + ) + if response.status_code >= 400: + raise SourceUnavailable(f"{response.status_code} from {url}: {response.text[:200]}") + + # An HTML body is never the list, and it is what both easy mistakes + # produce: a `/-/blob/` or `/blob/` URL serves the web UI, and a private + # source read without a credential redirects to a sign-in page. Both + # would otherwise reach the parser, which reports a format error and + # points at the file rather than at the URL. + if response.headers.get("Content-Type", "").startswith("text/html"): + raise SourceNotFound( + f"{url} answered with an HTML page rather than the asset list. A " + "`/-/blob/` (GitLab) or `/blob/` (GitHub) URL serves the web UI — use the " + "raw URL, `/-/raw//`. A private source read without a credential " + "redirects to a sign-in page and also answers this way." + ) + return Answer(text=response.text, etag=etag) + + # -- the one call --------------------------------------------------------- + + async def fetch(self, urls: list[str], *, known: dict[str, str] | None = None) -> Fetched | None: + """Fetch ``urls`` in order, or ``None`` when nothing changed. + + ``known`` maps a URL to the ``ETag`` it was last published at. ``None`` + comes back only when every configured URL answered ``304`` *and* the set + of URLs is itself unchanged, so that adding one to the list republishes + even though the others are byte-identical. + + A source serving no ``ETag`` at all is fine and costs one full download + per interval: nothing is republished unless the bytes actually differ + (:func:`~.publish.publish` compares digests), so the only cost is the + transfer. + + Mirrors :meth:`.github.GitHubClient.fetch` — including re-fetching the + ``304``s once anything has changed, because the published file is rebuilt + whole. + """ + known = known or {} + if not urls: # pragma: no cover - CatalogSyncSettings rejects this first + raise SourceNotFound("no catalog source URL is configured") + + resolved = [(url, await self._get(url, etag=known.get(url))) for url in urls] + + if known and {url for url, _ in resolved} == set(known): + if all(answer.not_modified for _, answer in resolved): + logger.debug("source unchanged: %d URL(s) answered 304", len(resolved)) + return None + + sources = [] + for url, answer in resolved: + if answer.not_modified: + answer = await self._get(url) + sources.append(Source(path=url, text=answer.text or "", etag=answer.etag)) + return Fetched(sources=tuple(sources)) + + +def _strong(etag: str) -> str: + """Send back the strong form of a validator, whatever form it arrived in. + + Verified against gitlab-master on 2026-08-25, and the reason the sidecar + would otherwise re-download the list on every single poll: + + * the raw route gzips whenever the client offers it — httpx always does — + and a gzipped response carries a **weak** etag, ``W/"35b6…"``; + * sending that weak etag back in ``If-None-Match`` is answered ``200``. + Sending ``"35b6…"`` for the same request is answered ``304``. + + RFC 7232 asks for a weak comparison on ``If-None-Match``, so the mismatch is + GitLab's; ``curl`` never sees it because it does not request gzip by default. + Stripping the prefix cannot produce a *wrong* ``304``: a strong match is + strictly narrower than the weak one we were already willing to accept. + """ + return etag[2:] if etag.startswith("W/") else etag diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/publish.py b/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/publish.py new file mode 100644 index 0000000000000000000000000000000000000000..d492b19910b560cd1cda367ea5c735b3d7051c66 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/publish.py @@ -0,0 +1,186 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Validate a fetched list, then publish it atomically (sidecar plan §2.3, §2.5). + +The order is load-bearing:: + + fetch -> parse -> guard -> write .tmp -> os.replace + +The service's last-good fallback covers a *failed fetch*. It does not cover a +*successful fetch of bad content*: that file becomes the access boundary the +instant it lands (plan §8.4). So nothing is written until it has been parsed by +the service's own parser and passed the guards. +""" + +from __future__ import annotations + +import hashlib +import json +import logging +import os +from dataclasses import dataclass +from datetime import datetime, timezone +from pathlib import Path + +from ..catalog.loader import CatalogError, parse_text, validate_catalog +from ..catalog.model import Catalog + +logger = logging.getLogger(__name__) + +META_SUFFIX = ".meta.json" + + +class CatalogRejected(Exception): + """The fetched content parsed, but must not become the access boundary.""" + + +@dataclass(frozen=True) +class Publication: + """What was published, and what it was built from.""" + + digest: str + asset_count: int + repo_ids: tuple[str, ...] + etags: dict[str, str] + written: bool + + +def review( + text: str, + *, + allowed_repos: frozenset[str] = frozenset(), + min_assets: int = 1, +) -> Catalog: + """Parse and guard, raising rather than returning anything questionable. + + Parsing is :func:`hf_storage_api.catalog.loader.parse_text` — the server's, + not a copy — so this rejects exactly what the server would reject at load + time: a truncated body, a URL pointing at a USD instead of a manifest, one + repo pinned at two revisions. + """ + if not _has_content(text): + # Caught before parsing, purely for the error message. An emptied URL list + # is all comments, `looks_like_url_list` then says "not a URL list", and + # the YAML parser reports "catalog must be a YAML mapping" — which points + # at the format rather than at the fact that every asset was withdrawn. + raise CatalogRejected("the fetched list has no entries at all") + + catalog = parse_text(text) + validate_catalog(catalog) + + assets = sum(len(repo.assets) for repo in catalog.repos) + if assets < min_assets: + # An empty-but-valid list is the failure that silently empties the USD + # Search index, and an empty index reads as "the crawl is broken" rather + # than "the catalog changed". + raise CatalogRejected( + f"the list yields {assets} asset(s), below HF_ADAPTER_CATALOG_MIN_ASSETS={min_assets}" + ) + + if allowed_repos: + unexpected = sorted({repo.repo_id for repo in catalog.repos} - allowed_repos) + if unexpected: + raise CatalogRejected( + f"the list names HuggingFace repo(s) outside the allowlist: {', '.join(unexpected)} " + f"(allowed: {', '.join(sorted(allowed_repos))})" + ) + return catalog + + +def _has_content(text: str) -> bool: + return any(line.strip() and not line.strip().startswith("#") for line in text.splitlines()) + + +def publish( + text: str, + target: Path, + *, + catalog: Catalog, + etags: dict[str, str] | None = None, + source: dict[str, object] | None = None, +) -> Publication: + """Write ``text`` to ``target`` so that no reader can ever see it half-written.""" + digest = hashlib.sha256(text.encode("utf-8")).hexdigest() + assets = sum(len(repo.assets) for repo in catalog.repos) + repo_ids = tuple(repo.repo_id for repo in catalog.repos) + previous = read_meta(target) + + if previous.get("digest") == digest and target.exists(): + # Rewriting identical bytes would move the mtime for nothing. The service + # hashes too and would decline to reload, but not touching the file at all + # keeps `ls -l` honest about when the asset set last changed. + logger.debug("catalog unchanged at %s (%s)", target, digest[:12]) + return Publication(digest, assets, repo_ids, etags or {}, written=False) + + target.parent.mkdir(parents=True, exist_ok=True) + _atomic_write(target, text) + _atomic_write( + meta_path(target), + json.dumps( + { + "digest": digest, + "asset_count": assets, + "repo_ids": list(repo_ids), + "etags": etags or {}, + "fetched_at": datetime.now(timezone.utc).isoformat(timespec="seconds"), + **(source or {}), + }, + indent=2, + sort_keys=True, + ) + + "\n", + ) + return Publication(digest, assets, repo_ids, etags or {}, written=True) + + +def meta_path(target: Path) -> Path: + """``catalog.txt`` -> ``catalog.meta.json``, beside it.""" + return target.with_suffix(META_SUFFIX) + + +def read_meta(target: Path) -> dict: + """The last publication's record, or an empty dict. + + Read on startup so a restarted sidecar resumes with a usable + ``If-None-Match`` instead of re-downloading, and readable by hand so + "which blob am I serving" is one ``cat`` away. + """ + try: + return json.loads(meta_path(target).read_text(encoding="utf-8")) + except (OSError, ValueError): + return {} + + +def known_etags(target: Path) -> dict[str, str]: + etags = read_meta(target).get("etags") + if not isinstance(etags, dict): + return {} + # Only trust the record if the file it describes is still there: an etag + # without its catalog would make us 304 our way into publishing nothing. + return {str(k): str(v) for k, v in etags.items()} if target.exists() else {} + + +def _atomic_write(path: Path, text: str) -> None: + """Write via a sibling temp file and rename. + + The temp file must live in the **same directory** as the target: one in + ``/tmp`` is on a different volume and ``os.replace`` fails with ``EXDEV`` — + and the fallback everyone reaches for, copy-then-move, puts the torn read + straight back. + """ + tmp = path.with_name(f".{path.name}.tmp") + tmp.write_text(text, encoding="utf-8") + os.replace(tmp, path) + + +__all__ = [ + "CatalogError", + "CatalogRejected", + "Publication", + "known_etags", + "meta_path", + "publish", + "read_meta", + "review", +] diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/settings.py b/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/settings.py new file mode 100644 index 0000000000000000000000000000000000000000..d184b69abbdacf50b069644be165bc53f867cce9 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/settings.py @@ -0,0 +1,153 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Configuration for the catalog-sync process (sidecar plan §4.1, §13).""" + +from __future__ import annotations + +from pathlib import Path +from typing import Literal + +from pydantic import model_validator +from pydantic_settings import BaseSettings, SettingsConfigDict + +from .http_source import AuthStyle + +SourceKind = Literal["github", "http"] + + +def _split(value: str) -> list[str]: + return [item.strip() for item in value.split(",") if item.strip()] + + +class CatalogSyncSettings(BaseSettings): + """The sync process's environment. + + Separate from :class:`~hf_storage_api.settings.Settings` because that one + *requires* an inbound gRPC auth token, and this process has no business + holding one — it never serves anything. The ``HF_ADAPTER_`` prefix is shared + on purpose, so ``tests/test_helm_chart.py``'s drift check covers the sidecar's + environment with the same rule it already applies to the server's. + + List-shaped settings are declared as comma-separated strings rather than + ``list[str]``: pydantic-settings decodes complex types from env as JSON, so + ``PATH=a,b`` would fail to parse where ``PATH=["a","b"]`` is what nobody + writes in a Helm values file. + """ + + model_config = SettingsConfigDict(env_prefix="HF_ADAPTER_", extra="ignore") + + # --- source: the GitHub Contents API (sidecar plan §2.2) ------------------ + catalog_github_repo: str = "" # / + catalog_github_path: str = "" # comma-separated files and/or directories + catalog_github_ref: str = "main" + catalog_github_api: str = "https://api.github.com" # GHE: https:///api/v3 + catalog_github_token: str | None = None + catalog_github_token_file: Path | None = None + + # --- source: a plain URL, with a credential (sidecar plan §13) ------------ + # For anything that is not GitHub — a GitLab raw URL, an artifact store. Not + # to be confused with the server's own HF_ADAPTER_CATALOG_URL, which fetches + # without a credential and without a validation gate. + catalog_http_url: str = "" # comma-separated; contents are concatenated + catalog_http_auth: AuthStyle = "bearer" # GitLab wants `private-token` + catalog_http_token: str | None = None + catalog_http_token_file: Path | None = None + + # --- target -------------------------------------------------------------- + catalog_sync_target: Path = Path("/var/lib/hf-storage-api/catalog.txt") + # An hour, and that is generous: the ceiling on how fast a *new* asset reaches + # a user is the crawler's 24 h re-scan (plan §6.9), so this interval really + # only bounds how stale a *revoked* asset may be. Under 60 s is pointless + # regardless — GitHub and GitLab both serve these with `max-age=60`. + catalog_sync_interval: float = 3600.0 + catalog_sync_timeout: float = 30.0 + + # --- guards (sidecar plan §2.3) ------------------------------------------ + # Without an allowlist, whoever can write the source file can point this + # service at any HF repo its token can read. + catalog_allowed_repos: str = "" + catalog_min_assets: int = 1 + + log_level: str = "INFO" + + @model_validator(mode="after") + def _check(self) -> CatalogSyncSettings: + chosen = [ + name + for name, configured in (("github", bool(self.catalog_github_repo)), ("http", bool(self.urls))) + if configured + ] + if len(chosen) != 1: + # Never guess. Two sources configured means someone is half way + # through a migration, and picking one for them would quietly serve + # the wrong asset set — which is also the access boundary (plan §8.4). + raise ValueError( + "set exactly one source: HF_ADAPTER_CATALOG_GITHUB_REPO (the GitHub " + "Contents API) or HF_ADAPTER_CATALOG_HTTP_URL (any URL that serves the " + f"list) — got: {', '.join(chosen) or 'neither'}" + ) + + if self.source_kind == "github": + if self.catalog_github_repo.count("/") != 1 or self.catalog_github_repo.startswith("http"): + raise ValueError( + f"HF_ADAPTER_CATALOG_GITHUB_REPO must be /, not {self.catalog_github_repo!r}" + ) + if not self.paths: + raise ValueError("HF_ADAPTER_CATALOG_GITHUB_PATH is required") + else: + bad = [url for url in self.urls if not url.startswith(("http://", "https://"))] + if bad: + raise ValueError(f"HF_ADAPTER_CATALOG_HTTP_URL must be absolute http(s) URLs, not {bad}") + + if self.catalog_min_assets < 1: + # Zero would defeat the guard it exists to be: an empty-but-valid file + # silently empties the USD Search index, and an empty index reads as a + # broken crawl rather than a changed catalog. + raise ValueError("HF_ADAPTER_CATALOG_MIN_ASSETS must be at least 1") + return self + + @property + def source_kind(self) -> SourceKind: + return "http" if self.urls else "github" + + @property + def paths(self) -> list[str]: + return [path.lstrip("/") for path in _split(self.catalog_github_path)] + + @property + def urls(self) -> list[str]: + return _split(self.catalog_http_url) + + @property + def sources(self) -> list[str]: + """What to fetch: repo paths for ``github``, URLs for ``http``.""" + return self.urls if self.source_kind == "http" else self.paths + + @property + def token_setting(self) -> str: + """The env var a credential problem should send someone to.""" + return f"HF_ADAPTER_CATALOG_{self.source_kind.upper()}_TOKEN" + + def resolve_token(self) -> str | None: + """The credential for the configured source, stripped. + + Not just for the file variant: a Kubernetes Secret populated with `echo` + carries a trailing newline and reaches us through the environment. An + unstripped token makes httpx reject the header outright, which reads as a + client bug rather than a malformed credential. + """ + if self.source_kind == "http": + token_file, token = self.catalog_http_token_file, self.catalog_http_token + else: + token_file, token = self.catalog_github_token_file, self.catalog_github_token + raw = token_file.read_text(encoding="utf-8") if token_file is not None else token + # `or None` rather than just stripping: an unset Helm value or compose + # variable renders as the empty string, and whitespace-only is the same + # thing. Both must mean "fetch anonymously", which a public source list + # is entitled to do. + return (raw.strip() if raw else "") or None + + @property + def allowed_repos(self) -> frozenset[str]: + return frozenset(_split(self.catalog_allowed_repos)) diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/source.py b/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/source.py new file mode 100644 index 0000000000000000000000000000000000000000..58b84f04e813f0a4e27ccf73a6ee8feb493909f5 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/catalog_sync/source.py @@ -0,0 +1,171 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""What every catalog source has in common (sidecar plan §2.2, §13). + +Two sources exist — the GitHub Contents API (:mod:`.github`) and a plain +authenticated URL (:mod:`.http_source`) — and they must fail *identically*: +same retry budget, same exception hierarchy, same "nothing changed" answer. A +second copy of the retry loop would be a second failure policy, and the +difference would only ever show up during an incident. + +So the parts that must not drift live here: the exceptions, the fetched-file +shapes, and the request loop. What each source keeps for itself is the part that +genuinely differs — how a response is *classified*, which is where the two APIs +have nothing in common. +""" + +from __future__ import annotations + +import asyncio +import logging +from dataclasses import dataclass + +import httpx + +from ..http_retry import retry_after + +logger = logging.getLogger(__name__) + +RETRY_STATUSES = frozenset({429, 500, 502, 503, 504}) + + +class SourceError(Exception): + """Base for anything that stopped us reading the source list.""" + + +class SourceAuthError(SourceError): + """401/403 — the credential is wrong, expired, or lost access. + + Distinct from :class:`SourceNotFound` because tokens expire on a schedule, + and this is what that looks like. + """ + + +class SourceNotFound(SourceError): + """404 — wrong repo, path, URL or ref. A private source read without a + credential looks exactly the same, deliberately: saying otherwise would leak + whether it exists.""" + + +class SourceUnavailable(SourceError): + """The retry budget ran out, or the source answered something unusable.""" + + +@dataclass(frozen=True) +class Source: + """One resolved source file, with whatever identified the version we read.""" + + path: str + text: str + etag: str | None + + +@dataclass(frozen=True) +class Fetched: + """Everything the configured paths resolved to, in a stable order.""" + + sources: tuple[Source, ...] + + @property + def text(self) -> str: + # Newline-joined so a file with no trailing newline cannot glue its last + # URL onto the next file's first one. + return "\n".join(source.text.strip("\n") for source in self.sources) + "\n" + + @property + def etags(self) -> dict[str, str]: + return {source.path: source.etag for source in self.sources if source.etag} + + +@dataclass(frozen=True) +class Answer: + """One response, already classified.""" + + not_modified: bool = False + text: str | None = None + etag: str | None = None + + +class Requester: + """The request loop, with the retry policy shared by every source. + + ``401``/``403``/``404`` are deliberately *not* retried here — they come back + to the caller to classify. They are configuration, not weather, and retrying + only delays the log line that explains them. + """ + + def __init__( + self, + *, + label: str, + timeout: float = 30.0, + max_retries: int = 3, + backoff_base: float = 0.5, + client: httpx.AsyncClient | None = None, + ) -> None: + self._label = label + self._max_retries = max_retries + self._backoff_base = backoff_base + self._client = client or httpx.AsyncClient(timeout=timeout, follow_redirects=True) + + async def aclose(self) -> None: + await self._client.aclose() + + async def get( + self, url: str, *, headers: dict[str, str], params: dict[str, str] | None = None + ) -> httpx.Response: + last: Exception | None = None + + for attempt in range(self._max_retries): + delay = self._backoff_base * (2**attempt) + try: + response = await self._client.get(url, headers=headers, params=params) + except httpx.HTTPError as exc: # connect/read errors + last = exc + logger.warning("%s request failed (%s), attempt %d: %s", self._label, url, attempt + 1, exc) + else: + if response.status_code not in RETRY_STATUSES: + return response + last = None + logger.warning( + "%s returned %d (%s), attempt %d", self._label, response.status_code, url, attempt + 1 + ) + delay = retry_after(response) or delay + await asyncio.sleep(delay) + + raise SourceUnavailable(f"GET {url} failed after {self._max_retries} attempts: {last}") + + +def usable_token(token: str, *, setting: str) -> str: + """Reject a token that could never become a header, with a message that says so. + + A Secret populated by ``echo``, or a shell error captured into the variable, + produces something httpx refuses to send — and the resulting + ``Illegal header value`` reads as a client bug, gets treated as a transient + failure, and is printed once per retry. Caught here instead, once, naming the + setting to look at. + """ + clean = token.strip() + if clean and clean.isascii() and clean.isprintable(): + return clean + raise SourceAuthError( + f"{setting} is not a usable credential: it contains whitespace or " + "non-printable characters. A Secret written with `echo`, or a failed " + "`$(...)` substitution, both look like this." + ) + + +__all__ = [ + "RETRY_STATUSES", + "Answer", + "Fetched", + "Requester", + "Source", + "SourceAuthError", + "SourceError", + "SourceNotFound", + "SourceUnavailable", + "retry_after", + "usable_token", +] diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/errors.py b/docker/hf-space/hf-storage-api/hf_storage_api/errors.py new file mode 100644 index 0000000000000000000000000000000000000000..47fe2ac440dab519f544eb34977b8e464a5ec207 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/errors.py @@ -0,0 +1,80 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""HuggingFace failures -> gRPC status (plan §5.3). + +The client's status handling is not uniform (contract doc §3.4): a listing call +that returns anything other than ``NOT_FOUND`` aborts the crawl, while +``check_if_exists`` quietly swallows four different codes. So map deliberately, +and never let an unhandled exception become ``UNKNOWN``. +""" + +from __future__ import annotations + +import functools +import logging + +import grpc + +from .hf.client import HFAuthError, HFNotFound, HFRateLimited, HFUnavailable + +logger = logging.getLogger(__name__) + +READ_ONLY_MESSAGE = ( + "hf-storage-api-service is read-only: it serves a HuggingFace dataset and implements no write RPCs" +) + + +async def unimplemented(context: grpc.aio.ServicerContext, rpc: str): + await context.abort(grpc.StatusCode.UNIMPLEMENTED, f"{rpc}: {READ_ONLY_MESSAGE}") + + +def status_for(exc: Exception) -> tuple[grpc.StatusCode, str]: + if isinstance(exc, HFNotFound): + return grpc.StatusCode.NOT_FOUND, str(exc) + if isinstance(exc, HFAuthError): + # Deliberately not NOT_FOUND: a dead token must not look like an empty + # dataset, which is a silent, successful-looking crawl of zero assets. + return grpc.StatusCode.PERMISSION_DENIED, str(exc) + if isinstance(exc, HFRateLimited): + return grpc.StatusCode.RESOURCE_EXHAUSTED, str(exc) + if isinstance(exc, HFUnavailable): + return grpc.StatusCode.UNAVAILABLE, str(exc) + return grpc.StatusCode.INTERNAL, f"{type(exc).__name__}: {exc}" + + +def handle_hf_errors(func): + """Translate upstream failures on a unary RPC into a mapped abort.""" + + @functools.wraps(func) + async def wrapper(self, request, context): + try: + return await func(self, request, context) + except grpc.aio.AbortError: + raise + except Exception as exc: # noqa: BLE001 - deliberate catch-all, mapped below + code, message = status_for(exc) + log = logger.exception if code == grpc.StatusCode.INTERNAL else logger.warning + log("%s failed: %s", func.__name__, message) + await context.abort(code, message) + + return wrapper + + +def handle_hf_errors_stream(func): + """Same, for a server-streaming RPC.""" + + @functools.wraps(func) + async def wrapper(self, request, context): + try: + async for item in func(self, request, context): + yield item + except grpc.aio.AbortError: + raise + except Exception as exc: # noqa: BLE001 - deliberate catch-all, mapped below + code, message = status_for(exc) + log = logger.exception if code == grpc.StatusCode.INTERNAL else logger.warning + log("%s failed: %s", func.__name__, message) + await context.abort(code, message) + + return wrapper diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/health.py b/docker/hf-space/hf-storage-api/hf_storage_api/health.py new file mode 100644 index 0000000000000000000000000000000000000000..c22100ecd59e47093310891e7910021efe910a69 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/health.py @@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""The standard gRPC health service, for Kubernetes probes (plan checklist 2.13). + +`grpc.health.v1.Health` rather than an HTTP sidecar port: this is a gRPC-only +server, Kubernetes has had native `grpc:` probes since 1.24, and it means the +probe exercises the same listener, the same HTTP/2 stack and the same +interceptors real traffic goes through — a TCP probe only proves something +accepted a connection. + +**What SERVING means here: the catalog is loaded.** It deliberately does *not* +reflect HuggingFace reachability. Nothing is preloaded from the Hub (plan §5.2), +so a Hub outage does not make this pod less able to serve than any other — it +would only take every replica out of the endpoints at once and turn a partial +outage into a total one. Hub failures belong in metrics and in the RPC status a +caller actually receives. +""" + +from __future__ import annotations + +import logging +from collections.abc import Mapping, Sequence + +from grpc_health.v1 import health, health_pb2, health_pb2_grpc + +from .registration import service_full_name + +logger = logging.getLogger(__name__) + +SERVICE_NAME = "grpc.health.v1.Health" +#: Prefix of every method on the health service, for the auth exemption. +METHOD_PREFIX = f"/{SERVICE_NAME}/" + +SERVING = health_pb2.HealthCheckResponse.SERVING +NOT_SERVING = health_pb2.HealthCheckResponse.NOT_SERVING + + +async def add_health_service(server, bindings: Mapping[str, Sequence[str]]) -> health.aio.HealthServicer: + """Register the health service and mark everything as serving. + + Reports on the empty service name — which is what a Kubernetes `grpc:` probe + queries by default, and what `grpc_health_probe` uses without `-service` — + plus one entry per bound (service, version) pair, so a caller can ask about + the exact path it intends to dial. + """ + servicer = health.aio.HealthServicer() + health_pb2_grpc.add_HealthServicer_to_server(servicer, server) + + names = [""] + [ + service_full_name(name, version) for name, versions in bindings.items() for version in versions + ] + for name in names: + # aio's set() is a coroutine — unawaited, nothing is ever marked SERVING + # and every probe fails with NOT_FOUND. + await servicer.set(name, SERVING) + + logger.debug("health service reporting on %d name(s)", len(names)) + return servicer + + +async def enter_graceful_shutdown(servicer: health.aio.HealthServicer) -> None: + """Flip to NOT_SERVING before the drain begins. + + Gives Kubernetes a chance to pull the pod from the Service endpoints before + connections start being refused, so a rollout does not drop in-flight calls. + """ + await servicer.enter_graceful_shutdown() diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/hf/__init__.py b/docker/hf-space/hf-storage-api/hf_storage_api/hf/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..52a7a9daf028f654d6a02f65c99cc609a57b492f --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/hf/__init__.py @@ -0,0 +1,2 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/hf/client.py b/docker/hf-space/hf-storage-api/hf_storage_api/hf/client.py new file mode 100644 index 0000000000000000000000000000000000000000..44d9f5694d21d494026b778e8f27954f78985d01 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/hf/client.py @@ -0,0 +1,245 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""The three HuggingFace Hub calls this service needs (plan §3.1): tree, +paths-info, resolve. + +A thin ``httpx`` client rather than ``huggingface_hub``: three endpoints do not +justify the dependency tree (plan §8.7). +""" + +from __future__ import annotations + +import asyncio +import logging +import re +from collections.abc import AsyncIterator, Sequence +from typing import Any + +import httpx + +from ..http_retry import retry_after +from .models import TreeEntry, parse_tree_entry + +logger = logging.getLogger(__name__) + +# Repo type -> the segment used under /api/ and in resolve URLs. Models sit at +# the bare root; datasets and spaces are namespaced. +_API_SEGMENT = {"dataset": "datasets", "model": "models", "space": "spaces"} +_URL_SEGMENT = {"dataset": "datasets", "model": "", "space": "spaces"} + +RETRY_STATUSES = frozenset({429, 500, 502, 503, 504}) + +# HF does not send `Retry-After` — it sends `RateLimit` in the +# draft-ietf-httpapi-ratelimit-headers form, e.g. `"api";r=9999;t=256`, where +# `t` is seconds until the 5-minute window resets. Verified 2026-09-01; see +# https://huggingface.co/docs/hub/main/en/rate-limits#http-headers. `retry_after` +# (imported above) stays as the fallback in case that ever changes. +_HF_RATE_LIMIT_RESET = re.compile(r"t=(\d+)") + + +def _hf_retry_delay(response: httpx.Response) -> float | None: + raw = response.headers.get("RateLimit") + if raw is not None: + match = _HF_RATE_LIMIT_RESET.search(raw) + if match: + return float(match.group(1)) + return retry_after(response) + + +class HFError(Exception): + """Base for upstream failures; mapped to gRPC status in ``errors.py``.""" + + +class HFNotFound(HFError): + pass + + +class HFAuthError(HFError): + """401/403 — the service token is wrong, expired, or lost repo access. + + Deliberately distinct from :class:`HFNotFound`: collapsing the two makes a + dead token look like an empty dataset (plan §5.3). + """ + + +class HFRateLimited(HFError): + pass + + +class HFUnavailable(HFError): + pass + + +class HFClient: + """Async HF Hub client. One instance per process; owns the connection pool.""" + + def __init__( + self, + *, + endpoint: str = "https://huggingface.co", + token: str | None = None, + timeout: float = 30.0, + max_connections: int = 20, + max_retries: int = 3, + backoff_base: float = 0.5, + client: httpx.AsyncClient | None = None, + ) -> None: + self._endpoint = endpoint.rstrip("/") + self._token = token + self._max_retries = max_retries + self._backoff_base = backoff_base + self._client = client or httpx.AsyncClient( + timeout=timeout, + limits=httpx.Limits(max_connections=max_connections), + follow_redirects=True, + ) + + async def aclose(self) -> None: + await self._client.aclose() + + # -- URL construction ----------------------------------------------------- + + def api_url(self, repo_type: str, repo_id: str, *suffix: str) -> str: + segment = _API_SEGMENT.get(repo_type, "datasets") + return "/".join([self._endpoint, "api", segment, repo_id, *[s for s in suffix if s]]) + + def resolve_url(self, repo_type: str, repo_id: str, revision: str, path: str) -> str: + segment = _URL_SEGMENT.get(repo_type, "datasets") + parts = [self._endpoint, segment, repo_id, "resolve", revision, path] + return "/".join([p for p in parts if p]) + + def _headers(self, token: str | None) -> dict[str, str]: + effective = token or self._token + return {"Authorization": f"Bearer {effective}"} if effective else {} + + # -- request plumbing ----------------------------------------------------- + + async def _request(self, method: str, url: str, *, token: str | None = None, **kwargs: Any): + last_exc: Exception | None = None + for attempt in range(self._max_retries): + try: + response = await self._client.request(method, url, headers=self._headers(token), **kwargs) + except httpx.HTTPError as exc: # connect/read errors + last_exc = exc + logger.warning("HF request failed (%s %s), attempt %d: %s", method, url, attempt + 1, exc) + else: + if response.status_code not in RETRY_STATUSES: + return self._check(response, url) + last_exc = None + logger.warning( + "HF returned %d (%s %s), attempt %d", response.status_code, method, url, attempt + 1 + ) + if response.status_code == 429 and attempt == self._max_retries - 1: + raise HFRateLimited(f"rate limited by {url}") + # Honour HF's actual reset signal rather than guessing with a + # fixed exponential curve, which can hammer a window that is + # about to reset anyway or, worse, undershoot one that has not. + delay = _hf_retry_delay(response) + if delay is not None: + await asyncio.sleep(max(delay, self._backoff_base)) + continue + await asyncio.sleep(self._backoff_base * (2**attempt)) + + raise HFUnavailable(f"{method} {url} failed after {self._max_retries} attempts: {last_exc}") + + @staticmethod + def _check(response: httpx.Response, url: str) -> httpx.Response: + if response.status_code in (401, 403): + # The Hub answers `{"error":"Invalid username or password."}` for a + # private repo with no token — which reads like a wrong URL. + raise HFAuthError(f"{response.status_code} from {url}: check the HF token and repo access") + if response.status_code == 404: + raise HFNotFound(url) + if response.status_code >= 400: + raise HFUnavailable(f"{response.status_code} from {url}: {response.text[:200]}") + return response + + # -- the three calls ------------------------------------------------------ + + async def repo_sha(self, repo_type: str, repo_id: str, *, token: str | None = None) -> str: + """Resolve a moving revision to a commit sha (plan §5.2).""" + response = await self._request("GET", self.api_url(repo_type, repo_id), token=token) + sha = response.json().get("sha") + if not sha: + raise HFUnavailable(f"repo info for {repo_id} carried no sha") + return str(sha) + + async def list_tree( + self, + repo_type: str, + repo_id: str, + revision: str, + path: str = "", + *, + recursive: bool = True, + expand: bool = False, + token: str | None = None, + ) -> list[TreeEntry]: + """List a subtree. Follows the Hub's link-header pagination.""" + url = self.api_url(repo_type, repo_id, "tree", revision, path) + params: dict[str, Any] = {} + if recursive: + params["recursive"] = "true" + if expand: + params["expand"] = "true" + + entries: list[TreeEntry] = [] + next_url: str | None = url + while next_url: + response = await self._request("GET", next_url, token=token, params=params or None) + entries.extend(parse_tree_entry(raw) for raw in response.json()) + next_url = response.links.get("next", {}).get("url") + params = {} # the Hub's next link already carries the query + return entries + + async def paths_info( + self, + repo_type: str, + repo_id: str, + revision: str, + paths: Sequence[str], + *, + expand: bool = False, + token: str | None = None, + ) -> list[TreeEntry]: + """Stat many paths in one round trip. Absent paths are simply omitted.""" + if not paths: + return [] + url = self.api_url(repo_type, repo_id, "paths-info", revision) + data: dict[str, Any] = {"paths": list(paths)} + if expand: + data["expand"] = "True" + response = await self._request("POST", url, token=token, data=data) + return [parse_tree_entry(raw) for raw in response.json()] + + async def get_bytes( + self, repo_type: str, repo_id: str, revision: str, path: str, *, token: str | None = None + ) -> bytes: + """Fetch a small file whole — sidecar JSONs (plan §6.5).""" + url = self.resolve_url(repo_type, repo_id, revision, path) + response = await self._request("GET", url, token=token) + return response.content + + async def stream( + self, + repo_type: str, + repo_id: str, + revision: str, + path: str, + *, + chunk_size: int, + token: str | None = None, + ) -> AsyncIterator[bytes]: + """Stream a file's bytes, re-chunked to ``chunk_size``. + + Re-chunking is explicit: forwarding whatever the socket yields would make + gRPC message size a property of the upstream TCP stream (plan §6.7). + """ + url = self.resolve_url(repo_type, repo_id, revision, path) + async with self._client.stream("GET", url, headers=self._headers(token)) as response: + if response.status_code >= 400: + await response.aread() + self._check(response, url) + async for chunk in response.aiter_bytes(chunk_size): + yield chunk diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/hf/models.py b/docker/hf-space/hf-storage-api/hf_storage_api/hf/models.py new file mode 100644 index 0000000000000000000000000000000000000000..ede2650944f983a7507df2b49a3e19b1c99e072a --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/hf/models.py @@ -0,0 +1,55 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Parsed HuggingFace Hub shapes. Captured samples: ``docs/reference/simready-asset-sample/``.""" + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime, timezone +from typing import Any + + +@dataclass(frozen=True) +class TreeEntry: + """One entry from ``/api/{type}s/{repo}/tree/{rev}`` or ``/paths-info/{rev}``.""" + + path: str + type: str # "file" | "directory" + size: int + etag: str # lfs.oid when present, else the git blob oid (plan §3.2) + last_modified: datetime | None + + @property + def is_file(self) -> bool: + return self.type == "file" + + +def _parse_timestamp(raw: Any) -> datetime | None: + if not isinstance(raw, str) or not raw: + return None + try: + parsed = datetime.fromisoformat(raw.replace("Z", "+00:00")) + except ValueError: + return None + return parsed if parsed.tzinfo else parsed.replace(tzinfo=timezone.utc) + + +def parse_tree_entry(raw: dict[str, Any]) -> TreeEntry: + """Build a :class:`TreeEntry` from one HF JSON entry. + + ``lfs.oid`` is the sha256 of the real content and wins over the git blob + ``oid``, which for an LFS file identifies the pointer rather than the asset. + ``lastCommit`` is only present with ``expand=true``. + """ + lfs = raw.get("lfs") or {} + etag = lfs.get("oid") or raw.get("oid") or "" + size = lfs.get("size") if isinstance(lfs.get("size"), int) else raw.get("size") + last_commit = raw.get("lastCommit") or {} + return TreeEntry( + path=raw.get("path", ""), + type=raw.get("type", "file"), + size=int(size or 0), + etag=etag, + last_modified=_parse_timestamp(last_commit.get("date")), + ) diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/http_retry.py b/docker/hf-space/hf-storage-api/hf_storage_api/http_retry.py new file mode 100644 index 0000000000000000000000000000000000000000..b155a73f5c0db36daeaf37e8a2dbc166e52b0318 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/http_retry.py @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Shared by every retry loop that talks to an upstream HTTP API +(:mod:`hf.client`, :mod:`catalog_sync.source`): parsing ``Retry-After``. + +A second copy of this would be a second failure policy, and the difference +would only ever show up during an incident. +""" + +from __future__ import annotations + +import httpx + + +def retry_after(response: httpx.Response) -> float | None: + """``Retry-After`` in seconds, or ``None`` to fall back to plain backoff. + + Only the delta-seconds form is handled — HF and GitHub both send that, never + the HTTP-date form. + """ + raw = response.headers.get("Retry-After") + try: + return float(raw) if raw else None + except ValueError: + return None diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/metadata.py b/docker/hf-space/hf-storage-api/hf_storage_api/metadata.py new file mode 100644 index 0000000000000000000000000000000000000000..06eeb23a9a857cf1ac44b257d9c97b98918552db --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/metadata.py @@ -0,0 +1,106 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Sidecar JSON -> ``GetMetadata`` user metadata (plan §6.5). + +**Every scalar is serialized as a string.** USD Search's tag flattener handles +``string_value``, ``list_value`` and ``struct_value`` and has no +``number_value``/``bool_value`` branch — a JSON number or boolean falls through +to a warning and loses its value (contract doc §5). Nested structs are left +nested on purpose: the flattener recurses and emits both ``key`` and +``parent.key``, so nested JSON is filterable without pre-flattening here. +""" + +from __future__ import annotations + +from typing import Any + +from google.protobuf.struct_pb2 import ListValue, Struct, Value + + +def prune_empty(value: Any) -> Any: + """Drop empty lists and objects, recursively. + + They carry nothing, and the client's flattener has no branch for an empty + ``list_value``: it falls through to "Unsupported tag value", logs a warning + per asset, and indexes a tag with a null value. ``com.nvidia.simready.packaging.json`` + ships ``"metadata": []`` on every SimReady asset, so this is one warning per + asset in every crawl. + """ + if isinstance(value, dict): + pruned = {k: prune_empty(v) for k, v in value.items()} + return {k: v for k, v in pruned.items() if v is not EMPTY} + if isinstance(value, (list, tuple)): + pruned = [prune_empty(v) for v in value] + kept = [v for v in pruned if v is not EMPTY] + return kept or EMPTY + return value + + +class _Empty: + """Sentinel for "drop this key", distinct from a legitimate None/0/false.""" + + def __repr__(self) -> str: # pragma: no cover - debugging aid + return "" + + +EMPTY = _Empty() + + +def stringify(value: Any) -> Value: + """Convert parsed JSON to a ``google.protobuf.Value`` with string scalars.""" + out = Value() + if value is None: + out.string_value = "" + elif isinstance(value, bool): + # Before the int check: bool is a subclass of int in Python. + out.string_value = "true" if value else "false" + elif isinstance(value, (int, float)): + out.string_value = repr(value) if isinstance(value, float) else str(value) + elif isinstance(value, str): + out.string_value = value + elif isinstance(value, dict): + struct = Struct() + for key, item in value.items(): + struct.fields[str(key)].CopyFrom(stringify(item)) + out.struct_value.CopyFrom(struct) + elif isinstance(value, (list, tuple)): + listing = ListValue() + for item in value: + listing.values.append(stringify(item)) + out.list_value.CopyFrom(listing) + else: + out.string_value = str(value) + return out + + +def merge_metadata( + *, + manifest: dict | None, + asset_metadata: dict | None, + synthesized: dict[str, str], +) -> dict[str, Value]: + """Merge the sidecars in increasing priority, then the ``hf:`` keys. + + The synthesized keys are namespaced so they stay distinguishable from + whatever the dataset authors put in their own JSON, and they are applied last + so a dataset cannot shadow them. + """ + merged: dict[str, Any] = {} + for source in (manifest, asset_metadata): + if source: + merged.update(source) + + merged = prune_empty(merged) + values = {key: stringify(item) for key, item in merged.items()} + values.update({key: stringify(item) for key, item in synthesized.items()}) + return values + + +def filter_keys(values: dict[str, Value], keys: list[str]) -> dict[str, Value]: + """Honour ``GetMetadataRequest.user_metadata_keys``; empty means everything + (which is USD Search's default).""" + if not keys: + return values + wanted = set(keys) + return {key: value for key, value in values.items() if key in wanted} diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/registration.py b/docker/hf-space/hf-storage-api/hf_storage_api/registration.py new file mode 100644 index 0000000000000000000000000000000000000000..7fcabfb121fcacb3bf65459a6aa636bd0e4dcd30 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/registration.py @@ -0,0 +1,125 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Bind the servicers to gRPC service paths (plan §2.4). + +**v1alpha is what USD Search's client dials** — verified from its imports. The +generator also emits v1beta, which is a *different* service path: registering the +wrong one fails every call with ``UNIMPLEMENTED`` rather than a type error. + +The message shapes are byte-identical between the two versions for every RPC we +implement, so one servicer instance is bound under both paths while the Kit-side +question (§8.1) is open. ``HF_ADAPTER_ADVERTISE_V1BETA=false`` turns that off. + +This module is the only place that imports the generated ``_grpc`` modules, and +it is the single source of truth for which (service, version) pairs exist — both +for binding them and for what ``ListServices`` advertises, so the two cannot +drift apart. +""" + +from __future__ import annotations + +import logging +from collections.abc import Mapping, Sequence + +import grpc +from nvidia.omniverse.storage.capabilities.v1alpha import capabilities_pb2_grpc as capabilities_v1alpha +from nvidia.omniverse.storage.capabilities.v1beta import capabilities_pb2_grpc as capabilities_v1beta +from nvidia.omniverse.storage.filefolder.v1alpha import filefolder_service_pb2_grpc as filefolder_v1alpha +from nvidia.omniverse.storage.filefolder.v1beta import filefolder_service_pb2_grpc as filefolder_v1beta +from nvidia.omniverse.storage.fileobject.v1alpha import fileobject_service_pb2_grpc as fileobject_v1alpha +from nvidia.omniverse.storage.fileobject.v1beta import fileobject_service_pb2_grpc as fileobject_v1beta +from nvidia.omniverse.storage.metadata.v1alpha import metadata_pb2_grpc as metadata_v1alpha + +logger = logging.getLogger(__name__) + +CAPABILITIES = "capabilities" +FILEOBJECT = "fileobject" +METADATA = "metadata" +FILEFOLDER = "filefolder" + +# Bare service name -> version -> the generated `add_*_to_server` function. +# `metadata` has **no v1beta upstream**: only v1alpha exists in ovstorage at the +# ref we pin, so it cannot be offered on v1beta however much we would like to. +BINDERS = { + CAPABILITIES: { + "v1alpha": capabilities_v1alpha.add_CapabilitiesServiceServicer_to_server, + "v1beta": capabilities_v1beta.add_CapabilitiesServiceServicer_to_server, + }, + FILEOBJECT: { + "v1alpha": fileobject_v1alpha.add_FileObjectServiceServicer_to_server, + "v1beta": fileobject_v1beta.add_FileObjectServiceServicer_to_server, + }, + METADATA: { + "v1alpha": metadata_v1alpha.add_MetadataServiceServicer_to_server, + }, + FILEFOLDER: { + "v1alpha": filefolder_v1alpha.add_FileFolderServiceServicer_to_server, + "v1beta": filefolder_v1beta.add_FileFolderServiceServicer_to_server, + }, +} + + +# Bare name -> the generated service class, for building the fully-qualified +# `nvidia.omniverse.storage...` path the health service and +# gRPC itself use. +SERVICE_CLASSES = { + CAPABILITIES: "CapabilitiesService", + FILEOBJECT: "FileObjectService", + METADATA: "MetadataService", + FILEFOLDER: "FileFolderService", +} + + +def service_full_name(name: str, version: str) -> str: + return f"nvidia.omniverse.storage.{name}.{version}.{SERVICE_CLASSES[name]}" + + +def planned_bindings(*, advertise_filefolder: bool, advertise_v1beta: bool) -> dict[str, list[str]]: + """Which (service, version) pairs this process will serve. + + ``ListServices`` reports exactly this, so a version we advertise is always + one a client can actually dial. + """ + services = [CAPABILITIES, FILEOBJECT, METADATA] + if advertise_filefolder: + services.append(FILEFOLDER) + + return { + name: [version for version in BINDERS[name] if version == "v1alpha" or advertise_v1beta] + for name in services + } + + +def register( + server: grpc.aio.Server, + *, + bindings: Mapping[str, Sequence[str]], + capabilities, + fileobject, + metadata, + filefolder=None, +) -> None: + """Bind every servicer named in ``bindings``.""" + servicers = { + CAPABILITIES: capabilities, + FILEOBJECT: fileobject, + METADATA: metadata, + FILEFOLDER: filefolder, + } + + bound: list[str] = [] + for name, versions in bindings.items(): + servicer = servicers[name] + if servicer is None: + raise ValueError(f"{name} is in the binding plan but no servicer was supplied") + for version in versions: + binder = BINDERS[name].get(version) + if binder is None: + # Advertising a version with no generated stub would tell clients + # to dial a path that answers UNIMPLEMENTED. + raise ValueError(f"no {version} proto for {name!r} (have: {', '.join(BINDERS[name])})") + binder(servicer, server) + bound.append(f"{name}.{version}") + + logger.info("bound gRPC services: %s", ", ".join(bound)) diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/server.py b/docker/hf-space/hf-storage-api/hf_storage_api/server.py new file mode 100644 index 0000000000000000000000000000000000000000..72a3c4a921a4cbe06cba628627c1152cbe5f1aba --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/server.py @@ -0,0 +1,131 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Process wiring: build the store, bind the servicers, serve.""" + +from __future__ import annotations + +import asyncio +import logging +import signal +from dataclasses import dataclass + +import grpc + +from .auth import BearerAuthInterceptor +from .catalog.loader import CatalogLoader +from .health import add_health_service, enter_graceful_shutdown +from .hf.client import HFClient +from .registration import planned_bindings, register +from .services.capabilities import CapabilitiesService +from .services.filefolder import FileFolderService +from .services.fileobject import FileObjectService +from .services.metadata_service import MetadataService +from .settings import Settings +from .store import AssetStore + +logger = logging.getLogger(__name__) + + +@dataclass +class Service: + """A wired-up, not-yet-serving service. Split out so tests can drive it over + an in-process channel without a port.""" + + settings: Settings + hf: HFClient + store: AssetStore + loader: CatalogLoader + server: grpc.aio.Server + health: object + + async def aclose(self) -> None: + await self.loader.stop() + await self.hf.aclose() + + +async def build(settings: Settings, *, hf: HFClient | None = None) -> Service: + """Load the catalog and wire everything up. + + The catalog is the only thing loaded here. No HuggingFace asset data is + fetched — folders load on first request (plan §5.2) — so startup does not + depend on the Hub being reachable. + """ + hf = hf or HFClient( + endpoint=settings.hf_endpoint, + token=settings.resolve_hf_token(), + timeout=settings.http_timeout, + max_connections=settings.http_max_connections, + max_retries=settings.http_max_retries, + backoff_base=settings.http_backoff_base, + ) + + loader = CatalogLoader(settings, hf) + catalog = await loader.load() + store = AssetStore(catalog, hf, settings) + + interceptors = [] + if not settings.allow_anonymous: + interceptors.append(BearerAuthInterceptor(settings.resolve_auth_token())) + else: + logger.warning("inbound auth is DISABLED (HF_ADAPTER_ALLOW_ANONYMOUS=true)") + + server = grpc.aio.server( + interceptors=interceptors, + maximum_concurrent_rpcs=settings.max_concurrent_rpcs, + ) + + # One plan drives both what gets bound and what ListServices reports. + bindings = planned_bindings( + advertise_filefolder=settings.advertise_filefolder, + advertise_v1beta=settings.advertise_v1beta, + ) + capabilities = CapabilitiesService(store, settings, bindings) + register( + server, + bindings=bindings, + capabilities=capabilities, + fileobject=FileObjectService(store, settings), + metadata=MetadataService(store, settings), + filefolder=FileFolderService(store, settings) if settings.advertise_filefolder else None, + ) + logger.info( + "advertising: %s", + ", ".join(f"{name} ({'+'.join(v)})" for name, v in bindings.items()), + ) + + # Registered last, and only once everything above succeeded: the catalog is + # loaded and every servicer is bound, which is exactly what SERVING claims. + health = await add_health_service(server, bindings) + + await loader.start_refresh(store.swap_catalog) + return Service(settings=settings, hf=hf, store=store, loader=loader, server=server, health=health) + + +async def serve(settings: Settings | None = None) -> None: + settings = settings or Settings() + logging.basicConfig( + level=settings.log_level.upper(), + format="%(asctime)s %(levelname)s %(name)s %(message)s", + ) + + service = await build(settings) + address = f"{settings.grpc_host}:{settings.grpc_port}" + service.server.add_insecure_port(address) + await service.server.start() + logger.info("listening on %s", address) + + stop = asyncio.Event() + loop = asyncio.get_running_loop() + for sig in (signal.SIGINT, signal.SIGTERM): + loop.add_signal_handler(sig, stop.set) + + try: + await stop.wait() + finally: + # NOT_SERVING first, so Kubernetes pulls the pod from the Service + # endpoints before we start refusing connections. + logger.info("draining...") + await enter_graceful_shutdown(service.health) + await service.server.stop(grace=10) + await service.aclose() diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/services/__init__.py b/docker/hf-space/hf-storage-api/hf_storage_api/services/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..52a7a9daf028f654d6a02f65c99cc609a57b492f --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/services/__init__.py @@ -0,0 +1,2 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/services/capabilities.py b/docker/hf-space/hf-storage-api/hf_storage_api/services/capabilities.py new file mode 100644 index 0000000000000000000000000000000000000000..c9747d2c46f42d014c72bf771a542257ef503fab --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/services/capabilities.py @@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""``CapabilitiesService`` — feature discovery. + +``ListServices`` is the single most useful lever a server has: the client only +constructs the ``filefolder`` and ``metadata`` stubs if this call names them, and +falls back from ``ListStat`` to ``Enumerate`` when ``filefolder`` is absent +(contract doc §2). Advertising three services is a legitimate, much smaller v1. +""" + +from __future__ import annotations + +import logging +from collections.abc import Mapping, Sequence + +from nvidia.omniverse.storage.capabilities.v1alpha import capabilities_pb2 + +from ..settings import Settings +from ..store import AssetStore + +logger = logging.getLogger(__name__) + + +class CapabilitiesService: + def __init__(self, store: AssetStore, settings: Settings, bindings: Mapping[str, Sequence[str]]) -> None: + self._store = store + self._settings = settings + # Exactly what registration bound, so an advertised version is always one + # a client can actually dial. `check_if_service_exists(name, version)` + # filters on these, so under-reporting them hides a service that works. + self._bindings = bindings + + def advertised(self) -> list[str]: + return list(self._bindings) + + async def ListServices(self, request, context): + return capabilities_pb2.ListServicesResponse( + services=[ + capabilities_pb2.ServiceEntry(service_name=name, service_versions=list(versions)) + for name, versions in self._bindings.items() + ] + ) + + async def ListTopLevelAddresses(self, request, context): + # One entry per catalogued repo. Answered from the catalog alone — no HF + # call, so this stays cheap and works before anything is loaded. + return capabilities_pb2.ListTopLevelAddressesResponse( + items=[ + capabilities_pb2.TopLevelAddressEntry(top_level_address=address) + for address in self._store.top_level_addresses() + ] + ) + + async def ListRoutes(self, request, context): + """Wildcard patterns for the addresses this server serves. + + Unused by USD Search's Python client, but it is one of only two RPCs that + could feed ``omni.client``'s ``on_registered`` callback, and it exists + only in v1alpha — see plan §2.4. Cheap insurance against a silent Kit + registration failure. + """ + return capabilities_pb2.ListRoutesResponse( + items=[ + capabilities_pb2.Route(wildcard_pattern=f"{address}*") + for address in self._store.top_level_addresses() + ] + ) diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/services/filefolder.py b/docker/hf-space/hf-storage-api/hf_storage_api/services/filefolder.py new file mode 100644 index 0000000000000000000000000000000000000000..8b1f990bfb0e45d7bd7b008de0cf524bd2307c38 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/services/filefolder.py @@ -0,0 +1,120 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""``FileFolderService`` — folder-scoped listing (plan §6.2). + +Only reachable when ``HF_ADAPTER_ADVERTISE_FILEFOLDER=true``: the client +constructs this stub, and prefers ``ListStat`` over ``Enumerate``, purely on the +strength of ``ListServices``. + +``ListStat`` embeds a full ``ResourceInfo`` per entry, so the client needs no +follow-up ``Stat`` — which removes the Stat-per-item cost that ``Enumerate`` +carries. At the repo root we return the crawl surface flat (no subfolders), so +the narrow crawl surface is preserved while the round trips collapse to one. +""" + +from __future__ import annotations + +import asyncio +import logging + +import grpc +from nvidia.omniverse.storage.filefolder.v1alpha import filefolder_service_pb2 + +from ..errors import handle_hf_errors_stream, unimplemented +from ..settings import Settings +from ..store import AssetStore +from .fileobject import _resource_info + +logger = logging.getLogger(__name__) + + +class FileFolderService: + def __init__(self, store: AssetStore, settings: Settings) -> None: + self._store = store + self._settings = settings + + @handle_hf_errors_stream + async def ListStat(self, request, context): + uri = request.folder.uri + repo = self._store.repo_for_root(uri) + + if repo is not None: + # Repo root: the crawl surface, flat. Returning no subfolder_addresses + # stops the client's breadth-first walk here, which is what keeps the + # indexed set to one entry per asset. + semaphore = asyncio.Semaphore(self._settings.enumerate_concurrency) + + async def resolve(asset_name: str): + async with semaphore: + return await self._store.folder(repo, asset_name) + + entries: list[filefolder_service_pb2.ListItem] = [] + for completed in asyncio.as_completed([resolve(name) for name in repo.assets]): + loaded = await completed + if loaded is None: + continue + entry = loaded.entry(loaded.root_usd) + if entry is None: + continue + address = self._store.address_for(repo, loaded.root_usd, revision=loaded.revision) + entries.append( + filefolder_service_pb2.ListItem( + resource_address=address, + resource_info=_resource_info(self._store, entry, address), + ) + ) + if len(entries) >= self._settings.enumerate_batch_size: + yield filefolder_service_pb2.ListStatResponse(entries=entries) + entries = [] + if entries: + yield filefolder_service_pb2.ListStatResponse(entries=entries) + return + + # Any other folder: the real tree, one level down. This is the resolve + # surface, so wildcard thumbnail templates and Kit folder probes work. + resolved = self._store.resolve(uri) + if resolved is None: + await context.abort(grpc.StatusCode.NOT_FOUND, uri) + loaded = await self._store.folder(resolved.repo, resolved.asset_name) + if loaded is None or not loaded.has_folder(resolved.path): + await context.abort(grpc.StatusCode.NOT_FOUND, uri) + + prefix = resolved.path.strip("/") + depth = len([p for p in prefix.split("/") if p]) + 1 + subfolders = [ + filefolder_service_pb2.FolderAddress( + uri=self._store.address_for(resolved.repo, sub, is_folder=True, revision=loaded.revision) + ) + for sub in sorted(loaded.subfolders) + if sub.startswith(prefix + "/") and len(sub.split("/")) == depth + ] + entries = [] + for path, entry in sorted(loaded.files.items()): + if not path.startswith(prefix + "/") or len(path.split("/")) != depth: + continue + address = self._store.address_for(resolved.repo, path, revision=loaded.revision) + entries.append( + filefolder_service_pb2.ListItem( + resource_address=address, + resource_info=_resource_info(self._store, entry, address), + ) + ) + yield filefolder_service_pb2.ListStatResponse(subfolder_addresses=subfolders, entries=entries) + + @handle_hf_errors_stream + async def List(self, request, context): + async for response in self.ListStat(request, context): + yield filefolder_service_pb2.ListResponse( + subfolder_addresses=response.subfolder_addresses, + sub_resource_addresses=[item.resource_address for item in response.entries], + ) + + async def CreateFolder(self, request, context): + await unimplemented(context, "CreateFolder") + + async def DeleteFolder(self, request, context): + await unimplemented(context, "DeleteFolder") + + async def GetFolderMode(self, request, context): + await unimplemented(context, "GetFolderMode") diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/services/fileobject.py b/docker/hf-space/hf-storage-api/hf_storage_api/services/fileobject.py new file mode 100644 index 0000000000000000000000000000000000000000..63c0040ef4dc64df24e838a5c0bff91b31a60284 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/services/fileobject.py @@ -0,0 +1,216 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""``FileObjectService`` — ``Stat``, ``Enumerate``, ``ReadFromAddress``. + +Two surfaces (plan §6.2): + +* **Crawl** — ``Enumerate`` returns only the root USD of each catalogued asset, + so nothing but indexable assets enters USD Search's stream. +* **Resolve** — ``Stat``/``ReadFromAddress`` answer for *any* path inside a + catalogued asset folder, because Kit asks for textures, MDL and sidecars while + opening the stage. +""" + +from __future__ import annotations + +import asyncio +import logging +from datetime import datetime, timezone + +import grpc +from nvidia.omniverse.storage.fileobject.v1alpha import fileobject_pb2, fileobject_service_pb2 + +from ..errors import handle_hf_errors, handle_hf_errors_stream, unimplemented +from ..hf.models import TreeEntry +from ..settings import Settings +from ..store import AssetStore + +logger = logging.getLogger(__name__) + + +def _metadata(entry: TreeEntry) -> fileobject_pb2.Metadata: + metadata = fileobject_pb2.Metadata(data_object_size=entry.size) + # Always set the timestamp: the client calls ToDatetime().timestamp() on it, + # so an unset field becomes epoch 0 in the index (plan §2.4). + metadata.last_modified_timestamp.FromDatetime(entry.last_modified or datetime.now(timezone.utc)) + return metadata + + +def _resource_info(store: AssetStore, entry: TreeEntry, address: str) -> fileobject_pb2.ResourceInfo: + """The one place a ``ResourceIdentity`` is minted — hence the one place it is + indexed. + + ``encoded_identity`` is the content oid, because USD Search turns it into + ``PathType.hash_value`` and re-indexes on it (contract doc §3.2); it must not + become the address, or a moving-ref deployment would never notice a change. + But omni.client sends that same identity back as ``GetMetadataRequest.uri``, + so the address it stood for has to be recoverable (contract doc §5.1). + Recording it here means a new call site cannot forget to. + """ + store.remember_identity(entry.etag, address) + return fileobject_pb2.ResourceInfo( + resource_identity=fileobject_pb2.ResourceIdentity(encoded_identity=entry.etag), + metadata=_metadata(entry), + ) + + +class FileObjectService: + def __init__(self, store: AssetStore, settings: Settings) -> None: + self._store = store + self._settings = settings + + # -- read path ------------------------------------------------------------ + + @handle_hf_errors + async def Stat(self, request, context): + address = request.resource_address + + # A folder address must succeed as a folder or fail NOT_FOUND — it must + # never report as an asset, or the client stops enumerating it + # (contract doc §3.2). + if address.endswith("/"): + if self._store.is_repo_root(address) or await self._store.stat_folder(address): + return fileobject_service_pb2.StatResponse( + resource_info=fileobject_pb2.ResourceInfo( + resource_identity=fileobject_pb2.ResourceIdentity(encoded_identity=""), + metadata=fileobject_pb2.Metadata(data_object_size=0), + ) + ) + await context.abort(grpc.StatusCode.NOT_FOUND, address) + + found = await self._store.stat(address) + if found is None: + await context.abort(grpc.StatusCode.NOT_FOUND, address) + _, entry = found + return fileobject_service_pb2.StatResponse(resource_info=_resource_info(self._store, entry, address)) + + @handle_hf_errors_stream + async def Enumerate(self, request, context): + """Stream the crawl surface: one ``AddressInfo`` per catalogued asset. + + The client issues exactly one ``Enumerate`` per root and consumes the + stream flat — it never recurses into a returned entry — so everything has + to come out of this one call (plan §2.4). + """ + address = request.resource_address + repo = self._store.repo_for_root(address) + if repo is None: + # Scoped to something other than a served root. Prefer NOT_FOUND: + # any other status aborts the crawl (contract doc §3.4). + await context.abort(grpc.StatusCode.NOT_FOUND, address) + + semaphore = asyncio.Semaphore(self._settings.enumerate_concurrency) + + async def resolve(asset_name: str): + async with semaphore: + return asset_name, await self._store.folder(repo, asset_name) + + batch: list[fileobject_pb2.AddressInfo] = [] + # Stream as results arrive rather than resolving everything first: a + # crawl that emits nothing for minutes is indistinguishable from a hang. + tasks = [asyncio.create_task(resolve(name)) for name in repo.assets] + try: + for completed in asyncio.as_completed(tasks): + asset_name, loaded = await completed + if loaded is None: + logger.warning("catalogued asset %s is absent upstream; skipping", asset_name) + continue + entry = loaded.entry(loaded.root_usd) + if entry is None: + logger.warning( + "asset %s: root USD %s not present in the folder; skipping", + asset_name, + loaded.root_usd, + ) + continue + batch.append( + fileobject_pb2.AddressInfo( + resource_address=self._store.address_for( + repo, loaded.root_usd, revision=loaded.revision + ), + metadata=_metadata(entry), + ) + ) + if len(batch) >= self._settings.enumerate_batch_size: + yield fileobject_service_pb2.EnumerateResponse(items=batch) + batch = [] + finally: + for task in tasks: + task.cancel() + + if batch: + yield fileobject_service_pb2.EnumerateResponse(items=batch) + + @handle_hf_errors_stream + async def ReadFromAddress(self, request, context): + address = request.resource_address + + # Authorise against the catalog + index before opening any upstream + # connection: never proxy a path the catalog does not cover (plan §6.7). + found = await self._store.stat(address) + if found is None: + await context.abort(grpc.StatusCode.NOT_FOUND, address) + resolved, entry = found + + yield fileobject_service_pb2.ReadFromAddressResponse( + resource_info=_resource_info(self._store, entry, address) + ) + + revision = await self._store.revision(resolved.repo) + stream = self._store.hf.stream( + resolved.repo.repo_type, + resolved.repo.repo_id, + revision, + resolved.path, + chunk_size=self._settings.chunk_size, + token=resolved.repo.token, + ) + try: + async for chunk in stream: + yield fileobject_service_pb2.ReadFromAddressResponse(chunk=fileobject_pb2.Chunk(chunk=chunk)) + except asyncio.CancelledError: + # The client hung up: close the upstream response instead of draining + # it into a dead RPC. With multi-hundred-MB assets that is a real + # bandwidth leak (plan §6.7). + await stream.aclose() + raise + + async def Read(self, request, context): + # The client downloads by address, not by ResourceIdentity, so this is + # unused. Implement only if the Phase-1.4 Kit log shows it (plan §2.4). + await context.abort( + grpc.StatusCode.UNIMPLEMENTED, "Read by identity is not supported; use ReadFromAddress" + ) + + # -- write path: read-only service (plan §6.8) ---------------------------- + + async def FetchWriteTypeInfo(self, request, context): + await unimplemented(context, "FetchWriteTypeInfo") + + async def Write(self, request_iterator, context): + await unimplemented(context, "Write") + + async def CompleteRedirectUpload(self, request, context): + await unimplemented(context, "CompleteRedirectUpload") + + async def UploadPart(self, request, context): + await unimplemented(context, "UploadPart") + + async def CompleteMultipartUpload(self, request, context): + await unimplemented(context, "CompleteMultipartUpload") + + async def AbortMultipartUpload(self, request, context): + await unimplemented(context, "AbortMultipartUpload") + + async def Delete(self, request, context): + await unimplemented(context, "Delete") + + async def Copy(self, request, context): + await unimplemented(context, "Copy") + + async def Move(self, request, context): + await unimplemented(context, "Move") + + async def GetOptimisticLockingSupport(self, request, context): + await unimplemented(context, "GetOptimisticLockingSupport") diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/services/metadata_service.py b/docker/hf-space/hf-storage-api/hf_storage_api/services/metadata_service.py new file mode 100644 index 0000000000000000000000000000000000000000..675ebe8e813b62b314bf6ff8b488170640be71ec --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/services/metadata_service.py @@ -0,0 +1,139 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""``MetadataService.GetMetadata`` — what lands in the search response (plan §6.5).""" + +from __future__ import annotations + +import logging + +import grpc +from nvidia.omniverse.storage.metadata.v1alpha import metadata_pb2 + +from ..errors import handle_hf_errors, unimplemented +from ..metadata import filter_keys, merge_metadata +from ..settings import Settings +from ..store import AssetStore + +logger = logging.getLogger(__name__) + + +class MetadataService: + def __init__(self, store: AssetStore, settings: Settings) -> None: + self._store = store + self._settings = settings + + @handle_hf_errors + async def GetMetadata(self, request, context): + uri = request.uri + resolved = self._store.resolve(uri) or self._resolve_identity(uri) + if resolved is None: + await context.abort(grpc.StatusCode.NOT_FOUND, uri) + + loaded = await self._store.folder(resolved.repo, resolved.asset_name) + if loaded is None: + await context.abort(grpc.StatusCode.NOT_FOUND, uri) + + layout = resolved.layout + asset_name = resolved.asset_name + # Under `catalog_kind="wrapp"` the per-asset filenames use the short stem + # from the root USD (e.g. `sm_IV_pole_a01_01`), not the full folder path + # that `asset_name` is under a versioned layout (plan §6.3). + stem = loaded.root_usd.rsplit("/", 1)[-1].removesuffix(".usd") + manifest_path = f"{asset_name}/{layout.render(layout.manifest, asset_name, stem=stem)}" + metadata_path = f"{asset_name}/{layout.render(layout.metadata, asset_name, stem=stem)}" + + manifest = await self._sidecar(resolved, manifest_path, loaded) + asset_metadata = await self._sidecar(resolved, metadata_path, loaded) + + entry = loaded.entry(resolved.path) + thumbnail = self._thumbnail_path(loaded, layout, asset_name) + revision = loaded.revision + repo = resolved.repo + synthesized = { + "hf:repo_id": repo.repo_id, + "hf:repo_type": repo.repo_type, + "hf:revision": revision, + "hf:path": resolved.path, + "hf:asset_name": asset_name, + "hf:public_url": self._store.hf.resolve_url( + repo.repo_type, repo.repo_id, revision, resolved.path + ), + } + if entry is not None: + synthesized["hf:blob_oid"] = entry.etag + if thumbnail is not None: + # An in-namespace address. When a deployment points + # thumbnail_metadata_fields at this key, the client `check_if_exists`-es + # the value *through this service*, so it has to be an address we can + # resolve — anything else comes straight back as NOT_FOUND and surfaces + # as "thumbnail_missing" on a thumbnail that exists. Under the default + # `https` scheme this coincides with the public URL below whenever the + # revision is embedded; it is still built via address_for, because it is + # the *addressable* form that is load-bearing here, not the public one. + synthesized["hf:thumbnail_url"] = self._store.address_for(repo, thumbnail, revision=revision) + # The public link, for display in search results. + synthesized["hf:thumbnail_public_url"] = self._store.hf.resolve_url( + repo.repo_type, repo.repo_id, revision, thumbnail + ) + + values = merge_metadata(manifest=manifest, asset_metadata=asset_metadata, synthesized=synthesized) + # Empty user_metadata_keys means "return everything" — USD Search's default. + values = filter_keys(values, list(request.user_metadata_keys)) + + return metadata_pb2.GetMetadataResponse( + user_metadata={key: metadata_pb2.UserMetadataValue(value=value) for key, value in values.items()} + ) + + def _resolve_identity(self, uri: str): + """Resolve a ``uri`` that is really a ``ResourceIdentity``. + + Kit's omni.client follows a successful ``Stat`` by calling ``GetMetadata`` + with the ``encoded_identity`` from that response in place of an address, + and reports the *stat* as NOT_FOUND if the metadata call fails — so + without this, no stage on this backend opens at all (contract doc §5.1). + The identity was indexed while minting it, milliseconds earlier. + """ + address = self._store.address_for_identity(uri) + if address is None: + return None + logger.debug("GetMetadata(%s) is a resource identity for %s", uri, address) + return self._store.resolve(address) + + async def _sidecar(self, resolved, path: str, loaded) -> dict | None: + if path not in loaded.files: + return None + return await self._store.sidecar_json(resolved.repo, path) + + @staticmethod + def _thumbnail_path(loaded, layout, asset_name: str) -> str | None: + """Find this asset's thumbnail. + + Presentation only: this value is a *public HTTPS* link for search results. + The pipeline route computes ``.thumbs//.png`` client-side with + ``STORAGE_API_THUMBNAIL_STYLE=nucleus`` (plan §6.6) — which has nothing to + find for ``catalog_kind="package_entry"``, since that dataset carries no + ``.thumbs/`` directory at all; a deployment serving it needs + ``thumbnail_style=storage_api`` on the USD Search side instead (plan docs/ + plans/simready-internal-catalog-kind.md §2.4). + """ + if layout.thumbnail: + candidate = f"{asset_name}/{layout.thumbnail}" + if candidate in loaded.files: + return candidate + thumbs_dir = f"{asset_name}/{layout.render(layout.thumbs_dir, asset_name)}" + filename = loaded.root_usd.rsplit("/", 1)[-1] + for candidate in ( + f"{thumbs_dir}/256x256/{filename}.png", + f"{thumbs_dir}/138x108/{filename}.png", + f"{thumbs_dir}/{filename}.png", + ): + if candidate in loaded.files: + return candidate + return None + + async def UpdateMetadata(self, request, context): + await unimplemented(context, "UpdateMetadata") + + async def DeleteMetadata(self, request, context): + await unimplemented(context, "DeleteMetadata") diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/settings.py b/docker/hf-space/hf-storage-api/hf_storage_api/settings.py new file mode 100644 index 0000000000000000000000000000000000000000..711512a72c2d3941b3c5c6135e6dbe004b90d359 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/settings.py @@ -0,0 +1,140 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Process configuration. See the plan's §7 for the full reference table.""" + +from __future__ import annotations + +from pathlib import Path +from typing import Literal + +from pydantic import model_validator +from pydantic_settings import BaseSettings, SettingsConfigDict + + +class Settings(BaseSettings): + model_config = SettingsConfigDict(env_prefix="HF_ADAPTER_", extra="ignore") + + grpc_port: int = 50051 + grpc_host: str = "0.0.0.0" # noqa: S104 - a server that only binds loopback is useless in a pod + + # --- HuggingFace --------------------------------------------------------- + hf_endpoint: str = "https://huggingface.co" + hf_token: str | None = None + hf_token_file: Path | None = None + http_timeout: float = 30.0 + http_max_connections: int = 20 + # A cold `discover`/`Enumerate` over a large repo can burn hundreds of + # requests in one burst (plan §6.3.2: a `list_tree` call per asset under + # `catalog_kind: wrapp`, hitting HF's small `api` rate-limit bucket rather + # than the much larger `resolvers` one). Retries stack with the reset delay + # HF's `RateLimit` response header carries (hf/client.py); these bound how + # long a single request is willing to wait it out before giving up. + http_max_retries: int = 5 + http_backoff_base: float = 1.0 + + # --- catalog ------------------------------------------------------------- + # Transport and format are independent: a plain list of HuggingFace file URLs + # is just as likely to live in a GitHub repo as a YAML catalog is. + catalog_source: Literal["file", "url", "discover"] = "file" + catalog_format: Literal["auto", "yaml", "url-list"] = "auto" + catalog_path: Path | None = None + catalog_url: str | None = None + catalog_refresh_seconds: float = 900.0 + + # A URL list has nowhere to put a layout, so a non-default one comes from the + # environment instead. `manifest` is inferred from the list itself. + layout_data_dir: str | None = None + layout_root_usd_index: str | None = None + + # --- namespace ----------------------------------------------------------- + # `https` emits addresses that mirror HuggingFace's public URLs one-to-one, so + # a pinned address needs no rewriting to be shown or shared. `hf` restores the + # synthetic namespace, which is unambiguous inside Kit — see plan §6.1. + uri_scheme: str = "https" + # Whether emitted addresses carry `/resolve//`, mirroring HuggingFace's + # own URL layout (plan §6.1). + # auto - yes when the repo's revision is a pinned sha, no for a moving ref + # always - yes; a moving ref then changes every base_key on each commit + # never - the bare `/` form + uri_revision_mode: Literal["auto", "always", "never"] = "auto" + + # --- laziness (plan §5.2) ------------------------------------------------ + folder_cache_ttl: float = 300.0 + folder_cache_size: int = 512 + negative_cache_ttl: float = 60.0 + revision_ttl: float = 300.0 + enumerate_concurrency: int = 8 + + # --- wire (plan §2.4) ---------------------------------------------------- + chunk_size: int = 1024 * 1024 + enumerate_batch_size: int = 200 + advertise_filefolder: bool = False + advertise_v1beta: bool = True + allow_redirect: bool = False + + # --- inbound auth (plan §6.4) ------------------------------------------- + auth_token: str | None = None + auth_token_file: Path | None = None + allow_anonymous: bool = False + + # --- observability ------------------------------------------------------- + log_level: str = "INFO" + metrics_port: int | None = None + max_concurrent_rpcs: int | None = None + + @model_validator(mode="after") + def _check(self) -> Settings: + if self.catalog_source == "file" and self.catalog_path is None: + raise ValueError("HF_ADAPTER_CATALOG_PATH is required when CATALOG_SOURCE=file") + if self.catalog_source == "url" and not self.catalog_url: + raise ValueError("HF_ADAPTER_CATALOG_URL is required when CATALOG_SOURCE=url") + if self.catalog_source == "discover" and self.catalog_path is None: + # `discover` still needs to know *which* repos to walk; that lives in the + # same catalog file, just without an explicit `assets:` list. + raise ValueError("HF_ADAPTER_CATALOG_PATH is required when CATALOG_SOURCE=discover") + if not self.allow_anonymous and not (self.auth_token or self.auth_token_file): + raise ValueError( + "inbound auth is required: set HF_ADAPTER_AUTH_TOKEN / _AUTH_TOKEN_FILE, " + "or HF_ADAPTER_ALLOW_ANONYMOUS=true to disable it deliberately" + ) + if self.chunk_size >= 4 * 1024 * 1024: + # The client sets no channel options, so its receive limit is gRPC's 4 MiB + # default (plan §2.4). + raise ValueError("chunk_size must stay well below the client's 4 MiB default limit") + return self + + def layout_defaults(self): + """Layout for formats that cannot carry one (plan §6.3).""" + from .catalog.model import LayoutConfig + + overrides = { + key: value + for key, value in ( + ("data_dir", self.layout_data_dir), + ("root_usd_index", self.layout_root_usd_index), + ) + if value is not None + } + return LayoutConfig(**overrides) + + @staticmethod + def _clean(token: str | None) -> str | None: + """Strip whitespace off a token, wherever it came from. + + Not just the file variants: a Kubernetes Secret populated with `echo` + carries a trailing newline, and it reaches us through the environment. + An unstripped token makes httpx reject the Authorization header outright, + which reads as a client bug rather than a malformed credential. + """ + return token.strip() if token else token + + def resolve_hf_token(self) -> str | None: + if self.hf_token_file is not None: + return self._clean(self.hf_token_file.read_text(encoding="utf-8")) + return self._clean(self.hf_token) + + def resolve_auth_token(self) -> str | None: + if self.auth_token_file is not None: + return self._clean(self.auth_token_file.read_text(encoding="utf-8")) + return self._clean(self.auth_token) diff --git a/docker/hf-space/hf-storage-api/hf_storage_api/store.py b/docker/hf-space/hf-storage-api/hf_storage_api/store.py new file mode 100644 index 0000000000000000000000000000000000000000..543825a90f63f5913a48e7abd683c10986237033 --- /dev/null +++ b/docker/hf-space/hf-storage-api/hf_storage_api/store.py @@ -0,0 +1,564 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Lazy, folder-granular asset state (plan §5.2). + +Nothing is fetched from HuggingFace until it is asked for. A deployment routinely +wants a few assets out of a large dataset, and a Kit stage-open touches exactly +one asset folder, so a whole-repo preload would spend rate limit, memory and +startup time on assets nobody opens. + +Folder granularity is the deliberate middle ground: one recursive ``tree`` call +scoped to an asset folder costs the same round trip as a single-file +``paths-info``, and Kit is about to ask for that folder's textures, MDL and +sidecars anyway. +""" + +from __future__ import annotations + +import json +import logging +from collections.abc import Mapping +from dataclasses import dataclass + +from . import addressing +from .cache import MISSING, Missing, SingleFlightCache +from .catalog.model import Catalog, LayoutConfig, RepoConfig +from .hf.client import HFClient, HFNotFound +from .hf.models import TreeEntry +from .settings import Settings + +logger = logging.getLogger(__name__) + + +@dataclass(frozen=True) +class LoadedFolder: + """One asset folder's contents. Immutable once built.""" + + repo_key: str + revision: str # resolved sha, never "main" + asset_name: str + root_usd: str # repo-relative path to the indexable USD + files: Mapping[str, TreeEntry] # repo-relative path -> entry + subfolders: frozenset[str] # repo-relative directory paths + + def entry(self, path: str) -> TreeEntry | None: + return self.files.get(path) + + def has_folder(self, path: str) -> bool: + stripped = path.strip("/") + return stripped == self.asset_name or stripped in self.subfolders + + +@dataclass(frozen=True) +class Resolved: + """An address resolved against the catalog — before any HF call.""" + + repo: RepoConfig + layout: LayoutConfig + asset_name: str + path: str + is_folder: bool + # The revision the address named, when it carried one. Checked against the + # revision actually being served before anything is returned. + address_revision: str | None = None + + +class AssetStore: + """Lazily-loaded view over the catalogued asset folders.""" + + def __init__(self, catalog: Catalog, hf: HFClient, settings: Settings) -> None: + self._catalog = catalog + self._hf = hf + self._settings = settings + self._folders: SingleFlightCache[tuple[str, str, str], LoadedFolder] = SingleFlightCache( + ttl=settings.folder_cache_ttl, + negative_ttl=settings.negative_cache_ttl, + max_size=settings.folder_cache_size, + ) + self._sidecars: SingleFlightCache[tuple[str, str, str], dict] = SingleFlightCache( + ttl=settings.folder_cache_ttl, + negative_ttl=settings.negative_cache_ttl, + max_size=settings.folder_cache_size * 4, + ) + # Revisions get their own cache: a resolved sha is tiny and shared by + # every folder in the repo. + self._revisions: SingleFlightCache[str, str] = SingleFlightCache( + ttl=settings.revision_ttl, + negative_ttl=settings.negative_cache_ttl, + max_size=64, + ) + # `ResourceIdentity.encoded_identity` -> the address it was minted for. + # omni.client hands that identity straight back as `GetMetadataRequest.uri` + # (contract doc §5.1), so the metadata service needs a way home from it. + # Sized like the sidecar cache: one entry per file we have ever stat-ed, + # which is a small multiple of the folders we hold. + self._identities: SingleFlightCache[str, str] = SingleFlightCache( + ttl=settings.folder_cache_ttl, + negative_ttl=settings.negative_cache_ttl, + max_size=settings.folder_cache_size * 4, + ) + + # -- catalog-only resolution (no network) --------------------------------- + + @property + def catalog(self) -> Catalog: + return self._catalog + + @property + def hf(self) -> HFClient: + return self._hf + + def swap_catalog(self, catalog: Catalog) -> None: + """Adopt a reloaded catalog. Cached folders stay valid — they are keyed by + (repo, sha, folder), so anything the new catalog drops simply stops being + reachable and ages out.""" + self._catalog = catalog + + @property + def _revision_in_uri(self) -> bool: + return self._settings.uri_revision_mode != "never" + + def _emit_revision(self, repo: RepoConfig, revision: str | None) -> str | None: + """Should an address for this repo carry `/resolve//`? + + `auto` includes it only for a pinned revision. A moving ref deliberately + stays out: the revision is not part of the URI precisely so `base_key` + survives a re-crawl, and embedding a sha that moves would make every + asset look new on every commit (plan §6.1). + """ + mode = self._settings.uri_revision_mode + if mode == "never" or revision is None: + return None + if mode == "always" or _looks_like_sha(repo.revision): + return revision + return None + + def top_level_addresses(self) -> list[str]: + return [ + addressing.build( + host=self._catalog.host(repo), + repo_type=repo.repo_type, + repo_id=repo.repo_id, + is_folder=True, + scheme=self._settings.uri_scheme, + ) + for repo in self._catalog.repos + ] + + def repo_for_root(self, address: str) -> RepoConfig | None: + parsed = self._parse(address) + if parsed is None: + return None + repo = self._catalog.repo(parsed.repo_type, parsed.repo_id) + return repo if repo and self._host_matches(parsed, repo) else None + + def resolve(self, address: str) -> Resolved | None: + """Map an address to its catalogued asset folder, using the catalog only. + + Returns ``None`` when the address is outside every catalogued asset + folder. **This is the access boundary** (plan §8.4): the check costs no + upstream request, so probing uncatalogued paths cannot generate HF + traffic, and laziness never weakens it. + """ + parsed = self._parse(address) + if parsed is None: + return None + repo = self._catalog.repo(parsed.repo_type, parsed.repo_id) + if repo is None or not self._host_matches(parsed, repo): + return None + layout = self._catalog.layout_for(repo) + if parsed.revision and _looks_like_sha(repo.revision) and parsed.revision != repo.revision: + # Pinned repo: a wrong revision is answerable from the catalog alone, + # so it costs no upstream request. + return None + + for asset_name in repo.assets: + if addressing.is_within(parsed.path, asset_name): + return Resolved( + repo=repo, + layout=layout, + asset_name=asset_name, + path=parsed.path, + is_folder=parsed.is_folder, + address_revision=parsed.revision, + ) + return None + + def is_repo_root(self, address: str) -> bool: + """Is this the root of a served repo, with or without a trailing slash?""" + parsed = addressing.try_parse(address, scheme=self._settings.uri_scheme) + return ( + parsed is not None + and parsed.path == "" + and self._catalog.repo(parsed.repo_type, parsed.repo_id) is not None + ) + + def address_for( + self, + repo: RepoConfig, + path: str, + *, + is_folder: bool = False, + revision: str | None = None, + ) -> str: + return addressing.build( + host=self._catalog.host(repo), + repo_type=repo.repo_type, + repo_id=repo.repo_id, + path=path, + is_folder=is_folder, + scheme=self._settings.uri_scheme, + revision=self._emit_revision(repo, revision), + ) + + def _host_matches(self, parsed, repo: RepoConfig) -> bool: + """The address must name the host this repo is configured against. + + Without this, accepting the `https://` form would make any host resolve — + so an endpoint mismatch (an HF Enterprise deployment, say) would serve + the right paths from the wrong namespace instead of failing. + """ + return parsed.host == self._catalog.host(repo) + + def _parse(self, address: str): + return addressing.try_parse( + address, scheme=self._settings.uri_scheme, revision_in_uri=self._revision_in_uri + ) + + # -- lazy loading --------------------------------------------------------- + + async def revision(self, repo: RepoConfig) -> str: + """Resolve the configured revision to a commit sha. + + A pinned sha short-circuits: no call at all. A moving ref costs one cheap + request per ``HF_ADAPTER_REVISION_TTL``, and the resolved sha then keys + every folder and sidecar entry, so cached content is immutable by + construction and never needs invalidating (plan §5.2, §6.9). + """ + if _looks_like_sha(repo.revision): + return repo.revision + + async def load() -> str: + return await self._hf.repo_sha(repo.repo_type, repo.repo_id, token=repo.token) + + sha = await self._revisions.get(repo.key, load) + if isinstance(sha, Missing): # pragma: no cover - repo_sha raises instead + raise HFNotFound(repo.repo_id) + return sha + + async def folder(self, repo: RepoConfig, asset_name: str) -> LoadedFolder | None: + """Load one asset folder, or return ``None`` if it is absent upstream.""" + revision = await self.revision(repo) + key = (repo.key, revision, asset_name) + + async def load() -> LoadedFolder | Missing: + layout = self._catalog.layout_for(repo) + if layout.catalog_kind == "wrapp": + return await self._load_wrapp_folder(repo, revision, asset_name, layout) + try: + entries = await self._hf.list_tree( + repo.repo_type, repo.repo_id, revision, asset_name, recursive=True, token=repo.token + ) + except HFNotFound: + logger.info("asset folder %s absent in %s@%s", asset_name, repo.repo_id, revision[:8]) + return MISSING + files = {e.path: e for e in entries if e.is_file} + subfolders = frozenset(e.path for e in entries if not e.is_file) + root_usd = await self._resolve_root_usd(repo, revision, asset_name, layout, files) + return LoadedFolder( + repo_key=repo.key, + revision=revision, + asset_name=asset_name, + root_usd=root_usd, + files=files, + subfolders=subfolders, + ) + + loaded = await self._folders.get(key, load) + return None if isinstance(loaded, Missing) else loaded + + async def _load_wrapp_folder( + self, repo: RepoConfig, revision: str, asset_name: str, layout: LayoutConfig + ) -> LoadedFolder | Missing: + """Build the folder from the ``.wrapp`` catalog manifest instead of + ``list_tree`` (plan §6.3.2). + + Trades one HF request for another, but off a different bucket: `.wrapp` + is fetched via `resolve` (the large bucket every plain file download + uses), where `list_tree` is an `api`-bucket call — the one that rate + limits first under a large `Enumerate`/`discover`, one `list_tree` per + asset having nothing to amortise it against. `catalog.items[]` already + carries every file's relative path, size and hash, so this also removes + the recursive tree read entirely rather than just moving its cost. + + Deliberately does not add the `.wrapp` file itself to the returned + folder's `files` — nothing resolves it (§6.5's `layout.manifest` for + this `catalog_kind` is `metadata.json`, not this file), and it has no + entry of its own inside its own catalog to source a size/hash from. + """ + wrapp_path = f"{asset_name}/.{_wrapp_folder_basename(asset_name)}{layout.marker_suffix}" + payload = await self._sidecar_json(repo, revision, wrapp_path) + if payload is None: + logger.info( + "asset folder %s absent in %s@%s (no %s)", asset_name, repo.repo_id, revision[:8], wrapp_path + ) + return MISSING + + items = ((payload.get("catalog") or {}).get("items")) or [] + files: dict[str, TreeEntry] = {} + subfolders: set[str] = set() + for item in items: + relative_path = item.get("relative_path") + if not relative_path: + continue + path = f"{asset_name}/{relative_path}" + files[path] = TreeEntry( + path=path, + type="file", + size=int(item.get("size") or 0), + etag=_wrapp_item_etag(item.get("hash")), + last_modified=None, + ) + parts = relative_path.split("/")[:-1] + prefix = asset_name + for part in parts: + prefix = f"{prefix}/{part}" + subfolders.add(prefix) + + root_usd = await self._resolve_root_usd(repo, revision, asset_name, layout, files) + return LoadedFolder( + repo_key=repo.key, + revision=revision, + asset_name=asset_name, + root_usd=root_usd, + files=files, + subfolders=frozenset(subfolders), + ) + + async def _resolve_root_usd( + self, + repo: RepoConfig, + revision: str, + asset_name: str, + layout: LayoutConfig, + files: Mapping[str, TreeEntry], + ) -> str: + """Pick the indexable USD. + + ``catalog_kind="wrapp"`` reads it from ``output_manifest``'s ``output`` + map — ``{stem: root_usd_filename}`` — instead of a root-USD index file; + the stem is not known ahead of time, so when that sidecar is missing or + unusable, the fallback is the one top-level USD file (``.usd``/``.usda``/ + ``.usdc``/``.usdz``) sitting directly at the asset folder's root + (verified 2026-09-11: the pipeline stopped writing ``output_manifest`` + entirely, so this is now the common path, not a rare one — + ``content_fallback``'s ``{stem}.usd`` has no real stem to substitute and + was rendering a nonsense doubled path). + + ``catalog_kind="package_entry"``: the marker file's own ``usd`` field is + the pointer — no separate index sidecar. Falls back the same way + ``wrapp`` does, to the one top-level USD file at the asset folder's root, + since this dataset's asset folders otherwise carry ambiguous duplicate + copies (plan docs/plans/simready-internal-catalog-kind.md §2.2). + + ``catalog_kind="manifest"``: ``root_usds.json`` where it exists, else the + naming convention (plan §3.3 — the index file was absent on 2 of 4 + sampled assets).""" + if layout.catalog_kind == "wrapp": + manifest_path = f"{asset_name}/{layout.output_manifest}" + payload = ( + await self._sidecar_json(repo, revision, manifest_path) if manifest_path in files else None + ) + output = (payload or {}).get("output") or {} + if output: + filename = next(iter(output.values())) + return f"{asset_name}/{str(filename).lstrip('/')}" + top_level_usd = _top_level_usd(asset_name, files) + if top_level_usd is not None: + return top_level_usd + logger.warning( + "%s has no usable output map and no top-level USD file; falling back to the naming" + " convention", + manifest_path, + ) + return f"{asset_name}/{layout.render(layout.content_fallback, asset_name)}" + + if layout.catalog_kind == "package_entry": + entry_path = f"{asset_name}/{layout.marker}" + payload = await self._sidecar_json(repo, revision, entry_path) if entry_path in files else None + usd = (payload or {}).get("usd") + candidate = f"{asset_name}/{str(usd).lstrip('/')}" if usd else None + # Verified live 2026-09-17 (nvidia/SimReady-Internal): a `usd` field + # can name a path that was never actually written into the packaged + # copy — the pipeline copied that asset's sidecar `.json` into + # `simready//usd/` but not its `.usda`/`.usdc`. Trusting the + # pointer blindly there drops the asset from Enumerate entirely + # (fileobject.py skips any entry whose root_usd misses), same + # failure mode as the `wrapp` incident (plan §13, 2026-09-11) — so + # this must be verified against `files`, not just parsed. + if candidate is not None and candidate in files: + return candidate + top_level_usd = _top_level_usd(asset_name, files) + if top_level_usd is not None: + if candidate is None: + logger.warning( + "%s has no usable 'usd' field; falling back to the top-level USD file", entry_path + ) + else: + logger.warning( + "%s names %s, which is not present in the folder; falling back to the top-level" + " USD file", + entry_path, + candidate, + ) + return top_level_usd + logger.warning( + "%s has no usable 'usd' field and no top-level USD file; falling back to the naming" + " convention", + entry_path, + ) + return f"{asset_name}/{layout.render(layout.content_fallback, asset_name)}" + + index_path = f"{asset_name}/{layout.render(layout.root_usd_index, asset_name)}" + if index_path in files: + payload = await self._sidecar_json(repo, revision, index_path) + entries = (payload or {}).get("entries") or [] + if entries: + # entries[] are relative to the asset folder. + return f"{asset_name}/{str(entries[0]).lstrip('/')}" + logger.warning("%s has an empty entries[]; falling back to the naming convention", index_path) + return f"{asset_name}/{layout.render(layout.content_fallback, asset_name)}" + + async def _sidecar_json(self, repo: RepoConfig, revision: str, path: str) -> dict | None: + """Fetch and parse a small JSON sidecar. Immutable within a revision.""" + key = (repo.key, revision, path) + + async def load() -> dict | Missing: + try: + raw = await self._hf.get_bytes(repo.repo_type, repo.repo_id, revision, path, token=repo.token) + except HFNotFound: + return MISSING + try: + parsed = json.loads(raw) + except json.JSONDecodeError: + logger.warning("sidecar %s is not valid JSON; ignoring", path) + return MISSING + return parsed if isinstance(parsed, dict) else MISSING + + result = await self._sidecars.get(key, load) + return None if isinstance(result, Missing) else result + + async def sidecar_json(self, repo: RepoConfig, path: str) -> dict | None: + return await self._sidecar_json(repo, await self.revision(repo), path) + + # -- the shapes the servicers need ---------------------------------------- + + async def _serves_revision(self, resolved: Resolved) -> bool: + """Does the address name the revision we are actually serving? + + Only reachable for a moving ref — a pinned mismatch is already rejected + in :meth:`resolve` without touching the network. Serving current content + under a stale sha would make the address a lie, so it is NOT_FOUND. + """ + if resolved.address_revision is None: + return True + return resolved.address_revision == await self.revision(resolved.repo) + + # -- resource identities -------------------------------------------------- + + def remember_identity(self, identity: str, address: str) -> None: + """Record which address a ``ResourceIdentity`` was minted for. + + Called from the one place that builds a ``ResourceInfo``, so every + identity we ever put on the wire can be mapped back (contract doc §5.1). + """ + if identity: + self._identities.put(identity, address) + + def address_for_identity(self, identity: str) -> str | None: + """The address an ``encoded_identity`` was minted for, if still known. + + ``None`` once the entry has aged out — the caller then treats the + identity as unresolvable, exactly as it would an unknown address. In + practice the lookup always follows the ``Stat`` that minted it by + milliseconds. + """ + cached = self._identities.peek(identity) + return cached if isinstance(cached, str) else None + + async def stat(self, address: str) -> tuple[Resolved, TreeEntry] | None: + """Resolve + load just enough to answer ``Stat``. ``None`` is NOT_FOUND.""" + resolved = self.resolve(address) + if resolved is None: + return None + if not await self._serves_revision(resolved): + return None + loaded = await self.folder(resolved.repo, resolved.asset_name) + if loaded is None: + return None + entry = loaded.entry(resolved.path) + if entry is None: + return None + return resolved, entry + + async def stat_folder(self, address: str) -> Resolved | None: + """Answer ``Stat`` for a folder address (one that ends in ``/``).""" + resolved = self.resolve(address) + if resolved is None: + return None + if not await self._serves_revision(resolved): + return None + loaded = await self.folder(resolved.repo, resolved.asset_name) + if loaded is None or not loaded.has_folder(resolved.path): + return None + return resolved + + @property + def stats(self) -> dict[str, float]: + return { + "folder_hits": self._folders.stats.hits, + "folder_misses": self._folders.stats.misses, + "folder_loads": self._folders.stats.loads, + "folder_negative_hits": self._folders.stats.negative_hits, + "folder_cached": len(self._folders), + "folder_hit_rate": self._folders.stats.hit_rate, + "sidecar_loads": self._sidecars.stats.loads, + "revision_loads": self._revisions.stats.loads, + } + + +def _looks_like_sha(revision: str) -> bool: + return len(revision) == 40 and all(c in "0123456789abcdef" for c in revision.lower()) + + +def _top_level_usd(asset_name: str, files: Mapping[str, TreeEntry]) -> str | None: + """The one USD file (``.usd``/``.usda``/``.usdc``/``.usdz``) sitting directly + at the asset folder's root, if there is exactly one candidate set to choose + from. Shared by ``wrapp`` and ``package_entry``'s root-USD fallback — both + reach for this when their own sidecar pointer is missing or unusable.""" + top_level_usds = sorted( + path + for path in files + if path.startswith(f"{asset_name}/") + and "/" not in path[len(asset_name) + 1 :] + and path.endswith((".usd", ".usda", ".usdc", ".usdz")) + ) + return top_level_usds[0] if top_level_usds else None + + +def _wrapp_folder_basename(asset_name: str) -> str: + """The ``.wrapp`` file's own name embeds the asset folder's basename, not + the full ``asset_name`` — which under ``catalog_kind: wrapp`` is + ``/``, one level deeper (plan §6.3.2).""" + parent = asset_name.rsplit("/", 1)[0] if "/" in asset_name else asset_name + return parent.rsplit("/", 1)[-1] + + +def _wrapp_item_etag(raw_hash: str | None) -> str: + """``catalog.items[].hash`` is ``";;"`` + (e.g. ``sha-256-flat;1048576;b4fecc7d...``) — the digest is what stands in + for an etag elsewhere in this service.""" + if not raw_hash: + return "" + return raw_hash.rsplit(";", 1)[-1] diff --git a/docker/hf-space/nginx.conf.template b/docker/hf-space/nginx.conf.template index eb704b9644cb9abc06514585b5d725b9c7dbc536..93e7727de5d5654b7ff637a9d69162de986be365 100644 --- a/docker/hf-space/nginx.conf.template +++ b/docker/hf-space/nginx.conf.template @@ -160,9 +160,15 @@ server { gzip_types text/css application/javascript application/json image/svg+xml; # stock gzip covers text/html only # Runtime index registry (blocking