diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 31f34000a..000000000 --- a/.flake8 +++ /dev/null @@ -1,4 +0,0 @@ -[flake8] -max-line-length=88 -extend-ignore=E203,D104,D100,I004 -exclude=tests/data/* diff --git a/.isort.cfg b/.isort.cfg deleted file mode 100644 index d200a9ae1..000000000 --- a/.isort.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[settings] -line_length=88 -known_third_party=requests,ruamel,yaml,pytest,rapidfuzz,opensource,colorama,progressbar,progressbar2 -multi_line_output=3 -include_trailing_comma=True -force_grid_wrap=0 -use_parentheses=True diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8ab5daaa5..17c8e29ed 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,26 +1,19 @@ exclude: docs repos: -- repo: https://github.com/psf/black - rev: 24.8.0 - hooks: - - id: black - args: [--safe, --quiet] -- repo: https://github.com/asottile/blacken-docs +- repo: https://github.com/adamchainz/blacken-docs rev: 1.18.0 hooks: - id: blacken-docs - additional_dependencies: [black==22.6.0] + additional_dependencies: [black==22.12.0] - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - - id: fix-encoding-pragma - args: [--remove] - id: check-yaml exclude: tests - id: sort-simple-yaml - files: grayskull/pypi/config.yaml + files: config.yaml - id: check-toml - id: check-json - id: check-merge-conflict @@ -28,14 +21,11 @@ repos: args: [--autofix] - id: debug-statements language_version: python3 -- repo: https://github.com/PyCQA/isort - rev: 5.13.2 - hooks: - - id: isort - exclude: tests/data -- repo: https://github.com/PyCQA/flake8 - rev: 7.1.1 +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.6.4 hooks: - - id: flake8 - exclude: tests/data - language_version: python3 + # Run the linter + - id: ruff + args: [ --fix, --exit-non-zero-on-fix ] + # Run the formatter + - id: ruff-format diff --git a/MANIFEST.in b/MANIFEST.in index 9e9189d9a..59797ce87 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -7,9 +7,7 @@ exclude .github exclude azure-pipelines.yml exclude .gitignore exclude .pre-commit-config.yaml -exclude .flake8 exclude .coveragerc -exclude .isort.cfg prune tests/ recursive-exclude * __pycache__ recursive-exclude * *.py[co] diff --git a/grayskull/base/track_packages.py b/grayskull/base/track_packages.py index 779d4d637..86ade424f 100644 --- a/grayskull/base/track_packages.py +++ b/grayskull/base/track_packages.py @@ -53,7 +53,7 @@ def solve_pkg_name(pkg: str, config_file: Union[Path, str]) -> str: @lru_cache(maxsize=5) def _get_track_info_from_file(config_file: Union[Path, str]) -> Dict: yaml = YAML() - with open(config_file, "r", encoding="utf_8") as yaml_file: + with open(config_file, encoding="utf_8") as yaml_file: return yaml.load(yaml_file) diff --git a/grayskull/cli/stdout.py b/grayskull/cli/stdout.py index 8de0fb2c4..17a653328 100644 --- a/grayskull/cli/stdout.py +++ b/grayskull/cli/stdout.py @@ -112,10 +112,8 @@ def print_req(list_pkg): f"\n{Fore.RED}RED{Style.RESET_ALL}: Package names not available on conda-forge" ) print_msg( - ( - f"{Fore.YELLOW}YELLOW{Style.RESET_ALL}: " - "PEP-725 PURLs that did not map to known package" - ) + f"{Fore.YELLOW}YELLOW{Style.RESET_ALL}: " + "PEP-725 PURLs that did not map to known package" ) print_msg(f"{Fore.GREEN}GREEN{Style.RESET_ALL}: Packages available on conda-forge") diff --git a/grayskull/license/data/__init__.py b/grayskull/license/data/__init__.py index a8b7b0e2b..16c587c61 100644 --- a/grayskull/license/data/__init__.py +++ b/grayskull/license/data/__init__.py @@ -11,6 +11,6 @@ def get_all_licenses() -> List: full_path = os.path.join(data_folder, license_file) if not os.path.isfile(full_path) or license_file.endswith(".py"): continue - with open(full_path, "r") as f: + with open(full_path) as f: all_licenses.append((license_file, f.read())) return all_licenses diff --git a/grayskull/license/discovery.py b/grayskull/license/discovery.py index 6e0159a69..0fa4ec7dc 100644 --- a/grayskull/license/discovery.py +++ b/grayskull/license/discovery.py @@ -208,7 +208,7 @@ def get_opensource_license(license_spdx: str) -> dict: def read_licence_cache(): - with open(Path(__file__).parent / "licence_cache.json", "r") as licence_cache: + with open(Path(__file__).parent / "licence_cache.json") as licence_cache: return json.load(licence_cache) @@ -421,7 +421,7 @@ def get_license_type(path_license: str, default: Optional[str] = None) -> Option :param default: Default value for the license type :return: License type """ - with open(path_license, "r", errors="ignore") as license_file: + with open(path_license, errors="ignore") as license_file: license_content = license_file.read() find_apache = re.findall( r"apache\.org\/licenses\/LICENSE\-([0-9])\.([0-9])", diff --git a/grayskull/strategy/config.yaml b/grayskull/strategy/config.yaml index 1ba106a1c..640487ac2 100644 --- a/grayskull/strategy/config.yaml +++ b/grayskull/strategy/config.yaml @@ -1,11 +1,3 @@ -art: - conda_forge: ascii-art - import_name: art - -bilby-pipe: - conda_forge: bilby_pipe - import_name: bilby_pipe - Boruta: conda_forge: boruta_py import_name: boruta @@ -30,6 +22,10 @@ annoy: conda_forge: python-annoy import_name: annoy +art: + conda_forge: ascii-art + import_name: art + asana: conda_forge: python-asana import_name: asana @@ -42,6 +38,14 @@ bash_completion: conda_forge: py-bash-completion import_name: bash_completion +bilby-pipe: + conda_forge: bilby_pipe + import_name: bilby_pipe + +blis: + conda_forge: cython-blis + import_name: blis + build: conda_forge: python-build import_name: build @@ -102,6 +106,11 @@ data-morph-ai: conda_forge: data-morph-ai import_name: data_morph +dataclasses: + conda_forge: dataclasses + import_name: dataclasses + avoid_selector: true + datadotworld: conda_forge: datadotworld-py import_name: datadotworld @@ -138,6 +147,11 @@ empyrical_dist: conda_forge: empyrical-dist import_name: empyrical_dist +enum34: + conda_forge: enum34 + import_name: enum + avoid_selector: true + esprima: conda_forge: esprima-python import_name: esprima @@ -150,6 +164,11 @@ evalml: conda_forge: evaml-core import_name: evalml +exceptiongroup: + conda_forge: exceptiongroup + import_name: exceptiongroup + avoid_selector: true + extract-msg: conda_forge: msg-extractor import_name: extract_msg @@ -174,22 +193,30 @@ flex: conda_forge: flex-swagger import_name: flex +flit_core: + conda_forge: flit-core + import_name: flit-core + gnupg: conda_forge: gnupg-py import_name: gnupg -google: - conda_forge: googlesearch - import_name: googlesearch - google-cloud-bigquery: conda_forge: google-cloud-bigquery-core import_name: google.cloud.bigquery +google: + conda_forge: googlesearch + import_name: googlesearch + graphviz: import_name: graphviz conda_forge: python-graphviz +gssapi: + conda_forge: python-gssapi + import_name: gssapi + h2o: conda_forge: h2o-py import_name: h2o @@ -218,6 +245,16 @@ ib_insync: conda_forge: ib-insync import_name: ib_insync +import_metadata: + conda_forge: import_metadata + import_name: import_metadata + avoid_selector: true + +importlib_metadata: + conda_forge: importlib-metadata + import_name: importlib-metadata + avoid_selector: true + installer: conda_forge: python-installer import_name: installer @@ -234,6 +271,14 @@ ioos_tools: conda_forge: ioos-tools import_name: ioos_tools +jsii: + conda_forge: python-jsii + import_name: jsii + +jupyter-client: + conda_forge: jupyter_client + import_name: jupyter_client + jupyter_jaeger: conda_forge: jupyter-jaeger import_name: jupyter_jaeger @@ -246,6 +291,10 @@ jupyterlab_latex: conda_forge: jupyterlab-latex import_name: jupyterlab_latex +kaleido: + conda_forge: python-kaleido + import_name: kaleido + kubernetes: conda_forge: python-kubernetes import_name: kubernetes @@ -282,14 +331,14 @@ ndarray_listener: conda_forge: ndarray-listener import_name: ndarray_listener -neo: - conda_forge: python-neo - import_name: neo - neo4j: conda_forge: neo4j-python-driver import_name: neo4j +neo: + conda_forge: python-neo + import_name: neo + nest_asyncio: conda_forge: nest-asyncio import_name: nest_asyncio @@ -302,11 +351,11 @@ nvidia-ml-py3: conda_forge: nvidia-ml import_name: pynvml -opencv-python: +opencv-python-headless: import_name: cv2 conda_forge: opencv -opencv-python-headless: +opencv-python: import_name: cv2 conda_forge: opencv @@ -382,9 +431,10 @@ python-qnotifications: conda_forge: qnotifications import_name: QNotifications -symengine: - conda_forge: python-symengine - import_name: symengine +pywin32: + conda_forge: pywin32-on-windows + import_name: pywin + avoid_selector: true quantum-grove: conda_forge: grove @@ -418,6 +468,10 @@ scikit-build: conda_forge: scikit-build import_name: skbuild +scikit-learn: + conda_forge: scikit-learn + import_name: sklearn + setuptools_scm: conda_forge: setuptools-scm import_name: setuptools_scm @@ -438,6 +492,10 @@ stjudecloud-oliver: conda_forge: oliver import_name: oliver +symengine: + conda_forge: python-symengine + import_name: symengine + tables: import_name: pytables conda_forge: pytables @@ -458,6 +516,11 @@ trino: conda_forge: trino-python-client import_name: trino +typing: + conda_forge: typing + import_name: typing + avoid_selector: true + useDAVE: conda_forge: dave import_name: numpy @@ -469,66 +532,3 @@ vsts: xxhash: import_name: xxhash conda_forge: python-xxhash - -kaleido: - conda_forge: python-kaleido - import_name: kaleido - -dataclasses: - conda_forge: dataclasses - import_name: dataclasses - avoid_selector: true - -typing: - conda_forge: typing - import_name: typing - avoid_selector: true - -import_metadata: - conda_forge: import_metadata - import_name: import_metadata - avoid_selector: true - -enum34: - conda_forge: enum34 - import_name: enum - avoid_selector: true - -pywin32: - conda_forge: pywin32-on-windows - import_name: pywin - avoid_selector: true - -exceptiongroup: - conda_forge: exceptiongroup - import_name: exceptiongroup - avoid_selector: true - -scikit-learn: - conda_forge: scikit-learn - import_name: sklearn - -importlib_metadata: - conda_forge: importlib-metadata - import_name: importlib-metadata - avoid_selector: true - -jupyter-client: - conda_forge: jupyter_client - import_name: jupyter_client - -flit_core: - conda_forge: flit-core - import_name: flit-core - -gssapi: - conda_forge: python-gssapi - import_name: gssapi - -jsii: - conda_forge: python-jsii - import_name: jsii - -blis: - conda_forge: cython-blis - import_name: blis diff --git a/grayskull/strategy/py_base.py b/grayskull/strategy/py_base.py index 47c892e65..0c78342d1 100644 --- a/grayskull/strategy/py_base.py +++ b/grayskull/strategy/py_base.py @@ -568,7 +568,7 @@ def discover_license(metadata: dict) -> List[ShortLicense]: if not git_url and urlparse(project_url).netloc == "github.com": git_url = project_url # "url" is always present but sometimes set to None - if not git_url and urlparse((metadata.get("url") or "")).netloc == "github.com": + if not git_url and urlparse(metadata.get("url") or "").netloc == "github.com": git_url = metadata.get("url") return search_license_file( diff --git a/grayskull/strategy/pypi.py b/grayskull/strategy/pypi.py index ff60f2596..9647473b8 100644 --- a/grayskull/strategy/pypi.py +++ b/grayskull/strategy/pypi.py @@ -61,9 +61,9 @@ class PypiStrategy(AbstractStrategy): def fetch_data(recipe, config, sections=None): update_recipe(recipe, config, sections or ALL_SECTIONS) if not (recipe["build"] and recipe["build"]["script"]): - recipe["build"][ - "script" - ] = "<{ PYTHON }} -m pip install . -vv --no-deps --no-build-isolation" + recipe["build"]["script"] = ( + "<{ PYTHON }} -m pip install . -vv --no-deps --no-build-isolation" + ) def merge_pypi_sdist_metadata( diff --git a/grayskull/utils.py b/grayskull/utils.py index bf377fa34..2c9a998a8 100644 --- a/grayskull/utils.py +++ b/grayskull/utils.py @@ -60,7 +60,7 @@ def visit_ImportFrom(node): node_iter = ast.NodeVisitor() node_iter.visit_Import = visit_Import node_iter.visit_ImportFrom = visit_ImportFrom - with open(script_file, "r") as f: + with open(script_file) as f: node_iter.visit(ast.parse(f.read())) return modules diff --git a/pyproject.toml b/pyproject.toml index 645bc6e40..3bd2ded7e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,21 +65,13 @@ include = ["grayskull", "grayskull.*"] [tool.setuptools_scm] write_to = "grayskull/_version.py" -[tool.black] -target-version = ["py310"] -exclude = ''' -/( - \.eggs - | \.git - | \.hg - | \.mypy_cache - | \.tox - | \.venv - | \.pytest_cache - | _build - | buck-out - | build - | dist - | tests/data -)/ -''' +[tool.ruff.lint] +select = [ + "E", # pycodestyle + "F", # Pyflakes + "UP", # pyupgrade + "I", # isort +] + +[tool.ruff.lint.per-file-ignores] +"tests/data/**" = ["E", "F"] diff --git a/tests/cli/test_cli_cmds.py b/tests/cli/test_cli_cmds.py index 49d473899..3bf5bc5e9 100644 --- a/tests/cli/test_cli_cmds.py +++ b/tests/cli/test_cli_cmds.py @@ -41,7 +41,7 @@ def test_grayskull_without_options(capsys, monkeypatch): monkeypatch.setattr(sys, "argv", ["foo"]) with pytest.raises(SystemExit) as pytest_wrapped_e: cli.main([]) - assert pytest_wrapped_e.type == SystemExit + assert pytest_wrapped_e.type is SystemExit captured = capsys.readouterr() assert "Grayskull - Conda recipe generator" in captured.out diff --git a/tests/license/test_discovery.py b/tests/license/test_discovery.py index 6bb8dff76..d5d0615a9 100644 --- a/tests/license/test_discovery.py +++ b/tests/license/test_discovery.py @@ -58,16 +58,21 @@ def test_get_opensource_license_data(): assert len(get_opensource_license_data()) >= 50 +licence_skip_mark = pytest.mark.xfail( + reason="Skipping the latest fuzzy match library is giving different results" +) + + @pytest.mark.parametrize( "licence_name, short_licence", [ ("MIT License", "MIT"), ("Expat", "MIT"), ("GPL 2.0", "GPL-2.0-or-later"), - ("GPL 3.0", "GPL-3.0-only"), - ("GPLv3", "GPL-3.0-only"), + pytest.param("GPL 3.0", "GPL-3.0-only", marks=licence_skip_mark), + pytest.param("GPLv3", "GPL-3.0-only", marks=licence_skip_mark), ("GPL-3.0-only", "GPL-3.0-only"), - ("LGPL 2.0", "LGPL-2.0-or-later"), + pytest.param("LGPL 2.0", "LGPL-2.0-or-later", marks=licence_skip_mark), ("LGPL-3.0-or-later", "LGPL-3.0-or-later"), ("2-Clause BSD License", "BSD-2-Clause"), ("3-Clause BSD License", "BSD-3-Clause"), @@ -111,7 +116,7 @@ def test_search_license_api_github(license_pytest_5_3_1: str): assert license_api.name == "MIT" assert license_api.path.endswith("LICENSE") - with open(license_api.path, "r") as f: + with open(license_api.path) as f: assert f.read() == license_pytest_5_3_1 diff --git a/tests/test_pypi.py b/tests/test_pypi.py index fb8899545..e504f1cee 100644 --- a/tests/test_pypi.py +++ b/tests/test_pypi.py @@ -1050,7 +1050,7 @@ def test_panel_entry_points(tmpdir): recipe = GrayskullFactory.create_recipe("pypi", config) generate_recipe(recipe, config, folder_path=str(tmpdir)) recipe_path = str(tmpdir / "panel" / "meta.yaml") - with open(recipe_path, "r") as f: + with open(recipe_path) as f: content = f.read() assert "- panel = panel.cli:main" in content