Skip to content

Commit

Permalink
MRG: Present is the __future__ (#5726)
Browse files Browse the repository at this point in the history
* ENH: Present is the __future__

* FIX: Bump versions to 3.5-compat

* FIX: Bump dependencies to 3.5 compat

* FIX: Permissive lib

* ENH: No more six

* DOC: whats_new.rst

* Towards a green travis (#32)

* FIX: use py3 dictionary iterator

* FIX: remove six.string_types

* Fix: bytecodes

* Fix: remove advance_iterator

* FIX: more encoding

* Fix: add StringIO from io

* FIX: Imports

* FIX: Heisenbugs

* FIX: Fixes for 3.5

* FIX: Ignore
  • Loading branch information
larsoner committed Nov 20, 2018
1 parent 9220f50 commit d7c8e86
Show file tree
Hide file tree
Showing 130 changed files with 398 additions and 1,681 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ jobs:
git config --global user.email "circle@mne.com";
git config --global user.name "Circle Ci";
pushd ~/mne-tools.github.io && git checkout master && git pull origin master && popd;
pushd doc/_build && rm -Rf ~/mne-tools.github.io/stable cp -a html_stable ~/mne-tools.github.io/stable && popd;
pushd doc/_build && rm -Rf ~/mne-tools.github.io/stable && cp -a html_stable ~/mne-tools.github.io/stable && popd;
pushd ~/mne-tools.github.io && git add -A && git commit -m "CircleCI update of stable docs (${CIRCLE_BUILD_NUM})." && git push origin master && popd;
else
echo "No deployment (build: ${CIRCLE_BRANCH}).";
Expand Down
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ matrix:
language: python
python: "3.6"

# 2.7 Old dependencies
# Old dependencies
- os: linux
env: PYTHON_VERSION=2.7
CONDA_DEPENDENCIES="numpy=1.8 scipy=0.12 matplotlib=1.3 pandas=0.13 scikit-learn=0.15 pytest pytest-cov"
env: PYTHON_VERSION=3.5
CONDA_DEPENDENCIES="numpy=1.11 scipy=0.17 matplotlib=1.5 pandas=0.18 scikit-learn=0.18 pytest pytest-cov"

# Minimal
- os: linux
Expand Down
12 changes: 6 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,18 @@ Dependencies

The minimum required dependencies to run MNE-Python are:

- Python >= 2.7
- NumPy >= 1.8
- SciPy >= 0.12
- Python >= 3.5
- NumPy >= 1.11.3
- SciPy >= 0.17.1

For full functionality, some functions require:

- Matplotlib >= 1.3
- Matplotlib >= 1.5
- Mayavi >= 4.6
- PySurfer >= 0.8
- Scikit-learn >= 0.15 (>= 0.18 recommended)
- Scikit-learn >= 0.18
- NiBabel >= 2.1.0
- Pandas >= 0.13
- Pandas >= 0.18
- Picard >= 0.3
- CuPy >= 4.0 (for NVIDIA CUDA acceleration)
- DIPY >= 0.10.1
Expand Down
3 changes: 2 additions & 1 deletion doc/configure_git.rst
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,8 @@ When you are ready to ask for someone to review your code and consider a merge:
how the code should be written (features, style, etc.) that are easier to
implement from the start.

#. Finally, make `travis`_ happy. Ensure that builds in all four jobs pass. To make code python3 compatible, refer to ``externals/six.py``. Use virtual environments to test code on different python versions. Please remember that `travis`_ only runs a subset of the tests and is thus not a substitute for running the entire test suite locally.
#. Finally, make `travis`_ happy. Ensure that builds in all four jobs pass.
Use virtual environments to test code on different python versions.

#. For the code to be mergeable, please rebase w.r.t master branch.

Expand Down
2 changes: 1 addition & 1 deletion doc/install_mne_python.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ When you are done, you should see a similar output if you type the following com
If you get an error message, consult the Anaconda documentation and search for Anaconda install
tips (`Stack Overflow <https://stackoverflow.com/>`_ results are often helpful).

.. note:: MNE-Python 0.17 will be the last release to support Python 2. From MNE-Python 0.18, only Python 3 will be supported.
.. note:: MNE-Python 0.18 only supports Python 3.5+.

2. Get MNE and its dependencies
###############################
Expand Down
2 changes: 0 additions & 2 deletions doc/sphinxext/gen_commands.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# -*- coding: utf-8 -*-

from __future__ import print_function

import os
import glob
from os import path as op
Expand Down
2 changes: 2 additions & 0 deletions doc/whats_new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ Bug
API
~~~

- Python 2 is no longer supported; MNE-Python now requires Python 3.5+, by `Eric Larson`_

.. _changes_0_17:

Version 0.17
Expand Down
21 changes: 10 additions & 11 deletions mne/annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from .utils import _pl, check_fname, _validate_type, verbose, warn, logger
from .utils import _check_pandas_installed
from .utils import _Counter as Counter
from .externals.six import string_types
from .io.write import (start_block, end_block, write_float, write_name_list,
write_double, start_file)
from .io.constants import FIFF
Expand Down Expand Up @@ -161,7 +160,7 @@ def __init__(self, onset, duration, description,
'(shape %s).'
% (onset.ndim, onset.shape))
duration = np.array(duration, dtype=float)
if isinstance(description, string_types):
if isinstance(description, str):
description = np.repeat(description, len(onset))
if duration.ndim != 1:
raise ValueError('Duration must be a one dimensional array.')
Expand Down Expand Up @@ -384,7 +383,7 @@ def _handle_meas_date(meas_date):
"""
if meas_date is None:
meas_date = 0
elif isinstance(meas_date, string_types):
elif isinstance(meas_date, str):
ACCEPTED_ISO8601 = '%Y-%m-%d %H:%M:%S.%f'
try:
meas_date = datetime.strptime(meas_date, ACCEPTED_ISO8601)
Expand Down Expand Up @@ -420,9 +419,9 @@ def _annotations_starts_stops(raw, kinds, name='unknown', invert=False):
onsets and ends are inclusive.
"""
_validate_type(kinds, (string_types, list, tuple), str(type(kinds)),
_validate_type(kinds, (str, list, tuple), str(type(kinds)),
"str, list or tuple")
if isinstance(kinds, string_types):
if isinstance(kinds, str):
kinds = [kinds]
else:
for kind in kinds:
Expand Down Expand Up @@ -486,8 +485,8 @@ def _write_annotations_txt(fname, annot):

data = np.array([annot.onset, annot.duration, annot.description],
dtype=str).T
with open(fname, 'w') as fid:
fid.write(content)
with open(fname, 'wb') as fid:
fid.write(content.encode())
np.savetxt(fid, data, delimiter=',', fmt="%s")


Expand Down Expand Up @@ -654,10 +653,10 @@ def is_orig_time(x):

def _read_annotations_txt(fname):
onset, duration, desc = np.loadtxt(fname, delimiter=',',
dtype=str, unpack=True)
onset = [float(o) for o in onset]
duration = [float(d) for d in duration]
desc = [str(d).strip() for d in desc]
dtype=np.bytes_, unpack=True)
onset = [float(o.decode()) for o in onset]
duration = [float(d.decode()) for d in duration]
desc = [str(d.decode()).strip() for d in desc]
return onset, duration, desc


Expand Down
3 changes: 1 addition & 2 deletions mne/beamformer/_compute_beamformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@
from ..time_frequency.csd import CrossSpectralDensity

from ..externals.h5io import read_hdf5, write_hdf5
from ..externals.six import string_types


def _check_rank(rank):
"""Check rank parameter and deal with deprecation."""
if isinstance(rank, string_types):
if isinstance(rank, str):
# XXX we can use rank='' to deprecate to get to None eventually:
# if rank == '':
# warn('The rank parameter default in 0.18 of "full" will change '
Expand Down
3 changes: 1 addition & 2 deletions mne/beamformer/_dics.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
_check_proj_match, _prepare_beamformer_input,
_compute_beamformer, _check_one_ch_type,
_check_src_type, Beamformer, _check_rank)
from ..externals import six


@verbose
Expand Down Expand Up @@ -361,7 +360,7 @@ def apply_dics(evoked, filters, verbose=None):

stc = _apply_dics(data=data, filters=filters, info=info, tmin=tmin)

return six.advance_iterator(stc)
return next(stc)


@verbose
Expand Down
5 changes: 2 additions & 3 deletions mne/beamformer/_lcmv.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from ..source_estimate import _make_stc, SourceEstimate, _get_src_type
from ..utils import logger, verbose, warn, _validate_type, _reg_pinv
from .. import Epochs
from ..externals import six
from ._compute_beamformer import (
_setup_picks, _pick_channels_spatial_filter,
_check_proj_match, _prepare_beamformer_input, _check_one_ch_type,
Expand Down Expand Up @@ -301,7 +300,7 @@ def apply_lcmv(evoked, filters, max_ori_out='signed', verbose=None):
stc = _apply_lcmv(data=data, filters=filters, info=info,
tmin=tmin, max_ori_out=max_ori_out)

return six.advance_iterator(stc)
return next(stc)


@verbose
Expand Down Expand Up @@ -402,7 +401,7 @@ def apply_lcmv_raw(raw, filters, start=None, stop=None, max_ori_out='signed',
stc = _apply_lcmv(data=data, filters=filters, info=info,
tmin=tmin, max_ori_out=max_ori_out)

return six.advance_iterator(stc)
return next(stc)


@verbose
Expand Down
3 changes: 1 addition & 2 deletions mne/beamformer/tests/test_dics.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
Beamformer)
from mne.time_frequency import csd_morlet
from mne.utils import run_tests_if_main, object_diff, requires_h5py
from mne.externals.six import advance_iterator
from mne.proj import compute_proj_evoked, make_projector

data_path = testing.data_path(download=False)
Expand Down Expand Up @@ -418,7 +417,7 @@ def test_apply_dics_timeseries():
# Test returning a generator
stcs = apply_dics_epochs(epochs, filters, return_generator=False)
stcs_gen = apply_dics_epochs(epochs, filters, return_generator=True)
assert_array_equal(stcs[0].data, advance_iterator(stcs_gen).data)
assert_array_equal(stcs[0].data, next(stcs_gen).data)

# Test computing timecourses on a volume source space
filters_vol = make_dics(evoked.info, fwd_vol, csd20, reg=reg)
Expand Down
3 changes: 1 addition & 2 deletions mne/beamformer/tests/test_lcmv.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
read_beamformer)
from mne.beamformer._lcmv import _lcmv_source_power
from mne.minimum_norm import make_inverse_operator, apply_inverse
from mne.externals.six import advance_iterator
from mne.simulation import simulate_evoked
from mne.utils import run_tests_if_main, object_diff, requires_h5py

Expand Down Expand Up @@ -392,7 +391,7 @@ def test_make_lcmv(tmpdir):
stcs = apply_lcmv_epochs(epochs, filters, max_ori_out='signed')
stcs_ = apply_lcmv_epochs(epochs, filters, return_generator=True,
max_ori_out='signed')
assert_array_equal(stcs[0].data, advance_iterator(stcs_).data)
assert_array_equal(stcs[0].data, next(stcs_).data)

epochs.drop_bad()
assert (len(epochs.events) == len(stcs))
Expand Down
25 changes: 12 additions & 13 deletions mne/bem.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
from .utils import (verbose, logger, run_subprocess, get_subjects_dir, warn,
_pl, _validate_type)
from .fixes import einsum
from .externals.six import string_types


# ############################################################################
Expand Down Expand Up @@ -312,7 +311,7 @@ def make_bem_solution(surfs, verbose=None):
write_bem_solution
"""
logger.info('Approximation method : Linear collocation\n')
if isinstance(surfs, string_types):
if isinstance(surfs, str):
# Load the surfaces
logger.info('Loading surfaces...')
surfs = read_bem_surfaces(surfs)
Expand Down Expand Up @@ -478,7 +477,7 @@ def _surfaces_to_bem(surfs, ids, sigmas, ico=None, rescale=True,
'number of elements (1 or 3)')
surf = list(surfs)
for si, surf in enumerate(surfs):
if isinstance(surf, string_types):
if isinstance(surf, str):
surfs[si] = read_surface(surf, return_dict=True)[-1]
# Downsampling if the surface is isomorphic with a subdivided icosahedron
if ico is not None:
Expand Down Expand Up @@ -736,7 +735,7 @@ def make_sphere_model(r0=(0., 0., 0.04), head_radius=0.09, info=None,
"""
for name in ('r0', 'head_radius'):
param = locals()[name]
if isinstance(param, string_types):
if isinstance(param, str):
if param != 'auto':
raise ValueError('%s, if str, must be "auto" not "%s"'
% (name, param))
Expand All @@ -749,14 +748,14 @@ def make_sphere_model(r0=(0., 0., 0.04), head_radius=0.09, info=None,
if len(sigmas) <= 1 and head_radius is not None:
raise ValueError('at least 2 sigmas must be supplied if '
'head_radius is not None, got %s' % (len(sigmas),))
if (isinstance(r0, string_types) and r0 == 'auto') or \
(isinstance(head_radius, string_types) and head_radius == 'auto'):
if (isinstance(r0, str) and r0 == 'auto') or \
(isinstance(head_radius, str) and head_radius == 'auto'):
if info is None:
raise ValueError('Info must not be None for auto mode')
head_radius_fit, r0_fit = fit_sphere_to_headshape(info, units='m')[:2]
if isinstance(r0, string_types):
if isinstance(r0, str):
r0 = r0_fit
if isinstance(head_radius, string_types):
if isinstance(head_radius, str):
head_radius = head_radius_fit
sphere = ConductorModel(is_sphere=True, r0=np.array(r0),
coord_frame=FIFF.FIFFV_COORD_HEAD)
Expand Down Expand Up @@ -851,7 +850,7 @@ def fit_sphere_to_headshape(info, dig_kinds='auto', units='m', verbose=None):
This function excludes any points that are low and frontal
(``z < 0 and y > 0``) to improve the fit.
"""
if not isinstance(units, string_types) or units not in ('m', 'mm'):
if not isinstance(units, str) or units not in ('m', 'mm'):
raise ValueError('units must be a "m" or "mm"')
radius, origin_head, origin_device = _fit_sphere_to_headshape(
info, dig_kinds)
Expand Down Expand Up @@ -895,7 +894,7 @@ def get_fitting_dig(info, dig_kinds='auto', verbose=None):
if info['dig'] is None:
raise RuntimeError('Cannot fit headshape without digitization '
', info["dig"] is None')
if isinstance(dig_kinds, string_types):
if isinstance(dig_kinds, str):
if dig_kinds == 'auto':
# try "extra" first
try:
Expand Down Expand Up @@ -964,7 +963,7 @@ def _fit_sphere_to_headshape(info, dig_kinds, verbose=None):
def _fit_sphere(points, disp='auto'):
"""Fit a sphere to an arbitrary set of points."""
from scipy.optimize import fmin_cobyla
if isinstance(disp, string_types) and disp == 'auto':
if isinstance(disp, str) and disp == 'auto':
disp = True if logger.level <= 20 else False
# initial guess for center and radius
radii = (np.max(points, axis=1) - np.min(points, axis=1)) / 2.
Expand Down Expand Up @@ -992,7 +991,7 @@ def constraint(center_rad):

def _check_origin(origin, info, coord_frame='head', disp=False):
"""Check or auto-determine the origin."""
if isinstance(origin, string_types):
if isinstance(origin, str):
if origin != 'auto':
raise ValueError('origin must be a numerical array, or "auto", '
'not %s' % (origin,))
Expand Down Expand Up @@ -1438,7 +1437,7 @@ def _add_gamma_multipliers(bem):

def _bem_find_surface(bem, id_):
"""Find surface from already-loaded BEM."""
if isinstance(id_, string_types):
if isinstance(id_, str):
name = id_
id_ = _surf_dict[id_]
else:
Expand Down
11 changes: 5 additions & 6 deletions mne/channels/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import numpy as np
from scipy import sparse

from ..externals.six import string_types
from ..utils import verbose, logger, warn, copy_function_doc_to_method_doc
from ..utils import _check_preload, _validate_type
from ..io.compensator import get_current_comp
Expand Down Expand Up @@ -779,10 +778,10 @@ def drop_channels(self, ch_names):
"""
msg = ("'ch_names' should be a list of strings (the name[s] of the "
"channel to be dropped), not a {0}.")
if isinstance(ch_names, string_types):
if isinstance(ch_names, str):
raise ValueError(msg.format("string"))
else:
if not all([isinstance(ch_name, string_types)
if not all([isinstance(ch_name, str)
for ch_name in ch_names]):
raise ValueError(msg.format(type(ch_names[0])))

Expand Down Expand Up @@ -1088,8 +1087,8 @@ def read_ch_connectivity(fname, picks=None):
fname = op.join(templates_dir, fname)

nb = loadmat(fname)['neighbours']
ch_names = _recursive_flatten(nb['label'], string_types)
neighbors = [_recursive_flatten(c, string_types) for c in
ch_names = _recursive_flatten(nb['label'], str)
neighbors = [_recursive_flatten(c, str) for c in
nb['neighblabel'].flatten()]
assert len(ch_names) == len(neighbors)
if picks is not None:
Expand Down Expand Up @@ -1134,7 +1133,7 @@ def _ch_neighbor_connectivity(ch_names, neighbors):

for neigh in neighbors:
if (not isinstance(neigh, list) and
not all(isinstance(c, string_types) for c in neigh)):
not all(isinstance(c, str) for c in neigh)):
raise ValueError('`neighbors` must be a list of lists of str')

ch_connectivity = np.eye(len(ch_names), dtype=bool)
Expand Down
1 change: 0 additions & 1 deletion mne/channels/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
from ..io.constants import FIFF
from ..io.meas_info import Info
from ..utils import _clean_names, warn, _check_ch_locs
from ..externals.six.moves import map
from .channels import _get_ch_info


Expand Down
Loading

0 comments on commit d7c8e86

Please sign in to comment.