buildstock-fetch 1.1.0__py3-none-any.whl → 1.2.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.

Potentially problematic release.


This version of buildstock-fetch might be problematic. Click here for more details.

@@ -28,6 +28,9 @@ app = typer.Typer(
28
28
  # File configuration
29
29
  BUILDSTOCK_RELEASES_FILE = str(files("buildstock_fetch").joinpath("data").joinpath("buildstock_releases.json"))
30
30
 
31
+ # File types that haven't been implemented yet
32
+ UNAVAILABLE_FILE_TYPES = ["load_curve_hourly", "load_curve_daily"]
33
+
31
34
 
32
35
  class InvalidProductError(Exception):
33
36
  """Exception raised when an invalid product is provided."""
@@ -222,6 +225,7 @@ def _get_file_type_options_grouped(release_name: str) -> list[dict]:
222
225
  "load_curve_annual",
223
226
  ],
224
227
  "Metadata": ["metadata"],
228
+ "Weather": ["weather"],
225
229
  }
226
230
 
227
231
  choices = []
@@ -431,18 +435,80 @@ def _print_data_processing_info(inputs: Mapping[str, Union[str, list[str]]]) ->
431
435
  print(f"Output directory: {inputs['output_directory']}")
432
436
 
433
437
 
434
- def _check_unavailable_file_types(inputs: Mapping[str, Union[str, list[str]]]) -> None:
435
- """Check and print warning for unavailable file types."""
436
- unavailable_file_types = ["load_curve_hourly", "load_curve_daily"]
437
- selected_file_types = inputs["file_type"].split() if isinstance(inputs["file_type"], str) else inputs["file_type"]
438
- selected_unavailable = [ft for ft in selected_file_types if ft in unavailable_file_types]
439
- if selected_unavailable:
438
+ def _check_weather_map_available_states(inputs: Mapping[str, Union[str, list[str]]]) -> tuple[list[str], list[str]]:
439
+ """Check if the weather map is available for the given release and state."""
440
+ available_states: list[str] = []
441
+ unavailable_states: list[str] = []
442
+ product_short_name = "res" if inputs["product"] == "resstock" else "com"
443
+ release_name = f"{product_short_name}_{inputs['release_year']}_{inputs['weather_file']}_{inputs['release_version']}"
444
+ selected_release = _get_all_available_releases()[release_name]
445
+ if "weather_map_available_states" not in selected_release:
446
+ unavailable_states = inputs["states"] if isinstance(inputs["states"], list) else [inputs["states"]]
447
+ else:
448
+ unavailable_states = [
449
+ state for state in inputs["states"] if state not in selected_release["weather_map_available_states"]
450
+ ]
451
+ available_states = [
452
+ state for state in inputs["states"] if state in selected_release["weather_map_available_states"]
453
+ ]
454
+ return available_states, unavailable_states
455
+
456
+
457
+ def _check_weather_file_availability(
458
+ inputs: Mapping[str, Union[str, list[str]]],
459
+ available_file_types: list[str],
460
+ selected_unavailable_file_types: list[str],
461
+ ) -> None:
462
+ """Check weather file availability and update file type lists."""
463
+ available_states, unavailable_states = _check_weather_map_available_states(inputs)
464
+
465
+ if len(unavailable_states) > 0:
466
+ selected_unavailable_file_types.append("weather")
467
+ if len(unavailable_states) == len(inputs["states"]) and "weather" in available_file_types:
468
+ available_file_types.remove("weather")
469
+
470
+ if len(unavailable_states) > 0:
471
+ console.print(
472
+ f"\n[yellow]The weather map is not available for the following states: {unavailable_states}[/yellow]"
473
+ )
474
+ console.print(
475
+ "\n[yellow]Please first build the weather station mapping for this state using the weather station mapping CLI tool (just build-weather-station-map)[/yellow]"
476
+ )
477
+ for state in unavailable_states:
478
+ selected_unavailable_file_types.append(f"weather: {state}")
479
+
480
+
481
+ def _print_unavailable_file_types_warning(selected_unavailable_file_types: list[str]) -> None:
482
+ """Print warning for unavailable file types."""
483
+ if selected_unavailable_file_types:
440
484
  console.print("\n[yellow]The following file types are not available yet:[/yellow]")
441
- for file_type in selected_unavailable:
485
+ for file_type in selected_unavailable_file_types:
442
486
  console.print(f" • {file_type}")
443
487
  console.print("")
444
488
 
445
489
 
490
+ def _check_unavailable_file_types(inputs: Mapping[str, Union[str, list[str]]]) -> tuple[list[str], list[str]]:
491
+ """Check and print warning for unavailable file types."""
492
+ selected_file_types = inputs["file_type"].split() if isinstance(inputs["file_type"], str) else inputs["file_type"]
493
+ # Create a copy to avoid modifying the original list
494
+ available_file_types = selected_file_types.copy()
495
+ selected_unavailable_file_types = []
496
+
497
+ for ft in selected_file_types:
498
+ if ft in UNAVAILABLE_FILE_TYPES:
499
+ selected_unavailable_file_types.append(ft)
500
+ # Only remove if it exists in available_file_types
501
+ if ft in available_file_types:
502
+ available_file_types.remove(ft)
503
+
504
+ if "weather" in selected_file_types:
505
+ _check_weather_file_availability(inputs, available_file_types, selected_unavailable_file_types)
506
+
507
+ _print_unavailable_file_types_warning(selected_unavailable_file_types)
508
+
509
+ return available_file_types, selected_unavailable_file_types
510
+
511
+
446
512
  def _fetch_all_building_ids(inputs: Mapping[str, Union[str, list[str]]]) -> list:
447
513
  """Fetch building IDs for all states and upgrade IDs."""
448
514
  bldg_ids = []
@@ -643,6 +709,94 @@ UPGRADE_ID_OPTION = typer.Option(
643
709
  OUTPUT_DIRECTORY_OPTION = typer.Option(None, "--output_directory", "-o", help='e.g., "data" or "../output"')
644
710
 
645
711
 
712
+ def _run_interactive_mode_wrapper() -> dict[str, Union[str, list[str]]]:
713
+ """Run interactive mode with error handling."""
714
+ try:
715
+ while True:
716
+ inputs = _run_interactive_mode()
717
+ if _verify_interactive_inputs(inputs):
718
+ return inputs
719
+ console.print("[yellow]Let's try again...[/yellow]")
720
+ except KeyboardInterrupt:
721
+ console.print("\n[red]Operation cancelled by user.[/red]")
722
+ raise typer.Exit(0) from None
723
+
724
+
725
+ def _process_direct_inputs(
726
+ product: str,
727
+ release_year: str,
728
+ weather_file: str,
729
+ release_version: float,
730
+ states: str,
731
+ file_type: str,
732
+ upgrade_id: str,
733
+ output_directory: str,
734
+ ) -> dict[str, Union[str, list[str]]]:
735
+ """Process direct command line inputs."""
736
+ states_list = states.split() if states else []
737
+ upgrade_ids_list = upgrade_id.split() if upgrade_id else ["0"]
738
+ file_type_list = file_type.split() if file_type else []
739
+
740
+ direct_inputs: dict[str, Union[str, list[str]]] = {
741
+ "product": product,
742
+ "release_year": release_year,
743
+ "weather_file": weather_file,
744
+ "release_version": _normalize_release_version(release_version),
745
+ "states": states_list,
746
+ "file_type": file_type_list,
747
+ "upgrade_ids": upgrade_ids_list,
748
+ "output_directory": output_directory,
749
+ }
750
+
751
+ try:
752
+ validation_result = _validate_direct_inputs(direct_inputs)
753
+ if validation_result is not True:
754
+ console.print(f"\n[red]{validation_result}[/red]")
755
+ raise typer.Exit(1) from None
756
+ except InvalidProductError:
757
+ console.print(f"\n[red]Invalid product: {direct_inputs['product']}[/red]")
758
+ raise typer.Exit(1) from None
759
+
760
+ return direct_inputs
761
+
762
+
763
+ def _process_data_download(inputs: dict[str, Union[str, list[str]]]) -> None:
764
+ """Process data download based on available file types."""
765
+ available_file_types, unavailable_file_types = _check_unavailable_file_types(inputs)
766
+ if "weather" in inputs["file_type"]:
767
+ available_weather_states, unavailable_weather_states = _check_weather_map_available_states(inputs)
768
+ else:
769
+ available_weather_states = None
770
+
771
+ if len(available_file_types) > 0:
772
+ # Fetch the building ids and download data
773
+ bldg_ids = _fetch_all_building_ids(inputs)
774
+
775
+ # Ask user about download choice
776
+ selected_bldg_ids = _get_user_download_choice(bldg_ids)
777
+
778
+ if selected_bldg_ids:
779
+ file_type_tuple = (
780
+ tuple(inputs["file_type"].split())
781
+ if isinstance(inputs["file_type"], str)
782
+ else tuple(inputs["file_type"])
783
+ )
784
+ output_dir = inputs["output_directory"]
785
+ if isinstance(output_dir, list):
786
+ output_dir = output_dir[0] if output_dir else "."
787
+
788
+ print(selected_bldg_ids)
789
+ print(available_weather_states)
790
+ print(file_type_tuple)
791
+ fetch_bldg_data(
792
+ selected_bldg_ids, file_type_tuple, Path(output_dir), weather_states=available_weather_states
793
+ )
794
+ else:
795
+ console.print("[yellow]No files selected for download.[/yellow]")
796
+ else:
797
+ console.print("[yellow]None of the selected file types are available for download.[/yellow]")
798
+
799
+
646
800
  def main_callback(
647
801
  product: str = PRODUCT_OPTION,
648
802
  release_year: str = RELEASE_YEAR_OPTION,
@@ -659,61 +813,15 @@ def main_callback(
659
813
 
660
814
  # If no arguments provided, run interactive mode
661
815
  if not any([product, release_year, weather_file, release_version, states, file_type]):
662
- try:
663
- while True:
664
- inputs = _run_interactive_mode()
665
- if _verify_interactive_inputs(inputs):
666
- break
667
- console.print("[yellow]Let's try again...[/yellow]")
668
- except KeyboardInterrupt:
669
- console.print("\n[red]Operation cancelled by user.[/red]")
670
- raise typer.Exit(0) from None
816
+ inputs = _run_interactive_mode_wrapper()
671
817
  else:
672
- states_list = states.split() if states else []
673
- upgrade_ids_list = upgrade_id.split() if upgrade_id else ["0"]
674
- file_type_list = file_type.split() if file_type else []
675
-
676
- direct_inputs: dict[str, Union[str, list[str]]] = {
677
- "product": product,
678
- "release_year": release_year,
679
- "weather_file": weather_file,
680
- "release_version": _normalize_release_version(release_version),
681
- "states": states_list,
682
- "file_type": file_type_list,
683
- "upgrade_ids": upgrade_ids_list,
684
- "output_directory": output_directory,
685
- }
686
- try:
687
- validation_result = _validate_direct_inputs(direct_inputs)
688
- if validation_result is not True:
689
- console.print(f"\n[red]{validation_result}[/red]")
690
- raise typer.Exit(1) from None
691
- except InvalidProductError:
692
- console.print(f"\n[red]Invalid product: {direct_inputs['product']}[/red]")
693
- raise typer.Exit(1) from None
694
-
695
- inputs = direct_inputs
818
+ inputs = _process_direct_inputs(
819
+ product, release_year, weather_file, release_version, states, file_type, upgrade_id, output_directory
820
+ )
696
821
 
697
822
  # Process the data
698
823
  _print_data_processing_info(inputs)
699
- _check_unavailable_file_types(inputs)
700
-
701
- # Fetch the building ids and download data
702
- bldg_ids = _fetch_all_building_ids(inputs)
703
-
704
- # Ask user about download choice
705
- selected_bldg_ids = _get_user_download_choice(bldg_ids)
706
-
707
- if selected_bldg_ids:
708
- file_type_tuple = (
709
- tuple(inputs["file_type"].split()) if isinstance(inputs["file_type"], str) else tuple(inputs["file_type"])
710
- )
711
- output_dir = inputs["output_directory"]
712
- if isinstance(output_dir, list):
713
- output_dir = output_dir[0] if output_dir else "."
714
- fetch_bldg_data(selected_bldg_ids, file_type_tuple, Path(output_dir))
715
- else:
716
- console.print("[yellow]No files selected for download.[/yellow]")
824
+ _process_data_download(inputs)
717
825
 
718
826
 
719
827
  app.command()(main_callback)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: buildstock-fetch
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary: This library simplifies downloading building characteristics and load curve data from NREL's ResStock and ComStock projects.
5
5
  Author-email: Switchbox <hello@switch.box>
6
6
  Project-URL: Homepage, https://switchbox-data.github.io/buildstock-fetch/
@@ -1,8 +1,8 @@
1
1
  buildstock_fetch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  buildstock_fetch/__main__.py,sha256=wEPNJ-s7F6KcRQ_4B5Xh08uqvYZHno5F2R8DU0BMBtk,80
3
- buildstock_fetch/main.py,sha256=r37TmyQo-RPZktnJvWRkpUr2uuuoDynht-wJf_NhrGQ,57071
4
- buildstock_fetch/main_cli.py,sha256=EslGmRfjhj4k7vjtKTrBrlOJDFShma5Ut8hl0q79DKw,27394
5
- buildstock_fetch/data/buildstock_releases.json,sha256=E1Uexf2jcLtrmJ-B9btIBSi0n8biF_O4x7vlLMPRK6E,9648
3
+ buildstock_fetch/main.py,sha256=J3C44xYW1MVe9CAtcJfyNwDeoJJ-XNRFVv7lAcmxH-0,72445
4
+ buildstock_fetch/main_cli.py,sha256=Qg2cXRuzMpMpm-eH567UrEY3HIoLYQtSLRWDYMNr6Y0,31813
5
+ buildstock_fetch/data/buildstock_releases.json,sha256=rHbNkWtTi6VXFim7xtvhwFWQUvtqvcbCfjtvRjkWV-4,10853
6
6
  buildstock_fetch/data/building_data/combined_metadata.parquet/product=comstock/release_year=2021/weather_file=amy2018/release_version=1/state=AK/d1454abff0d94c8090af7b3e923c473b-0.parquet,sha256=nG6H3oGyDzPk1B15YmFd_U81PsA14uABqqwK7P30nKE,7059
7
7
  buildstock_fetch/data/building_data/combined_metadata.parquet/product=comstock/release_year=2021/weather_file=amy2018/release_version=1/state=AK/dcd864cc169b4695be2b9775b1a054ae-0.parquet,sha256=fsREWV9g4fsA3cIWqyPnXVwd7FsJxED2btYpmyOvnbQ,7163
8
8
  buildstock_fetch/data/building_data/combined_metadata.parquet/product=comstock/release_year=2021/weather_file=amy2018/release_version=1/state=AL/d1454abff0d94c8090af7b3e923c473b-0.parquet,sha256=jiTG48ly-LZwfwAL3THdfRzHDG1qEogoxO7P78U4WOU,41201
@@ -1599,10 +1599,10 @@ buildstock_fetch/data/building_data/combined_metadata.parquet/product=resstock/r
1599
1599
  buildstock_fetch/data/building_data/combined_metadata.parquet/product=resstock/release_year=2024/weather_file=tmy3/release_version=2/state=WV/dcd864cc169b4695be2b9775b1a054ae-0.parquet,sha256=-taHsRgrCKXW_7QKoD8QwFBnavXSsSNc6ok3DHqZOXE,42818
1600
1600
  buildstock_fetch/data/building_data/combined_metadata.parquet/product=resstock/release_year=2024/weather_file=tmy3/release_version=2/state=WY/d1454abff0d94c8090af7b3e923c473b-0.parquet,sha256=bWuUnd02XJXYXkHqiXQuIidtm1be5yHmrz1-iFZ14ao,22304
1601
1601
  buildstock_fetch/data/building_data/combined_metadata.parquet/product=resstock/release_year=2024/weather_file=tmy3/release_version=2/state=WY/dcd864cc169b4695be2b9775b1a054ae-0.parquet,sha256=EC1DGLtXqwF1slnnbuTJyQZF0Ox5hoDRDxgaF_SpN8g,21727
1602
- buildstock_fetch/data/weather_station_map/weather_station_map.parquet,sha256=623W-fMLbpgKw5Rg-lM4blfi966f60govY1-IiAFprk,131839
1603
- buildstock_fetch-1.1.0.dist-info/licenses/LICENSE,sha256=TJeh2yvO8__8Rbamd8r48-zvlFCINAsu9nOo5QdMRX8,1066
1604
- buildstock_fetch-1.1.0.dist-info/METADATA,sha256=ZuU3FodFG0610biFzWf3QUml8piQ5lUbTYj2gkkiUZQ,7607
1605
- buildstock_fetch-1.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1606
- buildstock_fetch-1.1.0.dist-info/entry_points.txt,sha256=C7zPk3BSLcI47ymvYKI05nvfRJMEXz4BPIIDKsjePn8,54
1607
- buildstock_fetch-1.1.0.dist-info/top_level.txt,sha256=-PGb2C-Tb3O-wPqUHSOBrvJqRzNHgY_KTbTsXaHIo5M,17
1608
- buildstock_fetch-1.1.0.dist-info/RECORD,,
1602
+ buildstock_fetch/data/weather_station_map/weather_station_map.parquet,sha256=igNrx-UGH20CqPcjANTDrrMyj6Z4_JcXIg2aaCNhFRg,346990
1603
+ buildstock_fetch-1.2.0.dist-info/licenses/LICENSE,sha256=TJeh2yvO8__8Rbamd8r48-zvlFCINAsu9nOo5QdMRX8,1066
1604
+ buildstock_fetch-1.2.0.dist-info/METADATA,sha256=6Px9cA0FJ9O16wBWSUQ9EKEDXNVG3tuMd-uMhaJmOv4,7607
1605
+ buildstock_fetch-1.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1606
+ buildstock_fetch-1.2.0.dist-info/entry_points.txt,sha256=C7zPk3BSLcI47ymvYKI05nvfRJMEXz4BPIIDKsjePn8,54
1607
+ buildstock_fetch-1.2.0.dist-info/top_level.txt,sha256=-PGb2C-Tb3O-wPqUHSOBrvJqRzNHgY_KTbTsXaHIo5M,17
1608
+ buildstock_fetch-1.2.0.dist-info/RECORD,,