datamaker-py 0.8.0__tar.gz → 0.9.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 (35) hide show
  1. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/PKG-INFO +1 -1
  2. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/pyproject.toml +1 -1
  3. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/main.py +145 -0
  4. datamaker_py-0.9.0/src/datamaker/routes/masking_policies.py +130 -0
  5. datamaker_py-0.9.0/src/datamaker/routes/plans.py +72 -0
  6. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker_py.egg-info/PKG-INFO +1 -1
  7. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker_py.egg-info/SOURCES.txt +2 -0
  8. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/LICENSE +0 -0
  9. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/README.md +0 -0
  10. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/setup.cfg +0 -0
  11. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/__init__.py +0 -0
  12. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/core.py +0 -0
  13. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/error.py +0 -0
  14. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/__init__.py +0 -0
  15. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/api_keys.py +0 -0
  16. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/base.py +0 -0
  17. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/connections.py +0 -0
  18. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/custom_types.py +0 -0
  19. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/export_and_validation.py +0 -0
  20. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/folders_and_utils.py +0 -0
  21. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/generation.py +0 -0
  22. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/keymaps.py +0 -0
  23. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/projects.py +0 -0
  24. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/scenario_files.py +0 -0
  25. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/sets.py +0 -0
  26. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/teams.py +0 -0
  27. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/templates.py +0 -0
  28. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/routes/users.py +0 -0
  29. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker/template.py +0 -0
  30. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker_py.egg-info/dependency_links.txt +0 -0
  31. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker_py.egg-info/requires.txt +0 -0
  32. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/src/datamaker_py.egg-info/top_level.txt +0 -0
  33. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/tests/test_integration.py +0 -0
  34. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/tests/test_main.py +0 -0
  35. {datamaker_py-0.8.0 → datamaker_py-0.9.0}/tests/test_routes.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datamaker-py
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: The official Python library for the Automators DataMaker API.
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "datamaker-py"
7
- version = "0.8.0"
7
+ version = "0.9.0"
8
8
  description = "The official Python library for the Automators DataMaker API."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -22,6 +22,8 @@ from .routes.folders_and_utils import (
22
22
  from .routes.export_and_validation import ExportClient, ValidationClient
23
23
  from .routes.scenario_files import ScenarioFilesClient
24
24
  from .routes.sets import SetsClient
25
+ from .routes.plans import PlansClient
26
+ from .routes.masking_policies import MaskingPoliciesClient
25
27
  from .routes.keymaps import KeyMapsClient
26
28
 
27
29
  load_dotenv()
@@ -72,6 +74,10 @@ class DataMaker:
72
74
  )
73
75
  self._sets = SetsClient(api_key, default_headers, base_url, verify)
74
76
  self._keymaps = KeyMapsClient(api_key, default_headers, base_url, verify)
77
+ self._plans = PlansClient(api_key, default_headers, base_url, verify)
78
+ self._masking_policies = MaskingPoliciesClient(
79
+ api_key, default_headers, base_url, verify
80
+ )
75
81
 
76
82
  # Maintain backward compatibility
77
83
  self.api_key = self._generation.api_key
@@ -932,6 +938,135 @@ class DataMaker:
932
938
 
933
939
  # =================== PROPERTY ACCESS TO CLIENTS ===================
934
940
  # For advanced users who want direct access to specific clients
941
+
942
+ # =================== PLAN METHODS ===================
943
+ def get_plans(self):
944
+ """List the plans in the caller's active project.
945
+
946
+ Returns:
947
+ A list of plan dictionaries.
948
+ """
949
+ return self._plans.get_plans()
950
+
951
+ def get_plan(self, plan_id: str):
952
+ """Get a single plan by ID, including its full spec and history.
953
+
954
+ Args:
955
+ plan_id: The unique identifier of the plan.
956
+
957
+ Returns:
958
+ The plan dictionary.
959
+ """
960
+ return self._plans.get_plan(plan_id)
961
+
962
+ def update_plan(self, plan_id: str, **fields):
963
+ """Update a plan.
964
+
965
+ Args:
966
+ plan_id: The unique identifier of the plan.
967
+ **fields: Fields to change, e.g. title, summary, status.
968
+
969
+ Returns:
970
+ The updated plan dictionary.
971
+ """
972
+ return self._plans.update_plan(plan_id, **fields)
973
+
974
+ def delete_plan(self, plan_id: str):
975
+ """Delete a plan.
976
+
977
+ Args:
978
+ plan_id: The unique identifier of the plan.
979
+
980
+ Returns:
981
+ ``{"success": True}``. Note this differs from the other resources,
982
+ which answer ``{"message": ...}``.
983
+ """
984
+ return self._plans.delete_plan(plan_id)
985
+
986
+ # =================== MASKING POLICY METHODS ===================
987
+ def get_masking_policies(self, project_id: Optional[str] = None):
988
+ """Get the masking policies in the caller's project/team scope.
989
+
990
+ Args:
991
+ project_id: Optional project ID to scope the listing to. Falls back
992
+ to the DATAMAKER_PROJECT_ID env var.
993
+
994
+ Returns:
995
+ A list of masking policy dictionaries.
996
+ """
997
+ return self._masking_policies.get_masking_policies(project_id)
998
+
999
+ def get_masking_policy(self, policy_id: str):
1000
+ """Get a single masking policy by ID.
1001
+
1002
+ Args:
1003
+ policy_id: The unique identifier of the policy.
1004
+
1005
+ Returns:
1006
+ The masking policy dictionary.
1007
+ """
1008
+ return self._masking_policies.get_masking_policy(policy_id)
1009
+
1010
+ def create_masking_policy(
1011
+ self,
1012
+ name: str,
1013
+ fields,
1014
+ description: Optional[str] = None,
1015
+ consistent: Optional[bool] = None,
1016
+ reversible: Optional[bool] = None,
1017
+ key_map_name: Optional[str] = None,
1018
+ project_id: Optional[str] = None,
1019
+ ):
1020
+ """Create a masking policy.
1021
+
1022
+ Args:
1023
+ name: The policy name.
1024
+ fields: The field rule list.
1025
+ description: Optional description.
1026
+ consistent: Same input masks to the same output. Omit to take the
1027
+ API's default.
1028
+ reversible: Record the mapping so masking can be reversed. Needs
1029
+ key_map_name to be useful.
1030
+ key_map_name: The KeyMap a reversible policy mints mappings into.
1031
+ project_id: Project to create it in. Falls back to
1032
+ DATAMAKER_PROJECT_ID.
1033
+
1034
+ Returns:
1035
+ The created masking policy dictionary.
1036
+ """
1037
+ return self._masking_policies.create_masking_policy(
1038
+ name=name,
1039
+ fields=fields,
1040
+ description=description,
1041
+ consistent=consistent,
1042
+ reversible=reversible,
1043
+ key_map_name=key_map_name,
1044
+ project_id=project_id,
1045
+ )
1046
+
1047
+ def update_masking_policy(self, policy_id: str, **fields):
1048
+ """Update a masking policy.
1049
+
1050
+ Args:
1051
+ policy_id: The unique identifier of the policy.
1052
+ **fields: Fields to change. Use API spellings, e.g. keyMapName.
1053
+
1054
+ Returns:
1055
+ The updated masking policy dictionary.
1056
+ """
1057
+ return self._masking_policies.update_masking_policy(policy_id, **fields)
1058
+
1059
+ def delete_masking_policy(self, policy_id: str):
1060
+ """Delete a masking policy.
1061
+
1062
+ Args:
1063
+ policy_id: The unique identifier of the policy.
1064
+
1065
+ Returns:
1066
+ ``{"message": "Masking policy deleted"}``.
1067
+ """
1068
+ return self._masking_policies.delete_masking_policy(policy_id)
1069
+
935
1070
  @property
936
1071
  def generation(self):
937
1072
  """Access to generation client."""
@@ -1026,3 +1161,13 @@ class DataMaker:
1026
1161
  def keymaps(self):
1027
1162
  """Access to key maps client."""
1028
1163
  return self._keymaps
1164
+
1165
+ @property
1166
+ def plans(self):
1167
+ """Access to plans client."""
1168
+ return self._plans
1169
+
1170
+ @property
1171
+ def masking_policies(self):
1172
+ """Access to masking policies client."""
1173
+ return self._masking_policies
@@ -0,0 +1,130 @@
1
+ """Client for masking policy operations.
2
+
3
+ A masking policy is the set of field rules a masked generation or export
4
+ applies. Two flags decide how it behaves, and they are easy to confuse:
5
+
6
+ ``consistent``
7
+ The same input masks to the same output within the policy, so joins across
8
+ masked tables still line up.
9
+
10
+ ``reversible``
11
+ The mapping is recorded so it can be reversed later. A reversible policy
12
+ mints its mappings into the KeyMap named by ``key_map_name``, which is why
13
+ that argument only means anything alongside it.
14
+ """
15
+
16
+ import os
17
+ from typing import Any, Dict, List, Optional
18
+
19
+ from .base import BaseClient
20
+
21
+
22
+ class MaskingPoliciesClient(BaseClient):
23
+ """Client for masking policy operations."""
24
+
25
+ def get_masking_policies(
26
+ self, project_id: Optional[str] = None
27
+ ) -> List[Dict[str, Any]]:
28
+ """Fetch the masking policies in the caller's project/team scope.
29
+
30
+ Args:
31
+ project_id: Optional project ID to scope the listing to. Falls back
32
+ to the DATAMAKER_PROJECT_ID env var.
33
+
34
+ Returns:
35
+ A list of masking policy dictionaries.
36
+ """
37
+ project_id = project_id or os.environ.get("DATAMAKER_PROJECT_ID")
38
+
39
+ endpoint = "/masking-policies"
40
+ if project_id:
41
+ endpoint += f"?projectId={project_id}"
42
+
43
+ response = self._make_request("GET", endpoint)
44
+ return response.json()
45
+
46
+ def get_masking_policy(self, policy_id: str) -> Dict[str, Any]:
47
+ """Get a single masking policy by ID.
48
+
49
+ Args:
50
+ policy_id: The policy's ID.
51
+
52
+ Returns:
53
+ The masking policy dictionary.
54
+ """
55
+ response = self._make_request("GET", f"/masking-policies/{policy_id}")
56
+ return response.json()
57
+
58
+ def create_masking_policy(
59
+ self,
60
+ name: str,
61
+ fields: Any,
62
+ description: Optional[str] = None,
63
+ consistent: Optional[bool] = None,
64
+ reversible: Optional[bool] = None,
65
+ key_map_name: Optional[str] = None,
66
+ project_id: Optional[str] = None,
67
+ ) -> Dict[str, Any]:
68
+ """Create a masking policy.
69
+
70
+ Args:
71
+ name: The policy name.
72
+ fields: The field rule list. Shape varies by rule type.
73
+ description: Optional description.
74
+ consistent: Same input masks to the same output. Defaults to the
75
+ API's own default (True) when omitted.
76
+ reversible: Record the mapping so masking can be reversed. Requires
77
+ ``key_map_name`` to be useful.
78
+ key_map_name: The KeyMap a reversible policy mints mappings into.
79
+ project_id: Project to create it in. Falls back to
80
+ DATAMAKER_PROJECT_ID.
81
+
82
+ Returns:
83
+ The created masking policy dictionary.
84
+ """
85
+ project_id = project_id or os.environ.get("DATAMAKER_PROJECT_ID")
86
+
87
+ # Only send what the caller set: omitting a key lets the API apply its
88
+ # own default, whereas sending null would override it.
89
+ payload: Dict[str, Any] = {"name": name, "fields": fields}
90
+ if description is not None:
91
+ payload["description"] = description
92
+ if consistent is not None:
93
+ payload["consistent"] = consistent
94
+ if reversible is not None:
95
+ payload["reversible"] = reversible
96
+ if key_map_name is not None:
97
+ payload["keyMapName"] = key_map_name
98
+ if project_id:
99
+ payload["projectId"] = project_id
100
+
101
+ response = self._make_request("POST", "/masking-policies", json=payload)
102
+ return response.json()
103
+
104
+ def update_masking_policy(self, policy_id: str, **fields: Any) -> Dict[str, Any]:
105
+ """Update a masking policy.
106
+
107
+ Args:
108
+ policy_id: The policy's ID.
109
+ **fields: Fields to change. Use API spellings for multi-word keys,
110
+ e.g. ``keyMapName``.
111
+
112
+ Returns:
113
+ The updated masking policy dictionary.
114
+ """
115
+ response = self._make_request(
116
+ "PATCH", f"/masking-policies/{policy_id}", json=fields
117
+ )
118
+ return response.json()
119
+
120
+ def delete_masking_policy(self, policy_id: str) -> Dict[str, Any]:
121
+ """Delete a masking policy.
122
+
123
+ Args:
124
+ policy_id: The policy's ID.
125
+
126
+ Returns:
127
+ ``{"message": "Masking policy deleted"}``.
128
+ """
129
+ response = self._make_request("DELETE", f"/masking-policies/{policy_id}")
130
+ return response.json()
@@ -0,0 +1,72 @@
1
+ """Client for Plan operations.
2
+
3
+ A Plan is a reviewable description of work the agent (or a person) intends to
4
+ carry out: which entities, which targets, how many rows, and against which
5
+ environment. Plans are the governed path - they are authored, reviewed and only
6
+ then run - which is why this client covers authoring and inspection rather than
7
+ execution.
8
+
9
+ The plan RUN endpoints (`/plans/{id}/run`, `/runs`, `/signoffs`) are not wrapped
10
+ yet: they carry artifacts, logs and multi-step state, and their response shapes
11
+ are not described in the API's OpenAPI document at the time of writing. Use
12
+ ``client.plans._make_request`` or add them here once the API types them.
13
+ """
14
+
15
+ from typing import Any, Dict, List
16
+
17
+ from .base import BaseClient
18
+
19
+
20
+ class PlansClient(BaseClient):
21
+ """Client for plan operations."""
22
+
23
+ def get_plans(self) -> List[Dict[str, Any]]:
24
+ """List the plans in the caller's active project.
25
+
26
+ Returns:
27
+ A list of plan dictionaries, newest first.
28
+ """
29
+ response = self._make_request("GET", "/plans")
30
+ return response.json()
31
+
32
+ def get_plan(self, plan_id: str) -> Dict[str, Any]:
33
+ """Get a single plan by ID, including its full ``spec`` and ``history``.
34
+
35
+ Args:
36
+ plan_id: The plan's ID.
37
+
38
+ Returns:
39
+ The plan dictionary.
40
+ """
41
+ response = self._make_request("GET", f"/plans/{plan_id}")
42
+ return response.json()
43
+
44
+ def update_plan(self, plan_id: str, **fields: Any) -> Dict[str, Any]:
45
+ """Update a plan.
46
+
47
+ Args:
48
+ plan_id: The plan's ID.
49
+ **fields: Fields to change, e.g. ``title``, ``summary``, ``status``.
50
+
51
+ Returns:
52
+ The updated plan dictionary.
53
+ """
54
+ response = self._make_request("PATCH", f"/plans/{plan_id}", json=fields)
55
+ return response.json()
56
+
57
+ def delete_plan(self, plan_id: str) -> Dict[str, Any]:
58
+ """Delete a plan.
59
+
60
+ Note:
61
+ This endpoint answers ``{"success": true}``, unlike the other
62
+ resources, which answer ``{"message": ...}``. Returned as-is rather
63
+ than normalised, so the SDK reports what the API actually sent.
64
+
65
+ Args:
66
+ plan_id: The plan's ID.
67
+
68
+ Returns:
69
+ ``{"success": True}``.
70
+ """
71
+ response = self._make_request("DELETE", f"/plans/{plan_id}")
72
+ return response.json()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datamaker-py
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: The official Python library for the Automators DataMaker API.
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -15,6 +15,8 @@ src/datamaker/routes/export_and_validation.py
15
15
  src/datamaker/routes/folders_and_utils.py
16
16
  src/datamaker/routes/generation.py
17
17
  src/datamaker/routes/keymaps.py
18
+ src/datamaker/routes/masking_policies.py
19
+ src/datamaker/routes/plans.py
18
20
  src/datamaker/routes/projects.py
19
21
  src/datamaker/routes/scenario_files.py
20
22
  src/datamaker/routes/sets.py
File without changes
File without changes
File without changes