Skip to content
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

MISC: Check that min versions are aligned in CI and import_optional_dependency #45219

Merged
merged 21 commits into from
Jan 17, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3e82166
Start script to check sync of min versions
mroeschke Jan 5, 2022
4f996f3
Complete get_versions_from_optional
mroeschke Jan 5, 2022
b4e417d
Pin min pyreadstat, parser for CI file
mroeschke Jan 5, 2022
85f0e3d
Dont parse via yaml
mroeschke Jan 5, 2022
976bdb8
Only handle import_optional_dependency and CI for now
mroeschke Jan 6, 2022
e16176c
Merge remote-tracking branch 'upstream/master' into validate/min_verions
mroeschke Jan 6, 2022
83d4f09
Fix edge case with psycopg2
mroeschke Jan 6, 2022
01172dc
Merge remote-tracking branch 'upstream/master' into validate/min_verions
mroeschke Jan 7, 2022
82de0b7
Special case for psycopg2
mroeschke Jan 8, 2022
d108490
Merge remote-tracking branch 'upstream/master' into validate/min_verions
mroeschke Jan 8, 2022
d1dbdc1
Merge remote-tracking branch 'upstream/master' into validate/min_verions
mroeschke Jan 10, 2022
7b93130
Merge remote-tracking branch 'upstream/master' into validate/min_verions
mroeschke Jan 11, 2022
3a76a52
Add to sys path instead of using ast
mroeschke Jan 11, 2022
628c6f3
Merge remote-tracking branch 'upstream/main' into validate/min_verions
mroeschke Jan 12, 2022
d9bdc6a
Scope to specific files
mroeschke Jan 12, 2022
9b59be7
Merge remote-tracking branch 'upstream/main' into validate/min_verions
mroeschke Jan 13, 2022
aa30fda
Merge remote-tracking branch 'upstream/main' into validate/min_verions
mroeschke Jan 13, 2022
d83b06f
Merge remote-tracking branch 'upstream/main' into validate/min_verions
mroeschke Jan 14, 2022
81b1eff
Merge remote-tracking branch 'upstream/main' into validate/min_verions
mroeschke Jan 16, 2022
3c9f463
Address review
mroeschke Jan 16, 2022
8c96e00
Merge remote-tracking branch 'upstream/main' into validate/min_verions
mroeschke Jan 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,7 @@ repos:
entry: 'pg8000'
files: ^ci/deps
types: [yaml]
- id: validate-min-versions-in-sync
mroeschke marked this conversation as resolved.
Show resolved Hide resolved
mroeschke marked this conversation as resolved.
Show resolved Hide resolved
name: Check minimum version of dependencies are aligned
entry: python scripts/validate_min_versions_in_sync.py
language: python
4 changes: 2 additions & 2 deletions ci/deps/actions-38-minimum_versions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ dependencies:
- matplotlib=3.3.2
- numba=0.50.1
- numexpr=2.7.1
- openpyxl=3.0.3
- odfpy=1.4.1
- openpyxl=3.0.3
- pandas-gbq=0.14.0
- psycopg2=2.8.4
- pymysql=0.10.1
- pytables=3.6.1
- pyarrow=1.0.1
- pyreadstat
- pyreadstat=1.1.0
- pyxlsb=1.0.6
- s3fs=0.4.0
- scipy=1.4.1
Expand Down
2 changes: 1 addition & 1 deletion doc/source/getting_started/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ blosc 1.20.1 Compression for HDF5
zlib Compression for HDF5
fastparquet 0.4.0 Parquet reading / writing
pyarrow 1.0.1 Parquet, ORC, and feather reading / writing
pyreadstat SPSS files (.sav) reading
pyreadstat 1.1.0 SPSS files (.sav) reading
========================= ================== =============================================================

.. _install.warn_orc:
Expand Down
14 changes: 12 additions & 2 deletions pandas/compat/_optional.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -33,7 +40,6 @@
"xlrd": "2.0.1",
"xlwt": "1.3.0",
"xlsxwriter": "1.2.2",
"numba": "0.50.1",
"zstandard": "0.15.2",
}

Expand All @@ -46,6 +52,7 @@
"lxml.etree": "lxml",
"odf": "odfpy",
"pandas_gbq": "pandas-gbq",
"tables": "pytables",
"sqlalchemy": "SQLAlchemy",
"jinja2": "Jinja2",
}
Expand All @@ -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":
Copy link
Contributor

Choose a reason for hiding this comment

The 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?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm the L64 block handles if __version__ is not the correct path to the version. psycopg2 uses __version__ so it wouldn't hit this path

# psycopg2 appends " (dt dec pq3 ext lo64)" to it's version
version = version.split()[0]
return version


Expand Down
81 changes: 81 additions & 0 deletions scripts/validate_min_versions_in_sync.py
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 ast
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()


lithomas1 marked this conversation as resolved.
Show resolved Hide resolved
def get_versions_from_code(content: str) -> dict[str, str]:
lithomas1 marked this conversation as resolved.
Show resolved Hide resolved
num_dicts = 0
for node in ast.walk(ast.parse(content)):
if isinstance(node, ast.Dict):
if num_dicts == 0:
version_dict_ast = node
num_dicts += 1
elif num_dicts == 1:
install_map = {k.value: v.value for k, v in zip(node.keys, node.values)}
return {
install_map.get(k.value, k.value).casefold(): v.value
for k, v in zip(version_dict_ast.keys, version_dict_ast.values)
if k.value != "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) as f:
mroeschke marked this conversation as resolved.
Show resolved Hide resolved
_, ci_optional = get_versions_from_ci(f.readlines())
with open(CODE_PATH) as f:
code_optional = get_versions_from_code(f.read())
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}"
mroeschke marked this conversation as resolved.
Show resolved Hide resolved
)
sys.exit(1)
sys.exit(0)


if __name__ == "__main__":
main()