stackit-runcommand 1.1.0__py3-none-any.whl → 1.1.2__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.
@@ -13,11 +13,13 @@
13
13
  """ # noqa: E501
14
14
 
15
15
  import datetime
16
+ import decimal
16
17
  import json
17
18
  import mimetypes
18
19
  import os
19
20
  import re
20
21
  import tempfile
22
+ import uuid
21
23
  from enum import Enum
22
24
  from typing import Dict, List, Optional, Tuple, Union
23
25
  from urllib.parse import quote
@@ -64,8 +66,10 @@ class ApiClient:
64
66
  "bool": bool,
65
67
  "date": datetime.date,
66
68
  "datetime": datetime.datetime,
69
+ "decimal": decimal.Decimal,
67
70
  "object": object,
68
71
  }
72
+ _pool = None
69
73
 
70
74
  def __init__(self, configuration, header_name=None, header_value=None, cookie=None) -> None:
71
75
  self.config: Configuration = configuration
@@ -268,7 +272,7 @@ class ApiClient:
268
272
  return_data = self.__deserialize_file(response_data)
269
273
  elif response_type is not None:
270
274
  match = None
271
- content_type = response_data.getheader("content-type")
275
+ content_type = response_data.headers.get("content-type")
272
276
  if content_type is not None:
273
277
  match = re.search(r"charset=([a-zA-Z\-\d]+)[\s;]?", content_type)
274
278
  encoding = match.group(1) if match else "utf-8"
@@ -285,7 +289,7 @@ class ApiClient:
285
289
  return ApiResponse(
286
290
  status_code=response_data.status,
287
291
  data=return_data,
288
- headers=response_data.getheaders(),
292
+ headers=response_data.headers,
289
293
  raw_data=response_data.data,
290
294
  )
291
295
 
@@ -297,6 +301,7 @@ class ApiClient:
297
301
  If obj is str, int, long, float, bool, return directly.
298
302
  If obj is datetime.datetime, datetime.date
299
303
  convert to string in iso8601 format.
304
+ If obj is decimal.Decimal return string representation.
300
305
  If obj is list, sanitize each element in the list.
301
306
  If obj is dict, return the dict.
302
307
  If obj is OpenAPI model, return the properties dict.
@@ -312,12 +317,16 @@ class ApiClient:
312
317
  return obj.get_secret_value()
313
318
  elif isinstance(obj, self.PRIMITIVE_TYPES):
314
319
  return obj
320
+ elif isinstance(obj, uuid.UUID):
321
+ return str(obj)
315
322
  elif isinstance(obj, list):
316
323
  return [self.sanitize_for_serialization(sub_obj) for sub_obj in obj]
317
324
  elif isinstance(obj, tuple):
318
325
  return tuple(self.sanitize_for_serialization(sub_obj) for sub_obj in obj)
319
326
  elif isinstance(obj, (datetime.datetime, datetime.date)):
320
327
  return obj.isoformat()
328
+ elif isinstance(obj, decimal.Decimal):
329
+ return str(obj)
321
330
 
322
331
  elif isinstance(obj, dict):
323
332
  obj_dict = obj
@@ -327,7 +336,7 @@ class ApiClient:
327
336
  # and attributes which value is not None.
328
337
  # Convert attribute name to json key in
329
338
  # model definition for request.
330
- if hasattr(obj, "to_dict") and callable(obj.to_dict):
339
+ if hasattr(obj, "to_dict") and callable(getattr(obj, "to_dict")): # noqa: B009
331
340
  obj_dict = obj.to_dict()
332
341
  else:
333
342
  obj_dict = obj.__dict__
@@ -355,7 +364,7 @@ class ApiClient:
355
364
  data = json.loads(response_text)
356
365
  except ValueError:
357
366
  data = response_text
358
- elif re.match(r"^application/(json|[\w!#$&.+-^_]+\+json)\s*(;|$)", content_type, re.IGNORECASE):
367
+ elif re.match(r"^application/(json|[\w!#$&.+\-^_]+\+json)\s*(;|$)", content_type, re.IGNORECASE):
359
368
  if response_text == "":
360
369
  data = ""
361
370
  else:
@@ -401,12 +410,14 @@ class ApiClient:
401
410
 
402
411
  if klass in self.PRIMITIVE_TYPES:
403
412
  return self.__deserialize_primitive(data, klass)
404
- elif klass == object:
413
+ elif klass is object:
405
414
  return self.__deserialize_object(data)
406
- elif klass == datetime.date:
415
+ elif klass is datetime.date:
407
416
  return self.__deserialize_date(data)
408
- elif klass == datetime.datetime:
417
+ elif klass is datetime.datetime:
409
418
  return self.__deserialize_datetime(data)
419
+ elif klass is decimal.Decimal:
420
+ return decimal.Decimal(data)
410
421
  elif issubclass(klass, Enum):
411
422
  return self.__deserialize_enum(data, klass)
412
423
  else:
@@ -554,12 +565,14 @@ class ApiClient:
554
565
  os.close(fd)
555
566
  os.remove(path)
556
567
 
557
- content_disposition = response.getheader("Content-Disposition")
568
+ content_disposition = response.headers.get("Content-Disposition")
558
569
  if content_disposition:
559
570
  m = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', content_disposition)
560
571
  if m is None:
561
572
  raise ValueError("Unexpected 'content-disposition' header value")
562
- filename = m.group(1)
573
+ filename = os.path.basename(m.group(1)) # Strip any directory traversal
574
+ if filename in ("", ".", ".."): # fall back to tmp filename
575
+ filename = os.path.basename(path)
563
576
  path = os.path.join(os.path.dirname(path), filename)
564
577
 
565
578
  with open(path, "wb") as f:
@@ -130,7 +130,7 @@ class ApiException(OpenApiException):
130
130
  self.body = http_resp.data.decode("utf-8")
131
131
  except Exception: # noqa: S110
132
132
  pass
133
- self.headers = http_resp.getheaders()
133
+ self.headers = http_resp.headers
134
134
 
135
135
  @classmethod
136
136
  def from_response(
@@ -13,7 +13,6 @@
13
13
  Do not edit the class manually.
14
14
  """ # noqa: E501
15
15
 
16
-
17
16
  # import models into model package
18
17
  from stackit.runcommand.models.command_details import CommandDetails
19
18
  from stackit.runcommand.models.command_template import CommandTemplate
@@ -72,9 +72,9 @@ class CommandTemplateResponse(BaseModel):
72
72
  # override the default output from pydantic by calling `to_dict()` of each item in items (list)
73
73
  _items = []
74
74
  if self.items:
75
- for _item in self.items:
76
- if _item:
77
- _items.append(_item.to_dict())
75
+ for _item_items in self.items:
76
+ if _item_items:
77
+ _items.append(_item_items.to_dict())
78
78
  _dict["items"] = _items
79
79
  return _dict
80
80
 
@@ -32,9 +32,9 @@ class CommandTemplateSchema(BaseModel):
32
32
  description: Optional[StrictStr] = None
33
33
  name: Optional[StrictStr] = None
34
34
  os_type: Optional[List[StrictStr]] = Field(default=None, alias="osType")
35
- parameter_schema: Optional[ParametersSchema] = Field(default=None, alias="parameterSchema")
35
+ parameters_schema: Optional[ParametersSchema] = Field(default=None, alias="parametersSchema")
36
36
  title: Optional[StrictStr] = None
37
- __properties: ClassVar[List[str]] = ["description", "name", "osType", "parameterSchema", "title"]
37
+ __properties: ClassVar[List[str]] = ["description", "name", "osType", "parametersSchema", "title"]
38
38
 
39
39
  model_config = ConfigDict(
40
40
  populate_by_name=True,
@@ -73,9 +73,9 @@ class CommandTemplateSchema(BaseModel):
73
73
  exclude=excluded_fields,
74
74
  exclude_none=True,
75
75
  )
76
- # override the default output from pydantic by calling `to_dict()` of parameter_schema
77
- if self.parameter_schema:
78
- _dict["parameterSchema"] = self.parameter_schema.to_dict()
76
+ # override the default output from pydantic by calling `to_dict()` of parameters_schema
77
+ if self.parameters_schema:
78
+ _dict["parametersSchema"] = self.parameters_schema.to_dict()
79
79
  return _dict
80
80
 
81
81
  @classmethod
@@ -92,9 +92,9 @@ class CommandTemplateSchema(BaseModel):
92
92
  "description": obj.get("description"),
93
93
  "name": obj.get("name"),
94
94
  "osType": obj.get("osType"),
95
- "parameterSchema": (
96
- ParametersSchema.from_dict(obj["parameterSchema"])
97
- if obj.get("parameterSchema") is not None
95
+ "parametersSchema": (
96
+ ParametersSchema.from_dict(obj["parametersSchema"])
97
+ if obj.get("parametersSchema") is not None
98
98
  else None
99
99
  ),
100
100
  "title": obj.get("title"),
@@ -72,9 +72,9 @@ class GetCommandsResponse(BaseModel):
72
72
  # override the default output from pydantic by calling `to_dict()` of each item in items (list)
73
73
  _items = []
74
74
  if self.items:
75
- for _item in self.items:
76
- if _item:
77
- _items.append(_item.to_dict())
75
+ for _item_items in self.items:
76
+ if _item_items:
77
+ _items.append(_item_items.to_dict())
78
78
  _dict["items"] = _items
79
79
  return _dict
80
80
 
@@ -18,7 +18,14 @@ import json
18
18
  import pprint
19
19
  from typing import Any, ClassVar, Dict, List, Optional, Set
20
20
 
21
- from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr
21
+ from pydantic import (
22
+ BaseModel,
23
+ ConfigDict,
24
+ Field,
25
+ StrictBool,
26
+ StrictInt,
27
+ StrictStr,
28
+ )
22
29
  from typing_extensions import Self
23
30
 
24
31
 
@@ -39,12 +39,17 @@ class RESTResponse(io.IOBase):
39
39
  self.data = self.response.content
40
40
  return self.data
41
41
 
42
+ @property
43
+ def headers(self):
44
+ """Returns a dictionary of response headers."""
45
+ return self.response.headers
46
+
42
47
  def getheaders(self):
43
- """Returns a dictionary of the response headers."""
48
+ """Returns a dictionary of the response headers; use ``headers`` instead."""
44
49
  return self.response.headers
45
50
 
46
51
  def getheader(self, name, default=None):
47
- """Returns a given response header."""
52
+ """Returns a given response header; use ``headers.get()`` instead."""
48
53
  return self.response.headers.get(name, default)
49
54
 
50
55
 
@@ -94,6 +99,7 @@ class RESTClientObject:
94
99
  url,
95
100
  data=request_body,
96
101
  headers=headers,
102
+ timeout=_request_timeout,
97
103
  )
98
104
  elif content_type == "application/x-www-form-urlencoded":
99
105
  r = self.session.request(
@@ -101,6 +107,7 @@ class RESTClientObject:
101
107
  url,
102
108
  params=post_params,
103
109
  headers=headers,
110
+ timeout=_request_timeout,
104
111
  )
105
112
  elif content_type == "multipart/form-data":
106
113
  # must del headers['Content-Type'], or the correct
@@ -114,6 +121,7 @@ class RESTClientObject:
114
121
  url,
115
122
  files=post_params,
116
123
  headers=headers,
124
+ timeout=_request_timeout,
117
125
  )
118
126
  # Pass a `string` parameter directly in the body to support
119
127
  # other content types than JSON when `body` argument is
@@ -124,10 +132,17 @@ class RESTClientObject:
124
132
  url,
125
133
  data=body,
126
134
  headers=headers,
135
+ timeout=_request_timeout,
127
136
  )
128
137
  elif headers["Content-Type"].startswith("text/") and isinstance(body, bool):
129
138
  request_body = "true" if body else "false"
130
- r = self.session.request(method, url, data=request_body, headers=headers)
139
+ r = self.session.request(
140
+ method,
141
+ url,
142
+ data=request_body,
143
+ headers=headers,
144
+ timeout=_request_timeout,
145
+ )
131
146
  else:
132
147
  # Cannot generate the request from given parameters
133
148
  msg = """Cannot prepare a request message for provided
@@ -141,6 +156,7 @@ class RESTClientObject:
141
156
  url,
142
157
  params={},
143
158
  headers=headers,
159
+ timeout=_request_timeout,
144
160
  )
145
161
  except requests.exceptions.SSLError as e:
146
162
  msg = "\n".join([type(e).__name__, str(e)])
@@ -1,10 +1,12 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: stackit-runcommand
3
- Version: 1.1.0
3
+ Version: 1.1.2
4
4
  Summary: STACKIT Run Commands Service API
5
- Author: STACKIT Developer Tools
6
- Author-email: developer-tools@stackit.cloud
7
- Requires-Python: >=3.9,<4.0
5
+ Project-URL: Homepage, https://github.com/stackitcloud/stackit-sdk-python
6
+ Project-URL: Issues, https://github.com/stackitcloud/stackit-sdk-python/issues
7
+ Author-email: STACKIT Developer Tools <developer-tools@stackit.cloud>
8
+ License-File: LICENSE.md
9
+ License-File: NOTICE.txt
8
10
  Classifier: License :: OSI Approved :: Apache Software License
9
11
  Classifier: Operating System :: OS Independent
10
12
  Classifier: Programming Language :: Python :: 3
@@ -13,12 +15,12 @@ Classifier: Programming Language :: Python :: 3.10
13
15
  Classifier: Programming Language :: Python :: 3.11
14
16
  Classifier: Programming Language :: Python :: 3.12
15
17
  Classifier: Programming Language :: Python :: 3.13
16
- Requires-Dist: pydantic (>=2.9.2)
17
- Requires-Dist: python-dateutil (>=2.9.0.post0)
18
- Requires-Dist: requests (>=2.32.3)
19
- Requires-Dist: stackit-core (>=0.0.1a)
20
- Project-URL: Homepage, https://github.com/stackitcloud/stackit-sdk-python
21
- Project-URL: Issues, https://github.com/stackitcloud/stackit-sdk-python/issues
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Requires-Python: <4.0,>=3.9
20
+ Requires-Dist: pydantic>=2.9.2
21
+ Requires-Dist: python-dateutil>=2.9.0.post0
22
+ Requires-Dist: requests>=2.32.3
23
+ Requires-Dist: stackit-core>=0.0.1a
22
24
  Description-Content-Type: text/markdown
23
25
 
24
26
  # stackit.runcommand
@@ -42,4 +44,4 @@ import stackit.runcommand
42
44
 
43
45
  ## Getting Started
44
46
 
45
- [Examples](https://github.com/stackitcloud/stackit-sdk-python/tree/main/examples) for the usage of the package can be found in the [GitHub repository](https://github.com/stackitcloud/stackit-sdk-python) of the SDK.
47
+ [Examples](https://github.com/stackitcloud/stackit-sdk-python/tree/main/examples) for the usage of the package can be found in the [GitHub repository](https://github.com/stackitcloud/stackit-sdk-python) of the SDK.
@@ -1,27 +1,27 @@
1
1
  stackit/runcommand/__init__.py,sha256=hGt28Yt1GUrXvKoBqfnQpo2HKMRZcCmTgeszZXJat9I,2879
2
- stackit/runcommand/api/__init__.py,sha256=O-WDFpOgx6B55T02W-JUoG02zuSKFHZcszlw16eLV04,105
3
- stackit/runcommand/api/default_api.py,sha256=B-P2UAbtmpF9ZQEAuPIynew72m4QnjSu56QBFktpzHo,60628
4
- stackit/runcommand/api_client.py,sha256=dx4x895AQYur-rlSkTjBUJBI1HYPfW7UzrHFaVE0NSc,23348
2
+ stackit/runcommand/api_client.py,sha256=1vcV8w1hvZ0ATPOWrlO1fs0Cb1BwpOVV1ECHHCmrg4c,23916
5
3
  stackit/runcommand/api_response.py,sha256=HRYkVqMNIlfODacTQPTbiVj2YdcnutpQrKJdeAoCSpM,642
6
4
  stackit/runcommand/configuration.py,sha256=aCyt9z-HhMt3YCq_Zv8vO7dervXQs_Kz2kvzKrUUUT8,5703
7
- stackit/runcommand/exceptions.py,sha256=wJraDNW0BM6uJg2VHOoPy0YHDW_SAp9OCR1q0AWNit8,6425
8
- stackit/runcommand/models/__init__.py,sha256=6mJTV3kkUSCanC00iDEgZtOU3SUkO_FvV06hXwukNFw,1240
5
+ stackit/runcommand/exceptions.py,sha256=5EHd1-lZWDoSmwTR2S93BSU-lVkkNNC_40g9JM7WXWI,6420
6
+ stackit/runcommand/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ stackit/runcommand/rest.py,sha256=KerHWEoIwGlQsp2Lo5C3dqSKF3HtCi4WwbCqRA9PQUg,6413
8
+ stackit/runcommand/api/__init__.py,sha256=O-WDFpOgx6B55T02W-JUoG02zuSKFHZcszlw16eLV04,105
9
+ stackit/runcommand/api/default_api.py,sha256=B-P2UAbtmpF9ZQEAuPIynew72m4QnjSu56QBFktpzHo,60628
10
+ stackit/runcommand/models/__init__.py,sha256=YiZo6DNnSDhlocl4uFhR0nDZUJwE8NRx1X_E1krqqx8,1239
9
11
  stackit/runcommand/models/command_details.py,sha256=HPA4q4Z6v13iwAMQ2JLEYHoJl7RTkqmjuRNenCNIas0,4033
10
12
  stackit/runcommand/models/command_template.py,sha256=QIoUmYvq1PAjaSSBu3EPQjtTQUTqggRsXO4SZnxUFvg,2620
11
- stackit/runcommand/models/command_template_response.py,sha256=t1Y7pXPrD9RvfDU5ZLY2FdMMy492JdtbES8y6WH2FVY,3047
12
- stackit/runcommand/models/command_template_schema.py,sha256=JDde7o4DOLzEIWtulKtAFBmyrUsOYUTWnGBvrBHTqq0,3451
13
+ stackit/runcommand/models/command_template_response.py,sha256=RoCnU6uIPx3HYrNsJi269znZgvMczbKKyfZqZgCb_r0,3065
14
+ stackit/runcommand/models/command_template_schema.py,sha256=4bqvJ3Se5qcD93SMhYNNFpeSc8TsWiD3-0ggiPOm7do,3461
13
15
  stackit/runcommand/models/commands.py,sha256=lxz_DvGBoR1yU-3qOui6RP-C-yEKYTL1-SDXOXy78Nk,3661
14
16
  stackit/runcommand/models/create_command_payload.py,sha256=N3drh2OnqxMtw-W_FK5zF1Q723mn8xCtcN547Q2M-sI,2659
15
17
  stackit/runcommand/models/error_response.py,sha256=20AnQiIvV4CPvbYrMedl3TDENPq-GIadrWX1yTo3poI,2647
16
- stackit/runcommand/models/get_commands_response.py,sha256=3K9JdQ6K8giHj9lhn5pGVUoJQAosrrGF_xVwL5qI_ss,2892
17
- stackit/runcommand/models/model_field.py,sha256=MPZcyMtZHWnXmWINB6yirdmis6UWNbR1FdqOZ2FoFGg,3177
18
+ stackit/runcommand/models/get_commands_response.py,sha256=kklrjcW8qHMXB4alLZIvqslxSfUdic5J4kH7KbP5Jcc,2910
19
+ stackit/runcommand/models/model_field.py,sha256=_er9L8RH3DNRlrIz0OKv4rvUTDBAn1gnYtHzA7IlOE4,3206
18
20
  stackit/runcommand/models/new_command_response.py,sha256=naWeB_fMrj8pI9d3dNFvDQfgolO6LUlaaiFhORps0rM,2427
19
21
  stackit/runcommand/models/parameters_schema.py,sha256=e2TAAxFEV63gabsntL5qfFPhjxd_EPLruIU5E4oZtAA,2766
20
22
  stackit/runcommand/models/properties.py,sha256=yQUPHBp8DiPNlPj0b4NpwayMCIcBc7UHuOQN-YYCC8U,4199
21
- stackit/runcommand/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- stackit/runcommand/rest.py,sha256=JINjOPMJfbskBxSVNZn2LZ1rnG66pOi9tgq-4ImCrw4,5811
23
- stackit_runcommand-1.1.0.dist-info/LICENSE.md,sha256=3dF8Tb7yZn2tS4zyNa-yNe-68pH8qyWdGz4ioMd3MgE,10933
24
- stackit_runcommand-1.1.0.dist-info/METADATA,sha256=VrThUvokkmgJgJAn9wbspJQfVFPhKOlrMwYnFSKbRTU,1610
25
- stackit_runcommand-1.1.0.dist-info/NOTICE.txt,sha256=daK6MxvxH3YFeiVhow8N_fl9s-5sENiXgnGwgEgWPfw,63
26
- stackit_runcommand-1.1.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
27
- stackit_runcommand-1.1.0.dist-info/RECORD,,
23
+ stackit_runcommand-1.1.2.dist-info/METADATA,sha256=VdZPUiRsI13_WUIpXA2ILBHacLd92qVrgmXeSDTTcSs,1692
24
+ stackit_runcommand-1.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
+ stackit_runcommand-1.1.2.dist-info/licenses/LICENSE.md,sha256=3dF8Tb7yZn2tS4zyNa-yNe-68pH8qyWdGz4ioMd3MgE,10933
26
+ stackit_runcommand-1.1.2.dist-info/licenses/NOTICE.txt,sha256=daK6MxvxH3YFeiVhow8N_fl9s-5sENiXgnGwgEgWPfw,63
27
+ stackit_runcommand-1.1.2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.3
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any