crossplane-function-pythonic 0.6.1__py3-none-any.whl → 0.6.3__py3-none-any.whl
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/pythonic/__about__.py +8 -2
- crossplane/pythonic/__init__.py +21 -13
- crossplane/pythonic/__main__.py +1 -0
- crossplane/pythonic/auto_ready.py +89 -41
- crossplane/pythonic/command.py +43 -39
- crossplane/pythonic/composite.py +93 -67
- crossplane/pythonic/diff.py +880 -0
- crossplane/pythonic/function.py +194 -99
- crossplane/pythonic/grpc.py +85 -62
- crossplane/pythonic/main.py +13 -4
- crossplane/pythonic/packages.py +77 -50
- crossplane/pythonic/proto/v1/run_function_pb2.py +3 -3
- crossplane/pythonic/proto/v1/run_function_pb2_grpc.py +4 -4
- crossplane/pythonic/protobuf.py +281 -214
- crossplane/pythonic/render.py +413 -201
- crossplane/pythonic/version.py +2 -3
- {crossplane_function_pythonic-0.6.1.dist-info → crossplane_function_pythonic-0.6.3.dist-info}/METADATA +23 -25
- crossplane_function_pythonic-0.6.3.dist-info/RECORD +22 -0
- {crossplane_function_pythonic-0.6.1.dist-info → crossplane_function_pythonic-0.6.3.dist-info}/WHEEL +1 -1
- {crossplane_function_pythonic-0.6.1.dist-info → crossplane_function_pythonic-0.6.3.dist-info}/entry_points.txt +1 -0
- crossplane_function_pythonic-0.6.1.dist-info/RECORD +0 -22
- crossplane_function_pythonic-0.6.1.dist-info/licenses/LICENSE +0 -201
crossplane/pythonic/grpc.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
import asyncio
|
|
3
2
|
import logging
|
|
4
3
|
import os
|
|
@@ -16,88 +15,98 @@ from . import (
|
|
|
16
15
|
)
|
|
17
16
|
from .proto.v1 import run_function_pb2_grpc as grpcv1
|
|
18
17
|
|
|
19
|
-
|
|
20
18
|
logger = logging.getLogger(__name__)
|
|
21
19
|
|
|
22
20
|
|
|
23
21
|
class Command(command.Command):
|
|
24
|
-
name =
|
|
25
|
-
help =
|
|
22
|
+
name = "grpc"
|
|
23
|
+
help = "Run function-pythonic gRPC server"
|
|
26
24
|
|
|
27
25
|
@classmethod
|
|
28
26
|
def add_parser_arguments(cls, parser):
|
|
29
27
|
cls.add_function_arguments(parser)
|
|
30
28
|
parser.add_argument(
|
|
31
|
-
|
|
32
|
-
default=
|
|
33
|
-
help=
|
|
29
|
+
"--address",
|
|
30
|
+
default="0.0.0.0:9443",
|
|
31
|
+
help="Address to listen on for gRPC connections, default: 0.0.0.0:9443",
|
|
34
32
|
)
|
|
35
33
|
parser.add_argument(
|
|
36
|
-
|
|
37
|
-
default=os.getenv(
|
|
38
|
-
metavar=
|
|
39
|
-
help=
|
|
34
|
+
"--tls-certs-dir",
|
|
35
|
+
default=os.getenv("TLS_SERVER_CERTS_DIR"),
|
|
36
|
+
metavar="DIRECTORY",
|
|
37
|
+
help="Serve using TLS certificates.",
|
|
40
38
|
)
|
|
41
39
|
parser.add_argument(
|
|
42
|
-
|
|
43
|
-
action=
|
|
44
|
-
help=
|
|
40
|
+
"--insecure",
|
|
41
|
+
action="store_true",
|
|
42
|
+
help="Run without mTLS credentials, --tls-certs-dir will be ignored.",
|
|
45
43
|
)
|
|
46
44
|
parser.add_argument(
|
|
47
|
-
|
|
48
|
-
action=
|
|
49
|
-
dest=
|
|
50
|
-
help=
|
|
45
|
+
"--packages",
|
|
46
|
+
action="store_true",
|
|
47
|
+
dest="packages_configmaps",
|
|
48
|
+
help="Discover python packages from function-pythonic ConfigMaps, deprecated use --packages-configmaps",
|
|
51
49
|
)
|
|
52
50
|
parser.add_argument(
|
|
53
|
-
|
|
54
|
-
action=
|
|
55
|
-
help=
|
|
51
|
+
"--packages-configmaps",
|
|
52
|
+
action="store_true",
|
|
53
|
+
help="Discover python packages from function-pythonic ConfigMaps.",
|
|
56
54
|
)
|
|
57
55
|
parser.add_argument(
|
|
58
|
-
|
|
59
|
-
action=
|
|
60
|
-
help=
|
|
56
|
+
"--packages-secrets",
|
|
57
|
+
action="store_true",
|
|
58
|
+
help="Also Discover python packages from function-pythonic Secrets.",
|
|
61
59
|
)
|
|
62
60
|
parser.add_argument(
|
|
63
|
-
|
|
64
|
-
action=
|
|
61
|
+
"--packages-namespace",
|
|
62
|
+
action="append",
|
|
65
63
|
default=[],
|
|
66
|
-
metavar=
|
|
67
|
-
help=
|
|
64
|
+
metavar="NAMESPACE",
|
|
65
|
+
help="Namespaces to discover function-pythonic ConfigMaps and Secrets in, default is cluster wide.",
|
|
68
66
|
)
|
|
69
67
|
parser.add_argument(
|
|
70
|
-
|
|
71
|
-
action=
|
|
72
|
-
help=
|
|
68
|
+
"--packages-environmentconfigs",
|
|
69
|
+
action="store_true",
|
|
70
|
+
help="Also Discover python packages from function-pythonic EnvironmentConfigs.",
|
|
73
71
|
)
|
|
74
72
|
parser.add_argument(
|
|
75
|
-
|
|
76
|
-
action=
|
|
77
|
-
help=
|
|
73
|
+
"--packages-compositions",
|
|
74
|
+
action="store_true",
|
|
75
|
+
help="Also Discover python packages from function-pythonic Compositions.",
|
|
78
76
|
)
|
|
79
77
|
parser.add_argument(
|
|
80
|
-
|
|
81
|
-
default=
|
|
82
|
-
metavar=
|
|
83
|
-
help='Directory to store discovered function-pythonic ConfigMaps to, defaults "<cwd>/pythonic-packages"'
|
|
78
|
+
"--packages-dir",
|
|
79
|
+
default="./pythonic-packages",
|
|
80
|
+
metavar="DIRECTORY",
|
|
81
|
+
help='Directory to store discovered function-pythonic ConfigMaps to, defaults "<cwd>/pythonic-packages"',
|
|
84
82
|
)
|
|
85
83
|
parser.add_argument(
|
|
86
|
-
|
|
87
|
-
metavar=
|
|
88
|
-
help=
|
|
84
|
+
"--pip-install",
|
|
85
|
+
metavar="INSTALL",
|
|
86
|
+
help="Pip install command to install additional Python packages.",
|
|
89
87
|
)
|
|
90
88
|
|
|
91
89
|
def initialize(self):
|
|
92
90
|
if not self.args.tls_certs_dir and not self.args.insecure:
|
|
93
|
-
print(
|
|
91
|
+
print(
|
|
92
|
+
"Either --tls-certs-dir or --insecure must be specified",
|
|
93
|
+
file=sys.stderr,
|
|
94
|
+
)
|
|
94
95
|
sys.exit(1)
|
|
95
|
-
if (
|
|
96
|
-
|
|
96
|
+
if (
|
|
97
|
+
self.args.packages_environmentconfigs or self.args.packages_compositions
|
|
98
|
+
) and self.args.packages_namespace:
|
|
99
|
+
print(
|
|
100
|
+
"--packages-namespace cannot be used with --packages-environment-configs or --packages-compositions",
|
|
101
|
+
file=sys.stderr,
|
|
102
|
+
)
|
|
97
103
|
sys.exit(1)
|
|
98
104
|
if self.args.pip_install:
|
|
99
105
|
import pip._internal.cli.main
|
|
100
|
-
|
|
106
|
+
|
|
107
|
+
pip._internal.cli.main.main(
|
|
108
|
+
["install", "--user", *shlex.split(self.args.pip_install)]
|
|
109
|
+
)
|
|
101
110
|
|
|
102
111
|
self.initialize_function()
|
|
103
112
|
logger.info(f"Version: {__about__.__version__}")
|
|
@@ -107,7 +116,9 @@ class Command(command.Command):
|
|
|
107
116
|
|
|
108
117
|
async def run(self):
|
|
109
118
|
grpc.aio.init_grpc_aio()
|
|
110
|
-
grpc_runner = function.FunctionRunner(
|
|
119
|
+
grpc_runner = function.FunctionRunner(
|
|
120
|
+
self.args.render_unknowns, self.args.crossplane_v1
|
|
121
|
+
)
|
|
111
122
|
grpc_server = grpc.aio.server()
|
|
112
123
|
grpcv1.add_FunctionRunnerServiceServicer_to_server(grpc_runner, grpc_server)
|
|
113
124
|
if self.args.insecure:
|
|
@@ -117,33 +128,45 @@ class Command(command.Command):
|
|
|
117
128
|
grpc_server.add_secure_port(
|
|
118
129
|
self.args.address,
|
|
119
130
|
grpc.ssl_server_credentials(
|
|
120
|
-
private_key_certificate_chain_pairs=[
|
|
121
|
-
(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
131
|
+
private_key_certificate_chain_pairs=[
|
|
132
|
+
(
|
|
133
|
+
(certs / "tls.key").read_bytes(),
|
|
134
|
+
(certs / "tls.crt").read_bytes(),
|
|
135
|
+
)
|
|
136
|
+
],
|
|
137
|
+
root_certificates=(certs / "ca.crt").read_bytes(),
|
|
125
138
|
require_client_auth=True,
|
|
126
139
|
),
|
|
127
140
|
)
|
|
128
141
|
await grpc_server.start()
|
|
129
142
|
|
|
130
|
-
if
|
|
143
|
+
if (
|
|
144
|
+
self.args.packages_configmaps
|
|
145
|
+
or self.args.packages_secrets
|
|
146
|
+
or self.args.packages_environmentconfigs
|
|
147
|
+
or self.args.packages_compositions
|
|
148
|
+
):
|
|
131
149
|
from . import packages
|
|
150
|
+
|
|
132
151
|
async with asyncio.TaskGroup() as tasks:
|
|
133
152
|
tasks.create_task(grpc_server.wait_for_termination())
|
|
134
|
-
tasks.create_task(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
153
|
+
tasks.create_task(
|
|
154
|
+
packages.operator(
|
|
155
|
+
grpc_server,
|
|
156
|
+
grpc_runner,
|
|
157
|
+
self.args.packages_configmaps,
|
|
158
|
+
self.args.packages_secrets,
|
|
159
|
+
self.args.packages_namespace,
|
|
160
|
+
self.args.packages_environmentconfigs,
|
|
161
|
+
self.args.packages_compositions,
|
|
162
|
+
self.args.packages_dir,
|
|
163
|
+
)
|
|
164
|
+
)
|
|
144
165
|
else:
|
|
166
|
+
|
|
145
167
|
def stop():
|
|
146
168
|
asyncio.ensure_future(grpc_server.stop(5))
|
|
169
|
+
|
|
147
170
|
loop = asyncio.get_event_loop()
|
|
148
171
|
loop.add_signal_handler(signal.SIGINT, stop)
|
|
149
172
|
loop.add_signal_handler(signal.SIGTERM, stop)
|
crossplane/pythonic/main.py
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
import argparse
|
|
4
4
|
import asyncio
|
|
5
5
|
import sys
|
|
6
|
+
import warnings
|
|
7
|
+
|
|
8
|
+
# kr8s emits this at import time, so filter before importing it.
|
|
9
|
+
warnings.filterwarnings(
|
|
10
|
+
"ignore",
|
|
11
|
+
message="'asyncio.iscoroutinefunction' is deprecated",
|
|
12
|
+
category=DeprecationWarning,
|
|
13
|
+
module="kr8s._vendored.asyncache",
|
|
14
|
+
)
|
|
6
15
|
|
|
7
16
|
from . import (
|
|
8
17
|
grpc,
|
|
@@ -12,17 +21,17 @@ from . import (
|
|
|
12
21
|
|
|
13
22
|
|
|
14
23
|
def main():
|
|
15
|
-
parser = argparse.ArgumentParser(
|
|
16
|
-
subparsers = parser.add_subparsers(title=
|
|
24
|
+
parser = argparse.ArgumentParser("Crossplane Function Pythonic")
|
|
25
|
+
subparsers = parser.add_subparsers(title="Command", metavar="")
|
|
17
26
|
grpc.Command.create(subparsers)
|
|
18
27
|
render.Command.create(subparsers)
|
|
19
28
|
version.Command.create(subparsers)
|
|
20
29
|
args = parser.parse_args()
|
|
21
|
-
if not hasattr(args,
|
|
30
|
+
if not hasattr(args, "command"):
|
|
22
31
|
parser.print_help()
|
|
23
32
|
sys.exit(1)
|
|
24
33
|
asyncio.run(args.command(args).run())
|
|
25
34
|
|
|
26
35
|
|
|
27
|
-
if __name__ ==
|
|
36
|
+
if __name__ == "__main__":
|
|
28
37
|
main()
|
crossplane/pythonic/packages.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
import base64
|
|
3
2
|
import logging
|
|
4
3
|
import pathlib
|
|
@@ -6,36 +5,45 @@ import sys
|
|
|
6
5
|
|
|
7
6
|
import kopf
|
|
8
7
|
|
|
9
|
-
|
|
10
8
|
GRPC_SERVER = None
|
|
11
9
|
GRPC_RUNNER = None
|
|
12
10
|
PACKAGES_DIR = None
|
|
13
|
-
PACKAGE_LABEL =
|
|
11
|
+
PACKAGE_LABEL = "function-pythonic.package"
|
|
14
12
|
PACKAGE_LABELS = {PACKAGE_LABEL: kopf.PRESENT}
|
|
15
13
|
|
|
16
14
|
|
|
17
|
-
def operator(
|
|
18
|
-
|
|
15
|
+
def operator(
|
|
16
|
+
grpc_server,
|
|
17
|
+
grpc_runner,
|
|
18
|
+
packages_configmaps,
|
|
19
|
+
packages_secrets,
|
|
20
|
+
packages_namespaces,
|
|
21
|
+
packages_environmentconfigs,
|
|
22
|
+
packages_compositions,
|
|
23
|
+
packages_dir,
|
|
24
|
+
):
|
|
25
|
+
logging.getLogger("kopf.objects").setLevel(logging.INFO)
|
|
19
26
|
global GRPC_SERVER, GRPC_RUNNER, PACKAGES_DIR
|
|
20
27
|
GRPC_SERVER = grpc_server
|
|
21
28
|
GRPC_RUNNER = grpc_runner
|
|
22
29
|
PACKAGES_DIR = pathlib.Path(packages_dir).expanduser().resolve()
|
|
23
30
|
sys.path.insert(0, str(PACKAGES_DIR))
|
|
24
31
|
if packages_configmaps:
|
|
25
|
-
on_resource(
|
|
32
|
+
on_resource("", "v1", "configmaps")
|
|
26
33
|
if packages_secrets:
|
|
27
|
-
on_resource(
|
|
34
|
+
on_resource("", "v1", "secrets")
|
|
28
35
|
if not packages_namespaces:
|
|
29
36
|
if packages_environmentconfigs:
|
|
30
|
-
on_resource(
|
|
37
|
+
on_resource("apiextensions.crossplane.io", "v1beta1", "environmentconfigs")
|
|
31
38
|
if packages_compositions:
|
|
32
|
-
on_resource(
|
|
39
|
+
on_resource("apiextensions.crossplane.io", "v1", "compositions")
|
|
33
40
|
return kopf.operator(
|
|
34
41
|
standalone=True,
|
|
35
42
|
clusterwide=not packages_namespaces,
|
|
36
43
|
namespaces=packages_namespaces,
|
|
37
44
|
)
|
|
38
45
|
|
|
46
|
+
|
|
39
47
|
def on_resource(group, version, plural):
|
|
40
48
|
kopf.on.create(group, version, plural, labels=PACKAGE_LABELS)(create)
|
|
41
49
|
kopf.on.resume(group, version, plural, labels=PACKAGE_LABELS)(create)
|
|
@@ -54,42 +62,55 @@ async def cleanup(**_):
|
|
|
54
62
|
|
|
55
63
|
|
|
56
64
|
async def create(resource, labels, body, logger, **_):
|
|
57
|
-
resource_create(resource, labels,
|
|
65
|
+
resource_create(resource, labels, "Created", body, logger)
|
|
58
66
|
|
|
59
67
|
|
|
60
68
|
async def update(resource, labels, body, old, logger, **_):
|
|
61
|
-
resource_delete(resource, labels,
|
|
62
|
-
resource_create(resource, labels,
|
|
69
|
+
resource_delete(resource, labels, "Removed", old, logger)
|
|
70
|
+
resource_create(resource, labels, "Added", body, logger)
|
|
63
71
|
|
|
64
72
|
|
|
65
73
|
async def delete(resource, labels, body, logger, **_):
|
|
66
|
-
resource_delete(resource, labels,
|
|
74
|
+
resource_delete(resource, labels, "Deleted", body, logger)
|
|
67
75
|
|
|
68
76
|
|
|
69
77
|
def resource_create(resource, labels, action, body, logger):
|
|
70
78
|
package_dir = resource_package_dir(resource, labels, logger)
|
|
71
79
|
if not package_dir:
|
|
72
80
|
return
|
|
73
|
-
if resource.plural in (
|
|
74
|
-
package_create(resource, action, package_dir, body.get(
|
|
75
|
-
elif resource.plural ==
|
|
76
|
-
for step in body.get(
|
|
77
|
-
input = step.get(
|
|
78
|
-
if
|
|
79
|
-
|
|
81
|
+
if resource.plural in ("configmaps", "secrets", "environmentconfigs"):
|
|
82
|
+
package_create(resource, action, package_dir, body.get("data", {}), logger)
|
|
83
|
+
elif resource.plural == "compositions":
|
|
84
|
+
for step in body.get("spec", {}).get("pipeline", []):
|
|
85
|
+
input = step.get("input")
|
|
86
|
+
if (
|
|
87
|
+
input
|
|
88
|
+
and input.get("apiVersion") == "pythonic.fn.crossplane.io/v1alpha1"
|
|
89
|
+
):
|
|
90
|
+
package_create(
|
|
91
|
+
resource, action, package_dir, input.get("packages", {}), logger
|
|
92
|
+
)
|
|
80
93
|
|
|
81
94
|
|
|
82
95
|
def resource_delete(resource, labels, action, body, logger):
|
|
83
96
|
package_dir = resource_package_dir(resource, labels, logger)
|
|
84
97
|
if not package_dir:
|
|
85
98
|
return
|
|
86
|
-
if resource.plural in (
|
|
87
|
-
package_delete(action, package_dir, body.get(
|
|
88
|
-
elif resource.plural ==
|
|
89
|
-
for step in body.get(
|
|
90
|
-
input = step.get(
|
|
91
|
-
if
|
|
92
|
-
|
|
99
|
+
if resource.plural in ("configmaps", "secrets", "environmentconfigs"):
|
|
100
|
+
package_delete(action, package_dir, body.get("data", {}), logger)
|
|
101
|
+
elif resource.plural == "compositions":
|
|
102
|
+
for step in body.get("spec", {}).get("pipeline", []):
|
|
103
|
+
input = step.get("input")
|
|
104
|
+
if (
|
|
105
|
+
input
|
|
106
|
+
and input.get("apiVersion") == "pythonic.fn.crossplane.io/v1alpha1"
|
|
107
|
+
):
|
|
108
|
+
package_delete(
|
|
109
|
+
action,
|
|
110
|
+
package_dir,
|
|
111
|
+
step.get("input", {}).get("packages", {}),
|
|
112
|
+
logger,
|
|
113
|
+
)
|
|
93
114
|
|
|
94
115
|
|
|
95
116
|
def resource_package_dir(resource, labels, logger):
|
|
@@ -99,10 +120,10 @@ def resource_package_dir(resource, labels, logger):
|
|
|
99
120
|
logger.error(f"{PACKAGE_LABEL} label is missing")
|
|
100
121
|
return None
|
|
101
122
|
package_dir = PACKAGES_DIR
|
|
102
|
-
if resource.plural in (
|
|
103
|
-
for segment in package.split(
|
|
123
|
+
if resource.plural in ("configmaps", "secrets") and package:
|
|
124
|
+
for segment in package.split("."):
|
|
104
125
|
if not segment.isidentifier():
|
|
105
|
-
logger.error(
|
|
126
|
+
logger.error("Package has invalid package name: %s", package)
|
|
106
127
|
return None
|
|
107
128
|
package_dir = package_dir / segment
|
|
108
129
|
return package_dir
|
|
@@ -114,8 +135,8 @@ def package_create(resource, action, package_dir, package, logger):
|
|
|
114
135
|
package_name = package_dir / name
|
|
115
136
|
if isinstance(value, str):
|
|
116
137
|
package_name.parent.mkdir(parents=True, exist_ok=True)
|
|
117
|
-
if resource.plural ==
|
|
118
|
-
package_name.write_bytes(base64.b64decode(value.encode(
|
|
138
|
+
if resource.plural == "secrets":
|
|
139
|
+
package_name.write_bytes(base64.b64decode(value.encode("utf-8")))
|
|
119
140
|
else:
|
|
120
141
|
package_name.write_text(value)
|
|
121
142
|
module, name = package_file_name(package_name)
|
|
@@ -142,13 +163,13 @@ def package_delete(action, package_dir, package, logger):
|
|
|
142
163
|
logger.info(f"{action} file: {name}")
|
|
143
164
|
parent = package_name.parent
|
|
144
165
|
while (
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
166
|
+
parent.is_relative_to(PACKAGES_DIR)
|
|
167
|
+
and parent.is_dir()
|
|
168
|
+
and not list(parent.iterdir())
|
|
148
169
|
):
|
|
149
170
|
parent.rmdir()
|
|
150
|
-
module = str(parent.relative_to(PACKAGES_DIR)).replace(
|
|
151
|
-
if module !=
|
|
171
|
+
module = str(parent.relative_to(PACKAGES_DIR)).replace("/", ".")
|
|
172
|
+
if module != ".":
|
|
152
173
|
GRPC_RUNNER.invalidate_module(module)
|
|
153
174
|
logger.info(f"{action} package: {module}")
|
|
154
175
|
parent = parent.parent
|
|
@@ -158,23 +179,29 @@ def package_delete(action, package_dir, package, logger):
|
|
|
158
179
|
|
|
159
180
|
def validate_entry(name, value, logger):
|
|
160
181
|
if isinstance(value, str):
|
|
161
|
-
if
|
|
162
|
-
|
|
163
|
-
|
|
182
|
+
if name.endswith(".py"):
|
|
183
|
+
name = name[:-3]
|
|
184
|
+
if not name.isidentifier():
|
|
185
|
+
logger.error(f"Python module name is not an identifier: {name}")
|
|
186
|
+
return False
|
|
187
|
+
else:
|
|
188
|
+
if "/" in name:
|
|
189
|
+
logger.error(f"Python file name is not valid: {name}")
|
|
164
190
|
return False
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
191
|
+
elif isinstance(value, dict):
|
|
192
|
+
if not name.isidentifier():
|
|
193
|
+
logger.error(f"Python package name is not an identifier: {name}")
|
|
194
|
+
return False
|
|
195
|
+
else:
|
|
196
|
+
logger.error(
|
|
197
|
+
f'Python package "{name}" value is not a valid type: {value.__class__}'
|
|
198
|
+
)
|
|
169
199
|
return False
|
|
170
|
-
|
|
171
|
-
return True
|
|
172
|
-
logger.error(f"Python package name is not an identifier: {name}")
|
|
173
|
-
return False
|
|
200
|
+
return True
|
|
174
201
|
|
|
175
202
|
|
|
176
203
|
def package_file_name(package_name):
|
|
177
204
|
name = str(package_name.relative_to(PACKAGES_DIR))
|
|
178
|
-
if name.endswith(
|
|
179
|
-
return True, name[:-3].replace(
|
|
205
|
+
if name.endswith(".py"):
|
|
206
|
+
return True, name[:-3].replace("/", ".")
|
|
180
207
|
return False, name
|
|
@@ -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/pythonic/proto/v1/run_function.proto
|
|
5
|
-
# Protobuf Python Version:
|
|
5
|
+
# Protobuf Python Version: 7.35.1
|
|
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
|
|
@@ -11,8 +11,8 @@ from google.protobuf import symbol_database as _symbol_database
|
|
|
11
11
|
from google.protobuf.internal import builder as _builder
|
|
12
12
|
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
13
|
_runtime_version.Domain.PUBLIC,
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
7,
|
|
15
|
+
35,
|
|
16
16
|
1,
|
|
17
17
|
'',
|
|
18
18
|
'crossplane/pythonic/proto/v1/run_function.proto'
|
|
@@ -5,7 +5,7 @@ import warnings
|
|
|
5
5
|
|
|
6
6
|
from crossplane.pythonic.proto.v1 import run_function_pb2 as crossplane_dot_pythonic_dot_proto_dot_v1_dot_run__function__pb2
|
|
7
7
|
|
|
8
|
-
GRPC_GENERATED_VERSION = '1.
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.84.0'
|
|
9
9
|
GRPC_VERSION = grpc.__version__
|
|
10
10
|
_version_not_supported = False
|
|
11
11
|
|
|
@@ -25,7 +25,7 @@ if _version_not_supported:
|
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
class FunctionRunnerServiceStub
|
|
28
|
+
class FunctionRunnerServiceStub:
|
|
29
29
|
"""A FunctionRunnerService is a function.
|
|
30
30
|
"""
|
|
31
31
|
|
|
@@ -42,7 +42,7 @@ class FunctionRunnerServiceStub(object):
|
|
|
42
42
|
_registered_method=True)
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
class FunctionRunnerServiceServicer
|
|
45
|
+
class FunctionRunnerServiceServicer:
|
|
46
46
|
"""A FunctionRunnerService is a function.
|
|
47
47
|
"""
|
|
48
48
|
|
|
@@ -69,7 +69,7 @@ def add_FunctionRunnerServiceServicer_to_server(servicer, server):
|
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
# This class is part of an EXPERIMENTAL API.
|
|
72
|
-
class FunctionRunnerService
|
|
72
|
+
class FunctionRunnerService:
|
|
73
73
|
"""A FunctionRunnerService is a function.
|
|
74
74
|
"""
|
|
75
75
|
|