datamaker-py 0.9.0__tar.gz → 0.11.0__tar.gz

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 (45) hide show
  1. datamaker_py-0.11.0/PKG-INFO +143 -0
  2. datamaker_py-0.11.0/README.md +132 -0
  3. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/pyproject.toml +1 -1
  4. datamaker_py-0.11.0/src/datamaker/__init__.py +12 -0
  5. datamaker_py-0.11.0/src/datamaker/error.py +94 -0
  6. datamaker_py-0.11.0/src/datamaker/generated/__init__.py +7 -0
  7. datamaker_py-0.11.0/src/datamaker/generated/schema.py +1655 -0
  8. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/main.py +112 -5
  9. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/__init__.py +2 -0
  10. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/api_keys.py +5 -4
  11. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/base.py +10 -2
  12. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/connections.py +5 -4
  13. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/custom_types.py +20 -14
  14. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/export_and_validation.py +3 -2
  15. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/folders_and_utils.py +13 -12
  16. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/generation.py +2 -1
  17. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/keymaps.py +3 -2
  18. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/masking_policies.py +5 -4
  19. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/plans.py +5 -4
  20. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/projects.py +6 -5
  21. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/scenario_files.py +6 -5
  22. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/sets.py +5 -4
  23. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/teams.py +11 -10
  24. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/templates.py +7 -6
  25. datamaker_py-0.11.0/src/datamaker/routes/tosca.py +270 -0
  26. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/routes/users.py +14 -8
  27. datamaker_py-0.11.0/src/datamaker/types.py +136 -0
  28. datamaker_py-0.11.0/src/datamaker_py.egg-info/PKG-INFO +143 -0
  29. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker_py.egg-info/SOURCES.txt +6 -1
  30. datamaker_py-0.11.0/tests/test_tosca.py +425 -0
  31. datamaker_py-0.9.0/PKG-INFO +0 -79
  32. datamaker_py-0.9.0/README.md +0 -68
  33. datamaker_py-0.9.0/src/datamaker/__init__.py +0 -2
  34. datamaker_py-0.9.0/src/datamaker/error.py +0 -2
  35. datamaker_py-0.9.0/src/datamaker_py.egg-info/PKG-INFO +0 -79
  36. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/LICENSE +0 -0
  37. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/setup.cfg +0 -0
  38. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/core.py +0 -0
  39. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker/template.py +0 -0
  40. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker_py.egg-info/dependency_links.txt +0 -0
  41. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker_py.egg-info/requires.txt +0 -0
  42. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/src/datamaker_py.egg-info/top_level.txt +0 -0
  43. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/tests/test_integration.py +0 -0
  44. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/tests/test_main.py +0 -0
  45. {datamaker_py-0.9.0 → datamaker_py-0.11.0}/tests/test_routes.py +0 -0
@@ -0,0 +1,143 @@
1
+ Metadata-Version: 2.4
2
+ Name: datamaker-py
3
+ Version: 0.11.0
4
+ Summary: The official Python library for the Automators DataMaker API.
5
+ Requires-Python: >=3.11
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Requires-Dist: python-dotenv>=1.0.1
9
+ Requires-Dist: requests>=2.32.3
10
+ Dynamic: license-file
11
+
12
+ # DataMaker
13
+
14
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
15
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
16
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v1.json)](https://github.com/charliermarsh/ruff)
17
+
18
+ The official Python library for the Automators DataMaker API.
19
+
20
+ ## Installation
21
+
22
+ You can install the package using pip:
23
+
24
+ ```sh
25
+ pip install datamaker-py
26
+ ```
27
+
28
+ ## Quick start
29
+
30
+ Basic example:
31
+
32
+ ```python
33
+ from datamaker import DataMaker, Template
34
+
35
+ # Create an instance of DataMaker
36
+ datamaker = DataMaker()
37
+
38
+
39
+ def main():
40
+ # Define the template
41
+ template = Template(
42
+ name="basic template",
43
+ quantity=2,
44
+ fields=[
45
+ {"name": "first_name", "type": "First Name"},
46
+ {"name": "last_name", "type": "Last Name"},
47
+ {
48
+ "name": "email",
49
+ "type": "Derived",
50
+ "options": {"value": "{{first_name}}.{{last_name}}@automators.com"},
51
+ },
52
+ ],
53
+ )
54
+
55
+ # Generate data using the template
56
+ result = datamaker.generate(template)
57
+ print(result)
58
+
59
+
60
+ if __name__ == "__main__":
61
+ main()
62
+
63
+ ```
64
+
65
+ ## Push a set into Tosca Cloud
66
+
67
+ `push_tosca_dataset` creates or replaces a native Tosca Cloud data set from a saved
68
+ set, an input set version, a dataset or inline rows. A Tosca test step reads it with
69
+ `{TDM[<data set>][<subset>][<column>]}`.
70
+
71
+ ```python
72
+ from datamaker import DataMaker, ToscaDatasetSchemaChangedError
73
+
74
+ dm = DataMaker()
75
+
76
+ try:
77
+ result = dm.push_tosca_dataset(
78
+ integration_id,
79
+ name="Orders",
80
+ input_set_id="is_123", # or set_id=..., dataset_id=..., rows=[...]
81
+ on_existing="overwrite", # "fail" (default) | "overwrite" | "new"
82
+ )
83
+ print(result.dataset_id, result.rows_count, result.outcome, result.example)
84
+ except ToscaDatasetSchemaChangedError as e:
85
+ # The rows dropped a column the data set has. Pass on_schema_change="recreate"
86
+ # to delete and recreate it instead.
87
+ print("removed:", e.removed_columns, "added:", e.added_columns)
88
+ ```
89
+
90
+ An input set gets one Tosca subset per test case by default; `subsets_by` picks another
91
+ column or turns it off with `False`. `get_tosca_datasets(integration_id)` lists what a
92
+ space already holds.
93
+
94
+ ## Autocomplete Types
95
+
96
+ This SDK automatically generates TypeScript autocomplete definitions for use in the [datamaker application](https://github.com/automators/datamaker).
97
+
98
+ The artifact is generated automatically on every push to the `main` branch and can be fetched from:
99
+
100
+ ```
101
+ https://raw.githubusercontent.com/automators/datamaker-py/main/artifacts/autocomplete-types.ts
102
+ ```
103
+
104
+ See [`artifacts/README.md`](artifacts/README.md) for more details.
105
+
106
+ ## Development & Contibutions
107
+
108
+ See the [contributing.md](/CONTRIBUTING.md) guide for details on how to contribute to this project.
109
+
110
+ ## Types
111
+
112
+ Response types are **generated** from the API's OpenAPI document, not hand-written:
113
+
114
+ ```
115
+ spec/openapi.json -> src/datamaker/generated/schema.py -> src/datamaker/types.py
116
+ ```
117
+
118
+ Import from `datamaker.types`, which resolves each spec schema name to the class
119
+ that really matches it:
120
+
121
+ ```python
122
+ from datamaker.types import Project, Plan, Template
123
+
124
+ projects: list[Project] = dm.get_projects()
125
+ ```
126
+
127
+ They are `TypedDict`s, so nothing changes at runtime — methods still return the
128
+ plain dicts `response.json()` produces, and `project["name"]` works exactly as
129
+ before. The types are checker-only.
130
+
131
+ To regenerate after the API changes:
132
+
133
+ ```bash
134
+ python scripts/generate_schema.py
135
+ ```
136
+
137
+ CI runs `python scripts/generate_schema.py --check` and fails if the committed
138
+ types drift from the spec.
139
+
140
+ Three schemas cannot currently be generated (`SetDetail`, `PackInstallListItem`,
141
+ `SchemaGraphNavigation`): they are composed with `allOf`, which the generator
142
+ merges away rather than emitting as a named class. Methods returning those keep
143
+ `Dict`. The generator script lists them explicitly and fails if the set grows.
@@ -0,0 +1,132 @@
1
+ # DataMaker
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
4
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
5
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v1.json)](https://github.com/charliermarsh/ruff)
6
+
7
+ The official Python library for the Automators DataMaker API.
8
+
9
+ ## Installation
10
+
11
+ You can install the package using pip:
12
+
13
+ ```sh
14
+ pip install datamaker-py
15
+ ```
16
+
17
+ ## Quick start
18
+
19
+ Basic example:
20
+
21
+ ```python
22
+ from datamaker import DataMaker, Template
23
+
24
+ # Create an instance of DataMaker
25
+ datamaker = DataMaker()
26
+
27
+
28
+ def main():
29
+ # Define the template
30
+ template = Template(
31
+ name="basic template",
32
+ quantity=2,
33
+ fields=[
34
+ {"name": "first_name", "type": "First Name"},
35
+ {"name": "last_name", "type": "Last Name"},
36
+ {
37
+ "name": "email",
38
+ "type": "Derived",
39
+ "options": {"value": "{{first_name}}.{{last_name}}@automators.com"},
40
+ },
41
+ ],
42
+ )
43
+
44
+ # Generate data using the template
45
+ result = datamaker.generate(template)
46
+ print(result)
47
+
48
+
49
+ if __name__ == "__main__":
50
+ main()
51
+
52
+ ```
53
+
54
+ ## Push a set into Tosca Cloud
55
+
56
+ `push_tosca_dataset` creates or replaces a native Tosca Cloud data set from a saved
57
+ set, an input set version, a dataset or inline rows. A Tosca test step reads it with
58
+ `{TDM[<data set>][<subset>][<column>]}`.
59
+
60
+ ```python
61
+ from datamaker import DataMaker, ToscaDatasetSchemaChangedError
62
+
63
+ dm = DataMaker()
64
+
65
+ try:
66
+ result = dm.push_tosca_dataset(
67
+ integration_id,
68
+ name="Orders",
69
+ input_set_id="is_123", # or set_id=..., dataset_id=..., rows=[...]
70
+ on_existing="overwrite", # "fail" (default) | "overwrite" | "new"
71
+ )
72
+ print(result.dataset_id, result.rows_count, result.outcome, result.example)
73
+ except ToscaDatasetSchemaChangedError as e:
74
+ # The rows dropped a column the data set has. Pass on_schema_change="recreate"
75
+ # to delete and recreate it instead.
76
+ print("removed:", e.removed_columns, "added:", e.added_columns)
77
+ ```
78
+
79
+ An input set gets one Tosca subset per test case by default; `subsets_by` picks another
80
+ column or turns it off with `False`. `get_tosca_datasets(integration_id)` lists what a
81
+ space already holds.
82
+
83
+ ## Autocomplete Types
84
+
85
+ This SDK automatically generates TypeScript autocomplete definitions for use in the [datamaker application](https://github.com/automators/datamaker).
86
+
87
+ The artifact is generated automatically on every push to the `main` branch and can be fetched from:
88
+
89
+ ```
90
+ https://raw.githubusercontent.com/automators/datamaker-py/main/artifacts/autocomplete-types.ts
91
+ ```
92
+
93
+ See [`artifacts/README.md`](artifacts/README.md) for more details.
94
+
95
+ ## Development & Contibutions
96
+
97
+ See the [contributing.md](/CONTRIBUTING.md) guide for details on how to contribute to this project.
98
+
99
+ ## Types
100
+
101
+ Response types are **generated** from the API's OpenAPI document, not hand-written:
102
+
103
+ ```
104
+ spec/openapi.json -> src/datamaker/generated/schema.py -> src/datamaker/types.py
105
+ ```
106
+
107
+ Import from `datamaker.types`, which resolves each spec schema name to the class
108
+ that really matches it:
109
+
110
+ ```python
111
+ from datamaker.types import Project, Plan, Template
112
+
113
+ projects: list[Project] = dm.get_projects()
114
+ ```
115
+
116
+ They are `TypedDict`s, so nothing changes at runtime — methods still return the
117
+ plain dicts `response.json()` produces, and `project["name"]` works exactly as
118
+ before. The types are checker-only.
119
+
120
+ To regenerate after the API changes:
121
+
122
+ ```bash
123
+ python scripts/generate_schema.py
124
+ ```
125
+
126
+ CI runs `python scripts/generate_schema.py --check` and fails if the committed
127
+ types drift from the spec.
128
+
129
+ Three schemas cannot currently be generated (`SetDetail`, `PackInstallListItem`,
130
+ `SchemaGraphNavigation`): they are composed with `allOf`, which the generator
131
+ merges away rather than emitting as a named class. Methods returning those keep
132
+ `Dict`. The generator script lists them explicitly and fails if the set grows.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "datamaker-py"
7
- version = "0.9.0"
7
+ version = "0.11.0"
8
8
  description = "The official Python library for the Automators DataMaker API."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -0,0 +1,12 @@
1
+ from .main import DataMaker # noqa
2
+ from .template import Template # noqa
3
+ from .error import ( # noqa
4
+ DataMakerError,
5
+ DataMakerAPIError,
6
+ ReadOnlyConnectionError,
7
+ ToscaDatasetExistsError,
8
+ ToscaDatasetLockedError,
9
+ ToscaDatasetSchemaChangedError,
10
+ ToscaDatasetTooLargeError,
11
+ )
12
+ from .routes.tosca import ToscaDatasetPushResult # noqa
@@ -0,0 +1,94 @@
1
+ from typing import Any, List, Optional
2
+
3
+
4
+ class DataMakerError(Exception):
5
+ pass
6
+
7
+
8
+ class DataMakerAPIError(DataMakerError):
9
+ """The API answered with a non-2xx status.
10
+
11
+ Subclasses ``DataMakerError`` and keeps its message, so existing
12
+ ``except DataMakerError`` handlers are unaffected. Adds the status code and
13
+ the decoded JSON body (``None`` when the body was not JSON).
14
+ """
15
+
16
+ def __init__(self, message: str, status_code: int, body: Any = None):
17
+ super().__init__(message)
18
+ self.status_code = status_code
19
+ self.body = body
20
+
21
+ def _detail(self, key: str) -> Any:
22
+ return self.body.get(key) if isinstance(self.body, dict) else None
23
+
24
+
25
+ class ReadOnlyConnectionError(DataMakerAPIError):
26
+ """403: the connection is read-only, so DataMaker refused the write."""
27
+
28
+
29
+ class ToscaDatasetExistsError(DataMakerAPIError):
30
+ """409: a Tosca data set of that name exists and ``on_existing`` is "fail"."""
31
+
32
+ @property
33
+ def dataset_id(self) -> Optional[str]:
34
+ """The id of the data set that is already there."""
35
+ return self._detail("datasetId")
36
+
37
+
38
+ class ToscaDatasetLockedError(DataMakerAPIError):
39
+ """409: the data set is locked in Tosca Cloud, so it cannot be overwritten.
40
+
41
+ A test run or a "Test data - Expert" step holds it. Retry once it is
42
+ unlocked.
43
+ """
44
+
45
+ @property
46
+ def dataset_id(self) -> Optional[str]:
47
+ return self._detail("datasetId")
48
+
49
+
50
+ class ToscaDatasetSchemaChangedError(DataMakerAPIError):
51
+ """409: an overwrite would drop columns the Tosca data set has.
52
+
53
+ Tosca only overwrites in place when the columns match. Added columns are
54
+ handled by the API; a removed column is refused unless the push asks for
55
+ ``on_schema_change="recreate"``.
56
+ """
57
+
58
+ @property
59
+ def dataset_id(self) -> Optional[str]:
60
+ return self._detail("datasetId")
61
+
62
+ @property
63
+ def added_columns(self) -> List[str]:
64
+ return self._detail("added") or []
65
+
66
+ @property
67
+ def removed_columns(self) -> List[str]:
68
+ return self._detail("removed") or []
69
+
70
+
71
+ class ToscaDatasetTooLargeError(DataMakerAPIError):
72
+ """413: more rows or bytes than one push may write.
73
+
74
+ The row pair (``max_rows``, ``rows``) or the byte pair (``max_bytes``,
75
+ ``bytes``) is set, depending on which cap was hit. A set, input set or
76
+ dataset refused before its rows are loaded carries neither; the message
77
+ names the cap.
78
+ """
79
+
80
+ @property
81
+ def max_rows(self) -> Optional[int]:
82
+ return self._detail("maxRows")
83
+
84
+ @property
85
+ def rows(self) -> Optional[int]:
86
+ return self._detail("rows")
87
+
88
+ @property
89
+ def max_bytes(self) -> Optional[int]:
90
+ return self._detail("maxBytes")
91
+
92
+ @property
93
+ def bytes(self) -> Optional[int]:
94
+ return self._detail("bytes")
@@ -0,0 +1,7 @@
1
+ """Types generated from the API's OpenAPI document. Do not edit by hand.
2
+
3
+ Regenerate with `python scripts/generate_schema.py`; CI fails if this drifts
4
+ from `spec/openapi.json`.
5
+ """
6
+
7
+ from .schema import * # noqa: F401,F403