Skip to content

Commit 72e80b4

Browse files
code satisfies UP rules (#513)
* fix UP rules * fix typing union on py39 * fix * fix round * fix union typing * fix round * add eval-type-backport = {version = "^0.2.0", python = "3.9"}
1 parent 580f8f8 commit 72e80b4

40 files changed

+174
-186
lines changed

archetypal/__init__.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
# License: MIT, see full license in LICENSE.txt
55
# Web: https://github.com/samuelduchesne/archetypal
66
################################################################################
7+
from __future__ import annotations
8+
79
import logging as lg
810
from pathlib import Path
9-
from typing import Any, ClassVar, List, Literal, Optional
11+
from typing import Any, ClassVar, Literal
1012

1113
from energy_pandas.units import unit_registry
1214

@@ -67,7 +69,7 @@ class Settings(BaseSettings, arbitrary_types_allowed=True, validate_assignment=T
6769
log_filename: str = Field("archetypal")
6870

6971
# usual idfobjects
70-
useful_idf_objects: List[str] = Field(
72+
useful_idf_objects: list[str] = Field(
7173
[
7274
"WINDOWMATERIAL:GAS",
7375
"WINDOWMATERIAL:GLAZING",
@@ -169,7 +171,7 @@ class Settings(BaseSettings, arbitrary_types_allowed=True, validate_assignment=T
169171
"for ENERGYPLUS_VERSION in os.environ",
170172
)
171173

172-
energyplus_location: Optional[DirectoryPath] = Field(
174+
energyplus_location: DirectoryPath | None = Field(
173175
None,
174176
validation_alias="ENERGYPLUS_LOCATION",
175177
description="Root directory of the EnergyPlus install.",

archetypal/eplus_interface/energy_plus.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ def success_callback(self):
255255
pass
256256
else:
257257
log(
258-
"Files generated at the end of the simulation: %s" % "\n".join(save_dir.files()),
258+
"Files generated at the end of the simulation: {}".format("\n".join(save_dir.files())),
259259
lg.DEBUG,
260260
name=self.name,
261261
)

archetypal/eplus_interface/exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class EnergyPlusVersionError(Exception):
3636
"""EnergyPlus Version call error"""
3737

3838
def __init__(self, msg=None, idf_file=None, idf_version=None, ep_version=None):
39-
super(EnergyPlusVersionError, self).__init__(None)
39+
super().__init__(None)
4040
self.msg = msg
4141
self.idf_file = idf_file
4242
self.idf_version = idf_version

archetypal/eplus_interface/transition.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,7 @@ def transitions(self) -> list:
116116
@property
117117
def transitions_generator(self):
118118
"""Generate transitions."""
119-
for transition in self.transitions:
120-
yield transition
119+
yield from self.transitions
121120

122121
def __str__(self):
123122
"""Return string representation."""
@@ -143,7 +142,7 @@ class TransitionThread(Thread):
143142

144143
def __init__(self, idf, tmp, overwrite=False):
145144
"""Initialize Thread."""
146-
super(TransitionThread, self).__init__()
145+
super().__init__()
147146
self.overwrite = overwrite
148147
self.p = None
149148
self.std_out = None

archetypal/eplus_interface/version.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def __init__(self, version):
6060
version = ".".join(map(str, (version.major, version.minor, version.micro)))
6161
if isinstance(version, str) and "-" in version:
6262
version = version.replace("-", ".")
63-
super(EnergyPlusVersion, self).__init__(version)
63+
super().__init__(version)
6464
if self.dash not in self.valid_versions:
6565
raise InvalidEnergyPlusVersion()
6666

@@ -228,8 +228,8 @@ def get_eplus_basedirs():
228228
return Path("/Applications").dirs("EnergyPlus*")
229229
else:
230230
warnings.warn(
231-
"Archetypal is not compatible with %s. It is only compatible "
232-
"with Windows, Linux or MacOs" % platform.system()
231+
f"Archetypal is not compatible with {platform.system()}. It is only compatible "
232+
"with Windows, Linux or MacOs"
233233
)
234234

235235

archetypal/idfclass/extensions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def makedict(self: Eplusdata, dictfile, fnamefobject):
112112
# scream
113113
if node == "":
114114
continue
115-
log("this node -%s-is not present in base dictionary" % node)
115+
log(f"this node -{node}-is not present in base dictionary")
116116

117117
self.dt, self.dtls = dt, dtls
118118
return dt, dtls

archetypal/idfclass/idf.py

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@
2020
import uuid
2121
import warnings
2222
from collections import defaultdict
23+
from collections.abc import Iterable
2324
from io import IOBase, StringIO
2425
from itertools import chain
2526
from math import isclose
26-
from typing import IO, Iterable, Literal, Optional, Tuple, Union
27+
from typing import IO, ClassVar, Literal
2728

28-
from typing_extensions import ClassVar
29+
import numpy as np
30+
from sigfig import round
2931

3032
ReportingFrequency = Literal["Annual", "Monthly", "Daily", "Hourly", "Timestep"]
3133

@@ -205,13 +207,13 @@ def __set_on_dependencies(self, key, value):
205207
if key in self._independant_vars:
206208
self._reset_dependant_vars(key)
207209
key = f"_{key}"
208-
super(IDF, self).__setattr__(key, value)
210+
super().__setattr__(key, value)
209211

210212
def __init__(
211213
self,
212-
idfname: Optional[Union[str, IO, Path]] = None,
214+
idfname: str | IO | Path | None = None,
213215
epw=None,
214-
as_version: Union[str, EnergyPlusVersion] = None,
216+
as_version: str | EnergyPlusVersion = None,
215217
annual=False,
216218
design_day=False,
217219
expandobjects=False,
@@ -230,7 +232,7 @@ def __init__(
230232
output_directory=None,
231233
outputtype="standard",
232234
encoding=None,
233-
iddname: Optional[Union[str, IO, Path]] = None,
235+
iddname: str | IO | Path | None = None,
234236
reporting_frequency: ReportingFrequency = "Monthly",
235237
**kwargs,
236238
):
@@ -617,7 +619,7 @@ def output_suffix(self, value):
617619
self._output_suffix = value
618620

619621
@property
620-
def idfname(self) -> Union[Path, StringIO]:
622+
def idfname(self) -> Path | StringIO:
621623
"""Path: The path of the active (parsed) idf model."""
622624
if self._idfname is None:
623625
if self.as_version is None:
@@ -834,7 +836,7 @@ def sim_id(self) -> str:
834836

835837
# endregion
836838
@property
837-
def sim_info(self) -> Optional[DataFrame]:
839+
def sim_info(self) -> DataFrame | None:
838840
"""DataFrame: Unique number generated for a simulation."""
839841
if self.sql_file is not None:
840842
with sqlite3.connect(self.sql_file) as conn:
@@ -845,7 +847,7 @@ def sim_info(self) -> Optional[DataFrame]:
845847
return None
846848

847849
@property
848-
def sim_timestamp(self) -> Union[str, Series]:
850+
def sim_timestamp(self) -> str | Series:
849851
"""Return the simulation timestamp or "Never" if not ran yet."""
850852
if self.sim_info is None:
851853
return "Never"
@@ -1488,7 +1490,7 @@ def savecopy(self, filename, lineendings="default", encoding="latin-1"):
14881490
Returns:
14891491
Path: The new file path.
14901492
"""
1491-
super(IDF, self).save(filename, lineendings, encoding)
1493+
super().save(filename, lineendings, encoding)
14921494
return Path(filename)
14931495

14941496
def copy(self):
@@ -1515,7 +1517,7 @@ def save(self, lineendings="default", encoding="latin-1", **kwargs):
15151517
Returns:
15161518
IDF: The IDF model
15171519
"""
1518-
super(IDF, self).save(filename=self.idfname, lineendings=lineendings, encoding=encoding)
1520+
super().save(filename=self.idfname, lineendings=lineendings, encoding=encoding)
15191521
log(f"saved '{self.name}' at '{self.idfname}'")
15201522
return self
15211523

@@ -1538,7 +1540,7 @@ def saveas(self, filename, lineendings="default", encoding="latin-1", inplace=Fa
15381540
Returns:
15391541
IDF: A new IDF object based on the new location file.
15401542
"""
1541-
super(IDF, self).save(filename=filename, lineendings=lineendings, encoding=encoding)
1543+
super().save(filename=filename, lineendings=lineendings, encoding=encoding)
15421544

15431545
import inspect
15441546

@@ -1719,7 +1721,6 @@ def wwr(self, azimuth_threshold=10, round_to=10):
17191721

17201722
def roundto(x, to=10.0):
17211723
"""Round up to closest `to` number."""
1722-
from builtins import round
17231724

17241725
if to and not math.isnan(x):
17251726
return int(round(x / to)) * to
@@ -1754,7 +1755,6 @@ def roundto(x, to=10.0):
17541755

17551756
# Create dataframe with wall_area, window_area and wwr as columns and azimuth
17561757
# as indexes
1757-
from sigfig import round
17581758

17591759
df = (
17601760
pd.DataFrame({"wall_area": total_surface_area, "window_area": total_window_area})
@@ -1763,8 +1763,15 @@ def roundto(x, to=10.0):
17631763
)
17641764
df.wall_area = df.wall_area.apply(round, decimals=1)
17651765
df.window_area = df.window_area.apply(round, decimals=1)
1766-
df["wwr"] = (df.window_area / df.wall_area).fillna(0).apply(round, 2)
1767-
df["wwr_rounded_%"] = (df.window_area / df.wall_area * 100).fillna(0).apply(lambda x: roundto(x, to=round_to))
1766+
df["wwr"] = (
1767+
(df.window_area / df.wall_area).replace([np.inf, -np.inf], np.nan).fillna(0).apply(round, decimals=2)
1768+
)
1769+
df["wwr_rounded_%"] = (
1770+
(df.window_area / df.wall_area * 100)
1771+
.replace([np.inf, -np.inf], np.nan)
1772+
.fillna(0)
1773+
.apply(lambda x: roundto(x, to=round_to))
1774+
)
17681775
return df
17691776

17701777
def space_heating_profile(
@@ -1897,7 +1904,7 @@ def custom_profile(
18971904
log(f"Retrieved {name} in {time.time() - start_time:,.2f} seconds")
18981905
return series
18991906

1900-
def newidfobject(self, key, **kwargs) -> Optional[EpBunch]:
1907+
def newidfobject(self, key, **kwargs) -> EpBunch | None:
19011908
"""Define EpBunch object and add to model.
19021909
19031910
The function will test if the object exists to prevent duplicates.
@@ -2040,7 +2047,7 @@ def anidfobject(self, key: str, aname: str = "", **kwargs) -> EpBunch:
20402047
abunch = obj2bunch(self.model, self.idd_info, obj)
20412048
if aname:
20422049
warnings.warn(
2043-
"The aname parameter should no longer be used (%s)." % aname,
2050+
f"The aname parameter should no longer be used ({aname}).",
20442051
UserWarning,
20452052
)
20462053
namebunch(abunch, aname)
@@ -2247,7 +2254,7 @@ def set_wwr(
22472254
# reviewed as of 2021-11-10.
22482255

22492256
try:
2250-
ggr: Optional[Idf_MSequence] = self.idfobjects["GLOBALGEOMETRYRULES"][0]
2257+
ggr: Idf_MSequence | None = self.idfobjects["GLOBALGEOMETRYRULES"][0]
22512258
except IndexError:
22522259
ggr = None
22532260

@@ -2275,12 +2282,12 @@ def set_wwr(
22752282
continue
22762283
# remove all subsurfaces
22772284
for ss in wall_subsurfaces:
2278-
self.rename(ss.key.upper(), ss.Name, "%s window" % wall.Name)
2285+
self.rename(ss.key.upper(), ss.Name, f"{wall.Name} window")
22792286
self.removeidfobject(ss)
22802287
coords = window_vertices_given_wall(wall, wwr)
22812288
window = self.newidfobject(
22822289
"FENESTRATIONSURFACE:DETAILED",
2283-
Name="%s window" % wall.Name,
2290+
Name=f"{wall.Name} window",
22842291
Surface_Type="Window",
22852292
Construction_Name=construction or "",
22862293
Building_Surface_Name=wall.Name,
@@ -2492,7 +2499,7 @@ def coords_are_truly_relative(self):
24922499
all_zone_origin_at_0 = False
24932500
return ggr_asks_for_relative and not all_zone_origin_at_0
24942501

2495-
def rotate(self, angle: Optional[float] = None, anchor: Tuple[float, float, float] | None = None):
2502+
def rotate(self, angle: float | None = None, anchor: tuple[float, float, float] | None = None):
24962503
"""Rotate the IDF counterclockwise around `anchor` by the angle given (degrees).
24972504
24982505
IF angle is None, rotates to Direction_of_Relative_North specified in Zone
@@ -2512,7 +2519,7 @@ def rotate(self, angle: Optional[float] = None, anchor: Tuple[float, float, floa
25122519

25132520
anchor = Vector3D(*anchor)
25142521
# Rotate the building
2515-
super(IDF, self).rotate(angle, anchor=anchor)
2522+
super().rotate(angle, anchor=anchor)
25162523
log(f"Geometries rotated by {angle} degrees around " f"{anchor or 'building centroid'}")
25172524

25182525
# after building is rotate, change the north axis and zone direction to zero.
@@ -2522,14 +2529,14 @@ def rotate(self, angle: Optional[float] = None, anchor: Tuple[float, float, floa
25222529
# Mark the model as rotated
25232530
self.rotated = True
25242531

2525-
def translate(self, vector: Tuple[float, float, float]):
2532+
def translate(self, vector: tuple[float, float, float]):
25262533
"""Move the IDF in the direction given by a vector."""
25272534
if isinstance(vector, tuple):
25282535
from geomeppy.geom.vectors import Vector2D
25292536

25302537
vector = Vector2D(*vector)
25312538

2532-
super(IDF, self).translate(vector=vector)
2539+
super().translate(vector=vector)
25332540
self.translated = True
25342541

25352542
@property
@@ -2612,13 +2619,13 @@ def _process_csv(file, working_dir, simulname):
26122619
tables_out.makedirs_p()
26132620
file.copy(tables_out / "%s_%s.csv" % (file.basename().stripext(), simulname))
26142621
return
2615-
log("try to store file %s in DataFrame" % file)
2622+
log(f"try to store file {file} in DataFrame")
26162623
try:
26172624
df = pd.read_csv(file, sep=",", encoding="us-ascii")
26182625
except ParserError:
26192626
pass
26202627
else:
2621-
log("file %s stored" % file)
2628+
log(f"file {file} stored")
26222629
return df
26232630

26242631

archetypal/idfclass/outputs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Iterable
1+
from collections.abc import Iterable
22

33
from archetypal.idfclass.end_use_balance import EndUseBalance
44
from archetypal.idfclass.extensions import get_name_attribute

archetypal/idfclass/sql.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@
33
from __future__ import annotations
44

55
import logging
6+
from collections.abc import Sequence
67
from datetime import timedelta
78
from sqlite3 import connect
8-
from typing import List, Optional, Sequence, Union
9+
from typing import Literal
910

1011
import numpy as np
1112
import pandas as pd
1213
from energy_pandas import EnergyDataFrame
1314
from pandas import to_datetime
1415
from path import Path
15-
from typing_extensions import Literal
1616

1717
from archetypal.utils import log
1818

@@ -82,7 +82,7 @@ def values(self, environment_type: int = 3, units: str | None = None) -> EnergyD
8282
class _SqlOutputs:
8383
"""Represents all the available outputs from the Sql file."""
8484

85-
def __init__(self, file_path: str, available_outputs: List[tuple]):
85+
def __init__(self, file_path: str, available_outputs: list[tuple]):
8686
self._available_outputs = available_outputs
8787
self._properties = {}
8888

@@ -148,7 +148,7 @@ def tabular_data_keys(self):
148148
return self._tabular_data_keys
149149

150150
@property
151-
def available_outputs(self) -> List[tuple]:
151+
def available_outputs(self) -> list[tuple]:
152152
"""Get tuples (OutputName, ReportingFrequency) that can be requested.
153153
154154
Any of these outputs when input to data_collections_by_output_name will
@@ -229,9 +229,9 @@ def full_html_report(self):
229229

230230
def timeseries_by_name(
231231
self,
232-
variable_or_meter: Union[str, Sequence],
233-
reporting_frequency: Union[_REPORTING_FREQUENCIES] = "Hourly",
234-
environment_type: Union[Literal[1, 2, 3]] = 3,
232+
variable_or_meter: str | Sequence,
233+
reporting_frequency: _REPORTING_FREQUENCIES = "Hourly",
234+
environment_type: Literal[1, 2, 3] = 3,
235235
) -> EnergyDataFrame:
236236
"""Get an EnergyDataFrame for specified meters and/or variables.
237237
@@ -325,7 +325,7 @@ def timeseries_by_name(
325325
return data
326326

327327
def tabular_data_by_name(
328-
self, report_name: str, table_name: str, report_for_string: Optional[str] = None
328+
self, report_name: str, table_name: str, report_for_string: str | None = None
329329
) -> pd.DataFrame:
330330
"""Get (ReportName, TableName) data as DataFrame.
331331
@@ -371,7 +371,7 @@ def tabular_data_by_name(
371371
pivoted = pivoted.apply(pd.to_numeric, errors="ignore")
372372
return pivoted
373373

374-
def _extract_available_outputs(self) -> List:
374+
def _extract_available_outputs(self) -> list:
375375
"""Extract the list of all available outputs from the SQLite file."""
376376
with connect(self.file_path) as conn:
377377
cols = "Name, ReportingFrequency"

0 commit comments

Comments
 (0)