We truncated the diff of some files because they were too big.
If you want to see the full diff for every file, click here.
Changes of Revision 3
python-tvdb_api.changes
Changed
x
1
2
-------------------------------------------------------------------
3
+Thu Nov 1 16:49:30 UTC 2018 - Aliaksei Padvalski <avvissu@yandex.by>
4
+
5
+- Update to 2.0:
6
+ * Switch to TheTVDB new JSON based API - issue #57
7
+- Add support for Python3
8
+- Fix: non-executable-script
9
+- Update to description
10
+- Spec file cleanup
11
+
12
+-------------------------------------------------------------------
13
Fri Apr 21 12:40:16 UTC 2017 - aloisio@gmx.com
14
15
- Update to version 1.10
16
python-tvdb_api.spec
Changed
91
1
2
#
3
# spec file for package python-tvdb_api
4
#
5
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
6
# Copyright (c) 2017 Packman Team <packman@links2linux.de>
7
#
8
# All modifications and additions to the file contributed by third parties
9
10
#
11
12
13
-%define modname tvdb_api
14
+%{?!python_module:%define python_module() %{!?skip_python2:python-%{**}} %{!?skip_python3:python3-%{**}}}
15
Name: python-tvdb_api
16
-Version: 1.10
17
+Version: 2.0
18
Release: 0
19
-Summary: Python module to access the API from thetvdb.com
20
+Summary: Interface to thetvdb.com
21
# The UnLicense (https://unlicense.org)
22
License: SUSE-Permissive
23
Group: Productivity/Multimedia/Other
24
-Url: https://github.com/dbr/tvdb_api/tree/master
25
-Source0: https://files.pythonhosted.org/packages/source/t/%{modname}/%{modname}-%{version}.tar.gz
26
-BuildRequires: python-devel
27
-BuildRequires: python-setuptools
28
-BuildRoot: %{_tmppath}/%{name}-%{version}-build
29
+URL: https://github.com/dbr/tvdb_api
30
+Source0: https://files.pythonhosted.org/packages/source/t/tvdb_api/tvdb_api-%{version}.tar.gz
31
+BuildRequires: %{python_module devel}
32
+BuildRequires: %{python_module rpm-macros}
33
+BuildRequires: %{python_module setuptools}
34
+BuildRequires: fdupes
35
+Requires: python-requests-cache
36
BuildArch: noarch
37
-%py_requires
38
+%python_subpackages
39
40
%description
41
-tvdb_api is an easy to use interface to thetvdb.com via python
42
+An easy to use API interface to TheTVDB.com.
43
44
%prep
45
-%setup -q -n %{modname}-%{version}
46
-for file in {tvdb_cache,tvdb_api,tvdb_ui,tvdb_exceptions}
47
-do
48
- sed -i "1d" $file.py
49
-done
50
+%setup -q -n tvdb_api-%{version}
51
52
%build
53
-python setup.py build
54
+%python_build
55
56
%install
57
-python setup.py install --root=%{buildroot} --prefix=%{_prefix}
58
+%python_install
59
+
60
+# Fix: non-executable-script
61
+%{python_expand \
62
+pushd %{buildroot}%{$python_sitelib}
63
+for _file in $(grep -rl '^\#\!\/'); do
64
+ find -name ${_file##*/} -type f -not -perm /111 -exec sed '/^\#\!\//d' -i {} +
65
+ find -name ${_file##*/} -type f -perm /111 -exec sed 's|#!%{_bindir}/env python|#!%__$python|' -i {} +
66
+done
67
+popd
68
+}
69
+
70
+%if 0%{?have_python2}
71
+%py_compile %{buildroot}%{python2_sitelib}
72
+%py_compile -O %{buildroot}%{python2_sitelib}
73
+%endif
74
+%if 0%{?have_python3}
75
+%py3_compile %{buildroot}%{python3_sitelib}
76
+%py3_compile -O %{buildroot}%{python3_sitelib}
77
+%endif
78
+#
79
+
80
+%python_expand %fdupes %{buildroot}%{$python_sitelib}
81
82
-%files
83
-%defattr(-,root,root)
84
+%files %{python_files}
85
%doc UNLICENSE readme.md
86
-%{python_sitelib}/tvdb_*.py*
87
-%{python_sitelib}/%{modname}-%{version}-py%{python_version}.egg-info
88
+%{python_sitelib}/*
89
90
%changelog
91
tvdb_api-1.10.tar.gz/tvdb_cache.py
Deleted
201
1
2
-#!/usr/bin/env python
3
-#encoding:utf-8
4
-#author:dbr/Ben
5
-#project:tvdb_api
6
-#repository:http://github.com/dbr/tvdb_api
7
-#license:unlicense (http://unlicense.org/)
8
-
9
-"""
10
-urllib2 caching handler
11
-Modified from http://code.activestate.com/recipes/491261/
12
-"""
13
-from __future__ import with_statement
14
-
15
-__author__ = "dbr/Ben"
16
-__version__ = "1.10"
17
-
18
-import os
19
-import time
20
-import errno
21
-import httplib
22
-import urllib2
23
-import StringIO
24
-from hashlib import md5
25
-from threading import RLock
26
-
27
-cache_lock = RLock()
28
-
29
-def locked_function(origfunc):
30
- """Decorator to execute function under lock"""
31
- def wrapped(*args, **kwargs):
32
- cache_lock.acquire()
33
- try:
34
- return origfunc(*args, **kwargs)
35
- finally:
36
- cache_lock.release()
37
- return wrapped
38
-
39
-def calculate_cache_path(cache_location, url):
40
- """Checks if [cache_location]/[hash_of_url].headers and .body exist
41
- """
42
- thumb = md5(url).hexdigest()
43
- header = os.path.join(cache_location, thumb + ".headers")
44
- body = os.path.join(cache_location, thumb + ".body")
45
- return header, body
46
-
47
-def check_cache_time(path, max_age):
48
- """Checks if a file has been created/modified in the [last max_age] seconds.
49
- False means the file is too old (or doesn't exist), True means it is
50
- up-to-date and valid"""
51
- if not os.path.isfile(path):
52
- return False
53
- cache_modified_time = os.stat(path).st_mtime
54
- time_now = time.time()
55
- if cache_modified_time < time_now - max_age:
56
- # Cache is old
57
- return False
58
- else:
59
- return True
60
-
61
-@locked_function
62
-def exists_in_cache(cache_location, url, max_age):
63
- """Returns if header AND body cache file exist (and are up-to-date)"""
64
- hpath, bpath = calculate_cache_path(cache_location, url)
65
- if os.path.exists(hpath) and os.path.exists(bpath):
66
- return(
67
- check_cache_time(hpath, max_age)
68
- and check_cache_time(bpath, max_age)
69
- )
70
- else:
71
- # File does not exist
72
- return False
73
-
74
-@locked_function
75
-def store_in_cache(cache_location, url, response):
76
- """Tries to store response in cache."""
77
- hpath, bpath = calculate_cache_path(cache_location, url)
78
- try:
79
- outf = open(hpath, "wb")
80
- headers = str(response.info())
81
- outf.write(headers)
82
- outf.close()
83
-
84
- outf = open(bpath, "wb")
85
- outf.write(response.read())
86
- outf.close()
87
- except IOError:
88
- return True
89
- else:
90
- return False
91
-
92
-@locked_function
93
-def delete_from_cache(cache_location, url):
94
- """Deletes a response in cache."""
95
- hpath, bpath = calculate_cache_path(cache_location, url)
96
- try:
97
- if os.path.exists(hpath):
98
- os.remove(hpath)
99
- if os.path.exists(bpath):
100
- os.remove(bpath)
101
- except IOError:
102
- return True
103
- else:
104
- return False
105
-
106
-class CacheHandler(urllib2.BaseHandler):
107
- """Stores responses in a persistant on-disk cache.
108
-
109
- If a subsequent GET request is made for the same URL, the stored
110
- response is returned, saving time, resources and bandwidth
111
- """
112
- @locked_function
113
- def __init__(self, cache_location, max_age = 21600):
114
- """The location of the cache directory"""
115
- self.max_age = max_age
116
- self.cache_location = cache_location
117
- if not os.path.exists(self.cache_location):
118
- try:
119
- os.mkdir(self.cache_location)
120
- except OSError, e:
121
- if e.errno == errno.EEXIST and os.path.isdir(self.cache_location):
122
- # File exists, and it's a directory,
123
- # another process beat us to creating this dir, that's OK.
124
- pass
125
- else:
126
- # Our target dir is already a file, or different error,
127
- # relay the error!
128
- raise
129
-
130
- def default_open(self, request):
131
- """Handles GET requests, if the response is cached it returns it
132
- """
133
- if request.get_method() is not "GET":
134
- return None # let the next handler try to handle the request
135
-
136
- if exists_in_cache(
137
- self.cache_location, request.get_full_url(), self.max_age
138
- ):
139
- return CachedResponse(
140
- self.cache_location,
141
- request.get_full_url(),
142
- set_cache_header = True
143
- )
144
- else:
145
- return None
146
-
147
- def http_response(self, request, response):
148
- """Gets a HTTP response, if it was a GET request and the status code
149
- starts with 2 (200 OK etc) it caches it and returns a CachedResponse
150
- """
151
- if (request.get_method() == "GET"
152
- and str(response.code).startswith("2")
153
- ):
154
- if 'x-local-cache' not in response.info():
155
- # Response is not cached
156
- set_cache_header = store_in_cache(
157
- self.cache_location,
158
- request.get_full_url(),
159
- response
160
- )
161
- else:
162
- set_cache_header = True
163
-
164
- return CachedResponse(
165
- self.cache_location,
166
- request.get_full_url(),
167
- set_cache_header = set_cache_header
168
- )
169
- else:
170
- return response
171
-
172
-class CachedResponse(StringIO.StringIO):
173
- """An urllib2.response-like object for cached responses.
174
-
175
- To determine if a response is cached or coming directly from
176
- the network, check the x-local-cache header rather than the object type.
177
- """
178
-
179
- @locked_function
180
- def __init__(self, cache_location, url, set_cache_header=True):
181
- self.cache_location = cache_location
182
- hpath, bpath = calculate_cache_path(cache_location, url)
183
-
184
- StringIO.StringIO.__init__(self, file(bpath, "rb").read())
185
-
186
- self.url = url
187
- self.code = 200
188
- self.msg = "OK"
189
- headerbuf = file(hpath, "rb").read()
190
- if set_cache_header:
191
- headerbuf += "x-local-cache: %s\r\n" % (bpath)
192
- self.headers = httplib.HTTPMessage(StringIO.StringIO(headerbuf))
193
-
194
- def info(self):
195
- """Returns headers
196
- """
197
- return self.headers
198
-
199
- def geturl(self):
200
- """Returns original URL
201
tvdb_api-1.10.tar.gz/PKG-INFO -> tvdb_api-2.0.tar.gz/PKG-INFO
Changed
27
1
2
Metadata-Version: 1.1
3
Name: tvdb_api
4
-Version: 1.10
5
+Version: 2.0
6
Summary: Interface to thetvdb.com
7
Home-page: http://github.com/dbr/tvdb_api/tree/master
8
Author: dbr/Ben
9
10
>>> ep = t['My Name Is Earl'][1][22]
11
>>> ep
12
<Episode 01x22 - Stole a Badge>
13
- >>> ep['episodename']
14
+ >>> ep['episodeName']
15
u'Stole a Badge'
16
17
Platform: UNKNOWN
18
19
Classifier: Programming Language :: Python :: 2.7
20
Classifier: Programming Language :: Python :: 3.3
21
Classifier: Programming Language :: Python :: 3.4
22
+Classifier: Programming Language :: Python :: 3.5
23
+Classifier: Programming Language :: Python :: 3.6
24
Classifier: Topic :: Multimedia
25
Classifier: Topic :: Utilities
26
Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
tvdb_api-1.10.tar.gz/Rakefile -> tvdb_api-2.0.tar.gz/Rakefile
Changed
10
1
2
end
3
4
desc "Upload current version to PyPi"
5
-task :topypi do
6
+task :topypi => :test do
7
cur_file = File.open("tvdb_api.py").read()
8
tvdb_api_version = cur_file.scan(/__version__ = "(.*)"/)
9
tvdb_api_version = tvdb_api_version[0][0]
10
tvdb_api-1.10.tar.gz/readme.md -> tvdb_api-2.0.tar.gz/readme.md
Changed
19
1
2
The data is stored in an attribute named `data`, within the Show instance:
3
4
>>> t['scrubs'].data.keys()
5
- ['networkid', 'rating', 'airs_dayofweek', 'contentrating', 'seriesname', 'id', 'airs_time', 'network', 'fanart', 'lastupdated', 'actors', 'ratingcount', 'status', 'added', 'poster', 'imdb_id', 'genre', 'banner', 'seriesid', 'language', 'zap2it_id', 'addedby', 'tms_wanted', 'firstaired', 'runtime', 'overview']
6
+ ['networkid', 'rating', 'airs_dayofweek', 'contentrating', 'seriesname', 'id', 'airs_time', 'network', 'fanart', 'lastupdated', 'actors', 'ratingcount', 'status', 'added', 'poster', 'tms_wanted_old', 'imdb_id', 'genre', 'banner', 'seriesid', 'language', 'zap2it_id', 'addedby', 'firstaired', 'runtime', 'overview']
7
8
Although each element is also accessible via `t['scrubs']` for ease-of-use:
9
10
11
Remember a simple list of actors is accessible via the default Show data:
12
13
>>> t['scrubs']['actors']
14
- u'|Zach Braff|Donald Faison|Sarah Chalke|Christa Miller|Aloma Wright|Robert Maschio|Sam Lloyd|Neil Flynn|Ken Jenkins|Judy Reyes|John C. McGinley|Travis Schuldt|Johnny Kastl|Heather Graham|Michael Mosley|Kerry Bish\xe9|Dave Franco|Eliza Coupe|'
15
+ u'|Zach Braff|Donald Faison|Sarah Chalke|Judy Reyes|John C. McGinley|Neil Flynn|Ken Jenkins|Christa Miller|Aloma Wright|Robert Maschio|Sam Lloyd|Travis Schuldt|Johnny Kastl|Heather Graham|Michael Mosley|Kerry Bish\xe9|Dave Franco|Eliza Coupe|'
16
17
[tvdb]: http://thetvdb.com
18
[tvnamer]: http://github.com/dbr/tvnamer
19
tvdb_api-1.10.tar.gz/setup.py -> tvdb_api-2.0.tar.gz/setup.py
Changed
73
1
2
import sys
3
from setuptools import setup
4
+from setuptools.command.test import test as TestCommand
5
6
-IS_PY2 = sys.version_info[0] == 2
7
8
-_requirements = []
9
-if not IS_PY2:
10
- _requirements.append('requests_cache')
11
+class PyTest(TestCommand):
12
+ user_options = [('pytest-args=', 'a', "Arguments to pass to py.test")]
13
14
- # 'requests' is installed as requirement by requests-cache,
15
- # commented out because it triggers a bug in setuptool:
16
- # https://bitbucket.org/pypa/setuptools/issue/196/tests_require-pytest-pytest-cov-breaks
17
+ def initialize_options(self):
18
+ TestCommand.initialize_options(self)
19
+ self.pytest_args = []
20
21
+ def finalize_options(self):
22
+ TestCommand.finalize_options(self)
23
+ self.test_args = []
24
+ self.test_suite = True
25
26
+ def run_tests(self):
27
+ #import here, cause outside the eggs aren't loaded
28
+ import pytest
29
+ errno = pytest.main(self.pytest_args)
30
+ sys.exit(errno)
31
+
32
+
33
+_requirements = ['requests_cache', 'requests']
34
_modules = ['tvdb_api', 'tvdb_ui', 'tvdb_exceptions']
35
-if IS_PY2:
36
- _modules.append('tvdb_cache')
37
38
39
setup(
40
name = 'tvdb_api',
41
-version='1.10',
42
+version='2.0',
43
44
author='dbr/Ben',
45
description='Interface to thetvdb.com',
46
47
>>> ep = t['My Name Is Earl'][1][22]
48
>>> ep
49
<Episode 01x22 - Stole a Badge>
50
->>> ep['episodename']
51
+>>> ep['episodeName']
52
u'Stole a Badge'
53
""",
54
55
py_modules = _modules,
56
install_requires = _requirements,
57
58
+tests_require=['pytest'],
59
+cmdclass = {'test': PyTest},
60
+
61
classifiers=[
62
"Intended Audience :: Developers",
63
"Natural Language :: English",
64
65
"Programming Language :: Python :: 2.7",
66
"Programming Language :: Python :: 3.3",
67
"Programming Language :: Python :: 3.4",
68
+ "Programming Language :: Python :: 3.5",
69
+ "Programming Language :: Python :: 3.6",
70
"Topic :: Multimedia",
71
"Topic :: Utilities",
72
"Topic :: Software Development :: Libraries :: Python Modules",
73
tvdb_api-1.10.tar.gz/tests/test_tvdb_api.py -> tvdb_api-2.0.tar.gz/tests/test_tvdb_api.py
Changed
201
1
2
import os
3
import sys
4
import datetime
5
-import unittest
6
+import pytest
7
8
# Force parent directory onto path
9
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
10
11
import tvdb_api
12
-import tvdb_ui
13
from tvdb_api import (tvdb_shownotfound, tvdb_seasonnotfound,
14
-tvdb_episodenotfound, tvdb_attributenotfound)
15
+ tvdb_episodenotfound, tvdb_attributenotfound)
16
17
18
-IS_PY2 = sys.version_info[0] == 2
19
-
20
-
21
-class test_tvdb_basic(unittest.TestCase):
22
+class TestTvdbBasic:
23
# Used to store the cached instance of Tvdb()
24
t = None
25
-
26
- def setUp(self):
27
- if self.t is None:
28
- self.__class__.t = tvdb_api.Tvdb(cache = True, banners = False)
29
-
30
+
31
+ @classmethod
32
+ def setup_class(cls):
33
+ if cls.t is None:
34
+ cls.t = tvdb_api.Tvdb(cache=True, banners=False)
35
+
36
def test_different_case(self):
37
"""Checks the auto-correction of show names is working.
38
It should correct the weirdly capitalised 'sCruBs' to 'Scrubs'
39
"""
40
- self.assertEquals(self.t['scrubs'][1][4]['episodename'], 'My Old Lady')
41
- self.assertEquals(self.t['sCruBs']['seriesname'], 'Scrubs')
42
+ assert self.t['scrubs'][1][4]['episodeName'] == 'My Old Lady'
43
+ assert self.t['sCruBs']['seriesName'] == 'Scrubs'
44
45
def test_spaces(self):
46
"""Checks shownames with spaces
47
"""
48
- self.assertEquals(self.t['My Name Is Earl']['seriesname'], 'My Name Is Earl')
49
- self.assertEquals(self.t['My Name Is Earl'][1][4]['episodename'], 'Faked His Own Death')
50
+ assert self.t['My Name Is Earl']['seriesName'] == 'My Name Is Earl'
51
+ assert self.t['My Name Is Earl'][1][4]['episodeName'] == 'Faked My Own Death'
52
53
def test_numeric(self):
54
"""Checks numeric show names
55
"""
56
- self.assertEquals(self.t['24'][2][20]['episodename'], 'Day 2: 3:00 A.M.-4:00 A.M.')
57
- self.assertEquals(self.t['24']['seriesname'], '24')
58
+ assert self.t['24'][2][20]['episodeName'] == 'Day 2: 3:00 A.M. - 4:00 A.M.'
59
+ assert self.t['24']['seriesName'] == '24'
60
61
def test_show_iter(self):
62
"""Iterating over a show returns each seasons
63
"""
64
- self.assertEquals(
65
- len(
66
- [season for season in self.t['Life on Mars']]
67
- ),
68
- 2
69
- )
70
-
71
+ assert len([season for season in self.t['Life on Mars']]) == 2
72
+
73
def test_season_iter(self):
74
"""Iterating over a show returns episodes
75
"""
76
- self.assertEquals(
77
- len(
78
- [episode for episode in self.t['Life on Mars'][1]]
79
- ),
80
- 8
81
- )
82
+ assert len([episode for episode in self.t['Life on Mars'][1]]) == 8
83
84
def test_get_episode_overview(self):
85
"""Checks episode overview is retrieved correctly.
86
"""
87
- self.assertEquals(
88
- self.t['Battlestar Galactica (2003)'][1][6]['overview'].startswith(
89
- 'When a new copy of Doral, a Cylon who had been previously'),
90
- True
91
- )
92
+ assert self.t['Battlestar Galactica (2003)'][1][6]['overview'].startswith('When a new copy of Doral, a Cylon who had been previously') == True
93
94
def test_get_parent(self):
95
"""Check accessing series from episode instance
96
97
season = show[1]
98
episode = show[1][1]
99
100
- self.assertEquals(
101
- season.show,
102
- show
103
- )
104
-
105
- self.assertEquals(
106
- episode.season,
107
- season
108
- )
109
-
110
- self.assertEquals(
111
- episode.season.show,
112
- show
113
- )
114
+ assert season.show == show
115
+ assert episode.season == season
116
+ assert episode.season.show == show
117
118
def test_no_season(self):
119
show = self.t['Katekyo Hitman Reborn']
120
print(tvdb_api)
121
print(show[1][1])
122
123
-class test_tvdb_errors(unittest.TestCase):
124
- # Used to store the cached instance of Tvdb()
125
+
126
+class TestTvdbErrors:
127
t = None
128
-
129
- def setUp(self):
130
- if self.t is None:
131
- self.__class__.t = tvdb_api.Tvdb(cache = True, banners = False)
132
+
133
+ @classmethod
134
+ def setup_class(cls):
135
+ if cls.t is None:
136
+ cls.t = tvdb_api.Tvdb(cache=True, banners=False)
137
138
def test_seasonnotfound(self):
139
"""Checks exception is thrown when season doesn't exist.
140
"""
141
- self.assertRaises(tvdb_seasonnotfound, lambda:self.t['CNNNN'][10][1])
142
+ with pytest.raises(tvdb_seasonnotfound):
143
+ self.t['CNNNN'][10]
144
145
def test_shownotfound(self):
146
"""Checks exception is thrown when episode doesn't exist.
147
"""
148
- self.assertRaises(tvdb_shownotfound, lambda:self.t['the fake show thingy'])
149
-
150
+ with pytest.raises(tvdb_shownotfound):
151
+ self.t['the fake show thingy']
152
+
153
def test_episodenotfound(self):
154
"""Checks exception is raised for non-existent episode
155
"""
156
- self.assertRaises(tvdb_episodenotfound, lambda:self.t['Scrubs'][1][30])
157
+ with pytest.raises(tvdb_episodenotfound):
158
+ self.t['Scrubs'][1][30]
159
160
def test_attributenamenotfound(self):
161
"""Checks exception is thrown for if an attribute isn't found.
162
"""
163
- self.assertRaises(tvdb_attributenotfound, lambda:self.t['CNNNN'][1][6]['afakeattributething'])
164
- self.assertRaises(tvdb_attributenotfound, lambda:self.t['CNNNN']['afakeattributething'])
165
+ with pytest.raises(tvdb_attributenotfound):
166
+ self.t['CNNNN'][1][6]['afakeattributething']
167
+ self.t['CNNNN']['afakeattributething']
168
169
-class test_tvdb_search(unittest.TestCase):
170
+
171
+class TestTvdbSearch:
172
# Used to store the cached instance of Tvdb()
173
t = None
174
-
175
- def setUp(self):
176
- if self.t is None:
177
- self.__class__.t = tvdb_api.Tvdb(cache = True, banners = False)
178
+
179
+ @classmethod
180
+ def setup_class(cls):
181
+ if cls.t is None:
182
+ cls.t = tvdb_api.Tvdb(cache=True, banners=False)
183
184
def test_search_len(self):
185
"""There should be only one result matching
186
"""
187
- self.assertEquals(len(self.t['My Name Is Earl'].search('Faked His Own Death')), 1)
188
+ assert len(self.t['My Name Is Earl'].search('Faked My Own Death')) == 1
189
190
def test_search_checkname(self):
191
"""Checks you can get the episode name of a search result
192
"""
193
- self.assertEquals(self.t['Scrubs'].search('my first')[0]['episodename'], 'My First Day')
194
- self.assertEquals(self.t['My Name Is Earl'].search('Faked His Own Death')[0]['episodename'], 'Faked His Own Death')
195
-
196
+ assert self.t['Scrubs'].search('my first')[0]['episodeName'] == 'My First Day'
197
+ assert self.t['My Name Is Earl'].search('Faked My Own Death')[0]['episodeName'] == 'Faked My Own Death'
198
+
199
def test_search_multiresults(self):
200
"""Checks search can return multiple results
201
tvdb_api-1.10.tar.gz/tvdb_api.egg-info/PKG-INFO -> tvdb_api-2.0.tar.gz/tvdb_api.egg-info/PKG-INFO
Changed
27
1
2
Metadata-Version: 1.1
3
Name: tvdb-api
4
-Version: 1.10
5
+Version: 2.0
6
Summary: Interface to thetvdb.com
7
Home-page: http://github.com/dbr/tvdb_api/tree/master
8
Author: dbr/Ben
9
10
>>> ep = t['My Name Is Earl'][1][22]
11
>>> ep
12
<Episode 01x22 - Stole a Badge>
13
- >>> ep['episodename']
14
+ >>> ep['episodeName']
15
u'Stole a Badge'
16
17
Platform: UNKNOWN
18
19
Classifier: Programming Language :: Python :: 2.7
20
Classifier: Programming Language :: Python :: 3.3
21
Classifier: Programming Language :: Python :: 3.4
22
+Classifier: Programming Language :: Python :: 3.5
23
+Classifier: Programming Language :: Python :: 3.6
24
Classifier: Topic :: Multimedia
25
Classifier: Topic :: Utilities
26
Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
tvdb_api-1.10.tar.gz/tvdb_api.egg-info/SOURCES.txt -> tvdb_api-2.0.tar.gz/tvdb_api.egg-info/SOURCES.txt
Changed
16
1
2
readme.md
3
setup.py
4
tvdb_api.py
5
-tvdb_cache.py
6
tvdb_exceptions.py
7
tvdb_ui.py
8
tests/gprof2dot.py
9
10
tvdb_api.egg-info/PKG-INFO
11
tvdb_api.egg-info/SOURCES.txt
12
tvdb_api.egg-info/dependency_links.txt
13
+tvdb_api.egg-info/requires.txt
14
tvdb_api.egg-info/top_level.txt
15
\ No newline at end of file
16
tvdb_api-2.0.tar.gz/tvdb_api.egg-info/requires.txt
Added
4
1
2
+requests_cache
3
+requests
4
tvdb_api-1.10.tar.gz/tvdb_api.egg-info/top_level.txt -> tvdb_api-2.0.tar.gz/tvdb_api.egg-info/top_level.txt
Changed
7
1
2
tvdb_api
3
-tvdb_ui
4
tvdb_exceptions
5
-tvdb_cache
6
+tvdb_ui
7
tvdb_api-1.10.tar.gz/tvdb_api.py -> tvdb_api-2.0.tar.gz/tvdb_api.py
Changed
201
1
2
#!/usr/bin/env python
3
-#encoding:utf-8
4
-#author:dbr/Ben
5
-#project:tvdb_api
6
-#repository:http://github.com/dbr/tvdb_api
7
-#license:unlicense (http://unlicense.org/)
8
+# encoding:utf-8
9
+# author:dbr/Ben
10
+# project:tvdb_api
11
+# repository:http://github.com/dbr/tvdb_api
12
+# license:unlicense (http://unlicense.org/)
13
14
"""Simple-to-use Python interface to The TVDB's API (thetvdb.com)
15
16
17
18
>>> from tvdb_api import Tvdb
19
>>> t = Tvdb()
20
->>> t['Lost'][4][11]['episodename']
21
+>>> t['Lost'][4][11]['episodeName']
22
u'Cabin Fever'
23
"""
24
-__author__ = "dbr/Ben"
25
-__version__ = "1.10"
26
27
-import sys
28
+__author__ = "dbr/Ben"
29
+__version__ = "2.0"
30
31
-IS_PY2 = sys.version_info[0] == 2
32
33
+import sys
34
import os
35
import time
36
-if IS_PY2:
37
- import urllib
38
- import urllib2
39
- from tvdb_cache import CacheHandler
40
- from urllib import quote as url_quote
41
-else:
42
- import requests
43
- from urllib.parse import quote as url_quote
44
+import types
45
import getpass
46
import tempfile
47
import warnings
48
import logging
49
import datetime
50
-import zipfile
51
+import hashlib
52
53
-try:
54
- import xml.etree.cElementTree as ElementTree
55
-except ImportError:
56
- import xml.etree.ElementTree as ElementTree
57
+import requests
58
+import requests_cache
59
+from requests_cache.backends.base import _to_bytes, _DEFAULT_HEADERS
60
61
-try:
62
- import gzip
63
-except ImportError:
64
- gzip = None
65
+
66
+IS_PY2 = sys.version_info[0] == 2
67
+
68
+if IS_PY2:
69
+ user_input = raw_input
70
+ from urllib import quote as url_quote
71
+else:
72
+ from urllib.parse import quote as url_quote
73
+ user_input = input
74
75
76
if IS_PY2:
77
78
int_types = int
79
text_type = str
80
81
-
82
-from tvdb_ui import BaseUI, ConsoleUI
83
-from tvdb_exceptions import (tvdb_error, tvdb_userabort, tvdb_shownotfound,
84
- tvdb_seasonnotfound, tvdb_episodenotfound, tvdb_attributenotfound)
85
-
86
lastTimeout = None
87
88
+
89
def log():
90
return logging.getLogger("tvdb_api")
91
92
93
+## Exceptions
94
+
95
+class tvdb_exception(Exception):
96
+ """Any exception generated by tvdb_api
97
+ """
98
+ pass
99
+
100
+class tvdb_error(tvdb_exception):
101
+ """An error with thetvdb.com (Cannot connect, for example)
102
+ """
103
+ pass
104
+
105
+class tvdb_userabort(tvdb_exception):
106
+ """User aborted the interactive selection (via
107
+ the q command, ^c etc)
108
+ """
109
+ pass
110
+
111
+class tvdb_notauthorized(tvdb_exception):
112
+ """An authorization error with thetvdb.com
113
+ """
114
+ pass
115
+
116
+class tvdb_shownotfound(tvdb_exception):
117
+ """Show cannot be found on thetvdb.com (non-existant show)
118
+ """
119
+ pass
120
+
121
+class tvdb_seasonnotfound(tvdb_exception):
122
+ """Season cannot be found on thetvdb.com
123
+ """
124
+ pass
125
+
126
+class tvdb_episodenotfound(tvdb_exception):
127
+ """Episode cannot be found on thetvdb.com
128
+ """
129
+ pass
130
+
131
+class tvdb_resourcenotfound(tvdb_exception):
132
+ """Resource cannot be found on thetvdb.com
133
+ """
134
+ pass
135
+
136
+class tvdb_invalidlanguage(tvdb_exception):
137
+ """invalid language given on thetvdb.com
138
+ """
139
+ def __init__(self, value):
140
+ self.value = value
141
+
142
+ def __str__(self):
143
+ return repr(self.value)
144
+
145
+class tvdb_attributenotfound(tvdb_exception):
146
+ """Raised if an episode does not have the requested
147
+ attribute (such as a episode name)
148
+ """
149
+ pass
150
+
151
+
152
+## UI
153
+
154
+class BaseUI(object):
155
+ """Base user interface for Tvdb show selection.
156
+
157
+ Selects first show.
158
+
159
+ A UI is a callback. A class, it's __init__ function takes two arguments:
160
+
161
+ - config, which is the Tvdb config dict, setup in tvdb_api.py
162
+ - log, which is Tvdb's logger instance (which uses the logging module). You can
163
+ call log.info() log.warning() etc
164
+
165
+ It must have a method "selectSeries", this is passed a list of dicts, each dict
166
+ contains the the keys "name" (human readable show name), and "sid" (the shows
167
+ ID as on thetvdb.com). For example:
168
+
169
+ [{'name': u'Lost', 'sid': u'73739'},
170
+ {'name': u'Lost Universe', 'sid': u'73181'}]
171
+
172
+ The "selectSeries" method must return the appropriate dict, or it can raise
173
+ tvdb_userabort (if the selection is aborted), tvdb_shownotfound (if the show
174
+ cannot be found).
175
+
176
+ A simple example callback, which returns a random series:
177
+
178
+ >>> import random
179
+ >>> from tvdb_ui import BaseUI
180
+ >>> class RandomUI(BaseUI):
181
+ ... def selectSeries(self, allSeries):
182
+ ... import random
183
+ ... return random.choice(allSeries)
184
+
185
+ Then to use it..
186
+
187
+ >>> from tvdb_api import Tvdb
188
+ >>> t = Tvdb(custom_ui = RandomUI)
189
+ >>> random_matching_series = t['Lost']
190
+ >>> type(random_matching_series)
191
+ <class 'tvdb_api.Show'>
192
+ """
193
+ def __init__(self, config, log = None):
194
+ self.config = config
195
+ if log is not None:
196
+ warnings.warn("the UI's log parameter is deprecated, instead use\n"
197
+ "use import logging; logging.getLogger('ui').info('blah')\n"
198
+ "The self.log attribute will be removed in the next version")
199
+ self.log = logging.getLogger(__name__)
200
+
201
tvdb_api-1.10.tar.gz/tvdb_exceptions.py -> tvdb_api-2.0.tar.gz/tvdb_exceptions.py
Changed
59
1
2
"""
3
4
__author__ = "dbr/Ben"
5
-__version__ = "1.10"
6
+__version__ = "2.0"
7
8
-__all__ = ["tvdb_error", "tvdb_userabort", "tvdb_shownotfound",
9
-"tvdb_seasonnotfound", "tvdb_episodenotfound", "tvdb_attributenotfound"]
10
+import logging
11
12
-class tvdb_exception(Exception):
13
- """Any exception generated by tvdb_api
14
- """
15
- pass
16
+__all__ = ["tvdb_error", "tvdb_userabort", "tvdb_notauthorized", "tvdb_shownotfound",
17
+"tvdb_seasonnotfound", "tvdb_episodenotfound", "tvdb_attributenotfound",
18
+"tvdb_resourcenotfound", "tvdb_invalidlanguage"]
19
20
-class tvdb_error(tvdb_exception):
21
- """An error with thetvdb.com (Cannot connect, for example)
22
- """
23
- pass
24
+logging.getLogger(__name__).warning(
25
+ "tvdb_exceptions module is deprecated - use classes directly from tvdb_api instead")
26
27
-class tvdb_userabort(tvdb_exception):
28
- """User aborted the interactive selection (via
29
- the q command, ^c etc)
30
- """
31
- pass
32
-
33
-class tvdb_shownotfound(tvdb_exception):
34
- """Show cannot be found on thetvdb.com (non-existant show)
35
- """
36
- pass
37
-
38
-class tvdb_seasonnotfound(tvdb_exception):
39
- """Season cannot be found on thetvdb.com
40
- """
41
- pass
42
-
43
-class tvdb_episodenotfound(tvdb_exception):
44
- """Episode cannot be found on thetvdb.com
45
- """
46
- pass
47
-
48
-class tvdb_attributenotfound(tvdb_exception):
49
- """Raised if an episode does not have the requested
50
- attribute (such as a episode name)
51
- """
52
- pass
53
+from tvdb_api import (
54
+ tvdb_error, tvdb_userabort, tvdb_notauthorized, tvdb_shownotfound,
55
+ tvdb_seasonnotfound, tvdb_episodenotfound,
56
+ tvdb_resourcenotfound, tvdb_invalidlanguage,
57
+ tvdb_attributenotfound
58
+)
59
tvdb_api-1.10.tar.gz/tvdb_ui.py -> tvdb_api-2.0.tar.gz/tvdb_ui.py
Changed
169
1
2
#repository:http://github.com/dbr/tvdb_api
3
#license:unlicense (http://unlicense.org/)
4
5
-"""Contains included user interfaces for Tvdb show selection.
6
-
7
-A UI is a callback. A class, it's __init__ function takes two arguments:
8
-
9
-- config, which is the Tvdb config dict, setup in tvdb_api.py
10
-- log, which is Tvdb's logger instance (which uses the logging module). You can
11
-call log.info() log.warning() etc
12
-
13
-It must have a method "selectSeries", this is passed a list of dicts, each dict
14
-contains the the keys "name" (human readable show name), and "sid" (the shows
15
-ID as on thetvdb.com). For example:
16
-
17
-[{'name': u'Lost', 'sid': u'73739'},
18
- {'name': u'Lost Universe', 'sid': u'73181'}]
19
-
20
-The "selectSeries" method must return the appropriate dict, or it can raise
21
-tvdb_userabort (if the selection is aborted), tvdb_shownotfound (if the show
22
-cannot be found).
23
-
24
-A simple example callback, which returns a random series:
25
-
26
->>> import random
27
->>> from tvdb_ui import BaseUI
28
->>> class RandomUI(BaseUI):
29
-... def selectSeries(self, allSeries):
30
-... import random
31
-... return random.choice(allSeries)
32
-
33
-Then to use it..
34
-
35
->>> from tvdb_api import Tvdb
36
->>> t = Tvdb(custom_ui = RandomUI)
37
->>> random_matching_series = t['Lost']
38
->>> type(random_matching_series)
39
-<class 'tvdb_api.Show'>
40
-"""
41
42
__author__ = "dbr/Ben"
43
-__version__ = "1.10"
44
+__version__ = "2.0"
45
46
import sys
47
import logging
48
49
50
from tvdb_exceptions import tvdb_userabort
51
52
+logging.getLogger(__name__).warning(
53
+ "tvdb_ui module is deprecated - use classes directly from tvdb_api instead")
54
55
-IS_PY2 = sys.version_info[0] == 2
56
-
57
-if IS_PY2:
58
- user_input = raw_input
59
-else:
60
- user_input = input
61
-
62
-
63
-def log():
64
- return logging.getLogger(__name__)
65
-
66
-class BaseUI:
67
- """Default non-interactive UI, which auto-selects first results
68
- """
69
- def __init__(self, config, log = None):
70
- self.config = config
71
- if log is not None:
72
- warnings.warn("the UI's log parameter is deprecated, instead use\n"
73
- "use import logging; logging.getLogger('ui').info('blah')\n"
74
- "The self.log attribute will be removed in the next version")
75
- self.log = logging.getLogger(__name__)
76
-
77
- def selectSeries(self, allSeries):
78
- return allSeries[0]
79
-
80
-
81
-class ConsoleUI(BaseUI):
82
- """Interactively allows the user to select a show from a console based UI
83
- """
84
-
85
- def _displaySeries(self, allSeries, limit = 6):
86
- """Helper function, lists series with corresponding ID
87
- """
88
- if limit is not None:
89
- toshow = allSeries[:limit]
90
- else:
91
- toshow = allSeries
92
-
93
- print("TVDB Search Results:")
94
- for i, cshow in enumerate(toshow):
95
- i_show = i + 1 # Start at more human readable number 1 (not 0)
96
- log().debug('Showing allSeries[%s], series %s)' % (i_show, allSeries[i]['seriesname']))
97
- if i == 0:
98
- extra = " (default)"
99
- else:
100
- extra = ""
101
-
102
- output = "%s -> %s [%s] # http://thetvdb.com/?tab=series&id=%s&lid=%s%s" % (
103
- i_show,
104
- cshow['seriesname'],
105
- cshow['language'],
106
- str(cshow['id']),
107
- cshow['lid'],
108
- extra
109
- )
110
- if IS_PY2:
111
- print(output.encode("UTF-8", "ignore"))
112
- else:
113
- print(output)
114
-
115
- def selectSeries(self, allSeries):
116
- self._displaySeries(allSeries)
117
-
118
- if len(allSeries) == 1:
119
- # Single result, return it!
120
- print("Automatically selecting only result")
121
- return allSeries[0]
122
-
123
- if self.config['select_first'] is True:
124
- print("Automatically returning first search result")
125
- return allSeries[0]
126
-
127
- while True: # return breaks this loop
128
- try:
129
- print("Enter choice (first number, return for default, 'all', ? for help):")
130
- ans = user_input()
131
- except KeyboardInterrupt:
132
- raise tvdb_userabort("User aborted (^c keyboard interupt)")
133
- except EOFError:
134
- raise tvdb_userabort("User aborted (EOF received)")
135
-
136
- log().debug('Got choice of: %s' % (ans))
137
- try:
138
- selected_id = int(ans) - 1 # The human entered 1 as first result, not zero
139
- except ValueError: # Input was not number
140
- if len(ans.strip()) == 0:
141
- # Default option
142
- log().debug('Default option, returning first series')
143
- return allSeries[0]
144
- if ans == "q":
145
- log().debug('Got quit command (q)')
146
- raise tvdb_userabort("User aborted ('q' quit command)")
147
- elif ans == "?":
148
- print("## Help")
149
- print("# Enter the number that corresponds to the correct show.")
150
- print("# a - display all results")
151
- print("# all - display all results")
152
- print("# ? - this help")
153
- print("# q - abort tvnamer")
154
- print("# Press return with no input to select first result")
155
- elif ans.lower() in ["a", "all"]:
156
- self._displaySeries(allSeries, limit = None)
157
- else:
158
- log().debug('Unknown keypress %s' % (ans))
159
- else:
160
- log().debug('Trying to return ID: %d' % (selected_id))
161
- try:
162
- return allSeries[selected_id]
163
- except IndexError:
164
- log().debug('Invalid show number entered!')
165
- print("Invalid number (%s) selected!")
166
- self._displaySeries(allSeries)
167
-
168
+from tvdb_api import BaseUI, ConsoleUI
169