Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove remaining Python 2 support #187

Merged
merged 17 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# pyupgrade
d2a29a2c36b92d1e77ac291a42ece5d8a455a69b
0f081e455c6082b8f43bdc1ce8d03359e13cf5be
fec69ce479a84bac8270b5f1c95ae6344c9f797a
59dc3c129b40a7992b5d1fab5e5f04705662f71a
2d7173ec9277da9eb59982c03c7a6e4e06a49759
7cfe37c6e20df0417248451dd919aeabaed1349a
b8563af7487d4ea9cda48d5beb49b7354feda5db
26b7b0c40d317341168090353f85e87e1d9b9f51
c2ffbb7204424f6af32bb8f150e86c8f51bd9eb9
55f776114a9b5ef96d2504e1118ee74d75f34cc0
160475c6680a33a0c57535e7275cc6dad473c4ef
0419e92e29ecb98eec10cbd2534022563dbf44e5
6048a44d34a9398bda910563f5f85f1a43714319
328b8843108c427c6153d2e3e2bf32ce41682433
20 changes: 20 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
fail_fast: false
repos:
- repo: meta
hooks:
- id: check-hooks-apply
- id: check-useless-excludes
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: "v4.6.0"
hooks:
- id: check-yaml
- repo: https://github.com/asottile/pyupgrade
rev: v3.16.0
hooks:
- id: pyupgrade
args: [--py37-plus]
- repo: https://github.com/Mateusz-Grzelinski/actionlint-py
rev: "v1.7.1.15"
hooks:
- id: actionlint
1 change: 0 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# exdir documentation build configuration file, created by
# sphinx-quickstart on Fri Feb 3 09:52:17 2017.
Expand Down
1 change: 0 additions & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,4 @@ dependencies:
- pytest
- pytest-benchmark
- h5py
- six
- pandas
24 changes: 10 additions & 14 deletions examples/axona_to_exdir.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
from __future__ import division
from __future__ import print_function
from __future__ import with_statement

import sys
import quantities as pq
import os
Expand Down Expand Up @@ -43,7 +39,7 @@ def parse_header_and_leave_cursor(file_handle):
header += str(byte, 'latin-1')

if not byte:
raise IOError("Hit end of file '" + eeg_filename + "'' before '" + search_string + "' found.")
raise OSError("Hit end of file '" + eeg_filename + "'' before '" + search_string + "' found.")

if header[-len(search_string):] == search_string:
break
Expand Down Expand Up @@ -88,7 +84,7 @@ def __init__(self, filename):
if extension != ".set":
raise ValueError("file extension must be '.set'")

with open(self._absolute_filename, "r") as f:
with open(self._absolute_filename) as f:
text = f.read()

params = parse_params(text)
Expand Down Expand Up @@ -118,7 +114,7 @@ def __init__(self, filename):
for i in range(num_chans):
channel_id = self._channel_count + i
channel_ids.append(channel_id)
channel_names.append("channel_{}_group_{}_internal_{}".format(channel_id, group_id, i))
channel_names.append(f"channel_{channel_id}_group_{group_id}_internal_{i}")

channel_index = {"group_id": group_id,
"channel_names": np.array(channel_names, dtype="S"),
Expand All @@ -143,7 +139,7 @@ def __init__(self, filename):
def _channel_gain(self, channel_group_index, channel_index):
# TODO split into two functions, one for mapping and one for gain lookup
global_channel_index = channel_group_index * 4 + channel_index
param_name = "gain_ch_{}".format(global_channel_index)
param_name = f"gain_ch_{global_channel_index}"
return float(self._params[param_name])

def read_epoch():
Expand Down Expand Up @@ -217,7 +213,7 @@ def read_tracking(self):
# TODO store attributes, such as pixels_per_metre
pos_filename = os.path.join(self._path, self._base_filename+".pos")
if not os.path.exists(pos_filename):
raise IOError("'.pos' file not found:" + pos_filename)
raise OSError("'.pos' file not found:" + pos_filename)

with open(pos_filename, "rb") as f:
params = parse_header_and_leave_cursor(f)
Expand Down Expand Up @@ -296,7 +292,7 @@ def read_analogsignal(self,
elif file_type == "egf":
sample_count = int(params["num_EGF_samples"])
else:
raise IOError("Unknown file type. Should be .eeg or .efg.")
raise OSError("Unknown file type. Should be .eeg or .efg.")

sample_rate_split = params["sample_rate"].split(" ")
bytes_per_sample = params["bytes_per_sample"]
Expand All @@ -323,7 +319,7 @@ def read_analogsignal(self,

params["channel_id"] = eeg_original_channel_id

gain = self._params["gain_ch_{}".format(eeg_final_channel_id)]
gain = self._params[f"gain_ch_{eeg_final_channel_id}"]

signal = scale_analog_signal(data,
gain,
Expand Down Expand Up @@ -402,12 +398,12 @@ def set_subject_attrs():
# TODO for each channel_group, create LFP

for channel_index in axona_folder._channel_indexes:
channel_group = processing.create_group("channel_group_{}".format(channel_index["group_id"]))
channel_group = processing.create_group(f"channel_group_{channel_index['group_id']}")
if len(channel_index["analogsignals"]) > 0:
lfp = channel_group.create_group("LFP")

for index, analog_signal in enumerate(channel_index["analogsignals"]):
lfp_timeseries = lfp.require_group("LFP_timeseries_{}".format(index))
lfp_timeseries = lfp.require_group(f"LFP_timeseries_{index}")
lfp_timeseries.attrs["num_samples"] = 1 # TODO
lfp_timeseries.attrs["starting_time"] = {
"value": 0.0, # TODO
Expand All @@ -421,7 +417,7 @@ def set_subject_attrs():
event_waveform = channel_group.create_group("EventWaveform")

for index, spiketrain in enumerate(channel_index["spiketrains"]):
waveform_timeseries = event_waveform.create_group("waveform_timeseries_{}".format(index))
waveform_timeseries = event_waveform.create_group(f"waveform_timeseries_{index}")
waveform_timeseries.attrs["num_samples"] = spiketrain["num_spikes"]
waveform_timeseries.attrs["sample_length"] = spiketrain["samples_per_spike"]
waveform_timeseries.attrs["electrode_idx"] = channel_index["channel_ids"]
Expand Down
4 changes: 0 additions & 4 deletions examples/exdirio.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
This is the implementation of the NEO IO for the exdir format.
Depends on: scipy
Expand All @@ -11,9 +10,6 @@
Mikkel E. Lepperød @CINPLA
"""

from __future__ import division
from __future__ import print_function
from __future__ import with_statement

import sys
from neo.io.baseio import BaseIO
Expand Down
2 changes: 1 addition & 1 deletion examples/usecase_exdir.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
print(f[experiment]["voltage"])
print("First voltage:", f[experiment]["voltage"][0])
else:
print("No voltage values for: {}".format(experiment))
print(f"No voltage values for: {experiment}")



Expand Down
2 changes: 1 addition & 1 deletion examples/usecase_h5py.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
print(f[experiment]["voltage"])
print("First voltage:", f[experiment]["voltage"][0])
else:
print("No voltage values for: {}".format(experiment))
print(f"No voltage values for: {experiment}")



Expand Down
5 changes: 2 additions & 3 deletions exdir/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

# This file helps to compute a version number in source trees obtained from
# git-archive tarball (such as those provided by githubs download-from-tag
# feature). Distribution tarballs (built by setup.py sdist) and build
Expand Down Expand Up @@ -114,7 +113,7 @@ def run_command(
return None, None
else:
if verbose:
print("unable to find command, tried %s" % (commands,))
print(f"unable to find command, tried {commands}")
return None, None
stdout = process.communicate()[0].strip().decode()
if process.returncode != 0:
Expand Down Expand Up @@ -162,7 +161,7 @@ def git_get_keywords(versionfile_abs: str) -> Dict[str, str]:
# _version.py.
keywords: Dict[str, str] = {}
try:
with open(versionfile_abs, "r") as fobj:
with open(versionfile_abs) as fobj:
for line in fobj:
if line.strip().startswith("git_refnames ="):
mo = re.search(r'=\s*"(.*)"', line)
Expand Down
2 changes: 0 additions & 2 deletions exdir/core/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-

"""
.. module:: exdir.core
.. moduleauthor:: Svenn-Arne Dragly, Milad H. Mobarhan, Mikkel E. Lepperød, Simen Tennøe
Expand Down
10 changes: 4 additions & 6 deletions exdir/core/attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,7 @@ def _open_or_create(self):
return attrs

def __iter__(self):
for key in self.keys():
yield key
yield from self.keys()

@property
def filename(self):
Expand Down Expand Up @@ -212,8 +211,8 @@ def __str__(self):
return "<Attributes of closed Exdir object>"
string = ""
for key in self:
string += "{}: {},".format(key, self[key])
return "Attribute({}, {{{}}})".format(self.parent.name, string)
string += f"{key}: {self[key]},"
return f"Attribute({self.parent.name}, {{{string}}})"

def _repr_html_(self):
if self.file.io_mode == OpenMode.FILE_CLOSED:
Expand All @@ -223,5 +222,4 @@ def _repr_html_(self):
def __repr__(self):
if self.file.io_mode == OpenMode.FILE_CLOSED:
return "<Attributes of closed Exdir object>"
return "Attributes of Exdir object '{}' at '{}'".format(
self.parent.name, id(self))
return f"Attributes of Exdir object '{self.parent.name}' at '{id(self)}'"
17 changes: 8 additions & 9 deletions exdir/core/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Dataset(exob.Object):
an existing dataset, which is different from the behavior in h5py.
"""
def __init__(self, root_directory, parent_path, object_name, file):
super(Dataset, self).__init__(
super().__init__(
root_directory=root_directory,
parent_path=parent_path,
object_name=object_name,
Expand All @@ -64,10 +64,10 @@ def __getitem__(self, args):
if ("required" in self.meta["plugins"][plugin_name]
and self.meta["plugins"][plugin_name]["required"] == True
and plugin_name not in enabled_plugins):
raise Exception((
"Plugin '{}' was used to write '{}', "
raise Exception(
f"Plugin '{plugin_name}' was used to write '{self.name}', "
"but is not enabled."
).format(plugin_name, self.name))
)

plugins = self.plugin_manager.dataset_plugins.read_order

Expand Down Expand Up @@ -113,13 +113,13 @@ def _reload_data(self):
self.file._open_datasets[self.name] = self
except ValueError as e:
# Could be that it is a Git LFS file. Let's see if that is the case and warn if so.
with open(self.data_filename, "r", encoding="utf-8") as f:
with open(self.data_filename, encoding="utf-8") as f:
test_string = "version https://git-lfs.github.com/spec/v1"
contents = f.read(len(test_string))
if contents == test_string:
raise IOError("The file '{}' is a Git LFS placeholder. "
raise OSError(f"The file '{self.data_filename}' is a Git LFS placeholder. "
"Open the the Exdir File with the Git LFS plugin or run "
"`git lfs fetch` first. ".format(self.data_filename))
"`git lfs fetch` first. ")
else:
raise e

Expand Down Expand Up @@ -265,8 +265,7 @@ def __str__(self):
def __repr__(self):
if self.file.io_mode == OpenMode.FILE_CLOSED:
return "<Closed Exdir Dataset>"
return "<Exdir Dataset {} shape {} dtype {}>".format(
self.name, self.shape, self.dtype)
return f"<Exdir Dataset {self.name} shape {self.shape} dtype {self.dtype}>"

@property
def _data(self):
Expand Down
25 changes: 9 additions & 16 deletions exdir/core/exdir_file.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import os
import shutil
import weakref
try:
import pathlib
except ImportError as e:
try:
import pathlib2 as pathlib
except ImportError:
raise e
import pathlib
import warnings

import exdir
Expand Down Expand Up @@ -78,8 +72,8 @@ def __init__(self, directory, mode=None, allow_remove=False,
recognized_modes = ['a', 'r', 'r+', 'w', 'w-', 'x']
if mode not in recognized_modes:
raise ValueError(
"IO mode {} not recognized, "
"mode must be one of {}".format(mode, recognized_modes)
f"IO mode {mode} not recognized, "
f"mode must be one of {recognized_modes}"
)

self.plugin_manager = exdir.plugin_interface.plugin_interface.Manager(plugins)
Expand All @@ -97,9 +91,9 @@ def __init__(self, directory, mode=None, allow_remove=False,
name_validation = validation.none
else:
raise ValueError(
'IO name rule "{}" not recognized, '
f'IO name rule "{name_validation}" not recognized, '
'name rule must be one of "strict", "simple", '
'"thorough", "none"'.format(name_validation)
'"thorough", "none"'
)

warnings.warn(
Expand All @@ -126,7 +120,7 @@ def __init__(self, directory, mode=None, allow_remove=False,
if already_exists:
if not exob.is_nonraw_object_directory(directory):
raise RuntimeError(
"Path '{}' already exists, but is not a valid exdir file.".format(directory)
f"Path '{directory}' already exists, but is not a valid exdir file."
)

should_create_directory = False
Expand All @@ -143,8 +137,8 @@ def __init__(self, directory, mode=None, allow_remove=False,
shutil.rmtree(str(directory)) # NOTE str needed for Python 3.5
else:
raise RuntimeError(
"File {} already exists. We won't delete the entire tree "
"by default. Add allow_remove=True to override.".format(directory)
f"File {directory} already exists. We won't delete the entire tree "
"by default. Add allow_remove=True to override."
)
should_create_directory = True
elif mode == "w-" or mode == "x":
Expand Down Expand Up @@ -227,5 +221,4 @@ def __contains__(self, name):
def __repr__(self):
if self.io_mode == OpenMode.FILE_CLOSED:
return "<Closed Exdir File>"
return "<Exdir File '{}' (mode {})>".format(
self.directory, self.user_mode)
return f"<Exdir File '{self.directory}' (mode {self.user_mode})>"
Loading
Loading