konecty-sdk-python 2.0.1__tar.gz → 2.0.2__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. konecty_sdk_python-2.0.2/KonectySdkPython/lib/feature_types/__init__.py +46 -0
  2. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/feature_types/cross_module_query.py +9 -3
  3. konecty_sdk_python-2.0.2/KonectySdkPython/lib/feature_types/query_json.py +242 -0
  4. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/services/query.py +3 -1
  5. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/PKG-INFO +1 -1
  6. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/pyproject.toml +1 -1
  7. konecty_sdk_python-2.0.1/KonectySdkPython/lib/feature_types/__init__.py +0 -22
  8. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/.gitignore +0 -0
  9. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/__init__.py +0 -0
  10. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/cli/__init__.py +0 -0
  11. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/cli/apply.py +0 -0
  12. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/cli/backup.py +0 -0
  13. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/cli/pull.py +0 -0
  14. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/__init__.py +0 -0
  15. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/client.py +0 -0
  16. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/exceptions.py +0 -0
  17. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/feature_types/kpi.py +0 -0
  18. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/file_manager.py +0 -0
  19. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/filters.py +0 -0
  20. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/http.py +0 -0
  21. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/model.py +0 -0
  22. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/serialization.py +0 -0
  23. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/services/__init__.py +0 -0
  24. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/services/aggregation.py +0 -0
  25. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/services/base.py +0 -0
  26. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/services/change_user.py +0 -0
  27. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/services/comments.py +0 -0
  28. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/services/export.py +0 -0
  29. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/services/files.py +0 -0
  30. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/services/notifications.py +0 -0
  31. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/services/stream.py +0 -0
  32. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/services/subscriptions.py +0 -0
  33. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/settings.py +0 -0
  34. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/KonectySdkPython/lib/types.py +0 -0
  35. {konecty_sdk_python-2.0.1 → konecty_sdk_python-2.0.2}/README.md +0 -0
@@ -0,0 +1,46 @@
1
+ """Feature-specific types (KPI, Graph, Pivot, CrossModuleQuery, QueryJson, etc.). Re-exported for convenience."""
2
+
3
+ from .cross_module_query import (
4
+ DEFAULT_PRIMARY_LIMIT,
5
+ MAX_RELATION_LIMIT,
6
+ MAX_RELATIONS,
7
+ Aggregator,
8
+ CrossModuleQuery,
9
+ CrossModuleRelation,
10
+ )
11
+ from .kpi import KpiConfig, KpiOperation
12
+ from .query_json import (
13
+ AggregatorName,
14
+ AggregatorSpec,
15
+ ConditionValue,
16
+ ExplicitJoinCondition,
17
+ FilterMatch,
18
+ QueryFilter,
19
+ QueryFilterCondition,
20
+ QueryJson,
21
+ QueryRelation,
22
+ QuerySortItem,
23
+ SortDirection,
24
+ )
25
+
26
+ __all__ = [
27
+ "Aggregator",
28
+ "AggregatorName",
29
+ "AggregatorSpec",
30
+ "ConditionValue",
31
+ "CrossModuleQuery",
32
+ "CrossModuleRelation",
33
+ "DEFAULT_PRIMARY_LIMIT",
34
+ "ExplicitJoinCondition",
35
+ "FilterMatch",
36
+ "KpiConfig",
37
+ "KpiOperation",
38
+ "MAX_RELATION_LIMIT",
39
+ "MAX_RELATIONS",
40
+ "QueryFilter",
41
+ "QueryFilterCondition",
42
+ "QueryJson",
43
+ "QueryRelation",
44
+ "QuerySortItem",
45
+ "SortDirection",
46
+ ]
@@ -10,7 +10,9 @@ MAX_RELATION_LIMIT = 100_000
10
10
  DEFAULT_RELATION_LIMIT = 1000
11
11
  DEFAULT_PRIMARY_LIMIT = 1000
12
12
 
13
- AggregatorName = str # count, countDistinct, sum, avg, min, max, first, last, push, addToSet
13
+ AggregatorName = (
14
+ str # count, countDistinct, sum, avg, min, max, first, last, push, addToSet
15
+ )
14
16
 
15
17
 
16
18
  class Aggregator(BaseModel):
@@ -46,7 +48,9 @@ class CrossModuleRelation(BaseModel):
46
48
  limit: int = Field(default=DEFAULT_RELATION_LIMIT, ge=1, le=MAX_RELATION_LIMIT)
47
49
  start: int = Field(default=0, ge=0)
48
50
  aggregators: Dict[str, Aggregator] = Field(..., min_length=1)
49
- relations: Optional[List["CrossModuleRelation"]] = Field(default=None, max_length=MAX_RELATIONS)
51
+ relations: Optional[List["CrossModuleRelation"]] = Field(
52
+ default=None, max_length=MAX_RELATIONS
53
+ )
50
54
 
51
55
  model_config = {"extra": "allow"}
52
56
 
@@ -63,7 +67,9 @@ class CrossModuleQuery(BaseModel):
63
67
  sort: Optional[Union[str, List[SortItem]]] = None
64
68
  limit: int = Field(default=DEFAULT_PRIMARY_LIMIT, ge=1, le=MAX_RELATION_LIMIT)
65
69
  start: int = Field(default=0, ge=0)
66
- relations: List[CrossModuleRelation] = Field(default_factory=list, max_length=MAX_RELATIONS)
70
+ relations: List[CrossModuleRelation] = Field(
71
+ default_factory=list, max_length=MAX_RELATIONS
72
+ )
67
73
  groupBy: List[str] = Field(default_factory=list, alias="groupBy")
68
74
  aggregators: Dict[str, Aggregator] = Field(default_factory=dict)
69
75
  includeTotal: bool = Field(default=True, alias="includeTotal")
@@ -0,0 +1,242 @@
1
+ """
2
+ Strongly-typed query creator for POST /rest/query/json (Konecty cross-module query).
3
+ Use classes/dataclasses with properties for full intellisense; no builder pattern.
4
+ Serializes to the exact payload Konecty expects via to_dict().
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from dataclasses import dataclass, field
10
+ from typing import Any, Dict, List, Literal, Optional, Union
11
+
12
+ # ---------------------------------------------------------------------------
13
+ # Literal types (Konecty schema)
14
+ # ---------------------------------------------------------------------------
15
+
16
+ AggregatorName = Literal[
17
+ "count",
18
+ "countDistinct",
19
+ "sum",
20
+ "avg",
21
+ "min",
22
+ "max",
23
+ "first",
24
+ "last",
25
+ "push",
26
+ "addToSet",
27
+ ]
28
+ """Allowed aggregator names for relations (Konecty schema)."""
29
+
30
+ FilterMatch = Literal["and", "or"]
31
+ SortDirection = Literal["ASC", "DESC"]
32
+
33
+ # Value in a filter condition: scalar or list (e.g. for "in" operator)
34
+ ConditionValue = Union[str, int, float, bool, None, List[Union[str, int, float, bool]]]
35
+
36
+
37
+ # ---------------------------------------------------------------------------
38
+ # Filter (KonFilter)
39
+ # ---------------------------------------------------------------------------
40
+
41
+
42
+ @dataclass(frozen=False)
43
+ class QueryFilterCondition:
44
+ """Single condition: term, operator, optional value. Mirrors Konecty Condition."""
45
+
46
+ term: str
47
+ operator: str
48
+ value: Optional[ConditionValue] = None
49
+ editable: Optional[bool] = None
50
+ disabled: Optional[bool] = None
51
+ sort: Optional[int] = None
52
+
53
+ def to_dict(self) -> Dict[str, Any]:
54
+ out: Dict[str, Any] = {"term": self.term, "operator": self.operator}
55
+ if self.value is not None:
56
+ out["value"] = self.value
57
+ if self.editable is not None:
58
+ out["editable"] = self.editable
59
+ if self.disabled is not None:
60
+ out["disabled"] = self.disabled
61
+ if self.sort is not None:
62
+ out["sort"] = self.sort
63
+ return out
64
+
65
+
66
+ @dataclass(frozen=False)
67
+ class QueryFilter:
68
+ """Filter for query or relation. match + conditions; optional textSearch and nested filters."""
69
+
70
+ match: FilterMatch = "and"
71
+ conditions: List[QueryFilterCondition] = field(default_factory=list)
72
+ text_search: Optional[str] = None
73
+ filters: Optional[List["QueryFilter"]] = None
74
+
75
+ def to_dict(self) -> Dict[str, Any]:
76
+ out: Dict[str, Any] = {"match": self.match}
77
+ if self.conditions:
78
+ out["conditions"] = [c.to_dict() for c in self.conditions]
79
+ if self.text_search is not None:
80
+ out["textSearch"] = self.text_search
81
+ if self.filters:
82
+ out["filters"] = [f.to_dict() for f in self.filters]
83
+ return out
84
+
85
+
86
+ # ---------------------------------------------------------------------------
87
+ # Sort
88
+ # ---------------------------------------------------------------------------
89
+
90
+
91
+ @dataclass(frozen=True)
92
+ class QuerySortItem:
93
+ """Sort item: property and direction. Konecty sort element."""
94
+
95
+ property: str
96
+ direction: SortDirection = "ASC"
97
+
98
+ def to_dict(self) -> Dict[str, Any]:
99
+ return {"property": self.property, "direction": self.direction}
100
+
101
+
102
+ # ---------------------------------------------------------------------------
103
+ # Join (explicit on)
104
+ # ---------------------------------------------------------------------------
105
+
106
+
107
+ @dataclass(frozen=True)
108
+ class ExplicitJoinCondition:
109
+ """Explicit join: left and right keys. Optional in relation."""
110
+
111
+ left: str
112
+ right: str
113
+
114
+ def to_dict(self) -> Dict[str, Any]:
115
+ return {"left": self.left, "right": self.right}
116
+
117
+
118
+ # ---------------------------------------------------------------------------
119
+ # Aggregator
120
+ # ---------------------------------------------------------------------------
121
+
122
+
123
+ @dataclass(frozen=True)
124
+ class AggregatorSpec:
125
+ """Aggregator in a relation. aggregator (name); field required for countDistinct and similar."""
126
+
127
+ aggregator: AggregatorName
128
+ field: Optional[str] = None
129
+
130
+ def to_dict(self) -> Dict[str, Any]:
131
+ out: Dict[str, Any] = {"aggregator": self.aggregator}
132
+ if self.field is not None:
133
+ out["field"] = self.field
134
+ return out
135
+
136
+
137
+ # ---------------------------------------------------------------------------
138
+ # Relation (nested)
139
+ # ---------------------------------------------------------------------------
140
+
141
+ # Sort in relation: list of QuerySortItem or single string (e.g. "_createdAt DESC")
142
+ RelationSort = Union[List[QuerySortItem], str]
143
+
144
+
145
+ @dataclass(frozen=False)
146
+ class QueryRelation:
147
+ """
148
+ Relation in a cross-module query. document + lookup; at least one aggregator required.
149
+ Optional: on, filter, fields, sort, limit, start; optional nested relations.
150
+ """
151
+
152
+ document: str
153
+ lookup: str
154
+ aggregators: Dict[str, AggregatorSpec]
155
+ on: Optional[ExplicitJoinCondition] = None
156
+ filter: Optional[QueryFilter] = None
157
+ fields: Optional[str] = None
158
+ sort: Optional[RelationSort] = None
159
+ limit: int = 1000
160
+ start: int = 0
161
+ relations: Optional[List["QueryRelation"]] = None
162
+
163
+ def to_dict(self) -> Dict[str, Any]:
164
+ if not self.aggregators:
165
+ raise ValueError("At least one aggregator is required per relation")
166
+ out: Dict[str, Any] = {
167
+ "document": self.document,
168
+ "lookup": self.lookup,
169
+ "aggregators": {k: v.to_dict() for k, v in self.aggregators.items()},
170
+ "limit": self.limit,
171
+ "start": self.start,
172
+ }
173
+ if self.on is not None:
174
+ out["on"] = self.on.to_dict()
175
+ if self.filter is not None:
176
+ out["filter"] = self.filter.to_dict()
177
+ if self.fields is not None:
178
+ out["fields"] = self.fields
179
+ if self.sort is not None:
180
+ if isinstance(self.sort, str):
181
+ out["sort"] = self.sort
182
+ else:
183
+ out["sort"] = [s.to_dict() for s in self.sort]
184
+ if self.relations:
185
+ out["relations"] = [r.to_dict() for r in self.relations]
186
+ return out
187
+
188
+
189
+ # ---------------------------------------------------------------------------
190
+ # Root query (CrossModuleQuery)
191
+ # ---------------------------------------------------------------------------
192
+
193
+ # Sort at root: list of QuerySortItem or string
194
+ QuerySort = Union[List[QuerySortItem], str]
195
+
196
+ # Limits (Konecty constants)
197
+ MAX_RELATION_LIMIT_QUERY = 100_000
198
+ DEFAULT_PRIMARY_LIMIT_QUERY = 1000
199
+
200
+
201
+ @dataclass(frozen=False)
202
+ class QueryJson:
203
+ """
204
+ Fully-typed body for POST /rest/query/json. Primary document + optional filter,
205
+ fields, sort, limit, start, relations, groupBy, aggregators, includeTotal, includeMeta.
206
+ Use to_dict() to get the API payload (camelCase where required).
207
+ """
208
+
209
+ document: str
210
+ filter: Optional[QueryFilter] = None
211
+ fields: Optional[str] = None
212
+ sort: Optional[QuerySort] = None
213
+ limit: int = DEFAULT_PRIMARY_LIMIT_QUERY
214
+ start: int = 0
215
+ relations: List[QueryRelation] = field(default_factory=list)
216
+ group_by: List[str] = field(default_factory=list)
217
+ aggregators: Dict[str, AggregatorSpec] = field(default_factory=dict)
218
+ include_total: bool = True
219
+ include_meta: bool = False
220
+
221
+ def to_dict(self) -> Dict[str, Any]:
222
+ """Payload for POST /rest/query/json (camelCase for includeTotal, includeMeta, groupBy)."""
223
+ out: Dict[str, Any] = {
224
+ "document": self.document,
225
+ "limit": max(1, min(self.limit, MAX_RELATION_LIMIT_QUERY)),
226
+ "start": max(0, self.start),
227
+ "relations": [r.to_dict() for r in self.relations],
228
+ "groupBy": self.group_by,
229
+ "aggregators": {k: v.to_dict() for k, v in self.aggregators.items()},
230
+ "includeTotal": self.include_total,
231
+ "includeMeta": self.include_meta,
232
+ }
233
+ if self.filter is not None:
234
+ out["filter"] = self.filter.to_dict()
235
+ if self.fields is not None:
236
+ out["fields"] = self.fields
237
+ if self.sort is not None:
238
+ if isinstance(self.sort, str):
239
+ out["sort"] = self.sort
240
+ else:
241
+ out["sort"] = [s.to_dict() for s in self.sort]
242
+ return out
@@ -93,7 +93,9 @@ class QueryService(BaseService):
93
93
  Execute a cross-module query. POST /rest/query/json. Body is CrossModuleQuery (dict or model).
94
94
  Returns QueryResult with .stream (async generator), .total, .meta.
95
95
  """
96
- if hasattr(body, "model_dump"):
96
+ if hasattr(body, "to_dict"):
97
+ payload = body.to_dict()
98
+ elif hasattr(body, "model_dump"):
97
99
  payload = body.model_dump(by_alias=True, exclude_none=True)
98
100
  else:
99
101
  payload = dict(body)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: konecty_sdk_python
3
- Version: 2.0.1
3
+ Version: 2.0.2
4
4
  Summary: Konecty SDK Python
5
5
  Author-email: Leonardo Leal <leonardo.leal@konecty.com>, Derotino Silveira <derotino.silveira@konecty.com>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "konecty_sdk_python"
3
- version = "2.0.1"
3
+ version = "2.0.2"
4
4
  description = "Konecty SDK Python"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -1,22 +0,0 @@
1
- """Feature-specific types (KPI, Graph, Pivot, CrossModuleQuery, etc.). Re-exported for convenience."""
2
-
3
- from .cross_module_query import (
4
- CrossModuleQuery,
5
- CrossModuleRelation,
6
- Aggregator,
7
- DEFAULT_PRIMARY_LIMIT,
8
- MAX_RELATION_LIMIT,
9
- MAX_RELATIONS,
10
- )
11
- from .kpi import KpiConfig, KpiOperation
12
-
13
- __all__ = [
14
- "Aggregator",
15
- "CrossModuleQuery",
16
- "CrossModuleRelation",
17
- "DEFAULT_PRIMARY_LIMIT",
18
- "KpiConfig",
19
- "KpiOperation",
20
- "MAX_RELATION_LIMIT",
21
- "MAX_RELATIONS",
22
- ]