Skip to content

Commit 47b52be

Browse files
committed
Initial brownout README.md and implementation
1 parent b8a8f40 commit 47b52be

File tree

3 files changed

+150
-31
lines changed

3 files changed

+150
-31
lines changed

README.md

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,68 @@
1-
**Note:** `sklearn` package on PyPI exists to prevent bad actors to use the
2-
name. `scikit-learn` is the actual package name and should be used with pip,
3-
e.g. for:
1+
# Goal
2+
3+
This repo implements brownout for the deprecated `sklearn` package on PyPI.
4+
5+
# Brownout schedule
6+
7+
The following table shows the dates and time window, where an exception will be
8+
raised if you attempt to install the `sklearn` package from PyPI.
9+
10+
| Dates | Window(s) |
11+
|-----------------------------------|--------------------------------|
12+
| 2022 November 1st - December 30th | :00-:05 every hour |
13+
| 2023 January 1st - February 28th | :00-:10 every hour |
14+
| 2023 March 1st - April 30th | :00-:15 every hour |
15+
| 2023 May 1st - June 30th | :00-:10 and :30-:40 every hour |
16+
| 2023 July 1st - August 31st | :00-:15 and :30-45 every hour |
17+
| 2023 September 1st - October 30th | :00-:20 and :00-50 every hour |
18+
| 2023 November 1st onwards | always raise an exception |
19+
20+
# How to fix the error for the main use cases
21+
22+
- use `pip install scikit-learn` rather than `pip install sklearn`
23+
- replace `sklearn` by `scikit-learn` in your pip requirements files
24+
(`requirements.txt`, `setup.py,` `setup.cfg`, `Pipfile`, etc ...)
25+
- if the `sklearn` package is used by one of your dependencies
26+
it would be great if you take some time to track which package uses
27+
`sklearn` instead of `scikit-learn` and report it to their issue tracker
28+
- as last resort, set the environment variable ,
29+
`SKLEARN_ALLOW_DEPRECATED_SKLEARN_PACKAGE_INSTALL=True` to avoid this error
30+
31+
# Reason for the deprecation
32+
33+
`sklearn` package on PyPI exists to prevent malicious actors to use the
34+
`sklearn` package, since `sklearn` (the import name) and `scikit-learn` (the
35+
project name) are sometimes used interchangeably. `scikit-learn` is the actual
36+
package name and should be used with pip, e.g. for:
437
- pip commands: `pip install scikit-learn`
5-
- pip `requirements.txt` files
38+
- pip requirement files (`requirements.txt`, `setup.py,` `setup.cfg`,
39+
`Pipfile`, etc ...)
40+
41+
At the time of writing (October 2022) `sklearn` downloads is about 1/5 of the
42+
`scikit-learn` downloads on PyPI so a lot of people are using it.
43+
44+
There are some edge cases with the way the PyPI `sklearn` package is
45+
implemented:
46+
- `pip install sklearn==1.1.1` will say that the 1.1.1 version does not exist,
47+
which is confusing. The only available version at the time of writing of
48+
`sklearn` is 0.0.
49+
- `pip uninstall sklearn` will actually not uninstall `scikit-learn`, you can
50+
still do `import sklearn` afterwards
51+
- it can be confusing to have both `sklearn` and `scikit-learn` in the `pip
52+
list` output prompting questions like "why do I have scikit-learn 1.1.1 and
53+
sklearn 0.0, and what does it even mean"?
54+
55+
# Testing whether a package will be affected by the `sklearn` deprecation
56+
57+
If you want to test whether a package has `sklearn` in its dependencies
58+
independently of the brownout schedule, you can do:
59+
60+
```
61+
SKLEARN_ALLOW_DEPRECATED_SKLEARN_PACKAGE_INSTALL=False \
62+
pip install package-to-test-goes-here
63+
```
664

7-
The aim of this repo is to implement the brownout of the `sklearn` package on
8-
PyPI.
65+
If you get an error that means that the package has `sklearn` in one of its
66+
dependencies. It would be greatly appreciated if you track which package it is,
67+
and if you report it to the appropriate project issue tracker to make them
68+
aware of the `sklearn` deprecation.

setup.cfg

Lines changed: 0 additions & 8 deletions
This file was deleted.

setup.py

Lines changed: 84 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,87 @@
1-
# encoding: utf8
2-
1+
import os
2+
from datetime import datetime, MAXYEAR
3+
from dateutil.relativedelta import relativedelta
34
from setuptools import setup
45

56

6-
setup(
7-
author='UNKNOWN',
8-
author_email="UNKNOWN\nblas_opt_info:\nblas_mkl_info:\n FOUND:\n libraries = ['mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']\n library_dirs = ['/Users/filo/anaconda/lib']\n define_macros = [('SCIPY_MKL_H', None)]\n include_dirs = ['/Users/filo/anaconda/include']\n\n FOUND:\n libraries = ['mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']\n library_dirs = ['/Users/filo/anaconda/lib']\n define_macros = [('SCIPY_MKL_H', None)]\n include_dirs = ['/Users/filo/anaconda/include']\n\nUNKNOWN",
9-
description='A set of python modules for machine learning and data mining',
10-
install_requires=['scikit-learn'],
11-
long_description='''Use `scikit-learn <https://pypi.python.org/pypi/scikit-learn/>`_ instead.''',
12-
maintainer='UNKNOWN',
13-
maintainer_email="UNKNOWN\nblas_opt_info:\nblas_mkl_info:\n FOUND:\n libraries = ['mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']\n library_dirs = ['/Users/filo/anaconda/lib']\n define_macros = [('SCIPY_MKL_H', None)]\n include_dirs = ['/Users/filo/anaconda/include']\n\n FOUND:\n libraries = ['mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']\n library_dirs = ['/Users/filo/anaconda/lib']\n define_macros = [('SCIPY_MKL_H', None)]\n include_dirs = ['/Users/filo/anaconda/include']\n\nUNKNOWN",
14-
name='sklearn',
15-
platforms=['all'],
16-
py_modules=['wheel-platform-tag-is-broken-on-empty-wheels-see-issue-141'],
17-
url='https://pypi.python.org/pypi/scikit-learn/',
18-
version="0.0",
19-
zip_safe=False,
20-
)
7+
with open("README.md") as f:
8+
LONG_DESCRIPTION = f.read()
9+
10+
11+
def maybe_raise_error(checked_datetime):
12+
accept_deprecated_sklearn_package_install = os.environ.get(
13+
"SKLEARN_ALLOW_DEPRECATED_SKLEARN_PACKAGE_INSTALL", "use-brownout-schedule"
14+
)
15+
accept_deprecated_sklearn_package_install = (
16+
accept_deprecated_sklearn_package_install.lower()
17+
)
18+
19+
if accept_deprecated_sklearn_package_install == "true":
20+
return
21+
22+
if accept_deprecated_sklearn_package_install == "false":
23+
raise SystemExit(
24+
"Refusing to install the deprecated sklearn package, "
25+
"because SKLEARN_ALLOW_DEPRECATED_SKLEARN_PACKAGE_INSTALL=False is set"
26+
)
27+
28+
start_date = datetime(2022, 11, 1)
29+
all_start_dates = [start_date + relativedelta(months=2 * i) for i in range(7)]
30+
date_in_the_far_future = datetime(MAXYEAR, 12, 31, 23, 59, 59)
31+
all_end_dates = all_start_dates[1:] + [date_in_the_far_future]
32+
all_check_functions = [
33+
lambda dt: dt.minute < 5,
34+
lambda dt: dt.minute < 10,
35+
lambda dt: dt.minute < 15,
36+
lambda dt: (dt.minute < 10) or (30 < dt.minute < 40),
37+
lambda dt: (dt.minute < 15) or (30 < dt.minute < 45),
38+
lambda dt: (dt.minute < 20) or (30 < dt.minute < 50),
39+
lambda dt: True,
40+
]
41+
brownout_schedule = zip(all_start_dates, all_end_dates, all_check_functions)
42+
43+
error_message = "\n".join(
44+
[
45+
"The 'sklearn' PyPI package is deprecated, use 'scikit-learn' ",
46+
"rather than 'sklearn' for pip commands. ",
47+
"",
48+
"The brownout schedule for sklearn deprecation can be found at ",
49+
"https://github.com/scikit-learn/sklearn-pypi-package#brownout-schedule",
50+
"",
51+
"Here is how to fix this error in the main use cases:",
52+
"- use 'pip install scikit-learn' rather than 'pip install sklearn'",
53+
"- replace sklearn by scikit-learn in your pip requirements files",
54+
" (requirements.txt, setup.py, setup.cfg, Pipfile, etc ...)",
55+
"- if the sklearn package is used by one of your dependencies, ",
56+
" it would be great if you take some time to track which pakage uses ",
57+
" sklearn instead of scikit-learn and report it to their issue tracker",
58+
"- as last resort, set the environment variable ",
59+
" SKLEARN_ALLOW_DEPRECATED_SKLEARN_PACKAGE_INSTALL=True to avoid this error",
60+
"",
61+
"If the previous advice does not cover your use case, feel free to report it at:",
62+
"https://github.com/scikit-learn/sklearn-pypi-package/issues/new",
63+
]
64+
)
65+
for start_date, end_date, check_function in brownout_schedule:
66+
if (start_date <= checked_datetime < end_date) and check_function(
67+
checked_datetime
68+
):
69+
raise SystemExit(error_message)
70+
71+
72+
def main():
73+
now = datetime.now()
74+
now = datetime(2022, 11, 1)
75+
maybe_raise_error(now)
76+
77+
setup(
78+
description="deprecated sklearn package, use scikit-learn instead",
79+
long_description=LONG_DESCRIPTION,
80+
long_description_content_type="text/markdown",
81+
name="sklearn",
82+
version="0.1.0a1",
83+
)
84+
85+
86+
if __name__ == "__main__":
87+
main()

0 commit comments

Comments
 (0)