Skip to content

Commit

Permalink
Start checking using Flake8-PYI
Browse files Browse the repository at this point in the history
  • Loading branch information
Avasam committed May 22, 2024
1 parent 52d7324 commit d3ccb09
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 102 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.8
rev: v0.4.4
hooks:
- id: ruff
- id: ruff-format
2 changes: 1 addition & 1 deletion pkg_resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

import sys

if sys.version_info < (3, 8):
if sys.version_info < (3, 8): # noqa: UP036 # Check for unsupported versions
raise RuntimeError("Python 3.8 or later is required")

import os
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ testing = [
"pytest-mypy",
"pytest-enabler >= 2.2",
# workaround for pypa/setuptools#3921
'pytest-ruff >= 0.2.1; sys_platform != "cygwin"',
'pytest-ruff >= 0.3.2; sys_platform != "cygwin"',

# local
"virtualenv>=13.0.0",
Expand Down
36 changes: 16 additions & 20 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
exclude = [
"**/_vendor",
"setuptools/_distutils",
"setuptools/config/_validate_pyproject",
]

[lint]
extend-select = [
"C901",
"W",

# local
"UP", # pyupgrade
"YTT", # flake8-2020
"PYI", # flake8-pyi
"UP", # pyupgrade
"YTT", # flake8-2020
]
ignore = [
"UP015", # redundant-open-modes, explicit is preferred
"UP030", # temporarily disabled
"UP031", # temporarily disabled
"UP032", # temporarily disabled
"UP038", # Using `X | Y` in `isinstance` call is slower and more verbose https://github.com/astral-sh/ruff/issues/7871

# https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
"W191",
"E111",
Expand All @@ -24,26 +37,9 @@ ignore = [
"ISC001",
"ISC002",
]
extend-ignore = [
"UP015", # redundant-open-modes, explicit is preferred
"UP030", # temporarily disabled
"UP031", # temporarily disabled
"UP032", # temporarily disabled
"UP036", # temporarily disabled
]
exclude = [
"**/_vendor",
"setuptools/_distutils",
"setuptools/config/_validate_pyproject",
]

[format]
exclude = [
"**/_vendor",
"setuptools/_distutils",
"setuptools/config/_validate_pyproject",
]
# Enable preview, required for quote-style = "preserve"
# Enable preview to get hugged parenthesis unwrapping
preview = true
# https://docs.astral.sh/ruff/settings/#format-quote-style
quote-style = "preserve"
141 changes: 64 additions & 77 deletions setuptools/depends.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from .extern.packaging.version import Version


__all__ = ['Require', 'find_module', 'get_module_constant', 'extract_constant']
__all__ = ['Require', 'find_module']


class Require:
Expand Down Expand Up @@ -95,86 +95,73 @@ def empty():
return contextlib.closing(f)


def get_module_constant(module, symbol, default=-1, paths=None):
"""Find 'module' by searching 'paths', and extract 'symbol'
Return 'None' if 'module' does not exist on 'paths', or it does not define
'symbol'. If the module defines 'symbol' as a constant, return the
constant. Otherwise, return 'default'."""

try:
f, path, (suffix, mode, kind) = info = find_module(module, paths)
except ImportError:
# Module doesn't exist
return None

with maybe_close(f):
if kind == PY_COMPILED:
f.read(8) # skip magic & date
code = marshal.load(f)
elif kind == PY_FROZEN:
code = _imp.get_frozen_object(module, paths)
elif kind == PY_SOURCE:
code = compile(f.read(), path, 'exec')
else:
# Not something we can parse; we'll have to import it. :(
imported = _imp.get_module(module, paths, info)
return getattr(imported, symbol, None)

return extract_constant(code, symbol, default)


def extract_constant(code, symbol, default=-1):
"""Extract the constant value of 'symbol' from 'code'
If the name 'symbol' is bound to a constant value by the Python code
object 'code', return that value. If 'symbol' is bound to an expression,
return 'default'. Otherwise, return 'None'.
Return value is based on the first assignment to 'symbol'. 'symbol' must
be a global, or at least a non-"fast" local in the code block. That is,
only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol'
must be present in 'code.co_names'.
"""
if symbol not in code.co_names:
# name's not there, can't possibly be an assignment
return None

name_idx = list(code.co_names).index(symbol)

STORE_NAME = dis.opmap['STORE_NAME']
STORE_GLOBAL = dis.opmap['STORE_GLOBAL']
LOAD_CONST = dis.opmap['LOAD_CONST']

const = default

for byte_code in dis.Bytecode(code):
op = byte_code.opcode
arg = byte_code.arg

if op == LOAD_CONST:
const = code.co_consts[arg]
elif arg == name_idx and (op == STORE_NAME or op == STORE_GLOBAL):
return const
else:
const = default
# Some objects are not available on some platforms.
# XXX it'd be better to test assertions about bytecode instead.
if not sys.platform.startswith('java') and sys.platform != 'cli':

def get_module_constant(module, symbol, default=-1, paths=None):
"""Find 'module' by searching 'paths', and extract 'symbol'
Return 'None' if 'module' does not exist on 'paths', or it does not define
'symbol'. If the module defines 'symbol' as a constant, return the
constant. Otherwise, return 'default'."""

try:
f, path, (suffix, mode, kind) = info = find_module(module, paths)
except ImportError:
# Module doesn't exist
return None

with maybe_close(f):
if kind == PY_COMPILED:
f.read(8) # skip magic & date
code = marshal.load(f)
elif kind == PY_FROZEN:
code = _imp.get_frozen_object(module, paths)
elif kind == PY_SOURCE:
code = compile(f.read(), path, 'exec')
else:
# Not something we can parse; we'll have to import it. :(
imported = _imp.get_module(module, paths, info)
return getattr(imported, symbol, None)

return extract_constant(code, symbol, default)

def extract_constant(code, symbol, default=-1):
"""Extract the constant value of 'symbol' from 'code'
If the name 'symbol' is bound to a constant value by the Python code
object 'code', return that value. If 'symbol' is bound to an expression,
return 'default'. Otherwise, return 'None'.
Return value is based on the first assignment to 'symbol'. 'symbol' must
be a global, or at least a non-"fast" local in the code block. That is,
only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol'
must be present in 'code.co_names'.
"""
if symbol not in code.co_names:
# name's not there, can't possibly be an assignment
return None

return None
name_idx = list(code.co_names).index(symbol)

STORE_NAME = dis.opmap['STORE_NAME']
STORE_GLOBAL = dis.opmap['STORE_GLOBAL']
LOAD_CONST = dis.opmap['LOAD_CONST']

def _update_globals():
"""
Patch the globals to remove the objects not available on some platforms.
const = default

XXX it'd be better to test assertions about bytecode instead.
"""
for byte_code in dis.Bytecode(code):
op = byte_code.opcode
arg = byte_code.arg

if not sys.platform.startswith('java') and sys.platform != 'cli':
return
incompatible = 'extract_constant', 'get_module_constant'
for name in incompatible:
del globals()[name]
__all__.remove(name)
if op == LOAD_CONST:
const = code.co_consts[arg]
elif arg == name_idx and (op == STORE_NAME or op == STORE_GLOBAL):
return const
else:
const = default

return None

_update_globals()
__all__ += ['get_module_constant', 'extract_constant']
9 changes: 7 additions & 2 deletions setuptools/tests/test_easy_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
import itertools
import distutils.errors
import io
from typing import NamedTuple
import zipfile
import time
import re
import subprocess
import pathlib
import warnings
from collections import namedtuple
from pathlib import Path
from unittest import mock

Expand Down Expand Up @@ -1344,7 +1344,12 @@ def test_header(self):
assert not hdr.startswith('\\"')


VersionStub = namedtuple("VersionStub", "major, minor, micro, releaselevel, serial")
class VersionStub(NamedTuple):
major: int
minor: int
micro: int
releaselevel: str
serial: int


def test_use_correct_python_version_string(tmpdir, tmpdir_cwd, monkeypatch):
Expand Down

0 comments on commit d3ccb09

Please sign in to comment.