diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 56c8a0df2..077b80f80 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,3 +41,9 @@ repos: rev: 0.13.0 hooks: - id: check-github-workflows + + - repo: https://github.com/asottile/pyupgrade + rev: v2.31.0 + hooks: + - id: pyupgrade + args: [--py37-plus] diff --git a/aiidalab_widgets_base/codes.py b/aiidalab_widgets_base/codes.py index 37959ca57..5a89231a5 100644 --- a/aiidalab_widgets_base/codes.py +++ b/aiidalab_widgets_base/codes.py @@ -254,7 +254,7 @@ def __init__(self, path_to_root="../", **kwargs): btn_setup_code, self._setup_code_out, ] - super(AiiDACodeSetup, self).__init__(children, **kwargs) + super().__init__(children, **kwargs) @validate("input_plugin") def _validate_input_plugin(self, proposal): diff --git a/aiidalab_widgets_base/computational_resources.py b/aiidalab_widgets_base/computational_resources.py index 05b051198..87fb286f0 100644 --- a/aiidalab_widgets_base/computational_resources.py +++ b/aiidalab_widgets_base/computational_resources.py @@ -853,10 +853,8 @@ def __init__(self, path_to_root="../", **kwargs): # Code plugin. self.input_plugin = ipw.Dropdown( options=sorted( - [ - (ep.name, ep) - for ep in plugins.entry_point.get_entry_points("aiida.calculations") - ] + (ep.name, ep) + for ep in plugins.entry_point.get_entry_points("aiida.calculations") ), description="Code plugin:", layout=LAYOUT, diff --git a/aiidalab_widgets_base/computers.py b/aiidalab_widgets_base/computers.py index 52e71d93d..986f011a5 100644 --- a/aiidalab_widgets_base/computers.py +++ b/aiidalab_widgets_base/computers.py @@ -171,7 +171,7 @@ def __init__(self, **kwargs): btn_setup_ssh, self._setup_ssh_out, ] - super(SshComputerSetup, self).__init__(children, **kwargs) + super().__init__(children, **kwargs) @staticmethod def _ssh_keygen(): @@ -297,8 +297,8 @@ def _send_pubkey(hostname, username, password, proxycmd=""): from pexpect import TIMEOUT timeout = 10 - print("Sending public key to {}... ".format(hostname), end="") - str_ssh = "ssh-copy-id {}@{}".format(username, hostname) + print(f"Sending public key to {hostname}... ", end="") + str_ssh = f"ssh-copy-id {username}@{hostname}" if proxycmd: str_ssh += ' -o "ProxyCommand ssh -q -Y ' + proxycmd + ' netcat %h %p\n"' child = pexpect.spawn(str_ssh) @@ -314,7 +314,7 @@ def _send_pubkey(hostname, username, password, proxycmd=""): timeout=timeout, ) # final except TIMEOUT: - print("Exceeded {} s timeout".format(timeout)) + print(f"Exceeded {timeout} s timeout") return False possible_output = { @@ -736,11 +736,11 @@ def __init__(self, **kwargs): ipw.HBox([btn_setup_comp, btn_test]), ipw.HBox([self._setup_comp_out, self._test_out]), ] - super(AiidaComputerSetup, self).__init__(children, **kwargs) + super().__init__(children, **kwargs) def _configure_computer(self): """Create AuthInfo.""" - print("Configuring '{}'".format(self.label)) + print(f"Configuring '{self.label}'") sshcfg = parse_sshconfig(self.hostname) authparams = { "compress": True, diff --git a/aiidalab_widgets_base/databases.py b/aiidalab_widgets_base/databases.py index 66faa6433..f2b9331d9 100644 --- a/aiidalab_widgets_base/databases.py +++ b/aiidalab_widgets_base/databases.py @@ -66,7 +66,7 @@ def __init__(self, title="", **kwargs): self.query_message, ipw.HBox([self.drop_structure, self.link]), ] - super(CodQueryWidget, self).__init__(children=children, **kwargs) + super().__init__(children=children, **kwargs) @staticmethod def _query(idn=None, formula=None): @@ -106,7 +106,7 @@ def _on_click_query(self, change): # pylint: disable=unused-argument ) structures.append(entry_add) - self.query_message.value += "{} structures found".format(len(structures) - 1) + self.query_message.value += f"{len(structures) - 1} structures found" self.drop_structure.options = structures def _on_select_structure(self, change): @@ -462,10 +462,10 @@ def _reset(self, _=None): def clean_up_database(self, database, plugin): for domain in list(database.keys()): - for computer in list(database[domain].keys() - set(["default"])): + for computer in list(database[domain].keys() - {"default"}): for code in list( database[domain][computer].keys() - - set(["computer-configure", "computer-setup"]) + - {"computer-configure", "computer-setup"} ): if plugin != database[domain][computer][code]["input_plugin"]: del database[domain][computer][code] @@ -473,18 +473,18 @@ def clean_up_database(self, database, plugin): if ( len( database[domain][computer].keys() - - set(["computer-configure", "computer-setup"]) + - {"computer-configure", "computer-setup"} ) == 0 ): del database[domain][computer] # If no computers remained - remove the domain. - if len(database[domain].keys() - set(["default"])) == 0: + if len(database[domain].keys() - {"default"}) == 0: del database[domain] # Making sure the 'default' key still points to an existing computer. elif database[domain]["default"] not in database[domain]: database[domain]["default"] = sorted( - database[domain].keys() - set(["default"]) + database[domain].keys() - {"default"} )[0] return database diff --git a/aiidalab_widgets_base/elns.py b/aiidalab_widgets_base/elns.py index 6fad47d64..6565f6bea 100644 --- a/aiidalab_widgets_base/elns.py +++ b/aiidalab_widgets_base/elns.py @@ -19,7 +19,7 @@ def connect_to_eln(eln_instance=None, **kwargs): # assuming that the connection can only be established to the ELNs # with the stored configuration. try: - with open(ELN_CONFIG, "r") as file: + with open(ELN_CONFIG) as file: config = json.load(file) except (FileNotFoundError, json.JSONDecodeError, KeyError): return ( @@ -235,7 +235,7 @@ def write_to_config(self, config): def get_config(self): try: - with open(ELN_CONFIG, "r") as file: + with open(ELN_CONFIG) as file: return json.load(file) except (FileNotFoundError, json.JSONDecodeError, KeyError): return {} diff --git a/aiidalab_widgets_base/export.py b/aiidalab_widgets_base/export.py index 16e1b87b5..69a849fef 100644 --- a/aiidalab_widgets_base/export.py +++ b/aiidalab_widgets_base/export.py @@ -11,11 +11,11 @@ class ExportButtonWidget(Button): def __init__(self, process, **kwargs): self.process = process if "description" not in kwargs: - kwargs["description"] = "Export workflow ({})".format(self.process.id) + kwargs["description"] = f"Export workflow ({self.process.id})" if "layout" not in kwargs: kwargs["layout"] = {} kwargs["layout"]["width"] = "initial" - super(ExportButtonWidget, self).__init__(**kwargs) + super().__init__(**kwargs) self.on_click(self.export_aiida_subgraph) def export_aiida_subgraph(self, change=None): # pylint: disable=unused-argument @@ -42,7 +42,7 @@ def export_aiida_subgraph(self, change=None): # pylint: disable=unused-argument link.click(); document.body.removeChild(link); """.format( - payload=payload, filename="export_{}.aiida".format(self.process.id) + payload=payload, filename=f"export_{self.process.id}.aiida" ) ) display(javas) diff --git a/aiidalab_widgets_base/process.py b/aiidalab_widgets_base/process.py index ab4410a4f..62f8d30f5 100644 --- a/aiidalab_widgets_base/process.py +++ b/aiidalab_widgets_base/process.py @@ -210,7 +210,7 @@ def show_selected_input(self, change=None): clear_output() if change["new"]: selected_input = self.process.inputs[change["new"]] - self.info.value = "PK: {}".format(selected_input.id) + self.info.value = f"PK: {selected_input.id}" display(viewer(selected_input)) @@ -247,7 +247,7 @@ def show_selected_output(self, change=None): clear_output() if change["new"]: selected_output = self.process.outputs[change["new"]] - self.info.value = "PK: {}".format(selected_output.id) + self.info.value = f"PK: {selected_output.id}" display(viewer(selected_output)) @@ -278,7 +278,7 @@ def __init__( self.followers.append( ipw.VBox( [ - ipw.HTML("

{}

".format(follower.title)), + ipw.HTML(f"

{follower.title}

"), follower, ] ) @@ -347,7 +347,7 @@ def update(self): elif isinstance(self.process, (CalcFunctionNode, WorkFunctionNode)): string = get_process_function_report(self.process) else: - string = "Nothing to show for node type {}".format(self.process.__class__) + string = f"Nothing to show for node type {self.process.__class__}" self.value = string.replace("\n", "
") @@ -375,7 +375,7 @@ def calc_info(self, node): """Return a string with the summary of the state of a CalculationNode.""" if not isinstance(node, ProcessNode): - raise TypeError("Unknown type: {}".format(type(node))) + raise TypeError(f"Unknown type: {type(node)}") process_state = node.process_state.value.capitalize() pk = """{1}""".format( @@ -387,10 +387,10 @@ def calc_info(self, node): node.process_label, pk, process_state, node.exit_status ) else: - string = "{}<{}> {}".format(node.process_label, pk, process_state) + string = f"{node.process_label}<{pk}> {process_state}" if isinstance(node, WorkChainNode) and node.stepper_state_info: - string += " [{}]".format(node.stepper_state_info) + string += f" [{node.stepper_state_info}]" return string @@ -655,7 +655,7 @@ def update(self, _=None): if self.description_contains: dataf = dataf[dataf.Description.str.contains(self.description_contains)] - self.output.value = "{} processes shown".format(len(dataf)) + self.output.value = f"{len(dataf)} processes shown" # Add HTML links. dataf["PK"] = dataf["PK"].apply( diff --git a/aiidalab_widgets_base/structures.py b/aiidalab_widgets_base/structures.py index d68d7bd39..805e6479d 100644 --- a/aiidalab_widgets_base/structures.py +++ b/aiidalab_widgets_base/structures.py @@ -223,7 +223,7 @@ def user_modifications(source_structure): # pylint: disable=unused-argument else: structure_node = self.structure_node.store() - self.output.value = "Stored in AiiDA [{}]".format(structure_node) + self.output.value = f"Stored in AiiDA [{structure_node}]" def undo(self, _): """Undo modifications.""" @@ -594,10 +594,10 @@ def search(self, _=None): matches = sorted(matches, reverse=True, key=lambda n: n.ctime) options = OrderedDict() - options["Select a Structure ({} found)".format(len(matches))] = False + options[f"Select a Structure ({len(matches)} found)"] = False for mch in matches: - label = "PK: {}".format(mch.id) + label = f"PK: {mch.id}" label += " | " + mch.ctime.strftime("%Y-%m-%d %H:%M") label += " | " + mch.get_extra("formula") label += " | " + mch.node_type.split(".")[-2] diff --git a/aiidalab_widgets_base/utils/__init__.py b/aiidalab_widgets_base/utils/__init__.py index e7f5fdf30..a50b8b71d 100644 --- a/aiidalab_widgets_base/utils/__init__.py +++ b/aiidalab_widgets_base/utils/__init__.py @@ -24,7 +24,7 @@ def predefine_settings(obj, **kwargs): if hasattr(obj, key): setattr(obj, key, value) else: - raise AttributeError("'{}' object has no attirubte '{}'".format(obj, key)) + raise AttributeError(f"'{obj}' object has no attirubte '{key}'") def get_ase_from_file(fname, format=None): # pylint: disable=redefined-builtin @@ -34,14 +34,12 @@ def get_ase_from_file(fname, format=None): # pylint: disable=redefined-builtin else: traj = read(fname, format=format, index=":") if not traj: - print(("Could not read any information from the file {}".format(fname))) + print(f"Could not read any information from the file {fname}") return False if len(traj) > 1: print( - ( - "Warning: Uploaded file {} contained more than one structure. Selecting the first one.".format( - fname - ) + "Warning: Uploaded file {} contained more than one structure. Selecting the first one.".format( + fname ) ) return traj[0] diff --git a/aiidalab_widgets_base/viewers.py b/aiidalab_widgets_base/viewers.py index c147d418f..01ee596e9 100644 --- a/aiidalab_widgets_base/viewers.py +++ b/aiidalab_widgets_base/viewers.py @@ -63,9 +63,7 @@ def viewer(obj, downloadable=True, **kwargs): Returns the object itself if the viewer wasn't found.""" if not isinstance(obj, Node): # only working with AiiDA nodes - warnings.warn( - "This viewer works only with AiiDA objects, got {}".format(type(obj)) - ) + warnings.warn(f"This viewer works only with AiiDA objects, got {type(obj)}") return obj try: @@ -146,7 +144,7 @@ def __init__(self, parameter, downloadable=True, **kwargs): # this is used to setup table's appearance using CSS if downloadable: payload = base64.b64encode(dataf.to_csv(index=False).encode()).decode() - fname = "{}.csv".format(parameter.pk) + fname = f"{parameter.pk}.csv" to_add = """Download table in csv format: {title}""" self.value += to_add.format(filename=fname, payload=payload, title=fname) @@ -356,9 +354,9 @@ def _observe_cell(self, _=None): self.cell.lengths()[2] ) - self.cell_alpha.value = "α: {:.4f}".format(self.cell.angles()[0]) - self.cell_beta.value = "β: {:.4f}".format(self.cell.angles()[1]) - self.cell_gamma.value = "γ: {:.4f}".format(self.cell.angles()[2]) + self.cell_alpha.value = f"α: {self.cell.angles()[0]:.4f}" + self.cell_beta.value = f"β: {self.cell.angles()[1]:.4f}" + self.cell_gamma.value = f"γ: {self.cell.angles()[2]:.4f}" else: self.cell_a.value = "a:" self.cell_b.value = "b:" @@ -1103,7 +1101,7 @@ def __init__(self, bands, **kwargs): x_data = [plot_info["x"] for i in range(len(y_data))] labels = plot_info["labels"] # Create the figure - plot = figure(y_axis_label="Dispersion ({})".format(bands.units)) + plot = figure(y_axis_label=f"Dispersion ({bands.units})") plot.multi_line( x_data, y_data, line_width=2, line_color="red" ) # pylint: disable=too-many-function-args diff --git a/aiidalab_widgets_base/wizard.py b/aiidalab_widgets_base/wizard.py index c13d49561..21f2fc30b 100644 --- a/aiidalab_widgets_base/wizard.py +++ b/aiidalab_widgets_base/wizard.py @@ -83,9 +83,7 @@ def icons(cls): """Return the icon set and return animated icons based on the current time stamp.""" t = time() return { - key: item - if isinstance(item, str) - else item[int((t * len(item) % len(item)))] + key: item if isinstance(item, str) else item[int(t * len(item) % len(item))] for key, item in cls.ICONS.items() } diff --git a/docs/source/conf.py b/docs/source/conf.py index fdf1e8155..3d255c7e4 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -62,7 +62,7 @@ copyright_year_string = ( current_year if current_year == copyright_first_year - else "{}-{}".format(copyright_first_year, current_year) + else f"{copyright_first_year}-{current_year}" ) copyright = "{}, {}. All rights reserved".format( copyright_year_string, copyright_owners diff --git a/setup.py b/setup.py index 59b746b49..59482487d 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,3 @@ -# -*- coding: utf8 -*- """This file is required for editable installs of the package.""" from setuptools import setup