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

use ruff as linter #3008

Merged
merged 17 commits into from
Apr 4, 2023
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 .
mattijn marked this conversation as resolved.
Show resolved Hide resolved

- 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,
mattijn marked this conversation as resolved.
Show resolved Hide resolved
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