EPA-PM-API-Wrapper 0.3.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.
Files changed (654) hide show
  1. epa_pm_api_wrapper/__init__.py +30 -0
  2. epa_pm_api_wrapper/__main__.py +4 -0
  3. epa_pm_api_wrapper/cli.py +413 -0
  4. epa_pm_api_wrapper/client.py +507 -0
  5. epa_pm_api_wrapper/exceptions.py +67 -0
  6. epa_pm_api_wrapper/models/__init__.py +1451 -0
  7. epa_pm_api_wrapper/models/accept_reject_type.py +12 -0
  8. epa_pm_api_wrapper/models/account.py +15 -0
  9. epa_pm_api_wrapper/models/account_info.py +58 -0
  10. epa_pm_api_wrapper/models/account_type.py +122 -0
  11. epa_pm_api_wrapper/models/account_type_language_preference.py +9 -0
  12. epa_pm_api_wrapper/models/additional_identifier.py +58 -0
  13. epa_pm_api_wrapper/models/additional_identifier_type.py +60 -0
  14. epa_pm_api_wrapper/models/additional_identifier_type_group.py +10 -0
  15. epa_pm_api_wrapper/models/additional_identifier_types.py +19 -0
  16. epa_pm_api_wrapper/models/additional_identifiers.py +19 -0
  17. epa_pm_api_wrapper/models/address_type.py +84 -0
  18. epa_pm_api_wrapper/models/address_type_state.py +159 -0
  19. epa_pm_api_wrapper/models/adult_education.py +17 -0
  20. epa_pm_api_wrapper/models/agency_type.py +41 -0
  21. epa_pm_api_wrapper/models/agency_type_country.py +242 -0
  22. epa_pm_api_wrapper/models/alerts.py +16 -0
  23. epa_pm_api_wrapper/models/alerts_type.py +47 -0
  24. epa_pm_api_wrapper/models/alerts_type_alert.py +29 -0
  25. epa_pm_api_wrapper/models/all_energy_meters_type.py +32 -0
  26. epa_pm_api_wrapper/models/all_meter_types.py +130 -0
  27. epa_pm_api_wrapper/models/ambulatory_surgical_center.py +16 -0
  28. epa_pm_api_wrapper/models/amount_of_laundry_processed_annually.py +17 -0
  29. epa_pm_api_wrapper/models/amount_of_laundry_processed_annually_type.py +28 -0
  30. epa_pm_api_wrapper/models/amount_of_laundry_processed_annually_units_type.py +9 -0
  31. epa_pm_api_wrapper/models/annual_research_expenditure.py +16 -0
  32. epa_pm_api_wrapper/models/annual_research_expenditure_type.py +22 -0
  33. epa_pm_api_wrapper/models/annual_research_expenditure_type_value.py +10 -0
  34. epa_pm_api_wrapper/models/aquarium.py +17 -0
  35. epa_pm_api_wrapper/models/area_of_all_walk_in_refrigeration_units.py +19 -0
  36. epa_pm_api_wrapper/models/average_effluent_biological_oxygen_demand.py +16 -0
  37. epa_pm_api_wrapper/models/average_influent_biological_oxygen_demand.py +16 -0
  38. epa_pm_api_wrapper/models/average_number_of_residents.py +15 -0
  39. epa_pm_api_wrapper/models/average_number_of_vehicles_in_inventory.py +16 -0
  40. epa_pm_api_wrapper/models/bank_branch.py +16 -0
  41. epa_pm_api_wrapper/models/bank_branch_type.py +35 -0
  42. epa_pm_api_wrapper/models/bank_branch_type_use_details.py +58 -0
  43. epa_pm_api_wrapper/models/bar_nightclub.py +17 -0
  44. epa_pm_api_wrapper/models/barracks.py +17 -0
  45. epa_pm_api_wrapper/models/barracks_type.py +35 -0
  46. epa_pm_api_wrapper/models/barracks_type_use_details.py +58 -0
  47. epa_pm_api_wrapper/models/baseline_and_target.py +16 -0
  48. epa_pm_api_wrapper/models/baseline_and_target_type.py +27 -0
  49. epa_pm_api_wrapper/models/baseline_type.py +41 -0
  50. epa_pm_api_wrapper/models/billboard_metric_setting.py +21 -0
  51. epa_pm_api_wrapper/models/billboard_metric_type.py +33 -0
  52. epa_pm_api_wrapper/models/billboard_metrics.py +11 -0
  53. epa_pm_api_wrapper/models/billboard_metrics_type.py +26 -0
  54. epa_pm_api_wrapper/models/bowling_alley.py +40 -0
  55. epa_pm_api_wrapper/models/bowling_alley_use_details.py +58 -0
  56. epa_pm_api_wrapper/models/building.py +11 -0
  57. epa_pm_api_wrapper/models/casino.py +16 -0
  58. epa_pm_api_wrapper/models/category_type.py +17 -0
  59. epa_pm_api_wrapper/models/cegep.py +15 -0
  60. epa_pm_api_wrapper/models/cegep_type.py +35 -0
  61. epa_pm_api_wrapper/models/cegep_type_use_details.py +131 -0
  62. epa_pm_api_wrapper/models/ceiling_height.py +15 -0
  63. epa_pm_api_wrapper/models/ceiling_height_units_type.py +27 -0
  64. epa_pm_api_wrapper/models/clear_height.py +16 -0
  65. epa_pm_api_wrapper/models/clear_height_units_type.py +26 -0
  66. epa_pm_api_wrapper/models/college_university.py +15 -0
  67. epa_pm_api_wrapper/models/college_university_type.py +37 -0
  68. epa_pm_api_wrapper/models/college_university_type_use_details.py +131 -0
  69. epa_pm_api_wrapper/models/common_entrance.py +16 -0
  70. epa_pm_api_wrapper/models/community_center_and_social_meeting_hall.py +46 -0
  71. epa_pm_api_wrapper/models/community_center_and_social_meeting_hall_use_details.py +58 -0
  72. epa_pm_api_wrapper/models/completely_enclosed_footage.py +15 -0
  73. epa_pm_api_wrapper/models/construction_status_type.py +9 -0
  74. epa_pm_api_wrapper/models/contact_type.py +70 -0
  75. epa_pm_api_wrapper/models/convenience_store_with_gas_station.py +19 -0
  76. epa_pm_api_wrapper/models/convenience_store_with_gas_station_type.py +37 -0
  77. epa_pm_api_wrapper/models/convenience_store_with_gas_station_type_use_details.py +140 -0
  78. epa_pm_api_wrapper/models/convenience_store_without_gas_station.py +19 -0
  79. epa_pm_api_wrapper/models/convenience_store_without_gas_station_type.py +37 -0
  80. epa_pm_api_wrapper/models/convenience_store_without_gas_station_type_use_details.py +140 -0
  81. epa_pm_api_wrapper/models/convention_center.py +16 -0
  82. epa_pm_api_wrapper/models/cooking_facilities.py +15 -0
  83. epa_pm_api_wrapper/models/cooking_located_onsite.py +16 -0
  84. epa_pm_api_wrapper/models/cooling_equipment_redundancy.py +15 -0
  85. epa_pm_api_wrapper/models/cooling_equipment_redundancy_type.py +22 -0
  86. epa_pm_api_wrapper/models/cooling_equipment_redundancy_type_value.py +12 -0
  87. epa_pm_api_wrapper/models/country_code.py +16 -0
  88. epa_pm_api_wrapper/models/country_list.py +493 -0
  89. epa_pm_api_wrapper/models/courthouse.py +16 -0
  90. epa_pm_api_wrapper/models/courthouse_type.py +35 -0
  91. epa_pm_api_wrapper/models/courthouse_type_use_details.py +58 -0
  92. epa_pm_api_wrapper/models/custom_field.py +109 -0
  93. epa_pm_api_wrapper/models/custom_field_list.py +20 -0
  94. epa_pm_api_wrapper/models/custom_field_list_custom_field.py +17 -0
  95. epa_pm_api_wrapper/models/custom_field_valid_characters.py +15 -0
  96. epa_pm_api_wrapper/models/custom_field_when_to_prompt.py +15 -0
  97. epa_pm_api_wrapper/models/custom_metric.py +49 -0
  98. epa_pm_api_wrapper/models/custom_units_type.py +19 -0
  99. epa_pm_api_wrapper/models/custom_use.py +15 -0
  100. epa_pm_api_wrapper/models/custom_use_detail1.py +15 -0
  101. epa_pm_api_wrapper/models/custom_use_detail2.py +15 -0
  102. epa_pm_api_wrapper/models/custom_use_details_type.py +50 -0
  103. epa_pm_api_wrapper/models/custom_use_details_type_data_type.py +8 -0
  104. epa_pm_api_wrapper/models/custom_use_type.py +35 -0
  105. epa_pm_api_wrapper/models/custom_use_type_use_details.py +27 -0
  106. epa_pm_api_wrapper/models/customer.py +77 -0
  107. epa_pm_api_wrapper/models/customer_language_preference.py +9 -0
  108. epa_pm_api_wrapper/models/data_center.py +17 -0
  109. epa_pm_api_wrapper/models/data_center_type.py +35 -0
  110. epa_pm_api_wrapper/models/data_center_type_use_details.py +50 -0
  111. epa_pm_api_wrapper/models/data_exchange_settings.py +37 -0
  112. epa_pm_api_wrapper/models/data_exchange_settings_supported_meter_types.py +20 -0
  113. epa_pm_api_wrapper/models/data_exchange_settings_terms_of_use.py +40 -0
  114. epa_pm_api_wrapper/models/data_request.py +88 -0
  115. epa_pm_api_wrapper/models/data_request_locations.py +19 -0
  116. epa_pm_api_wrapper/models/data_request_locations_location.py +22 -0
  117. epa_pm_api_wrapper/models/data_request_requester_details.py +32 -0
  118. epa_pm_api_wrapper/models/data_request_status_type.py +13 -0
  119. epa_pm_api_wrapper/models/data_response.py +47 -0
  120. epa_pm_api_wrapper/models/data_response_properties.py +20 -0
  121. epa_pm_api_wrapper/models/data_type.py +9 -0
  122. epa_pm_api_wrapper/models/delivery_facility.py +16 -0
  123. epa_pm_api_wrapper/models/demand_tracking_type.py +35 -0
  124. epa_pm_api_wrapper/models/design.py +15 -0
  125. epa_pm_api_wrapper/models/design_base_type.py +83 -0
  126. epa_pm_api_wrapper/models/design_base_type_estimated_energy_list.py +17 -0
  127. epa_pm_api_wrapper/models/design_base_type_property_uses.py +709 -0
  128. epa_pm_api_wrapper/models/design_base_type_target.py +34 -0
  129. epa_pm_api_wrapper/models/design_unit_of_measure.py +37 -0
  130. epa_pm_api_wrapper/models/detail_type.py +22 -0
  131. epa_pm_api_wrapper/models/details_types.py +20 -0
  132. epa_pm_api_wrapper/models/disposal_destination_type.py +60 -0
  133. epa_pm_api_wrapper/models/distribution_center.py +17 -0
  134. epa_pm_api_wrapper/models/distribution_center_type.py +37 -0
  135. epa_pm_api_wrapper/models/distribution_center_type_use_details.py +76 -0
  136. epa_pm_api_wrapper/models/drinking_water_treatment_and_distribution.py +18 -0
  137. epa_pm_api_wrapper/models/drinking_water_treatment_and_distribution_type.py +37 -0
  138. epa_pm_api_wrapper/models/drinking_water_treatment_and_distribution_type_use_details.py +18 -0
  139. epa_pm_api_wrapper/models/e_grid_subregion.py +38 -0
  140. epa_pm_api_wrapper/models/e_grid_subregion_country.py +242 -0
  141. epa_pm_api_wrapper/models/e_grid_subregion_list.py +19 -0
  142. epa_pm_api_wrapper/models/edu.py +64 -0
  143. epa_pm_api_wrapper/models/edu_list.py +18 -0
  144. epa_pm_api_wrapper/models/electric_vehicle_charging_station.py +15 -0
  145. epa_pm_api_wrapper/models/empty_string.py +7 -0
  146. epa_pm_api_wrapper/models/empty_type.py +7 -0
  147. epa_pm_api_wrapper/models/enclosed_floor_area.py +15 -0
  148. epa_pm_api_wrapper/models/enclosed_mall.py +16 -0
  149. epa_pm_api_wrapper/models/energy_meter_assoc_and_config_type.py +25 -0
  150. epa_pm_api_wrapper/models/energy_performance_project.py +11 -0
  151. epa_pm_api_wrapper/models/energy_performance_project_type.py +136 -0
  152. epa_pm_api_wrapper/models/energy_power_station.py +20 -0
  153. epa_pm_api_wrapper/models/energy_uom_type.py +11 -0
  154. epa_pm_api_wrapper/models/enrollment.py +11 -0
  155. epa_pm_api_wrapper/models/error_type.py +29 -0
  156. epa_pm_api_wrapper/models/errors_type.py +25 -0
  157. epa_pm_api_wrapper/models/estimated_energy_list_type.py +19 -0
  158. epa_pm_api_wrapper/models/estimated_energy_type.py +58 -0
  159. epa_pm_api_wrapper/models/estimates_applied.py +15 -0
  160. epa_pm_api_wrapper/models/ev_charging_station_type.py +37 -0
  161. epa_pm_api_wrapper/models/ev_charging_station_type_use_details.py +41 -0
  162. epa_pm_api_wrapper/models/evaluation_period_type.py +35 -0
  163. epa_pm_api_wrapper/models/exterior_entrance_to_the_public.py +15 -0
  164. epa_pm_api_wrapper/models/fast_food_restaurant.py +17 -0
  165. epa_pm_api_wrapper/models/fast_food_restaurant_type.py +37 -0
  166. epa_pm_api_wrapper/models/fast_food_restaurant_type_use_details.py +84 -0
  167. epa_pm_api_wrapper/models/federal_agencies.py +19 -0
  168. epa_pm_api_wrapper/models/financial_office.py +16 -0
  169. epa_pm_api_wrapper/models/financial_office_type.py +35 -0
  170. epa_pm_api_wrapper/models/financial_office_type_use_details.py +58 -0
  171. epa_pm_api_wrapper/models/fire_station.py +16 -0
  172. epa_pm_api_wrapper/models/fire_station_type.py +35 -0
  173. epa_pm_api_wrapper/models/fire_station_type_use_details.py +92 -0
  174. epa_pm_api_wrapper/models/fitness_center_health_club_gym.py +42 -0
  175. epa_pm_api_wrapper/models/fitness_center_health_club_gym_use_details.py +58 -0
  176. epa_pm_api_wrapper/models/fixed_film_trickle_filtration_process.py +15 -0
  177. epa_pm_api_wrapper/models/floor_area_type_base.py +23 -0
  178. epa_pm_api_wrapper/models/food_sales.py +17 -0
  179. epa_pm_api_wrapper/models/food_sales_type.py +35 -0
  180. epa_pm_api_wrapper/models/food_sales_type_use_details.py +114 -0
  181. epa_pm_api_wrapper/models/food_service.py +17 -0
  182. epa_pm_api_wrapper/models/full_service_spa_floor_area.py +15 -0
  183. epa_pm_api_wrapper/models/generation_location_type.py +41 -0
  184. epa_pm_api_wrapper/models/government_subsidized_housing.py +16 -0
  185. epa_pm_api_wrapper/models/grant_dollars.py +11 -0
  186. epa_pm_api_wrapper/models/green_power_fuel_source_enum.py +13 -0
  187. epa_pm_api_wrapper/models/green_power_type_enum.py +15 -0
  188. epa_pm_api_wrapper/models/gross_floor_area_hotel_conference_space.py +18 -0
  189. epa_pm_api_wrapper/models/gross_floor_area_that_is_exhibit_space.py +19 -0
  190. epa_pm_api_wrapper/models/gross_floor_area_type.py +24 -0
  191. epa_pm_api_wrapper/models/gross_floor_area_units_type.py +8 -0
  192. epa_pm_api_wrapper/models/gross_floor_area_used_for_food_preparation.py +19 -0
  193. epa_pm_api_wrapper/models/gym_center_floor_area.py +15 -0
  194. epa_pm_api_wrapper/models/gymnasium_floor_area.py +15 -0
  195. epa_pm_api_wrapper/models/has_computer_lab.py +15 -0
  196. epa_pm_api_wrapper/models/has_dining_hall.py +15 -0
  197. epa_pm_api_wrapper/models/has_laboratory.py +15 -0
  198. epa_pm_api_wrapper/models/hey.py +11 -0
  199. epa_pm_api_wrapper/models/hey_type.py +29 -0
  200. epa_pm_api_wrapper/models/hey_type_meter.py +35 -0
  201. epa_pm_api_wrapper/models/hey_type_meter_meter_data.py +22 -0
  202. epa_pm_api_wrapper/models/hey_type_property_info.py +35 -0
  203. epa_pm_api_wrapper/models/hierarchy.py +16 -0
  204. epa_pm_api_wrapper/models/hierarchy_type.py +84 -0
  205. epa_pm_api_wrapper/models/highest_award_level.py +17 -0
  206. epa_pm_api_wrapper/models/highest_award_level_type.py +20 -0
  207. epa_pm_api_wrapper/models/highest_award_level_type_value.py +11 -0
  208. epa_pm_api_wrapper/models/hospital.py +22 -0
  209. epa_pm_api_wrapper/models/hospital_type.py +35 -0
  210. epa_pm_api_wrapper/models/hospital_type_use_details.py +132 -0
  211. epa_pm_api_wrapper/models/hotel.py +17 -0
  212. epa_pm_api_wrapper/models/hotel_type.py +41 -0
  213. epa_pm_api_wrapper/models/hotel_type_use_details.py +140 -0
  214. epa_pm_api_wrapper/models/hours_per_day_guests_onsite.py +16 -0
  215. epa_pm_api_wrapper/models/hours_per_day_guests_onsite_type.py +22 -0
  216. epa_pm_api_wrapper/models/hours_per_day_guests_onsite_type_value.py +9 -0
  217. epa_pm_api_wrapper/models/ice_curling_rink.py +27 -0
  218. epa_pm_api_wrapper/models/ice_curling_rink_type.py +35 -0
  219. epa_pm_api_wrapper/models/ice_curling_rink_type_use_details.py +78 -0
  220. epa_pm_api_wrapper/models/ice_events.py +15 -0
  221. epa_pm_api_wrapper/models/individual_meter.py +86 -0
  222. epa_pm_api_wrapper/models/indoor_arena.py +17 -0
  223. epa_pm_api_wrapper/models/indoor_arena_type.py +35 -0
  224. epa_pm_api_wrapper/models/indoor_arena_type_use_details.py +104 -0
  225. epa_pm_api_wrapper/models/international_weather_station_list.py +26 -0
  226. epa_pm_api_wrapper/models/irrigation_area_type.py +28 -0
  227. epa_pm_api_wrapper/models/irrigation_area_type_base.py +30 -0
  228. epa_pm_api_wrapper/models/irrigation_area_units_type.py +10 -0
  229. epa_pm_api_wrapper/models/is_high_school.py +16 -0
  230. epa_pm_api_wrapper/models/is_tertiary_care.py +17 -0
  231. epa_pm_api_wrapper/models/it_energy_configuration_type.py +20 -0
  232. epa_pm_api_wrapper/models/it_energy_configuration_type_value.py +14 -0
  233. epa_pm_api_wrapper/models/it_energy_meter_configuration.py +16 -0
  234. epa_pm_api_wrapper/models/k12_school.py +16 -0
  235. epa_pm_api_wrapper/models/k12_school_type.py +35 -0
  236. epa_pm_api_wrapper/models/k12_school_type_use_details.py +126 -0
  237. epa_pm_api_wrapper/models/laboratory.py +17 -0
  238. epa_pm_api_wrapper/models/laundry_facility.py +16 -0
  239. epa_pm_api_wrapper/models/length_of_all_commercial_kitchen_hoods.py +19 -0
  240. epa_pm_api_wrapper/models/length_of_all_open_closed_refrigeration_units.py +21 -0
  241. epa_pm_api_wrapper/models/length_of_use_detail_type.py +26 -0
  242. epa_pm_api_wrapper/models/length_units_type.py +8 -0
  243. epa_pm_api_wrapper/models/library.py +17 -0
  244. epa_pm_api_wrapper/models/library_type.py +35 -0
  245. epa_pm_api_wrapper/models/library_type_use_details.py +58 -0
  246. epa_pm_api_wrapper/models/license.py +60 -0
  247. epa_pm_api_wrapper/models/license_list.py +19 -0
  248. epa_pm_api_wrapper/models/licensed_bed_capacity.py +19 -0
  249. epa_pm_api_wrapper/models/lifestyle_center.py +18 -0
  250. epa_pm_api_wrapper/models/link_type.py +52 -0
  251. epa_pm_api_wrapper/models/links_type.py +19 -0
  252. epa_pm_api_wrapper/models/log.py +11 -0
  253. epa_pm_api_wrapper/models/log_type.py +79 -0
  254. epa_pm_api_wrapper/models/mailing_center_post_office.py +16 -0
  255. epa_pm_api_wrapper/models/mailing_center_post_office_type.py +37 -0
  256. epa_pm_api_wrapper/models/mailing_center_post_office_type_use_details.py +74 -0
  257. epa_pm_api_wrapper/models/manufacturing_industrial_plant.py +17 -0
  258. epa_pm_api_wrapper/models/manufacturing_industrial_plant_type.py +37 -0
  259. epa_pm_api_wrapper/models/manufacturing_industrial_plant_type_use_details.py +49 -0
  260. epa_pm_api_wrapper/models/mapping.py +11 -0
  261. epa_pm_api_wrapper/models/mapping_type.py +23 -0
  262. epa_pm_api_wrapper/models/maximum_number_of_floors.py +15 -0
  263. epa_pm_api_wrapper/models/maximum_resident_capacity.py +15 -0
  264. epa_pm_api_wrapper/models/medical_office.py +16 -0
  265. epa_pm_api_wrapper/models/medical_office_type.py +35 -0
  266. epa_pm_api_wrapper/models/medical_office_type_use_details.py +82 -0
  267. epa_pm_api_wrapper/models/meter.py +11 -0
  268. epa_pm_api_wrapper/models/meter_category_type.py +9 -0
  269. epa_pm_api_wrapper/models/meter_consumption.py +15 -0
  270. epa_pm_api_wrapper/models/meter_consumption_type.py +110 -0
  271. epa_pm_api_wrapper/models/meter_data.py +11 -0
  272. epa_pm_api_wrapper/models/meter_data_type.py +41 -0
  273. epa_pm_api_wrapper/models/meter_delivery.py +11 -0
  274. epa_pm_api_wrapper/models/meter_delivery_type.py +68 -0
  275. epa_pm_api_wrapper/models/meter_list_type.py +23 -0
  276. epa_pm_api_wrapper/models/meter_property_association_list.py +18 -0
  277. epa_pm_api_wrapper/models/meter_property_association_list_type.py +38 -0
  278. epa_pm_api_wrapper/models/meter_property_use_association_list.py +16 -0
  279. epa_pm_api_wrapper/models/meter_type.py +131 -0
  280. epa_pm_api_wrapper/models/meter_type_unit_of_measure.py +40 -0
  281. epa_pm_api_wrapper/models/metric.py +71 -0
  282. epa_pm_api_wrapper/models/months_in_use.py +15 -0
  283. epa_pm_api_wrapper/models/months_in_use_type.py +21 -0
  284. epa_pm_api_wrapper/models/months_main_indoor_ice_rink_in_use.py +15 -0
  285. epa_pm_api_wrapper/models/months_school_in_use_type.py +21 -0
  286. epa_pm_api_wrapper/models/movie_theater.py +15 -0
  287. epa_pm_api_wrapper/models/multifamily_housing.py +16 -0
  288. epa_pm_api_wrapper/models/multifamily_housing_type.py +37 -0
  289. epa_pm_api_wrapper/models/multifamily_housing_type_use_details.py +124 -0
  290. epa_pm_api_wrapper/models/museum.py +26 -0
  291. epa_pm_api_wrapper/models/museum_type.py +35 -0
  292. epa_pm_api_wrapper/models/museum_type_use_details.py +78 -0
  293. epa_pm_api_wrapper/models/non_refrigerated_warehouse.py +16 -0
  294. epa_pm_api_wrapper/models/non_refrigerated_warehouse_type.py +37 -0
  295. epa_pm_api_wrapper/models/non_refrigerated_warehouse_type_use_details.py +76 -0
  296. epa_pm_api_wrapper/models/notification_list.py +16 -0
  297. epa_pm_api_wrapper/models/notification_list_type.py +19 -0
  298. epa_pm_api_wrapper/models/notification_type.py +106 -0
  299. epa_pm_api_wrapper/models/number_of_annual_emergency_incidents.py +17 -0
  300. epa_pm_api_wrapper/models/number_of_bedrooms.py +15 -0
  301. epa_pm_api_wrapper/models/number_of_cash_registers.py +15 -0
  302. epa_pm_api_wrapper/models/number_of_commercial_refrigeration_units.py +16 -0
  303. epa_pm_api_wrapper/models/number_of_commercial_washing_machines.py +16 -0
  304. epa_pm_api_wrapper/models/number_of_computers.py +15 -0
  305. epa_pm_api_wrapper/models/number_of_concert_show_events_per_year.py +15 -0
  306. epa_pm_api_wrapper/models/number_of_cooking_equipment_units.py +15 -0
  307. epa_pm_api_wrapper/models/number_of_curling_sheets.py +16 -0
  308. epa_pm_api_wrapper/models/number_of_dc_fast_ev_charging_stations.py +15 -0
  309. epa_pm_api_wrapper/models/number_of_emergency_vehicles.py +16 -0
  310. epa_pm_api_wrapper/models/number_of_fteworkers.py +16 -0
  311. epa_pm_api_wrapper/models/number_of_full_time_students_enrolled_january_to_april.py +16 -0
  312. epa_pm_api_wrapper/models/number_of_full_time_students_enrolled_may_to_august.py +16 -0
  313. epa_pm_api_wrapper/models/number_of_full_time_students_enrolled_september_to_december.py +16 -0
  314. epa_pm_api_wrapper/models/number_of_guest_meals_served_per_year.py +15 -0
  315. epa_pm_api_wrapper/models/number_of_hotel_rooms.py +15 -0
  316. epa_pm_api_wrapper/models/number_of_indoor_ice_rinks.py +18 -0
  317. epa_pm_api_wrapper/models/number_of_laundry_hookups_in_all_units.py +16 -0
  318. epa_pm_api_wrapper/models/number_of_laundry_hookups_in_common_area.py +16 -0
  319. epa_pm_api_wrapper/models/number_of_letters_packages_per_year.py +17 -0
  320. epa_pm_api_wrapper/models/number_of_level_one_ev_charging_stations.py +15 -0
  321. epa_pm_api_wrapper/models/number_of_level_two_ev_charging_stations.py +15 -0
  322. epa_pm_api_wrapper/models/number_of_mri_machines.py +15 -0
  323. epa_pm_api_wrapper/models/number_of_open_closed_refrigeration_units.py +27 -0
  324. epa_pm_api_wrapper/models/number_of_paint_bays.py +16 -0
  325. epa_pm_api_wrapper/models/number_of_people.py +15 -0
  326. epa_pm_api_wrapper/models/number_of_repair_bays.py +16 -0
  327. epa_pm_api_wrapper/models/number_of_residential_lift_systems.py +15 -0
  328. epa_pm_api_wrapper/models/number_of_residential_living_units.py +20 -0
  329. epa_pm_api_wrapper/models/number_of_residential_living_units_high_rise_setting.py +18 -0
  330. epa_pm_api_wrapper/models/number_of_residential_living_units_low_rise_setting.py +18 -0
  331. epa_pm_api_wrapper/models/number_of_residential_living_units_mid_rise_setting.py +18 -0
  332. epa_pm_api_wrapper/models/number_of_residential_washing_machines.py +15 -0
  333. epa_pm_api_wrapper/models/number_of_rooms.py +16 -0
  334. epa_pm_api_wrapper/models/number_of_special_other_events_per_year.py +16 -0
  335. epa_pm_api_wrapper/models/number_of_sporting_events_per_year.py +15 -0
  336. epa_pm_api_wrapper/models/number_of_staffed_beds.py +15 -0
  337. epa_pm_api_wrapper/models/number_of_sterilization_units.py +15 -0
  338. epa_pm_api_wrapper/models/number_of_surgical_operating_beds.py +16 -0
  339. epa_pm_api_wrapper/models/number_of_walk_in_refrigeration_units.py +16 -0
  340. epa_pm_api_wrapper/models/number_of_warming_heating_equipment_units.py +15 -0
  341. epa_pm_api_wrapper/models/number_of_weekdays_open.py +17 -0
  342. epa_pm_api_wrapper/models/number_of_weekdays_type.py +21 -0
  343. epa_pm_api_wrapper/models/number_of_weekly_ice_resurfacing_for_all_rinks.py +23 -0
  344. epa_pm_api_wrapper/models/number_of_weekly_ice_resurfacing_type.py +20 -0
  345. epa_pm_api_wrapper/models/number_of_workers.py +16 -0
  346. epa_pm_api_wrapper/models/nutrient_removal.py +16 -0
  347. epa_pm_api_wrapper/models/occupancy_type.py +27 -0
  348. epa_pm_api_wrapper/models/office.py +16 -0
  349. epa_pm_api_wrapper/models/office_type.py +35 -0
  350. epa_pm_api_wrapper/models/office_type_use_details.py +58 -0
  351. epa_pm_api_wrapper/models/offsite_green_power_purchase.py +11 -0
  352. epa_pm_api_wrapper/models/offsite_green_power_purchase_type.py +224 -0
  353. epa_pm_api_wrapper/models/offsite_green_power_purchase_type_amount_purchased.py +31 -0
  354. epa_pm_api_wrapper/models/offsite_green_power_purchase_type_amount_purchased_percentage.py +46 -0
  355. epa_pm_api_wrapper/models/offsite_green_power_purchase_type_amount_purchased_percentage_meters.py +21 -0
  356. epa_pm_api_wrapper/models/offsite_green_power_purchase_type_amount_purchased_quantity.py +31 -0
  357. epa_pm_api_wrapper/models/offsite_green_power_purchase_type_cost.py +31 -0
  358. epa_pm_api_wrapper/models/offsite_green_power_purchase_type_fuel_sources.py +22 -0
  359. epa_pm_api_wrapper/models/offsite_green_power_purchase_type_fuel_sources_fuel_source.py +35 -0
  360. epa_pm_api_wrapper/models/offsite_green_power_purchase_type_rated_capacity.py +31 -0
  361. epa_pm_api_wrapper/models/offsite_green_power_purchase_type_renewable_generation_technologies.py +21 -0
  362. epa_pm_api_wrapper/models/on_site_laundry_facility.py +15 -0
  363. epa_pm_api_wrapper/models/onsite_laundry_type.py +20 -0
  364. epa_pm_api_wrapper/models/onsite_laundry_type_value.py +10 -0
  365. epa_pm_api_wrapper/models/onsite_renewable_detail.py +11 -0
  366. epa_pm_api_wrapper/models/onsite_renewable_detail_type.py +60 -0
  367. epa_pm_api_wrapper/models/onsite_renewable_details.py +28 -0
  368. epa_pm_api_wrapper/models/onsite_renewable_optional_info.py +13 -0
  369. epa_pm_api_wrapper/models/onsite_renewable_optional_info_type.py +134 -0
  370. epa_pm_api_wrapper/models/onsite_renewable_optional_info_type_rated_capacity.py +31 -0
  371. epa_pm_api_wrapper/models/onsite_renewable_optional_info_type_renewable_generation_technologies.py +21 -0
  372. epa_pm_api_wrapper/models/onsite_usage_detail_type.py +70 -0
  373. epa_pm_api_wrapper/models/open_footage.py +15 -0
  374. epa_pm_api_wrapper/models/open_on_weekends.py +16 -0
  375. epa_pm_api_wrapper/models/optional_floor_area_type.py +19 -0
  376. epa_pm_api_wrapper/models/organization_type.py +77 -0
  377. epa_pm_api_wrapper/models/other.py +16 -0
  378. epa_pm_api_wrapper/models/other_education.py +18 -0
  379. epa_pm_api_wrapper/models/other_entertainment_public_assembly.py +17 -0
  380. epa_pm_api_wrapper/models/other_lodging_residential.py +19 -0
  381. epa_pm_api_wrapper/models/other_mall.py +17 -0
  382. epa_pm_api_wrapper/models/other_public_services.py +21 -0
  383. epa_pm_api_wrapper/models/other_recreation.py +16 -0
  384. epa_pm_api_wrapper/models/other_restaurant_bar.py +17 -0
  385. epa_pm_api_wrapper/models/other_services.py +16 -0
  386. epa_pm_api_wrapper/models/other_speciality_hospital.py +17 -0
  387. epa_pm_api_wrapper/models/other_stadium.py +16 -0
  388. epa_pm_api_wrapper/models/other_stadium_type.py +35 -0
  389. epa_pm_api_wrapper/models/other_stadium_type_use_details.py +104 -0
  390. epa_pm_api_wrapper/models/other_technology_science.py +16 -0
  391. epa_pm_api_wrapper/models/other_type.py +35 -0
  392. epa_pm_api_wrapper/models/other_type_use_details.py +42 -0
  393. epa_pm_api_wrapper/models/other_utility.py +16 -0
  394. epa_pm_api_wrapper/models/outpatient_rehabilitation_physical_therapy.py +16 -0
  395. epa_pm_api_wrapper/models/owned_by.py +16 -0
  396. epa_pm_api_wrapper/models/owned_by_type.py +20 -0
  397. epa_pm_api_wrapper/models/owned_by_type_value.py +9 -0
  398. epa_pm_api_wrapper/models/parking.py +15 -0
  399. epa_pm_api_wrapper/models/parking_type.py +35 -0
  400. epa_pm_api_wrapper/models/parking_type_use_details.py +40 -0
  401. epa_pm_api_wrapper/models/partially_enclosed_footage.py +16 -0
  402. epa_pm_api_wrapper/models/ped.py +26 -0
  403. epa_pm_api_wrapper/models/pending_accounts_type.py +58 -0
  404. epa_pm_api_wrapper/models/pending_list.py +15 -0
  405. epa_pm_api_wrapper/models/pending_list_type.py +53 -0
  406. epa_pm_api_wrapper/models/pending_meters_type.py +104 -0
  407. epa_pm_api_wrapper/models/pending_properties_type.py +77 -0
  408. epa_pm_api_wrapper/models/percent_cooled.py +16 -0
  409. epa_pm_api_wrapper/models/percent_cooled_type.py +20 -0
  410. epa_pm_api_wrapper/models/percent_cooled_type_value.py +17 -0
  411. epa_pm_api_wrapper/models/percent_heated.py +16 -0
  412. epa_pm_api_wrapper/models/percent_heated_type.py +20 -0
  413. epa_pm_api_wrapper/models/percent_heated_type_value.py +17 -0
  414. epa_pm_api_wrapper/models/percent_of_gross_floor_area_that_is_common_space_only.py +16 -0
  415. epa_pm_api_wrapper/models/percent_of_lab_floor_area.py +16 -0
  416. epa_pm_api_wrapper/models/percent_office_cooled.py +11 -0
  417. epa_pm_api_wrapper/models/percent_office_cooled_type.py +20 -0
  418. epa_pm_api_wrapper/models/percent_office_cooled_type_value.py +9 -0
  419. epa_pm_api_wrapper/models/percent_office_heated.py +11 -0
  420. epa_pm_api_wrapper/models/percent_office_heated_type.py +20 -0
  421. epa_pm_api_wrapper/models/percent_office_heated_type_value.py +9 -0
  422. epa_pm_api_wrapper/models/percent_used_for_cold_storage.py +18 -0
  423. epa_pm_api_wrapper/models/performance_target_type.py +42 -0
  424. epa_pm_api_wrapper/models/performance_target_type_target_metric.py +10 -0
  425. epa_pm_api_wrapper/models/performance_target_type_target_value.py +107 -0
  426. epa_pm_api_wrapper/models/performing_arts.py +15 -0
  427. epa_pm_api_wrapper/models/period_type.py +8 -0
  428. epa_pm_api_wrapper/models/personal_services.py +17 -0
  429. epa_pm_api_wrapper/models/pgp.py +56 -0
  430. epa_pm_api_wrapper/models/pgp_list.py +18 -0
  431. epa_pm_api_wrapper/models/plant_data_type.py +28 -0
  432. epa_pm_api_wrapper/models/plant_data_type_value.py +71 -0
  433. epa_pm_api_wrapper/models/plant_design_flow_rate.py +16 -0
  434. epa_pm_api_wrapper/models/plant_design_flow_rate_type.py +22 -0
  435. epa_pm_api_wrapper/models/plant_design_flow_rate_units_type.py +8 -0
  436. epa_pm_api_wrapper/models/plant_type.py +17 -0
  437. epa_pm_api_wrapper/models/police_station.py +16 -0
  438. epa_pm_api_wrapper/models/pool_location.py +15 -0
  439. epa_pm_api_wrapper/models/pool_size.py +16 -0
  440. epa_pm_api_wrapper/models/pool_size_type.py +20 -0
  441. epa_pm_api_wrapper/models/pool_size_type_value.py +9 -0
  442. epa_pm_api_wrapper/models/pool_type.py +20 -0
  443. epa_pm_api_wrapper/models/pool_type_value.py +8 -0
  444. epa_pm_api_wrapper/models/precision_controls_for_temperature_and_humidity.py +16 -0
  445. epa_pm_api_wrapper/models/preschool_daycare.py +17 -0
  446. epa_pm_api_wrapper/models/preschool_daycare_type.py +35 -0
  447. epa_pm_api_wrapper/models/preschool_daycare_type_use_details.py +68 -0
  448. epa_pm_api_wrapper/models/primary_business_type.py +33 -0
  449. epa_pm_api_wrapper/models/primary_function_type.py +95 -0
  450. epa_pm_api_wrapper/models/prison.py +17 -0
  451. epa_pm_api_wrapper/models/professional_designation_list.py +23 -0
  452. epa_pm_api_wrapper/models/professional_designation_list_professional_designation.py +41 -0
  453. epa_pm_api_wrapper/models/property.py +11 -0
  454. epa_pm_api_wrapper/models/property_design_type.py +66 -0
  455. epa_pm_api_wrapper/models/property_metrics.py +15 -0
  456. epa_pm_api_wrapper/models/property_metrics_list.py +19 -0
  457. epa_pm_api_wrapper/models/property_metrics_type.py +58 -0
  458. epa_pm_api_wrapper/models/property_representation.py +59 -0
  459. epa_pm_api_wrapper/models/property_representation_property_representation_type.py +27 -0
  460. epa_pm_api_wrapper/models/property_type.py +192 -0
  461. epa_pm_api_wrapper/models/property_use.py +22 -0
  462. epa_pm_api_wrapper/models/race_track.py +16 -0
  463. epa_pm_api_wrapper/models/rated_capacity_uom_type.py +8 -0
  464. epa_pm_api_wrapper/models/rec_ownership_enum.py +10 -0
  465. epa_pm_api_wrapper/models/refrigerated_warehouse.py +17 -0
  466. epa_pm_api_wrapper/models/refrigerated_warehouse_type.py +37 -0
  467. epa_pm_api_wrapper/models/refrigerated_warehouse_type_use_details.py +66 -0
  468. epa_pm_api_wrapper/models/renewable_generation_technology_enum.py +11 -0
  469. epa_pm_api_wrapper/models/report.py +72 -0
  470. epa_pm_api_wrapper/models/report_error.py +53 -0
  471. epa_pm_api_wrapper/models/report_error_missing_metrics.py +21 -0
  472. epa_pm_api_wrapper/models/report_error_missing_metrics_property_missing_metric.py +43 -0
  473. epa_pm_api_wrapper/models/report_error_missing_metrics_property_missing_metric_metric.py +33 -0
  474. epa_pm_api_wrapper/models/report_metric_values_ws.py +57 -0
  475. epa_pm_api_wrapper/models/report_metrics.py +26 -0
  476. epa_pm_api_wrapper/models/report_metrics_group.py +36 -0
  477. epa_pm_api_wrapper/models/report_metrics_group_metrics.py +24 -0
  478. epa_pm_api_wrapper/models/report_metrics_group_metrics_metric.py +62 -0
  479. epa_pm_api_wrapper/models/report_properties.py +20 -0
  480. epa_pm_api_wrapper/models/report_status.py +11 -0
  481. epa_pm_api_wrapper/models/report_status_def.py +62 -0
  482. epa_pm_api_wrapper/models/report_status_type.py +33 -0
  483. epa_pm_api_wrapper/models/report_template.py +11 -0
  484. epa_pm_api_wrapper/models/report_template_type.py +63 -0
  485. epa_pm_api_wrapper/models/report_template_type_metrics.py +21 -0
  486. epa_pm_api_wrapper/models/report_type.py +17 -0
  487. epa_pm_api_wrapper/models/reporting_interval_type.py +15 -0
  488. epa_pm_api_wrapper/models/residence_hall_dormitory.py +16 -0
  489. epa_pm_api_wrapper/models/residence_hall_dormitory_type.py +37 -0
  490. epa_pm_api_wrapper/models/residence_hall_dormitory_type_use_details.py +58 -0
  491. epa_pm_api_wrapper/models/resident_population.py +16 -0
  492. epa_pm_api_wrapper/models/resident_population_type.py +20 -0
  493. epa_pm_api_wrapper/models/resident_population_type_value.py +12 -0
  494. epa_pm_api_wrapper/models/residential_care_facility.py +16 -0
  495. epa_pm_api_wrapper/models/residential_care_facility_type.py +37 -0
  496. epa_pm_api_wrapper/models/residential_care_facility_type_use_details.py +120 -0
  497. epa_pm_api_wrapper/models/response.py +11 -0
  498. epa_pm_api_wrapper/models/response_status.py +36 -0
  499. epa_pm_api_wrapper/models/response_status_errors.py +19 -0
  500. epa_pm_api_wrapper/models/response_type.py +59 -0
  501. epa_pm_api_wrapper/models/restaurant.py +20 -0
  502. epa_pm_api_wrapper/models/restaurant_type.py +35 -0
  503. epa_pm_api_wrapper/models/restaurant_type_use_details.py +84 -0
  504. epa_pm_api_wrapper/models/retail.py +17 -0
  505. epa_pm_api_wrapper/models/retail_type.py +35 -0
  506. epa_pm_api_wrapper/models/retail_type_use_details.py +130 -0
  507. epa_pm_api_wrapper/models/roller_rink.py +16 -0
  508. epa_pm_api_wrapper/models/school_district.py +15 -0
  509. epa_pm_api_wrapper/models/search_result_type.py +23 -0
  510. epa_pm_api_wrapper/models/search_results.py +15 -0
  511. epa_pm_api_wrapper/models/seating_capacity.py +16 -0
  512. epa_pm_api_wrapper/models/self_storage_facility.py +15 -0
  513. epa_pm_api_wrapper/models/self_storage_facility_type.py +37 -0
  514. epa_pm_api_wrapper/models/self_storage_facility_type_use_details.py +84 -0
  515. epa_pm_api_wrapper/models/send_data_response.py +43 -0
  516. epa_pm_api_wrapper/models/send_data_response_additional_email_addresses.py +17 -0
  517. epa_pm_api_wrapper/models/send_data_response_file_format.py +8 -0
  518. epa_pm_api_wrapper/models/senior_living_community.py +16 -0
  519. epa_pm_api_wrapper/models/senior_living_community_type.py +37 -0
  520. epa_pm_api_wrapper/models/senior_living_community_type_use_details.py +120 -0
  521. epa_pm_api_wrapper/models/share_level_type.py +12 -0
  522. epa_pm_api_wrapper/models/sharing_response.py +16 -0
  523. epa_pm_api_wrapper/models/sharing_response_type.py +34 -0
  524. epa_pm_api_wrapper/models/single_family_home.py +16 -0
  525. epa_pm_api_wrapper/models/single_family_home_type.py +35 -0
  526. epa_pm_api_wrapper/models/single_family_home_type_use_details.py +34 -0
  527. epa_pm_api_wrapper/models/single_store.py +15 -0
  528. epa_pm_api_wrapper/models/size_of_electronic_score_boards.py +15 -0
  529. epa_pm_api_wrapper/models/spectator_seating_capacity.py +16 -0
  530. epa_pm_api_wrapper/models/stadium_closed.py +17 -0
  531. epa_pm_api_wrapper/models/stadium_closed_type.py +35 -0
  532. epa_pm_api_wrapper/models/stadium_closed_type_use_details.py +104 -0
  533. epa_pm_api_wrapper/models/stadium_open.py +17 -0
  534. epa_pm_api_wrapper/models/stadium_open_type.py +35 -0
  535. epa_pm_api_wrapper/models/stadium_open_type_use_details.py +104 -0
  536. epa_pm_api_wrapper/models/state_code.py +159 -0
  537. epa_pm_api_wrapper/models/station.py +45 -0
  538. epa_pm_api_wrapper/models/status_type.py +8 -0
  539. epa_pm_api_wrapper/models/strip_mall.py +17 -0
  540. epa_pm_api_wrapper/models/student_seating_capacity.py +16 -0
  541. epa_pm_api_wrapper/models/supermarket.py +17 -0
  542. epa_pm_api_wrapper/models/supermarket_type.py +35 -0
  543. epa_pm_api_wrapper/models/supermarket_type_use_details.py +114 -0
  544. epa_pm_api_wrapper/models/supplemental_heating.py +15 -0
  545. epa_pm_api_wrapper/models/surgery_center_floor_area.py +16 -0
  546. epa_pm_api_wrapper/models/swimming_pool.py +15 -0
  547. epa_pm_api_wrapper/models/swimming_pool_type.py +35 -0
  548. epa_pm_api_wrapper/models/swimming_pool_type_use_details.py +34 -0
  549. epa_pm_api_wrapper/models/system_determined_string.py +7 -0
  550. epa_pm_api_wrapper/models/target_finder.py +11 -0
  551. epa_pm_api_wrapper/models/target_type_percentage_type.py +17 -0
  552. epa_pm_api_wrapper/models/target_type_percentage_values_type.py +107 -0
  553. epa_pm_api_wrapper/models/target_type_score_type.py +17 -0
  554. epa_pm_api_wrapper/models/target_type_score_values_type.py +106 -0
  555. epa_pm_api_wrapper/models/template_type.py +19 -0
  556. epa_pm_api_wrapper/models/template_type_value.py +15 -0
  557. epa_pm_api_wrapper/models/tenant_common_area_energy_type.py +21 -0
  558. epa_pm_api_wrapper/models/tenant_common_area_energy_use_information_type.py +31 -0
  559. epa_pm_api_wrapper/models/terminate_share_response_type.py +24 -0
  560. epa_pm_api_wrapper/models/terminate_sharing_response.py +16 -0
  561. epa_pm_api_wrapper/models/timeframe_type.py +103 -0
  562. epa_pm_api_wrapper/models/timeframe_type_baseline_period.py +18 -0
  563. epa_pm_api_wrapper/models/timeframe_type_compare_baseline_period.py +25 -0
  564. epa_pm_api_wrapper/models/timeframe_type_compare_current_period.py +25 -0
  565. epa_pm_api_wrapper/models/timeframe_type_current_period.py +18 -0
  566. epa_pm_api_wrapper/models/timeframe_type_current_vs_baseline.py +18 -0
  567. epa_pm_api_wrapper/models/timeframe_type_date_range.py +30 -0
  568. epa_pm_api_wrapper/models/timeframe_type_single_period.py +18 -0
  569. epa_pm_api_wrapper/models/timeframe_type_two_periods.py +24 -0
  570. epa_pm_api_wrapper/models/total_gross_floor_area.py +11 -0
  571. epa_pm_api_wrapper/models/total_ice_rink_surface_area_for_all_rinks.py +21 -0
  572. epa_pm_api_wrapper/models/transportation_terminal_station.py +16 -0
  573. epa_pm_api_wrapper/models/type_of_energy_star_partner.py +14 -0
  574. epa_pm_api_wrapper/models/type_of_meter.py +55 -0
  575. epa_pm_api_wrapper/models/type_of_waste_meter.py +122 -0
  576. epa_pm_api_wrapper/models/type_of_waste_meter_data_entry_method.py +18 -0
  577. epa_pm_api_wrapper/models/type_of_waste_meter_unit_of_measure.py +15 -0
  578. epa_pm_api_wrapper/models/un_auth_design_type.py +100 -0
  579. epa_pm_api_wrapper/models/un_auth_design_type_estimated_energy_list.py +17 -0
  580. epa_pm_api_wrapper/models/un_auth_design_type_property_uses.py +709 -0
  581. epa_pm_api_wrapper/models/un_auth_design_type_target.py +34 -0
  582. epa_pm_api_wrapper/models/ups_system_redundancy.py +16 -0
  583. epa_pm_api_wrapper/models/ups_system_redundancy_type.py +20 -0
  584. epa_pm_api_wrapper/models/ups_system_redundancy_type_value.py +12 -0
  585. epa_pm_api_wrapper/models/urgent_care_clinic_other_outpatient.py +17 -0
  586. epa_pm_api_wrapper/models/use_attribute_base.py +65 -0
  587. epa_pm_api_wrapper/models/use_attribute_base_default.py +9 -0
  588. epa_pm_api_wrapper/models/use_decimal_type.py +21 -0
  589. epa_pm_api_wrapper/models/use_details.py +1086 -0
  590. epa_pm_api_wrapper/models/use_integer_type.py +20 -0
  591. epa_pm_api_wrapper/models/use_string_type.py +19 -0
  592. epa_pm_api_wrapper/models/use_yes_no_type.py +20 -0
  593. epa_pm_api_wrapper/models/vehicle_dealership.py +16 -0
  594. epa_pm_api_wrapper/models/vehicle_dealership_type.py +37 -0
  595. epa_pm_api_wrapper/models/vehicle_dealership_type_use_details.py +84 -0
  596. epa_pm_api_wrapper/models/vehicle_repair_services.py +19 -0
  597. epa_pm_api_wrapper/models/vehicle_repair_services_type.py +37 -0
  598. epa_pm_api_wrapper/models/vehicle_repair_services_type_use_details.py +74 -0
  599. epa_pm_api_wrapper/models/verification.py +96 -0
  600. epa_pm_api_wrapper/models/veterinary_office.py +15 -0
  601. epa_pm_api_wrapper/models/vocational_school.py +16 -0
  602. epa_pm_api_wrapper/models/warning_type.py +29 -0
  603. epa_pm_api_wrapper/models/warnings_type.py +25 -0
  604. epa_pm_api_wrapper/models/waste_data.py +15 -0
  605. epa_pm_api_wrapper/models/waste_data_list.py +11 -0
  606. epa_pm_api_wrapper/models/waste_meter.py +11 -0
  607. epa_pm_api_wrapper/models/waste_meter_assoc_and_config_type.py +18 -0
  608. epa_pm_api_wrapper/models/waste_meter_data_type.py +32 -0
  609. epa_pm_api_wrapper/models/waste_meter_entry_type.py +113 -0
  610. epa_pm_api_wrapper/models/waste_meter_entry_type_average_percent_full.py +11 -0
  611. epa_pm_api_wrapper/models/waste_meter_type.py +81 -0
  612. epa_pm_api_wrapper/models/wastewater_treatment_plant.py +15 -0
  613. epa_pm_api_wrapper/models/wastewater_treatment_plant_type.py +37 -0
  614. epa_pm_api_wrapper/models/wastewater_treatment_plant_type_use_details.py +63 -0
  615. epa_pm_api_wrapper/models/water_meter_assoc_and_config_type.py +25 -0
  616. epa_pm_api_wrapper/models/weekly_building_occupied_hours.py +16 -0
  617. epa_pm_api_wrapper/models/weekly_operating_hours.py +19 -0
  618. epa_pm_api_wrapper/models/wholesale_club_supercenter.py +16 -0
  619. epa_pm_api_wrapper/models/wholesale_club_supercenter_type.py +37 -0
  620. epa_pm_api_wrapper/models/wholesale_club_supercenter_type_use_details.py +130 -0
  621. epa_pm_api_wrapper/models/worship_facility.py +19 -0
  622. epa_pm_api_wrapper/models/worship_facility_type.py +35 -0
  623. epa_pm_api_wrapper/models/worship_facility_type_use_details.py +102 -0
  624. epa_pm_api_wrapper/models/yes_no.py +8 -0
  625. epa_pm_api_wrapper/models/zoo.py +16 -0
  626. epa_pm_api_wrapper/py.typed +1 -0
  627. epa_pm_api_wrapper/resources/__init__.py +172 -0
  628. epa_pm_api_wrapper/resources/_base.py +22 -0
  629. epa_pm_api_wrapper/resources/account.py +37 -0
  630. epa_pm_api_wrapper/resources/association.py +145 -0
  631. epa_pm_api_wrapper/resources/building.py +89 -0
  632. epa_pm_api_wrapper/resources/consumption_data.py +142 -0
  633. epa_pm_api_wrapper/resources/custom_metric.py +91 -0
  634. epa_pm_api_wrapper/resources/customer.py +45 -0
  635. epa_pm_api_wrapper/resources/data_exchange.py +111 -0
  636. epa_pm_api_wrapper/resources/green_power.py +237 -0
  637. epa_pm_api_wrapper/resources/hey.py +22 -0
  638. epa_pm_api_wrapper/resources/hierarchy.py +59 -0
  639. epa_pm_api_wrapper/resources/identifier.py +92 -0
  640. epa_pm_api_wrapper/resources/meter.py +277 -0
  641. epa_pm_api_wrapper/resources/metrics.py +185 -0
  642. epa_pm_api_wrapper/resources/property.py +450 -0
  643. epa_pm_api_wrapper/resources/property_use.py +277 -0
  644. epa_pm_api_wrapper/resources/report.py +169 -0
  645. epa_pm_api_wrapper/resources/share.py +139 -0
  646. epa_pm_api_wrapper/resources/target_finder.py +34 -0
  647. epa_pm_api_wrapper/resources/verification.py +201 -0
  648. epa_pm_api_wrapper/resources/waste_data.py +124 -0
  649. epa_pm_api_wrapper/retry.py +219 -0
  650. epa_pm_api_wrapper-0.3.0.dist-info/METADATA +137 -0
  651. epa_pm_api_wrapper-0.3.0.dist-info/RECORD +654 -0
  652. epa_pm_api_wrapper-0.3.0.dist-info/WHEEL +4 -0
  653. epa_pm_api_wrapper-0.3.0.dist-info/entry_points.txt +2 -0
  654. epa_pm_api_wrapper-0.3.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,507 @@
1
+ """EPA Portfolio Manager API client.
2
+
3
+ Two clients are exposed:
4
+
5
+ - :class:`EpaPmClient` (sync, ``httpx.Client`` backend)
6
+ - :class:`EpaPmAsyncClient` (async, ``httpx.AsyncClient`` backend)
7
+
8
+ Both expose the API as attribute-namespaced resources::
9
+
10
+ client.account.get()
11
+ client.property.list(account_id)
12
+ client.report.templates.list()
13
+
14
+ …with the difference that async resource methods are coroutines::
15
+
16
+ async with EpaPmAsyncClient(user, pwd) as c:
17
+ acc = await c.account.get()
18
+
19
+ This module holds the shared HTTP plumbing (auth, base URL, request body
20
+ construction, error mapping, response parsing). The concrete request
21
+ methods live on each client (sync ``_request``, async ``_arequest``).
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import logging
27
+ from typing import Any, TypeVar, cast, overload
28
+
29
+ import httpx
30
+ from xsdata.formats.dataclass.parsers import XmlParser
31
+ from xsdata.formats.dataclass.serializers import XmlSerializer
32
+ from xsdata.formats.dataclass.serializers.config import SerializerConfig
33
+
34
+ from epa_pm_api_wrapper.exceptions import EpaErrorDetail, EpaPmApiError, EpaPmAuthError
35
+ from epa_pm_api_wrapper.models import Response
36
+ from epa_pm_api_wrapper.resources import (
37
+ AccountResource,
38
+ AssociationResource,
39
+ AsyncAccountResource,
40
+ AsyncAssociationResource,
41
+ AsyncBuildingResource,
42
+ AsyncConsumptionDataResource,
43
+ AsyncCustomerResource,
44
+ AsyncCustomMetricResource,
45
+ AsyncDataExchangeResource,
46
+ AsyncGreenPowerResource,
47
+ AsyncHeyResource,
48
+ AsyncHierarchyResource,
49
+ AsyncIdentifierResource,
50
+ AsyncMeterResource,
51
+ AsyncMetricsResource,
52
+ AsyncPropertyResource,
53
+ AsyncPropertyUseResource,
54
+ AsyncReportResource,
55
+ AsyncShareResource,
56
+ AsyncTargetFinderResource,
57
+ AsyncVerificationResource,
58
+ AsyncWasteDataResource,
59
+ BuildingResource,
60
+ ConsumptionDataResource,
61
+ CustomerResource,
62
+ CustomMetricResource,
63
+ DataExchangeResource,
64
+ GreenPowerResource,
65
+ HeyResource,
66
+ HierarchyResource,
67
+ IdentifierResource,
68
+ MeterResource,
69
+ MetricsResource,
70
+ PropertyResource,
71
+ PropertyUseResource,
72
+ ReportResource,
73
+ ShareResource,
74
+ TargetFinderResource,
75
+ VerificationResource,
76
+ WasteDataResource,
77
+ )
78
+ from epa_pm_api_wrapper.retry import AsyncRetryTransport, RetryConfig, RetryTransport
79
+
80
+ logger = logging.getLogger(__name__)
81
+
82
+ T = TypeVar("T")
83
+
84
+
85
+ def _resolve_retry(retries: int | None, retry: RetryConfig | None) -> RetryConfig | None:
86
+ """Resolve the retry config from the two convenience kwargs.
87
+
88
+ ``retry`` wins if explicitly provided. ``retries`` overrides only the
89
+ attempt count. ``retries=0`` disables retries (returns ``None``).
90
+ Default is ``RetryConfig()`` (3 retries, exponential backoff).
91
+ """
92
+ if retry is not None:
93
+ return retry
94
+ if retries == 0:
95
+ return None
96
+ if retries is not None:
97
+ return RetryConfig(max_retries=retries)
98
+ return RetryConfig()
99
+
100
+
101
+ def _wrap_transport_sync(
102
+ transport: httpx.BaseTransport | None,
103
+ retries: int | None,
104
+ retry: RetryConfig | None,
105
+ ) -> httpx.BaseTransport | None:
106
+ cfg = _resolve_retry(retries, retry)
107
+ if cfg is None:
108
+ return transport
109
+ return RetryTransport(transport, config=cfg)
110
+
111
+
112
+ def _wrap_transport_async(
113
+ transport: httpx.AsyncBaseTransport | None,
114
+ retries: int | None,
115
+ retry: RetryConfig | None,
116
+ ) -> httpx.AsyncBaseTransport | None:
117
+ cfg = _resolve_retry(retries, retry)
118
+ if cfg is None:
119
+ return transport
120
+ return AsyncRetryTransport(transport, config=cfg)
121
+
122
+
123
+ def _to_int(value: str | None) -> int | None:
124
+ """Parse an error number string into an int; return ``None`` on failure.
125
+
126
+ The XSD declares ``errorNumber`` as a string, but in practice the EPA
127
+ sends integer values (including negative ones like ``-200``). Callers
128
+ branch on integers, so we coerce here and fall back to ``None`` if a
129
+ future response ever surprises us with a non-integer code.
130
+ """
131
+ if value is None:
132
+ return None
133
+ try:
134
+ return int(value)
135
+ except ValueError:
136
+ return None
137
+
138
+
139
+ class _BaseClient:
140
+ """Plumbing shared by sync and async clients (no I/O methods)."""
141
+
142
+ LIVE_BASE_URL = "https://portfoliomanager.energystar.gov/ws"
143
+ TEST_BASE_URL = "https://portfoliomanager.energystar.gov/wstest"
144
+ DEFAULT_TIMEOUT = 30.0
145
+
146
+ def __init__(
147
+ self,
148
+ username: str,
149
+ password: str,
150
+ base_url: str | None = None,
151
+ use_test_env: bool = False,
152
+ ):
153
+ if base_url:
154
+ self.base_url = base_url.rstrip("/")
155
+ elif use_test_env:
156
+ self.base_url = self.TEST_BASE_URL
157
+ else:
158
+ self.base_url = self.LIVE_BASE_URL
159
+
160
+ self.auth = (username, password)
161
+ self.parser = XmlParser()
162
+ self.serializer = XmlSerializer(config=SerializerConfig(indent=" "))
163
+
164
+ def _build_request(
165
+ self,
166
+ path: str,
167
+ data: Any = None,
168
+ params: dict | None = None,
169
+ extra_headers: dict[str, str] | None = None,
170
+ ) -> tuple[str, bytes | str | None, dict | None, dict[str, str]]:
171
+ """Return ``(url, content, params, headers)`` ready for ``httpx.request``.
172
+
173
+ Centralizes URL construction, XML body rendering (when ``data`` is a
174
+ dataclass), Content-Type header injection, and the drop-None pass on
175
+ query params (so resources can forward optional kwargs directly).
176
+ """
177
+ url = f"{self.base_url}/{path.lstrip('/')}"
178
+
179
+ content: bytes | str | None = None
180
+ headers: dict[str, str] = {}
181
+ if data is not None:
182
+ content = self.serializer.render(data)
183
+ headers["Content-Type"] = "application/xml"
184
+ if extra_headers:
185
+ headers.update(extra_headers)
186
+
187
+ if params is not None:
188
+ params = {k: v for k, v in params.items() if v is not None}
189
+ if not params:
190
+ params = None
191
+
192
+ return url, content, params, headers
193
+
194
+ def _raise_for_response(self, resp: httpx.Response) -> None:
195
+ """Raise the right exception type for a non-2xx response.
196
+
197
+ 401 → :class:`EpaPmAuthError`. Other non-2xx → :class:`EpaPmApiError`,
198
+ carrying ``errors`` parsed from a ``<response status="Error">`` body
199
+ when present so callers can branch on EPA error numbers without
200
+ regex'ing the message string.
201
+ """
202
+ if resp.status_code == 401:
203
+ raise EpaPmAuthError(resp.status_code, resp.text)
204
+
205
+ if 200 <= resp.status_code < 300:
206
+ return
207
+
208
+ errors: list[EpaErrorDetail] = []
209
+ message = resp.text
210
+ try:
211
+ parsed = self.parser.from_string(resp.text, Response)
212
+ if parsed and parsed.errors and parsed.errors.error:
213
+ errors = [
214
+ EpaErrorDetail(
215
+ error_number=_to_int(e.error_number),
216
+ error_description=e.error_description,
217
+ )
218
+ for e in parsed.errors.error
219
+ ]
220
+ message = "; ".join(f"{e.error_number}: {e.error_description}" for e in parsed.errors.error)
221
+ except Exception as exc:
222
+ # Body wasn't a parseable error envelope; fall through with raw text.
223
+ logger.debug("could not parse error envelope (status=%d): %s", resp.status_code, exc)
224
+
225
+ logger.warning(
226
+ "EPA PM %s %s -> %d: %s",
227
+ resp.request.method,
228
+ resp.request.url,
229
+ resp.status_code,
230
+ message,
231
+ )
232
+ raise EpaPmApiError(resp.status_code, message, errors=errors)
233
+
234
+ def _parse_typed(self, resp: httpx.Response, response_type: type[T]) -> T:
235
+ """Parse a 2xx body to the given dataclass type or raise on failure."""
236
+ if not resp.text:
237
+ raise EpaPmApiError(resp.status_code, "Expected response body but got empty response")
238
+ result = self.parser.from_string(resp.text, response_type)
239
+ if result is None:
240
+ raise EpaPmApiError(resp.status_code, "Failed to parse response")
241
+ return cast(T, result)
242
+
243
+ def _parse_polymorphic(self, resp: httpx.Response) -> Any:
244
+ """Parse a 2xx body to whichever dataclass matches the root element."""
245
+ if not resp.text:
246
+ raise EpaPmApiError(resp.status_code, "Expected response body but got empty response")
247
+ result = self.parser.from_string(resp.text)
248
+ if result is None:
249
+ raise EpaPmApiError(resp.status_code, "Failed to parse response")
250
+ return result
251
+
252
+
253
+ class EpaPmClient(_BaseClient):
254
+ """Sync client.
255
+
256
+ Use as a context manager (``with EpaPmClient(...) as c:``) to release
257
+ the connection pool on exit, or call :meth:`close` manually.
258
+ """
259
+
260
+ def __init__(
261
+ self,
262
+ username: str,
263
+ password: str,
264
+ base_url: str | None = None,
265
+ use_test_env: bool = False,
266
+ timeout: float | httpx.Timeout | None = None,
267
+ transport: httpx.BaseTransport | None = None,
268
+ http_client: httpx.Client | None = None,
269
+ retries: int | None = None,
270
+ retry: RetryConfig | None = None,
271
+ ):
272
+ """Construct a sync client.
273
+
274
+ Pass ``http_client`` to fully control the underlying ``httpx.Client``
275
+ (proxies, custom transports, mounts, event hooks); when supplied,
276
+ ``timeout``, ``transport``, ``retries``, and ``retry`` are ignored.
277
+ Otherwise the client builds its own ``httpx.Client`` with basic auth,
278
+ follow_redirects, the given timeout (default ``DEFAULT_TIMEOUT``
279
+ seconds), and an optional ``transport`` automatically wrapped with
280
+ :class:`RetryTransport`.
281
+
282
+ Retry behavior defaults to ``RetryConfig()`` (3 retries on 429/5xx
283
+ with exponential backoff). Pass ``retries=0`` to disable, ``retries=N``
284
+ to override just the attempt count, or ``retry=RetryConfig(...)`` for
285
+ full control.
286
+ """
287
+ super().__init__(username, password, base_url=base_url, use_test_env=use_test_env)
288
+
289
+ if http_client is not None:
290
+ self.client = http_client
291
+ self._owns_client = False
292
+ else:
293
+ transport = _wrap_transport_sync(transport, retries, retry)
294
+ self.client = httpx.Client(
295
+ auth=self.auth,
296
+ timeout=self.DEFAULT_TIMEOUT if timeout is None else timeout,
297
+ transport=transport,
298
+ follow_redirects=True,
299
+ )
300
+ self._owns_client = True
301
+
302
+ self.account = AccountResource(self)
303
+ self.association = AssociationResource(self)
304
+ self.building = BuildingResource(self)
305
+ self.consumption_data = ConsumptionDataResource(self)
306
+ self.custom_metric = CustomMetricResource(self)
307
+ self.customer = CustomerResource(self)
308
+ self.data_exchange = DataExchangeResource(self)
309
+ self.green_power = GreenPowerResource(self)
310
+ self.hey = HeyResource(self)
311
+ self.hierarchy = HierarchyResource(self)
312
+ self.identifier = IdentifierResource(self)
313
+ self.meter = MeterResource(self)
314
+ self.metrics = MetricsResource(self)
315
+ self.property = PropertyResource(self)
316
+ self.property_use = PropertyUseResource(self)
317
+ self.report = ReportResource(self)
318
+ self.share = ShareResource(self)
319
+ self.target_finder = TargetFinderResource(self)
320
+ self.verification = VerificationResource(self)
321
+ self.waste_data = WasteDataResource(self)
322
+
323
+ def close(self) -> None:
324
+ """Close the underlying HTTP client and release its connection pool.
325
+
326
+ Only closes a client that this instance constructed. If a custom
327
+ ``http_client`` was passed in at init, ownership stays with the
328
+ caller and ``close`` is a no-op.
329
+ """
330
+ if self._owns_client:
331
+ self.client.close()
332
+
333
+ def __enter__(self) -> EpaPmClient:
334
+ return self
335
+
336
+ def __exit__(self, exc_type: object, exc: object, tb: object) -> None:
337
+ self.close()
338
+
339
+ @overload
340
+ def _request(
341
+ self,
342
+ method: str,
343
+ path: str,
344
+ data: Any = None,
345
+ params: dict | None = None,
346
+ response_type: type[T] = ...,
347
+ extra_headers: dict[str, str] | None = None,
348
+ ) -> T: ...
349
+
350
+ @overload
351
+ def _request(
352
+ self,
353
+ method: str,
354
+ path: str,
355
+ data: Any = None,
356
+ params: dict | None = None,
357
+ response_type: None = None,
358
+ extra_headers: dict[str, str] | None = None,
359
+ ) -> None: ...
360
+
361
+ def _request(
362
+ self,
363
+ method: str,
364
+ path: str,
365
+ data: Any = None,
366
+ params: dict | None = None,
367
+ response_type: type[T] | None = None,
368
+ extra_headers: dict[str, str] | None = None,
369
+ ) -> T | None:
370
+ url, content, params, headers = self._build_request(path, data, params, extra_headers)
371
+ logger.debug("EPA PM %s %s params=%s", method, url, params)
372
+ resp = self.client.request(method, url, content=content, params=params, headers=headers)
373
+ self._raise_for_response(resp)
374
+ if response_type:
375
+ return self._parse_typed(resp, response_type)
376
+ return None
377
+
378
+ def _request_polymorphic(self, method: str, path: str) -> Any:
379
+ """GET-style request that auto-resolves the response to its concrete subtype.
380
+
381
+ Use this for endpoints whose response element name is not fixed —
382
+ e.g. ``GET /propertyUse/{id}`` returns ``<office>``, ``<hotel>``,
383
+ ``<vehicleDealership>``, etc. depending on the use type. xsdata's
384
+ ``XmlContext`` resolves the root element to the matching dataclass
385
+ when ``from_string`` is called without an explicit type.
386
+ """
387
+ url, _, _, _ = self._build_request(path)
388
+ logger.debug("EPA PM %s %s (polymorphic)", method, url)
389
+ resp = self.client.request(method, url)
390
+ self._raise_for_response(resp)
391
+ return self._parse_polymorphic(resp)
392
+
393
+
394
+ class EpaPmAsyncClient(_BaseClient):
395
+ """Async client backed by ``httpx.AsyncClient``.
396
+
397
+ Use as an async context manager (``async with EpaPmAsyncClient(...) as c:``)
398
+ to release the connection pool on exit, or call :meth:`aclose` manually.
399
+ All resource methods are coroutines and must be ``await``-ed.
400
+ """
401
+
402
+ def __init__(
403
+ self,
404
+ username: str,
405
+ password: str,
406
+ base_url: str | None = None,
407
+ use_test_env: bool = False,
408
+ timeout: float | httpx.Timeout | None = None,
409
+ transport: httpx.AsyncBaseTransport | None = None,
410
+ http_client: httpx.AsyncClient | None = None,
411
+ retries: int | None = None,
412
+ retry: RetryConfig | None = None,
413
+ ):
414
+ """Construct an async client. See :class:`EpaPmClient` for parameter docs."""
415
+ super().__init__(username, password, base_url=base_url, use_test_env=use_test_env)
416
+
417
+ if http_client is not None:
418
+ self.client = http_client
419
+ self._owns_client = False
420
+ else:
421
+ transport = _wrap_transport_async(transport, retries, retry)
422
+ self.client = httpx.AsyncClient(
423
+ auth=self.auth,
424
+ timeout=self.DEFAULT_TIMEOUT if timeout is None else timeout,
425
+ transport=transport,
426
+ follow_redirects=True,
427
+ )
428
+ self._owns_client = True
429
+
430
+ self.account = AsyncAccountResource(self)
431
+ self.association = AsyncAssociationResource(self)
432
+ self.building = AsyncBuildingResource(self)
433
+ self.consumption_data = AsyncConsumptionDataResource(self)
434
+ self.custom_metric = AsyncCustomMetricResource(self)
435
+ self.customer = AsyncCustomerResource(self)
436
+ self.data_exchange = AsyncDataExchangeResource(self)
437
+ self.green_power = AsyncGreenPowerResource(self)
438
+ self.hey = AsyncHeyResource(self)
439
+ self.hierarchy = AsyncHierarchyResource(self)
440
+ self.identifier = AsyncIdentifierResource(self)
441
+ self.meter = AsyncMeterResource(self)
442
+ self.metrics = AsyncMetricsResource(self)
443
+ self.property = AsyncPropertyResource(self)
444
+ self.property_use = AsyncPropertyUseResource(self)
445
+ self.report = AsyncReportResource(self)
446
+ self.share = AsyncShareResource(self)
447
+ self.target_finder = AsyncTargetFinderResource(self)
448
+ self.verification = AsyncVerificationResource(self)
449
+ self.waste_data = AsyncWasteDataResource(self)
450
+
451
+ async def aclose(self) -> None:
452
+ """Close the underlying ``httpx.AsyncClient`` (skipped if injected)."""
453
+ if self._owns_client:
454
+ await self.client.aclose()
455
+
456
+ async def __aenter__(self) -> EpaPmAsyncClient:
457
+ return self
458
+
459
+ async def __aexit__(self, exc_type: object, exc: object, tb: object) -> None:
460
+ await self.aclose()
461
+
462
+ @overload
463
+ async def _arequest(
464
+ self,
465
+ method: str,
466
+ path: str,
467
+ data: Any = None,
468
+ params: dict | None = None,
469
+ response_type: type[T] = ...,
470
+ extra_headers: dict[str, str] | None = None,
471
+ ) -> T: ...
472
+
473
+ @overload
474
+ async def _arequest(
475
+ self,
476
+ method: str,
477
+ path: str,
478
+ data: Any = None,
479
+ params: dict | None = None,
480
+ response_type: None = None,
481
+ extra_headers: dict[str, str] | None = None,
482
+ ) -> None: ...
483
+
484
+ async def _arequest(
485
+ self,
486
+ method: str,
487
+ path: str,
488
+ data: Any = None,
489
+ params: dict | None = None,
490
+ response_type: type[T] | None = None,
491
+ extra_headers: dict[str, str] | None = None,
492
+ ) -> T | None:
493
+ url, content, params, headers = self._build_request(path, data, params, extra_headers)
494
+ logger.debug("EPA PM %s %s params=%s", method, url, params)
495
+ resp = await self.client.request(method, url, content=content, params=params, headers=headers)
496
+ self._raise_for_response(resp)
497
+ if response_type:
498
+ return self._parse_typed(resp, response_type)
499
+ return None
500
+
501
+ async def _arequest_polymorphic(self, method: str, path: str) -> Any:
502
+ """Async equivalent of :meth:`EpaPmClient._request_polymorphic`."""
503
+ url, _, _, _ = self._build_request(path)
504
+ logger.debug("EPA PM %s %s (polymorphic)", method, url)
505
+ resp = await self.client.request(method, url)
506
+ self._raise_for_response(resp)
507
+ return self._parse_polymorphic(resp)
@@ -0,0 +1,67 @@
1
+ """Exception types raised by the client.
2
+
3
+ ``EpaPmApiError`` carries the raw HTTP details *and* the structured EPA
4
+ error payload when the body parses as ``<response status="Error">``. The
5
+ flattened message string is preserved for backwards compatibility, but
6
+ production callers should prefer ``error_number`` / ``errors`` for
7
+ branching.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from dataclasses import dataclass
13
+
14
+
15
+ @dataclass(frozen=True)
16
+ class EpaErrorDetail:
17
+ """One ``<error>`` element from an EPA error response."""
18
+
19
+ error_number: int | None
20
+ error_description: str | None
21
+
22
+
23
+ class EpaPmError(Exception):
24
+ """Base exception for EPA PM API Wrapper."""
25
+
26
+
27
+ class EpaPmApiError(EpaPmError):
28
+ """Exception raised for errors returned by the API.
29
+
30
+ :ivar status_code: HTTP status code.
31
+ :ivar response_text: Raw response body (XML or plain text).
32
+ :ivar errors: Parsed list of EPA ``<error>`` entries when the body was
33
+ a structured ``<response status="Error">`` payload; empty otherwise.
34
+ :ivar error_number: Convenience accessor for the *first* EPA error
35
+ number when there's exactly one error in the payload — handy for
36
+ ``except EpaPmApiError as e: if e.error_number == 10: ...``. Use
37
+ :attr:`errors` if multiple errors may be present.
38
+ """
39
+
40
+ def __init__(
41
+ self,
42
+ status_code: int,
43
+ response_text: str,
44
+ errors: list[EpaErrorDetail] | None = None,
45
+ ):
46
+ self.status_code = status_code
47
+ self.response_text = response_text
48
+ self.errors: list[EpaErrorDetail] = errors or []
49
+ super().__init__(f"API error {status_code}: {response_text}")
50
+
51
+ @property
52
+ def error_number(self) -> int | None:
53
+ """The EPA error number when exactly one error was reported, else ``None``."""
54
+ if len(self.errors) == 1:
55
+ return self.errors[0].error_number
56
+ return None
57
+
58
+
59
+ class EpaPmAuthError(EpaPmApiError):
60
+ """Exception raised for authentication errors."""
61
+
62
+ def __init__(self, status_code: int, response_text: str):
63
+ super().__init__(status_code, response_text)
64
+ self.args = (
65
+ "Authentication failed. Please check your credentials (username/password) and ensure "
66
+ f"you are targeting the correct environment (live vs test). Details: {response_text}",
67
+ )