From b627bb7531e01a12ead0825f3ace71071721563c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Monta=C3=B1ana=20G=C3=B3mez?= Date: Tue, 13 Aug 2024 13:28:32 +0200 Subject: [PATCH] Add pyproject.toml install information Add __call__ method to support sklearn ensembles requirements for base estimators Update tests --- MANIFEST.in | 1 + pyproject.toml | 65 ++++++++++++++++++++++++++++++++++++++- setup.py | 56 --------------------------------- stree/Strees.py | 4 +++ stree/__init__.py | 3 +- stree/_version.py | 2 +- stree/tests/Stree_test.py | 17 ++++++---- 7 files changed, 83 insertions(+), 65 deletions(-) create mode 100644 MANIFEST.in delete mode 100644 setup.py diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..7152b80 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include README.md LICENSE \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 9bd6669..184dff4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,68 @@ +[build-system] +requires = ["setuptools", "scikit-learn>1.0", "numpy", "mufs"] +build-backend = "setuptools.build_meta" + +[tool.setuptools] +packages = ["stree"] +license-files = ["LICENSE"] + +[tool.setuptools.dynamic] +version = { attr = "stree.__version__" } + +[project] +name = "STree" +dependencies = ["scikit-learn>1.0", "numpy", "mufs"] +license = { file = "LICENSE" } +description = "Oblique decision tree with svm nodes." +readme = "README.md" +authors = [ + { name = "Ricardo Montañana", email = "ricardo.montanana@alu.uclm.es" }, +] +dynamic = ['version'] +requires-python = ">=3.8" +keywords = [ + "scikit-learn", + "oblique-classifier", + "oblique-decision-tree", + "decision-tree", + "svm", + "svc", +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Science/Research", + "Intended Audience :: Developers", + "Topic :: Software Development", + "Topic :: Scientific/Engineering", + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] + +[project.optional-dependencies] +dev = ["black", "flake8", "mypy", "coverage"] + +[project.urls] +Code = "https://github.com/Doctorado-ML/STree" +Documentation = "https://stree.readthedocs.io/en/latest/index.html" + +[tool.coverage.run] +branch = true +source = ["stree"] +command_line = "-m unittest discover -s stree.tests" + +[tool.coverage.report] +show_missing = true +fail_under = 100 + [tool.black] line-length = 79 +target_version = ['py311'] include = '\.pyi?$' exclude = ''' /( @@ -13,4 +76,4 @@ exclude = ''' | build | dist )/ -''' \ No newline at end of file +''' diff --git a/setup.py b/setup.py deleted file mode 100644 index 7333fb0..0000000 --- a/setup.py +++ /dev/null @@ -1,56 +0,0 @@ -import setuptools -import os - - -def readme(): - with open("README.md") as f: - return f.read() - - -def get_data(field, file_name="__init__.py"): - item = "" - with open(os.path.join("stree", file_name)) as f: - for line in f.readlines(): - if line.startswith(f"__{field}__"): - delim = '"' if '"' in line else "'" - item = line.split(delim)[1] - break - else: - raise RuntimeError(f"Unable to find {field} string.") - return item - - -def get_requirements(): - with open("requirements.txt") as f: - return f.read().splitlines() - - -setuptools.setup( - name="STree", - version=get_data("version", "_version.py"), - license=get_data("license"), - description="Oblique decision tree with svm nodes", - long_description=readme(), - long_description_content_type="text/markdown", - packages=setuptools.find_packages(), - url="https://github.com/Doctorado-ML/STree#stree", - project_urls={ - "Code": "https://github.com/Doctorado-ML/STree", - "Documentation": "https://stree.readthedocs.io/en/latest/index.html", - }, - author=get_data("author"), - author_email=get_data("author_email"), - keywords="scikit-learn oblique-classifier oblique-decision-tree decision-\ - tree svm svc", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "License :: OSI Approved :: " + get_data("license"), - "Programming Language :: Python :: 3.8", - "Natural Language :: English", - "Topic :: Scientific/Engineering :: Artificial Intelligence", - "Intended Audience :: Science/Research", - ], - install_requires=get_requirements(), - test_suite="stree.tests", - zip_safe=False, -) diff --git a/stree/Strees.py b/stree/Strees.py index fd618c4..4c242fd 100644 --- a/stree/Strees.py +++ b/stree/Strees.py @@ -174,6 +174,10 @@ class Stree(BaseEstimator, ClassifierMixin): """Return the version of the package.""" return __version__ + def __call__(self) -> str: + """Only added to comply with scikit-learn base estimator for ensemble""" + return self.version() + def _more_tags(self) -> dict: """Required by sklearn to supply features of the classifier make mandatory the labels array diff --git a/stree/__init__.py b/stree/__init__.py index bcb2514..02a5999 100644 --- a/stree/__init__.py +++ b/stree/__init__.py @@ -1,8 +1,9 @@ from .Strees import Stree, Siterator +from ._version import __version__ __author__ = "Ricardo Montañana Gómez" __copyright__ = "Copyright 2020-2021, Ricardo Montañana Gómez" __license__ = "MIT License" __author_email__ = "ricardo.montanana@alu.uclm.es" -__all__ = ["Stree", "Siterator"] +__all__ = ["__version__", "Stree", "Siterator"] diff --git a/stree/_version.py b/stree/_version.py index f708a9b..3e8d9f9 100644 --- a/stree/_version.py +++ b/stree/_version.py @@ -1 +1 @@ -__version__ = "1.3.2" +__version__ = "1.4.0" diff --git a/stree/tests/Stree_test.py b/stree/tests/Stree_test.py index 6a0a70f..df99100 100644 --- a/stree/tests/Stree_test.py +++ b/stree/tests/Stree_test.py @@ -289,12 +289,12 @@ class Stree_test(unittest.TestCase): "impurity sigmoid": 0.824, }, "Iris": { - "max_samples liblinear": 0.9550561797752809, + "max_samples liblinear": 0.9887640449438202, "max_samples linear": 1.0, "max_samples rbf": 0.6685393258426966, "max_samples poly": 0.6853932584269663, "max_samples sigmoid": 0.6404494382022472, - "impurity liblinear": 0.9550561797752809, + "impurity liblinear": 0.9887640449438202, "impurity linear": 1.0, "impurity rbf": 0.6685393258426966, "impurity poly": 0.6853932584269663, @@ -440,10 +440,10 @@ class Stree_test(unittest.TestCase): clf.fit(X, y) score = clf.score(X, y) # Check accuracy of the whole model - self.assertAlmostEquals(0.98, score, 5) + self.assertAlmostEqual(0.98, score, 5) svm = LinearSVC(random_state=0) svm.fit(X, y) - self.assertAlmostEquals(0.9666666666666667, svm.score(X, y), 5) + self.assertAlmostEqual(0.9666666666666667, svm.score(X, y), 5) data = svm.decision_function(X) expected = [ 0.4444444444444444, @@ -455,7 +455,7 @@ class Stree_test(unittest.TestCase): ty[data > 0] = 1 ty = ty.astype(int) for i in range(3): - self.assertAlmostEquals( + self.assertAlmostEqual( expected[i], clf.splitter_._gini(ty[:, i]), ) @@ -593,7 +593,7 @@ class Stree_test(unittest.TestCase): ) self.assertEqual(0.9526666666666667, clf2.fit(X, y).score(X, y)) X, y = load_wine(return_X_y=True) - self.assertEqual(0.9831460674157303, clf.fit(X, y).score(X, y)) + self.assertEqual(0.9887640449438202, clf.fit(X, y).score(X, y)) self.assertEqual(1.0, clf2.fit(X, y).score(X, y)) def test_zero_all_sample_weights(self): @@ -725,6 +725,11 @@ class Stree_test(unittest.TestCase): clf = Stree() self.assertEqual(__version__, clf.version()) + def test_call(self) -> None: + """Check call method.""" + clf = Stree() + self.assertEqual(__version__, clf()) + def test_graph(self): """Check graphviz representation of the tree.""" X, y = load_wine(return_X_y=True)