Skip to content

Commit

Permalink
use ruff as linter (#3008)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattijn authored Apr 4, 2023
1 parent 95829f6 commit d7c0b22
Show file tree
Hide file tree
Showing 38 changed files with 178 additions and 107 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
name: black-flake8-mypy
name: black-ruff-mypy
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.10
Expand All @@ -21,9 +21,10 @@ jobs:
run: |
black --diff --color .
black --check .
- name: Lint with flake8
run: |
flake8 . --statistics
- name: Lint with ruff
run: |
ruff check .
- name: Lint with mypy
run: |
mypy altair tests
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ install:

test :
black --diff --color --check .
flake8 . --statistics
ruff check .
mypy altair tests
python -m pytest --pyargs --doctest-modules tests

Expand Down
2 changes: 1 addition & 1 deletion altair/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# flake8: noqa
# ruff: noqa
__version__ = "5.0.0dev"

from typing import Any
Expand Down
6 changes: 3 additions & 3 deletions altair/_magics.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def _prepare_data(data, data_transformers):
elif isinstance(data, str):
return {"url": data}
else:
warnings.warn("data of type {} not recognized".format(type(data)))
warnings.warn("data of type {} not recognized".format(type(data)), stacklevel=1)
return data


Expand Down Expand Up @@ -94,11 +94,11 @@ def vegalite(line, cell):
elif not YAML_AVAILABLE:
try:
spec = json.loads(cell)
except json.JSONDecodeError:
except json.JSONDecodeError as err:
raise ValueError(
"%%vegalite: spec is not valid JSON. "
"Install pyyaml to parse spec as yaml"
)
) from err
else:
spec = yaml.load(cell, Loader=yaml.SafeLoader)

Expand Down
2 changes: 1 addition & 1 deletion altair/expr/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Tools for creating transform & filter expressions with a python syntax"""
# flake8: noqa
# ruff: noqa
from typing import Any

from .core import datum, Expression
Expand Down
25 changes: 14 additions & 11 deletions altair/utils/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,8 @@ def infer_vegalite_type(data):
else:
warnings.warn(
"I don't know how to infer vegalite type from '{}'. "
"Defaulting to nominal.".format(typ)
"Defaulting to nominal.".format(typ),
stacklevel=1,
)
return "nominal"

Expand Down Expand Up @@ -483,15 +484,15 @@ def parse_shorthand(

valid_typecodes = list(TYPECODE_MAP) + list(INV_TYPECODE_MAP)

units = dict(
field="(?P<field>.*)",
type="(?P<type>{})".format("|".join(valid_typecodes)),
agg_count="(?P<aggregate>count)",
op_count="(?P<op>count)",
aggregate="(?P<aggregate>{})".format("|".join(AGGREGATES)),
window_op="(?P<op>{})".format("|".join(AGGREGATES + WINDOW_AGGREGATES)),
timeUnit="(?P<timeUnit>{})".format("|".join(TIMEUNITS)),
)
units = {
"field": "(?P<field>.*)",
"type": "(?P<type>{})".format("|".join(valid_typecodes)),
"agg_count": "(?P<aggregate>count)",
"op_count": "(?P<op>count)",
"aggregate": "(?P<aggregate>{})".format("|".join(AGGREGATES)),
"window_op": "(?P<op>{})".format("|".join(AGGREGATES + WINDOW_AGGREGATES)),
"timeUnit": "(?P<timeUnit>{})".format("|".join(TIMEUNITS)),
}

patterns = []

Expand Down Expand Up @@ -710,7 +711,9 @@ def _wrap_in_channel_class(obj, encoding):
return [_wrap_in_channel_class(subobj, encoding) for subobj in obj]

if encoding not in name_to_channel:
warnings.warn("Unrecognized encoding channel '{}'".format(encoding))
warnings.warn(
"Unrecognized encoding channel '{}'".format(encoding), stacklevel=1
)
return obj

classes = name_to_channel[encoding]
Expand Down
10 changes: 6 additions & 4 deletions altair/utils/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ def pipe(data, *funcs):
"alt.pipe() is deprecated, and will be removed in a future release. "
"Use toolz.curried.pipe() instead.",
AltairDeprecationWarning,
stacklevel=1,
)
return curried.pipe(data, *funcs)

Expand All @@ -271,6 +272,7 @@ def curry(*args, **kwargs):
"alt.curry() is deprecated, and will be removed in a future release. "
"Use toolz.curried.curry() instead.",
AltairDeprecationWarning,
stacklevel=1,
)
return curried.curry(*args, **kwargs)

Expand All @@ -284,14 +286,14 @@ def import_pyarrow_interchange():
import pyarrow.interchange as pi

return pi
except pkg_resources.DistributionNotFound:
except pkg_resources.DistributionNotFound as err:
# The package is not installed
raise ImportError(
"Usage of the DataFrame Interchange Protocol requires the package 'pyarrow', but it is not installed."
)
except pkg_resources.VersionConflict:
) from err
except pkg_resources.VersionConflict as err:
# The package is installed but does not meet the minimum version requirement
raise ImportError(
"The installed version of 'pyarrow' does not meet the minimum requirement of version 11.0.0. "
"Please update 'pyarrow' to use the DataFrame Interchange Protocol."
)
) from err
2 changes: 1 addition & 1 deletion altair/utils/deprecation.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def _deprecate(obj, name=None, message=None):

@functools.wraps(obj)
def new_obj(*args, **kwargs):
warnings.warn(message, AltairDeprecationWarning)
warnings.warn(message, AltairDeprecationWarning, stacklevel=1)
return obj(*args, **kwargs)

new_obj._deprecated = True
Expand Down
6 changes: 3 additions & 3 deletions altair/utils/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,14 +251,14 @@ def spec_to_html(
if mode == "vega-lite" and vegalite_version is None:
raise ValueError("must specify vega-lite version for mode='vega-lite'")

render_kwargs = dict()
render_kwargs = {}
if template == "inline":
try:
from altair_viewer import get_bundled_script
except ImportError:
except ImportError as err:
raise ImportError(
"The altair_viewer package is required to convert to HTML with inline=True"
)
) from err
render_kwargs["vega_script"] = get_bundled_script("vega", vega_version)
render_kwargs["vegalite_script"] = get_bundled_script(
"vega-lite", vegalite_version
Expand Down
6 changes: 3 additions & 3 deletions altair/utils/plugin_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,11 @@ def _enable(self, name: str, **options) -> None:
for ep in importlib_metadata_get(self.entry_point_group)
if ep.name == name
]
except ValueError:
except ValueError as err:
if name in self.entrypoint_err_messages:
raise ValueError(self.entrypoint_err_messages[name])
raise ValueError(self.entrypoint_err_messages[name]) from err
else:
raise NoSuchEntryPoint(self.entry_point_group, name)
raise NoSuchEntryPoint(self.entry_point_group, name) from err
value = cast(PluginType, ep.load())
self.register(name, value)
self._active_name = name
Expand Down
2 changes: 1 addition & 1 deletion altair/utils/save.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def set_inspect_format_argument(format, fp, inline):
)

if format != "html" and inline:
warnings.warn("inline argument ignored for non HTML formats.")
warnings.warn("inline argument ignored for non HTML formats.", stacklevel=1)

return format

Expand Down
21 changes: 18 additions & 3 deletions altair/utils/schemapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,11 +564,22 @@ def to_dict(self, validate=True, ignore=None, context=None):
try:
self.validate(result)
except jsonschema.ValidationError as err:
raise SchemaValidationError(self, err)
# We do not raise `from err` as else the resulting
# traceback is very long as it contains part
# of the Vega-Lite schema. It would also first
# show the less helpful ValidationError instead of
# the more user friendly SchemaValidationError
raise SchemaValidationError(self, err) from None
return result

def to_json(
self, validate=True, ignore=[], context={}, indent=2, sort_keys=True, **kwargs
self,
validate=True,
ignore=None,
context=None,
indent=2,
sort_keys=True,
**kwargs,
):
"""Emit the JSON representation for this object as a string.
Expand All @@ -577,7 +588,7 @@ def to_json(
validate : boolean
If True (default), then validate the output dictionary
against the schema.
ignore : list
ignore : list (optional)
A list of keys to ignore. This will *not* passed to child to_dict
function calls.
context : dict (optional)
Expand All @@ -595,6 +606,10 @@ def to_json(
spec : string
The JSON specification of the chart object.
"""
if ignore is None:
ignore = []
if context is None:
context = {}
dct = self.to_dict(validate=validate, ignore=ignore, context=context)
return json.dumps(dct, indent=indent, sort_keys=sort_keys, **kwargs)

Expand Down
2 changes: 1 addition & 1 deletion altair/vegalite/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# flake8: noqa
# ruff: noqa
from .v5 import *
2 changes: 1 addition & 1 deletion altair/vegalite/api.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# flake8: noqa
# ruff: noqa
from .v5.api import *
2 changes: 1 addition & 1 deletion altair/vegalite/schema.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Altair schema wrappers"""
# flake8: noqa
# ruff: noqa
from .v5.schema import *
2 changes: 1 addition & 1 deletion altair/vegalite/v5/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# flake8: noqa
# ruff: noqa
from .schema import *
from .api import *

Expand Down
10 changes: 7 additions & 3 deletions altair/vegalite/v5/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def _prepare_data(data, context=None):

# if data is still not a recognized type, then return
if not isinstance(data, (dict, core.Data)):
warnings.warn("data of type {} not recognized".format(type(data)))
warnings.warn("data of type {} not recognized".format(type(data)), stacklevel=1)

return data

Expand Down Expand Up @@ -355,12 +355,14 @@ def param(
warnings.warn(
"""The value of 'empty' should be True or False.""",
utils.AltairDeprecationWarning,
stacklevel=1,
)
parameter.empty = False
elif parameter.empty == "all":
warnings.warn(
"""The value of 'empty' should be True or False.""",
utils.AltairDeprecationWarning,
stacklevel=1,
)
parameter.empty = True
elif (parameter.empty is False) or (parameter.empty is True):
Expand All @@ -372,6 +374,7 @@ def param(
warnings.warn(
"""Use 'value' instead of 'init'.""",
utils.AltairDeprecationWarning,
stacklevel=1,
)
if value is Undefined:
kwds["value"] = kwds.pop("init")
Expand Down Expand Up @@ -416,6 +419,7 @@ def _selection(type=Undefined, **kwds):
"""The types 'single' and 'multi' are now
combined and should be specified using "selection_point()".""",
utils.AltairDeprecationWarning,
stacklevel=1,
)
else:
raise ValueError("""'type' must be 'point' or 'interval'""")
Expand Down Expand Up @@ -2261,11 +2265,11 @@ def show(self, embed_opt=None, open_browser=None):
"""
try:
import altair_viewer # type: ignore
except ImportError:
except ImportError as err:
raise ValueError(
"'show' method requires the altair_viewer package. "
"See http://github.com/altair-viz/altair_viewer"
)
) from err
altair_viewer.show(self, embed_opt=embed_opt, open_browser=open_browser)

@utils.use_signature(core.Resolve)
Expand Down
2 changes: 1 addition & 1 deletion altair/vegalite/v5/schema/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# flake8: noqa
# ruff: noqa
from .core import *
from .channels import *
SCHEMA_VERSION = 'v5.6.1'
Expand Down
5 changes: 5 additions & 0 deletions doc/releases/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ Backward-Incompatible Changes
- Removed the Vega-Lite 3 and 4 wrappers (#2847).
- In regards to the grammar changes listed above, the old terminology will still work in many basic cases. On the other hand, if that old terminology gets used at a lower level, then it most likely will not work. For example, in the current version of :ref:`gallery_scatter_with_minimap`, two instances of the key ``param`` are used in dictionaries to specify axis domains. Those used to be ``selection``, but that usage is not compatible with the current Vega-Lite schema.

Maintenance
~~~~~~~~~~~

- Vega-Altair now uses ``ruff`` for linting.

Version 4.2.2 (released Jan 27, 2023)
-------------------------------------

Expand Down
31 changes: 31 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,37 @@ exclude = '''
requires = ["setuptools >= 40.6.0, <64", "wheel"]
build-backend = "setuptools.build_meta"

[tool.ruff]
target-version = "py310"
line-length = 88
select = [
# flake8-bugbear
"B",
# flake8-comprehensions
"C4",
# pycodestyle-error
"E",
# pycodestyle-warning
"W",
# pyflakes
"F",
# flake8-tidy-imports
"TID"
]
# ignore = ["E203", "E266", "E501", "W503"] see https://github.com/charliermarsh/ruff/issues/2402
ignore = ["E501", "TID252", "B905"]
exclude = [
".git",
"build",
"__pycache__",
"tests/examples_arguments_syntax",
"tests/examples_methods_syntax",
"altair/vegalite/v?/schema",
]

[tool.ruff.mccabe]
max-complexity = 18

[tool.pytest.ini_options]
markers = [
"save_engine: marks some of the tests which are using an external package to save a chart to e.g. a png file. This mark is used to run those tests selectively in the build GitHub Action.",
Expand Down
2 changes: 1 addition & 1 deletion requirements_dev.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
black<24
ipython
flake8
ruff
pytest
pytest-cov
m2r
Expand Down
Loading

0 comments on commit d7c0b22

Please sign in to comment.