From cd99ce804760c1d8f6e23cdc5e1bc7419a173d3d Mon Sep 17 00:00:00 2001 From: Nikita Titov Date: Sun, 21 Feb 2021 18:34:07 +0300 Subject: [PATCH] Drop Python 2 support (#331) * Update Readme.rst * Update .appveyor.yml * Update DESCRIPTION * Update setup.py * Update README.md * Update setup.py * Update __init__.py * Update fastrgf_model.py * Update rgf_model.py * Update sklearn.py * Update test_rgf_python.py * Update rgf_model.py * Update fastrgf_model.py * Update Dockerfile * Update .appveyor.yml * Update Readme.rst * Update rgf_model.py * Update fastrgf_model.py * Update setup.py * Update utils.py * Update utils.py * Update utils.py * Update utils.py * Update utils.py --- .appveyor.yml | 4 +-- R-package/DESCRIPTION | 2 +- R-package/README.md | 8 ++--- python-package/Readme.rst | 3 +- python-package/docker/Dockerfile | 2 +- python-package/rgf/__init__.py | 3 -- python-package/rgf/fastrgf_model.py | 15 ++++----- python-package/rgf/rgf_model.py | 23 ++++++-------- python-package/rgf/sklearn.py | 2 -- python-package/rgf/utils.py | 20 ++++++------ python-package/setup.py | 7 ++--- python-package/tests/test_rgf_python.py | 42 ++++++++++++------------- 12 files changed, 56 insertions(+), 75 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index a1483262..41c13cb7 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -9,7 +9,6 @@ environment: global: R_LIB_PATH: C:\RLibrary matrix: - - PYTHON_VERSION: 2.7 - PYTHON_VERSION: 3.6 - PYTHON_VERSION: 3.7 - PYTHON_VERSION: 3.8 @@ -27,7 +26,6 @@ install: - set PATH=%PATH:C:\Program Files\Git\usr\bin;=% # Delete sh.exe from PATH (mingw32-make fix) - ps: >- switch($env:PYTHON_VERSION) { - "2.7" {$env:MINICONDA = "C:\Miniconda"} "3.6" {$env:MINICONDA = "C:\Miniconda36"} "3.7" {$env:MINICONDA = "C:\Miniconda37"} default {$env:MINICONDA = "C:\Miniconda37"} @@ -41,7 +39,7 @@ install: - set PATH=%MINICONDA%;%MINICONDA%\Scripts;%PATH% - conda config --set always_yes yes --set changeps1 no - conda update -q conda - - conda create -q -n test-environment python=%PYTHON_VERSION% joblib six numpy scipy pandas scikit-learn pytest + - conda create -q -n test-environment python=%PYTHON_VERSION% joblib numpy scipy pandas scikit-learn pytest - activate test-environment - cd python-package - ps: $env:RGF_VER = (Get-Content rgf\VERSION).trim() diff --git a/R-package/DESCRIPTION b/R-package/DESCRIPTION index d3928c5f..70683b14 100644 --- a/R-package/DESCRIPTION +++ b/R-package/DESCRIPTION @@ -9,7 +9,7 @@ BugReports: https://github.com/RGF-team/rgf/issues URL: https://github.com/RGF-team/rgf/tree/master/R-package Description: Regularized Greedy Forest wrapper of the 'Regularized Greedy Forest' 'python' package, which also includes a Multi-core implementation (FastRGF) . License: MIT + file LICENSE -SystemRequirements: Python (2.7 or >= 3.6), rgf_python, scikit-learn (>= 0.18.0), scipy, numpy. Detailed installation instructions for each operating system can be found in the README file. +SystemRequirements: Python (>= 3.6), rgf_python, scikit-learn (>= 0.18.0), scipy, numpy. Detailed installation instructions for each operating system can be found in the README file. Depends: R(>= 3.2.0) Imports: diff --git a/R-package/README.md b/R-package/README.md index ef7e62a4..0a0465f4 100644 --- a/R-package/README.md +++ b/R-package/README.md @@ -35,7 +35,7 @@ The **RGF** package is a wrapper of the [Regularized Greedy Forest (RGF)](https:
-* Python (2.7 or >= 3.6) +* Python (>= 3.6)
@@ -44,7 +44,7 @@ All modules should be installed in the default python configuration (the configu
-#### **Debian/Ubuntu/Fedora** [ installed / tested on Python 2.7 ] +#### **Debian/Ubuntu/Fedora**
@@ -87,7 +87,7 @@ sudo python setup.py install -#### **Mac OS X** [ installed / tested on Python >= 3.6 ] +#### **Mac OS X**
@@ -247,7 +247,7 @@ UserWarning: Cannot find FastRGF executable files. FastRGF estimators will be un

-#### **Windows OS** [ installed / tested on Python >= 3.6 ] +#### **Windows OS**
diff --git a/python-package/Readme.rst b/python-package/Readme.rst index e9170593..6a26076b 100644 --- a/python-package/Readme.rst +++ b/python-package/Readme.rst @@ -54,9 +54,8 @@ Examples of using FastRGF estimators could be found `here = 3.6) +- Python (>= 3.6) - joblib -- six - scikit-learn (>= 0.18) Installation diff --git a/python-package/docker/Dockerfile b/python-package/docker/Dockerfile index d3bfc213..9025e410 100644 --- a/python-package/docker/Dockerfile +++ b/python-package/docker/Dockerfile @@ -10,7 +10,7 @@ RUN apt-get update && \ /bin/bash Miniconda3-latest-Linux-x86_64.sh -f -b -p /opt/conda && \ export PATH="/opt/conda/bin:$PATH" && \ # rgf_python - conda install -y -q numpy joblib six scipy scikit-learn pandas && \ + conda install -y -q numpy joblib scipy scikit-learn pandas && \ git clone https://github.com/RGF-team/rgf.git && \ cd rgf/python-package && python setup.py install && \ diff --git a/python-package/rgf/__init__.py b/python-package/rgf/__init__.py index c74cd4a0..0ca600b6 100644 --- a/python-package/rgf/__init__.py +++ b/python-package/rgf/__init__.py @@ -1,6 +1,3 @@ -from __future__ import absolute_import - - __all__ = ('RGFClassifier', 'RGFRegressor', 'FastRGFClassifier', 'FastRGFRegressor') diff --git a/python-package/rgf/fastrgf_model.py b/python-package/rgf/fastrgf_model.py index 6c7b10ae..3cbf24d6 100644 --- a/python-package/rgf/fastrgf_model.py +++ b/python-package/rgf/fastrgf_model.py @@ -1,11 +1,8 @@ -from __future__ import absolute_import - import os from math import ceil import numpy as np from joblib import cpu_count -from six import string_types from sklearn.base import ClassifierMixin, RegressorMixin, is_classifier from sklearn.exceptions import NotFittedError @@ -193,7 +190,7 @@ def _validate_params(self, elif l2 < 0: raise ValueError("l2 must be no smaller than 0.0 but was %r." % l2) - if not isinstance(opt_algorithm, string_types): + if not isinstance(opt_algorithm, str): raise ValueError("opt_algorithm must be a string, got {0}.".format( type(opt_algorithm))) elif opt_algorithm not in ALGORITHMS: @@ -257,14 +254,14 @@ def _validate_params(self, raise ValueError( "verbose must be no smaller than 0 but was %r." % verbose) - if not isinstance(loss, string_types): + if not isinstance(loss, str): raise ValueError( "loss must be a string, got {0}.".format(type(loss))) elif loss not in LOSSES: raise ValueError( "loss must be 'LS' or 'MODLS' or 'LOGISTIC' but was %r." % loss) - if not isinstance(calc_prob, string_types): + if not isinstance(calc_prob, str): raise ValueError( "calc_prob must be a string, got {0}.".format(type(calc_prob))) elif calc_prob not in ("sigmoid", "softmax"): @@ -317,7 +314,7 @@ def _set_params_with_dependencies(self): self._set_target_and_loss() def _get_params(self): - res = super(FastRGFEstimatorBase, self)._get_params() + res = super()._get_params() res.update(dict(max_depth=self.max_depth, max_leaf=self.max_leaf, tree_gain_ratio=self.tree_gain_ratio, @@ -373,7 +370,7 @@ def __init__(self, verbose=0): if not utils.Config().FASTRGF_AVAILABLE: raise Exception('FastRGF estimators are unavailable for usage.') - super(FastRGFRegressor, self).__init__() + super().__init__() self.n_estimators = n_estimators self.max_depth = max_depth self.max_leaf = max_leaf @@ -430,7 +427,7 @@ def __init__(self, verbose=0): if not utils.Config().FASTRGF_AVAILABLE: raise Exception('FastRGF estimators are unavailable for usage.') - super(FastRGFClassifier, self).__init__() + super().__init__() self.n_estimators = n_estimators self.max_depth = max_depth self.max_leaf = max_leaf diff --git a/python-package/rgf/rgf_model.py b/python-package/rgf/rgf_model.py index c758cd66..8a0848d3 100644 --- a/python-package/rgf/rgf_model.py +++ b/python-package/rgf/rgf_model.py @@ -1,12 +1,9 @@ -from __future__ import absolute_import - from glob import glob from math import ceil from shutil import copyfile import numpy as np from joblib import Parallel, delayed, cpu_count -from six import string_types from sklearn.base import ClassifierMixin, RegressorMixin, is_classifier from sklearn.exceptions import NotFittedError @@ -182,14 +179,14 @@ def _validate_params(self, raise ValueError( "test_interval must be greater than 0 but was %r." % test_interval) - if not isinstance(algorithm, string_types): + if not isinstance(algorithm, str): raise ValueError( "algorithm must be a string, got {0}.".format(type(algorithm))) elif algorithm not in ALGORITHMS: raise ValueError( "algorithm must be 'RGF' or 'RGF_Opt' or 'RGF_Sib' but was %r." % algorithm) - if not isinstance(loss, string_types): + if not isinstance(loss, str): raise ValueError( "loss must be a string, got {0}.".format(type(loss))) elif loss not in LOSSES: @@ -269,19 +266,19 @@ def _validate_params(self, raise ValueError( "verbose must be no smaller than 0 but was %r." % verbose) - if not isinstance(memory_policy, string_types): + if not isinstance(memory_policy, str): raise ValueError("memory_policy must be a string, got {0}.".format( type(memory_policy))) elif memory_policy not in ("conservative", "generous"): raise ValueError( "memory_policy must be 'conservative' or 'generous' but was %r." % memory_policy) - if init_model is not None and not isinstance(init_model, string_types): + if init_model is not None and not isinstance(init_model, str): raise ValueError( "init_model must be a string or None, got {0}.".format( type(init_model))) - if not isinstance(calc_prob, string_types): + if not isinstance(calc_prob, str): raise ValueError( "calc_prob must be a string, got {0}.".format(type(calc_prob))) elif calc_prob not in ("sigmoid", "softmax"): @@ -345,7 +342,7 @@ def _set_params_with_dependencies(self): self._n_iter = self.n_iter def _get_params(self): - res = super(RGFEstimatorBase, self)._get_params() + res = super()._get_params() res.update(dict(max_leaf=self.max_leaf, test_interval=self.test_interval, algorithm=self.algorithm, @@ -474,7 +471,7 @@ def __init__(self, init_model=None): if not utils.Config().RGF_AVAILABLE: raise Exception('RGF estimators are unavailable for usage.') - super(RGFRegressor, self).__init__() + super().__init__() self.max_leaf = max_leaf self.test_interval = test_interval self.algorithm = algorithm @@ -508,7 +505,7 @@ def __init__(self, __doc__ = __doc__.replace(_template, _value) def save_model(self, filename): - super(RGFRegressor, self).save_model(filename) + super().save_model(filename) _regressor_save_model_specific_values = { '{%file_singular_or_plural%}': 'file', @@ -541,7 +538,7 @@ def __init__(self, init_model=None): if not utils.Config().RGF_AVAILABLE: raise Exception('RGF estimators are unavailable for usage.') - super(RGFClassifier, self).__init__() + super().__init__() self.max_leaf = max_leaf self.test_interval = test_interval self.algorithm = algorithm @@ -596,7 +593,7 @@ def __init__(self, __doc__ = __doc__.replace(_template, _value) def save_model(self, filename): - super(RGFClassifier, self).save_model(filename) + super().save_model(filename) _classifier_save_model_specific_values = { '{%file_singular_or_plural%}': 'file(s)', diff --git a/python-package/rgf/sklearn.py b/python-package/rgf/sklearn.py index 9821678a..a78fa1fa 100644 --- a/python-package/rgf/sklearn.py +++ b/python-package/rgf/sklearn.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import - __all__ = ('RGFClassifier', 'RGFRegressor', 'FastRGFClassifier', 'FastRGFRegressor') diff --git a/python-package/rgf/utils.py b/python-package/rgf/utils.py index e7905d08..8ab73e9a 100644 --- a/python-package/rgf/utils.py +++ b/python-package/rgf/utils.py @@ -1,5 +1,3 @@ -from __future__ import absolute_import - import atexit import codecs import glob @@ -9,11 +7,12 @@ import stat import subprocess import warnings +from configparser import MissingSectionHeaderError, RawConfigParser +from io import StringIO from tempfile import gettempdir from threading import Lock from uuid import uuid4 -import six import numpy as np import scipy.sparse as sp from sklearn.base import BaseEstimator @@ -74,17 +73,17 @@ def __init__(self, verbose=False): @classmethod def init_paths(cls): if cls.TEMP_PATH is None: - config = six.moves.configparser.RawConfigParser() + config = RawConfigParser() path = os.path.join(os.path.expanduser('~'), '.rgfrc') try: with codecs.open(path, 'r', 'utf-8') as cfg: - with six.StringIO(cfg.read()) as strIO: - config.readfp(strIO) - except six.moves.configparser.MissingSectionHeaderError: + with StringIO(cfg.read()) as strIO: + config.read_file(strIO) + except MissingSectionHeaderError: with codecs.open(path, 'r', 'utf-8') as cfg: - with six.StringIO('[glob]\n' + cfg.read()) as strIO: - config.readfp(strIO) + with StringIO('[glob]\n' + cfg.read()) as strIO: + config.read_file(strIO) except Exception: pass @@ -244,7 +243,6 @@ def increment(self): def sparse_savetxt(filename, input_array, including_header=True): - zip_func = six.moves.zip if sp.isspmatrix_csr(input_array): input_array = input_array.tocoo() else: @@ -255,7 +253,7 @@ def sparse_savetxt(filename, input_array, including_header=True): with open(filename, 'w') as fw: if including_header: fw.write('sparse {0:d}\n'.format(input_array.shape[-1])) - for i, j, v in zip_func(input_array.row, input_array.col, input_array.data): + for i, j, v in zip(input_array.row, input_array.col, input_array.data): if i == current_sample_row: line.append('{0}:{1}'.format(j, v)) else: diff --git a/python-package/setup.py b/python-package/setup.py index c3a62eb8..8d039245 100644 --- a/python-package/setup.py +++ b/python-package/setup.py @@ -5,7 +5,6 @@ from setuptools.command.install_lib import install_lib from setuptools.command.sdist import sdist from shutil import rmtree -import io import logging import os import subprocess @@ -19,7 +18,7 @@ def read(filename): - return io.open(os.path.join(CURRENT_DIR, filename), encoding='utf-8').read() + return open(os.path.join(CURRENT_DIR, filename), encoding='utf-8').read() def copy_files(): @@ -380,7 +379,7 @@ def run(self): 'sdist': CustomSdist}, packages=find_packages(), include_package_data=True, - install_requires=["joblib", "six", "scikit-learn>=0.18"], + install_requires=["joblib", "scikit-learn>=0.18"], classifiers=['Development Status :: 5 - Production/Stable', 'Intended Audience :: Science/Research', 'License :: OSI Approved :: MIT License', @@ -389,8 +388,6 @@ def run(self): 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX', 'Operating System :: Unix', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', diff --git a/python-package/tests/test_rgf_python.py b/python-package/tests/test_rgf_python.py index 28c6ffe8..e7c4ac8f 100644 --- a/python-package/tests/test_rgf_python.py +++ b/python-package/tests/test_rgf_python.py @@ -443,24 +443,24 @@ def setUp(self): self.estimator_class = RGFClassifier self.kwargs = {} - super(TestRGFClassifier, self).setUp() + super().setUp() def test_params(self): - super(TestRGFClassifier, self).test_params(add_valid_params={'calc_prob': 'sigmoid', - 'n_jobs': -1}, - add_non_valid_params={'calc_prob': True, - 'n_jobs': '-1'}) + super().test_params(add_valid_params={'calc_prob': 'sigmoid', + 'n_jobs': -1}, + add_non_valid_params={'calc_prob': True, + 'n_jobs': '-1'}) def test_attributes(self): - super(TestRGFClassifier, self).test_attributes(add_attrs=['classes_', - 'n_classes_']) + super().test_attributes(add_attrs=['classes_', + 'n_classes_']) self.assertEqual(len(self.est.estimators_), len(np.unique(self.y_train))) np.testing.assert_array_equal(self.est.classes_, sorted(np.unique(self.y_train))) self.assertEqual(self.est.n_classes_, len(self.est.estimators_)) def test_warm_start(self): self.new_max_leaf = 1050 # +50 to default value - super(TestRGFClassifier, self).test_warm_start() + super().test_warm_start() warm_start_score = accuracy_score(self.y_test, self.y_pred) self.assertGreaterEqual(warm_start_score, self.accuracy, "Failed with score = {0:.5f}".format(warm_start_score)) @@ -471,17 +471,17 @@ def setUp(self): self.estimator_class = FastRGFClassifier self.kwargs = {} - super(TestFastRGFClassifier, self).setUp() + super().setUp() def test_params(self): - super(TestFastRGFClassifier, self).test_params(add_valid_params={'loss': 'LOGISTIC', - 'calc_prob': 'sigmoid'}, - add_non_valid_params={'loss': 'LOG', - 'calc_prob': None}) + super().test_params(add_valid_params={'loss': 'LOGISTIC', + 'calc_prob': 'sigmoid'}, + add_non_valid_params={'loss': 'LOG', + 'calc_prob': None}) def test_attributes(self): - super(TestFastRGFClassifier, self).test_attributes(add_attrs=['classes_', - 'n_classes_']) + super().test_attributes(add_attrs=['classes_', + 'n_classes_']) self.assertEqual(len(self.est.estimators_), len(np.unique(self.y_train))) np.testing.assert_array_equal(self.est.classes_, sorted(np.unique(self.y_train))) self.assertEqual(self.est.n_classes_, len(self.est.estimators_)) @@ -500,10 +500,10 @@ def setUp(self): self.mse = 2.0353275768 - super(TestRGFRegressor, self).setUp() + super().setUp() def test_attributes(self): - super(TestRGFRegressor, self).test_attributes() + super().test_attributes() self.assertEqual(len(self.est.estimators_), 1) def test_abs_regressor(self): @@ -515,7 +515,7 @@ def test_abs_regressor(self): def test_warm_start(self): self.new_max_leaf = 560 # +60 to default value - super(TestRGFRegressor, self).test_warm_start() + super().test_warm_start() warm_start_score = mean_squared_error(self.y_test, self.y_pred) self.assertLess(warm_start_score, self.mse, "Failed with MSE = {0:.5f}".format(warm_start_score)) @@ -528,15 +528,15 @@ def setUp(self): self.mse = 2.5522511545 - super(TestFastRGFRegressor, self).setUp() + super().setUp() def test_attributes(self): - super(TestFastRGFRegressor, self).test_attributes() + super().test_attributes() self.assertEqual(len(self.est.estimators_), 1) def test_parallel_gridsearch(self): self.kwargs['n_jobs'] = 1 - super(TestFastRGFRegressor, self).test_parallel_gridsearch() + super().test_parallel_gridsearch() def test_sklearn_integration(self): # TODO(fukatani): FastRGF bug?