diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6cb6c1247f..d66d594b9b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,11 +20,10 @@ repos: - id: check-json - id: detect-private-key - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.2 + rev: v0.1.5 hooks: - id: ruff - args: [holoviews] - files: holoviews/ + files: holoviews/|scripts/ - repo: https://github.com/hoxbro/clean_notebook rev: v0.1.13 hooks: @@ -35,3 +34,9 @@ repos: - id: codespell additional_dependencies: - tomli + - repo: https://github.com/pre-commit/pygrep-hooks + rev: v1.10.0 + hooks: + - id: rst-backticks + - id: rst-directive-colons + - id: rst-inline-touching-normal diff --git a/doc/FAQ.rst b/doc/FAQ.rst index fc9bd6f715..06153662af 100644 --- a/doc/FAQ.rst +++ b/doc/FAQ.rst @@ -15,7 +15,7 @@ potential pitfalls we hope to help users avoid: which for a Pandas dataframe will default to the name of that column. If you want to define your own specific label to display for a dimension, you can provide a tuple containing the column name and your -preferred label for it. For instance, if the column is named `x_col`, +preferred label for it. For instance, if the column is named ``x_col``, you can make the label 'X Label' using: .. code:: python @@ -33,7 +33,7 @@ passing arguments (or an unpacked dictionary) to ``redim.label``: curve = curve.redim.label(x_col='X Label', y_col='Label for Y') To override a label for plotting it is also possible to use the -`xlabel` and `ylabel` plot options: +``xlabel`` and ``ylabel`` plot options: .. code:: python @@ -45,7 +45,7 @@ To override a label for plotting it is also possible to use the **A:** Pass an unpacked dictionary containing the kdims/vdims' names as keys and a tuple of the bounds as values into ``redim.range``. -This constrains the bounds of x_col to `(0, max(x_col))`. +This constrains the bounds of x_col to ``(0, max(x_col))``. .. code:: python @@ -74,13 +74,13 @@ across all objects that are presented together, so that they can be compared directly. If you don't want objects that share a dimension to be normalized together in your layout, you can change the ``axiswise`` normalization option to True, making each object be normalized -independently, e.g. for a layout of `Curve` objects use: +independently, e.g. for a layout of ``Curve`` objects use: .. code:: python your_layout.opts(opts.Curve(axiswise=True)) -Alternatively you may also set `shared_axes=False` on the Layout itself: +Alternatively you may also set ``shared_axes=False`` on the Layout itself: .. code:: python @@ -96,7 +96,7 @@ normalized independently by changing ``framewise`` to True: **Q: How do I make only a single axis be shared across a layout?** -**A:** Even when `shared_axes=True`, HoloViews will only share axes +**A:** Even when ``shared_axes=True``, HoloViews will only share axes that have the same Dimension, so just make sure that axes that you want to be independent have a different name or label. Here, the x axis should be shared, but the y should be independent: @@ -107,7 +107,7 @@ axis should be shared, but the y should be independent: hv.Curve((xs, ys), 'x', 'y') + hv.Curve((xs, ys), 'x', 'z') -**Q: Why doesn't my DynamicMap respect the `framewise=False` option for axis normalization across frames?** +**Q: Why doesn't my DynamicMap respect the ``framewise=False`` option for axis normalization across frames?** **A:** Unfortunately, HoloViews has no way of knowing the axis ranges of objects that might be returned by future calls to a DynamicMap's @@ -365,7 +365,7 @@ to the return value of that cell, if it's a HoloViews object. So, if you want a given object to get customized, you need to make sure it is returned from the cell, or the options won't ever be applied, and you should only access it after it has been returned, or the options won't -*yet* have been applied. For instance, if you use `renderer.save()` +*yet* have been applied. For instance, if you use ``renderer.save()`` to export an object and only then return that object as the output of a cell, the exported object won't have the options applied, because they don't get applied until the object is returned diff --git a/doc/index.rst b/doc/index.rst index f6b16b2e5c..fdf3210fc9 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -19,7 +19,7 @@ The `Getting-Started `_ guide explains the basic concepts and h The `User Guide `_ goes more deeply into key concepts from HoloViews, when you are ready for further study. -The `API `_ is the definitive guide to each HoloViews object, but the same information is available more conveniently via the `hv.help()` command and tab completion in the Jupyter notebook. +The `API `_ is the definitive guide to each HoloViews object, but the same information is available more conveniently via the ``hv.help()`` command and tab completion in the Jupyter notebook. If you have any `issues `_ or wish to `contribute code `_, you can visit our `GitHub site `_ or file a topic on the `HoloViz Discourse `_. diff --git a/doc/releases.rst b/doc/releases.rst index fa6b14fb3f..911d38faf0 100644 --- a/doc/releases.rst +++ b/doc/releases.rst @@ -649,7 +649,7 @@ Enhancements: - Add support to Python 3.11 (`#5513 `__) -- Cleanup the top `__init__` module +- Cleanup the top ``__init__`` module (`#5516 `__) Documentation: @@ -1054,7 +1054,7 @@ to @douglas-raillard-arm, @jenssss, @w31t1, @Hoxbro, @martinfleis, @maximlt, - Support xyzservices.TileProvider as hv.Tiles input (`#5062 `__) -- Allow reversed layout/overlay binary operators for `+` and `*` to be used with custom objects +- Allow reversed layout/overlay binary operators for ``+`` and ``*`` to be used with custom objects (`#5073 `__) - Fix internal numpy.round usage (`#5095 `__) @@ -1479,11 +1479,11 @@ Bug fixes: (`#4646 `_) - Fixed bug resetting ranges (`#4654 `_) -- Fix bug matching elements to subplots in `DynamicMap` +- Fix bug matching elements to subplots in ``DynamicMap`` (`#4649 `_) -- Ensure consistent split `Violin` color assignment +- Ensure consistent split ``Violin`` color assignment (`#4650 `_) -- Ensure `PolyDrawCallback` always has vdim data +- Ensure ``PolyDrawCallback`` always has vdim data (`#4644 `_) - Set default align in bokeh correctly (`#4637 `_) @@ -1496,12 +1496,12 @@ Enhancements: (`#4572 `_) - Add ability to listen to dataset linked_selection (`#4547 `_) -- Added `selected` parameter to Bokeh PathPlot +- Added ``selected`` parameter to Bokeh PathPlot (`#4641 `_) Documentation: -- Improved `Bars` reference example, demonstrating the dataframe constructor +- Improved ``Bars`` reference example, demonstrating the dataframe constructor (`#4656 `_) - Various documentation fixes (`#4628 `_) @@ -1520,15 +1520,15 @@ and the core maintainer @philippjfr. Bug fixes: -- Fix the `.info` property to return the info +- Fix the ``.info`` property to return the info (`#4513 `_) -- Set `toolbar=True` the default in `save()` +- Set ``toolbar=True`` the default in ``save()`` (`#4518 `_) - Fix bug when the default value is 0 (`#4537 `_) - Ensure operations do not recursively accumulate pipelines (`#4544 `_) -- Fixed whiskers for `BoxWhisker` so that they never point inwards +- Fixed whiskers for ``BoxWhisker`` so that they never point inwards (`#4548 `_) - Fix issues with boomeranging events when aspect is set (`#4569 `_) @@ -1538,9 +1538,9 @@ Bug fixes: (`#4575 `_) - Do not attempt linking axes on annotations (`#4584 `_) -- Reset `RangeXY` when `framewise` is set +- Reset ``RangeXY`` when ``framewise`` is set (`#4585 `_) -- Add automatic collate for `Overlay` of `AdjointLayout`s +- Add automatic collate for ``Overlay`` of ``AdjointLayout`` s (`#4586 `_) - Fixed color-ranging after box select on side histogram (`#4587 `_) @@ -1551,30 +1551,30 @@ Compatibility: - Compatibility with bokeh 2.2 for CDSCallback (`#4568 `_) -- Handle `rcParam` deprecations in matplotlib 3.3 +- Handle ``rcParam`` deprecations in matplotlib 3.3 (`#4583 `_) Enhancements: -- Allow toggling the `selection_mode` on `link_selections` from the +- Allow toggling the ``selection_mode`` on ``link_selections`` from the context menu in the bokeh toolbar (`#4604 `_) - Optimize options machinery (`#4545 `_) -- Add new `Derived` stream class +- Add new ``Derived`` stream class (`#4532 `_) - Set Panel state to busy during callbacks (`#4546 `_) -- Support positional stream args in `DynamicMap` callback +- Support positional stream args in ``DynamicMap`` callback (`#4534 `_) -- `legend_opts` implemented +- ``legend_opts`` implemented (`#4558 `_) -- Add `History` stream +- Add ``History`` stream (`#4554 `_) - Updated spreading operation to support aggregate arrays (`#4562 `_) -- Add ability to supply `dim` transforms for all dimensions +- Add ability to supply ``dim`` transforms for all dimensions (`#4578 `_) - Add 'vline' and 'hline' Hover mode (`#4527 `_) @@ -1603,7 +1603,7 @@ Enhancements: (`#4372 `_) * Add support for lasso tool in linked selections (`#4362 `_) -- Add support for NdOverlay in linked selections +* Add support for NdOverlay in linked selections (`#4481 `_) * Add support for unwatching on ``Params`` stream (`#4417 `_) @@ -1700,7 +1700,7 @@ Enhancements: (`#4319 `_) * Unified datetime formatting in bokeh hover info (`#4318 `_) -* Add explicit `.df` and `.xr` namespaces to `dim` expressions to +* Add explicit ``.df`` and ``.xr`` namespaces to ``dim`` expressions to allow using dataframe and xarray APIs (`#4320 `_) * Allow using dim expressions as accessors @@ -1718,7 +1718,7 @@ Bug fixes: * Fix bug when updating bokeh Arrow elements (`#4313 `_) * Fix bug where Layout/Overlay constructors would drop items - (`#4313 `_) + (`#4323 `_) Compatibility: @@ -2298,8 +2298,8 @@ Enhancements: * Allow defining hook on backend load (`#3429 `_) -* Improvements for handling graph attributes in `Graph.from_networkx` - (``#3432 `_) +* Improvements for handling graph attributes in ``Graph.from_networkx`` + (`#3432 `_) Version 1.11.1 @@ -2332,9 +2332,9 @@ Bug fixes: Enhancements: * Provide control over gridlines ticker and mirrored axis ticker by - default (`#3398 `_) + default (`#3398 `_) * Enabled colorbars on CompositePlot classes such as Graphs, Chords - etc. (`#3397 `_) + etc. (`#3396 `_) * Ensure that xarray backend retains dimension metadata when casting element (`#3401 `_) * Consistently support clim options @@ -3842,6 +3842,7 @@ Features and improvements: - Bokeh plots now support custom tick formatters specified via Dimension value\_format (PR `#728 `__). + Version 1.5 ~~~~~~~~~~~ diff --git a/doc/roadmap.rst b/doc/roadmap.rst index dee5384bb9..382a6544bf 100644 --- a/doc/roadmap.rst +++ b/doc/roadmap.rst @@ -11,7 +11,7 @@ HoloViews is maintained by a core development team who coordinate contributions - Re-implement HoloViews layouts using Panel where feasible, to allow more powerful and flexible arrangements 3. **Separate packages into holoviews-core and extensions**: - HoloViews has always been designed with a backend-independent core that helps you describe and work with your data, along with plotting-library-specific backends that generate visualizations. To make this separation explicit and to make it simpler to generate objects in contexts where no backend is available, the holoviews package needs to be split into a core (probably to be called `holoviews-core`) along with packages per extension and possibly a `holoviews` metapackage that installs all of them as the single current package does. + HoloViews has always been designed with a backend-independent core that helps you describe and work with your data, along with plotting-library-specific backends that generate visualizations. To make this separation explicit and to make it simpler to generate objects in contexts where no backend is available, the holoviews package needs to be split into a core (probably to be called ``holoviews-core``) along with packages per extension and possibly a ``holoviews`` metapackage that installs all of them as the single current package does. 4. **Improved developer docs**: Because HoloViews includes both JavaScript and Python code and both core data-description features and optional backend-specific plotting support, it can be difficult to understand how to contribute to HoloViews development. We need much better developer docs to make it simpler to join the HoloViews team! diff --git a/doc/user_guide/index.rst b/doc/user_guide/index.rst index c1974ae8f2..616965873c 100644 --- a/doc/user_guide/index.rst +++ b/doc/user_guide/index.rst @@ -106,10 +106,10 @@ These guides provide detail about specific additional features in HoloViews: Using the ``Renderer`` and ``Plot`` classes for access to the plotting machinery. `Using linked brushing to cross-filter complex datasets `_ - Explains how to use the `link_selections` helper to cross-filter multiple elements. + Explains how to use the ``link_selections`` helper to cross-filter multiple elements. `Using Annotators to edit and label data `_ - Explains how to use the `annotate` helper to edit and annotate elements with the help of drawing tools and editable tables. + Explains how to use the ``annotate`` helper to edit and annotate elements with the help of drawing tools and editable tables. `Exporting and Archiving `_ Archive both your data and visualization in scripts and notebooks. diff --git a/holoviews/tests/core/test_archives.py b/holoviews/tests/core/test_archives.py index f8a44fc379..c698a518c4 100644 --- a/holoviews/tests/core/test_archives.py +++ b/holoviews/tests/core/test_archives.py @@ -124,7 +124,8 @@ def test_filearchive_json_single_file(self): fname = f"{export_name}_metadata.json" if not os.path.isfile(fname): raise AssertionError(f"No file {fname!r} created on export.") - self.assertEqual(json.load(open(fname)), data) + with open(fname) as f: + self.assertEqual(json.load(f), data) self.assertEqual(archive.listing(), []) """ diff --git a/holoviews/tests/plotting/bokeh/test_server.py b/holoviews/tests/plotting/bokeh/test_server.py index 76d2c14918..4f9f21cf8e 100644 --- a/holoviews/tests/plotting/bokeh/test_server.py +++ b/holoviews/tests/plotting/bokeh/test_server.py @@ -1,3 +1,4 @@ +import asyncio import time import param @@ -93,6 +94,13 @@ def tearDown(self): time.sleep(1) def _launcher(self, obj, threaded=True, port=6001): + try: + # In Python 3.12 this will raise a: + # `DeprecationWarning: There is no current event loop` + asyncio.get_event_loop() + except Exception: + asyncio.set_event_loop(asyncio.new_event_loop()) + self._port = port server = serve(obj, threaded=threaded, show=False, port=port) time.sleep(0.5) diff --git a/pyproject.toml b/pyproject.toml index 81ea95642b..0af7ae47fe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,8 +6,11 @@ requires = [ ] [tool.pytest.ini_options] -addopts = "-p no:dash" +addopts = ["--strict-config", "--strict-markers", "--color=yes"] +minversion = "7" +xfail_strict = true filterwarnings = [ + "error", # Numpy warning triggered in Bokeh, when timedelta or datetime numpy scalar are compared to a numerical scalar "ignore:elementwise comparison failed:DeprecationWarning:bokeh.core.property.bases", "ignore:dropping variables using `drop` will be deprecated; using drop_vars is encouraged:PendingDeprecationWarning:xarray.core.dataarray", @@ -47,8 +50,9 @@ filterwarnings = [ run.concurrency = ["greenlet"] [tool.ruff] -target-version = "py39" +fix = true +[tool.ruff.lint] select = [ "B", "E", @@ -84,20 +88,19 @@ ignore = [ "RUF005", # Consider {expr} instead of concatenation "RUF012", # Mutable class attributes should use `typing.ClassVar` ] - -fix = true unfixable = [ "F401", # Unused imports + "F841", # Unused variables ] -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] "__init__.py" = ["F403"] "holoviews/tests/*" = [ "RUF001", "RUF002", "RUF003", # Ambiguous unicode character "NPY002", # Replace legacy `np.random.rand` call with Generator ] -[tool.ruff.isort] +[tool.ruff.lint.isort] known-first-party = ["holoviews"] combine-as-imports = true diff --git a/scripts/check_latest_packages.py b/scripts/check_latest_packages.py index b864435ae3..9fcada6001 100644 --- a/scripts/check_latest_packages.py +++ b/scripts/check_latest_packages.py @@ -1,16 +1,17 @@ import sys -import requests -from datetime import datetime, date, timedelta +from datetime import date, datetime, timedelta +import requests from packaging.version import Version def main(*packages): allowed_date = date.today() - timedelta(days=5) - is_latest = True + GREEN, RED, RESET = "\033[92m", "\033[91m", "\033[0m" + all_latest = True for package in sorted(packages): url = f"https://pypi.org/pypi/{package}/json" - resp = requests.get(url).json() + resp = requests.get(url, timeout=20).json() latest = resp["info"]["version"] current = __import__(package).__version__ @@ -22,14 +23,16 @@ def main(*packages): ).date() version_check = Version(current) >= Version(latest) - date_check = allowed_date >= latest_release_date - is_latest &= version_check or date_check + date_check = current_release_date >= allowed_date + is_latest = version_check or date_check + all_latest &= is_latest + text_color = GREEN if is_latest else RED print( - f"Package: {package:<10} Current: {current:<7} ({current_release_date})\tLatest: {latest:<7} ({latest_release_date})" + f"{text_color}Package: {package:<10} Current: {current:<7} ({current_release_date})\tLatest: {latest:<7} ({latest_release_date}){RESET}" ) - if not is_latest: + if not all_latest: sys.exit(1)