pyFOCI 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pyFOCI/__init__.py ADDED
@@ -0,0 +1,10 @@
1
+ # Authors: scikit-learn-contrib developers
2
+ # License: BSD 3 clause
3
+
4
+ from ._template import TemplateTransformer
5
+ from ._version import __version__
6
+
7
+ __all__ = [
8
+ "TemplateTransformer",
9
+ "__version__",
10
+ ]
pyFOCI/_template.py ADDED
@@ -0,0 +1,97 @@
1
+ """
2
+ This is a module to be used as a reference for building other modules
3
+ """
4
+
5
+ # Authors: scikit-learn-contrib developers
6
+ # License: BSD 3 clause
7
+
8
+ import numpy as np
9
+ from sklearn.base import BaseEstimator, TransformerMixin, _fit_context
10
+
11
+ # from sklearn.utils.validation import check_is_fitted
12
+
13
+
14
+ # Note that the mixin class should always be on the left of `BaseEstimator` to ensure
15
+ # the MRO works as expected.
16
+ class TemplateTransformer(TransformerMixin, BaseEstimator):
17
+ """An example transformer that returns the element-wise square root.
18
+
19
+ For more information regarding how to build your own transformer, read more
20
+ in the :ref:`User Guide <user_guide>`.
21
+
22
+ Parameters
23
+ ----------
24
+ demo_param : str, default='demo'
25
+ A parameter used for demonstation of how to pass and store paramters.
26
+
27
+ Attributes
28
+ ----------
29
+ n_features_in_ : int
30
+ Number of features seen during :term:`fit`.
31
+
32
+ feature_names_in_ : ndarray of shape (`n_features_in_`,)
33
+ Names of features seen during :term:`fit`. Defined only when `X`
34
+ has feature names that are all strings.
35
+ """
36
+
37
+ # This is a dictionary allowing to define the type of parameters.
38
+ # It used to validate parameter within the `_fit_context` decorator.
39
+ _parameter_constraints = {
40
+ "demo_param": [str],
41
+ }
42
+
43
+ def __init__(self, demo_param="demo"):
44
+ self.demo_param = demo_param
45
+
46
+ @_fit_context(prefer_skip_nested_validation=True)
47
+ def fit(self, X, y=None):
48
+ """A reference implementation of a fitting function for a transformer.
49
+
50
+ Parameters
51
+ ----------
52
+ X : {array-like, sparse matrix}, shape (n_samples, n_features)
53
+ The training input samples.
54
+
55
+ y : None
56
+ There is no need of a target in a transformer, yet the pipeline API
57
+ requires this parameter.
58
+
59
+ Returns
60
+ -------
61
+ self : object
62
+ Returns self.
63
+ """
64
+ X = self._validate_data(X, accept_sparse=True)
65
+
66
+ # Return the transformer
67
+ return self
68
+
69
+ def transform(self, X):
70
+ """A reference implementation of a transform function.
71
+
72
+ Parameters
73
+ ----------
74
+ X : {array-like, sparse-matrix}, shape (n_samples, n_features)
75
+ The input samples.
76
+
77
+ Returns
78
+ -------
79
+ X_transformed : array, shape (n_samples, n_features)
80
+ The array containing the element-wise square roots of the values
81
+ in ``X``.
82
+ """
83
+ # Since this is a stateless transformer, we should not call `check_is_fitted`.
84
+ # Common test will check for this particularly.
85
+
86
+ # Input validation
87
+ # We need to set reset=False because we don't want to overwrite `n_features_in_`
88
+ # `feature_names_in_` but only check that the shape is consistent.
89
+ X = self._validate_data(X, accept_sparse=True, reset=False)
90
+ return np.sqrt(X)
91
+
92
+ def _more_tags(self):
93
+ # This is a quick example to show the tags API:\
94
+ # https://scikit-learn.org/dev/developers/develop.html#estimator-tags
95
+ # Here, our transformer does not do any operation in `fit` and only validate
96
+ # the parameters. Thus, it is stateless.
97
+ return {"stateless": True}
pyFOCI/_version.py ADDED
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '0.1.2'
22
+ __version_tuple__ = version_tuple = (0, 1, 2)
23
+
24
+ __commit_id__ = commit_id = None
@@ -0,0 +1,2 @@
1
+ # Authors: scikit-learn-contrib developers
2
+ # License: BSD 3 clause
@@ -0,0 +1,16 @@
1
+ """This file shows how to write test based on the scikit-learn common tests."""
2
+
3
+ # Authors: scikit-learn-contrib developers
4
+ # License: BSD 3 clause
5
+
6
+ from sklearn.utils.estimator_checks import parametrize_with_checks
7
+
8
+ from pyFOCI.utils.discovery import all_estimators
9
+
10
+
11
+ # parametrize_with_checks allows to get a generator of check that is more fine-grained
12
+ # than check_estimator
13
+ @parametrize_with_checks([est() for _, est in all_estimators()])
14
+ def test_estimators(estimator, check, request):
15
+ """Check the compatibility with scikit-learn API"""
16
+ check(estimator)
@@ -0,0 +1,31 @@
1
+ """This file will just show how to write tests for the template classes."""
2
+ import numpy as np
3
+ import pytest
4
+ from sklearn.datasets import load_iris
5
+ from sklearn.utils._testing import assert_allclose
6
+
7
+ from pyFOCI import TemplateTransformer
8
+
9
+ # Authors: scikit-learn-contrib developers
10
+ # License: BSD 3 clause
11
+
12
+
13
+ @pytest.fixture
14
+ def data():
15
+ return load_iris(return_X_y=True)
16
+
17
+
18
+ def test_template_transformer(data):
19
+ """Check the internals and behaviour of `TemplateTransformer`."""
20
+ X, y = data
21
+ trans = TemplateTransformer()
22
+ assert trans.demo_param == "demo"
23
+
24
+ trans.fit(X)
25
+ assert trans.n_features_in_ == X.shape[1]
26
+
27
+ X_trans = trans.transform(X)
28
+ assert_allclose(X_trans, np.sqrt(X))
29
+
30
+ X_trans = trans.fit_transform(X)
31
+ assert_allclose(X_trans, np.sqrt(X))
@@ -0,0 +1,2 @@
1
+ # Authors: scikit-learn-contrib developers
2
+ # License: BSD 3 clause
@@ -0,0 +1,207 @@
1
+ """
2
+ The :mod:`pyFOCI.utils.discovery` module includes utilities to discover
3
+ objects (i.e. estimators, displays, functions) from the `pyFOCI` package.
4
+ """
5
+
6
+ # Adapted from scikit-learn
7
+ # Authors: scikit-learn-contrib developers
8
+ # License: BSD 3 clause
9
+
10
+ import inspect
11
+ import pkgutil
12
+ from importlib import import_module
13
+ from operator import itemgetter
14
+ from pathlib import Path
15
+
16
+ from sklearn.base import (
17
+ BaseEstimator,
18
+ ClassifierMixin,
19
+ ClusterMixin,
20
+ RegressorMixin,
21
+ TransformerMixin,
22
+ )
23
+ from sklearn.utils._testing import ignore_warnings
24
+
25
+ _MODULE_TO_IGNORE = {"tests"}
26
+
27
+
28
+ def all_estimators(type_filter=None):
29
+ """Get a list of all estimators from `pyFOCI`.
30
+
31
+ This function crawls the module and gets all classes that inherit
32
+ from `BaseEstimator`. Classes that are defined in test-modules are not
33
+ included.
34
+
35
+ Parameters
36
+ ----------
37
+ type_filter : {"classifier", "regressor", "cluster", "transformer"} \
38
+ or list of such str, default=None
39
+ Which kind of estimators should be returned. If None, no filter is
40
+ applied and all estimators are returned. Possible values are
41
+ 'classifier', 'regressor', 'cluster' and 'transformer' to get
42
+ estimators only of these specific types, or a list of these to
43
+ get the estimators that fit at least one of the types.
44
+
45
+ Returns
46
+ -------
47
+ estimators : list of tuples
48
+ List of (name, class), where ``name`` is the class name as string
49
+ and ``class`` is the actual type of the class.
50
+
51
+ Examples
52
+ --------
53
+ >>> from pyFOCI.utils.discovery import all_estimators
54
+ >>> estimators = all_estimators()
55
+ >>> type(estimators)
56
+ <class 'list'>
57
+ """
58
+
59
+ def is_abstract(c):
60
+ return hasattr(c, "__abstractmethods__") and len(c.__abstractmethods__)
61
+
62
+ all_classes = []
63
+ root = str(Path(__file__).parent.parent) # pyFOCI package
64
+ # Ignore deprecation warnings triggered at import time and from walking
65
+ # packages
66
+ with ignore_warnings(category=FutureWarning):
67
+ for _, module_name, _ in pkgutil.walk_packages(path=[root], prefix="pyFOCI."):
68
+ module_parts = module_name.split(".")
69
+ if any(part in _MODULE_TO_IGNORE for part in module_parts):
70
+ continue
71
+ module = import_module(module_name)
72
+ classes = inspect.getmembers(module, inspect.isclass)
73
+ classes = [
74
+ (name, est_cls) for name, est_cls in classes if not name.startswith("_")
75
+ ]
76
+
77
+ all_classes.extend(classes)
78
+
79
+ all_classes = set(all_classes)
80
+
81
+ estimators = [
82
+ c
83
+ for c in all_classes
84
+ if (issubclass(c[1], BaseEstimator) and c[0] != "BaseEstimator")
85
+ ]
86
+ # get rid of abstract base classes
87
+ estimators = [c for c in estimators if not is_abstract(c[1])]
88
+
89
+ if type_filter is not None:
90
+ if not isinstance(type_filter, list):
91
+ type_filter = [type_filter]
92
+ else:
93
+ type_filter = list(type_filter) # copy
94
+ filtered_estimators = []
95
+ filters = {
96
+ "classifier": ClassifierMixin,
97
+ "regressor": RegressorMixin,
98
+ "transformer": TransformerMixin,
99
+ "cluster": ClusterMixin,
100
+ }
101
+ for name, mixin in filters.items():
102
+ if name in type_filter:
103
+ type_filter.remove(name)
104
+ filtered_estimators.extend(
105
+ [est for est in estimators if issubclass(est[1], mixin)]
106
+ )
107
+ estimators = filtered_estimators
108
+ if type_filter:
109
+ raise ValueError(
110
+ "Parameter type_filter must be 'classifier', "
111
+ "'regressor', 'transformer', 'cluster' or "
112
+ "None, got"
113
+ f" {repr(type_filter)}."
114
+ )
115
+
116
+ # drop duplicates, sort for reproducibility
117
+ # itemgetter is used to ensure the sort does not extend to the 2nd item of
118
+ # the tuple
119
+ return sorted(set(estimators), key=itemgetter(0))
120
+
121
+
122
+ def all_displays():
123
+ """Get a list of all displays from `pyFOCI`.
124
+
125
+ Returns
126
+ -------
127
+ displays : list of tuples
128
+ List of (name, class), where ``name`` is the display class name as
129
+ string and ``class`` is the actual type of the class.
130
+
131
+ Examples
132
+ --------
133
+ >>> from pyFOCI.utils.discovery import all_displays
134
+ >>> displays = all_displays()
135
+ """
136
+ all_classes = []
137
+ root = str(Path(__file__).parent.parent) # pyFOCI package
138
+ # Ignore deprecation warnings triggered at import time and from walking
139
+ # packages
140
+ with ignore_warnings(category=FutureWarning):
141
+ for _, module_name, _ in pkgutil.walk_packages(path=[root], prefix="pyFOCI."):
142
+ module_parts = module_name.split(".")
143
+ if any(part in _MODULE_TO_IGNORE for part in module_parts):
144
+ continue
145
+ module = import_module(module_name)
146
+ classes = inspect.getmembers(module, inspect.isclass)
147
+ classes = [
148
+ (name, display_class)
149
+ for name, display_class in classes
150
+ if not name.startswith("_") and name.endswith("Display")
151
+ ]
152
+ all_classes.extend(classes)
153
+
154
+ return sorted(set(all_classes), key=itemgetter(0))
155
+
156
+
157
+ def _is_checked_function(item):
158
+ if not inspect.isfunction(item):
159
+ return False
160
+
161
+ if item.__name__.startswith("_"):
162
+ return False
163
+
164
+ mod = item.__module__
165
+ if not mod.startswith("pyFOCI.") or mod.endswith("estimator_checks"):
166
+ return False
167
+
168
+ return True
169
+
170
+
171
+ def all_functions():
172
+ """Get a list of all functions from `pyFOCI`.
173
+
174
+ Returns
175
+ -------
176
+ functions : list of tuples
177
+ List of (name, function), where ``name`` is the function name as
178
+ string and ``function`` is the actual function.
179
+
180
+ Examples
181
+ --------
182
+ >>> from pyFOCI.utils.discovery import all_functions
183
+ >>> functions = all_functions()
184
+ """
185
+ all_functions = []
186
+ root = str(Path(__file__).parent.parent) # pyFOCI package
187
+ # Ignore deprecation warnings triggered at import time and from walking
188
+ # packages
189
+ with ignore_warnings(category=FutureWarning):
190
+ for _, module_name, _ in pkgutil.walk_packages(path=[root], prefix="pyFOCI."):
191
+ module_parts = module_name.split(".")
192
+ if any(part in _MODULE_TO_IGNORE for part in module_parts):
193
+ continue
194
+
195
+ module = import_module(module_name)
196
+ functions = inspect.getmembers(module, _is_checked_function)
197
+ functions = [
198
+ (func.__name__, func)
199
+ for name, func in functions
200
+ if not name.startswith("_")
201
+ ]
202
+ all_functions.extend(functions)
203
+
204
+ # drop duplicates, sort for reproducibility
205
+ # itemgetter is used to ensure the sort does not extend to the 2nd item of
206
+ # the tuple
207
+ return sorted(set(all_functions), key=itemgetter(0))
@@ -0,0 +1,2 @@
1
+ # Authors: scikit-learn-contrib developers
2
+ # License: BSD 3 clause
@@ -0,0 +1,31 @@
1
+ # Authors: scikit-learn-contrib developers
2
+ # License: BSD 3 clause
3
+
4
+ import pytest
5
+
6
+ from pyFOCI.utils.discovery import all_displays, all_estimators, all_functions
7
+
8
+
9
+ def test_all_estimators():
10
+ estimators = all_estimators()
11
+ assert len(estimators) == 1
12
+
13
+ estimators = all_estimators(type_filter="classifier")
14
+ assert len(estimators) == 0
15
+
16
+ estimators = all_estimators(type_filter=["classifier", "transformer"])
17
+ assert len(estimators) == 1
18
+
19
+ err_msg = "Parameter type_filter must be"
20
+ with pytest.raises(ValueError, match=err_msg):
21
+ all_estimators(type_filter="xxxx")
22
+
23
+
24
+ def test_all_displays():
25
+ displays = all_displays()
26
+ assert len(displays) == 0
27
+
28
+
29
+ def test_all_functions():
30
+ functions = all_functions()
31
+ assert len(functions) == 3
@@ -0,0 +1,42 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyFOCI
3
+ Version: 0.1.2
4
+ Summary: A template for scikit-learn compatible packages.
5
+ Author-email: Robert Pollak <robert.pollak@jku.at>
6
+ Project-URL: Homepage, https://github.com/scikit-learn-contrib/pyFOCI
7
+ Project-URL: Issues, https://github.com/scikit-learn-contrib/pyFOCI/issues
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.9
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: License :: OSI Approved :: BSD License
14
+ Classifier: Operating System :: POSIX
15
+ Classifier: Operating System :: Unix
16
+ Classifier: Operating System :: MacOS
17
+ Classifier: Operating System :: Microsoft :: Windows
18
+ Requires-Python: >=3.9
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: scikit-learn>=1.4.2
22
+ Requires-Dist: numpy
23
+ Dynamic: license-file
24
+
25
+ pyFOCI - A template for scikit-learn contributions
26
+ ============================================================
27
+
28
+ ![tests](https://github.com/m3dm-jku/pyFOCI/actions/workflows/python-app.yml/badge.svg)
29
+ [![codecov](https://codecov.io/gh/m3dm-jku/pyFOCI/graph/badge.svg?token=L0XPWwoPLw)](https://codecov.io/gh/m3dm-jku/pyFOCI)
30
+ ![doc](https://github.com/m3dm-jku/pyFOCI/actions/workflows/deploy-gh-pages.yml/badge.svg)
31
+
32
+ **pyFOCI** is a template project for [scikit-learn](https://scikit-learn.org)
33
+ compatible extensions.
34
+
35
+ It aids development of estimators that can be used in scikit-learn pipelines and
36
+ (hyper)parameter search, while facilitating testing (including some API compliance),
37
+ documentation, open source development, packaging, and continuous integration.
38
+
39
+ Refer to the documentation to modify the template for your own scikit-learn
40
+ contribution: https://m3dm-jku.github.io/pyFOCI/
41
+
42
+ *Thank you for cleanly contributing to the scikit-learn ecosystem!*
@@ -0,0 +1,15 @@
1
+ pyFOCI/__init__.py,sha256=LYC65o81QAJLGG-tg4_nBBMoibYPceEvHc-sf3FWybY,206
2
+ pyFOCI/_template.py,sha256=DWW6uFD35drYsfg3peBR5ITHcxhH-IoiL2DrymP_LQ4,3252
3
+ pyFOCI/_version.py,sha256=Q6ScJXlkBsUI-cazSvpYPMyIVUB-Vd0R3pq3_rM1wmI,520
4
+ pyFOCI/tests/__init__.py,sha256=OLs978IP7BWkfydS9GzMQg4oPPAsQl9dEfxS2iQD9nI,67
5
+ pyFOCI/tests/test_common.py,sha256=495dtSmqcMcDf_sKVPa3daaaQbOhSXoOlApxNfkqwcM,569
6
+ pyFOCI/tests/test_template.py,sha256=axZXhXw6xhWchUK7AJNiSEpNSN-J8gW5oqRc36HxCqI,790
7
+ pyFOCI/utils/__init__.py,sha256=OLs978IP7BWkfydS9GzMQg4oPPAsQl9dEfxS2iQD9nI,67
8
+ pyFOCI/utils/discovery.py,sha256=pvuOT4FsEgJyb17GaMt0_YeLgNBbUdWrNB3p3DI9XDU,6925
9
+ pyFOCI/utils/tests/__init__.py,sha256=OLs978IP7BWkfydS9GzMQg4oPPAsQl9dEfxS2iQD9nI,67
10
+ pyFOCI/utils/tests/test_discovery.py,sha256=fUYuWf_7mQin3r-AB3IQUhkeDDcLQ6FA7UvOC_rWha4,775
11
+ pyfoci-0.1.2.dist-info/licenses/LICENSE,sha256=HNmyx4jx1L81VhLt28JSV5MVbHVpb8xXOqx475vPl2I,1495
12
+ pyfoci-0.1.2.dist-info/METADATA,sha256=dh4cPUILRyBxEWY5Zsxlys5zMwEMZNtNMdLQgbkMJCE,1895
13
+ pyfoci-0.1.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
14
+ pyfoci-0.1.2.dist-info/top_level.txt,sha256=PuXEIncLIBHOETKKrnkjvF8s30Rr-6iywGsxBlUF08E,7
15
+ pyfoci-0.1.2.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2026, Johannes Kepler University Linz
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ * Neither the name of pyFOCI nor the names of its
15
+ contributors may be used to endorse or promote products derived from
16
+ this software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1 @@
1
+ pyFOCI