mindbridge-api-python-client 1.5.1__tar.gz → 1.6.1__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 (64) hide show
  1. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/PKG-INFO +7 -9
  2. mindbridge_api_python_client-1.6.1/pyproject.toml +148 -0
  3. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/__init__.py +2 -2
  4. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/account_grouping_item.py +0 -2
  5. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/account_groupings.py +0 -3
  6. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/account_groups.py +4 -23
  7. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/account_mappings.py +4 -23
  8. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/analyses.py +0 -6
  9. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/analysis_period.py +2 -5
  10. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/analysis_source_item.py +15 -15
  11. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/analysis_sources.py +3 -3
  12. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/async_result_item.py +5 -3
  13. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/base_set.py +9 -1
  14. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/common_validators.py +37 -4
  15. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/data_tables.py +26 -52
  16. mindbridge_api_python_client-1.6.1/src/mindbridgeapi/engagement_account_group_item.py +21 -0
  17. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/engagement_account_grouping_item.py +18 -1
  18. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/engagement_account_groupings.py +26 -2
  19. mindbridge_api_python_client-1.6.1/src/mindbridgeapi/engagement_account_groups.py +41 -0
  20. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/engagement_item.py +3 -3
  21. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/enumerations/deprecated_enum.py +3 -3
  22. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/file_manager_item.py +3 -18
  23. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/generated_pydantic_model/model.py +209 -6
  24. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/server.py +18 -4
  25. mindbridge_api_python_client-1.6.1/src/mindbridgeapi/task_histories.py +39 -0
  26. mindbridge_api_python_client-1.6.1/src/mindbridgeapi/task_history_item.py +40 -0
  27. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/task_item.py +18 -3
  28. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/tasks.py +25 -24
  29. mindbridge_api_python_client-1.6.1/src/mindbridgeapi/transaction_id_preview_item.py +56 -0
  30. mindbridge_api_python_client-1.6.1/src/mindbridgeapi/transaction_id_previews.py +39 -0
  31. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/transaction_id_selection.py +4 -2
  32. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/virtual_column.py +1 -1
  33. mindbridge_api_python_client-1.5.1/pyproject.toml +0 -126
  34. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/LICENSE.txt +0 -0
  35. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/README.md +0 -0
  36. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/account_group_item.py +0 -0
  37. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/account_mapping_item.py +0 -0
  38. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/accounting_period.py +0 -0
  39. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/analysis_item.py +0 -0
  40. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/analysis_result_item.py +0 -0
  41. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/analysis_results.py +0 -0
  42. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/analysis_source_type_item.py +0 -0
  43. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/analysis_source_types.py +0 -0
  44. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/analysis_type_item.py +0 -0
  45. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/analysis_types.py +0 -0
  46. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/async_results.py +0 -0
  47. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/chunked_file_item.py +0 -0
  48. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/chunked_file_part_item.py +0 -0
  49. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/chunked_files.py +0 -0
  50. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/column_mapping.py +0 -0
  51. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/engagements.py +0 -0
  52. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/enumerations/analysis_source_type.py +0 -0
  53. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/enumerations/analysis_type.py +0 -0
  54. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/enumerations/system_library.py +0 -0
  55. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/exceptions.py +0 -0
  56. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/file_manager.py +0 -0
  57. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/file_result_item.py +0 -0
  58. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/file_results.py +0 -0
  59. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/libraries.py +0 -0
  60. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/library_item.py +0 -0
  61. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/organization_item.py +0 -0
  62. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/organizations.py +0 -0
  63. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/users.py +0 -0
  64. {mindbridge_api_python_client-1.5.1 → mindbridge_api_python_client-1.6.1}/src/mindbridgeapi/version.py +0 -0
@@ -1,32 +1,30 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: mindbridge-api-python-client
3
- Version: 1.5.1
3
+ Version: 1.6.1
4
4
  Summary: Interact with the MindBridge API
5
- Home-page: https://www.mindbridge.ai
6
- License: Proprietary
5
+ License: LicenseRef-Proprietary
6
+ Keywords: MindBridge
7
7
  Author: MBAI Support
8
8
  Author-email: mbaisupport@mindbridge.ai
9
9
  Maintainer: MBAI Support
10
10
  Maintainer-email: mbaisupport@mindbridge.ai
11
- Requires-Python: >=3.9,<4.0
11
+ Requires-Python: >= 3.9
12
12
  Classifier: Development Status :: 4 - Beta
13
- Classifier: Framework :: Flake8
14
13
  Classifier: Framework :: Pydantic
15
14
  Classifier: Framework :: Pydantic :: 2
16
15
  Classifier: Framework :: Pytest
17
16
  Classifier: License :: Other/Proprietary License
18
17
  Classifier: Operating System :: OS Independent
19
- Classifier: Programming Language :: Python
20
18
  Classifier: Programming Language :: Python :: 3
21
19
  Classifier: Programming Language :: Python :: 3.9
22
20
  Classifier: Programming Language :: Python :: 3.10
23
21
  Classifier: Programming Language :: Python :: 3.11
24
22
  Classifier: Programming Language :: Python :: 3.12
25
23
  Classifier: Programming Language :: Python :: 3.13
26
- Classifier: Programming Language :: Python :: 3 :: Only
27
24
  Classifier: Typing :: Typed
28
25
  Requires-Dist: pydantic (>=2.5.2,<3.0.0)
29
- Requires-Dist: urllib3 (>=2.0.7,<3.0.0)
26
+ Requires-Dist: urllib3 (>=2.3.0,<3.0.0)
27
+ Project-URL: Homepage, https://www.mindbridge.ai
30
28
  Description-Content-Type: text/markdown
31
29
 
32
30
  <h1 align="center">MindBridge API Python Client</h1>
@@ -0,0 +1,148 @@
1
+ [build-system]
2
+ requires = ["poetry-core>=1.0.0"]
3
+ build-backend = "poetry.core.masonry.api"
4
+
5
+ [project]
6
+ name = "mindbridge-api-python-client"
7
+ version = "1.6.1"
8
+ description = "Interact with the MindBridge API"
9
+ readme = "README.md"
10
+ license = "LicenseRef-Proprietary"
11
+ license-files = ["LICENSE.txt"]
12
+ authors = [
13
+ {name = "MBAI Support", email = "mbaisupport@mindbridge.ai"}, # Must be first so that PyPI displays this
14
+ {name = "Edgar Silva", email = "edgar.silva@mindbridge.ai"},
15
+ {name = "Jordan Hatcher", email = "jordan.hatcher@mindbridge.ai"},
16
+ {name = "Kevin Paulson", email = "kevin.paulson@mindbridge.ai"},
17
+ {name = "Michael Smith", email = "msmith@mindbridge.ai"},
18
+ {name = "Owen Allen", email = "owen.allen@mindbridge.ai"},
19
+ {name = "Wing-Leung Chan", email = "wing-leung.chan@mindbridge.ai"},
20
+ ]
21
+ maintainers = [
22
+ {name = "MBAI Support", email = "mbaisupport@mindbridge.ai"},
23
+ ]
24
+ dependencies = [
25
+ "pydantic (>=2.5.2,<3.0.0)",
26
+ "urllib3 (>=2.3.0,<3.0.0)",
27
+ ]
28
+ requires-python = ">= 3.9"
29
+ keywords = [ "MindBridge" ]
30
+ dynamic = [ "classifiers" ]
31
+
32
+ [project.urls]
33
+ homepage = "https://www.mindbridge.ai"
34
+
35
+ [tool.poetry]
36
+ requires-poetry = ">=2.0"
37
+ classifiers = [ # Python classifiers are automatically added by poetry
38
+ "Development Status :: 4 - Beta",
39
+ "Framework :: Pydantic",
40
+ "Framework :: Pydantic :: 2",
41
+ "Framework :: Pytest",
42
+ "License :: Other/Proprietary License",
43
+ "Operating System :: OS Independent",
44
+ "Typing :: Typed",
45
+ ]
46
+ packages = [
47
+ { include = "mindbridgeapi", from = "src" },
48
+ ]
49
+
50
+ [tool.poetry.group.lint]
51
+ optional = true
52
+
53
+ [tool.poetry.group.lint.dependencies]
54
+ ruff = "^0.9.6"
55
+
56
+ [tool.poetry.group.test]
57
+ optional = true
58
+
59
+ [tool.poetry.group.test.dependencies]
60
+ pytest = "^8.1.1"
61
+ pytest-randomly = "^3.15.0"
62
+ openpyxl = "^3.1.5"
63
+ pandas = "^2.2.3"
64
+ datamodel-code-generator = "^0.28.0"
65
+ mypy = "^1.13.0"
66
+ pytest-cov = "^6.0.0"
67
+ pytest-html = "^4.1.1"
68
+
69
+ [tool.ruff]
70
+ extend-exclude = [
71
+ "src/mindbridgeapi/generated_pydantic_model/model.py",
72
+ ".cci_pycache",
73
+ ]
74
+
75
+ [tool.ruff.format]
76
+ line-ending = "lf"
77
+
78
+ [tool.ruff.lint]
79
+ select = [
80
+ "I", # isort
81
+ "F", # Pyflakes
82
+ "E", "W", # pycodestyle
83
+ "N", # pep8-naming
84
+ "B", # flake8-bugbear
85
+ "C4", # flake8-comprehensions
86
+ "ISC", # flake8-implicit-str-concat
87
+ "PT", # flake8-pytest-style
88
+ "RET", # flake8-return
89
+ "SIM", # flake8-simplify
90
+ "TID", # flake8-tidy-imports
91
+ "TRY", # tryceratops
92
+ "TC", # flake8-type-checking
93
+ "RUF100",
94
+ # flake8-clean-block = "^0.1.2"
95
+ # flake8-encodings = "^0.5.1" https://github.com/astral-sh/ruff/issues/3278
96
+ ]
97
+ ignore = [
98
+ "E111", "E114", "E117", # Conflicting lint rules with formatter
99
+ "SIM105", # Did not seem useful
100
+ "TRY003", # Did not seem useful
101
+ ]
102
+
103
+ [tool.ruff.lint.flake8-tidy-imports]
104
+ ban-relative-imports = "all"
105
+
106
+ [tool.ruff.lint.isort]
107
+ combine-as-imports = true
108
+ force-sort-within-sections = true
109
+ no-lines-before = ["future", "standard-library", "first-party", "local-folder", "third-party"]
110
+
111
+ [tool.pytest.ini_options]
112
+ addopts = [
113
+ "--strict-config",
114
+ "--strict-markers",
115
+ "--cov=mindbridgeapi",
116
+ "--cov=generate_model",
117
+ "--cov=set_circleci_pytest_enviroment_variables",
118
+ "--cov-report=html",
119
+ "--cov-report=term",
120
+ "--cov-report=xml",
121
+ ]
122
+
123
+ xfail_strict = true
124
+ filterwarnings = [ "error" ]
125
+ pythonpath = [ "tools" ]
126
+
127
+ [tool.coverage.run]
128
+ branch = true
129
+ omit = [ "src/mindbridgeapi/generated_pydantic_model/*" ]
130
+
131
+ [tool.coverage.report]
132
+ exclude_also = [
133
+ "if TYPE_CHECKING:",
134
+ 'if __name__ == "__main__":',
135
+ ]
136
+
137
+ [tool.mypy]
138
+ mypy_path = "$MYPY_CONFIG_FILE_DIR/src"
139
+ packages = "mindbridgeapi,tools.generate_model,tools.set_circleci_pytest_enviroment_variables"
140
+ plugins = [ "pydantic.mypy" ]
141
+ strict = true
142
+ no_implicit_optional = true
143
+ show_error_codes = true
144
+
145
+ [tool.pydantic-mypy]
146
+ init_forbid_extra = true
147
+ init_typed = true
148
+ warn_required_dynamic_aliases = true
@@ -21,10 +21,10 @@ from mindbridgeapi.enumerations.analysis_type import AnalysisType
21
21
  from mindbridgeapi.enumerations.system_library import SystemLibrary
22
22
  from mindbridgeapi.file_manager_item import FileManagerItem, FileManagerType
23
23
  from mindbridgeapi.generated_pydantic_model.model import (
24
+ Frequency,
24
25
  PeriodType as AnalysisEffectiveDateMetricsPeriod,
26
+ TargetWorkflowState,
25
27
  )
26
- from mindbridgeapi.generated_pydantic_model.model import Frequency
27
- from mindbridgeapi.generated_pydantic_model.model import TargetWorkflowState
28
28
  from mindbridgeapi.library_item import LibraryItem
29
29
  from mindbridgeapi.organization_item import OrganizationItem
30
30
  from mindbridgeapi.server import Server
@@ -17,8 +17,6 @@ from mindbridgeapi.common_validators import (
17
17
  from mindbridgeapi.generated_pydantic_model.model import (
18
18
  ApiAccountGroupingRead,
19
19
  ApiAccountGroupingUpdate,
20
- )
21
- from mindbridgeapi.generated_pydantic_model.model import (
22
20
  Type7 as _AccountGroupingFileType,
23
21
  )
24
22
 
@@ -8,7 +8,6 @@
8
8
 
9
9
  from dataclasses import dataclass
10
10
  from functools import cached_property
11
- import logging
12
11
  from typing import TYPE_CHECKING, Any, Optional, Union
13
12
  from mindbridgeapi.account_grouping_item import (
14
13
  AccountGroupingFileType,
@@ -28,8 +27,6 @@ if TYPE_CHECKING:
28
27
  from os import PathLike
29
28
  from pathlib import Path
30
29
 
31
- logger = logging.getLogger(__name__)
32
-
33
30
 
34
31
  @dataclass
35
32
  class AccountGroupings(BaseSet):
@@ -8,18 +8,15 @@
8
8
 
9
9
  from dataclasses import dataclass
10
10
  from functools import cached_property
11
- import logging
12
11
  from typing import TYPE_CHECKING, Any, Optional
13
12
  from mindbridgeapi.account_group_item import AccountGroupItem
14
13
  from mindbridgeapi.base_set import BaseSet
15
- from mindbridgeapi.exceptions import ItemNotFoundError, ParameterError
16
- from mindbridgeapi.generated_pydantic_model.model import MindBridgeQueryTerm
14
+ from mindbridgeapi.common_validators import _convert_json_query
15
+ from mindbridgeapi.exceptions import ItemNotFoundError
17
16
 
18
17
  if TYPE_CHECKING:
19
18
  from collections.abc import Generator
20
19
 
21
- logger = logging.getLogger(__name__)
22
-
23
20
 
24
21
  @dataclass
25
22
  class AccountGroups(BaseSet):
@@ -36,26 +33,10 @@ class AccountGroups(BaseSet):
36
33
  def get(
37
34
  self, json: Optional[dict[str, Any]] = None
38
35
  ) -> "Generator[AccountGroupItem, None, None]":
39
- if json is None:
40
- json = {}
41
-
42
- mindbridgequeryterm = MindBridgeQueryTerm.model_validate(json)
43
- json_str = mindbridgequeryterm.model_dump_json(
44
- by_alias=True, exclude_none=True, warnings=False
45
- )
46
- logger.info(f"Query (get) is: {json_str}")
47
-
48
- if "accountGroupingId" not in json_str:
49
- raise ParameterError(
50
- parameter_name="json",
51
- details=(
52
- "At least one valid accountGroupingId term must be provided when "
53
- "querying this entity."
54
- ),
55
- )
36
+ mb_query_dict = _convert_json_query(json, required_key="accountGroupingId")
56
37
 
57
38
  url = f"{self.base_url}/query"
58
- for resp_dict in super()._get(url=url, json=json):
39
+ for resp_dict in super()._get(url=url, json=mb_query_dict):
59
40
  yield AccountGroupItem.model_validate(resp_dict)
60
41
 
61
42
  def update(self, account_group: AccountGroupItem) -> AccountGroupItem:
@@ -8,18 +8,15 @@
8
8
 
9
9
  from dataclasses import dataclass
10
10
  from functools import cached_property
11
- import logging
12
11
  from typing import TYPE_CHECKING, Any, Optional
13
12
  from mindbridgeapi.account_mapping_item import AccountMappingItem
14
13
  from mindbridgeapi.base_set import BaseSet
15
- from mindbridgeapi.exceptions import ItemNotFoundError, ParameterError
16
- from mindbridgeapi.generated_pydantic_model.model import MindBridgeQueryTerm
14
+ from mindbridgeapi.common_validators import _convert_json_query
15
+ from mindbridgeapi.exceptions import ItemNotFoundError
17
16
 
18
17
  if TYPE_CHECKING:
19
18
  from collections.abc import Generator
20
19
 
21
- logger = logging.getLogger(__name__)
22
-
23
20
 
24
21
  @dataclass
25
22
  class AccountMappings(BaseSet):
@@ -35,26 +32,10 @@ class AccountMappings(BaseSet):
35
32
  def get(
36
33
  self, json: Optional[dict[str, Any]] = None
37
34
  ) -> "Generator[AccountMappingItem, None, None]":
38
- if json is None:
39
- json = {}
40
-
41
- mindbridgequeryterm = MindBridgeQueryTerm.model_validate(json)
42
- json_str = mindbridgequeryterm.model_dump_json(
43
- by_alias=True, exclude_none=True, warnings=False
44
- )
45
- logger.info(f"{json} was converted to {json_str}")
46
-
47
- if "engagementId" not in json_str:
48
- raise ParameterError(
49
- parameter_name="json",
50
- details=(
51
- "At least one valid engagementId term must be provided when "
52
- "querying this entity."
53
- ),
54
- )
35
+ mb_query_dict = _convert_json_query(json, required_key="engagementId")
55
36
 
56
37
  url = f"{self.base_url}/query"
57
- for resp_dict in super()._get(url=url, json=json):
38
+ for resp_dict in super()._get(url=url, json=mb_query_dict):
58
39
  yield AccountMappingItem.model_validate(resp_dict)
59
40
 
60
41
  def update(self, item: AccountMappingItem) -> AccountMappingItem:
@@ -83,12 +83,6 @@ class Analyses(BaseSet):
83
83
  url = f"{self.base_url}/{item.id}"
84
84
  super()._delete(url=url)
85
85
 
86
- def start(self, item: AnalysisItem) -> AnalysisItem:
87
- warnings.warn(
88
- "Use the run function instead", category=DeprecationWarning, stacklevel=2
89
- )
90
- return self.run(item)
91
-
92
86
  def run(self, item: AnalysisItem) -> AnalysisItem:
93
87
  analysis_id = getattr(item, "id", None)
94
88
  if analysis_id is None:
@@ -40,12 +40,9 @@ class AnalysisPeriod(ApiAnalysisPeriodRead):
40
40
  if not isinstance(other, AnalysisPeriod):
41
41
  return NotImplemented
42
42
 
43
- if (self.start_date > other.end_date) or (
43
+ return (self.start_date > other.end_date) or (
44
44
  (self.end_date == other.end_date) and (self.start_date > other.start_date)
45
- ):
46
- return True
47
-
48
- return False
45
+ )
49
46
 
50
47
  def __le__(self, other: object) -> bool:
51
48
  return NotImplemented
@@ -92,11 +92,11 @@ class _ApiAnalysisSourceCreateOnly(ApiAnalysisSourceCreateOnly):
92
92
  appropriate virtual column type.
93
93
  """
94
94
 
95
- proposed_virtual_columns: Optional[
96
- list[_VirtualColumn]
97
- ] = Field().merge_field_infos(
98
- ApiAnalysisSourceCreateOnly.model_fields["proposed_virtual_columns"]
99
- ) # type: ignore[assignment]
95
+ proposed_virtual_columns: Optional[list[_VirtualColumn]] = (
96
+ Field().merge_field_infos( # type: ignore[assignment]
97
+ ApiAnalysisSourceCreateOnly.model_fields["proposed_virtual_columns"]
98
+ )
99
+ )
100
100
 
101
101
 
102
102
  class _ApiAnalysisSourceUpdate(ApiAnalysisSourceUpdate):
@@ -106,11 +106,11 @@ class _ApiAnalysisSourceUpdate(ApiAnalysisSourceUpdate):
106
106
  determine the appropriate virtual column type.
107
107
  """
108
108
 
109
- proposed_virtual_columns: Optional[
110
- list[_VirtualColumn]
111
- ] = Field().merge_field_infos(
112
- ApiAnalysisSourceUpdate.model_fields["proposed_virtual_columns"]
113
- ) # type: ignore[assignment]
109
+ proposed_virtual_columns: Optional[list[_VirtualColumn]] = (
110
+ Field().merge_field_infos( # type: ignore[assignment]
111
+ ApiAnalysisSourceUpdate.model_fields["proposed_virtual_columns"]
112
+ )
113
+ )
114
114
  virtual_columns: Optional[list[_VirtualColumn]] = Field().merge_field_infos(
115
115
  ApiAnalysisSourceUpdate.model_fields["virtual_columns"]
116
116
  ) # type: ignore[assignment]
@@ -127,11 +127,11 @@ class AnalysisSourceItem(ApiAnalysisSourceRead):
127
127
  ApiAnalysisSourceRead.model_fields["analysis_source_type_id"],
128
128
  default=AnalysisSourceTypeItem.GENERAL_LEDGER_JOURNAL,
129
129
  )
130
- proposed_virtual_columns: Optional[
131
- list[_VirtualColumn]
132
- ] = Field().merge_field_infos(
133
- ApiAnalysisSourceRead.model_fields["proposed_virtual_columns"]
134
- ) # type: ignore[assignment]
130
+ proposed_virtual_columns: Optional[list[_VirtualColumn]] = (
131
+ Field().merge_field_infos( # type: ignore[assignment]
132
+ ApiAnalysisSourceRead.model_fields["proposed_virtual_columns"]
133
+ )
134
+ )
135
135
  virtual_columns: Optional[list[_VirtualColumn]] = Field().merge_field_infos(
136
136
  ApiAnalysisSourceRead.model_fields["virtual_columns"]
137
137
  ) # type: ignore[assignment]
@@ -21,8 +21,6 @@ from mindbridgeapi.exceptions import (
21
21
  )
22
22
  from mindbridgeapi.generated_pydantic_model.model import (
23
23
  ApiEffectiveDateMetricsRead as AnalysisEffectiveDateMetrics,
24
- )
25
- from mindbridgeapi.generated_pydantic_model.model import (
26
24
  PeriodType as AnalysisEffectiveDateMetricsPeriod,
27
25
  )
28
26
 
@@ -80,7 +78,9 @@ class AnalysisSources(BaseSet):
80
78
  def effective_date_metrics(
81
79
  self,
82
80
  item: AnalysisSourceItem,
83
- period_type: AnalysisEffectiveDateMetricsPeriod = AnalysisEffectiveDateMetricsPeriod.MONTH, # noqa:B950
81
+ period_type: AnalysisEffectiveDateMetricsPeriod = (
82
+ AnalysisEffectiveDateMetricsPeriod.MONTH
83
+ ),
84
84
  ) -> AnalysisEffectiveDateMetrics:
85
85
  if getattr(item, "id", None) is None:
86
86
  raise ItemNotFoundError
@@ -13,9 +13,11 @@ from mindbridgeapi.common_validators import (
13
13
  _warning_if_extra_fields,
14
14
  )
15
15
  from mindbridgeapi.exceptions import ItemError, ItemNotFoundError, ValidationError
16
- from mindbridgeapi.generated_pydantic_model.model import ApiAsyncResult
17
- from mindbridgeapi.generated_pydantic_model.model import Status3 as _AsyncResultStatus
18
- from mindbridgeapi.generated_pydantic_model.model import Type1 as _AsyncResultType
16
+ from mindbridgeapi.generated_pydantic_model.model import (
17
+ ApiAsyncResult,
18
+ Status3 as _AsyncResultStatus,
19
+ Type1 as _AsyncResultType,
20
+ )
19
21
 
20
22
  logger = logging.getLogger(__name__)
21
23
 
@@ -13,6 +13,7 @@ import logging
13
13
  import shutil
14
14
  from typing import TYPE_CHECKING, Any, Optional
15
15
  from urllib.parse import urlencode
16
+ from urllib3.util import Retry
16
17
  from mindbridgeapi.exceptions import UnexpectedServerError, ValidationError
17
18
 
18
19
  if TYPE_CHECKING:
@@ -61,7 +62,14 @@ class BaseSet:
61
62
  params = {"page": page_number}
62
63
  request_url = f"{url}?{urlencode(params)}"
63
64
 
64
- resp = self.server.http.request("POST", request_url, json=json)
65
+ # Same as set for the PoolManager (http) in Server, but getting a page will
66
+ # always be considered to be idempotent so we can allow repeat post requests
67
+ method = "POST"
68
+ retries = Retry(
69
+ connect=3, read=3, redirect=0, other=0, allowed_methods={method}
70
+ )
71
+
72
+ resp = self.server.http.request(method, request_url, retries=retries, json=json)
65
73
  self._check_response(resp)
66
74
  resp_dict = self._response_as_dict(resp)
67
75
 
@@ -7,11 +7,18 @@
7
7
  #
8
8
 
9
9
  import logging
10
- from typing import Any
10
+ from typing import Any, Optional, Union
11
11
  import warnings
12
- from mindbridgeapi.generated_pydantic_model.model import ApiUserInfo, ApiUserInfoRead
13
- from mindbridgeapi.generated_pydantic_model.model import ApiUserRead as UserItem
14
- from mindbridgeapi.generated_pydantic_model.model import Role
12
+ from pydantic import RootModel
13
+ from mindbridgeapi.exceptions import ParameterError
14
+ from mindbridgeapi.generated_pydantic_model.model import (
15
+ ApiUserInfo,
16
+ ApiUserInfoRead,
17
+ ApiUserRead as UserItem,
18
+ Role,
19
+ )
20
+
21
+ MindBridgeQuery = RootModel[dict[str, Any]]
15
22
 
16
23
  logger = logging.getLogger(__name__)
17
24
 
@@ -69,3 +76,29 @@ def _convert_userinfo_to_useritem(v: Any) -> Any:
69
76
  return UserItem(
70
77
  id=v.user_id, first_name=first_name, last_name="", role=Role.ROLE_ADMIN
71
78
  )
79
+
80
+
81
+ def _convert_json_query(
82
+ json: Optional[dict[str, Any]], required_key: Optional[str] = None
83
+ ) -> dict[str, Union[int, float, bool, str]]:
84
+ if json is None:
85
+ json = {}
86
+
87
+ mb_query = MindBridgeQuery.model_validate(json)
88
+ json_str = mb_query.model_dump_json(exclude_none=True)
89
+
90
+ logger.info(f"Query (get) is: {json_str}")
91
+
92
+ if required_key is not None and required_key not in json_str:
93
+ raise ParameterError(
94
+ parameter_name="json",
95
+ details=(
96
+ f"At least one valid {required_key} term must be provided when querying"
97
+ " this entity."
98
+ ),
99
+ )
100
+
101
+ mb_query_dict: dict[str, Union[int, float, bool, str]] = mb_query.model_dump(
102
+ mode="json", exclude_none=True
103
+ )
104
+ return mb_query_dict
@@ -8,28 +8,25 @@
8
8
 
9
9
  from dataclasses import dataclass
10
10
  from functools import cached_property
11
- import logging
12
11
  from typing import TYPE_CHECKING, Any, Optional
13
12
  import warnings
14
13
  from mindbridgeapi.async_result_item import AsyncResultItem, AsyncResultType
15
14
  from mindbridgeapi.async_results import AsyncResults
16
15
  from mindbridgeapi.base_set import BaseSet
16
+ from mindbridgeapi.common_validators import _convert_json_query
17
17
  from mindbridgeapi.exceptions import ItemError, ItemNotFoundError, ParameterError
18
18
  from mindbridgeapi.generated_pydantic_model.model import (
19
19
  ApiDataTableExportRequest,
20
20
  ApiDataTableQuerySortOrder,
21
21
  ApiDataTableRead,
22
22
  Direction,
23
- MindBridgeQueryTerm,
23
+ Type4 as DataTableColumnType,
24
24
  )
25
- from mindbridgeapi.generated_pydantic_model.model import Type4 as DataTableColumnType
26
25
 
27
26
  if TYPE_CHECKING:
28
27
  from collections.abc import Generator
29
28
  from pathlib import Path
30
29
 
31
- logger = logging.getLogger(__name__)
32
-
33
30
 
34
31
  @dataclass
35
32
  class DataTables(BaseSet):
@@ -49,28 +46,10 @@ class DataTables(BaseSet):
49
46
  def get(
50
47
  self, json: Optional[dict[str, Any]] = None
51
48
  ) -> "Generator[ApiDataTableRead, None, None]":
52
- logger.info("Starting Query (get)")
53
-
54
- if json is None:
55
- json = {}
56
-
57
- mindbridgequeryterm = MindBridgeQueryTerm.model_validate(json)
58
- json_str = mindbridgequeryterm.model_dump_json(
59
- by_alias=True, exclude_none=True, warnings=False
60
- )
61
- logger.info(f"Query (get) is: {json_str}")
62
-
63
- if "analysisId" not in json_str:
64
- raise ParameterError(
65
- parameter_name="json",
66
- details=(
67
- "At least one valid analysisId term must be provided when querying "
68
- "this entity."
69
- ),
70
- )
49
+ mb_query_dict = _convert_json_query(json, required_key="analysisId")
71
50
 
72
51
  url = f"{self.base_url}/query"
73
- for resp_dict in super()._get(url=url, json=json):
52
+ for resp_dict in super()._get(url=url, json=mb_query_dict):
74
53
  yield ApiDataTableRead.model_validate(resp_dict)
75
54
 
76
55
  @staticmethod
@@ -101,7 +80,20 @@ class DataTables(BaseSet):
101
80
  input_item: ApiDataTableRead,
102
81
  sort_direction: Optional[Direction] = None,
103
82
  sort_field: Optional[str] = None,
104
- ) -> ApiDataTableQuerySortOrder:
83
+ ) -> Optional[ApiDataTableQuerySortOrder]:
84
+ if sort_field is not None and not isinstance(sort_field, str):
85
+ raise ParameterError(
86
+ parameter_name="sort_field", details="Not provided as str."
87
+ )
88
+
89
+ if sort_field is None and input_item.logical_name == "gl_journal_lines":
90
+ sort_field = "rowid"
91
+ elif sort_field is None and input_item.logical_name == "gl_journal_tx":
92
+ sort_field = "txid"
93
+
94
+ if sort_field is None or sort_field == "":
95
+ return None
96
+
105
97
  if sort_direction is None:
106
98
  sort_direction = Direction.ASC
107
99
 
@@ -112,22 +104,6 @@ class DataTables(BaseSet):
112
104
  parameter_name="sort_direction", details="Not a valid Direction."
113
105
  ) from err
114
106
 
115
- if sort_field is not None and not isinstance(sort_field, str):
116
- raise ParameterError(
117
- parameter_name="sort_field", details="Not provided as str."
118
- )
119
-
120
- if sort_field is None and input_item.type == "flows_compact":
121
- sort_field = "flow_id"
122
- elif sort_field is None and input_item.logical_name == "gl_journal_lines":
123
- sort_field = "rowid"
124
- elif sort_field is None and input_item.logical_name == "gl_journal_tx":
125
- sort_field = "txid"
126
- elif sort_field is None or sort_field == "":
127
- # Don't send a sort
128
- sort_field = None
129
- sort_direction = None
130
-
131
107
  return ApiDataTableQuerySortOrder(direction=sort_direction, field=sort_field)
132
108
 
133
109
  def export(
@@ -144,23 +120,21 @@ class DataTables(BaseSet):
144
120
 
145
121
  fields = self._export_get_fields(input_item=input_item, fields=fields)
146
122
 
147
- if query is None:
148
- query = {}
149
-
150
- mindbridge_query_term = MindBridgeQueryTerm.model_validate(query)
151
-
152
- sort = self._export_get_sort(
153
- input_item=input_item, sort_direction=sort_direction, sort_field=sort_field
154
- )
155
-
156
123
  url = f"{self.base_url}/{input_item.id}/export"
157
124
  data_table_export_request = ApiDataTableExportRequest(
158
- fields=fields, query=mindbridge_query_term, limit=limit, sort=sort
125
+ fields=fields,
126
+ limit=limit,
127
+ sort=self._export_get_sort(
128
+ input_item=input_item,
129
+ sort_direction=sort_direction,
130
+ sort_field=sort_field,
131
+ ),
159
132
  )
160
133
 
161
134
  json = data_table_export_request.model_dump(
162
135
  mode="json", by_alias=True, exclude_none=True
163
136
  )
137
+ json["query"] = _convert_json_query(query)
164
138
 
165
139
  resp_dict = super()._create(url=url, json=json)
166
140