digitalkin 0.1.1__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.
Files changed (59) hide show
  1. digitalkin/__init__.py +18 -0
  2. digitalkin/__version__.py +11 -0
  3. digitalkin/grpc/__init__.py +31 -0
  4. digitalkin/grpc/_base_server.py +488 -0
  5. digitalkin/grpc/module_server.py +233 -0
  6. digitalkin/grpc/module_servicer.py +304 -0
  7. digitalkin/grpc/registry_server.py +63 -0
  8. digitalkin/grpc/registry_servicer.py +451 -0
  9. digitalkin/grpc/utils/exceptions.py +33 -0
  10. digitalkin/grpc/utils/factory.py +178 -0
  11. digitalkin/grpc/utils/models.py +169 -0
  12. digitalkin/grpc/utils/types.py +24 -0
  13. digitalkin/logger.py +17 -0
  14. digitalkin/models/__init__.py +11 -0
  15. digitalkin/models/module/__init__.py +5 -0
  16. digitalkin/models/module/module.py +31 -0
  17. digitalkin/models/services/__init__.py +6 -0
  18. digitalkin/models/services/cost.py +53 -0
  19. digitalkin/models/services/storage.py +10 -0
  20. digitalkin/modules/__init__.py +7 -0
  21. digitalkin/modules/_base_module.py +177 -0
  22. digitalkin/modules/archetype_module.py +14 -0
  23. digitalkin/modules/job_manager.py +158 -0
  24. digitalkin/modules/tool_module.py +14 -0
  25. digitalkin/modules/trigger_module.py +14 -0
  26. digitalkin/py.typed +0 -0
  27. digitalkin/services/__init__.py +28 -0
  28. digitalkin/services/agent/__init__.py +6 -0
  29. digitalkin/services/agent/agent_strategy.py +22 -0
  30. digitalkin/services/agent/default_agent.py +16 -0
  31. digitalkin/services/cost/__init__.py +6 -0
  32. digitalkin/services/cost/cost_strategy.py +15 -0
  33. digitalkin/services/cost/default_cost.py +13 -0
  34. digitalkin/services/default_service.py +13 -0
  35. digitalkin/services/development_service.py +10 -0
  36. digitalkin/services/filesystem/__init__.py +6 -0
  37. digitalkin/services/filesystem/default_filesystem.py +29 -0
  38. digitalkin/services/filesystem/filesystem_strategy.py +31 -0
  39. digitalkin/services/identity/__init__.py +6 -0
  40. digitalkin/services/identity/default_identity.py +15 -0
  41. digitalkin/services/identity/identity_strategy.py +12 -0
  42. digitalkin/services/registry/__init__.py +6 -0
  43. digitalkin/services/registry/default_registry.py +13 -0
  44. digitalkin/services/registry/registry_strategy.py +17 -0
  45. digitalkin/services/service_provider.py +27 -0
  46. digitalkin/services/snapshot/__init__.py +6 -0
  47. digitalkin/services/snapshot/default_snapshot.py +39 -0
  48. digitalkin/services/snapshot/snapshot_strategy.py +31 -0
  49. digitalkin/services/storage/__init__.py +6 -0
  50. digitalkin/services/storage/default_storage.py +91 -0
  51. digitalkin/services/storage/grpc_storage.py +207 -0
  52. digitalkin/services/storage/storage_strategy.py +42 -0
  53. digitalkin/utils/__init__.py +1 -0
  54. digitalkin/utils/arg_parser.py +136 -0
  55. digitalkin-0.1.1.dist-info/METADATA +588 -0
  56. digitalkin-0.1.1.dist-info/RECORD +59 -0
  57. digitalkin-0.1.1.dist-info/WHEEL +5 -0
  58. digitalkin-0.1.1.dist-info/licenses/LICENSE +430 -0
  59. digitalkin-0.1.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,14 @@
1
+ """ToolModule extends BaseModule to implement specific module types."""
2
+
3
+ from abc import ABC
4
+
5
+ from ._base_module import BaseModule
6
+
7
+
8
+ class ToolModule(BaseModule, ABC):
9
+ """ToolModule extends BaseModule to implement specific module types."""
10
+
11
+ def __init__(self, metadata):
12
+ """Initialize the module with the given metadata."""
13
+ super().__init__(metadata)
14
+ self.capabilities = ["tool"]
@@ -0,0 +1,14 @@
1
+ """TriggerModule extends BaseModule to implement specific module types."""
2
+
3
+ from abc import ABC
4
+
5
+ from ._base_module import BaseModule
6
+
7
+
8
+ class TriggerModule(BaseModule, ABC):
9
+ """TriggerModule extends BaseModule to implement specific module types."""
10
+
11
+ def __init__(self, metadata):
12
+ """Initialize the module with the given metadata."""
13
+ super().__init__(metadata)
14
+ self.capabilities = ["trigger"]
digitalkin/py.typed ADDED
File without changes
@@ -0,0 +1,28 @@
1
+ """This package contains the abstract base class for all services."""
2
+
3
+ from .agent import AgentStrategy, DefaultAgent
4
+ from .cost import CostStrategy, DefaultCost
5
+ from .filesystem import DefaultFilesystem, FilesystemStrategy
6
+ from .identity import DefaultIdentity, IdentityStrategy
7
+ from .registry import DefaultRegistry, RegistryStrategy
8
+ from .service_provider import ServiceProvider
9
+ from .snapshot import DefaultSnapshot, SnapshotStrategy
10
+ from .storage import DefaultStorage, StorageStrategy
11
+
12
+ __all__ = [
13
+ "AgentStrategy",
14
+ "CostStrategy",
15
+ "DefaultAgent",
16
+ "DefaultCost",
17
+ "DefaultFilesystem",
18
+ "DefaultIdentity",
19
+ "DefaultRegistry",
20
+ "DefaultSnapshot",
21
+ "DefaultStorage",
22
+ "FilesystemStrategy",
23
+ "IdentityStrategy",
24
+ "RegistryStrategy",
25
+ "ServiceProvider",
26
+ "SnapshotStrategy",
27
+ "StorageStrategy",
28
+ ]
@@ -0,0 +1,6 @@
1
+ """This module is responsible for handling the agent services."""
2
+
3
+ from .agent_strategy import AgentStrategy
4
+ from .default_agent import DefaultAgent
5
+
6
+ __all__ = ["AgentStrategy", "DefaultAgent"]
@@ -0,0 +1,22 @@
1
+ """This module contains the abstract base class for agent strategies."""
2
+
3
+ from abc import ABC, abstractmethod
4
+
5
+
6
+ class AgentStrategy(ABC):
7
+ """Abstract base class for agent strategies."""
8
+
9
+ @abstractmethod
10
+ def __init__(self) -> None:
11
+ """Initialize the agent strategy."""
12
+ raise NotImplementedError
13
+
14
+ @abstractmethod
15
+ def start(self) -> None:
16
+ """Start the agent."""
17
+ raise NotImplementedError
18
+
19
+ @abstractmethod
20
+ def stop(self) -> None:
21
+ """Stop the agent."""
22
+ raise NotImplementedError
@@ -0,0 +1,16 @@
1
+ """Default agent implementation for the agent service."""
2
+
3
+ from .agent_strategy import AgentStrategy
4
+
5
+
6
+ class DefaultAgent(AgentStrategy):
7
+ """Default agent implementation for the agent service."""
8
+
9
+ def __init__(self) -> None:
10
+ """Initialize the default agent."""
11
+
12
+ def start(self) -> None:
13
+ """Start the agent."""
14
+
15
+ def stop(self) -> None:
16
+ """Stop the agent."""
@@ -0,0 +1,6 @@
1
+ """This module is responsible for handling the cost services."""
2
+
3
+ from .cost_strategy import CostStrategy
4
+ from .default_cost import DefaultCost
5
+
6
+ __all__ = ["CostStrategy", "DefaultCost"]
@@ -0,0 +1,15 @@
1
+ """This module contains the abstract base class for cost strategies."""
2
+
3
+ from abc import ABC, abstractmethod
4
+
5
+
6
+ class CostStrategy(ABC):
7
+ """Abstract base class for cost strategies."""
8
+
9
+ @abstractmethod
10
+ def __init__(self) -> None:
11
+ """Initialize the cost strategy."""
12
+
13
+ @abstractmethod
14
+ def register_cost(self, data: dict[str, str]) -> None:
15
+ """Register a new cost."""
@@ -0,0 +1,13 @@
1
+ """Default cost."""
2
+
3
+ from .cost_strategy import CostStrategy
4
+
5
+
6
+ class DefaultCost(CostStrategy):
7
+ """Default cost strategy."""
8
+
9
+ def __init__(self) -> None:
10
+ """Initialize the cost strategy."""
11
+
12
+ def register_cost(self, data: dict[str, str]) -> None:
13
+ """Register a new cost."""
@@ -0,0 +1,13 @@
1
+ """Default entrypoint for a DigitalKin module's services."""
2
+
3
+ from digitalkin.services.service_provider import ServiceProvider
4
+ from digitalkin.services.storage.default_storage import DefaultStorage
5
+
6
+
7
+ class DefaultServiceProvider(ServiceProvider):
8
+ """Service Instance used as default service in a Module.
9
+
10
+ Currently only allow the default (local) database service.
11
+ """
12
+
13
+ storage = DefaultStorage()
@@ -0,0 +1,10 @@
1
+ """Dev entrypoint for a DigitalKin module's services."""
2
+
3
+ from digitalkin.services.service_provider import ServiceProvider
4
+ from digitalkin.services.storage.grpc_storage import GrpcStorage
5
+
6
+
7
+ class DevelopmentServiceProvider(ServiceProvider):
8
+ """Service Instance used as a development service in a Module."""
9
+
10
+ storage = GrpcStorage()
@@ -0,0 +1,6 @@
1
+ """This module is responsible for handling the filesystem services."""
2
+
3
+ from .default_filesystem import DefaultFilesystem
4
+ from .filesystem_strategy import FilesystemStrategy
5
+
6
+ __all__ = ["DefaultFilesystem", "FilesystemStrategy"]
@@ -0,0 +1,29 @@
1
+ """Default filesystem."""
2
+
3
+ from typing import Any
4
+
5
+ from .filesystem_strategy import FilesystemStrategy
6
+
7
+
8
+ class DefaultFilesystem(FilesystemStrategy):
9
+ """Default state filesystem strategy."""
10
+
11
+ def create(self, data: dict[str, Any]) -> str:
12
+ """Create a new file in the file system."""
13
+ raise NotImplementedError
14
+
15
+ def get(self, data: dict[str, Any]) -> list[dict[str, Any]]:
16
+ """Get files from the file system."""
17
+ raise NotImplementedError
18
+
19
+ def update(self, data: dict[str, Any]) -> int:
20
+ """Update files in the file system."""
21
+ raise NotImplementedError
22
+
23
+ def delete(self, data: dict[str, Any]) -> int:
24
+ """Delete files from the file system."""
25
+ raise NotImplementedError
26
+
27
+ def get_all(self) -> list[dict[str, Any]]:
28
+ """Get all files from the file system."""
29
+ raise NotImplementedError
@@ -0,0 +1,31 @@
1
+ """This module contains the abstract base class for filesystem strategies."""
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import Any
5
+
6
+
7
+ class FilesystemStrategy(ABC):
8
+ """Abstract base class for file system strategies."""
9
+
10
+ def __init__(self) -> None:
11
+ """Initialize the file system strategy."""
12
+
13
+ @abstractmethod
14
+ def create(self, data: dict[str, Any]) -> str:
15
+ """Create a new file in the file system."""
16
+
17
+ @abstractmethod
18
+ def get(self, data: dict[str, Any]) -> list[dict[str, Any]]:
19
+ """Get files from the file system."""
20
+
21
+ @abstractmethod
22
+ def update(self, data: dict[str, Any]) -> int:
23
+ """Update files in the file system."""
24
+
25
+ @abstractmethod
26
+ def delete(self, data: dict[str, Any]) -> int:
27
+ """Delete files from the file system."""
28
+
29
+ @abstractmethod
30
+ def get_all(self) -> list[dict[str, Any]]:
31
+ """Get all files from the file system."""
@@ -0,0 +1,6 @@
1
+ """This module is responsible for handling the identity service."""
2
+
3
+ from .default_identity import DefaultIdentity
4
+ from .identity_strategy import IdentityStrategy
5
+
6
+ __all__ = ["DefaultIdentity", "IdentityStrategy"]
@@ -0,0 +1,15 @@
1
+ """Default identity."""
2
+
3
+ from .identity_strategy import IdentityStrategy
4
+
5
+
6
+ class DefaultIdentity(IdentityStrategy):
7
+ """DefaultIdentity is the default identity strategy."""
8
+
9
+ async def get_identity(self) -> str: # noqa: PLR6301
10
+ """Get the identity.
11
+
12
+ Returns:
13
+ str: The identity
14
+ """
15
+ return "default_identity"
@@ -0,0 +1,12 @@
1
+ """This module contains the abstract base class for identity strategies."""
2
+
3
+ from abc import ABC, abstractmethod
4
+
5
+
6
+ class IdentityStrategy(ABC):
7
+ """IdentityStrategy is the abstract base class for all identity strategies."""
8
+
9
+ @abstractmethod
10
+ async def get_identity(self) -> str:
11
+ """Get the identity."""
12
+ raise NotImplementedError
@@ -0,0 +1,6 @@
1
+ """This module is responsible for handling the registry service."""
2
+
3
+ from .default_registry import DefaultRegistry
4
+ from .registry_strategy import RegistryStrategy
5
+
6
+ __all__ = ["DefaultRegistry", "RegistryStrategy"]
@@ -0,0 +1,13 @@
1
+ """Default registry."""
2
+
3
+ from .registry_strategy import RegistryStrategy
4
+
5
+
6
+ class DefaultRegistry(RegistryStrategy):
7
+ """Default registry strategy."""
8
+
9
+ def __init__(self) -> None:
10
+ """Initialize the registry strategy."""
11
+
12
+ def get_by_id(self, module_id: str) -> None:
13
+ """Get services from the registry."""
@@ -0,0 +1,17 @@
1
+ """This module contains the abstract base class for registry strategies."""
2
+
3
+ from abc import ABC, abstractmethod
4
+
5
+
6
+ class RegistryStrategy(ABC):
7
+ """Abstract base class for registry strategies."""
8
+
9
+ @abstractmethod
10
+ def __init__(self) -> None:
11
+ """Initialize the registry strategy."""
12
+ raise NotImplementedError
13
+
14
+ @abstractmethod
15
+ def get_by_id(self, module_id: str) -> None:
16
+ """Get services from the registry."""
17
+ raise NotImplementedError
@@ -0,0 +1,27 @@
1
+ """Service Provider definitions."""
2
+
3
+ from typing import ClassVar
4
+
5
+ from pydantic import BaseModel
6
+
7
+ from digitalkin.services.agent.agent_strategy import AgentStrategy
8
+ from digitalkin.services.cost.cost_strategy import CostStrategy
9
+ from digitalkin.services.filesystem.filesystem_strategy import FilesystemStrategy
10
+ from digitalkin.services.identity.identity_strategy import IdentityStrategy
11
+ from digitalkin.services.registry.registry_strategy import RegistryStrategy
12
+ from digitalkin.services.snapshot.snapshot_strategy import SnapshotStrategy
13
+ from digitalkin.services.storage.storage_strategy import StorageStrategy
14
+
15
+
16
+ class ServiceProvider(BaseModel):
17
+ """Service class describing the available services in a Module."""
18
+
19
+ storage: ClassVar[StorageStrategy]
20
+ cost: ClassVar[CostStrategy]
21
+ snapshot: ClassVar[SnapshotStrategy]
22
+ registry: ClassVar[RegistryStrategy]
23
+ filesystem: ClassVar[FilesystemStrategy]
24
+ agent: ClassVar[AgentStrategy]
25
+ identity: ClassVar[IdentityStrategy]
26
+
27
+ model_config = {"arbitrary_types_allowed": True}
@@ -0,0 +1,6 @@
1
+ """This module is responsible for handling the snapshot service."""
2
+
3
+ from .default_snapshot import DefaultSnapshot
4
+ from .snapshot_strategy import SnapshotStrategy
5
+
6
+ __all__ = ["DefaultSnapshot", "SnapshotStrategy"]
@@ -0,0 +1,39 @@
1
+ """Default snapshot."""
2
+
3
+ from typing import Any
4
+
5
+ from .snapshot_strategy import SnapshotStrategy
6
+
7
+
8
+ class DefaultSnapshot(SnapshotStrategy):
9
+ """Default snapshot strategy."""
10
+
11
+ def create(self, data: dict[str, Any]) -> str: # noqa: ARG002, PLR6301
12
+ """Create a new snapshot in the file system.
13
+
14
+ Returns:
15
+ str: The ID of the new snapshot
16
+ """
17
+ return "1"
18
+
19
+ def get(self, data: dict[str, Any]) -> None:
20
+ """Get snapshots from the file system."""
21
+
22
+ def update(self, data: dict[str, Any]) -> int: # noqa: ARG002, PLR6301
23
+ """Update snapshots in the file system.
24
+
25
+ Returns:
26
+ int: The number of snapshots updated
27
+ """
28
+ return 1
29
+
30
+ def delete(self, data: dict[str, Any]) -> int: # noqa: ARG002, PLR6301
31
+ """Delete snapshots from the file system.
32
+
33
+ Returns:
34
+ int: The number of snapshots deleted
35
+ """
36
+ return 1
37
+
38
+ def get_all(self) -> None:
39
+ """Get all snapshots from the file system."""
@@ -0,0 +1,31 @@
1
+ """This module contains the abstract base class for snapshot strategies."""
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import Any
5
+
6
+
7
+ class SnapshotStrategy(ABC):
8
+ """Abstract base class for snapshot strategies."""
9
+
10
+ def __init__(self) -> None:
11
+ """Initialize the snapshot strategy."""
12
+
13
+ @abstractmethod
14
+ def create(self, data: dict[str, Any]) -> str:
15
+ """Create a new snapshot in the file system."""
16
+
17
+ @abstractmethod
18
+ def get(self, data: dict[str, Any]) -> None:
19
+ """Get snapshots from the file system."""
20
+
21
+ @abstractmethod
22
+ def update(self, data: dict[str, Any]) -> int:
23
+ """Update snapshots in the file system."""
24
+
25
+ @abstractmethod
26
+ def delete(self, data: dict[str, Any]) -> int:
27
+ """Delete snapshots from the file system."""
28
+
29
+ @abstractmethod
30
+ def get_all(self) -> None:
31
+ """Get all snapshots from the file system."""
@@ -0,0 +1,6 @@
1
+ """This module is responsible for handling the storage service."""
2
+
3
+ from .default_storage import DefaultStorage
4
+ from .storage_strategy import StorageStrategy
5
+
6
+ __all__ = ["DefaultStorage", "StorageStrategy"]
@@ -0,0 +1,91 @@
1
+ """This module implements the default storage strategy."""
2
+
3
+ import logging
4
+ from typing import Any
5
+
6
+ from .storage_strategy import StorageStrategy
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class DefaultStorage(StorageStrategy):
12
+ """This class implements the default storage strategy."""
13
+
14
+ storage: dict[str, list[dict[str, Any]]]
15
+
16
+ def __init__(self) -> None:
17
+ """Initialize the default storage strategy."""
18
+ super().__init__()
19
+ self.storage = {"setups": []}
20
+
21
+ def connect(self) -> bool: # noqa: PLR6301
22
+ """Establish connection to the database.
23
+
24
+ Returns:
25
+ bool: True if the connection is successful, False otherwise
26
+ """
27
+ return True
28
+
29
+ def disconnect(self) -> bool: # noqa: PLR6301
30
+ """Close connection to the database.
31
+
32
+ Returns:
33
+ bool: True if the connection is closed, False otherwise
34
+ """
35
+ return True
36
+
37
+ def create(self, table: str, data: dict[str, Any]) -> str:
38
+ """Create a new record in the database.
39
+
40
+ Returns:
41
+ str: The ID of the new record
42
+ """
43
+ if table not in self.storage:
44
+ self.storage[table] = []
45
+ self.storage[table].append(data["data"])
46
+ logger.info("CREATE %s:%s succesfull", table, data["data"])
47
+ return f"{len(self.storage[table]) - 1}"
48
+
49
+ def get(self, table: str, data: dict[str, Any]) -> list[dict[str, Any]]:
50
+ """Get records from the database.
51
+
52
+ Returns:
53
+ list[dict[str, Any]]: The list of records
54
+ """
55
+ logger.info("GET table = %s: keys = %s", table, data["keys"])
56
+ if table not in self.storage:
57
+ logger.info("GET table = %s: TABLE DOESN'T EXIST", table)
58
+ return []
59
+ return [self.storage[table][int(key)] for key in data["keys"]]
60
+
61
+ def update(self, table: str, data: dict[str, Any]) -> int:
62
+ """Update records in the database.
63
+
64
+ Returns:
65
+ int: The number of records updated
66
+ """
67
+ if table not in self.storage:
68
+ logger.info("UPDATE table = %s: TABLE DOESN'T EXIST", table)
69
+ return 0
70
+ self.storage[table][data["update_id"]] = data["update_value"]
71
+ return 1
72
+
73
+ def delete(self, table: str, data: dict[str, Any]) -> int:
74
+ """Delete records from the database.
75
+
76
+ Returns:
77
+ int: The number of records deleted
78
+ """
79
+ if table not in self.storage:
80
+ logger.info("UPDATE table = %s: TABLE DOESN'T EXIST", table)
81
+ return 0
82
+ del self.storage[table][data["delete_id"]]
83
+ return 1
84
+
85
+ def get_all(self) -> dict[str, list[dict[str, Any]]]:
86
+ """Get all records from the database.
87
+
88
+ Returns:
89
+ dict[str, list[dict[str, Any]]]: table with respective list of records
90
+ """
91
+ return self.storage