spaceforge 1.1.7__py3-none-any.whl → 1.2.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.
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.1.7'
32
- __version_tuple__ = version_tuple = (1, 1, 7)
31
+ __version__ = version = '1.2.1'
32
+ __version_tuple__ = version_tuple = (1, 2, 1)
33
33
 
34
34
  __commit_id__ = commit_id = None
spaceforge/cls.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import uuid
2
- from typing import Dict, List, Literal, Optional
2
+ from typing import Dict, List, Literal, Optional, Union
3
3
 
4
4
  from pydantic import Field
5
5
  from pydantic.dataclasses import dataclass as pydantic_dataclass
@@ -12,6 +12,12 @@ BinaryType = Literal[
12
12
  "arm64",
13
13
  ]
14
14
 
15
+ ParameterType = Literal[
16
+ "string",
17
+ "number",
18
+ "boolean",
19
+ ]
20
+
15
21
 
16
22
  @pydantic_dataclass
17
23
  class Binary:
@@ -35,17 +41,19 @@ class Parameter:
35
41
  Attributes:
36
42
  name (str): The name of the parameter.
37
43
  description (str): A description of the parameter.
44
+ type (ParameterType): The type of the parameter.
38
45
  sensitive (bool): Whether the parameter contains sensitive information.
39
46
  required (bool): Whether the parameter is required.
40
- default (Optional[str]): The default value of the parameter, if any. (required if sensitive is False)
47
+ default (Optional[Union[str, int, float, bool]]): The default value of the parameter, if any. (required if sensitive is False)
41
48
  id (str): Unique identifier for the parameter.
42
49
  """
43
50
 
44
51
  name: str
45
52
  description: str
53
+ type: ParameterType
46
54
  sensitive: bool = False
47
55
  required: bool = False
48
- default: Optional[str] = None
56
+ default: Optional[Union[str, int, float, bool]] = None
49
57
  id: str = Field(default_factory=lambda: str(uuid.uuid4()))
50
58
 
51
59
  def __post_init__(self) -> None:
@@ -54,6 +62,26 @@ class Parameter:
54
62
  f"Default value for parameter {self.name} should be set if parameter is optional."
55
63
  )
56
64
 
65
+ # Validate that default value Python type matches the declared type
66
+ if self.default is not None:
67
+ if self.type == "string":
68
+ if not isinstance(self.default, str):
69
+ raise ValueError(
70
+ f"Parameter {self.name} has type 'string' but default value has Python type {type(self.default).__name__}. Expected str."
71
+ )
72
+ elif self.type == "number":
73
+ if not isinstance(self.default, (int, float)) or isinstance(
74
+ self.default, bool
75
+ ):
76
+ raise ValueError(
77
+ f"Parameter {self.name} has type 'number' but default value has Python type {type(self.default).__name__}. Expected int or float."
78
+ )
79
+ elif self.type == "boolean":
80
+ if not isinstance(self.default, bool):
81
+ raise ValueError(
82
+ f"Parameter {self.name} has type 'boolean' but default value has Python type {type(self.default).__name__}. Expected bool."
83
+ )
84
+
57
85
 
58
86
  @pydantic_dataclass
59
87
  class Variable:
spaceforge/conftest.py CHANGED
@@ -35,6 +35,7 @@ class TestPlugin(SpaceforgePlugin):
35
35
  Parameter(
36
36
  name="test_param",
37
37
  description="Test parameter",
38
+ type="string",
38
39
  required=False,
39
40
  default="default_value"
40
41
  )
spaceforge/schema.json CHANGED
@@ -123,7 +123,7 @@
123
123
  "type": "object"
124
124
  },
125
125
  "Parameter": {
126
- "description": "A class to represent a parameter with a name and value.\n\nAttributes:\n name (str): The name of the parameter.\n description (str): A description of the parameter.\n sensitive (bool): Whether the parameter contains sensitive information.\n required (bool): Whether the parameter is required.\n default (Optional[str]): The default value of the parameter, if any. (required if sensitive is False)\n id (str): Unique identifier for the parameter.",
126
+ "description": "A class to represent a parameter with a name and value.\n\nAttributes:\n name (str): The name of the parameter.\n description (str): A description of the parameter.\n type (ParameterType): The type of the parameter.\n sensitive (bool): Whether the parameter contains sensitive information.\n required (bool): Whether the parameter is required.\n default (Optional[Union[str, int, float, bool]]): The default value of the parameter, if any. (required if sensitive is False)\n id (str): Unique identifier for the parameter.",
127
127
  "properties": {
128
128
  "name": {
129
129
  "title": "Name",
@@ -133,6 +133,15 @@
133
133
  "title": "Description",
134
134
  "type": "string"
135
135
  },
136
+ "type": {
137
+ "enum": [
138
+ "string",
139
+ "number",
140
+ "boolean"
141
+ ],
142
+ "title": "Type",
143
+ "type": "string"
144
+ },
136
145
  "sensitive": {
137
146
  "default": false,
138
147
  "title": "Sensitive",
@@ -148,6 +157,15 @@
148
157
  {
149
158
  "type": "string"
150
159
  },
160
+ {
161
+ "type": "integer"
162
+ },
163
+ {
164
+ "type": "number"
165
+ },
166
+ {
167
+ "type": "boolean"
168
+ },
151
169
  {
152
170
  "type": "null"
153
171
  }
@@ -162,7 +180,8 @@
162
180
  },
163
181
  "required": [
164
182
  "name",
165
- "description"
183
+ "description",
184
+ "type"
166
185
  ],
167
186
  "title": "Parameter",
168
187
  "type": "object"
spaceforge/test_cls.py CHANGED
@@ -8,6 +8,7 @@ def test_ensure_optional_parameters_require_default_values() -> None:
8
8
  Parameter(
9
9
  name="optional_default",
10
10
  description="default value",
11
+ type="string",
11
12
  required=False,
12
13
  )
13
14
 
@@ -15,3 +16,87 @@ def test_ensure_optional_parameters_require_default_values() -> None:
15
16
  def test_ensure_variables_have_either_value_or_value_from_parameter() -> None:
16
17
  with pytest.raises(ValueError):
17
18
  Variable(key="test_var", sensitive=False)
19
+
20
+
21
+ def test_parameter_type_validation_string() -> None:
22
+ """Test that string type accepts any default value."""
23
+ # Should not raise
24
+ Parameter(
25
+ name="string_param",
26
+ description="A string parameter",
27
+ type="string",
28
+ required=False,
29
+ default="any value works",
30
+ )
31
+
32
+
33
+ def test_parameter_type_validation_number_valid() -> None:
34
+ """Test that number type accepts valid numeric strings."""
35
+ # Integer
36
+ Parameter(
37
+ name="int_param",
38
+ description="An integer parameter",
39
+ type="number",
40
+ required=False,
41
+ default=42,
42
+ )
43
+
44
+ # Float
45
+ Parameter(
46
+ name="float_param",
47
+ description="A float parameter",
48
+ type="number",
49
+ required=False,
50
+ default=3.14,
51
+ )
52
+
53
+ # Negative number
54
+ Parameter(
55
+ name="negative_param",
56
+ description="A negative parameter",
57
+ type="number",
58
+ required=False,
59
+ default=-100,
60
+ )
61
+
62
+
63
+ def test_parameter_type_validation_number_invalid() -> None:
64
+ """Test that number type rejects non-numeric strings."""
65
+ with pytest.raises(
66
+ ValueError,
67
+ match="Parameter invalid_number has type 'number' but default value has Python type str.",
68
+ ):
69
+ Parameter(
70
+ name="invalid_number",
71
+ description="Invalid number parameter",
72
+ type="number",
73
+ required=False,
74
+ default="not a number",
75
+ )
76
+
77
+
78
+ def test_parameter_type_validation_boolean_invalid() -> None:
79
+ """Test that boolean type rejects values other than 'true'/'false'."""
80
+ with pytest.raises(
81
+ ValueError,
82
+ match="Parameter invalid_bool has type 'boolean' but default value has Python type str.",
83
+ ):
84
+ Parameter(
85
+ name="invalid_bool",
86
+ description="Invalid boolean parameter",
87
+ type="boolean",
88
+ required=False,
89
+ default="1",
90
+ )
91
+
92
+ with pytest.raises(
93
+ ValueError,
94
+ match="Parameter invalid_bool2 has type 'boolean' but default value has Python type str.",
95
+ ):
96
+ Parameter(
97
+ name="invalid_bool2",
98
+ description="Invalid boolean parameter",
99
+ type="boolean",
100
+ required=False,
101
+ default="yes",
102
+ )
@@ -30,12 +30,14 @@ class PluginExample(SpaceforgePlugin):
30
30
  Parameter(
31
31
  name="api_key",
32
32
  description="API key for authentication",
33
+ type="string",
33
34
  required=True,
34
35
  sensitive=True,
35
36
  ),
36
37
  Parameter(
37
38
  name="endpoint",
38
39
  description="API endpoint URL",
40
+ type="string",
39
41
  required=False,
40
42
  default="https://api.example.com",
41
43
  ),
@@ -106,7 +108,7 @@ class TestPlugin(SpaceforgePlugin):
106
108
  __author__ = "Test"
107
109
 
108
110
  __parameters__ = [
109
- Parameter(name="test_param", description="Test parameter", required=False, default="default_value")
111
+ Parameter(name="test_param", description="Test parameter", type="string", required=False, default="default_value")
110
112
  ]
111
113
 
112
114
  def after_plan(self) -> None:
@@ -619,6 +621,7 @@ class FullTestPlugin(SpaceforgePlugin):
619
621
  Parameter(
620
622
  name="test_param",
621
623
  description="Test parameter",
624
+ type="string",
622
625
  required=False,
623
626
  default="test_value"
624
627
  )
@@ -811,12 +814,14 @@ class TestPluginGeneratorEdgeCases:
811
814
  Parameter(
812
815
  name="api key",
813
816
  description="API key for authentication",
817
+ type="string",
814
818
  required=True,
815
819
  sensitive=True,
816
820
  ),
817
821
  Parameter(
818
822
  name="endpoint",
819
823
  description="API endpoint URL",
824
+ type="string",
820
825
  required=False,
821
826
  default="https://api.example.com",
822
827
  ),
@@ -17,12 +17,14 @@ class TestPluginGeneratorParameters:
17
17
  Parameter(
18
18
  name="api_key",
19
19
  description="API key for authentication",
20
+ type="string",
20
21
  required=True,
21
22
  sensitive=True,
22
23
  ),
23
24
  Parameter(
24
25
  name="endpoint",
25
26
  description="API endpoint URL",
27
+ type="string",
26
28
  required=False,
27
29
  default="https://api.example.com",
28
30
  ),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spaceforge
3
- Version: 1.1.7
3
+ Version: 1.2.1
4
4
  Summary: A Python framework for building Spacelift plugins
5
5
  Author-email: Spacelift <support@spacelift.io>
6
6
  Maintainer-email: Spacelift <support@spacelift.io>
@@ -34,6 +34,7 @@ Requires-Dist: pytest-cov; extra == "dev"
34
34
  Requires-Dist: black; extra == "dev"
35
35
  Requires-Dist: isort; extra == "dev"
36
36
  Requires-Dist: mypy; extra == "dev"
37
+ Requires-Dist: pylint; extra == "dev"
37
38
  Requires-Dist: types-PyYAML; extra == "dev"
38
39
  Requires-Dist: setuptools-scm[toml]>=6.2; extra == "dev"
39
40
  Requires-Dist: autoflake; extra == "dev"
@@ -2,19 +2,19 @@ spaceforge/README.md,sha256=gDyCQN0EW4xp8Skvs6J0qHpO9CjVTnRfSnhduAIFQs4,7717
2
2
  spaceforge/__init__.py,sha256=TU-vvm15dK1ucixNW0V42eTT72x3_hmKSyxP4MC1Occ,589
3
3
  spaceforge/__main__.py,sha256=UKbeCuEFgoNlEOX44-kYUAQuUdySdkAKsvbjXEyLeWI,965
4
4
  spaceforge/_version.py,sha256=70eCBV_uVCm0U7qrtYRUZM3GJnJRtvZQ_aPFLd8H7CI,1009
5
- spaceforge/_version_scm.py,sha256=XScxAJn_hLwoilMyvvJG_0tPX3X-Jhde5mefhI8pVSM,704
6
- spaceforge/cls.py,sha256=oYW5t5_xs9ZM6Ne_b4trxCPxLHQrqbqgUeibeM8O4PU,6329
7
- spaceforge/conftest.py,sha256=U-xCavCsgRAQXqflIIOMeq9pcGbeqRviUNkEXgZol8g,2141
5
+ spaceforge/_version_scm.py,sha256=vTBkgV8s9uBGLjgp067jeWVTh-Y6mBirMNSkXJot2J8,704
6
+ spaceforge/cls.py,sha256=qe_-pQ9G7p6Hxv8FxNw9OwhPeMQk3vIS_SezxSoca2M,7644
7
+ spaceforge/conftest.py,sha256=J2BIqOu0VYpUlxnJf07cW6l2NHSzVvkXw18jKTTR3hE,2168
8
8
  spaceforge/generator.py,sha256=qOC9YeP9QmwFZQoe0BbvJb8RHtv3BVupYxvu2ceQMkE,18768
9
9
  spaceforge/plugin.py,sha256=Ytm2B7nnJNH231V4gUFY1pBmwVNTpIg3YviUL_Bnf24,14963
10
10
  spaceforge/runner.py,sha256=NNddgK_OsnQWx2YFcyTpAOWfFLBDUphufBVfXYEzfzM,3166
11
- spaceforge/schema.json,sha256=89IROLVlCj8txGMiLt4Bbuo_2muSxKoZCyaXQ2vuA9c,10869
12
- spaceforge/test_cls.py,sha256=nXAgbnFnGdFxrtA7vNXiePjNUASuoYW-lEuQGx9WMGs,468
13
- spaceforge/test_generator.py,sha256=sEDV7ShT2BpLoW4zC8ZT-P-V4_dP8kOI0WuiZ6uVIgc,32625
11
+ spaceforge/schema.json,sha256=nZf438rSKThw64Au7-tmoVw8EYsb7OGhzLfInO31ddA,11328
12
+ spaceforge/test_cls.py,sha256=uDnEmgF7bHzu3FjMk4-boEuJqk_B5AWKMPiKgl83Onc,2777
13
+ spaceforge/test_generator.py,sha256=Gm3IA-8ykwCbj1JMKe03mj5DMZSNFEtCz8ue0xKjUUs,32791
14
14
  spaceforge/test_generator_binaries.py,sha256=X_7pPLGE45eQt-Kv9_ku__LsyLgOvViHc_BvVpSCMp0,7263
15
15
  spaceforge/test_generator_core.py,sha256=gOqRx0rnME-srGMHun4KidXMN-iaqfKKTyoQ0Tw6b9Q,6253
16
16
  spaceforge/test_generator_hooks.py,sha256=2lJs8dYlFb7QehWcYF0O4qg38s5UudEpzJyBi1XiS3k,2542
17
- spaceforge/test_generator_parameters.py,sha256=77az9rcocFny2AC4O2eTzjCW712fR1DBHzGrgBKeR4w,1878
17
+ spaceforge/test_generator_parameters.py,sha256=aZRNwYcogJqp2NiYrqEkuxDi2Z6Z2S1SVoejUvsHHCE,1948
18
18
  spaceforge/test_plugin.py,sha256=rZ4Uv_0lIR0qb1GFHkiosGO3WHTWhO7epz8INDxV8Q0,13018
19
19
  spaceforge/test_plugin_file_operations.py,sha256=B0qvIo5EcfKMiHLhBv-hAnpSonn83ojcmJHXasydojA,3782
20
20
  spaceforge/test_plugin_hooks.py,sha256=ugaVdzH1-heRJSJN0lu8zoqLcLPC3tg_PzUX98qu9Sw,1038
@@ -25,9 +25,9 @@ spaceforge/test_runner_core.py,sha256=eNR9YOwJwv7LsMtNQ4WXXMPIW6RE_A7hUp4bCpzz1R
25
25
  spaceforge/test_runner_execution.py,sha256=GJhoECdhIY2M3MWcmTrIYfkJd2P5n86zixO3FY38_CQ,5344
26
26
  spaceforge/templates/binary_install.sh.j2,sha256=xyq-ol6z8M4RJ107GAs5cdvudVV45JmhwExHovfCHMI,1544
27
27
  spaceforge/templates/ensure_spaceforge_and_run.sh.j2,sha256=OKrpZI-M1VU5rCdu7XMbBto7R-HV9lAImc3x3112vhY,580
28
- spaceforge-1.1.7.dist-info/licenses/LICENSE,sha256=qtl16T_VToz1-IpjGKSLCHsy_zmCFg2H5SkvJi85C4c,1065
29
- spaceforge-1.1.7.dist-info/METADATA,sha256=sNVO6Alkg9uDBZXmd0rpr8kZy6P6bnAK81gJ0GzvP-o,2307
30
- spaceforge-1.1.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
31
- spaceforge-1.1.7.dist-info/entry_points.txt,sha256=qawuuKBSNTGg-njnQnhxxFldFvXYAPej6bF_f3iyQ48,56
32
- spaceforge-1.1.7.dist-info/top_level.txt,sha256=eVw-Lw4Th0oHM8Gx1Y8YetyNgbNbMBU00yWs-kwGeSs,11
33
- spaceforge-1.1.7.dist-info/RECORD,,
28
+ spaceforge-1.2.1.dist-info/licenses/LICENSE,sha256=qtl16T_VToz1-IpjGKSLCHsy_zmCFg2H5SkvJi85C4c,1065
29
+ spaceforge-1.2.1.dist-info/METADATA,sha256=XNh0_CLGSEym4RDnjkVbm8Yo4MIeSzLSXOgTzz7IXLY,2345
30
+ spaceforge-1.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
31
+ spaceforge-1.2.1.dist-info/entry_points.txt,sha256=qawuuKBSNTGg-njnQnhxxFldFvXYAPej6bF_f3iyQ48,56
32
+ spaceforge-1.2.1.dist-info/top_level.txt,sha256=eVw-Lw4Th0oHM8Gx1Y8YetyNgbNbMBU00yWs-kwGeSs,11
33
+ spaceforge-1.2.1.dist-info/RECORD,,