crossplane-function-sdk-python 0.5.0__tar.gz → 0.7.0__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.
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/.github/workflows/ci.yml +1 -1
- crossplane_function_sdk_python-0.7.0/CODEOWNERS +22 -0
- crossplane_function_sdk_python-0.7.0/OWNERS.md +18 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/PKG-INFO +6 -5
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/crossplane/function/__version__.py +1 -1
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/crossplane/function/proto/v1/run_function_pb2.py +3 -3
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/crossplane/function/proto/v1/run_function_pb2_grpc.py +1 -1
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/crossplane/function/proto/v1beta1/run_function_pb2.py +3 -3
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/crossplane/function/proto/v1beta1/run_function_pb2_grpc.py +1 -1
- crossplane_function_sdk_python-0.7.0/crossplane/function/py.typed +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/crossplane/function/resource.py +16 -12
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/crossplane/function/runtime.py +9 -1
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/pyproject.toml +11 -7
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/tests/test_resource.py +87 -1
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/tests/testdata/models/io/upbound/aws/s3/v1beta2.py +2 -2
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/.gitignore +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/LICENSE +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/README.md +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/crossplane/function/logging.py +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/crossplane/function/proto/v1/run_function.proto +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/crossplane/function/proto/v1/run_function_pb2.pyi +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/crossplane/function/proto/v1beta1/run_function.proto +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/crossplane/function/proto/v1beta1/run_function_pb2.pyi +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/crossplane/function/response.py +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/renovate.json +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/tests/test_response.py +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/tests/test_runtime.py +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/tests/testdata/models/io/k8s/apimachinery/pkg/apis/__init__.py +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/tests/testdata/models/io/k8s/apimachinery/pkg/apis/meta/__init__.py +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/tests/testdata/models/io/k8s/apimachinery/pkg/apis/meta/v1.py +0 -0
- {crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/tests/testdata/models/io/upbound/aws/s3/__init__.py +0 -0
|
@@ -120,7 +120,7 @@ jobs:
|
|
|
120
120
|
path: "dist"
|
|
121
121
|
|
|
122
122
|
- name: Publish to PyPI
|
|
123
|
-
uses: pypa/gh-action-pypi-publish@v1.
|
|
123
|
+
uses: pypa/gh-action-pypi-publish@v1.12.4
|
|
124
124
|
with:
|
|
125
125
|
# Note that this is currently being pushed to the 'crossplane' PyPI
|
|
126
126
|
# user (not org). See @negz if you need access - PyPI requires 2FA to
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
# SPDX-FileCopyrightText: 2025 The Crossplane Authors <https://crossplane.io>
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: CC0-1.0
|
|
5
|
+
|
|
6
|
+
# This file controls automatic PR reviewer assignment. See the following docs:
|
|
7
|
+
#
|
|
8
|
+
# * https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
|
|
9
|
+
# * https://docs.github.com/en/organizations/organizing-members-into-teams/managing-code-review-settings-for-your-team
|
|
10
|
+
#
|
|
11
|
+
# The goal of this file is for most PRs to automatically and fairly have one
|
|
12
|
+
# maintainer set as PR reviewers. All maintainers have permission to approve
|
|
13
|
+
# and merge PRs. All PRs must be approved by at least one maintainer before being merged.
|
|
14
|
+
#
|
|
15
|
+
# Where possible, prefer explicitly specifying a maintainer who is a subject
|
|
16
|
+
# matter expert for a particular part of the codebase rather than using fallback
|
|
17
|
+
# owners. Fallback owners are listed at the bottom of this file.
|
|
18
|
+
#
|
|
19
|
+
# See also OWNERS.md for governance details
|
|
20
|
+
|
|
21
|
+
# Fallback owners
|
|
22
|
+
* @negz @bobh66
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2025 The Crossplane Authors <https://crossplane.io>
|
|
3
|
+
|
|
4
|
+
SPDX-License-Identifier: CC-BY-4.0
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
# OWNERS
|
|
8
|
+
|
|
9
|
+
This page lists all maintainers for **this** repository. Each repository in the
|
|
10
|
+
[Crossplane Contrib organization](https://github.com/crossplane-contrib/) will list their
|
|
11
|
+
repository maintainers in their own `OWNERS.md` file.
|
|
12
|
+
|
|
13
|
+
## Maintainers
|
|
14
|
+
* Nic Cope <negz@upbound.com> ([negz](https://github.com/negz))
|
|
15
|
+
* Bob Haddleton <bob.haddleton@nokia.com> ([bobh66](https://github.com/bobh66))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
See [CODEOWNERS](./CODEOWNERS) for automatic PR assignment.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: crossplane-function-sdk-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: The Python SDK for Crossplane composition functions
|
|
5
5
|
Project-URL: Documentation, https://github.com/crossplane/function-sdk-python#readme
|
|
6
6
|
Project-URL: Issues, https://github.com/crossplane/function-sdk-python/issues
|
|
@@ -11,12 +11,13 @@ License-File: LICENSE
|
|
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
|
12
12
|
Classifier: Programming Language :: Python
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Typing :: Typed
|
|
14
15
|
Requires-Python: >=3.11
|
|
15
16
|
Requires-Dist: grpcio-reflection==1.*
|
|
16
|
-
Requires-Dist: grpcio==1
|
|
17
|
-
Requires-Dist: protobuf==5.
|
|
17
|
+
Requires-Dist: grpcio==1.71.0
|
|
18
|
+
Requires-Dist: protobuf==5.29.3
|
|
18
19
|
Requires-Dist: pydantic==2.*
|
|
19
|
-
Requires-Dist: structlog==
|
|
20
|
+
Requires-Dist: structlog==25.*
|
|
20
21
|
Description-Content-Type: text/markdown
|
|
21
22
|
|
|
22
23
|
# function-sdk-python
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
3
|
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
4
|
# source: crossplane/function/proto/v1/run_function.proto
|
|
5
|
-
# Protobuf Python Version: 5.
|
|
5
|
+
# Protobuf Python Version: 5.29.0
|
|
6
6
|
"""Generated protocol buffer code."""
|
|
7
7
|
from google.protobuf import descriptor as _descriptor
|
|
8
8
|
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
@@ -12,8 +12,8 @@ from google.protobuf.internal import builder as _builder
|
|
|
12
12
|
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
13
|
_runtime_version.Domain.PUBLIC,
|
|
14
14
|
5,
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
29,
|
|
16
|
+
0,
|
|
17
17
|
'',
|
|
18
18
|
'crossplane/function/proto/v1/run_function.proto'
|
|
19
19
|
)
|
|
@@ -5,7 +5,7 @@ import warnings
|
|
|
5
5
|
|
|
6
6
|
from crossplane.function.proto.v1 import run_function_pb2 as crossplane_dot_function_dot_proto_dot_v1_dot_run__function__pb2
|
|
7
7
|
|
|
8
|
-
GRPC_GENERATED_VERSION = '1.
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.71.0'
|
|
9
9
|
GRPC_VERSION = grpc.__version__
|
|
10
10
|
_version_not_supported = False
|
|
11
11
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
3
|
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
4
|
# source: crossplane/function/proto/v1beta1/run_function.proto
|
|
5
|
-
# Protobuf Python Version: 5.
|
|
5
|
+
# Protobuf Python Version: 5.29.0
|
|
6
6
|
"""Generated protocol buffer code."""
|
|
7
7
|
from google.protobuf import descriptor as _descriptor
|
|
8
8
|
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
@@ -12,8 +12,8 @@ from google.protobuf.internal import builder as _builder
|
|
|
12
12
|
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
13
|
_runtime_version.Domain.PUBLIC,
|
|
14
14
|
5,
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
29,
|
|
16
|
+
0,
|
|
17
17
|
'',
|
|
18
18
|
'crossplane/function/proto/v1beta1/run_function.proto'
|
|
19
19
|
)
|
|
@@ -5,7 +5,7 @@ import warnings
|
|
|
5
5
|
|
|
6
6
|
from crossplane.function.proto.v1beta1 import run_function_pb2 as crossplane_dot_function_dot_proto_dot_v1beta1_dot_run__function__pb2
|
|
7
7
|
|
|
8
|
-
GRPC_GENERATED_VERSION = '1.
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.71.0'
|
|
9
9
|
GRPC_VERSION = grpc.__version__
|
|
10
10
|
_version_not_supported = False
|
|
11
11
|
|
|
File without changes
|
|
@@ -18,6 +18,7 @@ import dataclasses
|
|
|
18
18
|
import datetime
|
|
19
19
|
|
|
20
20
|
import pydantic
|
|
21
|
+
from google.protobuf import json_format
|
|
21
22
|
from google.protobuf import struct_pb2 as structpb
|
|
22
23
|
|
|
23
24
|
import crossplane.function.proto.v1.run_function_pb2 as fnv1
|
|
@@ -38,7 +39,15 @@ def update(r: fnv1.Resource, source: dict | structpb.Struct | pydantic.BaseModel
|
|
|
38
39
|
"""
|
|
39
40
|
match source:
|
|
40
41
|
case pydantic.BaseModel():
|
|
41
|
-
|
|
42
|
+
data = source.model_dump(exclude_defaults=True, warnings=False)
|
|
43
|
+
# In Pydantic, exclude_defaults=True in model_dump excludes fields
|
|
44
|
+
# that have their value equal to the default. If a field like
|
|
45
|
+
# apiVersion is set to its default value 's3.aws.upbound.io/v1beta2'
|
|
46
|
+
# (and not explicitly provided during initialization), it will be
|
|
47
|
+
# excluded from the serialized output.
|
|
48
|
+
data["apiVersion"] = source.apiVersion
|
|
49
|
+
data["kind"] = source.kind
|
|
50
|
+
r.resource.update(data)
|
|
42
51
|
case structpb.Struct():
|
|
43
52
|
# TODO(negz): Use struct_to_dict and update to match other semantics?
|
|
44
53
|
r.resource.MergeFrom(source)
|
|
@@ -57,9 +66,7 @@ def dict_to_struct(d: dict) -> structpb.Struct:
|
|
|
57
66
|
function makes it possible to work with a Python dict, then convert it to a
|
|
58
67
|
struct in a RunFunctionResponse.
|
|
59
68
|
"""
|
|
60
|
-
|
|
61
|
-
s.update(d)
|
|
62
|
-
return s
|
|
69
|
+
return json_format.ParseDict(d, structpb.Struct())
|
|
63
70
|
|
|
64
71
|
|
|
65
72
|
def struct_to_dict(s: structpb.Struct) -> dict:
|
|
@@ -69,10 +76,7 @@ def struct_to_dict(s: structpb.Struct) -> dict:
|
|
|
69
76
|
protobuf struct. This function makes it possible to convert resources to a
|
|
70
77
|
dictionary.
|
|
71
78
|
"""
|
|
72
|
-
return
|
|
73
|
-
k: (struct_to_dict(v) if isinstance(v, structpb.Struct) else v)
|
|
74
|
-
for k, v in s.items()
|
|
75
|
-
}
|
|
79
|
+
return json_format.MessageToDict(s, preserving_proto_field_name=True)
|
|
76
80
|
|
|
77
81
|
|
|
78
82
|
@dataclasses.dataclass
|
|
@@ -110,10 +114,10 @@ def get_condition(resource: structpb.Struct, typ: str) -> Condition:
|
|
|
110
114
|
"""
|
|
111
115
|
unknown = Condition(typ=typ, status="Unknown")
|
|
112
116
|
|
|
113
|
-
if "status" not in resource:
|
|
117
|
+
if not resource or "status" not in resource:
|
|
114
118
|
return unknown
|
|
115
119
|
|
|
116
|
-
if "conditions" not in resource["status"]:
|
|
120
|
+
if not resource["status"] or "conditions" not in resource["status"]:
|
|
117
121
|
return unknown
|
|
118
122
|
|
|
119
123
|
for c in resource["status"]["conditions"]:
|
|
@@ -149,9 +153,9 @@ class Credentials:
|
|
|
149
153
|
def get_credentials(req: structpb.Struct, name: str) -> Credentials:
|
|
150
154
|
"""Get the supplied credentials."""
|
|
151
155
|
empty = Credentials(type="data", data={})
|
|
152
|
-
if "credentials" not in req:
|
|
156
|
+
if not req or "credentials" not in req:
|
|
153
157
|
return empty
|
|
154
|
-
if name not in req["credentials"]:
|
|
158
|
+
if not req["credentials"] or name not in req["credentials"]:
|
|
155
159
|
return empty
|
|
156
160
|
return Credentials(
|
|
157
161
|
type=req["credentials"][name]["type"],
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import asyncio
|
|
18
18
|
import os
|
|
19
|
+
import signal
|
|
19
20
|
|
|
20
21
|
import grpc
|
|
21
22
|
from grpc_reflection.v1alpha import reflection
|
|
@@ -31,6 +32,8 @@ SERVICE_NAMES = (
|
|
|
31
32
|
fnv1beta1.DESCRIPTOR.services_by_name["FunctionRunnerService"].full_name,
|
|
32
33
|
)
|
|
33
34
|
|
|
35
|
+
SHUTDOWN_GRACE_PERIOD_SECONDS = 5
|
|
36
|
+
|
|
34
37
|
|
|
35
38
|
def load_credentials(tls_certs_dir: str) -> grpc.ServerCredentials:
|
|
36
39
|
"""Load TLS credentials for a composition function gRPC server.
|
|
@@ -90,6 +93,11 @@ def serve(
|
|
|
90
93
|
|
|
91
94
|
server = grpc.aio.server()
|
|
92
95
|
|
|
96
|
+
loop.add_signal_handler(
|
|
97
|
+
signal.SIGTERM,
|
|
98
|
+
lambda: asyncio.ensure_future(server.stop(grace=SHUTDOWN_GRACE_PERIOD_SECONDS)),
|
|
99
|
+
)
|
|
100
|
+
|
|
93
101
|
grpcv1.add_FunctionRunnerServiceServicer_to_server(function, server)
|
|
94
102
|
grpcv1beta1.add_FunctionRunnerServiceServicer_to_server(
|
|
95
103
|
BetaFunctionRunner(wrapped=function), server
|
|
@@ -116,7 +124,7 @@ def serve(
|
|
|
116
124
|
try:
|
|
117
125
|
loop.run_until_complete(start())
|
|
118
126
|
finally:
|
|
119
|
-
loop.run_until_complete(server.stop(grace=
|
|
127
|
+
loop.run_until_complete(server.stop(grace=SHUTDOWN_GRACE_PERIOD_SECONDS))
|
|
120
128
|
loop.close()
|
|
121
129
|
|
|
122
130
|
|
{crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/pyproject.toml
RENAMED
|
@@ -14,14 +14,15 @@ classifiers = [
|
|
|
14
14
|
"Development Status :: 4 - Beta",
|
|
15
15
|
"Programming Language :: Python",
|
|
16
16
|
"Programming Language :: Python :: 3.11",
|
|
17
|
+
"Typing :: Typed",
|
|
17
18
|
]
|
|
18
19
|
|
|
19
20
|
dependencies = [
|
|
20
|
-
"grpcio==1
|
|
21
|
+
"grpcio==1.71.0",
|
|
21
22
|
"grpcio-reflection==1.*",
|
|
22
|
-
"protobuf==5.
|
|
23
|
+
"protobuf==5.29.3", # Must be compatible with grpcio-tools.
|
|
23
24
|
"pydantic==2.*",
|
|
24
|
-
"structlog==
|
|
25
|
+
"structlog==25.*",
|
|
25
26
|
]
|
|
26
27
|
|
|
27
28
|
dynamic = ["version"]
|
|
@@ -38,13 +39,16 @@ validate-bump = false # Allow going from 0.0.0.dev0+x to 0
|
|
|
38
39
|
[tool.hatch.envs.default]
|
|
39
40
|
type = "virtual"
|
|
40
41
|
path = ".venv-default"
|
|
41
|
-
dependencies = ["ipython==
|
|
42
|
+
dependencies = ["ipython==9.1.0"]
|
|
42
43
|
|
|
43
44
|
[tool.hatch.envs.generate]
|
|
44
45
|
type = "virtual"
|
|
45
46
|
detached = true
|
|
46
47
|
path = ".venv-generate"
|
|
47
|
-
dependencies = [
|
|
48
|
+
dependencies = [
|
|
49
|
+
"grpcio-tools==1.71.0",
|
|
50
|
+
"protobuf==5.29.3",
|
|
51
|
+
]
|
|
48
52
|
|
|
49
53
|
[tool.hatch.envs.generate.scripts]
|
|
50
54
|
protoc = "python -m grpc_tools.protoc --proto_path=. --python_out=. --pyi_out=. --grpc_python_out=. crossplane/function/proto/v1beta1/run_function.proto crossplane/function/proto/v1/run_function.proto"
|
|
@@ -62,8 +66,8 @@ packages = ["crossplane"]
|
|
|
62
66
|
|
|
63
67
|
# This special environment is used by hatch fmt.
|
|
64
68
|
[tool.hatch.envs.hatch-static-analysis]
|
|
65
|
-
dependencies = ["ruff==0.6
|
|
66
|
-
config-path = "none"
|
|
69
|
+
dependencies = ["ruff==0.11.6"]
|
|
70
|
+
config-path = "none" # Disable Hatch's default Ruff config.
|
|
67
71
|
|
|
68
72
|
[tool.ruff]
|
|
69
73
|
target-version = "py311"
|
{crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/tests/test_resource.py
RENAMED
|
@@ -90,7 +90,11 @@ class TestResource(unittest.TestCase):
|
|
|
90
90
|
),
|
|
91
91
|
want=fnv1.Resource(
|
|
92
92
|
resource=resource.dict_to_struct(
|
|
93
|
-
{
|
|
93
|
+
{
|
|
94
|
+
"apiVersion": "s3.aws.upbound.io/v1beta2",
|
|
95
|
+
"kind": "Bucket",
|
|
96
|
+
"spec": {"forProvider": {"region": "us-west-2"}},
|
|
97
|
+
}
|
|
94
98
|
),
|
|
95
99
|
),
|
|
96
100
|
),
|
|
@@ -244,6 +248,66 @@ class TestResource(unittest.TestCase):
|
|
|
244
248
|
dataclasses.asdict(case.want), dataclasses.asdict(got), "-want, +got"
|
|
245
249
|
)
|
|
246
250
|
|
|
251
|
+
def test_dict_to_struct(self) -> None:
|
|
252
|
+
@dataclasses.dataclass
|
|
253
|
+
class TestCase:
|
|
254
|
+
reason: str
|
|
255
|
+
d: dict
|
|
256
|
+
want: structpb.Struct
|
|
257
|
+
|
|
258
|
+
cases = [
|
|
259
|
+
TestCase(
|
|
260
|
+
reason="Convert an empty dictionary to a struct.",
|
|
261
|
+
d={},
|
|
262
|
+
want=structpb.Struct(),
|
|
263
|
+
),
|
|
264
|
+
TestCase(
|
|
265
|
+
reason="Convert a dictionary with a single field to a struct.",
|
|
266
|
+
d={"foo": "bar"},
|
|
267
|
+
want=structpb.Struct(
|
|
268
|
+
fields={"foo": structpb.Value(string_value="bar")}
|
|
269
|
+
),
|
|
270
|
+
),
|
|
271
|
+
TestCase(
|
|
272
|
+
reason="Convert a nested dictionary to a struct.",
|
|
273
|
+
d={"foo": {"bar": "baz"}},
|
|
274
|
+
want=structpb.Struct(
|
|
275
|
+
fields={
|
|
276
|
+
"foo": structpb.Value(
|
|
277
|
+
struct_value=structpb.Struct(
|
|
278
|
+
fields={"bar": structpb.Value(string_value="baz")}
|
|
279
|
+
)
|
|
280
|
+
)
|
|
281
|
+
}
|
|
282
|
+
),
|
|
283
|
+
),
|
|
284
|
+
TestCase(
|
|
285
|
+
reason="Convert a nested dictionary containing lists to a struct.",
|
|
286
|
+
d={"foo": {"bar": ["baz", "qux"]}},
|
|
287
|
+
want=structpb.Struct(
|
|
288
|
+
fields={
|
|
289
|
+
"foo": structpb.Value(
|
|
290
|
+
struct_value=structpb.Struct(
|
|
291
|
+
fields={
|
|
292
|
+
"bar": structpb.Value(
|
|
293
|
+
list_value=structpb.ListValue(
|
|
294
|
+
values=[
|
|
295
|
+
structpb.Value(string_value="baz"),
|
|
296
|
+
structpb.Value(string_value="qux"),
|
|
297
|
+
]
|
|
298
|
+
)
|
|
299
|
+
)
|
|
300
|
+
}
|
|
301
|
+
)
|
|
302
|
+
)
|
|
303
|
+
}
|
|
304
|
+
),
|
|
305
|
+
),
|
|
306
|
+
]
|
|
307
|
+
for case in cases:
|
|
308
|
+
got = resource.dict_to_struct(case.d)
|
|
309
|
+
self.assertEqual(case.want, got, "-want, +got")
|
|
310
|
+
|
|
247
311
|
def test_struct_to_dict(self) -> None:
|
|
248
312
|
@dataclasses.dataclass
|
|
249
313
|
class TestCase:
|
|
@@ -275,6 +339,28 @@ class TestResource(unittest.TestCase):
|
|
|
275
339
|
),
|
|
276
340
|
want={"foo": {"bar": "baz"}},
|
|
277
341
|
),
|
|
342
|
+
TestCase(
|
|
343
|
+
reason="Convert a nested struct containing ListValues to a dictionary.",
|
|
344
|
+
s=structpb.Struct(
|
|
345
|
+
fields={
|
|
346
|
+
"foo": structpb.Value(
|
|
347
|
+
struct_value=structpb.Struct(
|
|
348
|
+
fields={
|
|
349
|
+
"bar": structpb.Value(
|
|
350
|
+
list_value=structpb.ListValue(
|
|
351
|
+
values=[
|
|
352
|
+
structpb.Value(string_value="baz"),
|
|
353
|
+
structpb.Value(string_value="qux"),
|
|
354
|
+
]
|
|
355
|
+
)
|
|
356
|
+
)
|
|
357
|
+
}
|
|
358
|
+
)
|
|
359
|
+
)
|
|
360
|
+
}
|
|
361
|
+
),
|
|
362
|
+
want={"foo": {"bar": ["baz", "qux"]}},
|
|
363
|
+
),
|
|
278
364
|
]
|
|
279
365
|
|
|
280
366
|
for case in cases:
|
|
@@ -759,11 +759,11 @@ class Status(BaseModel):
|
|
|
759
759
|
|
|
760
760
|
|
|
761
761
|
class Bucket(BaseModel):
|
|
762
|
-
apiVersion: Optional[str] =
|
|
762
|
+
apiVersion: Optional[str] = 's3.aws.upbound.io/v1beta2'
|
|
763
763
|
"""
|
|
764
764
|
APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
|
765
765
|
"""
|
|
766
|
-
kind: Optional[str] =
|
|
766
|
+
kind: Optional[str] = 'Bucket'
|
|
767
767
|
"""
|
|
768
768
|
Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
|
769
769
|
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/tests/test_response.py
RENAMED
|
File without changes
|
{crossplane_function_sdk_python-0.5.0 → crossplane_function_sdk_python-0.7.0}/tests/test_runtime.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|