acex-devkit 1.0.0__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.
@@ -0,0 +1,17 @@
1
+ """ACE-X DevKit - Development kit for building ACE-X drivers and plugins."""
2
+
3
+ __version__ = "1.0.0"
4
+
5
+ from acex_devkit.drivers import (
6
+ NetworkElementDriver,
7
+ TransportBase,
8
+ RendererBase,
9
+ ParserBase,
10
+ )
11
+
12
+ __all__ = [
13
+ "NetworkElementDriver",
14
+ "TransportBase",
15
+ "RendererBase",
16
+ "ParserBase",
17
+ ]
@@ -0,0 +1,15 @@
1
+ """Base classes for ACE-X network element drivers."""
2
+
3
+ from acex_devkit.drivers.base import (
4
+ NetworkElementDriver,
5
+ TransportBase,
6
+ RendererBase,
7
+ ParserBase,
8
+ )
9
+
10
+ __all__ = [
11
+ "NetworkElementDriver",
12
+ "TransportBase",
13
+ "RendererBase",
14
+ "ParserBase",
15
+ ]
@@ -0,0 +1,123 @@
1
+ """Driver base classes for ACE-X network element drivers."""
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import Any, Dict
5
+
6
+ from acex_devkit.models.logical_node import LogicalNode
7
+
8
+
9
+ class ParserBase(ABC):
10
+ """Base class for configuration parsers."""
11
+
12
+ @abstractmethod
13
+ def parse(self, configuration: str) -> Any:
14
+ """Parse device configuration into a structured model.
15
+
16
+ Args:
17
+ configuration: Raw configuration string from device
18
+
19
+ Returns:
20
+ Parsed configuration model
21
+ """
22
+ pass
23
+
24
+
25
+ class RendererBase(ABC):
26
+ """Base class for configuration renderers."""
27
+
28
+ @abstractmethod
29
+ def render(self, model: Dict[str, Any], asset: Any = None) -> Any:
30
+ """Render configuration model to device-specific format.
31
+
32
+ Args:
33
+ model: Device-agnostic configuration model
34
+ asset: Optional asset context
35
+
36
+ Returns:
37
+ Device-specific configuration (e.g., string, XML tree)
38
+ """
39
+ pass
40
+
41
+
42
+ class TransportBase(ABC):
43
+ """Base class for device transport/communication."""
44
+
45
+ @abstractmethod
46
+ def connect(self) -> None:
47
+ """Establish connection to the device."""
48
+ pass
49
+
50
+ @abstractmethod
51
+ def send(self, payload: Any) -> None:
52
+ """Send configuration to the device.
53
+
54
+ Args:
55
+ payload: Configuration payload to send
56
+ """
57
+ pass
58
+
59
+ @abstractmethod
60
+ def verify(self) -> bool:
61
+ """Verify configuration was applied correctly.
62
+
63
+ Returns:
64
+ True if verification succeeded, False otherwise
65
+ """
66
+ pass
67
+
68
+ @abstractmethod
69
+ def rollback(self) -> None:
70
+ """Rollback configuration if verification fails."""
71
+ pass
72
+
73
+
74
+ class NetworkElementDriver:
75
+ """Base class for network element drivers.
76
+
77
+ Combines renderer, transport, and parser to provide complete
78
+ configuration management for network devices.
79
+
80
+ Attributes:
81
+ renderer_class: Renderer class to use (must be set in subclass)
82
+ transport_class: Transport class to use (must be set in subclass)
83
+ parser_class: Parser class to use (must be set in subclass)
84
+ """
85
+
86
+ renderer_class = None
87
+ transport_class = None
88
+ parser_class = None
89
+
90
+ def __init__(self):
91
+ """Initialize driver with renderer, transport, and parser instances."""
92
+ if self.renderer_class is None or self.transport_class is None or self.parser_class is None:
93
+ raise NotImplementedError(
94
+ "renderer_class, transport_class, and parser_class must be set in subclass"
95
+ )
96
+ self.renderer = self.renderer_class()
97
+ self.transport = self.transport_class()
98
+ self.parser = self.parser_class()
99
+
100
+ @abstractmethod
101
+ def render(self, logical_node: LogicalNode, asset: Any = None) -> Any:
102
+ """Render logical node to device configuration.
103
+
104
+ Args:
105
+ logical_node: Logical node containing configuration
106
+ asset: Optional asset context
107
+
108
+ Returns:
109
+ Rendered configuration
110
+ """
111
+ return self.renderer.render(logical_node.model_dump(), asset)
112
+
113
+ @abstractmethod
114
+ def parse(self, configuration: str) -> Any:
115
+ """Parse device configuration.
116
+
117
+ Args:
118
+ configuration: Raw device configuration
119
+
120
+ Returns:
121
+ Parsed configuration model
122
+ """
123
+ return self.parser.parse(configuration)
@@ -0,0 +1,53 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Dict
3
+
4
+ class ParserBase(ABC):
5
+ @abstractmethod
6
+ def parse(self, model: Dict[str, Any]) -> Any:
7
+ """Parsar running-config"""
8
+
9
+ class RendererBase(ABC):
10
+ @abstractmethod
11
+ def render(self, model: Dict[str, Any]) -> Any:
12
+ """Tar en device‑agnostisk konfigurationsmodell och returnerar
13
+ en transport‑specifik representation (t.ex. string, XML‑tree…)."""
14
+
15
+ class TransportBase(ABC):
16
+ @abstractmethod
17
+ def connect(self) -> None: ...
18
+
19
+ @abstractmethod
20
+ def send(self, payload: Any) -> None: ...
21
+
22
+ @abstractmethod
23
+ def verify(self) -> bool: ...
24
+
25
+ @abstractmethod
26
+ def rollback(self) -> None: ...
27
+
28
+ class NetworkElementDriver:
29
+ """Kombinerar renderer + transport – exponeras som en plugin."""
30
+ renderer_class = None
31
+ transport_class = None
32
+ parser_class = None
33
+
34
+ def __init__(self):
35
+ if self.renderer_class is None or self.transport_class is None or self.parser_class is None:
36
+ raise NotImplementedError("renderer_class and transport_class must be set in subclass")
37
+ self.renderer = self.renderer_class()
38
+ self.transport = self.transport_class()
39
+ self.parser = self.parser_class()
40
+
41
+ @abstractmethod
42
+ def render(self, logical_node: "LogicalNode") -> Any:
43
+ """Tar en LogicalNode och returnerar en konfigurationsrepresentation."""
44
+ return self.renderer.render(logical_node.model_dump())
45
+
46
+
47
+ # def apply(self, model: Dict[str, Any]) -> None:
48
+ # cfg = self.renderer.render(model)
49
+ # self.transport.connect()
50
+ # self.transport.send(cfg)
51
+ # if not self.transport.verify():
52
+ # self.transport.rollback()
53
+ # raise RuntimeError("Verification failed – rollback executed")
@@ -0,0 +1,41 @@
1
+ """Common exceptions for ACE-X DevKit."""
2
+
3
+
4
+ class AcexDevkitException(Exception):
5
+ """Base exception for ACE-X DevKit."""
6
+ pass
7
+
8
+
9
+ class MethodNotImplemented(AcexDevkitException):
10
+ """Raised when a required method is not implemented."""
11
+ pass
12
+
13
+
14
+ class DriverException(AcexDevkitException):
15
+ """Base exception for driver-related errors."""
16
+ pass
17
+
18
+
19
+ class ConnectionError(DriverException):
20
+ """Raised when device connection fails."""
21
+ pass
22
+
23
+
24
+ class ConfigurationError(DriverException):
25
+ """Raised when configuration application fails."""
26
+ pass
27
+
28
+
29
+ class VerificationError(DriverException):
30
+ """Raised when configuration verification fails."""
31
+ pass
32
+
33
+
34
+ class RenderingError(DriverException):
35
+ """Raised when configuration rendering fails."""
36
+ pass
37
+
38
+
39
+ class ParsingError(DriverException):
40
+ """Raised when configuration parsing fails."""
41
+ pass
@@ -0,0 +1,7 @@
1
+ """Models for ACE-X DevKit."""
2
+
3
+ # TODO: Move all models to this package
4
+ # TODO: Move all base classes to this package
5
+
6
+
7
+ __all__ = []
@@ -0,0 +1,42 @@
1
+ """Type definitions and protocols for ACE-X DevKit."""
2
+
3
+ from typing import Protocol, Any, Dict, runtime_checkable
4
+
5
+
6
+ @runtime_checkable
7
+ class Renderable(Protocol):
8
+ """Protocol for objects that can be rendered to configuration."""
9
+
10
+ def render(self, model: Dict[str, Any], asset: Any = None) -> Any:
11
+ """Render configuration."""
12
+ ...
13
+
14
+
15
+ @runtime_checkable
16
+ class Parseable(Protocol):
17
+ """Protocol for objects that can parse configuration."""
18
+
19
+ def parse(self, configuration: str) -> Any:
20
+ """Parse configuration."""
21
+ ...
22
+
23
+
24
+ @runtime_checkable
25
+ class Transportable(Protocol):
26
+ """Protocol for objects that can transport configuration."""
27
+
28
+ def connect(self) -> None:
29
+ """Connect to device."""
30
+ ...
31
+
32
+ def send(self, payload: Any) -> None:
33
+ """Send configuration."""
34
+ ...
35
+
36
+ def verify(self) -> bool:
37
+ """Verify configuration."""
38
+ ...
39
+
40
+ def rollback(self) -> None:
41
+ """Rollback configuration."""
42
+ ...
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.4
2
+ Name: acex-devkit
3
+ Version: 1.0.0
4
+ Summary: ACE-X DevKit - Development kit for building ACE-X drivers and plugins
5
+ License: AGPL-3.0
6
+ Keywords: automation,devkit,sdk,drivers,plugins
7
+ Author: Johan Lahti
8
+ Author-email: johan.lahti@acebit.se
9
+ Requires-Python: >=3.13,<4.0
10
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Requires-Dist: pydantic (>=2.12.5,<3.0.0)
15
+ Requires-Dist: typing-extensions (>=4.0.0,<5.0.0)
16
+ Project-URL: Homepage, https://github.com/acex-labs/acex
17
+ Project-URL: Repository, https://github.com/acex-labs/acex
18
+ Description-Content-Type: text/markdown
19
+
20
+ # ACE-X DevKit
21
+
22
+ Development kit for building ACE-X drivers and plugins.
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pip install acex-devkit
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ### Building a Network Element Driver
33
+
34
+ ```python
35
+ from acex_devkit.drivers import NetworkElementDriver, TransportBase, RendererBase, ParserBase
36
+ from acex_devkit.models import ComposedConfiguration
37
+
38
+ class MyRenderer(RendererBase):
39
+ def render(self, model: dict) -> str:
40
+ # Implement your rendering logic
41
+ pass
42
+
43
+ class MyTransport(TransportBase):
44
+ def connect(self) -> None:
45
+ # Implement connection logic
46
+ pass
47
+
48
+ def send(self, payload: Any) -> None:
49
+ # Implement send logic
50
+ pass
51
+
52
+ def verify(self) -> bool:
53
+ # Implement verification logic
54
+ return True
55
+
56
+ def rollback(self) -> None:
57
+ # Implement rollback logic
58
+ pass
59
+
60
+ class MyParser(ParserBase):
61
+ def parse(self, configuration: str) -> ComposedConfiguration:
62
+ # Implement parsing logic
63
+ pass
64
+
65
+ class MyDriver(NetworkElementDriver):
66
+ renderer_class = MyRenderer
67
+ transport_class = MyTransport
68
+ parser_class = MyParser
69
+
70
+ def render(self, configuration: ComposedConfiguration, asset):
71
+ return self.renderer.render(configuration, asset)
72
+
73
+ def parse(self, configuration: str) -> ComposedConfiguration:
74
+ return self.parser.parse(configuration)
75
+ ```
76
+
77
+ ## Package Contents
78
+
79
+ - **models**: Common data models (Asset, LogicalNode, ComposedConfiguration, etc.)
80
+ - **drivers**: Base classes for building network element drivers
81
+ - **exceptions**: Common exceptions
82
+ - **types**: Type aliases and protocols
83
+
84
+ ## License
85
+
86
+ AGPL-3.0
87
+
@@ -0,0 +1,10 @@
1
+ acex_devkit/__init__.py,sha256=ANPGzAzDVEwQ24CvLvvg6pl3YH5K-Ce7PWWKtNDMOqc,318
2
+ acex_devkit/drivers/__init__.py,sha256=dKTc3QNJu3x49nZaf53M95k524ODeK544B90PUl9y1I,277
3
+ acex_devkit/drivers/base.py,sha256=njOEmzZ2glh6rNo9OHtwx7g-WL-vOVftc2akx1kMP2U,3557
4
+ acex_devkit/drivers/base_driver.py,sha256=p4462s8CFeZxLIM9kSJfK5viaXfGg_k3s0MvRJMQYIA,1800
5
+ acex_devkit/exceptions/__init__.py,sha256=KHfVL1rD1dTznMTO13t9bTsh32RdfzRilXovdXcXuLg,879
6
+ acex_devkit/models/__init__.py,sha256=KsrEEDA5p2VrT2FZXxZyTaFckQcFge4o9d6S5ZRIYKs,133
7
+ acex_devkit/types/__init__.py,sha256=4dgCg5YvI1GUUxliCgisIZWsOsXtSof0NtKmma8y6tM,1027
8
+ acex_devkit-1.0.0.dist-info/METADATA,sha256=2Ox2V9e4pquO9lRBPrQSAQsaKLGA69rzn3vLYe9ozXE,2405
9
+ acex_devkit-1.0.0.dist-info/WHEEL,sha256=kJCRJT_g0adfAJzTx2GUMmS80rTJIVHRCfG0DQgLq3o,88
10
+ acex_devkit-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.3.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any