77sys .path .append (str (Path (__file__ ).resolve ().parents [1 ] / "src" ))
88
99from dataverse_sdk import DataverseClient
10+ from enum import IntEnum
1011from azure .identity import InteractiveBrowserCredential
1112import traceback
1213import requests
@@ -64,6 +65,24 @@ def backoff_retry(op, *, delays=(0, 2, 5, 10, 20), retry_http_statuses=(400, 403
6465 if last_exc :
6566 raise last_exc
6667
68+ # Enum demonstrating local option set creation with multilingual labels (for French labels to work, enable French language in the environment first)
69+ class Status (IntEnum ):
70+ Active = 1
71+ Inactive = 2
72+ Archived = 5
73+ __labels__ = {
74+ 1033 : {
75+ "Active" : "Active" ,
76+ "Inactive" : "Inactive" ,
77+ "Archived" : "Archived" ,
78+ },
79+ 1036 : {
80+ "Active" : "Actif" ,
81+ "Inactive" : "Inactif" ,
82+ "Archived" : "Archivé" ,
83+ }
84+ }
85+
6786print ("Ensure custom table exists (Metadata):" )
6887table_info = None
6988created_this_run = False
@@ -86,7 +105,7 @@ def backoff_retry(op, *, delays=(0, 2, 5, 10, 20), retry_http_statuses=(400, 403
86105else :
87106 # Create it since it doesn't exist
88107 try :
89- log_call ("client.create_table('new_SampleItem', schema={code,count,amount,when,active})" )
108+ log_call ("client.create_table('new_SampleItem', schema={code,count,amount,when,active,status<enum> })" )
90109 table_info = client .create_table (
91110 "new_SampleItem" ,
92111 {
@@ -95,6 +114,7 @@ def backoff_retry(op, *, delays=(0, 2, 5, 10, 20), retry_http_statuses=(400, 403
95114 "amount" : "decimal" ,
96115 "when" : "datetime" ,
97116 "active" : "bool" ,
117+ "status" : Status ,
98118 },
99119 )
100120 created_this_run = True if table_info and table_info .get ("columns_created" ) else False
@@ -130,6 +150,7 @@ def backoff_retry(op, *, delays=(0, 2, 5, 10, 20), retry_http_statuses=(400, 403
130150count_key = f"{ attr_prefix } _count"
131151amount_key = f"{ attr_prefix } _amount"
132152when_key = f"{ attr_prefix } _when"
153+ status_key = f"{ attr_prefix } _status"
133154id_key = f"{ logical } id"
134155
135156def summary_from_record (rec : dict ) -> dict :
@@ -148,6 +169,46 @@ def print_line_summaries(label: str, summaries: list[dict]) -> None:
148169 f"count={ s .get ('count' )} amount={ s .get ('amount' )} when={ s .get ('when' )} "
149170 )
150171
172+ def _resolve_status_value (kind : str , raw_value , use_french : bool ):
173+ """kind values:
174+ - 'label': English label
175+ - 'fr_label': French label if allowed, else fallback to English equivalent
176+ - 'int': the enum integer value
177+ """
178+ if kind == "label" :
179+ return raw_value
180+ if kind == "fr_label" :
181+ if use_french :
182+ return raw_value
183+ return "Active" if raw_value == "Actif" else "Inactive"
184+ return raw_value
185+
186+ def _has_installed_language (base_url : str , credential , lcid : int ) -> bool :
187+ try :
188+ token = credential .get_token (f"{ base_url } /.default" ).token
189+ url = f"{ base_url } /api/data/v9.2/RetrieveAvailableLanguages()"
190+ headers = {"Authorization" : f"Bearer { token } " , "Accept" : "application/json" }
191+ resp = requests .get (url , headers = headers , timeout = 15 )
192+ if not resp .ok :
193+ return False
194+ data = resp .json () if resp .content else {}
195+ langs : list [int ] = []
196+ for val in data .values ():
197+ if isinstance (val , list ) and val and all (isinstance (x , int ) for x in val ):
198+ langs = val
199+ break
200+ print ({"lang_check" : {"endpoint" : url , "status" : resp .status_code , "found" : langs , "using" : lcid in langs }})
201+ return lcid in langs
202+ except Exception :
203+ return False
204+
205+ # if French language (1036) is installed, we use labels in both English and French
206+ use_french_labels = _has_installed_language (base_url , credential , 1036 )
207+ if use_french_labels :
208+ print ({"labels_language" : "fr" , "note" : "French labels in use." })
209+ else :
210+ print ({"labels_language" : "en" , "note" : "Using English (and numeric values)." })
211+
151212# 2) Create a record in the new table
152213print ("Create records (OData) demonstrating single create and bound CreateMultiple (multi):" )
153214
@@ -159,21 +220,42 @@ def print_line_summaries(label: str, summaries: list[dict]) -> None:
159220 amount_key : 123.45 ,
160221 when_key : "2025-01-01" ,
161222 f"{ attr_prefix } _active" : True ,
223+ status_key : ("Actif" if use_french_labels else Status .Active .value ),
162224}
163225# Generate multiple payloads
226+ # Distribution update: roughly one-third English labels, one-third French labels, one-third raw integer values.
227+ # We cycle per record: index % 3 == 1 -> English label, == 2 -> French label (if available, else English), == 0 -> integer value.
164228multi_payloads : list [dict ] = []
165229base_date = date (2025 , 1 , 2 )
230+ # Fixed 6-step cycle pattern encapsulated in helper: Active, Inactive, Actif, Inactif, 1, 2 (repeat)
231+ def _status_value_for_index (idx : int , use_french : bool ):
232+ pattern = [
233+ ("label" , "Active" ),
234+ ("label" , "Inactive" ),
235+ ("fr_label" , "Actif" ),
236+ ("fr_label" , "Inactif" ),
237+ ("int" , Status .Active .value ),
238+ ("int" , Status .Inactive .value ),
239+ ]
240+ kind , raw = pattern [(idx - 1 ) % len (pattern )]
241+ if kind == "label" :
242+ return raw
243+ if kind == "fr_label" :
244+ if use_french :
245+ return raw
246+ return "Active" if raw == "Actif" else "Inactive"
247+ return raw
248+
166249for i in range (1 , 16 ):
167- multi_payloads .append (
168- {
169- f"{ attr_prefix } _name" : f"Sample { i :02d} " ,
170- code_key : f"X{ 200 + i :03d} " ,
171- count_key : 5 * i ,
172- amount_key : round (10.0 * i , 2 ),
173- when_key : (base_date + timedelta (days = i - 1 )).isoformat (),
174- f"{ attr_prefix } _active" : True ,
175- }
176- )
250+ multi_payloads .append ({
251+ f"{ attr_prefix } _name" : f"Sample { i :02d} " ,
252+ code_key : f"X{ 200 + i :03d} " ,
253+ count_key : 5 * i ,
254+ amount_key : round (10.0 * i , 2 ),
255+ when_key : (base_date + timedelta (days = i - 1 )).isoformat (),
256+ f"{ attr_prefix } _active" : True ,
257+ status_key : _status_value_for_index (i , use_french_labels ),
258+ })
177259
178260record_ids : list [str ] = []
179261
@@ -239,11 +321,13 @@ def print_line_summaries(label: str, summaries: list[dict]) -> None:
239321 f"{ attr_prefix } _amount" : 543.21 ,
240322 f"{ attr_prefix } _when" : "2025-02-02" ,
241323 f"{ attr_prefix } _active" : False ,
324+ status_key : ("Inactif" if use_french_labels else Status .Inactive .value ),
242325 }
243326 expected_checks = {
244327 f"{ attr_prefix } _code" : "X002" ,
245328 f"{ attr_prefix } _count" : 99 ,
246329 f"{ attr_prefix } _active" : False ,
330+ status_key : Status .Inactive .value ,
247331 }
248332 amount_key = f"{ attr_prefix } _amount"
249333
@@ -356,7 +440,7 @@ def run_paging_demo(label: str, *, top: Optional[int], page_size: Optional[int])
356440 print ({"paging_demo" : label , "top" : top , "page_size" : page_size })
357441 total = 0
358442 page_index = 0
359- _select = [id_key , code_key , amount_key , when_key ]
443+ _select = [id_key , code_key , amount_key , when_key , status_key ]
360444 _orderby = [f"{ code_key } asc" ]
361445 for page in client .get_multiple (
362446 entity_set ,
@@ -373,7 +457,13 @@ def run_paging_demo(label: str, *, top: Optional[int], page_size: Optional[int])
373457 "page" : page_index ,
374458 "page_size" : len (page ),
375459 "sample" : [
376- {"id" : r .get (id_key ), "code" : r .get (code_key ), "amount" : r .get (amount_key ), "when" : r .get (when_key )}
460+ {
461+ "id" : r .get (id_key ),
462+ "code" : r .get (code_key ),
463+ "amount" : r .get (amount_key ),
464+ "when" : r .get (when_key ),
465+ "status" : r .get (status_key ),
466+ }
377467 for r in page [:5 ]
378468 ],
379469 })
0 commit comments