hvplot 0.9.3a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. hvplot/__init__.py +322 -0
  2. hvplot/_version.py +16 -0
  3. hvplot/backend_transforms.py +329 -0
  4. hvplot/converter.py +2855 -0
  5. hvplot/cudf.py +26 -0
  6. hvplot/dask.py +42 -0
  7. hvplot/data/crime.csv +56 -0
  8. hvplot/datasets.yaml +48 -0
  9. hvplot/fugue.py +64 -0
  10. hvplot/ibis.py +21 -0
  11. hvplot/intake.py +32 -0
  12. hvplot/interactive.py +968 -0
  13. hvplot/networkx.py +625 -0
  14. hvplot/pandas.py +30 -0
  15. hvplot/plotting/__init__.py +63 -0
  16. hvplot/plotting/andrews_curves.py +99 -0
  17. hvplot/plotting/core.py +2288 -0
  18. hvplot/plotting/lag_plot.py +34 -0
  19. hvplot/plotting/parallel_coordinates.py +85 -0
  20. hvplot/plotting/scatter_matrix.py +220 -0
  21. hvplot/polars.py +21 -0
  22. hvplot/sample_data.py +30 -0
  23. hvplot/streamz.py +21 -0
  24. hvplot/tests/__init__.py +0 -0
  25. hvplot/tests/conftest.py +44 -0
  26. hvplot/tests/data/README.md +5 -0
  27. hvplot/tests/data/RGB-red.byte.tif +0 -0
  28. hvplot/tests/plotting/__init__.py +0 -0
  29. hvplot/tests/plotting/testcore.py +108 -0
  30. hvplot/tests/plotting/testohlc.py +34 -0
  31. hvplot/tests/plotting/testscattermatrix.py +138 -0
  32. hvplot/tests/test_links.py +99 -0
  33. hvplot/tests/testbackend_transforms.py +89 -0
  34. hvplot/tests/testcharts.py +452 -0
  35. hvplot/tests/testfugue.py +46 -0
  36. hvplot/tests/testgeo.py +468 -0
  37. hvplot/tests/testgeowithoutgv.py +60 -0
  38. hvplot/tests/testgridplots.py +259 -0
  39. hvplot/tests/testhelp.py +75 -0
  40. hvplot/tests/testibis.py +17 -0
  41. hvplot/tests/testinteractive.py +1442 -0
  42. hvplot/tests/testnetworkx.py +26 -0
  43. hvplot/tests/testoperations.py +385 -0
  44. hvplot/tests/testoptions.py +596 -0
  45. hvplot/tests/testoverrides.py +74 -0
  46. hvplot/tests/testpanel.py +70 -0
  47. hvplot/tests/testpatch.py +135 -0
  48. hvplot/tests/testplotting.py +69 -0
  49. hvplot/tests/teststreaming.py +28 -0
  50. hvplot/tests/testtransforms.py +39 -0
  51. hvplot/tests/testui.py +383 -0
  52. hvplot/tests/testutil.py +378 -0
  53. hvplot/tests/util.py +82 -0
  54. hvplot/ui.py +1032 -0
  55. hvplot/util.py +677 -0
  56. hvplot/utilities.py +129 -0
  57. hvplot/xarray.py +62 -0
  58. hvplot-0.9.3a1.dist-info/LICENSE +29 -0
  59. hvplot-0.9.3a1.dist-info/METADATA +243 -0
  60. hvplot-0.9.3a1.dist-info/RECORD +63 -0
  61. hvplot-0.9.3a1.dist-info/WHEEL +5 -0
  62. hvplot-0.9.3a1.dist-info/entry_points.txt +2 -0
  63. hvplot-0.9.3a1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,138 @@
1
+ from unittest import TestCase, SkipTest
2
+ import sys
3
+
4
+ from parameterized import parameterized
5
+ import numpy as np
6
+ import pandas as pd
7
+
8
+ from holoviews.core import GridMatrix, NdOverlay
9
+ from holoviews.element import (
10
+ Bivariate,
11
+ Distribution,
12
+ HexTiles,
13
+ Histogram,
14
+ Scatter,
15
+ )
16
+ from hvplot import scatter_matrix
17
+
18
+
19
+ class TestScatterMatrix(TestCase):
20
+ def setUp(self):
21
+ self.df = pd.DataFrame(np.random.randn(1000, 4), columns=['a', 'b', 'c', 'd'])
22
+
23
+ def test_returns_gridmatrix(self):
24
+ sm = scatter_matrix(self.df)
25
+ self.assertIsInstance(sm, GridMatrix)
26
+
27
+ def test_wrong_diagonal(self):
28
+ with self.assertRaises(ValueError):
29
+ scatter_matrix(self.df, diagonal='wrong')
30
+
31
+ def test_wrong_chart(self):
32
+ with self.assertRaises(ValueError):
33
+ scatter_matrix(self.df, chart='wrong')
34
+
35
+ def test_diagonal_default(self):
36
+ sm = scatter_matrix(self.df)
37
+ self.assertIsInstance(sm['a', 'a'], Histogram)
38
+
39
+ def test_offdiagonal_default(self):
40
+ sm = scatter_matrix(self.df)
41
+ self.assertIsInstance(sm['a', 'b'], Scatter)
42
+
43
+ def test_diagonal_kde(self):
44
+ sm = scatter_matrix(self.df, diagonal='kde')
45
+ self.assertIsInstance(sm['a', 'a'], Distribution)
46
+
47
+ def test_offdiagonal_bivariate(self):
48
+ sm = scatter_matrix(self.df, chart='bivariate')
49
+ self.assertIsInstance(sm['a', 'b'], Bivariate)
50
+
51
+ def test_offdiagonal_hexbin(self):
52
+ sm = scatter_matrix(self.df, chart='hexbin')
53
+ self.assertIsInstance(sm['a', 'b'], HexTiles)
54
+
55
+ def test_diagonal_kwargs_mutually_exclusive(self):
56
+ with self.assertRaises(TypeError):
57
+ scatter_matrix(self.df, diagonal_kwds=dict(a=1), hist_kwds=dict(a=1))
58
+ with self.assertRaises(TypeError):
59
+ scatter_matrix(self.df, diagonal_kwds=dict(a=1), density_kwds=dict(a=1))
60
+ with self.assertRaises(TypeError):
61
+ scatter_matrix(self.df, density_kwds=dict(a=1), hist_kwds=dict(a=1))
62
+
63
+ def test_diagonal_kwargs(self):
64
+ sm = scatter_matrix(self.df, diagonal_kwds=dict(line_color='red'))
65
+ self.assertEqual(sm['a', 'a'].opts.get().kwargs['line_color'], 'red')
66
+
67
+ def test_c(self):
68
+ df = self.df.copy(deep=True)
69
+ df['e'] = np.random.choice(list('xyz'), size=len(df))
70
+ sm = scatter_matrix(df, c='e')
71
+
72
+ self.assertIsInstance(sm['a', 'a'], NdOverlay)
73
+ diag_kdims = sm['a', 'a'].kdims
74
+ self.assertEqual(len(diag_kdims), 1)
75
+ self.assertEqual(diag_kdims[0].name, 'e')
76
+
77
+ self.assertIsInstance(sm['a', 'b'], Scatter)
78
+ offdiag_vdims = sm['a', 'b'].vdims
79
+ self.assertTrue('e' in (d.name for d in offdiag_vdims))
80
+
81
+
82
+ class TestDatashader(TestCase):
83
+ def setUp(self):
84
+ try:
85
+ import datashader # noqa
86
+ except ImportError:
87
+ raise SkipTest('Datashader not available')
88
+ if sys.maxsize < 2**32:
89
+ raise SkipTest('Datashader does not support 32-bit systems')
90
+ self.df = pd.DataFrame(np.random.randn(1000, 3), columns=['a', 'b', 'c'])
91
+
92
+ def test_rasterize_datashade_mutually_exclusive(self):
93
+ with self.assertRaises(ValueError):
94
+ scatter_matrix(self.df, rasterize=True, datashade=True)
95
+
96
+ def test_spread_but_no_rasterize_or_datashade(self):
97
+ with self.assertRaises(ValueError):
98
+ scatter_matrix(self.df, dynspread=True)
99
+ with self.assertRaises(ValueError):
100
+ scatter_matrix(self.df, spread=True)
101
+ with self.assertRaises(ValueError):
102
+ scatter_matrix(self.df, dynspread=True, spread=True)
103
+
104
+ @parameterized.expand([('rasterize',), ('datashade',)])
105
+ def test_rasterization(self, operation):
106
+ sm = scatter_matrix(self.df, **{operation: True})
107
+ dm = sm['a', 'b']
108
+ self.assertEqual(dm.callback.operation.name, operation)
109
+ dm[()]
110
+ self.assertEqual(len(dm.last.pipeline.operations), 3)
111
+
112
+ @parameterized.expand([('rasterize',), ('datashade',)])
113
+ def test_datashade_aggregator(self, operation):
114
+ sm = scatter_matrix(self.df, aggregator='mean', **{operation: True})
115
+ dm = sm['a', 'b']
116
+ dm[()]
117
+ self.assertEqual(dm.last.pipeline.operations[-1].aggregator, 'mean')
118
+
119
+ @parameterized.expand([('spread',), ('dynspread',)])
120
+ def test_spread_rasterize(self, operation):
121
+ sm = scatter_matrix(self.df, rasterize=True, **{operation: True})
122
+ dm = sm['a', 'b']
123
+ dm[()]
124
+ self.assertEqual(len(dm.last.pipeline.operations), 4)
125
+
126
+ @parameterized.expand([('spread',), ('dynspread',)])
127
+ def test_spread_datashade(self, operation):
128
+ sm = scatter_matrix(self.df, datashade=True, **{operation: True})
129
+ dm = sm['a', 'b']
130
+ dm[()]
131
+ self.assertEqual(len(dm.last.pipeline.operations), 4)
132
+
133
+ @parameterized.expand([('spread',), ('dynspread',)])
134
+ def test_spread_kwargs(self, operation):
135
+ sm = scatter_matrix(self.df, datashade=True, **{operation: True, 'shape': 'circle'})
136
+ dm = sm['a', 'b']
137
+ dm[()]
138
+ self.assertEqual(dm.last.pipeline.operations[-1].args[0].keywords['shape'], 'circle')
@@ -0,0 +1,99 @@
1
+ """Urls in docstrings etc. should be valid and secure, i.e.
2
+
3
+ - exist, i.e. provide a 200 response
4
+ - use https:// instead of http:// unless
5
+ - https:// is not supported by the web site
6
+ - https:// cannot be used. For example in SVGs.
7
+ """
8
+
9
+ import pathlib
10
+ import re
11
+ from concurrent.futures import ThreadPoolExecutor, as_completed
12
+ from urllib.request import urlopen
13
+ import glob
14
+
15
+ import pytest
16
+
17
+ # Note: The regex will find urls from code cells in notebooks ending with '\\' because the are really inside \"some_url\"
18
+ URL_REGEX = r"(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))" # pylint: disable=line-too-long
19
+ ROOT = pathlib.Path(__file__).parent
20
+ PACKAGE_ROOT = ROOT.parent
21
+ MAX_WORKERS = 10
22
+ POST_FIXES = ['.py', '.ipynb', '.md', '.yaml']
23
+ SKIP_URLS = [
24
+ 'https://anaconda.org/anaconda/hvplot',
25
+ 'https://anaconda.org/conda-forge/hvplot',
26
+ 'https://anaconda.org/pyviz/hvplot',
27
+ 'https://creativecommons.org/publicdomain/zero/1.0/',
28
+ 'https://github.com/rasterio/rasterio',
29
+ 'https://www.dask.org',
30
+ 'pyproject.toml/equivalent',
31
+ ]
32
+
33
+
34
+ def _get_files_to_check():
35
+ for post_fix in POST_FIXES:
36
+ for file in glob.glob('**/*' + post_fix, recursive=True):
37
+ yield pathlib.Path(file)
38
+
39
+
40
+ FIXTURES = [pytest.param(file, id=str(file)) for file in _get_files_to_check()]
41
+
42
+
43
+ def _skip_url(url: str):
44
+ if url in SKIP_URLS:
45
+ return True
46
+ if url.startswith('https://github.com/holoviz/hvplot/pull/'):
47
+ return True
48
+ if url.startswith('https://img.shields.io'):
49
+ return True
50
+ if url.startswith('assets.holoviews.org/data/'):
51
+ return True
52
+ if url.startswith('Math.PI'):
53
+ return True
54
+ return False
55
+
56
+
57
+ def _clean_url(url: str):
58
+ if url.endswith('\\'):
59
+ return url[0:-1]
60
+ return url
61
+
62
+
63
+ def _find_urls(text):
64
+ url = re.findall(URL_REGEX, text)
65
+ return {_clean_url(x[0]) for x in url if not _skip_url(x[0])}
66
+
67
+
68
+ def _request_a_response(url):
69
+ return urlopen(url)
70
+
71
+
72
+ def _verify_urls(urls):
73
+ """Returns True if all urls are valid"""
74
+ futures = {}
75
+ with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
76
+ futures = {}
77
+ for url in urls:
78
+ futures[executor.submit(_request_a_response, url)] = url
79
+
80
+ for future in as_completed(futures):
81
+ url = futures[future]
82
+ try:
83
+ result = future.result()
84
+ except Exception as ex:
85
+ raise ValueError(f'The url {url} raised an exception') from ex
86
+ if not result.status == 200:
87
+ raise ValueError(f'The url {url} responded with status {result.status}, not 200.')
88
+
89
+ return True
90
+
91
+
92
+ # @pytest.mark.parametrize(["file"], FIXTURES)
93
+ # def test_urls(file: pathlib.Path):
94
+ # """The urls is docstring should be valid"""
95
+ # # Given
96
+ # text = file.read_text()
97
+ # urls = _find_urls(text)
98
+ # # When/ Then
99
+ # assert _verify_urls(urls)
@@ -0,0 +1,89 @@
1
+ import holoviews
2
+ import pytest
3
+ from holoviews.core import Store
4
+ from holoviews.element import Area, Curve
5
+
6
+ from hvplot.backend_transforms import (
7
+ _transfer_opts,
8
+ _transform_size_to_mpl,
9
+ _is_interactive_opt,
10
+ )
11
+
12
+
13
+ @pytest.mark.parametrize(
14
+ ('width', 'height', 'aspect', 'opts'),
15
+ (
16
+ (300, 100, None, {'aspect': 3.0, 'fig_size': 100.0}),
17
+ (300, None, 3, {'aspect': 3, 'fig_size': 100.0}),
18
+ (None, 300, 3, {'aspect': 3, 'fig_size': 100.0}),
19
+ (300, None, None, {'fig_size': 100.0}),
20
+ (None, 300, None, {'fig_size': 100.0}),
21
+ ),
22
+ )
23
+ def test_transform_size_to_mpl(width, height, aspect, opts):
24
+ assert _transform_size_to_mpl(width, height, aspect) == opts
25
+
26
+
27
+ @pytest.mark.parametrize(
28
+ ('element', 'opt', 'val', 'backend', 'opt_kind', 'transf_opt', 'transf_val'),
29
+ (
30
+ (Curve([]), 'line_dash', 'dashed', 'matplotlib', 'style', 'linestyle', 'dashed'),
31
+ (Curve([]), 'line_alpha', 0.123, 'matplotlib', 'style', None, None),
32
+ (Area([]), 'line_cap', 'square', 'matplotlib', 'style', 'capstyle', 'projecting'),
33
+ (Curve([]), 'line_dash', 'dashed', 'plotly', 'style', 'dash', 'dash'),
34
+ ),
35
+ )
36
+ def test_transfer_opts(element, opt, val, backend, opt_kind, transf_opt, transf_val):
37
+ current_backend = Store.current_backend
38
+ if backend not in Store.registry:
39
+ holoviews.extension(backend)
40
+ Store.set_current_backend(backend)
41
+ try:
42
+ element = element.opts(backend='bokeh', **{opt: val})
43
+ new_element = element.apply(_transfer_opts, backend=backend)
44
+ new_opts = new_element.opts.get(opt_kind).kwargs
45
+ if transf_opt is None:
46
+ assert val not in new_opts.values()
47
+ else:
48
+ assert transf_opt in new_opts
49
+ assert new_opts[transf_opt] == transf_val
50
+ finally:
51
+ Store.set_current_backend(current_backend)
52
+
53
+
54
+ @pytest.mark.parametrize(
55
+ ('opt', 'val', 'backend', 'opt_kind', 'transf_opt', 'transf_val'),
56
+ (
57
+ ('line_dash', 'dashed', 'matplotlib', 'style', 'linestyle', 'dashed'),
58
+ ('line_dash', 'dashed', 'plotly', 'style', 'dash', 'dash'),
59
+ ),
60
+ )
61
+ def test_transfer_opts_compositeoverlay(opt, val, backend, opt_kind, transf_opt, transf_val):
62
+ current_backend = Store.current_backend
63
+ if backend not in Store.registry:
64
+ holoviews.extension(backend)
65
+ Store.set_current_backend(backend)
66
+ try:
67
+ element = Area([]) * Curve([]).opts(backend='bokeh', **{opt: val})
68
+ new_element = element.apply(_transfer_opts, backend=backend)
69
+ transformed_element = new_element.Curve.I
70
+ new_opts = transformed_element.opts.get(opt_kind).kwargs
71
+ assert transf_opt in new_opts
72
+ assert new_opts[transf_opt] == transf_val
73
+ finally:
74
+ Store.set_current_backend(current_backend)
75
+
76
+
77
+ @pytest.mark.parametrize(
78
+ ('bk_option', 'expected'),
79
+ (
80
+ ('height', False),
81
+ ('hover_line_alpha', True),
82
+ ('nonselection_line_alpha', True),
83
+ ('muted_line_alpha', True),
84
+ ('selection_line_alpha', True),
85
+ ('annular_muted_alpha', True),
86
+ ),
87
+ )
88
+ def test_is_interactive_opt(bk_option, expected):
89
+ assert _is_interactive_opt(bk_option) == expected