bruce-models 0.0.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.
- bruce_models-0.0.1/MANIFEST.in +10 -0
- bruce_models-0.0.1/PKG-INFO +26 -0
- bruce_models-0.0.1/README.md +13 -0
- bruce_models-0.0.1/bruce_models/__init__.py +15 -0
- bruce_models-0.0.1/bruce_models/api/__init__.py +3 -0
- bruce_models-0.0.1/bruce_models/api/api.py +18 -0
- bruce_models-0.0.1/bruce_models/api/bruce_api.py +118 -0
- bruce_models-0.0.1/bruce_models/api/guardian_api.py +98 -0
- bruce_models-0.0.1/bruce_models/entity/__init__.py +2 -0
- bruce_models-0.0.1/bruce_models/entity/entity.py +150 -0
- bruce_models-0.0.1/bruce_models/entity/entity_type.py +52 -0
- bruce_models-0.0.1/bruce_models/scenario/__init__.py +1 -0
- bruce_models-0.0.1/bruce_models/scenario/scenario.py +43 -0
- bruce_models-0.0.1/bruce_models.egg-info/PKG-INFO +26 -0
- bruce_models-0.0.1/bruce_models.egg-info/SOURCES.txt +19 -0
- bruce_models-0.0.1/bruce_models.egg-info/dependency_links.txt +1 -0
- bruce_models-0.0.1/bruce_models.egg-info/requires.txt +1 -0
- bruce_models-0.0.1/bruce_models.egg-info/top_level.txt +1 -0
- bruce_models-0.0.1/pyproject.toml +3 -0
- bruce_models-0.0.1/setup.cfg +4 -0
- bruce_models-0.0.1/setup.py +21 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: bruce-models
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: This is a library which defines data-models for the Nextspace API and provides functions for communicating with the endpoints.
|
|
5
|
+
Author: Matvey Lavrinovich
|
|
6
|
+
Author-email: matveylavrinovich@gmail.com
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Requires-Python: >=3.6
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: requests>=2.0
|
|
13
|
+
|
|
14
|
+
# bruce-models
|
|
15
|
+
|
|
16
|
+
This is a library which defines data-models for the Nextspace API and provides functions for communicating with the endpoints.
|
|
17
|
+
|
|
18
|
+
### Local build
|
|
19
|
+
|
|
20
|
+
- `pip install .`
|
|
21
|
+
|
|
22
|
+
- `python ./public/main.py` (to test it loads after build)
|
|
23
|
+
|
|
24
|
+
### Test a release build
|
|
25
|
+
|
|
26
|
+
- `python -m build`
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# bruce-models
|
|
2
|
+
|
|
3
|
+
This is a library which defines data-models for the Nextspace API and provides functions for communicating with the endpoints.
|
|
4
|
+
|
|
5
|
+
### Local build
|
|
6
|
+
|
|
7
|
+
- `pip install .`
|
|
8
|
+
|
|
9
|
+
- `python ./public/main.py` (to test it loads after build)
|
|
10
|
+
|
|
11
|
+
### Test a release build
|
|
12
|
+
|
|
13
|
+
- `python -m build`
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .api.api import Api
|
|
2
|
+
from .api.bruce_api import BruceApi
|
|
3
|
+
from .api.guardian_api import GuardianApi
|
|
4
|
+
from .scenario.scenario import Scenario
|
|
5
|
+
from .entity.entity import Entity
|
|
6
|
+
from .entity.entity_type import EntityType
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"Api"
|
|
10
|
+
"BruceApi",
|
|
11
|
+
"GuardianApi",
|
|
12
|
+
"Scenario",
|
|
13
|
+
"Entity",
|
|
14
|
+
"EntityType"
|
|
15
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from typing import Dict
|
|
3
|
+
|
|
4
|
+
class Api:
|
|
5
|
+
@staticmethod
|
|
6
|
+
def parse_result(result: requests.Response) -> Dict:
|
|
7
|
+
"""
|
|
8
|
+
Parses the result of an API request to a Nextspace endpoint.
|
|
9
|
+
"""
|
|
10
|
+
if result.status_code >= 400 or result.status_code < 200:
|
|
11
|
+
error = result.json()
|
|
12
|
+
raise Exception(error)
|
|
13
|
+
|
|
14
|
+
# Technically, our API can return other types such as a raw CSV file.
|
|
15
|
+
# However, it is very rare.
|
|
16
|
+
# If we need to update this method, we can check for the type and wrap non-json (CSV) in a dict.
|
|
17
|
+
|
|
18
|
+
return result.json()
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from typing import Optional, Dict, TypedDict
|
|
3
|
+
import threading
|
|
4
|
+
from bruce_models import Api
|
|
5
|
+
from bruce_models import GuardianApi
|
|
6
|
+
|
|
7
|
+
class BruceApiParams(TypedDict):
|
|
8
|
+
"""
|
|
9
|
+
Represents the parameters for the Bruce API.
|
|
10
|
+
"""
|
|
11
|
+
base_url: Optional[str]
|
|
12
|
+
session_id: Optional[str]
|
|
13
|
+
account_id: Optional[str]
|
|
14
|
+
env: Optional[str]
|
|
15
|
+
guardian: Optional[GuardianApi]
|
|
16
|
+
|
|
17
|
+
class BruceApi:
|
|
18
|
+
"""
|
|
19
|
+
A basic API wrapper for making HTTP requests.
|
|
20
|
+
"""
|
|
21
|
+
def __init__(self, params: BruceApiParams):
|
|
22
|
+
self._loading = True
|
|
23
|
+
self._lock = threading.Lock()
|
|
24
|
+
self._init(params)
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def loading(self) -> bool:
|
|
28
|
+
return self._loading
|
|
29
|
+
|
|
30
|
+
def _init(self, params):
|
|
31
|
+
try:
|
|
32
|
+
# If no env was supplied, set to PROD.
|
|
33
|
+
self.env = params.get("env", "PROD")
|
|
34
|
+
self.base_url = params.get("base_url")
|
|
35
|
+
self.session_id = params.get("session_id")
|
|
36
|
+
self.account_id = params.get("account_id")
|
|
37
|
+
|
|
38
|
+
# If no base_url was supplied, but an account_id was, we can request for it.
|
|
39
|
+
if not self.base_url and self.account_id:
|
|
40
|
+
# Use Guardian instance if was supplied, if not, create one.
|
|
41
|
+
guardian = params.get("guardian", GuardianApi({ "env": self.env, "session_id": self.session_id }))
|
|
42
|
+
account = guardian.GET(f"account/{self.account_id}")
|
|
43
|
+
self.base_url = account.get("URL").get("Base")
|
|
44
|
+
elif not self.base_url:
|
|
45
|
+
raise ValueError("A valid base URL or account ID is required.")
|
|
46
|
+
|
|
47
|
+
self._loading = False
|
|
48
|
+
except Exception as e:
|
|
49
|
+
self._loading = False
|
|
50
|
+
raise e
|
|
51
|
+
|
|
52
|
+
def set_session_id(self, session_id: str):
|
|
53
|
+
"""
|
|
54
|
+
Sets the x-sessionid header for all future requests.
|
|
55
|
+
"""
|
|
56
|
+
self.session_id = session_id
|
|
57
|
+
|
|
58
|
+
def get_env(self):
|
|
59
|
+
"""
|
|
60
|
+
Returns the current environment.
|
|
61
|
+
"""
|
|
62
|
+
return self.env
|
|
63
|
+
|
|
64
|
+
def _build_headers(self) -> Dict[str, str]:
|
|
65
|
+
"""
|
|
66
|
+
Builds the headers for all requests that are sent.
|
|
67
|
+
"""
|
|
68
|
+
headers = {
|
|
69
|
+
"Content-Type": "application/json"
|
|
70
|
+
}
|
|
71
|
+
if self.session_id:
|
|
72
|
+
headers["x-sessionid"] = self.session_id
|
|
73
|
+
return headers
|
|
74
|
+
|
|
75
|
+
def get(self, url: str, params: dict = {}) -> Dict:
|
|
76
|
+
"""
|
|
77
|
+
Sends a GET request to the API.
|
|
78
|
+
The URL should be absolute.
|
|
79
|
+
"""
|
|
80
|
+
self._wait_for_loading()
|
|
81
|
+
response = requests.get(url, headers=self._build_headers(), params=params)
|
|
82
|
+
return Api.parse_result(response)
|
|
83
|
+
|
|
84
|
+
def GET(self, url: str, params: dict = {}) -> Dict:
|
|
85
|
+
"""
|
|
86
|
+
Sends a GET request to the API.
|
|
87
|
+
The URL should be relative to the base URL.
|
|
88
|
+
"""
|
|
89
|
+
self._wait_for_loading()
|
|
90
|
+
full = f"{self.base_url}/{url.lstrip('/')}"
|
|
91
|
+
return self.get(full, params)
|
|
92
|
+
|
|
93
|
+
def post(self, url: str, data: dict = {}, params: dict = {}) -> Dict:
|
|
94
|
+
"""
|
|
95
|
+
Sends a POST request to the API.
|
|
96
|
+
The URL should be absolute.
|
|
97
|
+
"""
|
|
98
|
+
self._wait_for_loading()
|
|
99
|
+
response = requests.post(url, headers=self._build_headers(), json=data, params=params)
|
|
100
|
+
return Api.parse_result(response)
|
|
101
|
+
|
|
102
|
+
def POST(self, url: str, data: dict = {}, params: dict = {}) -> Dict:
|
|
103
|
+
"""
|
|
104
|
+
Sends a POST request to the API.
|
|
105
|
+
The URL should be relative to the base URL.
|
|
106
|
+
"""
|
|
107
|
+
self._wait_for_loading()
|
|
108
|
+
full = f"{self.base_url}/{url.lstrip('/')}"
|
|
109
|
+
return self.post(full, data, params)
|
|
110
|
+
|
|
111
|
+
def _wait_for_loading(self):
|
|
112
|
+
"""
|
|
113
|
+
Blocks further requests until the loading state is set to False.
|
|
114
|
+
This method will prevent further requests until initialization is complete.
|
|
115
|
+
"""
|
|
116
|
+
with self._lock:
|
|
117
|
+
while self._loading:
|
|
118
|
+
pass
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from typing import Optional, Dict, TypedDict
|
|
3
|
+
import threading
|
|
4
|
+
from bruce_models import Api
|
|
5
|
+
|
|
6
|
+
class GuardianApiParams(TypedDict):
|
|
7
|
+
"""
|
|
8
|
+
Represents the parameters for the Guardian API.
|
|
9
|
+
"""
|
|
10
|
+
base_url: Optional[str]
|
|
11
|
+
session_id: Optional[str]
|
|
12
|
+
env: Optional[str]
|
|
13
|
+
|
|
14
|
+
class GuardianApi:
|
|
15
|
+
"""
|
|
16
|
+
A basic API wrapper for making HTTP requests.
|
|
17
|
+
"""
|
|
18
|
+
def __init__(self, params: GuardianApiParams):
|
|
19
|
+
self._loading = True
|
|
20
|
+
self._lock = threading.Lock()
|
|
21
|
+
self._init(params)
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def loading(self) -> bool:
|
|
25
|
+
return self._loading
|
|
26
|
+
|
|
27
|
+
def _init(self, params):
|
|
28
|
+
try:
|
|
29
|
+
# If no env was supplied, set to PROD.
|
|
30
|
+
self.env = params.get("env", "PROD")
|
|
31
|
+
self.base_url = params.get("base_url")
|
|
32
|
+
self.session_id = params.get("session_id")
|
|
33
|
+
|
|
34
|
+
# If no base_url was supplied, we'll calculate it based on the env.
|
|
35
|
+
if not self.base_url:
|
|
36
|
+
if self.env == "DEV":
|
|
37
|
+
self.base_url = "https://guardian.nextspace-dev.net/"
|
|
38
|
+
elif self.env == "STG":
|
|
39
|
+
self.base_url = "https://guardian.nextspace-stg.net/"
|
|
40
|
+
elif self.env == "UAT":
|
|
41
|
+
self.base_url = "https://guardan.nextspace-uat.net/"
|
|
42
|
+
else:
|
|
43
|
+
self.base_url = "https://guardian.nextspace.host/"
|
|
44
|
+
|
|
45
|
+
self._loading = False
|
|
46
|
+
except Exception as e:
|
|
47
|
+
self._loading = False
|
|
48
|
+
raise e
|
|
49
|
+
|
|
50
|
+
def set_session_id(self, session_id: str):
|
|
51
|
+
"""
|
|
52
|
+
Sets the x-sessionid header for all future requests.
|
|
53
|
+
"""
|
|
54
|
+
self.session_id = session_id
|
|
55
|
+
|
|
56
|
+
def get_env(self):
|
|
57
|
+
"""
|
|
58
|
+
Returns the current environment.
|
|
59
|
+
"""
|
|
60
|
+
return self.env
|
|
61
|
+
|
|
62
|
+
def _build_headers(self) -> Dict[str, str]:
|
|
63
|
+
"""
|
|
64
|
+
Builds the headers for all requests that are sent.
|
|
65
|
+
"""
|
|
66
|
+
headers = {
|
|
67
|
+
"Content-Type": "application/json"
|
|
68
|
+
}
|
|
69
|
+
if self.session_id:
|
|
70
|
+
headers["x-sessionid"] = self.session_id
|
|
71
|
+
return headers
|
|
72
|
+
|
|
73
|
+
def get(self, url: str) -> Dict:
|
|
74
|
+
"""
|
|
75
|
+
Sends a GET request to the API.
|
|
76
|
+
The URL should be absolute.
|
|
77
|
+
"""
|
|
78
|
+
self._wait_for_loading()
|
|
79
|
+
response = requests.get(url, headers=self._build_headers())
|
|
80
|
+
return Api.parse_result(response)
|
|
81
|
+
|
|
82
|
+
def GET(self, url: str) -> Dict:
|
|
83
|
+
"""
|
|
84
|
+
Sends a GET request to the API.
|
|
85
|
+
The URL should be relative to the base URL.
|
|
86
|
+
"""
|
|
87
|
+
self._wait_for_loading()
|
|
88
|
+
full = f"{self.base_url}/{url.lstrip('/')}"
|
|
89
|
+
return self.get(full)
|
|
90
|
+
|
|
91
|
+
def _wait_for_loading(self):
|
|
92
|
+
"""
|
|
93
|
+
Blocks further requests until the loading state is set to False.
|
|
94
|
+
This method will prevent further requests until initialization is complete.
|
|
95
|
+
"""
|
|
96
|
+
with self._lock:
|
|
97
|
+
while self._loading:
|
|
98
|
+
pass
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
from typing import Optional, TypedDict, List, Any
|
|
2
|
+
from bruce_models import BruceApi
|
|
3
|
+
|
|
4
|
+
class JEntityInternal(TypedDict):
|
|
5
|
+
"""
|
|
6
|
+
Represents the Nextspace internal properties defined under the 'Bruce' key of an Entity record.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# ID of the entity.
|
|
10
|
+
# If unset an ID will be generated during the Update request.
|
|
11
|
+
ID: Optional[str]
|
|
12
|
+
# Name of the Entity.
|
|
13
|
+
# This can be set directly, or the Entity Type can be configured to use a specific attribute.
|
|
14
|
+
# If the attribute is changed, a re-index should be launched to update the name.
|
|
15
|
+
Name: Optional[str]
|
|
16
|
+
# Nextspace internal ID.
|
|
17
|
+
# Readonly and created on Entity creation.
|
|
18
|
+
InternalID: Optional[int]
|
|
19
|
+
|
|
20
|
+
# Entity Type ID.
|
|
21
|
+
EntityType_ID: str
|
|
22
|
+
|
|
23
|
+
# ID of the user who created the entity.
|
|
24
|
+
# Will be set automatically on creation.
|
|
25
|
+
CreatedBy_User_ID: Optional[str]
|
|
26
|
+
# Created date/time of the entity.
|
|
27
|
+
CreatedTime: Optional[Any]
|
|
28
|
+
# Array of associated tags (Used to be called layers).
|
|
29
|
+
# Update to change what tags are associated. Exclude from data to keep it the same.
|
|
30
|
+
Layer_ID: Optional[List[int]]
|
|
31
|
+
|
|
32
|
+
# Scenario this is related to. Typically the Key, but if the record isn't found then it will be the ID.
|
|
33
|
+
# When present, this indicates this is a variant of the primary record and not the primary record.
|
|
34
|
+
Scenario: Optional[str | int]
|
|
35
|
+
|
|
36
|
+
# If we're retrieving historic records, then these values are populated,
|
|
37
|
+
# to indicate the historic data key and date-time.
|
|
38
|
+
HistoricAttrKey: Optional[str]
|
|
39
|
+
HistoricDateTime: Optional[str]
|
|
40
|
+
|
|
41
|
+
# Marker that indicates the entity is a calculated alternative schema.
|
|
42
|
+
# This is used to indicate that the entity is read-only and should not be saved.
|
|
43
|
+
SchemaID: Optional[str]
|
|
44
|
+
|
|
45
|
+
# Entity relative position to parent within an assembly.
|
|
46
|
+
AssemblyPosition: Optional[List[List[float]]]
|
|
47
|
+
|
|
48
|
+
# Entity location in degrees/meters.
|
|
49
|
+
# This is typically relative to the active scene's terrain.
|
|
50
|
+
# However what its relative to is dictated by the Entity Style during rendering.
|
|
51
|
+
# This dictates where 3D models are placed, in the absence of VectorGeometry-
|
|
52
|
+
#this is used to place vector points as well.
|
|
53
|
+
Location: Optional[Any]
|
|
54
|
+
# These are applied only to the Entity's LOD and not the VectorGeometry.
|
|
55
|
+
Transform: Optional[Any]
|
|
56
|
+
# Entity boundaries in degrees/meters.
|
|
57
|
+
Boundaries: Optional[Any]
|
|
58
|
+
# Entity vector geometry. Eg: a point, polyline, or polygon to draw.
|
|
59
|
+
VectorGeometry: Optional[Any]
|
|
60
|
+
|
|
61
|
+
class Entity:
|
|
62
|
+
"""
|
|
63
|
+
Represents an Entity in Nextspace.
|
|
64
|
+
You will find the JEntity data-model and all related API communication here.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
class JEntity(TypedDict, total=False):
|
|
68
|
+
"""
|
|
69
|
+
Represents the JSON structure of an Entity.
|
|
70
|
+
"""
|
|
71
|
+
Bruce: JEntityInternal
|
|
72
|
+
__additional__: Optional[dict[str, Any]]
|
|
73
|
+
|
|
74
|
+
@staticmethod
|
|
75
|
+
def get(api: BruceApi, entity_id: str = "") -> JEntity:
|
|
76
|
+
"""
|
|
77
|
+
Retrieves an Entity by its ID.
|
|
78
|
+
"""
|
|
79
|
+
if not entity_id:
|
|
80
|
+
raise ValueError("A valid Entity ID is required.")
|
|
81
|
+
return api.GET(f"v3/entity/{entity_id}")
|
|
82
|
+
|
|
83
|
+
@staticmethod
|
|
84
|
+
def get(api: BruceApi, entity_id: str = "", scenario: Optional[str | int] = 0) -> JEntity:
|
|
85
|
+
"""
|
|
86
|
+
Retrieves an Entity by its ID and Scenario.
|
|
87
|
+
"""
|
|
88
|
+
if not entity_id:
|
|
89
|
+
raise ValueError("A valid Entity ID is required.")
|
|
90
|
+
return api.GET(f"v3/entity/{entity_id}?Scenario={scenario}")
|
|
91
|
+
|
|
92
|
+
@staticmethod
|
|
93
|
+
def get_list(
|
|
94
|
+
api: BruceApi,
|
|
95
|
+
entity_type_id: str = "",
|
|
96
|
+
skip: int = 0,
|
|
97
|
+
take: int = 50,
|
|
98
|
+
scenario: Optional[str | int] = 0
|
|
99
|
+
) -> List[JEntity]:
|
|
100
|
+
"""
|
|
101
|
+
Retrieves a list of Entities.
|
|
102
|
+
"""
|
|
103
|
+
params = {
|
|
104
|
+
"Type": entity_type_id,
|
|
105
|
+
"PageIndex": skip,
|
|
106
|
+
"PageSize": take,
|
|
107
|
+
"Scenario": scenario
|
|
108
|
+
}
|
|
109
|
+
data = api.GET("v3/entities", params)
|
|
110
|
+
return data["Items"]
|
|
111
|
+
|
|
112
|
+
@staticmethod
|
|
113
|
+
def update(
|
|
114
|
+
api: BruceApi,
|
|
115
|
+
# Entity to update/create.
|
|
116
|
+
entity: JEntityInternal,
|
|
117
|
+
# (Optional) Scenario to update the Entity under.
|
|
118
|
+
# It can be specified here, or within the Entity itself.
|
|
119
|
+
# If specified here, it will override the Entity's Scenario.
|
|
120
|
+
scenario: Optional[str | int] = 0
|
|
121
|
+
) -> JEntity:
|
|
122
|
+
"""
|
|
123
|
+
Updates or creates an Entity.
|
|
124
|
+
If an Entity does not have an ID, a new record is made.
|
|
125
|
+
"""
|
|
126
|
+
params = {
|
|
127
|
+
"Scenario": scenario
|
|
128
|
+
}
|
|
129
|
+
return api.POST("v3/entity", entity, params)
|
|
130
|
+
|
|
131
|
+
@staticmethod
|
|
132
|
+
def update_list(
|
|
133
|
+
api: BruceApi,
|
|
134
|
+
# List of Entities to update/create.
|
|
135
|
+
entities: List[JEntityInternal],
|
|
136
|
+
# (Optional) Scenario to update the Entities under.
|
|
137
|
+
# It can be specified here, or within the Entity itself.
|
|
138
|
+
# If specified here, it will override the Entity's Scenario.
|
|
139
|
+
scenario: Optional[str | int] = 0
|
|
140
|
+
) -> List[JEntity]:
|
|
141
|
+
"""
|
|
142
|
+
Updates or creates a list of Entities.
|
|
143
|
+
If an Entity does not have an ID, a new record is made.
|
|
144
|
+
"""
|
|
145
|
+
body = {
|
|
146
|
+
"Items": entities,
|
|
147
|
+
"Scenario": scenario
|
|
148
|
+
}
|
|
149
|
+
data = api.POST("v3/entities", body)
|
|
150
|
+
return data["Items"]
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from typing import Optional, TypedDict, List, Any
|
|
2
|
+
from bruce_models import BruceApi
|
|
3
|
+
|
|
4
|
+
class EntityType:
|
|
5
|
+
"""
|
|
6
|
+
Represents an Entity Type in Nextspace.
|
|
7
|
+
You will find the JEntityType data-model and all related API communication here.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
class JEntityType(TypedDict):
|
|
11
|
+
# ID of the Entity Type.
|
|
12
|
+
ID: Optional[str]
|
|
13
|
+
# Human readable name of the Entity Type.
|
|
14
|
+
Name: str;
|
|
15
|
+
# Human readable description of the Entity Type.
|
|
16
|
+
Description: Optional[str]
|
|
17
|
+
# If Entity Type access (and Entity access) should be restricted.
|
|
18
|
+
# When an Entity Type is restricted a user must have the "EntityType_<typeId>" permission.
|
|
19
|
+
IsAccessRestricted: Optional[bool]
|
|
20
|
+
# The data schema defining expected attributes for entities to have.
|
|
21
|
+
DataSchema: Optional[Any]
|
|
22
|
+
# Attribute that defines Entity names in the Entity Type.
|
|
23
|
+
# If not supplied, then the Entities can have names set directly.
|
|
24
|
+
# It is a comma separated array of attribute string paths.
|
|
25
|
+
DisplayNameAttributePath: Optional[str]
|
|
26
|
+
# If this schema is "strict". If Entities in an Entity Type are different enough between each-other then the schema is not strict.
|
|
27
|
+
# This will dictate how UI will display the attributes.
|
|
28
|
+
IsStrictSchema: Optional[bool]
|
|
29
|
+
# Default Style for the corresponding Entities.
|
|
30
|
+
DisplaySettings_ID: Optional[int]
|
|
31
|
+
# Last updated date/time.
|
|
32
|
+
LastUpdate_Time: Optional[Any]
|
|
33
|
+
# ID of the parent Entity Type (if any).
|
|
34
|
+
# This is used for organization. When a parent type is deleted, the child types are also deleted.
|
|
35
|
+
Parent_EntityType_ID: Optional[str]
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
def get(api: BruceApi, id: str) -> JEntityType:
|
|
39
|
+
"""
|
|
40
|
+
Get an Entity Type by its ID.
|
|
41
|
+
"""
|
|
42
|
+
if not id:
|
|
43
|
+
raise ValueError("ID is required to get an Entity Type.")
|
|
44
|
+
return api.GET("entitytype", id)
|
|
45
|
+
|
|
46
|
+
@staticmethod
|
|
47
|
+
def get_list(api: BruceApi) -> List[JEntityType]:
|
|
48
|
+
"""
|
|
49
|
+
Get a list of all Entity Types.
|
|
50
|
+
"""
|
|
51
|
+
data = api.GET("entitytypes")
|
|
52
|
+
return data["Items"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .scenario import Scenario
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from typing import Optional, TypedDict
|
|
2
|
+
from bruce_models import BruceApi
|
|
3
|
+
|
|
4
|
+
class Scenario:
|
|
5
|
+
"""
|
|
6
|
+
Represents a Scenario in Nextspace.
|
|
7
|
+
You will find the JScenario data-model and all related API communication here.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
class JScenario(TypedDict):
|
|
11
|
+
"""
|
|
12
|
+
Represents the JSON structure of a Scenario.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
# Unique numeric identity of the record.
|
|
16
|
+
# Generated by the database.
|
|
17
|
+
ID: Optional[int]
|
|
18
|
+
# (30) Unique keyword that is used for identification of the record when referred to in URL.
|
|
19
|
+
Key: str
|
|
20
|
+
# (120) User friendly name to display in UI.
|
|
21
|
+
DisplayName: str
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
Represents the Scenario model and provides functions to interact with the API.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
@staticmethod
|
|
28
|
+
def get_by_id(api: BruceApi, scenario_id: int = 0) -> JScenario:
|
|
29
|
+
"""
|
|
30
|
+
Retrieves a Scenario by its ID.
|
|
31
|
+
"""
|
|
32
|
+
if not scenario_id or scenario_id < 1:
|
|
33
|
+
raise ValueError("A valid scenario ID is required.")
|
|
34
|
+
return api.GET(f"scenario/{scenario_id}")
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def get_by_key(api: BruceApi, scenario_key: str = "") -> JScenario:
|
|
38
|
+
"""
|
|
39
|
+
Retrieves a Scenario by its Key.
|
|
40
|
+
"""
|
|
41
|
+
if not scenario_key:
|
|
42
|
+
raise ValueError("A valid scenario Key is required.")
|
|
43
|
+
return api.GET(f"scenario/key/{scenario_key}")
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: bruce-models
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: This is a library which defines data-models for the Nextspace API and provides functions for communicating with the endpoints.
|
|
5
|
+
Author: Matvey Lavrinovich
|
|
6
|
+
Author-email: matveylavrinovich@gmail.com
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Requires-Python: >=3.6
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: requests>=2.0
|
|
13
|
+
|
|
14
|
+
# bruce-models
|
|
15
|
+
|
|
16
|
+
This is a library which defines data-models for the Nextspace API and provides functions for communicating with the endpoints.
|
|
17
|
+
|
|
18
|
+
### Local build
|
|
19
|
+
|
|
20
|
+
- `pip install .`
|
|
21
|
+
|
|
22
|
+
- `python ./public/main.py` (to test it loads after build)
|
|
23
|
+
|
|
24
|
+
### Test a release build
|
|
25
|
+
|
|
26
|
+
- `python -m build`
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
MANIFEST.in
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
setup.py
|
|
5
|
+
bruce_models/__init__.py
|
|
6
|
+
bruce_models.egg-info/PKG-INFO
|
|
7
|
+
bruce_models.egg-info/SOURCES.txt
|
|
8
|
+
bruce_models.egg-info/dependency_links.txt
|
|
9
|
+
bruce_models.egg-info/requires.txt
|
|
10
|
+
bruce_models.egg-info/top_level.txt
|
|
11
|
+
bruce_models/api/__init__.py
|
|
12
|
+
bruce_models/api/api.py
|
|
13
|
+
bruce_models/api/bruce_api.py
|
|
14
|
+
bruce_models/api/guardian_api.py
|
|
15
|
+
bruce_models/entity/__init__.py
|
|
16
|
+
bruce_models/entity/entity.py
|
|
17
|
+
bruce_models/entity/entity_type.py
|
|
18
|
+
bruce_models/scenario/__init__.py
|
|
19
|
+
bruce_models/scenario/scenario.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests>=2.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
bruce_models
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="bruce-models",
|
|
5
|
+
version="0.0.1",
|
|
6
|
+
description="This is a library which defines data-models for the Nextspace API and provides functions for communicating with the endpoints.",
|
|
7
|
+
long_description=open("README.md").read(),
|
|
8
|
+
long_description_content_type="text/markdown",
|
|
9
|
+
author="Matvey Lavrinovich",
|
|
10
|
+
author_email="matveylavrinovich@gmail.com",
|
|
11
|
+
packages=find_packages(),
|
|
12
|
+
install_requires=[
|
|
13
|
+
"requests>=2.0"
|
|
14
|
+
],
|
|
15
|
+
classifiers=[
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Intended Audience :: Developers"
|
|
19
|
+
],
|
|
20
|
+
python_requires=">=3.6",
|
|
21
|
+
)
|