File: url.py

package info (click to toggle)
nbdkit 1.42.9-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 14,696 kB
  • sloc: ansic: 59,224; sh: 16,793; makefile: 6,463; python: 1,837; cpp: 1,116; ml: 504; perl: 502; tcl: 62
file content (78 lines) | stat: -rw-r--r-- 2,136 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# Example Python plugin.
#
# This example can be freely used for any purpose.

# Run it from the build directory like this:
#
#   ./nbdkit -f -v python ./plugins/python/examples/url.py \
#       url=http://example.com/disk.img
#
# Or run it after installing nbdkit like this:
#
#   nbdkit -f -v python ./plugins/python/examples/url.py \
#       url=http://example.com/disk.img
#
# The -f -v arguments are optional.  They cause the server to stay in
# the foreground and print debugging, which is useful when testing.

import urllib.request

import nbdkit

# There are several variants of the API.  nbdkit will use this
# constant to determine which one you want to use.  This is the latest
# version at the time this example was written.
API_VERSION = 2

url = None


# Parse the url parameter.
def config(key, value):
    global url
    if key == "url":
        url = value
    else:
        raise RuntimeError("unknown parameter: " + key)


def config_complete():
    if url is None:
        raise RuntimeError("url parameter is required")


# Although Python code cannot be run in parallel, if your
# plugin callbacks sleep then you can improve parallelism
# by relaxing the thread model.
def thread_model():
    return nbdkit.THREAD_MODEL_PARALLEL


# This is called when a client connects.
def open(readonly):
    return 1


def get_size(h):
    rq = urllib.request.Request(url, method='HEAD')
    rp = urllib.request.urlopen(rq)
    headers = rp.info()

    # Check the server supports range requests.
    if headers.get_all('accept-ranges') == []:
        raise RuntimeError("server does not support range requests")

    content_length = int(headers.get_all('content-length')[0])
    return content_length


def pread(h, buf, offset, flags):
    count = len(buf)
    headers = {"range": "bytes=%d-%d" % (offset, offset+count-1)}
    rq = urllib.request.Request(url, b"", headers)
    rp = urllib.request.urlopen(rq)
    b = rp.read()
    if len(b) != count:
        raise RuntimeError("incorrect length of data returned: perhaps the " +
                           "server does not really support range requests")
    buf[:] = b