crossplane-function-pythonic 0.0.8__py3-none-any.whl → 0.0.9.post0__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/composite.py +9 -9
- crossplane/pythonic/function.py +26 -15
- crossplane/pythonic/main.py +20 -15
- crossplane/pythonic/packages.py +3 -3
- crossplane/pythonic/protobuf.py +19 -29
- {crossplane_function_pythonic-0.0.8.dist-info → crossplane_function_pythonic-0.0.9.post0.dist-info}/METADATA +21 -18
- crossplane_function_pythonic-0.0.9.post0.dist-info/RECORD +11 -0
- crossplane_function_pythonic-0.0.8.dist-info/RECORD +0 -11
- {crossplane_function_pythonic-0.0.8.dist-info → crossplane_function_pythonic-0.0.9.post0.dist-info}/WHEEL +0 -0
- {crossplane_function_pythonic-0.0.8.dist-info → crossplane_function_pythonic-0.0.9.post0.dist-info}/entry_points.txt +0 -0
- {crossplane_function_pythonic-0.0.8.dist-info → crossplane_function_pythonic-0.0.9.post0.dist-info}/licenses/LICENSE +0 -0
crossplane/pythonic/composite.py
CHANGED
@@ -637,15 +637,6 @@ class Event:
|
|
637
637
|
else:
|
638
638
|
self._result.severity = fnv1.Severity.SEVERITY_NORMAL
|
639
639
|
|
640
|
-
@property
|
641
|
-
def message(self):
|
642
|
-
return self._result.message if bool(self) else None
|
643
|
-
|
644
|
-
@message.setter
|
645
|
-
def message(self, message):
|
646
|
-
if bool(self):
|
647
|
-
self._result.message = message
|
648
|
-
|
649
640
|
@property
|
650
641
|
def reason(self):
|
651
642
|
return self._result.reason if bool(self) else None
|
@@ -655,6 +646,15 @@ class Event:
|
|
655
646
|
if bool(self):
|
656
647
|
self._result.reason = reason
|
657
648
|
|
649
|
+
@property
|
650
|
+
def message(self):
|
651
|
+
return self._result.message if bool(self) else None
|
652
|
+
|
653
|
+
@message.setter
|
654
|
+
def message(self, message):
|
655
|
+
if bool(self):
|
656
|
+
self._result.message = message
|
657
|
+
|
658
658
|
@property
|
659
659
|
def claim(self):
|
660
660
|
return bool(self) and self._result == fnv1.Target.TARGET_COMPOSITE_AND_CLAIM
|
crossplane/pythonic/function.py
CHANGED
@@ -87,7 +87,18 @@ class FunctionRunner(grpcv1.FunctionRunnerService):
|
|
87
87
|
logger.exception('Exec exception')
|
88
88
|
crossplane.function.response.fatal(response, f"Exec exception: {e}")
|
89
89
|
return response
|
90
|
-
|
90
|
+
for field in dir(module):
|
91
|
+
value = getattr(module, field)
|
92
|
+
if inspect.isclass(value) and issubclass(value, BaseComposite):
|
93
|
+
if clazz:
|
94
|
+
logger.error('Composite script has multiple BaseComposite classes')
|
95
|
+
crossplane.function.response.fatal(response, 'Composite script has multiple BaseComposite classes')
|
96
|
+
return response
|
97
|
+
clazz = value
|
98
|
+
if not clazz:
|
99
|
+
logger.error('Composite script does not have have a BaseComposite class')
|
100
|
+
crossplane.function.response.fatal(response, 'Composite script does have have a BaseComposite class')
|
101
|
+
return response
|
91
102
|
else:
|
92
103
|
composite = composite.rsplit('.', 1)
|
93
104
|
if len(composite) == 1:
|
@@ -100,20 +111,20 @@ class FunctionRunner(grpcv1.FunctionRunnerService):
|
|
100
111
|
logger.error(str(e))
|
101
112
|
crossplane.function.response.fatal(response, f"Import module exception: {e}")
|
102
113
|
return response
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
114
|
+
clazz = getattr(module, composite[1], None)
|
115
|
+
if not clazz:
|
116
|
+
logger.error(f"{composite[0]} did not define: {composite[1]}")
|
117
|
+
crossplane.function.response.fatal(response, f"{composite[0]} did not define: {composite[1]}")
|
118
|
+
return response
|
119
|
+
composite = '.'.join(composite)
|
120
|
+
if not inspect.isclass(clazz):
|
121
|
+
logger.error(f"{composite} is not a class")
|
122
|
+
crossplane.function.response.fatal(response, f"{composite} is not a class")
|
123
|
+
return response
|
124
|
+
if not issubclass(clazz, BaseComposite):
|
125
|
+
logger.error(f"{composite} is not a subclass of BaseComposite")
|
126
|
+
crossplane.function.response.fatal(response, f"{composite} is not a subclass of BaseComposite")
|
127
|
+
return response
|
117
128
|
self.clazzes[composite] = clazz
|
118
129
|
|
119
130
|
try:
|
crossplane/pythonic/main.py
CHANGED
@@ -13,7 +13,6 @@ import traceback
|
|
13
13
|
import crossplane.function.logging
|
14
14
|
import crossplane.function.proto.v1.run_function_pb2_grpc as grpcv1
|
15
15
|
import grpc
|
16
|
-
import pip._internal.cli.main
|
17
16
|
|
18
17
|
from . import function
|
19
18
|
|
@@ -24,7 +23,7 @@ def main():
|
|
24
23
|
|
25
24
|
class Main:
|
26
25
|
async def main(self):
|
27
|
-
parser = argparse.ArgumentParser('
|
26
|
+
parser = argparse.ArgumentParser('Crossplane Function Pythonic')
|
28
27
|
parser.add_argument(
|
29
28
|
'--debug', '-d',
|
30
29
|
action='store_true',
|
@@ -40,18 +39,18 @@ class Main:
|
|
40
39
|
parser.add_argument(
|
41
40
|
'--address',
|
42
41
|
default='0.0.0.0:9443',
|
43
|
-
help='Address
|
42
|
+
help='Address to listen on for gRPC connections, default: 0.0.0.0:9443',
|
44
43
|
)
|
45
44
|
parser.add_argument(
|
46
45
|
'--tls-certs-dir',
|
47
46
|
default=os.getenv('TLS_SERVER_CERTS_DIR'),
|
48
47
|
metavar='DIRECTORY',
|
49
|
-
help='Serve using
|
48
|
+
help='Serve using TLS certificates.',
|
50
49
|
)
|
51
50
|
parser.add_argument(
|
52
51
|
'--insecure',
|
53
52
|
action='store_true',
|
54
|
-
help='Run without mTLS credentials
|
53
|
+
help='Run without mTLS credentials, --tls-certs-dir will be ignored.',
|
55
54
|
)
|
56
55
|
parser.add_argument(
|
57
56
|
'--packages',
|
@@ -94,15 +93,23 @@ class Main:
|
|
94
93
|
help='Allow oversized protobuf messages'
|
95
94
|
)
|
96
95
|
args = parser.parse_args()
|
96
|
+
if not args.tls_certs_dir and not args.insecure:
|
97
|
+
print('Either --tls-certs-dir or --insecure must be specified', file=sys.stderr)
|
98
|
+
sys.exit(1)
|
99
|
+
|
97
100
|
self.configure_logging(args)
|
101
|
+
# enables read only volumes or mismatched uid volumes
|
102
|
+
sys.dont_write_bytecode = True
|
103
|
+
await self.run(args)
|
98
104
|
|
105
|
+
# Allow for independent running of function-pythonic
|
106
|
+
async def run(self, args):
|
99
107
|
if args.pip_install:
|
100
|
-
pip._internal.cli.main
|
108
|
+
import pip._internal.cli.main
|
109
|
+
pip._internal.cli.main.main(['install', '--user', *shlex.split(args.pip_install)])
|
101
110
|
|
102
|
-
# enables read only volumes or mismatched uid volumes
|
103
|
-
sys.dont_write_bytecode = True
|
104
111
|
for path in reversed(args.python_path):
|
105
|
-
sys.path.insert(0, str(pathlib.Path(path).resolve()))
|
112
|
+
sys.path.insert(0, str(pathlib.Path(path).expanduser().resolve()))
|
106
113
|
|
107
114
|
if args.allow_oversize_protos:
|
108
115
|
from google.protobuf.internal import api_implementation
|
@@ -113,8 +120,10 @@ class Main:
|
|
113
120
|
grpc_runner = function.FunctionRunner(args.debug)
|
114
121
|
grpc_server = grpc.aio.server()
|
115
122
|
grpcv1.add_FunctionRunnerServiceServicer_to_server(grpc_runner, grpc_server)
|
116
|
-
if args.
|
117
|
-
|
123
|
+
if args.insecure:
|
124
|
+
grpc_server.add_insecure_port(args.address)
|
125
|
+
else:
|
126
|
+
certs = pathlib.Path(args.tls_certs_dir).expanduser().resolve()
|
118
127
|
grpc_server.add_secure_port(
|
119
128
|
args.address,
|
120
129
|
grpc.ssl_server_credentials(
|
@@ -126,10 +135,6 @@ class Main:
|
|
126
135
|
require_client_auth=True,
|
127
136
|
),
|
128
137
|
)
|
129
|
-
else:
|
130
|
-
if not args.insecure:
|
131
|
-
raise ValueError('Either --tls-certs-dir or --insecure must be specified')
|
132
|
-
grpc_server.add_insecure_port(args.address)
|
133
138
|
await grpc_server.start()
|
134
139
|
|
135
140
|
if args.packages:
|
crossplane/pythonic/packages.py
CHANGED
@@ -14,7 +14,7 @@ PACKAGE_LABEL = {'function-pythonic.package': kopf.PRESENT}
|
|
14
14
|
PACKAGES_DIR = None
|
15
15
|
|
16
16
|
|
17
|
-
def operator(grpc_server, grpc_runner, packages_secrets,
|
17
|
+
def operator(grpc_server, grpc_runner, packages_secrets, packages_namespaces, packages_dir):
|
18
18
|
logging.getLogger('kopf.objects').setLevel(logging.INFO)
|
19
19
|
global GRPC_SERVER, GRPC_RUNNER, PACKAGES_DIR
|
20
20
|
GRPC_SERVER = grpc_server
|
@@ -28,8 +28,8 @@ def operator(grpc_server, grpc_runner, packages_secrets, packages_namespace, pac
|
|
28
28
|
kopf.on.delete('', 'v1', 'secrets', labels=PACKAGE_LABEL)(delete)
|
29
29
|
return kopf.operator(
|
30
30
|
standalone=True,
|
31
|
-
clusterwide=not
|
32
|
-
namespaces=
|
31
|
+
clusterwide=not packages_namespaces,
|
32
|
+
namespaces=packages_namespaces,
|
33
33
|
)
|
34
34
|
|
35
35
|
|
crossplane/pythonic/protobuf.py
CHANGED
@@ -25,10 +25,16 @@ append = sys.maxsize
|
|
25
25
|
|
26
26
|
|
27
27
|
def Map(**kwargs):
|
28
|
-
|
28
|
+
map = Values(None, None, None, Values.Type.MAP)
|
29
|
+
for name, value in kwargs.items():
|
30
|
+
map[name] = value
|
31
|
+
return map
|
29
32
|
|
30
33
|
def List(*args):
|
31
|
-
|
34
|
+
list = Values(None, None, None, Values.Type.LIST)
|
35
|
+
for ix, value in enumerate(args):
|
36
|
+
list[ix] = value
|
37
|
+
return list
|
32
38
|
|
33
39
|
def Unknown():
|
34
40
|
return Values(None, None, None, Values.Type.UNKNOWN)
|
@@ -683,36 +689,16 @@ class Values:
|
|
683
689
|
def __call__(self, *args, **kwargs):
|
684
690
|
if self._readOnly:
|
685
691
|
raise ValueError(f"{self._readOnly} is read only")
|
692
|
+
self.__dict__['_values'] = None
|
693
|
+
self.__dict__['_type'] = self.Type.UNKNOWN
|
686
694
|
self._cache.clear()
|
687
695
|
self._unknowns.clear()
|
688
696
|
if len(kwargs):
|
689
|
-
if not self._isMap:
|
690
|
-
if not self._isUnknown:
|
691
|
-
raise ValueError('Cannot specify kwargs on lists')
|
692
|
-
self.__dict__['_type'] = self.Type.MAP
|
693
697
|
if len(args):
|
694
|
-
raise ValueError('Connect specify
|
695
|
-
if self._values is None:
|
696
|
-
if self._parent is None:
|
697
|
-
self.__dict__['_values'] = google.protobuf.struct_pb2.Struct()
|
698
|
-
else:
|
699
|
-
self.__dict__['_values'] = self._parent._create_child(self._key, self._type)
|
700
|
-
self._values.Clear()
|
698
|
+
raise ValueError('Connect specify both kwargs and args')
|
701
699
|
for key, value in kwargs.items():
|
702
700
|
self[key] = value
|
703
701
|
elif len(args):
|
704
|
-
if not self._isList:
|
705
|
-
if not self._isUnknown:
|
706
|
-
raise ValueError('Cannot specify args on maps')
|
707
|
-
self.__dict__['_type'] = self.Type.LIST
|
708
|
-
if len(kwargs):
|
709
|
-
raise ValueError('Connect specify kwargs on lists')
|
710
|
-
if self._values is None:
|
711
|
-
if self._parent is None:
|
712
|
-
self.__dict__['_values'] = google.protobuf.struct_pb2.ListValue()
|
713
|
-
else:
|
714
|
-
self.__dict__['_values'] = self._parent._create_child(self._key, self._type)
|
715
|
-
self._values.Clear()
|
716
702
|
for key in range(len(args)):
|
717
703
|
self[key] = args[key]
|
718
704
|
return self
|
@@ -767,17 +753,21 @@ class Values:
|
|
767
753
|
values[key].number_value = value
|
768
754
|
elif isinstance(value, dict):
|
769
755
|
values[key].struct_value.Clear()
|
770
|
-
|
756
|
+
for k, v in value.items():
|
757
|
+
self[key][k] = v
|
771
758
|
elif isinstance(value, (list, tuple)):
|
772
759
|
values[key].list_value.Clear()
|
773
|
-
|
760
|
+
for ix, v in enumerate(value):
|
761
|
+
self[key][ix] = v
|
774
762
|
elif isinstance(value, Values):
|
775
763
|
if value._isMap:
|
776
764
|
values[key].struct_value.Clear()
|
777
|
-
|
765
|
+
for k, v in value:
|
766
|
+
self[key][k] = v
|
778
767
|
elif value._isList:
|
779
768
|
values[key].list_value.Clear()
|
780
|
-
|
769
|
+
for ix, v in enumerate(value):
|
770
|
+
self[key][ix] = v
|
781
771
|
else:
|
782
772
|
self._unknowns[key] = value
|
783
773
|
if self._isMap:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: crossplane-function-pythonic
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.9.post0
|
4
4
|
Summary: A Python centric Crossplane Function
|
5
5
|
Project-URL: Documentation, https://github.com/fortra/function-pythonic#readme
|
6
6
|
Project-URL: Issues, https://github.com/fortra/function-pythonic/issues
|
@@ -15,8 +15,11 @@ Classifier: Programming Language :: Python :: 3.12
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.13
|
16
16
|
Requires-Python: <3.14,>=3.11
|
17
17
|
Requires-Dist: crossplane-function-sdk-python==0.9.0
|
18
|
-
Requires-Dist: kopf==1.38.0
|
19
18
|
Requires-Dist: pyyaml==6.0.2
|
19
|
+
Provides-Extra: packages
|
20
|
+
Requires-Dist: kopf==1.38.0; extra == 'packages'
|
21
|
+
Provides-Extra: pip-install
|
22
|
+
Requires-Dist: pip==25.2; extra == 'pip-install'
|
20
23
|
Description-Content-Type: text/markdown
|
21
24
|
|
22
25
|
# function-pythonic
|
@@ -49,7 +52,7 @@ spec:
|
|
49
52
|
apiVersion: pythonic.fn.crossplane.io/v1beta1
|
50
53
|
kind: Composite
|
51
54
|
composite: |
|
52
|
-
class
|
55
|
+
class VpcComposite(BaseComposite):
|
53
56
|
def compose(self):
|
54
57
|
vpc = self.resources.vpc('ec2.aws.crossplane.io/v1beta1', 'VPC')
|
55
58
|
vpc.spec.forProvider.region = self.spec.region
|
@@ -78,7 +81,7 @@ kind: Function
|
|
78
81
|
metadata:
|
79
82
|
name: function-pythonic
|
80
83
|
spec:
|
81
|
-
package: ghcr.io/fortra/function-pythonic:v0.0.
|
84
|
+
package: ghcr.io/fortra/function-pythonic:v0.0.9
|
82
85
|
```
|
83
86
|
## Composed Resource Dependencies
|
84
87
|
|
@@ -179,13 +182,13 @@ proto = format(request, 'protobuf') # get the request as a protobuf string
|
|
179
182
|
Composite composition is performed from a Composite orientation. A `BaseComposite` class
|
180
183
|
is subclassed and the `compose` method is implemented.
|
181
184
|
```python
|
182
|
-
class
|
185
|
+
class MyComposite(BaseComposite):
|
183
186
|
def compose(self):
|
184
187
|
# Compose the Composite
|
185
188
|
```
|
186
189
|
The compose method can also declare itself as performing async io:
|
187
190
|
```python
|
188
|
-
class
|
191
|
+
class MyAsyncComposite(BaseComposite):
|
189
192
|
async def compose(self):
|
190
193
|
# Compose the Composite using async io when needed
|
191
194
|
```
|
@@ -287,7 +290,7 @@ Each resource in the list is the following RequiredResource class:
|
|
287
290
|
|
288
291
|
### Conditions
|
289
292
|
|
290
|
-
The `
|
293
|
+
The `BaseComposite.conditions`, `Resource.conditions`, and `RequiredResource.conditions` fields
|
291
294
|
are maps of that entity's status conditions array, with the map key being the condition type.
|
292
295
|
The fields are read only for `Resource.conditions` and `RequiredResource.conditions`.
|
293
296
|
|
@@ -328,7 +331,7 @@ metadata:
|
|
328
331
|
name: composite-example
|
329
332
|
spec:
|
330
333
|
composite: |
|
331
|
-
class
|
334
|
+
class HelloComposite(BaseComposite):
|
332
335
|
def compose(self):
|
333
336
|
self.status.composite = 'Hello, World!'
|
334
337
|
```
|
@@ -370,7 +373,7 @@ spec:
|
|
370
373
|
apiVersion: pythonic.fn.fortra.com/v1alpha1
|
371
374
|
kind: Composite
|
372
375
|
composite: |
|
373
|
-
class
|
376
|
+
class GreetingComposite(BaseComposite):
|
374
377
|
def compose(self):
|
375
378
|
self.status.greeting = f"Hello, {self.spec.who}!"
|
376
379
|
```
|
@@ -383,7 +386,7 @@ metadata:
|
|
383
386
|
annotations:
|
384
387
|
render.crossplane.io/runtime: Development
|
385
388
|
spec:
|
386
|
-
package: ghcr.io/fortra/function-pythonic:v0.0.
|
389
|
+
package: ghcr.io/fortra/function-pythonic:v0.0.9
|
387
390
|
```
|
388
391
|
In one terminal session, run function-pythonic:
|
389
392
|
```shell
|
@@ -443,7 +446,7 @@ Then, in your Composition:
|
|
443
446
|
kind: Composite
|
444
447
|
composite: |
|
445
448
|
from example.pythonic import features
|
446
|
-
class
|
449
|
+
class FetureComposite(BaseComposite):
|
447
450
|
def compose(self):
|
448
451
|
anything = features.anything()
|
449
452
|
...
|
@@ -485,7 +488,7 @@ kind: Function
|
|
485
488
|
metadata:
|
486
489
|
name: function-pythonic
|
487
490
|
spec:
|
488
|
-
package: ghcr.io/fortra/function-pythonic:v0.0.
|
491
|
+
package: ghcr.io/fortra/function-pythonic:v0.0.9
|
489
492
|
runtimeConfigRef:
|
490
493
|
name: function-pythonic
|
491
494
|
---
|
@@ -514,12 +517,6 @@ kind: ClusterRole
|
|
514
517
|
metadata:
|
515
518
|
name: function-pythonic
|
516
519
|
rules:
|
517
|
-
- apiGroups:
|
518
|
-
- ''
|
519
|
-
resources:
|
520
|
-
- events
|
521
|
-
verbs:
|
522
|
-
- create
|
523
520
|
- apiGroups:
|
524
521
|
- ''
|
525
522
|
resources:
|
@@ -528,6 +525,12 @@ rules:
|
|
528
525
|
- list
|
529
526
|
- watch
|
530
527
|
- patch
|
528
|
+
- apiGroups:
|
529
|
+
- ''
|
530
|
+
resources:
|
531
|
+
- events
|
532
|
+
verbs:
|
533
|
+
- create
|
531
534
|
---
|
532
535
|
apiVersion: rbac.authorization.k8s.io/v1
|
533
536
|
kind: ClusterRoleBinding
|
@@ -0,0 +1,11 @@
|
|
1
|
+
crossplane/pythonic/__init__.py,sha256=9Oz3mvFO-8GXb75iEfybSHgVr3p8INdqA201tCusuSo,408
|
2
|
+
crossplane/pythonic/composite.py,sha256=TxloK31jx3xDmLnalntPXCHNnxuudevdeqPzKcSBO_I,19937
|
3
|
+
crossplane/pythonic/function.py,sha256=95asJ_6dFy-KSXiMIkJkxqI264kSqBs4Vh61RAojqSY,11336
|
4
|
+
crossplane/pythonic/main.py,sha256=kcpoR4F84IhxLzaPSWWdIoaXmrUyjXofvwQuenVPHSE,6683
|
5
|
+
crossplane/pythonic/packages.py,sha256=quxAkmioIGJr9g4uRHsqPwhzyu2f2_UyNHHQmZjSJ8A,6108
|
6
|
+
crossplane/pythonic/protobuf.py,sha256=ULcaqeyeqCaz0SSSZXNpeUPh1EQLdAV09Dwj3ltIx7k,33899
|
7
|
+
crossplane_function_pythonic-0.0.9.post0.dist-info/METADATA,sha256=FhRLdxg9QMegatxFTBkSNROk93V-G-B1EfWksEBxf3w,23452
|
8
|
+
crossplane_function_pythonic-0.0.9.post0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
9
|
+
crossplane_function_pythonic-0.0.9.post0.dist-info/entry_points.txt,sha256=jJ4baywFDviB9WyAhyhNYF2VOCb6XtbRSjKf7bnBwhg,68
|
10
|
+
crossplane_function_pythonic-0.0.9.post0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
11
|
+
crossplane_function_pythonic-0.0.9.post0.dist-info/RECORD,,
|
@@ -1,11 +0,0 @@
|
|
1
|
-
crossplane/pythonic/__init__.py,sha256=9Oz3mvFO-8GXb75iEfybSHgVr3p8INdqA201tCusuSo,408
|
2
|
-
crossplane/pythonic/composite.py,sha256=CK_3ejKZ29zWnAZ94r5ycNduf_cmDeH8-AL5QcJL1Mo,19937
|
3
|
-
crossplane/pythonic/function.py,sha256=4kfyR0U6UaAQAhVbFrhFPwOOsHjeNEktuTuswLrm0G4,10535
|
4
|
-
crossplane/pythonic/main.py,sha256=W6SG6o6vYCl75tdvWnTmPyYhcs6FeI5YaniCOK1s4TE,6491
|
5
|
-
crossplane/pythonic/packages.py,sha256=LVC-MUlptLjnMPdxcFu7LrcyJgLuHU8IIag2YLQfzSs,6105
|
6
|
-
crossplane/pythonic/protobuf.py,sha256=9wvKMXavrHxD1n1TufFQs_6If9m4gRZA36p_pmrlU7I,34633
|
7
|
-
crossplane_function_pythonic-0.0.8.dist-info/METADATA,sha256=iXgH80gmev0loJC3jMCous6Cav5fLhS9Yh3QBJMfBkw,23291
|
8
|
-
crossplane_function_pythonic-0.0.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
9
|
-
crossplane_function_pythonic-0.0.8.dist-info/entry_points.txt,sha256=jJ4baywFDviB9WyAhyhNYF2VOCb6XtbRSjKf7bnBwhg,68
|
10
|
-
crossplane_function_pythonic-0.0.8.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
11
|
-
crossplane_function_pythonic-0.0.8.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|