geobox 2.2.5__py3-none-any.whl → 2.3.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/api.py CHANGED
@@ -35,6 +35,7 @@ from .attachment import Attachment
35
35
  from .apikey import ApiKey
36
36
  from .log import Log
37
37
  from .usage import Usage, UsageScale, UsageParam
38
+ from .table import Table
38
39
 
39
40
  logger = logging.getLogger(__name__)
40
41
 
@@ -109,7 +110,7 @@ class _RequestSession(requests.Session):
109
110
 
110
111
  return original_content_type
111
112
 
112
- def request(self, method: str, url: str, **kwargs) -> requests.Response:
113
+ def request(self, method: str, url: str, verify: bool = True, **kwargs) -> requests.Response:
113
114
  """
114
115
  Override request method with header management.
115
116
 
@@ -136,7 +137,7 @@ class _RequestSession(requests.Session):
136
137
  kwargs['headers'] = request_headers
137
138
 
138
139
  try:
139
- response = super().request(method, url, **kwargs)
140
+ response = super().request(method, url, verify=verify, **kwargs)
140
141
  finally:
141
142
  if original_content_type:
142
143
  self.headers['Content-Type'] = original_content_type
@@ -150,12 +151,14 @@ class GeoboxClient:
150
151
  """
151
152
 
152
153
  def __init__(self,
153
- host: str = 'https://api.geobox.ir',
154
- ver: str = 'v1/',
155
- username: str = None,
156
- password: str = None,
157
- access_token: str = None,
158
- apikey: str = None):
154
+ host: str = 'https://api.geobox.ir',
155
+ ver: str = 'v1/',
156
+ username: str = None,
157
+ password: str = None,
158
+ access_token: str = None,
159
+ apikey: str = None,
160
+ verify: bool = True,
161
+ ):
159
162
  """
160
163
  Constructs all the necessary attributes for the Api object.
161
164
 
@@ -175,6 +178,7 @@ class GeoboxClient:
175
178
  password (str, optional): Password for authentication
176
179
  access_token (str, optional): Bearer token for authentication
177
180
  apikey (str, optional): API key for authentication
181
+ verify (bool, optional): it controls whether to verify the server's TLS certificate. Defaults to True. When set to False, requests will accept any TLS certificate presented by the server, and will ignore hostname mismatches and/or expired certificates, which will make your application vulnerable to man-in-the-middle (MitM) attacks. Setting verify to False may be useful during local development or testing
178
182
 
179
183
  Example:
180
184
  >>> from geobox import GeoboxClient
@@ -188,7 +192,7 @@ class GeoboxClient:
188
192
  self.password = os.getenv('GEOBOX_PASSWORD') if os.getenv('GEOBOX_PASSWORD') else password
189
193
  self.access_token = os.getenv('GEOBOX_ACCESS_TOKEN') if os.getenv('GEOBOX_ACCESS_TOKEN') else access_token
190
194
  self.apikey = os.getenv('GEOBOX_APIKEY') if os.getenv('GEOBOX_APIKEY') else apikey
191
-
195
+ self.verify = verify
192
196
  self.session = _RequestSession(access_token=self.access_token)
193
197
 
194
198
  host = host.lower()
@@ -232,7 +236,7 @@ class GeoboxClient:
232
236
  url = urljoin(self.base_url, "auth/token/")
233
237
  data = {"username": self.username, "password": self.password}
234
238
  try:
235
- response = requests.post(url, data=data)
239
+ response = requests.post(url, data=data, verify=self.verify)
236
240
  response_data = response.json()
237
241
  if response.status_code == 200:
238
242
  return response_data["access_token"]
@@ -328,11 +332,11 @@ class GeoboxClient:
328
332
 
329
333
  try:
330
334
  if files:
331
- response = self.session.request(method, url, data=payload, files=files)
335
+ response = self.session.request(method, url, verify=self.verify, data=payload, files=files)
332
336
  elif is_json:
333
- response = self.session.request(method, url, json=payload)
337
+ response = self.session.request(method, url, verify=self.verify, json=payload)
334
338
  else:
335
- response = self.session.request(method, url, data=payload)
339
+ response = self.session.request(method, url, verify=self.verify, data=payload)
336
340
 
337
341
  except requests.exceptions.Timeout as e:
338
342
  raise ApiRequestError(f"Request timed out: {e}")
@@ -2635,3 +2639,117 @@ class GeoboxClient:
2635
2639
  >>> client.update_usage()
2636
2640
  """
2637
2641
  return Usage.update_usage(self, user_id=user_id)
2642
+
2643
+
2644
+
2645
+ def get_tables(self, **kwargs) -> Union[List['Table'], int]:
2646
+ """
2647
+ Get list of tables with optional filtering and pagination.
2648
+
2649
+ Keyword Args:
2650
+ include_settings (bool): Whether to include table settings. default: False
2651
+ temporary (bool): Whether to return temporary tables. default: False
2652
+ q (str): query filter based on OGC CQL standard. e.g. "field1 LIKE '%GIS%' AND created_at > '2021-01-01'"
2653
+ 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
2654
+ search_fields (str): comma separated list of fields for searching
2655
+ 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.
2656
+ return_count (bool): Whether to return total count. default: False.
2657
+ skip (int): Number of items to skip. default: 0
2658
+ limit (int): Number of items to return. default: 10
2659
+ user_id (int): Specific user. privileges required
2660
+ shared (bool): Whether to return shared tables. default: False
2661
+
2662
+ Returns:
2663
+ List[Table] | int: A list of table instances or the total number of tables.
2664
+
2665
+ Example:
2666
+ >>> from geobox import GeoboxClient
2667
+ >>> client = GeoboxClient()
2668
+ >>> tables = client.get_tables(q="name LIKE '%My table%'")
2669
+ """
2670
+ return Table.get_tables(self, **kwargs)
2671
+
2672
+
2673
+ def create_table(self,
2674
+ name: str,
2675
+ display_name: Optional[str] = None,
2676
+ description: Optional[str] = None,
2677
+ temporary: bool = False,
2678
+ fields: Optional[List[Dict]] = None,
2679
+ ) -> 'Table':
2680
+ """
2681
+ Create a new table.
2682
+
2683
+ Args:
2684
+ name (str): The name of the Table.
2685
+ display_name (str, optional): The display name of the table.
2686
+ description (str, optional): The description of the table.
2687
+ temporary (bool, optional): Whether to create a temporary tables. default: False
2688
+ fields (List[Dict], optional): raw table fields. you can use add_field method for simpler and safer field addition. required dictionary keys: name, datatype
2689
+
2690
+ Returns:
2691
+ Table: The newly created table instance.
2692
+
2693
+ Raises:
2694
+ ValidationError: If the table data is invalid.
2695
+
2696
+ Example:
2697
+ >>> from geobox import GeoboxClient
2698
+ >>> client = GeoboxClient()
2699
+ >>> table = client.create_table(name="my_table")
2700
+ """
2701
+ return Table.create_table(self,
2702
+ name=name,
2703
+ display_name=display_name,
2704
+ description=description,
2705
+ temporary=temporary,
2706
+ fields=fields,
2707
+ )
2708
+
2709
+
2710
+ def get_table(self,
2711
+ uuid: str,
2712
+ user_id: int = None,
2713
+ ) -> 'Table':
2714
+ """
2715
+ Get a table by UUID.
2716
+
2717
+ Args:
2718
+ uuid (str): The UUID of the table to get.
2719
+ user_id (int): Specific user. privileges required.
2720
+
2721
+ Returns:
2722
+ Table: The Table object.
2723
+
2724
+ Raises:
2725
+ NotFoundError: If the table with the specified UUID is not found.
2726
+
2727
+ Example:
2728
+ >>> from geobox import GeoboxClient
2729
+ >>> client = GeoboxClient()
2730
+ >>> table = client.get_table(uuid="12345678-1234-5678-1234-567812345678")
2731
+ """
2732
+ return Table.get_table(self, uuid, user_id)
2733
+
2734
+
2735
+ def get_table_by_name(self,
2736
+ name: str,
2737
+ user_id: int = None,
2738
+ ) -> Union['Table', None]:
2739
+ """
2740
+ Get a table by name
2741
+
2742
+ Args:
2743
+ name (str): the name of the table to get
2744
+ user_id (int, optional): specific user. privileges required.
2745
+
2746
+ Returns:
2747
+ Table | None: returns the table if a table matches the given name, else None
2748
+
2749
+ Example:
2750
+ >>> from geobox import GeoboxClient
2751
+ >>> client = GeoboxClient()
2752
+ >>> table = client.get_table_by_name(name='test')
2753
+
2754
+ """
2755
+ return Table.get_table_by_name(self, name, user_id)
geobox/enums.py CHANGED
@@ -429,4 +429,8 @@ class SpatialPredicate(Enum):
429
429
  EQUAL = 'Equal'
430
430
  OVERLAP = 'Overlap'
431
431
  TOUCH = 'Touch'
432
- WITHIN = 'Within'
432
+ WITHIN = 'Within'
433
+
434
+
435
+ class TableExportFormat(Enum):
436
+ CSV = 'CSV'
geobox/field.py CHANGED
@@ -15,10 +15,11 @@ if TYPE_CHECKING:
15
15
  class Field(Base):
16
16
 
17
17
  def __init__(self,
18
- layer: 'VectorLayer',
19
- data_type: 'FieldType',
20
- field_id: int = None,
21
- data: Optional[Dict] = {}):
18
+ layer: 'VectorLayer',
19
+ data_type: 'FieldType',
20
+ field_id: int = None,
21
+ data: Optional[Dict] = {},
22
+ ):
22
23
  """
23
24
  Constructs all the necessary attributes for the Field object.
24
25
 
@@ -82,7 +83,13 @@ class Field(Base):
82
83
 
83
84
 
84
85
  @classmethod
85
- def create_field(cls, api: 'GeoboxClient', layer: 'VectorLayer', name: str, data_type: 'FieldType', data: Dict = {}) -> 'Field':
86
+ def create_field(cls,
87
+ api: 'GeoboxClient',
88
+ layer: 'VectorLayer',
89
+ name: str,
90
+ data_type: 'FieldType',
91
+ data: Dict = {},
92
+ ) -> 'Field':
86
93
  """
87
94
  Create a new field
88
95
 
@@ -261,7 +268,10 @@ class Field(Base):
261
268
  return self.layer.api.get(endpoint)
262
269
 
263
270
 
264
- def update_domain(self, range_domain: Dict = None, list_domain: Dict = None) -> Dict:
271
+ def update_domain(self,
272
+ range_domain: Dict = None,
273
+ list_domain: Dict = None,
274
+ ) -> Dict:
265
275
  """
266
276
  Update field domian values
267
277
 
@@ -277,9 +287,10 @@ class Field(Base):
277
287
  >>> client = GeoboxClient()
278
288
  >>> field = client.get_vector(uuid="12345678-1234-5678-1234-567812345678").get_fields()[0]
279
289
  >>> range_d = {'min': 1, 'max': 10}
290
+ >>> field.update_domain(range_domain = range_d)
291
+ or
280
292
  >>> list_d = {'1': 'value1', '2': 'value2'}
281
- >>> field.update_domain(range_domain = range_d, list_domain=list_d)
282
- {'min': 1, 'max': 10, 'items: {'1': 'value1', '2': 'value2'}}
293
+ >>> field.update_domain(list_domain=list_d)
283
294
  """
284
295
  if not self.domain:
285
296
  self.domain = {'min': None, 'max': None, 'items': {}}
@@ -291,7 +302,7 @@ class Field(Base):
291
302
  if list_domain:
292
303
  self.domain['items'] = {**self.domain['items'], **list_domain}
293
304
 
294
- self.save()
305
+ self.update(domain=self.domain)
295
306
  return self.domain
296
307
 
297
308
 
@@ -318,4 +329,4 @@ class Field(Base):
318
329
  from .aio.field import AsyncField
319
330
 
320
331
  async_layer = self.layer.to_async(async_client=async_client)
321
- return AsyncField(layer=async_layer, data_type=self.data_type, field_id=self.field_id, data=self.data)
332
+ return AsyncField(layer=async_layer, data_type=self.data_type, field_id=self.field_id, data=self.data)