geobox 2.3.0__py3-none-any.whl → 2.4.0__py3-none-any.whl
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.
- geobox/aio/api.py +153 -7
- geobox/aio/apikey.py +0 -26
- geobox/aio/attachment.py +5 -31
- geobox/aio/basemap.py +2 -30
- geobox/aio/dashboard.py +0 -26
- geobox/aio/feature.py +172 -17
- geobox/aio/field.py +0 -27
- geobox/aio/file.py +0 -26
- geobox/aio/layout.py +0 -26
- geobox/aio/log.py +0 -27
- geobox/aio/map.py +0 -26
- geobox/aio/model3d.py +0 -26
- geobox/aio/mosaic.py +0 -26
- geobox/aio/plan.py +0 -26
- geobox/aio/query.py +0 -26
- geobox/aio/raster.py +0 -26
- geobox/aio/scene.py +1 -26
- geobox/aio/settings.py +0 -28
- geobox/aio/table.py +644 -55
- geobox/aio/task.py +0 -27
- geobox/aio/tile3d.py +0 -26
- geobox/aio/tileset.py +1 -26
- geobox/aio/usage.py +0 -32
- geobox/aio/user.py +0 -59
- geobox/aio/vector_tool.py +49 -0
- geobox/aio/vectorlayer.py +8 -34
- geobox/aio/version.py +1 -25
- geobox/aio/view.py +5 -35
- geobox/aio/workflow.py +0 -26
- geobox/api.py +152 -7
- geobox/apikey.py +0 -26
- geobox/attachment.py +0 -26
- geobox/basemap.py +0 -28
- geobox/dashboard.py +0 -26
- geobox/enums.py +11 -1
- geobox/feature.py +170 -15
- geobox/field.py +0 -28
- geobox/file.py +0 -26
- geobox/layout.py +0 -26
- geobox/log.py +0 -26
- geobox/map.py +0 -26
- geobox/model3d.py +0 -26
- geobox/mosaic.py +0 -26
- geobox/plan.py +1 -26
- geobox/query.py +1 -26
- geobox/raster.py +1 -31
- geobox/scene.py +1 -27
- geobox/settings.py +1 -29
- geobox/table.py +640 -55
- geobox/task.py +2 -29
- geobox/tile3d.py +0 -26
- geobox/tileset.py +1 -26
- geobox/usage.py +2 -33
- geobox/user.py +1 -59
- geobox/vector_tool.py +49 -0
- geobox/vectorlayer.py +9 -36
- geobox/version.py +1 -26
- geobox/view.py +4 -34
- geobox/workflow.py +1 -26
- {geobox-2.3.0.dist-info → geobox-2.4.0.dist-info}/METADATA +1 -1
- geobox-2.4.0.dist-info/RECORD +74 -0
- {geobox-2.3.0.dist-info → geobox-2.4.0.dist-info}/WHEEL +1 -1
- geobox-2.3.0.dist-info/RECORD +0 -74
- {geobox-2.3.0.dist-info → geobox-2.4.0.dist-info}/licenses/LICENSE +0 -0
- {geobox-2.3.0.dist-info → geobox-2.4.0.dist-info}/top_level.txt +0 -0
geobox/aio/api.py
CHANGED
|
@@ -32,7 +32,7 @@ from .attachment import AsyncAttachment
|
|
|
32
32
|
from .apikey import AsyncApiKey
|
|
33
33
|
from .log import AsyncLog
|
|
34
34
|
from .usage import AsyncUsage, UsageScale, UsageParam
|
|
35
|
-
from .table import AsyncTable
|
|
35
|
+
from .table import AsyncTable, AsyncRelationship, RelationshipCardinality, RelationshipEndpoint
|
|
36
36
|
from ..exception import AuthenticationError, ApiRequestError, NotFoundError, ValidationError, ServerError, AuthorizationError
|
|
37
37
|
from ..utils import join_url_params
|
|
38
38
|
|
|
@@ -130,11 +130,10 @@ class AsyncGeoboxClient:
|
|
|
130
130
|
"""
|
|
131
131
|
Constructs all the necessary attributes for the Api object.
|
|
132
132
|
"""
|
|
133
|
-
self.username =
|
|
134
|
-
self.password =
|
|
135
|
-
self.access_token =
|
|
136
|
-
self.apikey =
|
|
137
|
-
|
|
133
|
+
self.username = username if username else os.getenv('GEOBOX_USERNAME')
|
|
134
|
+
self.password = password if password else os.getenv('GEOBOX_PASSWORD')
|
|
135
|
+
self.access_token = access_token if access_token else os.getenv('GEOBOX_ACCESS_TOKEN')
|
|
136
|
+
self.apikey = apikey if apikey else os.getenv('GEOBOX_APIKEY')
|
|
138
137
|
self.session = AsyncRequestSession(access_token=self.access_token)
|
|
139
138
|
|
|
140
139
|
host = host.lower()
|
|
@@ -2766,4 +2765,151 @@ class AsyncGeoboxClient:
|
|
|
2766
2765
|
>>> async with AsyncGeoboxClient() as client:
|
|
2767
2766
|
>>> table = await client.get_table_by_name(name='test')
|
|
2768
2767
|
"""
|
|
2769
|
-
return await AsyncTable.get_table_by_name(self, name, user_id)
|
|
2768
|
+
return await AsyncTable.get_table_by_name(self, name, user_id)
|
|
2769
|
+
|
|
2770
|
+
|
|
2771
|
+
async def get_relationships(
|
|
2772
|
+
self,
|
|
2773
|
+
**kwargs,
|
|
2774
|
+
) -> Union[List['AsyncRelationship'], int]:
|
|
2775
|
+
"""
|
|
2776
|
+
[async] Get a list of relationships with optional filtering and pagination.
|
|
2777
|
+
|
|
2778
|
+
Keyword Args:
|
|
2779
|
+
q (str): query filter based on OGC CQL standard. e.g. "field1 LIKE '%GIS%' AND created_at > '2021-01-01'"
|
|
2780
|
+
search (str): search term for keyword-based searching among search_fields or all textual fields if search_fields does not have value. NOTE: if q param is defined this param will be ignored
|
|
2781
|
+
search_fields (str): comma separated list of fields for searching
|
|
2782
|
+
order_by (str): comma separated list of fields for sorting results [field1 A|D, field2 A|D, …]. e.g. name A, type D. NOTE: "A" denotes ascending order and "D" denotes descending order.
|
|
2783
|
+
return_count (bool): Whether to return total count. default: False.
|
|
2784
|
+
skip (int): Number of items to skip. default: 0
|
|
2785
|
+
limit (int): Number of items to return. default: 10
|
|
2786
|
+
user_id (int): Specific user. privileges required
|
|
2787
|
+
shared (bool): Whether to return shared tables. default: False
|
|
2788
|
+
|
|
2789
|
+
Returns:
|
|
2790
|
+
List[AsyncRelationship] | int: A list of relationship instances or the total number of relationships.
|
|
2791
|
+
|
|
2792
|
+
Example:
|
|
2793
|
+
>>> from geobox.aio import AsyncGeoboxClient
|
|
2794
|
+
>>> async with AsyncGeoboxClient() as client:
|
|
2795
|
+
>>> relationships = await client.get_relationships(q="name LIKE '%My relationship%'")
|
|
2796
|
+
"""
|
|
2797
|
+
return await AsyncRelationship.get_relationships(self, **kwargs)
|
|
2798
|
+
|
|
2799
|
+
|
|
2800
|
+
async def create_relationship(
|
|
2801
|
+
self,
|
|
2802
|
+
name: str,
|
|
2803
|
+
cardinality: 'RelationshipCardinality',
|
|
2804
|
+
*,
|
|
2805
|
+
source: 'RelationshipEndpoint',
|
|
2806
|
+
target: 'RelationshipEndpoint',
|
|
2807
|
+
relation_table: Optional['AsyncTable'] = None,
|
|
2808
|
+
display_name: Optional[str] = None,
|
|
2809
|
+
description: Optional[str] = None,
|
|
2810
|
+
user_id: Optional[int] = None,
|
|
2811
|
+
) -> 'AsyncRelationship':
|
|
2812
|
+
"""
|
|
2813
|
+
[async] Create a new AsyncRelationship
|
|
2814
|
+
|
|
2815
|
+
Args:
|
|
2816
|
+
name (str): name of the relationship
|
|
2817
|
+
cardinality (RelationshipCardinality): One to One, One to Many, or Many to Many
|
|
2818
|
+
|
|
2819
|
+
Keyword Args:
|
|
2820
|
+
source (RelationshipEndpoint): Definition of the source side of the relationship, including the table (or layer), field, and foreign-key field
|
|
2821
|
+
target (RelationshipEndpoint): Definition of the target side of the relationship, including the table (or layer), field, and foreign-key field
|
|
2822
|
+
relation_table (AsyncTable, optional): The table that stores the relationship metadata or join records. (Required for Many-to-Many relationships)
|
|
2823
|
+
display_name (str, optional): Human-readable name for the relationship
|
|
2824
|
+
description (str, optional): the description of the relationship
|
|
2825
|
+
user_id (int, optional): Specific user. privileges required.
|
|
2826
|
+
|
|
2827
|
+
Returns:
|
|
2828
|
+
AsyncRelationship: a relationship instance
|
|
2829
|
+
|
|
2830
|
+
Example:
|
|
2831
|
+
>>> from geobox.aio import AsyncGeoboxClient
|
|
2832
|
+
>>> from geobox.aio.table import RelationshipEndpoint, RelationshipCardinality
|
|
2833
|
+
>>> async with AsyncGeoboxClient() as client:
|
|
2834
|
+
>>> source = RelationshipEndpoint(
|
|
2835
|
+
... table=client.get_table_by_name('owner'),
|
|
2836
|
+
... field="name", # on source table
|
|
2837
|
+
... fk_field="book_name", # on relation table
|
|
2838
|
+
... )
|
|
2839
|
+
>>> target = RelationshipEndpoint(
|
|
2840
|
+
... table=client.get_table_by_name('parcel'),
|
|
2841
|
+
... field="name", # on target table
|
|
2842
|
+
... fk_field="author_name", # on relation table
|
|
2843
|
+
... )
|
|
2844
|
+
>>> relationship = await client.create_relationship(
|
|
2845
|
+
... name="owner_parcel",
|
|
2846
|
+
... cardinality=RelationshipCardinality.ManytoMany,
|
|
2847
|
+
... source=source,
|
|
2848
|
+
... target=target,
|
|
2849
|
+
... relation_table=client.get_table_by_name('owner_parcel'),
|
|
2850
|
+
... )
|
|
2851
|
+
"""
|
|
2852
|
+
return await AsyncRelationship.create_relationship(
|
|
2853
|
+
self,
|
|
2854
|
+
name=name,
|
|
2855
|
+
cardinality=cardinality,
|
|
2856
|
+
source=source,
|
|
2857
|
+
target=target,
|
|
2858
|
+
relation_table=relation_table,
|
|
2859
|
+
display_name=display_name,
|
|
2860
|
+
description=description,
|
|
2861
|
+
user_id=user_id,
|
|
2862
|
+
)
|
|
2863
|
+
|
|
2864
|
+
|
|
2865
|
+
async def get_relationship(
|
|
2866
|
+
self,
|
|
2867
|
+
uuid: str,
|
|
2868
|
+
user_id: Optional[int] = None,
|
|
2869
|
+
) -> 'AsyncRelationship':
|
|
2870
|
+
"""
|
|
2871
|
+
[async] Get a relationship by UUID.
|
|
2872
|
+
|
|
2873
|
+
Args:
|
|
2874
|
+
uuid (str): The UUID of the relationship to get.
|
|
2875
|
+
user_id (int, optional): Specific user. privileges required.
|
|
2876
|
+
|
|
2877
|
+
Returns:
|
|
2878
|
+
AsyncRelationship: The AsyncRelationship object.
|
|
2879
|
+
|
|
2880
|
+
Raises:
|
|
2881
|
+
NotFoundError: If the AsyncRelationship with the specified UUID is not found.
|
|
2882
|
+
|
|
2883
|
+
Example:
|
|
2884
|
+
>>> from geobox.aio import AsyncGeoboxClient
|
|
2885
|
+
>>> async with AsyncGeoboxClient() as client:
|
|
2886
|
+
>>> relationship = await client.get_relationship(uuid="12345678-1234-5678-1234-567812345678")
|
|
2887
|
+
"""
|
|
2888
|
+
return await AsyncRelationship.get_relationship(
|
|
2889
|
+
self,
|
|
2890
|
+
uuid=uuid,
|
|
2891
|
+
user_id=user_id,
|
|
2892
|
+
)
|
|
2893
|
+
|
|
2894
|
+
|
|
2895
|
+
async def get_relationship_by_name(
|
|
2896
|
+
self,
|
|
2897
|
+
name: str,
|
|
2898
|
+
user_id: Optional[int] = None,
|
|
2899
|
+
) -> Union['AsyncRelationship', None]:
|
|
2900
|
+
"""
|
|
2901
|
+
[async] Get a relationship by name
|
|
2902
|
+
|
|
2903
|
+
Args:
|
|
2904
|
+
name (str): the name of the relationship to get
|
|
2905
|
+
user_id (int, optional): specific user. privileges required.
|
|
2906
|
+
|
|
2907
|
+
Returns:
|
|
2908
|
+
AsyncRelationship | None: returns the relationship if a relationship matches the given name, else None
|
|
2909
|
+
|
|
2910
|
+
Example:
|
|
2911
|
+
>>> from geobox.aio import AsyncGeoboxClient
|
|
2912
|
+
>>> async with AsyncGeoboxClient() as client:
|
|
2913
|
+
>>> relationship = await client.get_relationship_by_name(name='test')
|
|
2914
|
+
"""
|
|
2915
|
+
return await AsyncRelationship.get_relationship_by_name(self, name=name, user_id=user_id)
|
geobox/aio/apikey.py
CHANGED
|
@@ -6,8 +6,6 @@ from ..utils import clean_data
|
|
|
6
6
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
8
|
from . import AsyncGeoboxClient
|
|
9
|
-
from ..api import GeoboxClient
|
|
10
|
-
from ..apikey import ApiKey
|
|
11
9
|
|
|
12
10
|
|
|
13
11
|
class AsyncApiKey(AsyncBase):
|
|
@@ -237,27 +235,3 @@ class AsyncApiKey(AsyncBase):
|
|
|
237
235
|
endpoint = f"{self.endpoint}/grant"
|
|
238
236
|
await self.api.post(endpoint)
|
|
239
237
|
self.data['revoked'] = False
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
def to_sync(self, sync_client: 'GeoboxClient') -> 'ApiKey':
|
|
243
|
-
"""
|
|
244
|
-
Switch to sync version of the apikey instance to have access to the sync methods
|
|
245
|
-
|
|
246
|
-
Args:
|
|
247
|
-
sync_client (GeoboxClient): The sync version of the GeoboxClient instance for making requests.
|
|
248
|
-
|
|
249
|
-
Returns:
|
|
250
|
-
ApiKey: the sync instance of the apikey.
|
|
251
|
-
|
|
252
|
-
Example:
|
|
253
|
-
>>> from geobox import Geoboxclient
|
|
254
|
-
>>> from geobox.aio import AsyncGeoboxClient
|
|
255
|
-
>>> from geobox.aio.apikey import AsyncApiKey
|
|
256
|
-
>>> client = GeoboxClient()
|
|
257
|
-
>>> async with AsyncGeoboxClient() as async_client:
|
|
258
|
-
>>> apikey = await AsyncApiKey.get_apikey(async_client, key_id=1)
|
|
259
|
-
>>> sync_apikey = apikey.to_sync(client)
|
|
260
|
-
"""
|
|
261
|
-
from ..apikey import ApiKey
|
|
262
|
-
|
|
263
|
-
return ApiKey(api=sync_client, key_id=self.key_id, data=self.data)
|
geobox/aio/attachment.py
CHANGED
|
@@ -10,9 +10,7 @@ from ..utils import clean_data
|
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
12
|
from . import AsyncGeoboxClient
|
|
13
|
-
from .feature import
|
|
14
|
-
from ..api import GeoboxClient
|
|
15
|
-
from ..attachment import Attachment
|
|
13
|
+
from .feature import AsyncFeature
|
|
16
14
|
|
|
17
15
|
|
|
18
16
|
class AsyncAttachment(AsyncBase):
|
|
@@ -126,8 +124,8 @@ class AsyncAttachment(AsyncBase):
|
|
|
126
124
|
loc_x: int,
|
|
127
125
|
loc_y: int,
|
|
128
126
|
resource: Union['AsyncMap', 'AsyncVectorLayer', 'AsyncVectorLayerView'],
|
|
129
|
-
file: '
|
|
130
|
-
feature: '
|
|
127
|
+
file: 'AsyncFile',
|
|
128
|
+
feature: 'AsyncFeature' = None,
|
|
131
129
|
display_name: str = None,
|
|
132
130
|
description: str = None, ) -> 'AsyncAttachment':
|
|
133
131
|
"""
|
|
@@ -139,8 +137,8 @@ class AsyncAttachment(AsyncBase):
|
|
|
139
137
|
loc_x (int): x parameter of the attachment location.
|
|
140
138
|
loc_y (int): y parameter of the attachment location.
|
|
141
139
|
resource (AsyncMap | AsyncVectorLayer | AsyncVectorLayerView): the resource object.
|
|
142
|
-
file (
|
|
143
|
-
feature (
|
|
140
|
+
file (AsyncFile): the file object.
|
|
141
|
+
feature (AsyncFeature, optional): the feature object.
|
|
144
142
|
display_name (str, optional): The display name of the scene.
|
|
145
143
|
description (str, optional): The description of the scene.
|
|
146
144
|
|
|
@@ -315,27 +313,3 @@ class AsyncAttachment(AsyncBase):
|
|
|
315
313
|
>>> attachment.thumbnail
|
|
316
314
|
"""
|
|
317
315
|
return super()._thumbnail(format='')
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
def to_sync(self, sync_client: 'GeoboxClient') -> 'Attachment':
|
|
321
|
-
"""
|
|
322
|
-
Switch to sync version of the attachment instance to have access to the sync methods
|
|
323
|
-
|
|
324
|
-
Args:
|
|
325
|
-
sync_client (GeoboxClient): The sync version of the GeoboxClient instance for making requests.
|
|
326
|
-
|
|
327
|
-
Returns:
|
|
328
|
-
Attachment: the sync instance of the attachment.
|
|
329
|
-
|
|
330
|
-
Example:
|
|
331
|
-
>>> from geobox import Geoboxclient
|
|
332
|
-
>>> from geobox.aio import AsyncGeoboxClient
|
|
333
|
-
>>> from geobox.aio.attachment import AsyncAttachment
|
|
334
|
-
>>> client = GeoboxClient()
|
|
335
|
-
>>> async with AsyncGeoboxClient() as async_client:
|
|
336
|
-
>>> attachment = await AsyncAttachment.get_attachment(async_client, uuid="12345678-1234-5678-1234-567812345678")
|
|
337
|
-
>>> sync_attachment = attachment.to_sync(client)
|
|
338
|
-
"""
|
|
339
|
-
from ..attachment import Attachment
|
|
340
|
-
|
|
341
|
-
return Attachment(api=sync_client, attachment_id=self.attachment_id, data=self.data)
|
geobox/aio/basemap.py
CHANGED
|
@@ -7,8 +7,6 @@ from ..utils import clean_data
|
|
|
7
7
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
9
9
|
from . import AsyncGeoboxClient
|
|
10
|
-
from ..api import GeoboxClient
|
|
11
|
-
from ..basemap import Basemap
|
|
12
10
|
|
|
13
11
|
|
|
14
12
|
class AsyncBasemap(AsyncBase):
|
|
@@ -143,12 +141,12 @@ class AsyncBasemap(AsyncBase):
|
|
|
143
141
|
|
|
144
142
|
|
|
145
143
|
@classmethod
|
|
146
|
-
async def proxy_basemap(cls, api: '
|
|
144
|
+
async def proxy_basemap(cls, api: 'AsyncGeoboxClient', url: str) -> None:
|
|
147
145
|
"""
|
|
148
146
|
[async] Proxy the basemap
|
|
149
147
|
|
|
150
148
|
Args:
|
|
151
|
-
api (
|
|
149
|
+
api (AsyncGeoboxClient): The GeoboxClient instance for making requests.
|
|
152
150
|
url (str): the proxy server url.
|
|
153
151
|
|
|
154
152
|
Returns:
|
|
@@ -168,29 +166,3 @@ class AsyncBasemap(AsyncBase):
|
|
|
168
166
|
query_string = urlencode(param)
|
|
169
167
|
endpoint = urljoin(cls.BASE_ENDPOINT, f"?{query_string}")
|
|
170
168
|
await api.get(endpoint)
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
def to_sync(self, sync_client: 'GeoboxClient') -> 'Basemap':
|
|
174
|
-
"""
|
|
175
|
-
Switch to sync version of the basemap instance to have access to the sync methods
|
|
176
|
-
|
|
177
|
-
Args:
|
|
178
|
-
sync_client (GeoboxClient): The sync version of the GeoboxClient instance for making requests.
|
|
179
|
-
|
|
180
|
-
Returns:
|
|
181
|
-
Basemap: the sync instance of the basemap.
|
|
182
|
-
|
|
183
|
-
Example:
|
|
184
|
-
>>> from geobox import Geoboxclient
|
|
185
|
-
>>> from geobox.aio import AsyncGeoboxClient
|
|
186
|
-
>>> from geobox.aio.basemap import AsyncBasemap
|
|
187
|
-
>>> client = GeoboxClient()
|
|
188
|
-
>>> async with AsyncGeoboxClient() as async_client:
|
|
189
|
-
>>> basemap = await AsyncBasemap.get_basemap(async_client, name='test')
|
|
190
|
-
or
|
|
191
|
-
>>> basemap = await async_client.get_basemap(name='test')
|
|
192
|
-
>>> sync_basemap = basemap.to_sync(client)
|
|
193
|
-
"""
|
|
194
|
-
from ..basemap import Basemap
|
|
195
|
-
|
|
196
|
-
return Basemap(api=sync_client, data=self.data)
|
geobox/aio/dashboard.py
CHANGED
|
@@ -5,8 +5,6 @@ from .base import AsyncBase
|
|
|
5
5
|
if TYPE_CHECKING:
|
|
6
6
|
from . import AsyncGeoboxClient
|
|
7
7
|
from .user import AsyncUser
|
|
8
|
-
from ..api import GeoboxClient
|
|
9
|
-
from ..dashboard import Dashboard
|
|
10
8
|
|
|
11
9
|
|
|
12
10
|
class AsyncDashboard(AsyncBase):
|
|
@@ -314,27 +312,3 @@ class AsyncDashboard(AsyncBase):
|
|
|
314
312
|
'limit': limit
|
|
315
313
|
}
|
|
316
314
|
return await super()._get_shared_users(self.endpoint, params)
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
def to_sync(self, sync_client: 'GeoboxClient') -> 'Dashboard':
|
|
320
|
-
"""
|
|
321
|
-
Switch to sync version of the dashboard instance to have access to the sync methods
|
|
322
|
-
|
|
323
|
-
Args:
|
|
324
|
-
sync_client (GeoboxClient): The sync version of the GeoboxClient instance for making requests.
|
|
325
|
-
|
|
326
|
-
Returns:
|
|
327
|
-
Dashboard: the sync instance of the dashboard.
|
|
328
|
-
|
|
329
|
-
Example:
|
|
330
|
-
>>> from geobox import Geoboxclient
|
|
331
|
-
>>> from geobox.aio import AsyncGeoboxClient
|
|
332
|
-
>>> from geobox.aio.dashboard import AsyncDashboard
|
|
333
|
-
>>> client = GeoboxClient()
|
|
334
|
-
>>> async with AsyncGeoboxClient() as async_client:
|
|
335
|
-
>>> dashboard = await AsyncDashboard.get_dashboard(async_client, uuid="12345678-1234-5678-1234-567812345678")
|
|
336
|
-
>>> sync_dashboard = dashboard.to_sync(client)
|
|
337
|
-
"""
|
|
338
|
-
from ..dashboard import Dashboard
|
|
339
|
-
|
|
340
|
-
return Dashboard(api=sync_client, uuid=self.uuid, data=self.data)
|
geobox/aio/feature.py
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
from urllib.parse import urljoin
|
|
2
|
-
from typing import Optional, List, Dict, Any, TYPE_CHECKING
|
|
2
|
+
from typing import Optional, List, Dict, Any, TYPE_CHECKING, Union
|
|
3
3
|
|
|
4
4
|
from .base import AsyncBase
|
|
5
5
|
from ..enums import FeatureType
|
|
6
6
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
|
-
from .vectorlayer import VectorLayer
|
|
9
|
-
from
|
|
10
|
-
from ..feature import Feature
|
|
8
|
+
from .vectorlayer import VectorLayer, AsyncVectorLayer
|
|
9
|
+
from .table import AsyncTable, AsyncTableRow, AsyncRelationship
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
class AsyncFeature(AsyncBase):
|
|
@@ -522,26 +521,182 @@ class AsyncFeature(AsyncBase):
|
|
|
522
521
|
return self
|
|
523
522
|
|
|
524
523
|
|
|
525
|
-
def
|
|
524
|
+
async def _get_other_side_of_relationship(
|
|
525
|
+
self,
|
|
526
|
+
relationship: 'AsyncRelationship',
|
|
527
|
+
) -> Union['AsyncTable', 'AsyncVectorLayer']:
|
|
526
528
|
"""
|
|
527
|
-
[async]
|
|
529
|
+
[async] Determine which side of a relationship this table is on and return the opposite side.
|
|
530
|
+
|
|
531
|
+
Used internally to navigate bidirectional relationships.
|
|
532
|
+
|
|
533
|
+
Args:
|
|
534
|
+
relationship (AsyncRelationship): The relationship to examine.
|
|
535
|
+
|
|
536
|
+
Returns:
|
|
537
|
+
AsyncTable | AsyncVectorLayer: The endpoint (table or layer) on the opposite side
|
|
538
|
+
of the relationship from this table.
|
|
539
|
+
|
|
540
|
+
Raises:
|
|
541
|
+
ValueError: If this table is not part of the given relationship.
|
|
542
|
+
|
|
543
|
+
Note:
|
|
544
|
+
This method assumes the table is either the source or target,
|
|
545
|
+
not the relation table in Many-to-Many relationships.
|
|
546
|
+
"""
|
|
547
|
+
if relationship.source_id == self.layer.id:
|
|
548
|
+
return await relationship.get_target()
|
|
549
|
+
|
|
550
|
+
if relationship.target_id == self.layer.id:
|
|
551
|
+
return await relationship.get_source()
|
|
528
552
|
|
|
553
|
+
raise ValueError("Relationship does not involve this table.")
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
async def _fetch_related_from_target(
|
|
557
|
+
self,
|
|
558
|
+
target: Union['AsyncTable', 'AsyncVectorLayer'],
|
|
559
|
+
relationship_uuid: str,
|
|
560
|
+
) -> Union[List['AsyncTableRow'], List['AsyncFeature']]:
|
|
561
|
+
"""
|
|
562
|
+
[async] Fetch related rows/features from a relationship target.
|
|
563
|
+
|
|
564
|
+
Internal helper that dispatches to the appropriate API method
|
|
565
|
+
based on target type.
|
|
566
|
+
|
|
529
567
|
Args:
|
|
530
|
-
|
|
568
|
+
target (AsyncTable | AsyncVectorLayer): The target endpoint (Table or VectorLayer) to query.
|
|
569
|
+
relationship_uuid (str): UUID of the relationship to traverse.
|
|
570
|
+
|
|
571
|
+
Raises:
|
|
572
|
+
TypeError: If target is not a Table or VectorLayer.
|
|
531
573
|
|
|
532
574
|
Returns:
|
|
533
|
-
|
|
575
|
+
List[AsyncTableRow] | List[AsyncFeature]: Related rows or features.
|
|
576
|
+
"""
|
|
577
|
+
from .table import AsyncTable
|
|
578
|
+
from .vectorlayer import AsyncVectorLayer
|
|
579
|
+
|
|
580
|
+
if isinstance(target, AsyncTable):
|
|
581
|
+
return await target.get_rows(
|
|
582
|
+
relationship_uuid=relationship_uuid,
|
|
583
|
+
related_record_id=self.id,
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
if isinstance(target, AsyncVectorLayer):
|
|
587
|
+
return await target.get_features(
|
|
588
|
+
relationship_uuid=relationship_uuid,
|
|
589
|
+
related_record_id=self.id,
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
raise TypeError(f"Unsupported target type: {type(target)}")
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
async def get_related_records(self,
|
|
596
|
+
relationship_uuid: str,
|
|
597
|
+
) -> Union[List['AsyncTableRow'], List['AsyncFeature']]:
|
|
598
|
+
"""
|
|
599
|
+
[async] Get the related records on the *other side* of the relationship that are linked to this row
|
|
600
|
+
|
|
601
|
+
Args:
|
|
602
|
+
relationship_uuid (str): The uuid of relationship
|
|
603
|
+
|
|
604
|
+
Returns:
|
|
605
|
+
List[AsyncTableRow] | List[AsyncFeature]: a list of the related records
|
|
606
|
+
|
|
607
|
+
Raises:
|
|
608
|
+
ValueError:
|
|
609
|
+
If the given relationship does not involve the current table
|
|
610
|
+
(i.e., this row is neither the source nor the target of the relationship).
|
|
611
|
+
|
|
612
|
+
TypeError:
|
|
613
|
+
If the relationship target type is not supported for fetching
|
|
614
|
+
related records.
|
|
534
615
|
|
|
535
616
|
Example:
|
|
536
|
-
>>> from geobox import Geoboxclient
|
|
537
617
|
>>> from geobox.aio import AsyncGeoboxClient
|
|
538
|
-
>>>
|
|
539
|
-
>>>
|
|
540
|
-
>>>
|
|
541
|
-
>>>
|
|
542
|
-
|
|
618
|
+
>>> async with AsyncGeoboxClient() as client:
|
|
619
|
+
>>> layer = await client.get_vector(uuid="12345678-1234-5678-1234-567812345678")
|
|
620
|
+
>>> feature = await layer.get_feature(feature_id=1)
|
|
621
|
+
>>> related_records = await feature.get_related_records(relationship_uuid="12345678-1234-5678-1234-567812345678")
|
|
622
|
+
"""
|
|
623
|
+
relationship = await self.api.get_relationship(relationship_uuid)
|
|
624
|
+
|
|
625
|
+
other_side = await self._get_other_side_of_relationship(relationship)
|
|
626
|
+
|
|
627
|
+
return await self._fetch_related_from_target(
|
|
628
|
+
target=other_side,
|
|
629
|
+
relationship_uuid=relationship_uuid,
|
|
630
|
+
)
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
async def associate_with(
|
|
634
|
+
self,
|
|
635
|
+
relationship_uuid: str,
|
|
636
|
+
*,
|
|
637
|
+
target_ids: Optional[List[int]] = None,
|
|
638
|
+
q: Optional[str] = None,
|
|
639
|
+
) -> Dict:
|
|
543
640
|
"""
|
|
544
|
-
|
|
641
|
+
[async] Create relationships between the source record and target records
|
|
642
|
+
|
|
643
|
+
Args:
|
|
644
|
+
relationship_uuid (str): the relationship uuid
|
|
645
|
+
target_ids (List[int], optional): a list of target record ids to be associated with the current record
|
|
646
|
+
q (str, optional): query filter on target layer or table to select which target features or rows that are going to be related to the current record
|
|
647
|
+
|
|
648
|
+
Returns:
|
|
649
|
+
Dict: the record association result
|
|
545
650
|
|
|
546
|
-
|
|
547
|
-
|
|
651
|
+
Example:
|
|
652
|
+
>>> from geobox.aio import AsyncGeoboxClient
|
|
653
|
+
>>> async with AsyncGeoboxClient() as client:
|
|
654
|
+
>>> layer = await client.get_vector(uuid="12345678-1234-5678-1234-567812345678")
|
|
655
|
+
>>> feature = await layer.get_feature(feature_id=1)
|
|
656
|
+
>>> await feature.associate_with(
|
|
657
|
+
... relationship_uuid="12345678-1234-5678-1234-567812345678",
|
|
658
|
+
... target_ids=[1, 2, 3],
|
|
659
|
+
... )
|
|
660
|
+
"""
|
|
661
|
+
relationship = await self.api.get_relationship(uuid=relationship_uuid)
|
|
662
|
+
return await relationship.associate_records(
|
|
663
|
+
source_id=self.id,
|
|
664
|
+
target_ids=target_ids,
|
|
665
|
+
q=q,
|
|
666
|
+
)
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
async def disassociate_with(
|
|
670
|
+
self,
|
|
671
|
+
relationship_uuid: str,
|
|
672
|
+
*,
|
|
673
|
+
target_ids: Optional[List[int]] = None,
|
|
674
|
+
q: Optional[str] = None,
|
|
675
|
+
) -> Dict:
|
|
676
|
+
"""
|
|
677
|
+
[async] Remove relationships between the source record and target records
|
|
678
|
+
|
|
679
|
+
Args:
|
|
680
|
+
relationship_uuid (str): the relationship uuid
|
|
681
|
+
target_ids (List[int], optional): a list of target record ids to be disassociated with the current record
|
|
682
|
+
q (str, optional): query filter on target layer or table to select which target features or rows that are going to be related to the current record
|
|
683
|
+
|
|
684
|
+
Returns:
|
|
685
|
+
Dict: the record association result
|
|
686
|
+
|
|
687
|
+
Example:
|
|
688
|
+
>>> from geobox.aio import AsyncGeoboxClient
|
|
689
|
+
>>> async with AsyncGeoboxClient() as client:
|
|
690
|
+
>>> layer = await client.get_vector(uuid="12345678-1234-5678-1234-567812345678")
|
|
691
|
+
>>> feature = await layer.get_feature(feature_id=1)
|
|
692
|
+
>>> await feature.disassociate_with(
|
|
693
|
+
... relationship_uuid="12345678-1234-5678-1234-567812345678",
|
|
694
|
+
... target_ids=[1, 2, 3],
|
|
695
|
+
... )
|
|
696
|
+
"""
|
|
697
|
+
relationship = await self.api.get_relationship(uuid=relationship_uuid)
|
|
698
|
+
return await relationship.disassociate_records(
|
|
699
|
+
source_id=self.id,
|
|
700
|
+
target_ids=target_ids,
|
|
701
|
+
q=q,
|
|
702
|
+
)
|
geobox/aio/field.py
CHANGED
|
@@ -8,8 +8,6 @@ from ..enums import FieldType
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
9
9
|
from .api import AsyncGeoboxClient
|
|
10
10
|
from .vectorlayer import VectorLayer
|
|
11
|
-
from ..api import GeoboxClient
|
|
12
|
-
from ..field import Field
|
|
13
11
|
|
|
14
12
|
|
|
15
13
|
class AsyncField(AsyncBase):
|
|
@@ -288,28 +286,3 @@ class AsyncField(AsyncBase):
|
|
|
288
286
|
|
|
289
287
|
await self.save()
|
|
290
288
|
return self.domain
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
def to_sync(self, sync_client: 'GeoboxClient') -> 'Field':
|
|
294
|
-
"""
|
|
295
|
-
Switch to sync version of the field instance to have access to the sync methods
|
|
296
|
-
|
|
297
|
-
Args:
|
|
298
|
-
sync_client (GeoboxClient): The sync version of the GeoboxClient instance for making requests.
|
|
299
|
-
|
|
300
|
-
Returns:
|
|
301
|
-
Field: the sync instance of the field.
|
|
302
|
-
|
|
303
|
-
Example:
|
|
304
|
-
>>> from geobox import Geoboxclient
|
|
305
|
-
>>> from geobox.aio import AsyncGeoboxClient
|
|
306
|
-
>>> client = GeoboxClient()
|
|
307
|
-
>>> async with AsyncGeoboxClient() as async_client:
|
|
308
|
-
>>> layer = await async_client.get_vector(uuid="12345678-1234-5678-1234-567812345678")
|
|
309
|
-
>>> field = await layer.get_field(name='test')
|
|
310
|
-
>>> sync_field = field.to_sync(client)
|
|
311
|
-
"""
|
|
312
|
-
from ..field import Field
|
|
313
|
-
|
|
314
|
-
sync_layer = self.layer.to_sync(sync_client=sync_client)
|
|
315
|
-
return Field(layer=sync_layer, data_type=self.data_type, field_id=self.field_id, data=self.data)
|
geobox/aio/file.py
CHANGED
|
@@ -16,8 +16,6 @@ from ..exception import ApiRequestError
|
|
|
16
16
|
if TYPE_CHECKING:
|
|
17
17
|
from . import AsyncGeoboxClient
|
|
18
18
|
from .user import AsyncUser
|
|
19
|
-
from ..api import GeoboxClient
|
|
20
|
-
from ..file import File
|
|
21
19
|
|
|
22
20
|
|
|
23
21
|
class AsyncFile(AsyncBase):
|
|
@@ -496,27 +494,3 @@ class AsyncFile(AsyncBase):
|
|
|
496
494
|
'limit': limit
|
|
497
495
|
}
|
|
498
496
|
return await super()._get_shared_users(self.endpoint, params)
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
def to_sync(self, sync_client: 'GeoboxClient') -> 'File':
|
|
502
|
-
"""
|
|
503
|
-
Switch to sync version of the file instance to have access to the sync methods
|
|
504
|
-
|
|
505
|
-
Args:
|
|
506
|
-
sync_client (GeoboxClient): The sync version of the GeoboxClient instance for making requests.
|
|
507
|
-
|
|
508
|
-
Returns:
|
|
509
|
-
File: the async instance of the file.
|
|
510
|
-
|
|
511
|
-
Example:
|
|
512
|
-
>>> from geobox import Geoboxclient
|
|
513
|
-
>>> from geobox.aio import AsyncGeoboxClient
|
|
514
|
-
>>> from geobox.aio.file import AsyncFile
|
|
515
|
-
>>> client = GeoboxClient()
|
|
516
|
-
>>> async with AsyncGeoboxClient() as async_client:
|
|
517
|
-
>>> file = await AsyncFile.get_file(async_client, uuid="12345678-1234-5678-1234-567812345678")
|
|
518
|
-
>>> sync_file = file.to_sync(client)
|
|
519
|
-
"""
|
|
520
|
-
from ..file import File
|
|
521
|
-
|
|
522
|
-
return File(api=sync_client, uuid=self.uuid, data=self.data)
|