holoviz / panel

@@ -34,7 +34,7 @@
Loading
34 34
    PasswordInput,
35 35
    TextAreaInput,
36 36
)
37 -
from .misc import Audio, FileDownload, VideoStream # noqa
37 +
from .misc import FileDownload, VideoStream # noqa
38 38
from .player import DiscretePlayer, Player # noqa
39 39
from .slider import ( # noqa
40 40
    DateSlider, DateRangeSlider, DiscreteSlider, EditableRangeSlider,

@@ -3,101 +3,19 @@
Loading
3 3
"""
4 4
import os
5 5
6 -
from io import BytesIO
7 6
from base64 import b64encode
8 -
from six import string_types
9 7
10 8
import param
11 -
import numpy as np
12 9
13 10
from ..io.notebook import push
14 11
from ..io.state import state
15 12
from ..models import (
16 -
    Audio as _BkAudio, VideoStream as _BkVideoStream, FileDownload as _BkFileDownload
13 +
    VideoStream as _BkVideoStream, FileDownload as _BkFileDownload
17 14
)
18 15
from .base import Widget
19 16
from .indicators import Progress # noqa
20 17
21 18
22 -
class _MediaBase(Widget):
23 -
24 -
    loop = param.Boolean(default=False, doc="""
25 -
        Whether the meida should loop""")
26 -
27 -
    time = param.Number(default=0, doc="""
28 -
        The current timestamp""")
29 -
30 -
    throttle = param.Integer(default=250, doc="""
31 -
        How frequently to sample the current playback time in
32 -
        milliseconds""")
33 -
34 -
    paused = param.Boolean(default=True, doc="""
35 -
        Whether the media is currently paused""")
36 -
37 -
    value = param.String(default='', doc="""
38 -
        The media file either local or remote.""")
39 -
40 -
    volume = param.Number(default=None, bounds=(0, 100), doc="""
41 -
        The volume of the media player.""")
42 -
43 -
    _rename = {'name': None, 'sample_rate': None}
44 -
45 -
    _default_mime = None
46 -
47 -
    _media_type = None
48 -
49 -
    def __init__(self, **params):
50 -
        self.param.warning('%s widget is deprecated, use the equivalent '
51 -
                           'Pane type instead.' % type(self).__name__)
52 -
        super().__init__(**params)
53 -
54 -
    def _from_numpy(self, data):
55 -
        from scipy.io import wavfile
56 -
        buffer = BytesIO()
57 -
        wavfile.write(buffer, self.sample_rate, data)
58 -
        return buffer
59 -
60 -
    def _process_param_change(self, msg):
61 -
        msg = super()._process_param_change(msg)
62 -
63 -
        if 'value' in msg:
64 -
            value =  msg['value']
65 -
            if isinstance(value, np.ndarray):
66 -
                fmt = 'wav'
67 -
                buffer = self._from_numpy(value)
68 -
                data = b64encode(buffer.getvalue())
69 -
            elif os.path.isfile(value):
70 -
                fmt = value.split('.')[-1]
71 -
                with open(value, 'rb') as f:
72 -
                    data = f.read()
73 -
                data = b64encode(data)
74 -
            elif value.lower().startswith('http'):
75 -
                return msg
76 -
            elif not value:
77 -
                data, fmt = b'', self._default_mime
78 -
            else:
79 -
                raise ValueError('Value should be either path to a sound file or numpy array')
80 -
            template = 'data:audio/{mime};base64,{data}'
81 -
            msg['value'] = template.format(data=data.decode('utf-8'),
82 -
                                           mime=fmt)
83 -
        return msg
84 -
85 -
86 -
class Audio(_MediaBase):
87 -
88 -
    sample_rate = param.Integer(default=44100, doc="""
89 -
        The sample_rate of the audio when given a NumPy array.""")
90 -
91 -
    value = param.ClassSelector(default='', class_=(string_types + (np.ndarray,)), doc="""
92 -
        The audio file either local or remote.""")
93 -
94 -
    _media_type = 'audio'
95 -
96 -
    _default_mime = 'wav'
97 -
98 -
    _widget_type = _BkAudio
99 -
100 -
101 19
class VideoStream(Widget):
102 20
103 21
    format = param.ObjectSelector(default='png', objects=['png', 'jpeg'],

@@ -5,7 +5,6 @@
Loading
5 5
layouts and widgets. Panes may render anything including plots, text,
6 6
images, equations etc.
7 7
"""
8 -
from .ace import Ace # noqa
9 8
from .alert import Alert # noqa
10 9
from .base import PaneBase, Pane, panel # noqa
11 10
from .equation import LaTeX # noqa

@@ -1,11 +1,23 @@
Loading
1 1
import pathlib
2 2
3 +
from base64 import b64encode
4 +
from io import BytesIO
5 +
3 6
import numpy as np
7 +
import pytest
8 +
9 +
try:
10 +
    from scipy.io import wavfile
11 +
except Exception:
12 +
    wavfile = None
4 13
5 14
from panel.pane import Audio, Video
6 15
7 16
ASSETS = pathlib.Path(__file__).parent / 'assets'
8 17
18 +
scipy_available = pytest.mark.skipif(wavfile is None, reason="requires scipy")
19 +
20 +
9 21
10 22
def test_video_url(document, comm):
11 23
    url = 'https://file-examples-com.github.io/uploads/2017/04/file_example_MP4_640_3MG.mp4'
@@ -50,3 +62,27 @@
Loading
50 62
    model = audio.get_root(document, comm=comm)
51 63
52 64
    assert model.value == 'data:audio/wav;base64,UklGRsQAAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YaAAAAAAAF4ErQjgDOgQuBRDGH0bXB7WIOMifCScJT8mYyYHJi0l1yMLIs0fJR0dGr4WFBMqDw4LzQZ1Ahf+vfl59VfxZu2z6UrmN+OD4DjeXNz42g7aotm22UjaWNvi3ODeTOEe5E3nzuqU7pXywvYO+2v/yAMZCFAMXhA1FMoXDxv7HYMgoCJJJHolLyZlJhwmVSURJFciKiCTHZoaSBeqE8oP' # noqa
65 +
66 +
67 +
@scipy_available
68 +
def test_audio_array(document, comm):
69 +
    data = np.random.randint(-100,100, 100).astype('int16')
70 +
    sample_rate = 10
71 +
    buffer = BytesIO()
72 +
    wavfile.write(buffer, sample_rate, data)
73 +
    b64_encoded = b64encode(buffer.getvalue()).decode('utf-8')
74 +
75 +
    audio = Audio(data, sample_rate=sample_rate)
76 +
    model = audio.get_root(document, comm=comm)
77 +
    model_value = model.value
78 +
79 +
    assert model_value.split(',')[1] == b64_encoded
80 +
    assert model.value.startswith('data:audio/wav;base64')
81 +
82 +
83 +
def test_audio_url(document, comm):
84 +
    audio_url = 'http://ccrma.stanford.edu/~jos/mp3/pno-cs.mp3'
85 +
    audio = Audio(audio_url)
86 +
    model = audio.get_root(document, comm=comm)
87 +
88 +
    assert audio_url == model.value

@@ -1,41 +1,8 @@
Loading
1 -
from io import BytesIO, StringIO
2 -
from base64 import b64encode
1 +
from io import StringIO
3 2
4 -
import numpy as np
5 3
import pytest
6 4
7 -
try:
8 -
    from scipy.io import wavfile
9 -
except Exception:
10 -
    wavfile = None
11 -
12 -
from panel.widgets import __file__ as wfile, Audio, FileDownload, Progress
13 -
14 -
scipy_available = pytest.mark.skipif(wavfile is None, reason="requires scipy")
15 -
16 -
17 -
@scipy_available
18 -
def test_audio_array(document, comm):
19 -
    data = np.random.randint(-100,100, 100).astype('int16')
20 -
    sample_rate = 10
21 -
    buffer = BytesIO()
22 -
    wavfile.write(buffer, sample_rate, data)
23 -
    b64_encoded = b64encode(buffer.getvalue()).decode('utf-8')
24 -
25 -
    audio = Audio(name='Button', value=data, sample_rate=sample_rate)
26 -
    widget = audio.get_root(document, comm=comm)
27 -
    widget_value = widget.value
28 -
29 -
    assert widget_value.split(',')[1] == b64_encoded
30 -
    assert widget.value.startswith('data:audio/wav;base64')
31 -
32 -
33 -
def test_audio_url(document, comm):
34 -
    audio_url = 'http://ccrma.stanford.edu/~jos/mp3/pno-cs.mp3'
35 -
    audio2 = Audio(name='Audio', value=audio_url)
36 -
    url_widget = audio2.get_root(document, comm=comm)
37 -
38 -
    assert audio_url == url_widget.value
5 +
from panel.widgets import __file__ as wfile, FileDownload, Progress
39 6
40 7
41 8
def test_progress_bounds():
Files Coverage
panel 83.45%
Project Totals (183 files) 83.45%
1
coverage:
2
  status:
3
    patch: off
4
    project:
5
      default:
6
        target: auto
7
        threshold: 0.5%
8

9
comment:
10
  require_changes: yes
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading