"torchvision/git@developer.sourcefind.cn:OpenDAS/vision.git" did not exist on "d32bce08c6d205d0468625c5b308b895b166ac1b"
Unverified Commit 12e5913b authored by Kai Chen's avatar Kai Chen Committed by GitHub
Browse files

Remove supports for python 2.7 and bump version to 0.4.0 (#211)

* remove supports for python 2.7

* fix the unit test for python 3.5

* add python 3.8 in CI

* try ubuntu 18.04 as the environment
parent 2624090f
dist: xenial dist: bionic
sudo: required sudo: required
language: python language: python
before_install: before_install:
- sudo add-apt-repository -y ppa:mc3man/xerus-media
- sudo apt-get update - sudo apt-get update
- sudo apt-get install -y ffmpeg libjpeg-turbo* - sudo apt-get install -y ffmpeg libturbojpeg
- pip install -U git+git://github.com/lilohuang/PyTurboJPEG.git - pip install -U git+git://github.com/lilohuang/PyTurboJPEG.git
install: install:
- pip install torch==1.4.0+cpu torchvision==0.5.0+cpu -f https://download.pytorch.org/whl/torch_stable.html - pip install torch==1.4.0+cpu torchvision==0.5.0+cpu -f https://download.pytorch.org/whl/torch_stable.html
- rm -rf .eggs && pip install -e . codecov flake8 yapf isort mock - rm -rf .eggs && pip install -e .
cache: cache:
pip: true pip: true
...@@ -23,8 +22,10 @@ python: ...@@ -23,8 +22,10 @@ python:
- "3.5" - "3.5"
- "3.6" - "3.6"
- "3.7" - "3.7"
- "3.8"
before_script: before_script:
- pip install codecov flake8 yapf isort
- flake8 - flake8
- isort -rc --diff mmcv/ tests/ examples/ - isort -rc --diff mmcv/ tests/ examples/
- yapf -r -d mmcv/ tests/ examples/ - yapf -r -d mmcv/ tests/ examples/
...@@ -41,7 +42,7 @@ deploy: ...@@ -41,7 +42,7 @@ deploy:
on: on:
branch: master branch: master
tags: true tags: true
python: "3.6" python: "3.7"
distributions: sdist bdist_wheel distributions: sdist bdist_wheel
skip_cleanup: true skip_cleanup: true
skip_upload_docs: true skip_upload_docs: true
...@@ -30,7 +30,7 @@ It provides the following functionalities. ...@@ -30,7 +30,7 @@ It provides the following functionalities.
See the `documentation <http://mmcv.readthedocs.io/en/latest>`_ for more features and usage. See the `documentation <http://mmcv.readthedocs.io/en/latest>`_ for more features and usage.
Note: MMCV currently supports both Python 2.7 and 3.5+, but we plan to remove the support for Python 2. Please migrate to Python 3 as soon as possible. Note: MMCV requires Python 3.5+.
Installation Installation
......
...@@ -55,7 +55,7 @@ class TxtHandler1(mmcv.BaseFileHandler): ...@@ -55,7 +55,7 @@ class TxtHandler1(mmcv.BaseFileHandler):
Here is an example of `PickleHandler`. Here is an example of `PickleHandler`.
```python ```python
from six.moves import cPickle as pickle import pickle
class PickleHandler(mmcv.BaseFileHandler): class PickleHandler(mmcv.BaseFileHandler):
......
...@@ -2,9 +2,7 @@ ...@@ -2,9 +2,7 @@
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
class BaseFileHandler(object): class BaseFileHandler(metaclass=ABCMeta):
__metaclass__ = ABCMeta # python 2 compatibility
@abstractmethod @abstractmethod
def load_from_fileobj(self, file, **kwargs): def load_from_fileobj(self, file, **kwargs):
......
# Copyright (c) Open-MMLab. All rights reserved. # Copyright (c) Open-MMLab. All rights reserved.
from six.moves import cPickle as pickle import pickle
from .base import BaseFileHandler from .base import BaseFileHandler
......
...@@ -5,8 +5,8 @@ from .misc import (check_prerequisites, concat_list, is_list_of, is_seq_of, ...@@ -5,8 +5,8 @@ from .misc import (check_prerequisites, concat_list, is_list_of, is_seq_of,
is_str, is_tuple_of, iter_cast, list_cast, is_str, is_tuple_of, iter_cast, list_cast,
requires_executable, requires_package, slice_list, requires_executable, requires_package, slice_list,
tuple_cast) tuple_cast)
from .path import (FileNotFoundError, check_file_exist, fopen, is_filepath, from .path import (check_file_exist, fopen, is_filepath, mkdir_or_exist,
mkdir_or_exist, scandir, symlink) scandir, symlink)
from .progressbar import (ProgressBar, track_iter_progress, from .progressbar import (ProgressBar, track_iter_progress,
track_parallel_progress, track_progress) track_parallel_progress, track_progress)
from .registry import Registry, build_from_cfg from .registry import Registry, build_from_cfg
...@@ -17,7 +17,7 @@ __all__ = [ ...@@ -17,7 +17,7 @@ __all__ = [
'list_cast', 'tuple_cast', 'is_seq_of', 'is_list_of', 'is_tuple_of', 'list_cast', 'tuple_cast', 'is_seq_of', 'is_list_of', 'is_tuple_of',
'slice_list', 'concat_list', 'check_prerequisites', 'requires_package', 'slice_list', 'concat_list', 'check_prerequisites', 'requires_package',
'requires_executable', 'is_filepath', 'fopen', 'check_file_exist', 'requires_executable', 'is_filepath', 'fopen', 'check_file_exist',
'mkdir_or_exist', 'symlink', 'scandir', 'FileNotFoundError', 'ProgressBar', 'mkdir_or_exist', 'symlink', 'scandir', 'ProgressBar', 'track_progress',
'track_progress', 'track_iter_progress', 'track_parallel_progress', 'track_iter_progress', 'track_parallel_progress', 'Registry',
'Registry', 'build_from_cfg', 'Timer', 'TimerError', 'check_time' 'build_from_cfg', 'Timer', 'TimerError', 'check_time'
] ]
...@@ -5,11 +5,11 @@ import shutil ...@@ -5,11 +5,11 @@ import shutil
import sys import sys
import tempfile import tempfile
from argparse import ArgumentParser from argparse import ArgumentParser
from collections import abc
from importlib import import_module from importlib import import_module
from addict import Dict from addict import Dict
from .misc import collections_abc
from .path import check_file_exist from .path import check_file_exist
BASE_KEY = '_base_' BASE_KEY = '_base_'
...@@ -46,7 +46,7 @@ def add_args(parser, cfg, prefix=''): ...@@ -46,7 +46,7 @@ def add_args(parser, cfg, prefix=''):
parser.add_argument('--' + prefix + k, action='store_true') parser.add_argument('--' + prefix + k, action='store_true')
elif isinstance(v, dict): elif isinstance(v, dict):
add_args(parser, v, prefix + k + '.') add_args(parser, v, prefix + k + '.')
elif isinstance(v, collections_abc.Iterable): elif isinstance(v, abc.Iterable):
parser.add_argument('--' + prefix + k, type=type(v[0]), nargs='+') parser.add_argument('--' + prefix + k, type=type(v[0]), nargs='+')
else: else:
print('cannot parse key {} of type {}'.format(prefix + k, type(v))) print('cannot parse key {} of type {}'.format(prefix + k, type(v)))
......
# Copyright (c) Open-MMLab. All rights reserved. # Copyright (c) Open-MMLab. All rights reserved.
import collections
import functools import functools
import itertools import itertools
import subprocess import subprocess
from collections import abc
from importlib import import_module from importlib import import_module
import six
# ABCs from collections will be deprecated in python 3.8+,
# while collections.abc is not available in python 2.7
try:
import collections.abc as collections_abc
except ImportError:
import collections as collections_abc
def is_str(x): def is_str(x):
"""Whether the input is an string instance.""" """Whether the input is an string instance.
return isinstance(x, six.string_types)
Note: This method is deprecated since python 2 is no longer supported.
"""
return isinstance(x, str)
def iter_cast(inputs, dst_type, return_type=None): def iter_cast(inputs, dst_type, return_type=None):
...@@ -32,12 +26,12 @@ def iter_cast(inputs, dst_type, return_type=None): ...@@ -32,12 +26,12 @@ def iter_cast(inputs, dst_type, return_type=None):
Returns: Returns:
iterator or specified type: The converted object. iterator or specified type: The converted object.
""" """
if not isinstance(inputs, collections_abc.Iterable): if not isinstance(inputs, abc.Iterable):
raise TypeError('inputs must be an iterable object') raise TypeError('inputs must be an iterable object')
if not isinstance(dst_type, type): if not isinstance(dst_type, type):
raise TypeError('"dst_type" must be a valid type') raise TypeError('"dst_type" must be a valid type')
out_iterable = six.moves.map(dst_type, inputs) out_iterable = map(dst_type, inputs)
if return_type is None: if return_type is None:
return out_iterable return out_iterable
...@@ -73,7 +67,7 @@ def is_seq_of(seq, expected_type, seq_type=None): ...@@ -73,7 +67,7 @@ def is_seq_of(seq, expected_type, seq_type=None):
bool: Whether the sequence is valid. bool: Whether the sequence is valid.
""" """
if seq_type is None: if seq_type is None:
exp_seq_type = collections_abc.Sequence exp_seq_type = abc.Sequence
else: else:
assert isinstance(seq_type, type) assert isinstance(seq_type, type)
exp_seq_type = seq_type exp_seq_type = seq_type
......
# Copyright (c) Open-MMLab. All rights reserved. # Copyright (c) Open-MMLab. All rights reserved.
import os import os
import os.path as osp import os.path as osp
import sys
from pathlib import Path from pathlib import Path
import six
from .misc import is_str from .misc import is_str
if sys.version_info <= (3, 3):
FileNotFoundError = IOError
else:
FileNotFoundError = FileNotFoundError
def is_filepath(x): def is_filepath(x):
if is_str(x) or isinstance(x, Path): if is_str(x) or isinstance(x, Path):
...@@ -37,11 +29,7 @@ def mkdir_or_exist(dir_name, mode=0o777): ...@@ -37,11 +29,7 @@ def mkdir_or_exist(dir_name, mode=0o777):
if dir_name == '': if dir_name == '':
return return
dir_name = osp.expanduser(dir_name) dir_name = osp.expanduser(dir_name)
if six.PY3: os.makedirs(dir_name, mode=mode, exist_ok=True)
os.makedirs(dir_name, mode=mode, exist_ok=True)
else:
if not osp.isdir(dir_name):
os.makedirs(dir_name, mode=mode)
def symlink(src, dst, overwrite=True, **kwargs): def symlink(src, dst, overwrite=True, **kwargs):
...@@ -50,7 +38,9 @@ def symlink(src, dst, overwrite=True, **kwargs): ...@@ -50,7 +38,9 @@ def symlink(src, dst, overwrite=True, **kwargs):
os.symlink(src, dst, **kwargs) os.symlink(src, dst, **kwargs)
def _scandir_py35(dir_path, suffix=None): def scandir(dir_path, suffix=None):
if (suffix is not None) and not isinstance(suffix, (str, tuple)):
raise TypeError('"suffix" must be a string or tuple of strings')
for entry in os.scandir(dir_path): for entry in os.scandir(dir_path):
if not entry.is_file(): if not entry.is_file():
continue continue
...@@ -61,25 +51,6 @@ def _scandir_py35(dir_path, suffix=None): ...@@ -61,25 +51,6 @@ def _scandir_py35(dir_path, suffix=None):
yield filename yield filename
def _scandir_py(dir_path, suffix=None):
for filename in os.listdir(dir_path):
if not osp.isfile(osp.join(dir_path, filename)):
continue
if suffix is None:
yield filename
elif filename.endswith(suffix):
yield filename
def scandir(dir_path, suffix=None):
if suffix is not None and not isinstance(suffix, (str, tuple)):
raise TypeError('"suffix" must be a string or tuple of strings')
if sys.version_info >= (3, 5):
return _scandir_py35(dir_path, suffix)
else:
return _scandir_py(dir_path, suffix)
def find_vcs_root(path, markers=('.git', )): def find_vcs_root(path, markers=('.git', )):
"""Finds the root directory (including itself) of specified markers. """Finds the root directory (including itself) of specified markers.
......
# Copyright (c) Open-MMLab. All rights reserved. # Copyright (c) Open-MMLab. All rights reserved.
import sys import sys
from collections.abc import Iterable
from multiprocessing import Pool from multiprocessing import Pool
from shutil import get_terminal_size
from .misc import collections_abc
from .timer import Timer from .timer import Timer
...@@ -19,10 +20,6 @@ class ProgressBar(object): ...@@ -19,10 +20,6 @@ class ProgressBar(object):
@property @property
def terminal_width(self): def terminal_width(self):
if sys.version_info > (3, 3):
from shutil import get_terminal_size
else:
from backports.shutil_get_terminal_size import get_terminal_size
width, _ = get_terminal_size() width, _ = get_terminal_size()
return width return width
...@@ -79,11 +76,11 @@ def track_progress(func, tasks, bar_width=50, file=sys.stdout, **kwargs): ...@@ -79,11 +76,11 @@ def track_progress(func, tasks, bar_width=50, file=sys.stdout, **kwargs):
""" """
if isinstance(tasks, tuple): if isinstance(tasks, tuple):
assert len(tasks) == 2 assert len(tasks) == 2
assert isinstance(tasks[0], collections_abc.Iterable) assert isinstance(tasks[0], Iterable)
assert isinstance(tasks[1], int) assert isinstance(tasks[1], int)
task_num = tasks[1] task_num = tasks[1]
tasks = tasks[0] tasks = tasks[0]
elif isinstance(tasks, collections_abc.Iterable): elif isinstance(tasks, Iterable):
task_num = len(tasks) task_num = len(tasks)
else: else:
raise TypeError( raise TypeError(
...@@ -145,11 +142,11 @@ def track_parallel_progress(func, ...@@ -145,11 +142,11 @@ def track_parallel_progress(func,
""" """
if isinstance(tasks, tuple): if isinstance(tasks, tuple):
assert len(tasks) == 2 assert len(tasks) == 2
assert isinstance(tasks[0], collections_abc.Iterable) assert isinstance(tasks[0], Iterable)
assert isinstance(tasks[1], int) assert isinstance(tasks[1], int)
task_num = tasks[1] task_num = tasks[1]
tasks = tasks[0] tasks = tasks[0]
elif isinstance(tasks, collections_abc.Iterable): elif isinstance(tasks, Iterable):
task_num = len(tasks) task_num = len(tasks)
else: else:
raise TypeError( raise TypeError(
...@@ -193,11 +190,11 @@ def track_iter_progress(tasks, bar_width=50, file=sys.stdout, **kwargs): ...@@ -193,11 +190,11 @@ def track_iter_progress(tasks, bar_width=50, file=sys.stdout, **kwargs):
""" """
if isinstance(tasks, tuple): if isinstance(tasks, tuple):
assert len(tasks) == 2 assert len(tasks) == 2
assert isinstance(tasks[0], collections_abc.Iterable) assert isinstance(tasks[0], Iterable)
assert isinstance(tasks[1], int) assert isinstance(tasks[1], int)
task_num = tasks[1] task_num = tasks[1]
tasks = tasks[0] tasks = tasks[0]
elif isinstance(tasks, collections_abc.Iterable): elif isinstance(tasks, Iterable):
task_num = len(tasks) task_num = len(tasks)
else: else:
raise TypeError( raise TypeError(
......
# Copyright (c) Open-MMLab. All rights reserved. # Copyright (c) Open-MMLab. All rights reserved.
__version__ = '0.3.2' __version__ = '0.4.0'
...@@ -17,6 +17,6 @@ line_length = 79 ...@@ -17,6 +17,6 @@ line_length = 79
multi_line_output = 0 multi_line_output = 0
known_standard_library = pkg_resources,setuptools known_standard_library = pkg_resources,setuptools
known_first_party = mmcv known_first_party = mmcv
known_third_party = Cython,addict,cv2,mock,numpy,pytest,resnet_cifar,six,torch,torchvision,yaml known_third_party = Cython,addict,cv2,numpy,pytest,resnet_cifar,torch,torchvision,yaml
no_lines_before = STDLIB,LOCALFOLDER no_lines_before = STDLIB,LOCALFOLDER
default_section = THIRDPARTY default_section = THIRDPARTY
import platform import platform
import re import re
import sys
from io import open # for Python 2 (identical to builtin in Python 3)
from pkg_resources import DistributionNotFound, get_distribution from pkg_resources import DistributionNotFound, get_distribution
from setuptools import Extension, dist, find_packages, setup from setuptools import Extension, dist, find_packages, setup
...@@ -24,11 +22,7 @@ def choose_requirement(primary, secondary): ...@@ -24,11 +22,7 @@ def choose_requirement(primary, secondary):
return str(primary) return str(primary)
install_requires = ['addict', 'numpy', 'pyyaml', 'six'] install_requires = ['addict', 'numpy', 'pyyaml']
if sys.version_info < (3, ):
install_requires.extend(
['backports.shutil_get_terminal_size', 'enum34', 'pathlib'])
# If first not installed install second package # If first not installed install second package
CHOOSE_INSTALL_REQUIRES = [('opencv-python-headless>=3', 'opencv-python>=3')] CHOOSE_INSTALL_REQUIRES = [('opencv-python-headless>=3', 'opencv-python>=3')]
...@@ -82,12 +76,11 @@ setup( ...@@ -82,12 +76,11 @@ setup(
'Development Status :: 4 - Beta', 'Development Status :: 4 - Beta',
'License :: OSI Approved :: Apache Software License', 'License :: OSI Approved :: Apache Software License',
'Operating System :: OS Independent', 'Operating System :: OS Independent',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Topic :: Utilities', 'Topic :: Utilities',
], ],
url='https://github.com/open-mmlab/mmcv', url='https://github.com/open-mmlab/mmcv',
......
# Copyright (c) Open-MMLab. All rights reserved. # Copyright (c) Open-MMLab. All rights reserved.
import json import json
import os.path as osp import os.path as osp
import sys
import pytest import pytest
from mmcv import Config, FileNotFoundError from mmcv import Config
def test_construct(): def test_construct():
...@@ -25,7 +26,11 @@ def test_construct(): ...@@ -25,7 +26,11 @@ def test_construct():
assert isinstance(cfg, Config) assert isinstance(cfg, Config)
assert cfg.filename == cfg_file assert cfg.filename == cfg_file
assert cfg.text == open(cfg_file, 'r').read() assert cfg.text == open(cfg_file, 'r').read()
assert cfg.dump() == format_text if sys.version_info >= (3, 6):
assert cfg.dump() == format_text
else:
loaded = json.loads(cfg.dump())
assert set(loaded.keys()) == set(cfg_dict)
def test_fromfile(): def test_fromfile():
......
import os.path as osp import os.path as osp
import sys import sys
import warnings import warnings
from unittest.mock import MagicMock
from mock import MagicMock
import mmcv.runner import mmcv.runner
......
...@@ -52,7 +52,7 @@ def test_requires_package(capsys): ...@@ -52,7 +52,7 @@ def test_requires_package(capsys):
def func_b(): def func_b():
pass pass
@mmcv.requires_package('six') @mmcv.requires_package('numpy')
def func_c(): def func_c():
return 1 return 1
......
# Copyright (c) Open-MMLab. All rights reserved. # Copyright (c) Open-MMLab. All rights reserved.
import os.path as osp import os.path as osp
import sys
from pathlib import Path from pathlib import Path
import pytest import pytest
...@@ -22,12 +21,8 @@ def test_fopen(): ...@@ -22,12 +21,8 @@ def test_fopen():
def test_check_file_exist(): def test_check_file_exist():
mmcv.check_file_exist(__file__) mmcv.check_file_exist(__file__)
if sys.version_info > (3, 3): with pytest.raises(FileNotFoundError):
with pytest.raises(FileNotFoundError): # noqa mmcv.check_file_exist('no_such_file.txt')
mmcv.check_file_exist('no_such_file.txt')
else:
with pytest.raises(IOError):
mmcv.check_file_exist('no_such_file.txt')
def test_scandir(): def test_scandir():
...@@ -43,4 +38,4 @@ def test_scandir(): ...@@ -43,4 +38,4 @@ def test_scandir():
]) ])
assert set(mmcv.scandir(folder, '.png')) == set() assert set(mmcv.scandir(folder, '.png')) == set()
with pytest.raises(TypeError): with pytest.raises(TypeError):
mmcv.scandir(folder, 111) list(mmcv.scandir(folder, 111))
# Copyright (c) Open-MMLab. All rights reserved. # Copyright (c) Open-MMLab. All rights reserved.
import os import os
import sys
import time import time
try: try:
...@@ -13,8 +12,6 @@ try: ...@@ -13,8 +12,6 @@ try:
except ImportError: except ImportError:
from io import StringIO from io import StringIO
import pytest # isort:skip
import mmcv # isort:skip import mmcv # isort:skip
...@@ -23,10 +20,6 @@ def reset_string_io(io): ...@@ -23,10 +20,6 @@ def reset_string_io(io):
io.seek(0) io.seek(0)
if sys.version_info[0] == 2:
pytest.skip('skipping tests for python 2', allow_module_level=True)
class TestProgressBar(object): class TestProgressBar(object):
def test_start(self): def test_start(self):
......
...@@ -3,8 +3,7 @@ import os.path as osp ...@@ -3,8 +3,7 @@ import os.path as osp
import sys import sys
import tempfile import tempfile
import warnings import warnings
from unittest.mock import MagicMock
from mock import MagicMock
sys.modules['wandb'] = MagicMock() sys.modules['wandb'] = MagicMock()
...@@ -59,6 +58,6 @@ def test_wandb_hook(): ...@@ -59,6 +58,6 @@ def test_wandb_hook():
}) })
runner.register_hook(hook) runner.register_hook(hook)
runner.run([loader, loader], [('train', 1), ('val', 1)], 1) runner.run([loader, loader], [('train', 1), ('val', 1)], 1)
hook.wandb.init.assert_called() hook.wandb.init.assert_called_with()
hook.wandb.log.assert_called_with({'accuracy/val': 0.98}, step=5) hook.wandb.log.assert_called_with({'accuracy/val': 0.98}, step=5)
hook.wandb.join.assert_called() hook.wandb.join.assert_called_with()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment