otdf-python 0.3.2__tar.gz → 0.3.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {otdf_python-0.3.2 → otdf_python-0.3.4}/.github/check_entitlements.sh +0 -1
- {otdf_python-0.3.2 → otdf_python-0.3.4}/.github/workflows/build-python.yaml +0 -3
- {otdf_python-0.3.2 → otdf_python-0.3.4}/.pre-commit-config.yaml +1 -1
- otdf_python-0.3.4/.release-please-manifest.json +3 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/CHANGELOG.md +18 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/PKG-INFO +1 -5
- {otdf_python-0.3.2 → otdf_python-0.3.4}/README.md +0 -4
- otdf_python-0.3.4/docs/CONNECT_RPC.md +156 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/README.md +7 -7
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/pyproject.toml +1 -1
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/scripts/build_connect_proto.sh +1 -1
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/scripts/generate_connect_proto.py +6 -6
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/uv.lock +1 -1
- {otdf_python-0.3.2 → otdf_python-0.3.4}/pyproject.toml +2 -1
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/auth_headers.py +13 -1
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/cli.py +9 -9
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/header.py +2 -2
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/kas_connect_rpc_client.py +7 -1
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/nanotdf.py +1 -1
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/sdk.py +6 -84
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/sdk_builder.py +5 -37
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/conftest.py +1 -1
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/otdfctl_only/test_otdfctl_generated_fixtures.py +2 -2
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/otdfctl_to_python/test_cli_comparison.py +2 -2
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/otdfctl_to_python/test_tdf_reader_integration.py +7 -7
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/test_cli_integration.py +4 -4
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/test_cli_tdf_validation.py +3 -3
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/test_pe_interaction.py +3 -3
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/support_common.py +2 -2
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_cli.py +5 -6
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_crypto_utils.py +1 -1
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_inner_classes.py +21 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_manifest_format.py +2 -2
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_sdk.py +0 -3
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_sdk_builder.py +5 -5
- otdf_python-0.3.4/tests/test_sdk_mock.py +31 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_sdk_tdf_integration.py +4 -4
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_tdf.py +1 -1
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_tdf_reader.py +2 -2
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_url_normalization.py +0 -6
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_validate_otdf_python.py +4 -4
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_zip_reader.py +2 -1
- {otdf_python-0.3.2 → otdf_python-0.3.4}/uv.lock +21 -21
- otdf_python-0.3.2/.release-please-manifest.json +0 -3
- otdf_python-0.3.2/docs/CONNECT_RPC_MIGRATION.md +0 -283
- otdf_python-0.3.2/docs/PROTOBUF_SETUP.md +0 -135
- otdf_python-0.3.2/tests/test_sdk_mock.py +0 -58
- {otdf_python-0.3.2 → otdf_python-0.3.4}/.github/start_opentdf_docker.sh +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/.github/workflows/platform-integration-test.yaml +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/.github/workflows/release-please.yaml +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/.github/workflows/test-suite.yaml +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/.gitignore +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/.release-please-config-develop.json +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/.release-please-config.json +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/.release-please-manifest-develop.json +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/.vscode/extensions.json +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/.vscode/settings.json +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/LICENSE +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/conftest.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/docs/DEVELOPING.md +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/docs/LEGACY_VERSION.md +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/docs/RELEASES.md +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/buf.gen.yaml +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/buf.lock +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/buf.yaml +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/authorization/authorization.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/authorization/v2/authorization.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/common/common.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/entity/entity.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/entityresolution/entity_resolution.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/entityresolution/v2/entity_resolution.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/kas/kas.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/logger/audit/test.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/policy/actions/actions.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/policy/attributes/attributes.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/policy/kasregistry/key_access_server_registry.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/policy/keymanagement/key_management.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/policy/namespaces/namespaces.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/policy/objects.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/policy/registeredresources/registered_resources.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/policy/resourcemapping/resource_mapping.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/policy/selectors.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/policy/subjectmapping/subject_mapping.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/policy/unsafe/unsafe.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/proto-files/wellknownconfiguration/wellknown_configuration.proto +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/scripts/setup_connect_rpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/__init__.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/authorization/__init__.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/authorization/authorization_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/authorization/authorization_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/authorization/authorization_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/authorization/v2/authorization_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/authorization/v2/authorization_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/authorization/v2/authorization_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/common/__init__.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/common/common_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/common/common_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/entity/__init__.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/entity/entity_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/entity/entity_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/entityresolution/__init__.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/entityresolution/entity_resolution_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/entityresolution/entity_resolution_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/entityresolution/entity_resolution_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/entityresolution/v2/entity_resolution_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/entityresolution/v2/entity_resolution_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/entityresolution/v2/entity_resolution_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/kas/__init__.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/kas/kas_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/kas/kas_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/kas/kas_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/__init__.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/authorization/authorization_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/authorization/v2/authorization_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/common/common_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/entity/entity_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/entityresolution/entity_resolution_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/entityresolution/v2/entity_resolution_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/kas/kas_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/logger/audit/test_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/policy/actions/actions_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/policy/attributes/attributes_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/policy/kasregistry/key_access_server_registry_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/policy/keymanagement/key_management_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/policy/namespaces/namespaces_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/policy/objects_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/policy/registeredresources/registered_resources_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/policy/resourcemapping/resource_mapping_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/policy/selectors_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/policy/subjectmapping/subject_mapping_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/policy/unsafe/unsafe_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/legacy_grpc/wellknownconfiguration/wellknown_configuration_pb2_grpc.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/logger/__init__.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/logger/audit/test_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/logger/audit/test_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/__init__.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/actions/actions_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/actions/actions_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/actions/actions_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/attributes/attributes_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/attributes/attributes_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/attributes/attributes_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/kasregistry/key_access_server_registry_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/kasregistry/key_access_server_registry_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/kasregistry/key_access_server_registry_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/keymanagement/key_management_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/keymanagement/key_management_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/keymanagement/key_management_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/namespaces/namespaces_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/namespaces/namespaces_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/namespaces/namespaces_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/objects_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/objects_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/registeredresources/registered_resources_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/registeredresources/registered_resources_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/registeredresources/registered_resources_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/resourcemapping/resource_mapping_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/resourcemapping/resource_mapping_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/resourcemapping/resource_mapping_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/selectors_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/selectors_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/subjectmapping/subject_mapping_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/subjectmapping/subject_mapping_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/subjectmapping/subject_mapping_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/unsafe/unsafe_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/unsafe/unsafe_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/policy/unsafe/unsafe_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/wellknownconfiguration/__init__.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/wellknownconfiguration/wellknown_configuration_pb2.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/wellknownconfiguration/wellknown_configuration_pb2.pyi +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/otdf-python-proto/src/otdf_python_proto/wellknownconfiguration/wellknown_configuration_pb2_connect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/__init__.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/__main__.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/address_normalizer.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/aesgcm.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/assertion_config.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/asym_crypto.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/asym_decryption.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/asym_encryption.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/autoconfigure_utils.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/collection_store.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/collection_store_impl.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/config.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/connect_client.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/constants.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/crypto_utils.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/dpop.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/ecc_mode.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/eckeypair.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/invalid_zip_exception.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/kas_client.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/kas_info.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/kas_key_cache.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/key_type.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/key_type_constants.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/manifest.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/nanotdf_ecdsa_struct.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/nanotdf_type.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/policy_binding_serializer.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/policy_info.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/policy_object.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/policy_stub.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/resource_locator.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/sdk_exceptions.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/symmetric_and_payload_config.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/tdf.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/tdf_reader.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/tdf_writer.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/token_source.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/version.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/zip_reader.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/src/otdf_python/zip_writer.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/__init__.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/config_pydantic.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/otdfctl_to_python/test_cli_decrypt.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/otdfctl_to_python/test_cli_inspect.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/python_only/test_kas_client_integration.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/support_sdk.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/test_data/empty_file.txt +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/test_data/sample_binary.png +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/test_data/sample_text.txt +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/integration/test_data/sample_with_attributes.txt +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/mock_crypto.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/server_logs.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/support_cli_args.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/support_otdfctl.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/support_otdfctl_args.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_address_normalizer.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_aesgcm.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_assertion_config.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_asym_encryption.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_autoconfigure_utils.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_collection_store.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_config.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_eckeypair.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_header.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_kas_client.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_kas_key_cache.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_kas_key_management.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_key_type.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_log_collection.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_manifest.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_nanotdf.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_nanotdf_ecdsa_struct.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_nanotdf_integration.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_nanotdf_type.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_policy_object.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_sdk_exceptions.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_tdf_key_management.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_tdf_writer.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_token_source.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_use_plaintext_flow.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_version.py +0 -0
- {otdf_python-0.3.2 → otdf_python-0.3.4}/tests/test_zip_writer.py +0 -0
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.4](https://github.com/b-long/opentdf-python-sdk/compare/otdf-python-v0.3.3...otdf-python-v0.3.4) (2025-10-04)
|
|
4
|
+
|
|
5
|
+
### Chores
|
|
6
|
+
|
|
7
|
+
* chore: remove placeholders ([#110](https://github.com/b-long/opentdf-python-sdk/issues/110))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
* update ruff ([#108](https://github.com/b-long/opentdf-python-sdk/issues/108)) ([5e4c796](https://github.com/b-long/opentdf-python-sdk/commit/5e4c796a8c1fc10b206cd2769f7c8548903ad3c1))
|
|
13
|
+
|
|
14
|
+
## [0.3.3](https://github.com/b-long/opentdf-python-sdk/compare/otdf-python-v0.3.2...otdf-python-v0.3.3) (2025-09-17)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* improve docs ([#106](https://github.com/b-long/opentdf-python-sdk/issues/106)) ([49aa4ae](https://github.com/b-long/opentdf-python-sdk/commit/49aa4aea5e576c20b3e26c852331de8b0469742f))
|
|
20
|
+
|
|
3
21
|
## [0.3.2](https://github.com/b-long/opentdf-python-sdk/compare/otdf-python-v0.3.1...otdf-python-v0.3.2) (2025-09-12)
|
|
4
22
|
|
|
5
23
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: otdf-python
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: Unofficial OpenTDF SDK for Python
|
|
5
5
|
Author-email: b-long <b-long@users.noreply.github.com>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -102,8 +102,6 @@ with open("encrypted.tdf", "wb") as f:
|
|
|
102
102
|
### Decrypt Data
|
|
103
103
|
|
|
104
104
|
```python
|
|
105
|
-
from otdf_python.tdf import TDFReaderConfig
|
|
106
|
-
|
|
107
105
|
# Read encrypted TDF file
|
|
108
106
|
with open("encrypted.tdf", "rb") as f:
|
|
109
107
|
encrypted_data = f.read()
|
|
@@ -116,8 +114,6 @@ decrypted_data = tdf_reader.payload
|
|
|
116
114
|
with open("decrypted.txt", "wb") as f:
|
|
117
115
|
f.write(decrypted_data)
|
|
118
116
|
|
|
119
|
-
# Don't forget to close the SDK when done
|
|
120
|
-
sdk.close()
|
|
121
117
|
```
|
|
122
118
|
|
|
123
119
|
## Project Structure
|
|
@@ -83,8 +83,6 @@ with open("encrypted.tdf", "wb") as f:
|
|
|
83
83
|
### Decrypt Data
|
|
84
84
|
|
|
85
85
|
```python
|
|
86
|
-
from otdf_python.tdf import TDFReaderConfig
|
|
87
|
-
|
|
88
86
|
# Read encrypted TDF file
|
|
89
87
|
with open("encrypted.tdf", "rb") as f:
|
|
90
88
|
encrypted_data = f.read()
|
|
@@ -97,8 +95,6 @@ decrypted_data = tdf_reader.payload
|
|
|
97
95
|
with open("decrypted.txt", "wb") as f:
|
|
98
96
|
f.write(decrypted_data)
|
|
99
97
|
|
|
100
|
-
# Don't forget to close the SDK when done
|
|
101
|
-
sdk.close()
|
|
102
98
|
```
|
|
103
99
|
|
|
104
100
|
## Project Structure
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Connect RPC in OpenTDF Python SDK
|
|
2
|
+
|
|
3
|
+
This document describes the Connect RPC implementation in the OpenTDF Python SDK, which provides a modern HTTP-friendly alternative to traditional gRPC.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Connect RPC is a protocol that brings the benefits of RPC to HTTP APIs. It's designed to be:
|
|
8
|
+
- **HTTP-compatible**: Works with standard HTTP infrastructure
|
|
9
|
+
- **Type-safe**: Generated from Protocol Buffer definitions
|
|
10
|
+
- **Efficient**: Binary protocol with JSON fallback
|
|
11
|
+
- **Simple**: Easy to debug and integrate
|
|
12
|
+
|
|
13
|
+
## Architecture
|
|
14
|
+
|
|
15
|
+
The SDK uses a two-module structure for protocol buffer generation:
|
|
16
|
+
|
|
17
|
+
- **Main SDK**: `src/otdf_python/` - Core SDK functionality
|
|
18
|
+
- **Protocol Generation**: `otdf-python-proto/` - Generated Connect RPC and protobuf files
|
|
19
|
+
|
|
20
|
+
### Generated Files
|
|
21
|
+
|
|
22
|
+
Connect RPC generates the following files in `otdf-python-proto/src/otdf_python_proto/`:
|
|
23
|
+
|
|
24
|
+
- `*_connect.py` - Connect RPC client implementations (recommended)
|
|
25
|
+
- `*_pb2.py` - Protocol buffer message definitions
|
|
26
|
+
- `legacy_grpc/*_pb2_grpc.py` - Traditional gRPC clients (backward compatibility)
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
### Client Creation
|
|
31
|
+
|
|
32
|
+
Connect RPC clients are created using the generated `*_connect.py` modules:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from otdf_python_proto.kas import kas_connect
|
|
36
|
+
from otdf_python_proto.policy import policy_connect
|
|
37
|
+
|
|
38
|
+
# Create Connect RPC clients
|
|
39
|
+
kas_client = kas_connect.KeyAccessServiceClient(base_url="https://example.com")
|
|
40
|
+
policy_client = policy_connect.PolicyServiceClient(base_url="https://your-policy-endpoint")
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Authentication
|
|
44
|
+
|
|
45
|
+
Connect RPC clients support standard HTTP authentication:
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
import httpx
|
|
49
|
+
|
|
50
|
+
# Create authenticated HTTP client, assuming `token` holds your auth token
|
|
51
|
+
http_client = httpx.Client(
|
|
52
|
+
headers={"Authorization": f"Bearer {token}"}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Use with Connect RPC client
|
|
56
|
+
kas_client = kas_connect.KeyAccessServiceClient(
|
|
57
|
+
base_url="https://example.com",
|
|
58
|
+
http_client=http_client
|
|
59
|
+
)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Regenerating Connect RPC Files
|
|
63
|
+
|
|
64
|
+
To regenerate the Connect RPC and protobuf files:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
cd otdf-python-proto
|
|
68
|
+
uv run python scripts/generate_connect_proto.py
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Download Fresh Proto Files
|
|
72
|
+
|
|
73
|
+
To download the latest protocol definitions:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
cd otdf-python-proto
|
|
77
|
+
uv run python scripts/generate_connect_proto.py --download
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Requirements
|
|
81
|
+
|
|
82
|
+
- `buf` tool: `brew install bufbuild/buf/buf` (or see [official installation guide](https://buf.build/docs/installation))
|
|
83
|
+
- Python dependencies managed by `uv`
|
|
84
|
+
|
|
85
|
+
## Benefits Over gRPC
|
|
86
|
+
|
|
87
|
+
1. **HTTP Compatibility**: Works with load balancers, proxies, and other HTTP infrastructure
|
|
88
|
+
2. **Debugging**: Easy to inspect with standard HTTP tools
|
|
89
|
+
3. **Flexibility**: Supports both binary and JSON encoding
|
|
90
|
+
4. **Simplicity**: No special HTTP/2 requirements
|
|
91
|
+
|
|
92
|
+
## Migration from gRPC
|
|
93
|
+
|
|
94
|
+
If migrating from legacy gRPC clients:
|
|
95
|
+
|
|
96
|
+
1. Replace `*_pb2_grpc.py` imports with `*_connect.py`
|
|
97
|
+
2. Update client instantiation to use base URLs instead of channels
|
|
98
|
+
3. Leverage HTTP client features for authentication and configuration
|
|
99
|
+
|
|
100
|
+
## Testing
|
|
101
|
+
|
|
102
|
+
Connect RPC clients can be easily mocked and tested using standard HTTP testing tools:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
import httpx
|
|
106
|
+
import respx
|
|
107
|
+
from otdf_python_proto.kas import kas_pb2, kas_connect
|
|
108
|
+
|
|
109
|
+
@respx.mock
|
|
110
|
+
def test_connect_rpc_client():
|
|
111
|
+
# 1. Create a sample protobuf response message
|
|
112
|
+
expected_response = kas_pb2.RewrapResponse(
|
|
113
|
+
entity_wrapped_key=b'some-unwrapped-key'
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# 2. Mock the correct Connect RPC endpoint URL
|
|
117
|
+
respx.post("https://example.com/kas.AccessService/Rewrap").mock(
|
|
118
|
+
return_value=httpx.Response(
|
|
119
|
+
200,
|
|
120
|
+
# 3. Return the serialized protobuf message as content
|
|
121
|
+
content=expected_response.SerializeToString(),
|
|
122
|
+
headers={'Content-Type': 'application/proto'}
|
|
123
|
+
)
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
client = kas_connect.KeyAccessServiceClient(base_url="https://example.com")
|
|
127
|
+
# Test client calls...
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Error Handling
|
|
131
|
+
|
|
132
|
+
Connect RPC provides structured error handling through standard HTTP status codes and error details:
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from connectrpc import ConnectError
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
# Assuming `kas_client` and `request` are defined as in previous examples
|
|
139
|
+
response = kas_client.rewrap(request)
|
|
140
|
+
except ConnectError as e:
|
|
141
|
+
print(f"Connect RPC error: {e.code} - {e.message}")
|
|
142
|
+
# Handle specific error types
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Performance Considerations
|
|
146
|
+
|
|
147
|
+
- Use connection pooling with `httpx.Client` for better performance
|
|
148
|
+
- Configure appropriate timeouts for your use case
|
|
149
|
+
- Consider using binary encoding for high-throughput scenarios
|
|
150
|
+
|
|
151
|
+
## Additional Resources
|
|
152
|
+
|
|
153
|
+
For more information, see:
|
|
154
|
+
- [Connect RPC Documentation](https://connectrpc.com/docs/)
|
|
155
|
+
- [Connect Python Repository](https://github.com/connectrpc/connect-python)
|
|
156
|
+
- [OpenTDF Platform](https://github.com/opentdf/platform)
|
|
@@ -12,12 +12,12 @@ This project now supports **Connect RPC**, a modern HTTP-friendly alternative to
|
|
|
12
12
|
- 🚀 **Simplified deployment** - No special gRPC infrastructure required
|
|
13
13
|
- 📊 **Better observability** - Standard HTTP status codes and headers
|
|
14
14
|
|
|
15
|
-
See [
|
|
15
|
+
See [CONNECT_RPC.md](../docs/CONNECT_RPC.md) for additional information.
|
|
16
16
|
|
|
17
17
|
## Structure
|
|
18
18
|
|
|
19
19
|
- `proto-files/`: Contains the raw .proto files downloaded from the OpenTDF platform
|
|
20
|
-
- `
|
|
20
|
+
- `src/otdf_python_proto/`: Contains the generated Python protobuf and Connect RPC client files
|
|
21
21
|
- `scripts/`: Contains build scripts for generating protobuf and Connect RPC files
|
|
22
22
|
- `buf.yaml`: Buf configuration for proto validation and management
|
|
23
23
|
- `buf.gen.yaml`: Buf generation configuration for Connect RPC and protobuf
|
|
@@ -40,10 +40,10 @@ Or use the convenience script:
|
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
This generates:
|
|
43
|
-
- `
|
|
44
|
-
- `
|
|
45
|
-
- `
|
|
46
|
-
- `
|
|
43
|
+
- `src/otdf_python_proto/**/*_connect.py` - Connect RPC clients (preferred)
|
|
44
|
+
- `src/otdf_python_proto/**/*_pb2.py` - Standard protobuf classes
|
|
45
|
+
- `src/otdf_python_proto/**/*_pb2.pyi` - Type stubs for better IDE support
|
|
46
|
+
- `src/otdf_python_proto/legacy_grpc/**/*_pb2_grpc.py` - Legacy gRPC clients (backward compatibility)
|
|
47
47
|
|
|
48
48
|
### Legacy gRPC Generation
|
|
49
49
|
|
|
@@ -158,7 +158,7 @@ response = client.GetPolicy(request)
|
|
|
158
158
|
|
|
159
159
|
If you're migrating from traditional gRPC clients to Connect RPC:
|
|
160
160
|
|
|
161
|
-
1. Read the [Connect RPC Migration Guide](../
|
|
161
|
+
1. Read the [Connect RPC Migration Guide](../docs/CONNECT_RPC.md)
|
|
162
162
|
2. Run the Connect RPC generation: `./scripts/build_connect_proto.sh` (or from the submodule: `cd otdf-python-proto && uv run python scripts/generate_connect_proto.py`)
|
|
163
163
|
3. Update your client code to use `*_connect.py` modules
|
|
164
164
|
4. Test with your authentication and deployment setup
|
|
@@ -87,7 +87,7 @@ if [[ $? -eq 0 ]]; then
|
|
|
87
87
|
echo " python examples/connect_rpc_client_example.py"
|
|
88
88
|
echo ""
|
|
89
89
|
echo "For more information, see:"
|
|
90
|
-
echo " -
|
|
90
|
+
echo " - docs/CONNECT_RPC.md"
|
|
91
91
|
echo " - https://connectrpc.com/docs/"
|
|
92
92
|
else
|
|
93
93
|
echo "✗ Connect RPC generation failed!"
|
|
@@ -96,10 +96,10 @@ def copy_opentdf_proto_files(proto_gen_dir: Path) -> bool:
|
|
|
96
96
|
print(f" Copying {relative_path}...")
|
|
97
97
|
|
|
98
98
|
# Copy the file content
|
|
99
|
-
with open(
|
|
99
|
+
with proto_file.open() as src:
|
|
100
100
|
content = src.read()
|
|
101
101
|
|
|
102
|
-
with open(
|
|
102
|
+
with dest_path.open("w") as dst:
|
|
103
103
|
dst.write(content)
|
|
104
104
|
|
|
105
105
|
copied_files += 1
|
|
@@ -155,7 +155,7 @@ def run_buf_generate(proto_gen_dir: Path) -> bool:
|
|
|
155
155
|
|
|
156
156
|
# Update buf.gen.yaml with the correct path
|
|
157
157
|
buf_gen_path = proto_gen_dir / "buf.gen.yaml"
|
|
158
|
-
with open(
|
|
158
|
+
with buf_gen_path.open() as f:
|
|
159
159
|
content = f.read()
|
|
160
160
|
|
|
161
161
|
# Replace the local plugin path
|
|
@@ -163,7 +163,7 @@ def run_buf_generate(proto_gen_dir: Path) -> bool:
|
|
|
163
163
|
"- local: protoc-gen-connect_python", f"- local: {connect_plugin_path}"
|
|
164
164
|
)
|
|
165
165
|
|
|
166
|
-
with open(
|
|
166
|
+
with buf_gen_path.open("w") as f:
|
|
167
167
|
f.write(updated_content)
|
|
168
168
|
|
|
169
169
|
# Run buf generate
|
|
@@ -221,7 +221,7 @@ def _fix_ignore_if_default_value(proto_files_dir):
|
|
|
221
221
|
# Iterate all .proto files in the directory
|
|
222
222
|
for proto_file in proto_files_dir.glob("**/*.proto"):
|
|
223
223
|
try:
|
|
224
|
-
with open(
|
|
224
|
+
with proto_file.open("r") as file:
|
|
225
225
|
content = file.read()
|
|
226
226
|
|
|
227
227
|
# Replace the old enum value with the new one
|
|
@@ -230,7 +230,7 @@ def _fix_ignore_if_default_value(proto_files_dir):
|
|
|
230
230
|
)
|
|
231
231
|
|
|
232
232
|
# Write the updated content back to the file
|
|
233
|
-
with open(
|
|
233
|
+
with proto_file.open("w") as file:
|
|
234
234
|
file.write(updated_content)
|
|
235
235
|
|
|
236
236
|
print(f"Updated {proto_file.name} to use IGNORE_IF_ZERO_VALUE")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "otdf-python"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.4"
|
|
4
4
|
description = "Unofficial OpenTDF SDK for Python"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -73,6 +73,7 @@ lint.select = [
|
|
|
73
73
|
"I",
|
|
74
74
|
# Performance-related rules
|
|
75
75
|
"PERF", # Ruff's performance rules
|
|
76
|
+
"PTH", # pathlib (path handling)
|
|
76
77
|
# Additional useful rules
|
|
77
78
|
"UP", # pyupgrade (modern Python features)
|
|
78
79
|
"SIM", # flake8-simplify (simplifications)
|
|
@@ -10,7 +10,7 @@ class AuthHeaders:
|
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
auth_header: str
|
|
13
|
-
dpop_header: str
|
|
13
|
+
dpop_header: str = ""
|
|
14
14
|
|
|
15
15
|
def get_auth_header(self) -> str:
|
|
16
16
|
"""Returns the authorization header."""
|
|
@@ -19,3 +19,15 @@ class AuthHeaders:
|
|
|
19
19
|
def get_dpop_header(self) -> str:
|
|
20
20
|
"""Returns the DPoP header."""
|
|
21
21
|
return self.dpop_header
|
|
22
|
+
|
|
23
|
+
def to_dict(self) -> dict[str, str]:
|
|
24
|
+
"""
|
|
25
|
+
Convert authentication headers to a dictionary for use with HTTP clients.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
Dictionary with 'Authorization' header and optionally 'DPoP' header
|
|
29
|
+
"""
|
|
30
|
+
headers = {"Authorization": self.auth_header}
|
|
31
|
+
if self.dpop_header:
|
|
32
|
+
headers["DPoP"] = self.dpop_header
|
|
33
|
+
return headers
|
|
@@ -88,7 +88,7 @@ def load_client_credentials(creds_file_path: str) -> tuple[str, str]:
|
|
|
88
88
|
"CRITICAL", f"Credentials file does not exist: {creds_file_path}"
|
|
89
89
|
)
|
|
90
90
|
|
|
91
|
-
with open(
|
|
91
|
+
with creds_path.open() as f:
|
|
92
92
|
creds = json.load(f)
|
|
93
93
|
|
|
94
94
|
client_id = creds.get("clientId")
|
|
@@ -223,13 +223,13 @@ def cmd_encrypt(args):
|
|
|
223
223
|
|
|
224
224
|
try:
|
|
225
225
|
# Read input file
|
|
226
|
-
with open(
|
|
226
|
+
with input_path.open("rb") as input_file:
|
|
227
227
|
payload = input_file.read()
|
|
228
228
|
|
|
229
229
|
# Determine output
|
|
230
230
|
if args.output:
|
|
231
231
|
output_path = Path(args.output)
|
|
232
|
-
with open(
|
|
232
|
+
with output_path.open("wb") as output_file:
|
|
233
233
|
try:
|
|
234
234
|
# Create appropriate config based on container type
|
|
235
235
|
container_type = getattr(args, "container_type", "tdf")
|
|
@@ -247,7 +247,7 @@ def cmd_encrypt(args):
|
|
|
247
247
|
logger.debug("Creating TDF")
|
|
248
248
|
config = create_tdf_config(sdk, args)
|
|
249
249
|
output_stream = BytesIO()
|
|
250
|
-
|
|
250
|
+
_manifest, size, _ = sdk.create_tdf(
|
|
251
251
|
BytesIO(payload), config, output_stream
|
|
252
252
|
)
|
|
253
253
|
output_file.write(output_stream.getvalue())
|
|
@@ -274,7 +274,7 @@ def cmd_encrypt(args):
|
|
|
274
274
|
logger.debug("Creating TDF")
|
|
275
275
|
config = create_tdf_config(sdk, args)
|
|
276
276
|
output_stream = BytesIO()
|
|
277
|
-
|
|
277
|
+
_manifest, size, _ = sdk.create_tdf(
|
|
278
278
|
BytesIO(payload), config, output_stream
|
|
279
279
|
)
|
|
280
280
|
output_file.write(output_stream.getvalue())
|
|
@@ -296,13 +296,13 @@ def cmd_decrypt(args):
|
|
|
296
296
|
|
|
297
297
|
try:
|
|
298
298
|
# Read encrypted file
|
|
299
|
-
with open(
|
|
299
|
+
with input_path.open("rb") as input_file:
|
|
300
300
|
encrypted_data = input_file.read()
|
|
301
301
|
|
|
302
302
|
# Determine output
|
|
303
303
|
if args.output:
|
|
304
304
|
output_path = Path(args.output)
|
|
305
|
-
with open(
|
|
305
|
+
with output_path.open("wb") as output_file:
|
|
306
306
|
try:
|
|
307
307
|
# Try to determine if it's a NanoTDF or regular TDF
|
|
308
308
|
# NanoTDFs have a specific header format, regular TDFs are ZIP files
|
|
@@ -359,7 +359,7 @@ def cmd_inspect(args):
|
|
|
359
359
|
|
|
360
360
|
try:
|
|
361
361
|
# Read encrypted file
|
|
362
|
-
with open(
|
|
362
|
+
with input_path.open("rb") as input_file:
|
|
363
363
|
encrypted_data = input_file.read()
|
|
364
364
|
|
|
365
365
|
if encrypted_data.startswith(b"PK"):
|
|
@@ -400,7 +400,7 @@ def cmd_inspect(args):
|
|
|
400
400
|
except Exception as e:
|
|
401
401
|
# If we can't inspect due to auth issues, show what we can
|
|
402
402
|
logger.warning(f"Limited inspection due to: {e}")
|
|
403
|
-
with open(
|
|
403
|
+
with input_path.open("rb") as input_file:
|
|
404
404
|
encrypted_data = input_file.read()
|
|
405
405
|
|
|
406
406
|
file_type = "TDF" if encrypted_data.startswith(b"PK") else "NanoTDF"
|
|
@@ -51,7 +51,7 @@ class Header:
|
|
|
51
51
|
# MAGIC_NUMBER_AND_VERSION (3 bytes)
|
|
52
52
|
offset += 3
|
|
53
53
|
# ResourceLocator
|
|
54
|
-
|
|
54
|
+
_kas_locator, kas_size = ResourceLocator.from_bytes_with_size(buffer[offset:])
|
|
55
55
|
offset += kas_size
|
|
56
56
|
# ECC mode (1 byte)
|
|
57
57
|
ecc_mode = ECCMode(buffer[offset])
|
|
@@ -59,7 +59,7 @@ class Header:
|
|
|
59
59
|
# Payload config (1 byte)
|
|
60
60
|
offset += 1
|
|
61
61
|
# PolicyInfo
|
|
62
|
-
|
|
62
|
+
_policy_info, policy_size = PolicyInfo.from_bytes_with_size(
|
|
63
63
|
buffer[offset:], ecc_mode
|
|
64
64
|
)
|
|
65
65
|
offset += policy_size
|
|
@@ -9,6 +9,8 @@ import urllib3
|
|
|
9
9
|
from otdf_python_proto.kas import kas_pb2
|
|
10
10
|
from otdf_python_proto.kas.kas_pb2_connect import AccessServiceClient
|
|
11
11
|
|
|
12
|
+
from otdf_python.auth_headers import AuthHeaders
|
|
13
|
+
|
|
12
14
|
from .sdk_exceptions import SDKException
|
|
13
15
|
|
|
14
16
|
|
|
@@ -69,7 +71,11 @@ class KASConnectRPCClient:
|
|
|
69
71
|
Dictionary with authentication headers or None
|
|
70
72
|
"""
|
|
71
73
|
if access_token:
|
|
72
|
-
|
|
74
|
+
auth_headers = AuthHeaders(
|
|
75
|
+
auth_header=f"Bearer {access_token}",
|
|
76
|
+
dpop_header="", # Empty for now, ready for future DPoP support
|
|
77
|
+
)
|
|
78
|
+
return auth_headers.to_dict()
|
|
73
79
|
return None
|
|
74
80
|
|
|
75
81
|
def get_public_key(self, normalized_kas_url, kas_info, access_token=None):
|
|
@@ -300,7 +300,7 @@ class NanoTDF:
|
|
|
300
300
|
iv, ciphertext = self._encrypt_payload(payload, key)
|
|
301
301
|
|
|
302
302
|
# Wrap key if needed
|
|
303
|
-
wrapped_key,
|
|
303
|
+
wrapped_key, _kas_public_key = self._wrap_key_if_needed(key, config)
|
|
304
304
|
|
|
305
305
|
# Compose the complete NanoTDF: [IV][CIPHERTEXT][WRAPPED_KEY][WRAPPED_KEY_LEN]
|
|
306
306
|
if wrapped_key:
|