surfdataverse 4.0.1__tar.gz → 4.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {surfdataverse-4.0.1 → surfdataverse-4.0.2}/PKG-INFO +1 -1
- {surfdataverse-4.0.1 → surfdataverse-4.0.2}/pyproject.toml +1 -1
- {surfdataverse-4.0.1 → surfdataverse-4.0.2}/src/surfdataverse/core.py +34 -15
- {surfdataverse-4.0.1 → surfdataverse-4.0.2}/README.md +0 -0
- {surfdataverse-4.0.1 → surfdataverse-4.0.2}/src/surfdataverse/__init__.py +0 -0
- {surfdataverse-4.0.1 → surfdataverse-4.0.2}/src/surfdataverse/container.py +0 -0
- {surfdataverse-4.0.1 → surfdataverse-4.0.2}/src/surfdataverse/exceptions.py +0 -0
|
@@ -7,7 +7,7 @@ from decimal import Decimal
|
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from typing import Optional
|
|
9
9
|
|
|
10
|
-
import msal
|
|
10
|
+
import msal # type: ignore
|
|
11
11
|
import pandas as pd
|
|
12
12
|
import requests
|
|
13
13
|
|
|
@@ -205,13 +205,13 @@ class DataverseBase:
|
|
|
205
205
|
self.name = table_logical_name.title().replace("_", " ")
|
|
206
206
|
|
|
207
207
|
# Stored values for this session
|
|
208
|
-
self._guid_mapping = {}
|
|
209
|
-
self._all_relationships = {} # Populated by first call
|
|
210
|
-
self._global_choices = {} # Populated by first call
|
|
208
|
+
self._guid_mapping: dict[str, dict] = {}
|
|
209
|
+
self._all_relationships: dict = {} # Populated by first call
|
|
210
|
+
self._global_choices: dict = {} # Populated by first call
|
|
211
211
|
|
|
212
|
-
self._table_metadata = {}
|
|
213
|
-
self._table_definitions = {}
|
|
214
|
-
self._table_relationships = {}
|
|
212
|
+
self._table_metadata: dict = {}
|
|
213
|
+
self._table_definitions: dict = {}
|
|
214
|
+
self._table_relationships: dict = {}
|
|
215
215
|
|
|
216
216
|
# === RELATIONSHIPS
|
|
217
217
|
@property
|
|
@@ -361,7 +361,7 @@ class DataverseBase:
|
|
|
361
361
|
raise DataverseAPIError(error_msg, response.status_code, response.text)
|
|
362
362
|
|
|
363
363
|
# === HELPER METHODS
|
|
364
|
-
def name_to_guid(self, table_name, name=
|
|
364
|
+
def name_to_guid(self, table_name, name: str="", name_column=None) -> str | None:
|
|
365
365
|
"""
|
|
366
366
|
Fetches a mapping of unique names to GUIDs in a Dataverse table
|
|
367
367
|
|
|
@@ -700,14 +700,25 @@ class DataverseEntity(DataverseBase):
|
|
|
700
700
|
field_type = metadata[column].get("AttributeType")
|
|
701
701
|
|
|
702
702
|
# File columns (check first since they can have special handling)
|
|
703
|
-
if field_type
|
|
703
|
+
if field_type in ["File", "Image", "Virtual"]:
|
|
704
704
|
self.set_file(column, value)
|
|
705
|
-
|
|
706
|
-
elif
|
|
705
|
+
|
|
706
|
+
elif field_type == "Lookup":
|
|
707
|
+
if column not in self.get_table_relationships():
|
|
708
|
+
raise EntityError(
|
|
709
|
+
f"Crosscheck: Column {column} is not a valid lookup for this entity despite "
|
|
710
|
+
f"being lookup"
|
|
711
|
+
)
|
|
707
712
|
self.set_lookup(column, value)
|
|
708
|
-
|
|
709
|
-
elif
|
|
713
|
+
|
|
714
|
+
elif field_type == "Picklist":
|
|
715
|
+
if column not in self.global_choices:
|
|
716
|
+
raise EntityError(
|
|
717
|
+
f"Crosscheck: Column {column} is not a valid choice for this entity despite "
|
|
718
|
+
f"being picklist"
|
|
719
|
+
)
|
|
710
720
|
self.set_choice(column, value)
|
|
721
|
+
|
|
711
722
|
# Regular data columns (including DateTime, String, Integer, Decimal, etc.)
|
|
712
723
|
else:
|
|
713
724
|
self.set_data(column, value)
|
|
@@ -841,7 +852,10 @@ class DataverseEntity(DataverseBase):
|
|
|
841
852
|
target_entity_set_name = self.get_table_entity_set_name(logical_name=target_entity)
|
|
842
853
|
|
|
843
854
|
if not is_valid_guid(value):
|
|
844
|
-
|
|
855
|
+
guid_result = self.name_to_guid(target_entity, value)
|
|
856
|
+
if guid_result is None:
|
|
857
|
+
raise EntityError(f"Could not find GUID for lookup value '{value}'")
|
|
858
|
+
value = guid_result
|
|
845
859
|
|
|
846
860
|
self.data[f"{lookup_column_schema_name}@odata.bind"] = f"/{target_entity_set_name}({value})"
|
|
847
861
|
|
|
@@ -938,9 +952,14 @@ class DataverseEntity(DataverseBase):
|
|
|
938
952
|
filename = f"{column}_data.json"
|
|
939
953
|
# logger.info(f"Uploading JSON content as file: {filename} of type {type(json_content)}")
|
|
940
954
|
return self.upload_file(column, file_content, filename)
|
|
955
|
+
elif isinstance(value, bytes):
|
|
956
|
+
# Raw bytes data - upload directly
|
|
957
|
+
file_content = io.BytesIO(value)
|
|
958
|
+
filename = f"{column}_data.bin" # Generic binary file extension
|
|
959
|
+
return self.upload_file(column, file_content, filename)
|
|
941
960
|
else:
|
|
942
961
|
raise ValueError(
|
|
943
|
-
f"Unsupported file value type: {type(value)}. Expected dict or
|
|
962
|
+
f"Unsupported file value type: {type(value)}. Expected dict, list, or bytes for file data."
|
|
944
963
|
)
|
|
945
964
|
|
|
946
965
|
def get_file_url(self, column):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|