pinexq-procon 2.1.0.dev3__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.
- pinexq/procon/__init__.py +0 -0
- pinexq/procon/core/__init__.py +0 -0
- pinexq/procon/core/cli.py +442 -0
- pinexq/procon/core/exceptions.py +64 -0
- pinexq/procon/core/helpers.py +61 -0
- pinexq/procon/core/logconfig.py +48 -0
- pinexq/procon/core/naming.py +36 -0
- pinexq/procon/core/types.py +15 -0
- pinexq/procon/dataslots/__init__.py +19 -0
- pinexq/procon/dataslots/abstractionlayer.py +215 -0
- pinexq/procon/dataslots/annotation.py +389 -0
- pinexq/procon/dataslots/dataslots.py +369 -0
- pinexq/procon/dataslots/datatypes.py +50 -0
- pinexq/procon/dataslots/default_reader_writer.py +26 -0
- pinexq/procon/dataslots/filebackend.py +126 -0
- pinexq/procon/dataslots/metadata.py +137 -0
- pinexq/procon/jobmanagement/__init__.py +9 -0
- pinexq/procon/jobmanagement/api_helpers.py +287 -0
- pinexq/procon/remote/__init__.py +0 -0
- pinexq/procon/remote/messages.py +250 -0
- pinexq/procon/remote/rabbitmq.py +420 -0
- pinexq/procon/runtime/__init__.py +3 -0
- pinexq/procon/runtime/foreman.py +128 -0
- pinexq/procon/runtime/job.py +384 -0
- pinexq/procon/runtime/settings.py +12 -0
- pinexq/procon/runtime/tool.py +16 -0
- pinexq/procon/runtime/worker.py +437 -0
- pinexq/procon/step/__init__.py +3 -0
- pinexq/procon/step/introspection.py +234 -0
- pinexq/procon/step/schema.py +99 -0
- pinexq/procon/step/step.py +119 -0
- pinexq/procon/step/versioning.py +84 -0
- pinexq_procon-2.1.0.dev3.dist-info/METADATA +83 -0
- pinexq_procon-2.1.0.dev3.dist-info/RECORD +35 -0
- pinexq_procon-2.1.0.dev3.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Building blocks for all schemas
|
|
3
|
+
|
|
4
|
+
All objects for the schema description of function signatures are here
|
|
5
|
+
represented as Pydantic BaseModel classes.
|
|
6
|
+
"""
|
|
7
|
+
import warnings
|
|
8
|
+
from enum import Enum
|
|
9
|
+
from typing import Any, Annotated, Type, Mapping
|
|
10
|
+
|
|
11
|
+
from pydantic import ConfigDict, BaseModel, constr, Field, model_validator
|
|
12
|
+
|
|
13
|
+
from pydantic.json_schema import (
|
|
14
|
+
GenerateJsonSchema, DEFAULT_REF_TEMPLATE, JsonSchemaMode, JsonSchemaValue, CoreSchema
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# Custom JSON schema generators to create schemas with '$schema' identifier
|
|
19
|
+
# -> copied from: https://github.com/pydantic/pydantic/blob/73373c3e08fe5fe23e4b05f549ea34e0da6a16b7/tests/test_json_schema.py#L3090-L3116
|
|
20
|
+
|
|
21
|
+
class GenerateJsonSchemaWithDialect(GenerateJsonSchema):
|
|
22
|
+
def generate(self, schema: CoreSchema, mode: JsonSchemaMode = 'validation') -> JsonSchemaValue:
|
|
23
|
+
json_schema = super().generate(schema)
|
|
24
|
+
json_schema['$schema'] = self.schema_dialect
|
|
25
|
+
return json_schema
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class BaseModelWithSchema(BaseModel):
|
|
29
|
+
@classmethod
|
|
30
|
+
def model_json_schema(
|
|
31
|
+
cls,
|
|
32
|
+
by_alias: bool = True,
|
|
33
|
+
ref_template: str = DEFAULT_REF_TEMPLATE,
|
|
34
|
+
schema_generator: Type[GenerateJsonSchema] = GenerateJsonSchemaWithDialect,
|
|
35
|
+
mode: JsonSchemaMode = 'validation'
|
|
36
|
+
) -> dict[str, Any]:
|
|
37
|
+
return super().model_json_schema(by_alias, ref_template, schema_generator, mode)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# Models defining the structure of the "manifest" generated by the "signature" command
|
|
41
|
+
class DataslotModel(BaseModel):
|
|
42
|
+
"""Description of a single DataSlot"""
|
|
43
|
+
name: str
|
|
44
|
+
title: str
|
|
45
|
+
description: str
|
|
46
|
+
mediatype: str
|
|
47
|
+
metadata: dict
|
|
48
|
+
min_slots: Annotated[int, Field(ge=0, strict=True, serialization_alias='minSlots')]
|
|
49
|
+
max_slots: Annotated[int | None, Field(ge=1, strict=True, serialization_alias='maxSlots')]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class FunctionModel(BaseModel):
|
|
53
|
+
"""Structure of a Step-function manifest"""
|
|
54
|
+
version: Annotated[str, Field(min_length=0, max_length=40)]
|
|
55
|
+
function_name: Annotated[str, Field(min_length=1, max_length=100)]
|
|
56
|
+
short_description: str
|
|
57
|
+
long_description: str
|
|
58
|
+
parameters: Any = None # 'DynamicParameters' actually, but embedded at runtime as schema
|
|
59
|
+
returns: Any = None # 'DynamicReturns' actually, but embedded at runtime as schema
|
|
60
|
+
input_dataslots: list[DataslotModel]
|
|
61
|
+
output_dataslots: list[DataslotModel]
|
|
62
|
+
procon_version: str
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class DynamicParameters(BaseModelWithSchema):
|
|
66
|
+
"""Basis for a dynamically created model of the functions parameters."""
|
|
67
|
+
model_config = ConfigDict(
|
|
68
|
+
arbitrary_types_allowed=True,
|
|
69
|
+
extra="forbid",
|
|
70
|
+
strict=True,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
@model_validator(mode="before")
|
|
74
|
+
@classmethod
|
|
75
|
+
def _convert_enums(cls, values: Mapping[str, Any]) -> Mapping[str, Any]:
|
|
76
|
+
values = dict(values) # Ensure mutable dict
|
|
77
|
+
for field_name, model_field in cls.model_fields.items():
|
|
78
|
+
field_type = model_field.annotation
|
|
79
|
+
if isinstance(field_type, type) and issubclass(field_type, Enum):
|
|
80
|
+
value = values.get(field_name)
|
|
81
|
+
if isinstance(value, str):
|
|
82
|
+
try:
|
|
83
|
+
values[field_name] = field_type(value)
|
|
84
|
+
except ValueError:
|
|
85
|
+
warnings.warn(
|
|
86
|
+
f"Failed to convert '{value}' to '{field_type.__name__}' for field '{field_name}'."
|
|
87
|
+
)
|
|
88
|
+
return values
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class DynamicReturns(BaseModelWithSchema):
|
|
94
|
+
"""Basis for a dynamically created model of the functions return value."""
|
|
95
|
+
model_config = ConfigDict(
|
|
96
|
+
arbitrary_types_allowed=True,
|
|
97
|
+
extra="ignore",
|
|
98
|
+
strict=True,
|
|
99
|
+
)
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import Any, TypeVar
|
|
3
|
+
|
|
4
|
+
import pydantic
|
|
5
|
+
|
|
6
|
+
from ..core.exceptions import ProConException, ProConSchemaValidationError
|
|
7
|
+
from ..dataslots import DataSlotDescription, DataslotLayer
|
|
8
|
+
from ..dataslots.metadata import MetadataHandler
|
|
9
|
+
from .introspection import FunctionSchema, StepClassInfo
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class ExecutionContext:
|
|
14
|
+
"""Wraps all information to call a function in a Step container"""
|
|
15
|
+
|
|
16
|
+
function_name: str
|
|
17
|
+
parameters: dict[str, Any] = field(default_factory=dict)
|
|
18
|
+
input_dataslots: dict[str, "DataSlotDescription"] = field(default_factory=dict)
|
|
19
|
+
output_dataslots: dict[str, "DataSlotDescription"] = field(default_factory=dict)
|
|
20
|
+
metadata_handler: MetadataHandler | None = None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
ExecutionContextType = TypeVar("ExecutionContextType", bound="ExecutionContext")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Step:
|
|
27
|
+
_signatures: dict[str, FunctionSchema]
|
|
28
|
+
_context: ExecutionContextType | None = None
|
|
29
|
+
|
|
30
|
+
def __init__(self, use_cli=True):
|
|
31
|
+
self._signatures = StepClassInfo(self).get_func_schemas()
|
|
32
|
+
|
|
33
|
+
if use_cli:
|
|
34
|
+
# Do the import here to avoid circular imports
|
|
35
|
+
from pinexq.procon.core.cli import cli
|
|
36
|
+
|
|
37
|
+
cli.main(
|
|
38
|
+
obj=self, # This Step object *self* is available as *obj* attribute in the context of each cli command
|
|
39
|
+
auto_envvar_prefix="PROCON",
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def _call(self, context: ExecutionContextType) -> Any:
|
|
43
|
+
"""Calls a function from this container"""
|
|
44
|
+
try:
|
|
45
|
+
# Check if this class contains the function?
|
|
46
|
+
function = getattr(self, context.function_name)
|
|
47
|
+
# is it one of the exposed functions?
|
|
48
|
+
signature = self._signatures[context.function_name]
|
|
49
|
+
except (KeyError, AttributeError):
|
|
50
|
+
raise ProConException(
|
|
51
|
+
f"No function with such name: '{context.function_name}'"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Connect to the dataslot sources and load the data into parameters
|
|
55
|
+
with DataslotLayer(
|
|
56
|
+
function=function,
|
|
57
|
+
parameters=context.parameters,
|
|
58
|
+
dataslots_in_descr=context.input_dataslots,
|
|
59
|
+
dataslots_out_descr=context.output_dataslots,
|
|
60
|
+
signature=signature,
|
|
61
|
+
metadata_handler=context.metadata_handler,
|
|
62
|
+
) as ds_handle:
|
|
63
|
+
# Match parameters with the function's signature
|
|
64
|
+
try:
|
|
65
|
+
# The validation may fail when e.g. Enums are used within the
|
|
66
|
+
# parameters. TODO: find a way how to verify nested enums.
|
|
67
|
+
function_parameter_model = signature.get_parameters_model().model_validate(ds_handle.parameters)
|
|
68
|
+
except pydantic.ValidationError as ex:
|
|
69
|
+
raise ProConSchemaValidationError(
|
|
70
|
+
"Parameters don't match the functions signature!"
|
|
71
|
+
) from ex
|
|
72
|
+
|
|
73
|
+
# Call the function
|
|
74
|
+
self._context = context
|
|
75
|
+
try:
|
|
76
|
+
# Get the parameter model as a dictionary. Unlike .model_dump(), casting
|
|
77
|
+
# it with `dict()` will only convert the root level Basemodel and not
|
|
78
|
+
# any embedded Basemodels.
|
|
79
|
+
function_parameters = dict(function_parameter_model)
|
|
80
|
+
|
|
81
|
+
# The actual function call
|
|
82
|
+
result = ds_handle.function(**function_parameters)
|
|
83
|
+
|
|
84
|
+
# Update parameters to handle "return-by-reference" via Output-Dataslots
|
|
85
|
+
ds_handle.update_parameters(function_parameters)
|
|
86
|
+
# Update return value to handle Return-Dataslots
|
|
87
|
+
ds_handle.update_result(result)
|
|
88
|
+
except ProConException:
|
|
89
|
+
raise
|
|
90
|
+
except Exception as ex:
|
|
91
|
+
raise ProConException(
|
|
92
|
+
f"Exception during execution of '{context.function_name}'!"
|
|
93
|
+
) from ex
|
|
94
|
+
finally:
|
|
95
|
+
self._context = None
|
|
96
|
+
|
|
97
|
+
# Match the results signature
|
|
98
|
+
# But only if there is no return-Dataslot, in which case there is no return value
|
|
99
|
+
# FixMe: Data in the return.dataslot is actually not validated against the signature!
|
|
100
|
+
if not ds_handle.has_results_data_slot():
|
|
101
|
+
try:
|
|
102
|
+
signature.get_returns_model().model_validate({"value": result})
|
|
103
|
+
except pydantic.ValidationError as ex:
|
|
104
|
+
raise ProConSchemaValidationError(
|
|
105
|
+
"The functions return values doesn't match its signature!"
|
|
106
|
+
) from ex
|
|
107
|
+
|
|
108
|
+
# The result value or None, if a `return.dataslot` is defined
|
|
109
|
+
func_result = ds_handle.result
|
|
110
|
+
|
|
111
|
+
return func_result
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def step_context(self) -> ExecutionContextType | None:
|
|
115
|
+
return self._context
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def step_signatures(self) -> dict[str, FunctionSchema]:
|
|
119
|
+
return self._signatures
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Any, Callable
|
|
3
|
+
|
|
4
|
+
from pydantic import Field
|
|
5
|
+
from pydantic.dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
from ..core.types import UNSET, UNSETTYPE
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
METADATA_ANNOTATION_NAME = "__pxq_metadata__"
|
|
11
|
+
|
|
12
|
+
# Version string regex
|
|
13
|
+
VERSION_PATTERN = r"""
|
|
14
|
+
^(?: # start of the string
|
|
15
|
+
(?P<version>[0-9]{1,8}(?:\.[0-9]{1,8}){,2}) # version number
|
|
16
|
+
(?:-(?P<postfix>[0-9a-zA-Z_-]+))? # postfix string
|
|
17
|
+
)$ # end of the string
|
|
18
|
+
"""
|
|
19
|
+
version_regex = re.compile(VERSION_PATTERN, flags=re.VERBOSE)
|
|
20
|
+
|
|
21
|
+
# Regex pattern for just the postfix substring for pydantic
|
|
22
|
+
POSTFIX_PATTERN = r"^[0-9a-zA-Z_-]*$"
|
|
23
|
+
postfix_regex = re.compile(POSTFIX_PATTERN)
|
|
24
|
+
|
|
25
|
+
# Restrictions
|
|
26
|
+
# <major:int>.<minor:int>.<patch:int>-<string> mit max 40 chars
|
|
27
|
+
# maj/min/patch each <= 8 chars , defaults == 0
|
|
28
|
+
|
|
29
|
+
MAX_VERSION_LENGTH = 40
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class version:
|
|
34
|
+
"""Decorator to attach version information to a Step function.
|
|
35
|
+
|
|
36
|
+
Attributes:
|
|
37
|
+
version: ...
|
|
38
|
+
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
version: str | UNSETTYPE = Field(default=UNSET, pattern=version_regex)
|
|
42
|
+
major: int | UNSETTYPE = Field(default=UNSET, ge=0, lt=100_000_000, kw_only=True)
|
|
43
|
+
minor: int | UNSETTYPE = Field(default=UNSET, ge=0, lt=100_000_000, kw_only=True)
|
|
44
|
+
patch: int | UNSETTYPE = Field(default=UNSET, ge=0, lt=100_000_000, kw_only=True)
|
|
45
|
+
postfix: str | UNSETTYPE = Field(default=UNSET, pattern=postfix_regex, kw_only=True)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def __post_init__(self):
|
|
49
|
+
version_was_set = self.version is not UNSET
|
|
50
|
+
any_specifier_was_set = (self.major is not UNSET or self.minor is not UNSET
|
|
51
|
+
or self.patch is not UNSET or self.postfix is not UNSET)
|
|
52
|
+
if not (version_was_set or any_specifier_was_set):
|
|
53
|
+
self.major = 0 # default value when no parameter was given
|
|
54
|
+
elif not (version_was_set ^ any_specifier_was_set):
|
|
55
|
+
raise ValueError("You have to define the version either as a string or explicitly via the "
|
|
56
|
+
"'major', 'minor', 'patch', 'postfix' keyword, but not both!")
|
|
57
|
+
|
|
58
|
+
if not version_was_set:
|
|
59
|
+
self._set_version_from_kwargs()
|
|
60
|
+
|
|
61
|
+
if len(self.version) > MAX_VERSION_LENGTH:
|
|
62
|
+
raise ValueError(f"The version string is too long! "
|
|
63
|
+
f"Max {MAX_VERSION_LENGTH} chars are allowed, but it has {len(self.version)} chars.")
|
|
64
|
+
|
|
65
|
+
def _set_version_from_kwargs(self):
|
|
66
|
+
"""Generate the version string from single kwarg variables"""
|
|
67
|
+
# The default string will always be "0.0.0" and all values and postfix are optional
|
|
68
|
+
self.version = (f"{self.major or '0'}.{self.minor or '0'}.{self.patch or '0'}"
|
|
69
|
+
f"{f'-{self.postfix}' if self.postfix else ''}")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def __call__(self, function: Callable[[Any], Any]):
|
|
73
|
+
"""Called when used as a decorator to attach metadata to 'func'."""
|
|
74
|
+
metadata = function.__dict__.setdefault(METADATA_ANNOTATION_NAME, {})
|
|
75
|
+
metadata["version"] = self
|
|
76
|
+
|
|
77
|
+
return function
|
|
78
|
+
|
|
79
|
+
def __str__(self) -> str:
|
|
80
|
+
return self.version
|
|
81
|
+
|
|
82
|
+
def get_version_metadata(function: Callable[[Any], Any]) -> version:
|
|
83
|
+
metadata = getattr(function, METADATA_ANNOTATION_NAME, {})
|
|
84
|
+
return metadata.get("version", version())
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: pinexq-procon
|
|
3
|
+
Version: 2.1.0.dev3
|
|
4
|
+
Summary: Framework to create containers for DataCybernetic's PineXQ computing platform
|
|
5
|
+
Author: Sebastian Höfer, Carsten Blank, Mathias Reichardt
|
|
6
|
+
Author-email: Sebastian Höfer <hoefer@data-cybernetics.com>, Carsten Blank <blank@data-cybernetics.com>, Mathias Reichardt <reichardt@data-cybernetics.com>
|
|
7
|
+
License: Copyright (C) data cybernetics ssc GmbH - All Rights Reserved
|
|
8
|
+
<contactus@data-cybernetics.com>, December 2023
|
|
9
|
+
Requires-Dist: aio-pika==9.5.5
|
|
10
|
+
Requires-Dist: click>=8.1.3
|
|
11
|
+
Requires-Dist: docstring-parser==0.*
|
|
12
|
+
Requires-Dist: httpx-caching>=0.1a4
|
|
13
|
+
Requires-Dist: httpx==0.*
|
|
14
|
+
Requires-Dist: pinexq-client>=0.10
|
|
15
|
+
Requires-Dist: pydantic>=2.10.0
|
|
16
|
+
Requires-Dist: pyjwt>=2.10.0
|
|
17
|
+
Requires-Dist: rich>=13.3.2
|
|
18
|
+
Requires-Dist: stamina>=24.2.0
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# PineXQ ProCon Framework
|
|
23
|
+
|
|
24
|
+
Computations in DC-Cloud are done by **Workers** running inside a **ProcessingContainer**, or short "ProCon", which is also the name of the framework.
|
|
25
|
+
ProCon provides an unobtrusive wrapper around function definitions without introducing new semantics, allowing for a clean definition of the computational task, while handling all cloud-related communication and data-management transparently in the background.
|
|
26
|
+
This removes the code and configuration required from the function implementation.
|
|
27
|
+
|
|
28
|
+
### Installation
|
|
29
|
+
|
|
30
|
+
To install the package use the `pip` command, to either install from a package feed:
|
|
31
|
+
```
|
|
32
|
+
pip install pinexq-procon
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Creating a container
|
|
37
|
+
|
|
38
|
+
To publish a function in a container it has to be a method of a class inheriting from the `Step` class.
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from pinexq.procon.step import Step # import package
|
|
42
|
+
|
|
43
|
+
class MyStepCollection(Step): # define the container class
|
|
44
|
+
def calculate_square(self, x: float) -> float: # define a step function
|
|
45
|
+
"""Calculate the square of x
|
|
46
|
+
|
|
47
|
+
:param x: a float number
|
|
48
|
+
:returns: the square of x
|
|
49
|
+
"""
|
|
50
|
+
return x ** 2
|
|
51
|
+
|
|
52
|
+
# More step functions can go in the same class
|
|
53
|
+
|
|
54
|
+
if __name__ == '__main__': # add script guard
|
|
55
|
+
MyStepCollection() # run the container - this will spawn the cli
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
It is mandatory to annotate the types of parameters and return value.
|
|
59
|
+
Docstrings are optional, but highly recommended.
|
|
60
|
+
|
|
61
|
+
The [documentation](doc/ProCon.md) has a detailed section about [implementing processing-steps](doc/Implementing-a-Step.md).
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
### Running a Step-function locally
|
|
65
|
+
|
|
66
|
+
The Python file with the container is itself a cli-tool.
|
|
67
|
+
You get a list of all available commands with the `--help` parameter.
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
python ./my_step_file.py --help
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
With the `run` option you can call a function in the container directly and the result is written to the console.
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
python ./my_step_file.py run --function calculate_square --parameters "{'x': 5}"
|
|
77
|
+
25
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
You can find full list of available commands in the [cli documentation](doc/Using-Procon-From-Cli.md).
|
|
81
|
+
All possible parameters and environment variables are listed [here](doc/Parameters.md).
|
|
82
|
+
|
|
83
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
pinexq/procon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
pinexq/procon/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
pinexq/procon/core/cli.py,sha256=8MPdTi9sCluFn7Y9TfaBKJavTsUmR5SG5Eup1SAMaZM,16602
|
|
4
|
+
pinexq/procon/core/exceptions.py,sha256=0SXvC54-H6E65Fi06mQc6FlTnWB91GHH27ci7ypBYRE,1677
|
|
5
|
+
pinexq/procon/core/helpers.py,sha256=2nnd99o0_oPwAptOF_6LySeeDv8ZPf6EO2R88yUBbuY,1996
|
|
6
|
+
pinexq/procon/core/logconfig.py,sha256=UlIqgzShK3UETmRz2iSDniypQxnIGOuwz-gZetfaths,1503
|
|
7
|
+
pinexq/procon/core/naming.py,sha256=K2g3dFZdz46WevbRpeK-75v6427ph56F43evDARWxHk,916
|
|
8
|
+
pinexq/procon/core/types.py,sha256=w6XmboyUSly4JI-zM-A3Otc-f-F2NrfzGvpC7HLOcwA,226
|
|
9
|
+
pinexq/procon/dataslots/__init__.py,sha256=uiRtBPBbK7thyte7Ch7x-S00LYaX_qJ_ELtPfqaydi4,365
|
|
10
|
+
pinexq/procon/dataslots/abstractionlayer.py,sha256=ll86ONfQNsmbn55IbF4aE9D9jpe32s5L7UmX23JIx-4,9257
|
|
11
|
+
pinexq/procon/dataslots/annotation.py,sha256=O-oAi2vrrwZaAD0tOB4viAqYsGTe_ICftfAa2YH_5nk,16487
|
|
12
|
+
pinexq/procon/dataslots/dataslots.py,sha256=6RQwncq8E_9ILPBhxthnWfy9K6_W8IY6jouTNAZLhXI,14274
|
|
13
|
+
pinexq/procon/dataslots/datatypes.py,sha256=TpbHCAjuFokHUUG8Dweu7RlULmu4QIZYB4lvnk09ROg,1292
|
|
14
|
+
pinexq/procon/dataslots/default_reader_writer.py,sha256=f9edmeaTDO11D5im_cqIqBgFGfqh9Sb5cw6DtxO2KvM,1003
|
|
15
|
+
pinexq/procon/dataslots/filebackend.py,sha256=xGAXwo5XzDtznzoQMLwReKrabNCeRQuYYjHGjWugcyI,3935
|
|
16
|
+
pinexq/procon/dataslots/metadata.py,sha256=Qi5vetHF6_3epubYeoSZ3KFopboxrbjDUSId7SLbrP8,4382
|
|
17
|
+
pinexq/procon/jobmanagement/__init__.py,sha256=W4UC5s70RzL_EwnEuvXsXS7Hph2awsblCQvZ_ROM-DQ,190
|
|
18
|
+
pinexq/procon/jobmanagement/api_helpers.py,sha256=xEtNEOEgQUtIIz6wtK-fiJThfgCIdLBQcKMb9L394VU,10224
|
|
19
|
+
pinexq/procon/remote/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
+
pinexq/procon/remote/messages.py,sha256=Mr6rz3VRxRxUM3l2Y0vU7CDmpc9Mi1NuhvEndoZbKEo,6904
|
|
21
|
+
pinexq/procon/remote/rabbitmq.py,sha256=2Kwsct35sN0pameRVCDER3WlPgnCI8YzCq9dlbGQgw8,16070
|
|
22
|
+
pinexq/procon/runtime/__init__.py,sha256=K-pSghTgjHAJJSeJpG8F_sYHDp8j3CL2X6izHS76DT0,119
|
|
23
|
+
pinexq/procon/runtime/foreman.py,sha256=YrKA8u1UieOU1aM22sbTv7PuppwuP8KII7WuDy7aQJc,5022
|
|
24
|
+
pinexq/procon/runtime/job.py,sha256=HDQRGIGj12McUQQ6F8bB2E_Wkuu-M-sf1in1MCxy1OQ,13883
|
|
25
|
+
pinexq/procon/runtime/settings.py,sha256=owSCPBEEpaf7zSDMdgy-jX_ZQ5--A7705nZcsPFx2sU,444
|
|
26
|
+
pinexq/procon/runtime/tool.py,sha256=PJ9Gtz3OuLvtOopPz955qJJvrrRj1ZyXKNYKIPPgQAc,653
|
|
27
|
+
pinexq/procon/runtime/worker.py,sha256=JOYyoZUoIOmVV-sK5fkmSouAiYU4M1pB5F6_XNektlA,17845
|
|
28
|
+
pinexq/procon/step/__init__.py,sha256=QZCtYx2uumBdzfZxeLoVlYqZS6l8nnVewqOtzYucblw,92
|
|
29
|
+
pinexq/procon/step/introspection.py,sha256=OF1hSherQGg9i4-WnyudUvslu0CDaxRzUrV5iKrD6K4,9814
|
|
30
|
+
pinexq/procon/step/schema.py,sha256=TlPjn1ETx3bTTy0Gb_6vU0RZ1QW4OIC6hYmBjWNhxiE,3664
|
|
31
|
+
pinexq/procon/step/step.py,sha256=cmErYmKzEilcMPVmMtSJMY7zGd1rb23x5VTVzmZU_hM,4862
|
|
32
|
+
pinexq/procon/step/versioning.py,sha256=2RzEtz0Y5_yrMFw8hUXVdagLUDgTtD5LqmrZnLogpJc,3304
|
|
33
|
+
pinexq_procon-2.1.0.dev3.dist-info/WHEEL,sha256=ZyFSCYkV2BrxH6-HRVRg3R9Fo7MALzer9KiPYqNxSbo,79
|
|
34
|
+
pinexq_procon-2.1.0.dev3.dist-info/METADATA,sha256=gWOhHZbbIU97BepESzg4mTA2_GvLHZ__ZbTzYBNl_dk,3038
|
|
35
|
+
pinexq_procon-2.1.0.dev3.dist-info/RECORD,,
|