@@ -105,7 +105,13 @@ def __init__(
105105 scenario : Optional [Scenario ] = None ,
106106 situation : Optional [Dict ] = None ,
107107 dataset : Optional [
108- Union [pd .DataFrame , str , UKSingleYearDataset , UKMultiYearDataset ]
108+ Union [
109+ pd .DataFrame ,
110+ str ,
111+ os .PathLike ,
112+ UKSingleYearDataset ,
113+ UKMultiYearDataset ,
114+ ]
109115 ] = None ,
110116 trace : bool = False ,
111117 reform : Union [Dict , Type [Reform ]] = None ,
@@ -148,8 +154,8 @@ def __init__(
148154 # Build simulation from appropriate source
149155 if situation is not None :
150156 self .build_from_situation (situation )
151- elif isinstance (dataset , str ):
152- self .build_from_url (dataset )
157+ elif isinstance (dataset , ( str , os . PathLike ) ):
158+ self .build_from_dataset_source (dataset )
153159 elif isinstance (dataset , pd .DataFrame ):
154160 self .build_from_dataframe (dataset )
155161 elif isinstance (dataset , Dataset ):
@@ -159,7 +165,7 @@ def __init__(
159165 elif isinstance (dataset , UKMultiYearDataset ):
160166 self .build_from_multi_year_dataset (dataset )
161167 elif dataset is None :
162- self .build_from_url (get_default_dataset_url ())
168+ self .build_from_dataset_source (get_default_dataset_url ())
163169 else :
164170 raise ValueError (f"Unsupported dataset type: { dataset .__class__ } " )
165171
@@ -260,6 +266,52 @@ def build_from_situation(self, situation: Dict) -> None:
260266 self , fiscal_year = self .default_input_period
261267 )
262268
269+ def build_from_dataset_source (
270+ self , dataset_source : Union [str , os .PathLike ]
271+ ) -> None :
272+ """Build simulation from a supported dataset source string."""
273+ dataset_source = os .fspath (dataset_source )
274+ if dataset_source .startswith ("hf://" ):
275+ self .build_from_url (dataset_source )
276+ return
277+ if "://" in dataset_source :
278+ raise ValueError (
279+ "Only HuggingFace dataset URLs are supported directly by "
280+ "policyengine-uk. Download or materialize other dataset "
281+ "sources to a local file path before passing them to Simulation."
282+ )
283+ self .build_from_file (dataset_source )
284+
285+ def build_from_file (
286+ self ,
287+ dataset_file : Union [str , os .PathLike ],
288+ * ,
289+ cache_key : Optional [str ] = None ,
290+ ) -> None :
291+ """Build simulation from a local dataset file path."""
292+ dataset_file = os .fspath (dataset_file )
293+
294+ if UKMultiYearDataset .validate_file_path (dataset_file , False ):
295+ multi_year_dataset = UKMultiYearDataset (dataset_file )
296+ elif UKSingleYearDataset .validate_file_path (dataset_file , False ):
297+ multi_year_dataset = extend_single_year_dataset (
298+ UKSingleYearDataset (dataset_file ),
299+ self .tax_benefit_system .parameters ,
300+ )
301+ else :
302+ dataset = Dataset .from_file (dataset_file , self .default_input_period )
303+ self .build_from_dataset (dataset )
304+ return
305+
306+ # Pre-encode string enum columns to int16 once before caching so
307+ # subsequent loads skip the expensive astype(str) + searchsorted path.
308+ _pre_encode_enum_columns (multi_year_dataset , self .tax_benefit_system )
309+ if cache_key is not None :
310+ _url_dataset_cache [cache_key ] = multi_year_dataset
311+
312+ self .build_from_multi_year_dataset (multi_year_dataset )
313+ self .dataset = multi_year_dataset
314+
263315 def build_from_url (self , url : str ) -> None :
264316 """Build simulation from a HuggingFace dataset URL.
265317
@@ -269,7 +321,7 @@ def build_from_url(self, url: str) -> None:
269321 Raises:
270322 ValueError: If URL is not a HuggingFace URL
271323 """
272- if "hf://" not in url :
324+ if not url . startswith ( "hf://" ) :
273325 raise ValueError (f"Non-HuggingFace URLs are currently not supported." )
274326
275327 # Return early from in-memory cache if available: skips HDF5 reading,
@@ -295,26 +347,7 @@ def build_from_url(self, url: str) -> None:
295347 version = version ,
296348 )
297349
298- # Determine dataset type and build accordingly
299- if UKMultiYearDataset .validate_file_path (dataset_file , False ):
300- multi_year_dataset = UKMultiYearDataset (dataset_file )
301- elif UKSingleYearDataset .validate_file_path (dataset_file , False ):
302- multi_year_dataset = extend_single_year_dataset (
303- UKSingleYearDataset (dataset_file ),
304- self .tax_benefit_system .parameters ,
305- )
306- else :
307- dataset = Dataset .from_file (dataset_file , self .default_input_period )
308- self .build_from_dataset (dataset )
309- return
310-
311- # Pre-encode string enum columns to int16 once before caching so
312- # subsequent loads skip the expensive astype(str) + searchsorted path.
313- _pre_encode_enum_columns (multi_year_dataset , self .tax_benefit_system )
314- _url_dataset_cache [url ] = multi_year_dataset
315-
316- self .build_from_multi_year_dataset (multi_year_dataset )
317- self .dataset = multi_year_dataset
350+ self .build_from_file (dataset_file , cache_key = url )
318351
319352 def build_from_dataframe (self , df : pd .DataFrame ) -> None :
320353 """Build simulation from a pandas DataFrame.
0 commit comments