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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: surfdataverse
3
- Version: 4.0.1
3
+ Version: 4.0.2
4
4
  Summary: A Python package for ionysis Microsoft Dataverse integration
5
5
  Keywords: dataverse,microsoft,crm,api
6
6
  Author: ionysis
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "surfdataverse"
7
- version = "4.0.1"
7
+ version = "4.0.2"
8
8
  description = "A Python package for ionysis Microsoft Dataverse integration"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -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=None, name_column=None) -> uuid.UUID | None:
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 == "File" or (field_type == "Virtual" and "json" in column.lower()):
703
+ if field_type in ["File", "Image", "Virtual"]:
704
704
  self.set_file(column, value)
705
- # Lookup columns
706
- elif column in self.get_table_relationships():
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
- # Choice columns (picklist/option sets)
709
- elif column in self.global_choices:
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
- value = self.name_to_guid(target_entity, value)
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 list for JSON data."
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