-
-
Notifications
You must be signed in to change notification settings - Fork 18.6k
MISC: Check that min versions are aligned in CI and import_optional_dependency #45219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3e82166
4f996f3
b4e417d
85f0e3d
976bdb8
e16176c
83d4f09
01172dc
82de0b7
d108490
d1dbdc1
7b93130
3a76a52
628c6f3
d9bdc6a
9b59be7
aa30fda
d83b06f
81b1eff
3c9f463
8c96e00
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,17 +11,24 @@ | |
|
||
VERSIONS = { | ||
"bs4": "4.8.2", | ||
"blosc": "1.20.1", | ||
"bottleneck": "1.3.1", | ||
"fsspec": "0.7.4", | ||
"fastparquet": "0.4.0", | ||
"fsspec": "0.7.4", | ||
"html5lib": "1.1", | ||
"gcsfs": "0.6.0", | ||
"jinja2": "2.11", | ||
"lxml.etree": "4.5.0", | ||
"matplotlib": "3.3.2", | ||
"numba": "0.50.1", | ||
"numexpr": "2.7.1", | ||
"odfpy": "1.4.1", | ||
"openpyxl": "3.0.3", | ||
"pandas_gbq": "0.14.0", | ||
"psycopg2": "2.8.4", # (dt dec pq3 ext lo64) | ||
"pymysql": "0.10.1", | ||
"pyarrow": "1.0.1", | ||
"pyreadstat": "1.1.0", | ||
"pytest": "6.0", | ||
"pyxlsb": "1.0.6", | ||
"s3fs": "0.4.0", | ||
|
@@ -33,7 +40,6 @@ | |
"xlrd": "2.0.1", | ||
"xlwt": "1.3.0", | ||
"xlsxwriter": "1.2.2", | ||
"numba": "0.50.1", | ||
"zstandard": "0.15.2", | ||
} | ||
|
||
|
@@ -46,6 +52,7 @@ | |
"lxml.etree": "lxml", | ||
"odf": "odfpy", | ||
"pandas_gbq": "pandas-gbq", | ||
"tables": "pytables", | ||
"sqlalchemy": "SQLAlchemy", | ||
"jinja2": "Jinja2", | ||
} | ||
|
@@ -59,6 +66,9 @@ def get_version(module: types.ModuleType) -> str: | |
|
||
if version is None: | ||
raise ImportError(f"Can't determine version for {module.__name__}") | ||
if module.__name__ == "psycopg2": | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you integrate this to L64, e.g. maybe make a separate make of module -> lambda functions that can handle the special case modules? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm the L64 block handles if |
||
# psycopg2 appends " (dt dec pq3 ext lo64)" to it's version | ||
version = version.split()[0] | ||
return version | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
#!/usr/bin/env python3 | ||
""" | ||
Check pandas required and optional dependencies are synced across: | ||
|
||
ci/deps/actions-.*-minimum_versions.yaml | ||
pandas/compat/_optional.py | ||
|
||
TODO: doc/source/getting_started/install.rst | ||
|
||
This is meant to be run as a pre-commit hook - to run it manually, you can do: | ||
|
||
pre-commit run validate-min-versions-in-sync --all-files | ||
""" | ||
from __future__ import annotations | ||
|
||
import pathlib | ||
import sys | ||
|
||
DOC_PATH = pathlib.Path("doc/source/getting_started/install.rst").resolve() | ||
CI_PATH = next( | ||
pathlib.Path("ci/deps").absolute().glob("actions-*-minimum_versions.yaml") | ||
) | ||
CODE_PATH = pathlib.Path("pandas/compat/_optional.py").resolve() | ||
# pandas package is not available | ||
# in pre-commit environment | ||
sys.path.append("pandas/compat") | ||
sys.path.append("pandas/util") | ||
import version | ||
|
||
sys.modules["pandas.util.version"] = version | ||
import _optional | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you import these as fully qualified and/or make this whole section a bit more idiomatic (i know tricky, but give a try) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tried playing around with this but couldn't simplify it further than what @lithomas1 suggested. |
||
|
||
lithomas1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
def get_versions_from_code() -> dict[str, str]: | ||
install_map = _optional.INSTALL_MAPPING | ||
versions = _optional.VERSIONS | ||
return { | ||
install_map.get(k, k).casefold(): v | ||
for k, v in versions.items() | ||
if k != "pytest" | ||
} | ||
|
||
|
||
def get_versions_from_ci(content: list[str]) -> tuple[dict[str, str], dict[str, str]]: | ||
# Don't parse with pyyaml because it ignores comments we're looking for | ||
seen_required = False | ||
seen_optional = False | ||
required_deps = {} | ||
optional_deps = {} | ||
for line in content: | ||
if "# required dependencies" in line: | ||
seen_required = True | ||
elif "# optional dependencies" in line: | ||
seen_optional = True | ||
elif seen_required and line.strip(): | ||
package, version = line.strip().split("=") | ||
package = package[2:] | ||
if not seen_optional: | ||
required_deps[package] = version | ||
else: | ||
optional_deps[package] = version | ||
return required_deps, optional_deps | ||
|
||
|
||
def main(): | ||
with open(CI_PATH, encoding="utf-8") as f: | ||
_, ci_optional = get_versions_from_ci(f.readlines()) | ||
code_optional = get_versions_from_code() | ||
diff = set(ci_optional.items()).symmetric_difference(code_optional.items()) | ||
if diff: | ||
sys.stdout.write( | ||
f"The follow minimum version differences were found between " | ||
f"{CI_PATH} and {CODE_PATH}. Please ensure these are aligned: " | ||
f"{diff}\n" | ||
) | ||
sys.exit(1) | ||
sys.exit(0) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Uh oh!
There was an error while loading. Please reload this page.