Skip to content
Open
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
6 changes: 3 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ jobs:
- uv-cache-0
- restore_cache:
keys:
- user-install-bin-cache-310
- user-install-bin-cache-311

# Hack in uninstalls of libraries as necessary if pip doesn't do the right thing in upgrading for us...
- run:
Expand All @@ -129,9 +129,9 @@ jobs:
paths:
- ~/.cache/uv
- save_cache:
key: user-install-bin-cache-310
key: user-install-bin-cache-311
paths:
- ~/.local/lib/python3.10/site-packages
- ~/.local/lib/python3.11/site-packages
- ~/.local/bin

- run:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scheduled_updates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ jobs:
# uv pip compile requires setting the python version explicitly in the command :(
run: |
uv pip compile pyproject.toml \
--python "3.10" --python-platform "x86_64-unknown-linux-gnu" \
--python "3.11" --python-platform "x86_64-unknown-linux-gnu" \
--group test --group lockfile_extras \
--resolution lowest-direct \
--format pylock.toml --output-file tools/pylock.ci-old.toml
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
python: '3.12'
kind: minimal
- os: ubuntu-22.04
python: '3.10'
python: '3.11'
kind: old
- os: ubuntu-latest
python: '3.14t' # free-threaded
Expand Down Expand Up @@ -128,6 +128,10 @@ jobs:
python-version: ${{ matrix.python }}
if: matrix.kind == 'old'
- run: bash ./tools/github_actions_verify_python.sh "${{ matrix.python }}"
- run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends libopenblas-dev
if: matrix.kind == 'old' && startswith(matrix.os, 'ubuntu')
- run: bash ./tools/github_actions_dependencies.sh
timeout-minutes: 10
- run: python ./tools/github_actions_check_old_env.py
Expand Down
1 change: 0 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ repos:
- pymef # for mne/io/mef
- quantities # for mne/io/neuralynx
- scipy
- typing_extensions # TODO VERSION remove once we require Python 3.11
args: [--no-python-downloads, --no-project]

# Codespell
Expand Down
1 change: 1 addition & 0 deletions doc/changes/dev/14140.dependency.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Updated minimum Python version to 3.11, by `Thomas Binns`_.
21 changes: 8 additions & 13 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
import os
import subprocess
import sys
from datetime import datetime, timezone
import tomllib
from datetime import UTC, datetime
from importlib.metadata import metadata
from pathlib import Path

Expand Down Expand Up @@ -58,7 +59,7 @@
# -- Project information -----------------------------------------------------

project = "MNE"
td = datetime.now(tz=timezone.utc)
td = datetime.now(tz=UTC)

# We need to triage which date type we use so that incremental builds work
# (Sphinx looks at variable changes and rewrites all files if some change)
Expand Down Expand Up @@ -443,17 +444,11 @@
"pooch.HTTPDownloader",
}
numpydoc_validate = True
try:
import tomllib
# TODO VERSION: Can be removed once Python 3.11 is required
except Exception:
pass
else:
pyproject_path = Path(__file__).parent.parent / "pyproject.toml"
pyproject = tomllib.loads(pyproject_path.read_text("utf-8"))
pyproject_nv = pyproject["tool"]["numpydoc_validation"]
numpydoc_validation_checks = set(pyproject_nv["checks"])
numpydoc_validation_exclude = set(pyproject_nv["exclude"])
pyproject_path = Path(__file__).parent.parent / "pyproject.toml"
pyproject = tomllib.loads(pyproject_path.read_text("utf-8"))
pyproject_nv = pyproject["tool"]["numpydoc_validation"]
numpydoc_validation_checks = set(pyproject_nv["checks"])
numpydoc_validation_exclude = set(pyproject_nv["exclude"])


# -- Sphinx-gallery configuration --------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: mne
channels:
- conda-forge
dependencies:
- python >=3.10
- python >=3.11
- antio >=0.5.0
- conda
- curryreader >=0.1.2
Expand Down
6 changes: 2 additions & 4 deletions mne/_fiff/meas_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -2010,7 +2010,7 @@ def _check_consistency(self, prepend_error=""):
if (
not isinstance(self["meas_date"], datetime.datetime)
or self["meas_date"].tzinfo is None
or self["meas_date"].tzinfo is not datetime.timezone.utc
or self["meas_date"].tzinfo is not datetime.UTC
):
raise RuntimeError(
f'{prepend_error}info["meas_date"] must be a datetime object in UTC'
Expand Down Expand Up @@ -3777,9 +3777,7 @@ def anonymize_info(info, daysback=None, keep_his=False, verbose=None):
for field in keep_fields:
_check_option("keep_his", field, valid_fields)

default_anon_dos = datetime.datetime(
2000, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc
)
default_anon_dos = datetime.datetime(2000, 1, 1, 0, 0, 0, tzinfo=datetime.UTC)
default_str = "mne_anonymize"
default_subject_id = 0
default_sex = 0
Expand Down
14 changes: 7 additions & 7 deletions mne/_fiff/tests/test_meas_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import json
import pickle
import string
from datetime import date, datetime, timedelta, timezone
from datetime import UTC, date, datetime, timedelta
from pathlib import Path

import numpy as np
Expand Down Expand Up @@ -350,7 +350,7 @@ def test_read_write_info(tmp_path):

# Check that having a very old date in fine until you try to save it to fif
with info._unlock(check_after=True):
info["meas_date"] = datetime(1800, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
info["meas_date"] = datetime(1800, 1, 1, 0, 0, 0, tzinfo=UTC)
fname = tmp_path / "test.fif"
with pytest.raises(RuntimeError, match="must be between "):
write_info(fname, info, overwrite=True)
Expand Down Expand Up @@ -406,7 +406,7 @@ def test_info_serialization_special_types():
info = create_info(ch_names=["EEG1"], sfreq=1000.0, ch_types="eeg")

# Test meas_date (datetime)
meas_date = datetime(2023, 11, 13, 10, 30, 0, tzinfo=timezone.utc)
meas_date = datetime(2023, 11, 13, 10, 30, 0, tzinfo=UTC)
with info._unlock():
info["meas_date"] = meas_date

Expand Down Expand Up @@ -726,7 +726,7 @@ def _test_anonymize_info(base_info, tmp_path):
assert isinstance(base_info, Info)
base_info = base_info.copy()

default_anon_dos = datetime(2000, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
default_anon_dos = datetime(2000, 1, 1, 0, 0, 0, tzinfo=UTC)
default_str = "mne_anonymize"
default_subject_id = 0
default_desc = "Anonymized using a time shift" + " to preserve age at acquisition"
Expand All @@ -739,7 +739,7 @@ def _test_anonymize_info(base_info, tmp_path):

# Fake some additional data
_complete_info(base_info)
meas_date = datetime(2010, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
meas_date = datetime(2010, 1, 1, 0, 0, 0, tzinfo=UTC)
with base_info._unlock():
base_info["meas_date"] = meas_date
base_info["subject_info"].update(
Expand Down Expand Up @@ -940,7 +940,7 @@ def test_meas_date_convert(stamp, dt):
meas_datetime = _stamp_to_dt(stamp)
stamp2 = _dt_to_stamp(meas_datetime)
assert stamp == stamp2
assert meas_datetime == datetime(*dt, tzinfo=timezone.utc)
assert meas_datetime == datetime(*dt, tzinfo=UTC)
# smoke test for info __repr__
info = create_info(1, 1000.0, "eeg")
with info._unlock():
Expand Down Expand Up @@ -988,7 +988,7 @@ def _complete_info(info):
info["helium_info"] = dict(
he_level_raw=np.float32(12.34),
helium_level=np.float32(45.67),
meas_date=datetime(2024, 11, 14, 14, 8, 2, tzinfo=timezone.utc),
meas_date=datetime(2024, 11, 14, 14, 8, 2, tzinfo=UTC),
orig_file_guid="e",
)
info["experimenter"] = "f"
Expand Down
6 changes: 3 additions & 3 deletions mne/annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from collections import Counter, OrderedDict, UserDict, UserList
from collections.abc import Iterable
from copy import deepcopy
from datetime import datetime, timedelta, timezone
from datetime import UTC, datetime, timedelta
from itertools import takewhile
from textwrap import shorten

Expand Down Expand Up @@ -425,7 +425,7 @@ def __init__(
try: # only warn if `orig_time` is not the default '1970-01-01 00:00:00'
if _handle_meas_date(0) == datetime.strptime(
orig_time, "%Y-%m-%d %H:%M:%S"
).replace(tzinfo=timezone.utc):
).replace(tzinfo=UTC):
pass
except ValueError: # error if incorrect datetime format AND not the default
warn(
Expand Down Expand Up @@ -1772,7 +1772,7 @@ def _handle_meas_date(meas_date):
except ValueError:
meas_date = None
else:
meas_date = meas_date.replace(tzinfo=timezone.utc)
meas_date = meas_date.replace(tzinfo=UTC)
elif isinstance(meas_date, tuple):
# old way
meas_date = _stamp_to_dt(meas_date)
Expand Down
2 changes: 1 addition & 1 deletion mne/export/_egimff.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def export_evokeds_mff(fname, evoked, history=None, *, overwrite=False, verbose=
if op.exists(fname):
os.remove(fname) if op.isfile(fname) else shutil.rmtree(fname)
writer = mffpy.Writer(fname)
current_time = datetime.datetime.now(datetime.timezone.utc)
current_time = datetime.datetime.now(datetime.UTC)
writer.addxml("fileInfo", recordTime=current_time)
try:
device = info["device_info"]["type"]
Expand Down
10 changes: 5 additions & 5 deletions mne/export/tests/test_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# Copyright the MNE-Python contributors.

from contextlib import nullcontext
from datetime import date, datetime, timezone
from datetime import UTC, date, datetime
from pathlib import Path

import numpy as np
Expand Down Expand Up @@ -52,7 +52,7 @@
["meas_date", "orig_time", "ext"],
[
[None, None, ".vhdr"],
[datetime(2022, 12, 3, 19, 1, 10, 720100, tzinfo=timezone.utc), None, ".eeg"],
[datetime(2022, 12, 3, 19, 1, 10, 720100, tzinfo=UTC), None, ".eeg"],
],
)
def test_export_raw_pybv(tmp_path, meas_date, orig_time, ext):
Expand Down Expand Up @@ -198,7 +198,7 @@ def _create_raw_for_edf_tests(stim_channel_index=None):
def test_double_export_edf(tmp_path):
"""Test exporting an EDF file multiple times."""
raw = _create_raw_for_edf_tests(stim_channel_index=2)
raw.info.set_meas_date(datetime(2023, 9, 4, 14, 53, 9, tzinfo=timezone.utc))
raw.info.set_meas_date(datetime(2023, 9, 4, 14, 53, 9, tzinfo=UTC))
raw.set_annotations(Annotations(onset=[1], duration=[0], description=["test"]))

# include subject info and measurement date
Expand Down Expand Up @@ -379,7 +379,7 @@ def test_rawarray_edf(tmp_path):
hour=time_now.hour,
minute=time_now.minute,
second=time_now.second,
tzinfo=timezone.utc,
tzinfo=UTC,
)
raw.set_meas_date(meas_date)
temp_fname = tmp_path / "test.edf"
Expand Down Expand Up @@ -427,7 +427,7 @@ def test_channel_label_too_long_for_edf_raises_error(tmp_path):
def test_measurement_date_outside_range_valid_for_edf(tmp_path):
"""Test trying to save an EDF with a measurement date before 1985-01-01."""
raw = _create_raw_for_edf_tests()
raw.set_meas_date(datetime(year=1984, month=1, day=1, tzinfo=timezone.utc))
raw.set_meas_date(datetime(year=1984, month=1, day=1, tzinfo=UTC))
with pytest.raises(ValueError, match="EDF only allows dates from 1985 to 2084"):
raw.export(tmp_path / "test.edf", overwrite=True)

Expand Down
4 changes: 2 additions & 2 deletions mne/io/brainvision/brainvision.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import os
import os.path as op
import re
from datetime import datetime, timezone
from datetime import UTC, datetime
from io import StringIO
from pathlib import Path
from typing import Literal
Expand Down Expand Up @@ -517,7 +517,7 @@ def _str_to_meas_date(date_str):
else:
raise

meas_date = meas_date.replace(tzinfo=timezone.utc)
meas_date = meas_date.replace(tzinfo=UTC)
return meas_date


Expand Down
2 changes: 1 addition & 1 deletion mne/io/brainvision/tests/test_brainvision.py
Original file line number Diff line number Diff line change
Expand Up @@ -1048,7 +1048,7 @@ def test_event_id_stability_when_save_and_fif_reload(tmp_path):
def test_parse_impedance():
"""Test case for parsing the impedances from header."""
expected_imp_meas_time = datetime.datetime(
2013, 11, 13, 16, 12, 27, tzinfo=datetime.timezone.utc
2013, 11, 13, 16, 12, 27, tzinfo=datetime.UTC
)
expected_imp_unit = "kOhm"
expected_electrodes = [
Expand Down
4 changes: 2 additions & 2 deletions mne/io/ctf/tests/test_ctf.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import copy
import os
import shutil
from datetime import datetime, timezone
from datetime import UTC, datetime
from os import path as op

import numpy as np
Expand Down Expand Up @@ -740,4 +740,4 @@ def _convert_time_bad(date_str, time_str):
raw = read_raw_ctf(ctf_dir / ctf_fname_continuous, verbose=True)
log = log.getvalue()
assert "No date or time found" in log
assert raw.info["meas_date"] == datetime.fromtimestamp(0, tz=timezone.utc)
assert raw.info["meas_date"] == datetime.fromtimestamp(0, tz=UTC)
4 changes: 2 additions & 2 deletions mne/io/curry/curry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Copyright the MNE-Python contributors.

import re
from datetime import datetime, timezone
from datetime import UTC, datetime
from pathlib import Path

import numpy as np
Expand Down Expand Up @@ -161,7 +161,7 @@ def _get_curry_meas_info(fname):
try:
year, month, day, hour, minute, second, millisec = meas_date
meas_date = datetime(
year, month, day, hour, minute, second, millisec * 1000, timezone.utc
year, month, day, hour, minute, second, millisec * 1000, UTC
)
except Exception:
meas_date = None
Expand Down
4 changes: 2 additions & 2 deletions mne/io/curry/tests/test_curry.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.

from datetime import datetime, timezone
from datetime import UTC, datetime
from pathlib import Path
from shutil import copyfile

Expand Down Expand Up @@ -632,7 +632,7 @@ def test_read_files_missing_channel(fname, expected_channel_list):
[
pytest.param(
Ref_chan_omitted_file,
datetime(2018, 11, 21, 12, 53, 48, 525000, tzinfo=timezone.utc),
datetime(2018, 11, 21, 12, 53, 48, 525000, tzinfo=UTC),
id="valid start date",
),
pytest.param(curry7_rfDC_file, None, id="start date year is 0"),
Expand Down
Loading
Loading