Overview
Submit package home:Aloysi...:Multimedia / python-tvdb_api to package Multimedia / python-tvdb_api
python-tvdb_api.changes
Changed
x
1
2
-------------------------------------------------------------------
3
+Fri Apr 21 12:40:16 UTC 2017 - aloisio@gmx.com
4
+
5
+- Update to version 1.10
6
+- Spec cleanup
7
+
8
+-------------------------------------------------------------------
9
Mon Feb 4 14:26:00 UTC 2013 - hvogel@opensuse.org
10
11
- Update to version 1.8.2
12
python-tvdb_api.spec
Changed
77
1
2
+#
3
+# spec file for package python-tvdb_api
4
+#
5
+# Copyright (c) 2017 Packman Team <packman@links2linux.de>
6
+#
7
+# All modifications and additions to the file contributed by third parties
8
+# remain the property of their copyright owners, unless otherwise agreed
9
+# upon. The license for this file, and modifications and additions to the
10
+# file, is the same license as for the pristine package itself (unless the
11
+# license for the pristine package is not an Open Source License, in which
12
+# case the license is the MIT License). An "Open Source License" is a
13
+# license that conforms to the Open Source Definition (Version 1.9)
14
+# published by the Open Source Initiative.
15
+
16
+# Please submit bugfixes or comments via http://bugs.links2linux.org/
17
+#
18
+
19
+
20
%define modname tvdb_api
21
-Name: python-tvdb_api
22
-Summary: Python module to access the API from thetvdb.com
23
-License: GPL
24
-Url: http://pypi.python.org/pypi/tvdb_api
25
-Group: Productivity/Multimedia/Other
26
-Version: 1.8.2
27
-Release: 1
28
-Source0: tvdb_api-%version.tar.bz2
29
-BuildRoot: %{_tmppath}/%{name}-buildroot
30
-BuildRequires: python-devel python-setuptools
31
+Name: python-tvdb_api
32
+Version: 1.10
33
+Release: 0
34
+Summary: Python module to access the API from thetvdb.com
35
+# The UnLicense (https://unlicense.org)
36
+License: SUSE-Permissive
37
+Group: Productivity/Multimedia/Other
38
+Url: https://github.com/dbr/tvdb_api/tree/master
39
+Source0: https://files.pythonhosted.org/packages/source/t/%{modname}/%{modname}-%{version}.tar.gz
40
+BuildRequires: python-devel
41
+BuildRequires: python-setuptools
42
+BuildRoot: %{_tmppath}/%{name}-%{version}-build
43
+BuildArch: noarch
44
%py_requires
45
46
%description
47
-tvdb_api is an easy to use interface to thetvdb.com
48
+tvdb_api is an easy to use interface to thetvdb.com via python
49
50
%prep
51
-%setup -q -n %modname-%version
52
+%setup -q -n %{modname}-%{version}
53
+for file in {tvdb_cache,tvdb_api,tvdb_ui,tvdb_exceptions}
54
+do
55
+ sed -i "1d" $file.py
56
+done
57
58
%build
59
+python setup.py build
60
61
%install
62
-python setup.py install --root=$RPM_BUILD_ROOT --prefix=%_prefix \
63
- --record-rpm=INSTALLED_FILES
64
-
65
-%clean
66
-rm -rf $RPM_BUILD_ROOT
67
+python setup.py install --root=%{buildroot} --prefix=%{_prefix}
68
69
-%files -f INSTALLED_FILES
70
+%files
71
%defattr(-,root,root)
72
+%doc UNLICENSE readme.md
73
+%{python_sitelib}/tvdb_*.py*
74
+%{python_sitelib}/%{modname}-%{version}-py%{python_version}.egg-info
75
76
%changelog
77
tvdb_api-1.8.2.tar.bz2/PKG-INFO -> tvdb_api-1.10.tar.gz/PKG-INFO
Changed
22
1
2
-Metadata-Version: 1.0
3
+Metadata-Version: 1.1
4
Name: tvdb_api
5
-Version: 1.8.2
6
+Version: 1.10
7
Summary: Interface to thetvdb.com
8
Home-page: http://github.com/dbr/tvdb_api/tree/master
9
Author: dbr/Ben
10
11
Classifier: Natural Language :: English
12
Classifier: Operating System :: OS Independent
13
Classifier: Programming Language :: Python
14
+Classifier: Programming Language :: Python :: 2
15
+Classifier: Programming Language :: Python :: 2.6
16
+Classifier: Programming Language :: Python :: 2.7
17
+Classifier: Programming Language :: Python :: 3.3
18
+Classifier: Programming Language :: Python :: 3.4
19
Classifier: Topic :: Multimedia
20
Classifier: Topic :: Utilities
21
Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
tvdb_api-1.8.2.tar.bz2/Rakefile -> tvdb_api-1.10.tar.gz/Rakefile
Changed
14
1
2
end
3
4
desc "Upload current version to PyPi"
5
-task :topypi => :test do
6
+task :topypi 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].to_f
10
+ tvdb_api_version = tvdb_api_version[0][0]
11
12
puts "Build sdist and send tvdb_api v#{tvdb_api_version} to PyPi?"
13
if $stdin.gets.chomp == "y"
14
tvdb_api-1.8.2.tar.bz2/readme.md -> tvdb_api-1.10.tar.gz/readme.md
Changed
35
1
2
3
`tvdb_api` is an easy to use interface to [thetvdb.com][tvdb]
4
5
+It supports Python 2.6, 2.7, 3.3 and 3.4
6
+
7
`tvnamer` has moved to a separate repository: [github.com/dbr/tvnamer][tvnamer] - it is a utility which uses `tvdb_api` to rename files from `some.show.s01e03.blah.abc.avi` to `Some Show - [01x03] - The Episode Name.avi` (which works by getting the episode name from `tvdb_api`)
8
9
[](http://travis-ci.org/dbr/tvdb_api)
10
11
12
There are several exceptions you may catch, these can be imported from `tvdb_api`:
13
14
-- `tvdb_error` - this is raised when there is an error communicating with [www.thetvdb.com][tvdb] (a network error most commonly)
15
+- `tvdb_error` - this is raised when there is an error communicating with [thetvdb.com][tvdb] (a network error most commonly)
16
- `tvdb_userabort` - raised when a user aborts the Select Series dialog (by `ctrl+c`, or entering `q`)
17
- `tvdb_shownotfound` - raised when `t['show name']` cannot find anything
18
- `tvdb_seasonnotfound` - raised when the requested series (`t['show name][99]`) does not exist
19
20
The data is stored in an attribute named `data`, within the Show instance:
21
22
>>> t['scrubs'].data.keys()
23
- ['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', 'firstaired', 'runtime', 'overview']
24
+ ['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']
25
26
Although each element is also accessible via `t['scrubs']` for ease-of-use:
27
28
29
>>> t['scrubs']['actors']
30
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|'
31
32
-[tvdb]: http://www.thetvdb.com
33
+[tvdb]: http://thetvdb.com
34
[tvnamer]: http://github.com/dbr/tvnamer
35
tvdb_api-1.8.2.tar.bz2/setup.py -> tvdb_api-1.10.tar.gz/setup.py
Changed
49
1
2
+import sys
3
from setuptools import setup
4
+
5
+IS_PY2 = sys.version_info[0] == 2
6
+
7
+_requirements = []
8
+if not IS_PY2:
9
+ _requirements.append('requests_cache')
10
+
11
+ # 'requests' is installed as requirement by requests-cache,
12
+ # commented out because it triggers a bug in setuptool:
13
+ # https://bitbucket.org/pypa/setuptools/issue/196/tests_require-pytest-pytest-cov-breaks
14
+
15
+
16
+_modules = ['tvdb_api', 'tvdb_ui', 'tvdb_exceptions']
17
+if IS_PY2:
18
+ _modules.append('tvdb_cache')
19
+
20
+
21
setup(
22
name = 'tvdb_api',
23
-version='1.8.2',
24
+version='1.10',
25
26
author='dbr/Ben',
27
description='Interface to thetvdb.com',
28
29
u'Stole a Badge'
30
""",
31
32
-py_modules = ['tvdb_api', 'tvdb_ui', 'tvdb_exceptions', 'tvdb_cache'],
33
+py_modules = _modules,
34
+install_requires = _requirements,
35
36
classifiers=[
37
"Intended Audience :: Developers",
38
"Natural Language :: English",
39
"Operating System :: OS Independent",
40
"Programming Language :: Python",
41
+ "Programming Language :: Python :: 2",
42
+ "Programming Language :: Python :: 2.6",
43
+ "Programming Language :: Python :: 2.7",
44
+ "Programming Language :: Python :: 3.3",
45
+ "Programming Language :: Python :: 3.4",
46
"Topic :: Multimedia",
47
"Topic :: Utilities",
48
"Topic :: Software Development :: Libraries :: Python Modules",
49
tvdb_api-1.8.2.tar.bz2/tests/test_tvdb_api.py -> tvdb_api-1.10.tar.gz/tests/test_tvdb_api.py
Changed
137
1
2
from tvdb_api import (tvdb_shownotfound, tvdb_seasonnotfound,
3
tvdb_episodenotfound, tvdb_attributenotfound)
4
5
+
6
+IS_PY2 = sys.version_info[0] == 2
7
+
8
+
9
class test_tvdb_basic(unittest.TestCase):
10
# Used to store the cached instance of Tvdb()
11
t = None
12
13
show
14
)
15
16
+ def test_no_season(self):
17
+ show = self.t['Katekyo Hitman Reborn']
18
+ print(tvdb_api)
19
+ print(show[1][1])
20
21
class test_tvdb_errors(unittest.TestCase):
22
# Used to store the cached instance of Tvdb()
23
24
"""Check valid_languages is up-to-date (compared to languages.xml)
25
"""
26
et = self.t._getetsrc(
27
- "http://www.thetvdb.com/api/%s/languages.xml" % (
28
+ "http://thetvdb.com/api/%s/languages.xml" % (
29
self.t.config['apikey']
30
)
31
)
32
33
self.fail("Expected ValueError from setting cache to float")
34
35
def test_custom_urlopener(self):
36
+ if not IS_PY2:
37
+ raise unittest.SkipTest("cannot supply custom opener in Python 3 because requests is used")
38
+
39
class UsedCustomOpener(Exception):
40
pass
41
42
import urllib2
43
class TestOpener(urllib2.BaseHandler):
44
def default_open(self, request):
45
- print request.get_method()
46
+ print(request.get_method())
47
raise UsedCustomOpener("Something")
48
49
custom_opener = urllib2.build_opener(TestOpener())
50
51
else:
52
self.fail("Did not use custom opener")
53
54
+ def test_custom_request_session(self):
55
+ if IS_PY2:
56
+ return
57
+ from requests import Session as OriginalSession
58
+ class Used(Exception):
59
+ pass
60
+ class CustomCacheForTest(OriginalSession):
61
+ call_count = 0
62
+ def request(self, *args, **kwargs):
63
+ raise Used("Hurray")
64
+ c = CustomCacheForTest()
65
+ t = tvdb_api.Tvdb(cache = c)
66
+ try:
67
+ t['scrubs']
68
+ except Used:
69
+ pass
70
+ else:
71
+ self.fail("Did not use custom session")
72
+
73
+
74
class test_tvdb_by_id(unittest.TestCase):
75
t = None
76
def setUp(self):
77
78
self.assertEquals(self.t['My Name Is Earl'][1][4]['episodename'], 'Faked His Own Death')
79
80
81
+class test_tvdb_show_ordering(unittest.TestCase):
82
+ # Used to store the cached instance of Tvdb()
83
+ t_dvd = None
84
+ t_air = None
85
+
86
+ def setUp(self):
87
+ if self.t_dvd is None:
88
+ self.t_dvd = tvdb_api.Tvdb(cache = True, useZip = True, dvdorder=True)
89
+
90
+ if self.t_air is None:
91
+ self.t_air = tvdb_api.Tvdb(cache = True, useZip = True)
92
+
93
+ def test_ordering(self):
94
+ """Test Tvdb.search method
95
+ """
96
+ self.assertEquals(u'The Train Job', self.t_air['Firefly'][1][1]['episodename'])
97
+ self.assertEquals(u'Serenity', self.t_dvd['Firefly'][1][1]['episodename'])
98
+
99
+ self.assertEquals(u'The Cat & the Claw (Part 1)', self.t_air['Batman The Animated Series'][1][1]['episodename'])
100
+ self.assertEquals(u'On Leather Wings', self.t_dvd['Batman The Animated Series'][1][1]['episodename'])
101
+
102
+class test_tvdb_show_search(unittest.TestCase):
103
+ # Used to store the cached instance of Tvdb()
104
+ t = None
105
+
106
+ def setUp(self):
107
+ if self.t is None:
108
+ self.__class__.t = tvdb_api.Tvdb(cache = True, useZip = True)
109
+
110
+ def test_search(self):
111
+ """Test Tvdb.search method
112
+ """
113
+ results = self.t.search("my name is earl")
114
+ all_ids = [x['seriesid'] for x in results]
115
+ self.assertTrue('75397' in all_ids)
116
+
117
+
118
+class test_tvdb_alt_names(unittest.TestCase):
119
+ t = None
120
+ def setUp(self):
121
+ if self.t is None:
122
+ self.__class__.t = tvdb_api.Tvdb(cache = True, actors = True)
123
+
124
+ def test_1(self):
125
+ """Tests basic access of series name alias
126
+ """
127
+ results = self.t.search("Don't Trust the B---- in Apartment 23")
128
+ series = results[0]
129
+ self.assertTrue(
130
+ 'Apartment 23' in series['aliasnames']
131
+ )
132
+
133
+
134
if __name__ == '__main__':
135
runner = unittest.TextTestRunner(verbosity = 2)
136
unittest.main(testRunner = runner)
137
tvdb_api-1.8.2.tar.bz2/tvdb_api.egg-info/PKG-INFO -> tvdb_api-1.10.tar.gz/tvdb_api.egg-info/PKG-INFO
Changed
22
1
2
-Metadata-Version: 1.0
3
+Metadata-Version: 1.1
4
Name: tvdb-api
5
-Version: 1.8.2
6
+Version: 1.10
7
Summary: Interface to thetvdb.com
8
Home-page: http://github.com/dbr/tvdb_api/tree/master
9
Author: dbr/Ben
10
11
Classifier: Natural Language :: English
12
Classifier: Operating System :: OS Independent
13
Classifier: Programming Language :: Python
14
+Classifier: Programming Language :: Python :: 2
15
+Classifier: Programming Language :: Python :: 2.6
16
+Classifier: Programming Language :: Python :: 2.7
17
+Classifier: Programming Language :: Python :: 3.3
18
+Classifier: Programming Language :: Python :: 3.4
19
Classifier: Topic :: Multimedia
20
Classifier: Topic :: Utilities
21
Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
tvdb_api-1.8.2.tar.bz2/tvdb_api.py -> tvdb_api-1.10.tar.gz/tvdb_api.py
Changed
593
1
2
#repository:http://github.com/dbr/tvdb_api
3
#license:unlicense (http://unlicense.org/)
4
5
-"""Simple-to-use Python interface to The TVDB's API (www.thetvdb.com)
6
+"""Simple-to-use Python interface to The TVDB's API (thetvdb.com)
7
8
Example usage:
9
10
11
u'Cabin Fever'
12
"""
13
__author__ = "dbr/Ben"
14
-__version__ = "1.8.2"
15
+__version__ = "1.10"
16
+
17
+import sys
18
+
19
+IS_PY2 = sys.version_info[0] == 2
20
21
import os
22
import time
23
-import urllib
24
-import urllib2
25
+if IS_PY2:
26
+ import urllib
27
+ import urllib2
28
+ from tvdb_cache import CacheHandler
29
+ from urllib import quote as url_quote
30
+else:
31
+ import requests
32
+ from urllib.parse import quote as url_quote
33
import getpass
34
-import StringIO
35
import tempfile
36
import warnings
37
import logging
38
39
gzip = None
40
41
42
-from tvdb_cache import CacheHandler
43
+if IS_PY2:
44
+ int_types = (int, long)
45
+ text_type = unicode
46
+else:
47
+ int_types = int
48
+ text_type = str
49
+
50
51
from tvdb_ui import BaseUI, ConsoleUI
52
from tvdb_exceptions import (tvdb_error, tvdb_userabort, tvdb_shownotfound,
53
54
55
#keep only the 100th latest results
56
if time.time() - self._lastgc > 20:
57
- tbd = self._stack[:-100]
58
- i = 0
59
- for o in tbd:
60
+ for o in self._stack[:-100]:
61
del self[o]
62
- del self._stack[i]
63
- i += 1
64
+ self._stack = self._stack[-100:]
65
+
66
+ self._lastgc = time.time()
67
68
- _lastgc = time.time()
69
- del tbd
70
-
71
super(ShowContainer, self).__setitem__(key, value)
72
73
74
75
searchresult = cur_season.search(term = term, key = key)
76
if len(searchresult) != 0:
77
results.extend(searchresult)
78
- #end for cur_season
79
+
80
return results
81
82
83
84
if term == None:
85
raise TypeError("must supply string to search for (contents)")
86
87
- term = unicode(term).lower()
88
+ term = text_type(term).lower()
89
for cur_key, cur_value in self.items():
90
- cur_key, cur_value = unicode(cur_key).lower(), unicode(cur_value).lower()
91
+ cur_key, cur_value = text_type(cur_key).lower(), text_type(cur_value).lower()
92
if key is not None and cur_key != key:
93
# Do not search this key
94
continue
95
- if cur_value.find( unicode(term).lower() ) > -1:
96
+ if cur_value.find( text_type(term).lower() ) > -1:
97
return self
98
- #end if cur_value.find()
99
- #end for cur_key, cur_value
100
101
102
class Actors(list):
103
104
search_all_languages = False,
105
apikey = None,
106
forceConnect=False,
107
- useZip=False):
108
+ useZip=False,
109
+ dvdorder=False):
110
111
"""interactive (True/False):
112
When True, uses built-in console UI is used to select the correct show.
113
114
an arbitrary Python object, which is used as a urllib2
115
opener, which should be created by urllib2.build_opener
116
117
+ In Python 3, True/False enable or disable default
118
+ caching. Passing string specified directory where to store
119
+ the "tvdb.sqlite3" cache file. Also a custom
120
+ requests.Session instance can be passed (e.g maybe a
121
+ customised instance of requests_cache.CachedSession)
122
+
123
banners (True/False):
124
Retrieves the banners for a show. These are accessed
125
via the _banners key of a Show(), for example:
126
127
And only the main language xml is used, the actor and banner xml are lost.
128
"""
129
130
+
131
global lastTimeout
132
133
# if we're given a lastTimeout that is less than 1 min just give up
134
135
136
self.config['useZip'] = useZip
137
138
+ self.config['dvdorder'] = dvdorder
139
140
- if cache is True:
141
- self.config['cache_enabled'] = True
142
- self.config['cache_location'] = self._getTempDir()
143
- self.urlopener = urllib2.build_opener(
144
- CacheHandler(self.config['cache_location'])
145
- )
146
+ if not IS_PY2: # FIXME: Allow using requests in Python 2?
147
+ import requests_cache
148
+ if cache is True:
149
+ self.session = requests_cache.CachedSession(
150
+ expire_after=21600, # 6 hours
151
+ backend='sqlite',
152
+ cache_name=self._getTempDir(),
153
+ )
154
+ self.config['cache_enabled'] = True
155
+ elif cache is False:
156
+ self.session = requests.Session()
157
+ self.config['cache_enabled'] = False
158
+ elif isinstance(cache, text_type):
159
+ # Specified cache path
160
+ self.session = requests_cache.CachedSession(
161
+ expire_after=21600, # 6 hours
162
+ backend='sqlite',
163
+ cache_name=os.path.join(cache, "tvdb_api"),
164
+ )
165
+ else:
166
+ self.session = cache
167
+ try:
168
+ self.session.get
169
+ except AttributeError:
170
+ raise ValueError("cache argument must be True/False, string as cache path or requests.Session-type object (e.g from requests_cache.CachedSession)")
171
+ else:
172
+ # For backwards compatibility in Python 2.x
173
+ if cache is True:
174
+ self.config['cache_enabled'] = True
175
+ self.config['cache_location'] = self._getTempDir()
176
+ self.urlopener = urllib2.build_opener(
177
+ CacheHandler(self.config['cache_location'])
178
+ )
179
180
- elif cache is False:
181
- self.config['cache_enabled'] = False
182
- self.urlopener = urllib2.build_opener() # default opener with no caching
183
+ elif cache is False:
184
+ self.config['cache_enabled'] = False
185
+ self.urlopener = urllib2.build_opener() # default opener with no caching
186
187
- elif isinstance(cache, basestring):
188
- self.config['cache_enabled'] = True
189
- self.config['cache_location'] = cache
190
- self.urlopener = urllib2.build_opener(
191
- CacheHandler(self.config['cache_location'])
192
- )
193
+ elif isinstance(cache, basestring):
194
+ self.config['cache_enabled'] = True
195
+ self.config['cache_location'] = cache
196
+ self.urlopener = urllib2.build_opener(
197
+ CacheHandler(self.config['cache_location'])
198
+ )
199
200
- elif isinstance(cache, urllib2.OpenerDirector):
201
- # If passed something from urllib2.build_opener, use that
202
- log().debug("Using %r as urlopener" % cache)
203
- self.config['cache_enabled'] = True
204
- self.urlopener = cache
205
+ elif isinstance(cache, urllib2.OpenerDirector):
206
+ # If passed something from urllib2.build_opener, use that
207
+ log().debug("Using %r as urlopener" % cache)
208
+ self.config['cache_enabled'] = True
209
+ self.urlopener = cache
210
211
- else:
212
- raise ValueError("Invalid value for Cache %r (type was %s)" % (cache, type(cache)))
213
+ else:
214
+ raise ValueError("Invalid value for Cache %r (type was %s)" % (cache, type(cache)))
215
216
self.config['banners_enabled'] = banners
217
self.config['actors_enabled'] = actors
218
219
logging.basicConfig(level=logging.DEBUG)
220
221
222
- # List of language from http://www.thetvdb.com/api/0629B785CE550C8D/languages.xml
223
+ # List of language from http://thetvdb.com/api/0629B785CE550C8D/languages.xml
224
# Hard-coded here as it is realtively static, and saves another HTTP request, as
225
# recommended on http://thetvdb.com/wiki/index.php/API:languages.xml
226
self.config['valid_languages'] = [
227
228
229
# The following url_ configs are based of the
230
# http://thetvdb.com/wiki/index.php/Programmers_API
231
- self.config['base_url'] = "http://www.thetvdb.com"
232
+ self.config['base_url'] = "http://thetvdb.com"
233
234
if self.config['search_all_languages']:
235
self.config['url_getSeries'] = u"%(base_url)s/api/GetSeries.php?seriesname=%%s&language=all" % self.config
236
237
self.config['url_seriesBanner'] = u"%(base_url)s/api/%(apikey)s/series/%%s/banners.xml" % self.config
238
self.config['url_artworkPrefix'] = u"%(base_url)s/banners/%%s" % self.config
239
240
- #end __init__
241
-
242
def _getTempDir(self):
243
"""Returns the [system temp dir]/tvdb_api-u501 (or
244
tvdb_api-myuser)
245
246
uid = "u%d" % (os.getuid())
247
else:
248
# For Windows
249
- uid = getpass.getuser()
250
+ try:
251
+ uid = getpass.getuser()
252
+ except ImportError:
253
+ return os.path.join(tempfile.gettempdir(), "tvdb_api")
254
255
return os.path.join(tempfile.gettempdir(), "tvdb_api-%s" % (uid))
256
257
def _loadUrl(self, url, recache = False, language=None):
258
- global lastTimeout
259
- try:
260
- log().debug("Retrieving URL %s" % url)
261
- resp = self.urlopener.open(url)
262
- if 'x-local-cache' in resp.headers:
263
- log().debug("URL %s was cached in %s" % (
264
- url,
265
- resp.headers['x-local-cache'])
266
- )
267
- if recache:
268
- log().debug("Attempting to recache %s" % url)
269
- resp.recache()
270
- except (IOError, urllib2.URLError), errormsg:
271
- if not str(errormsg).startswith('HTTP Error'):
272
- lastTimeout = datetime.datetime.now()
273
- raise tvdb_error("Could not connect to server: %s" % (errormsg))
274
- #end try
275
-
276
- # handle gzipped content,
277
- # http://dbr.lighthouseapp.com/projects/13342/tickets/72-gzipped-data-patch
278
- if 'gzip' in resp.headers.get("Content-Encoding", ''):
279
- if gzip:
280
- stream = StringIO.StringIO(resp.read())
281
- gz = gzip.GzipFile(fileobj=stream)
282
- return gz.read()
283
-
284
- raise tvdb_error("Received gzip data from thetvdb.com, but could not correctly handle it")
285
+ if not IS_PY2:
286
+ # Python 3: return content at URL as bytes
287
+ resp = self.session.get(url)
288
+ if 'application/zip' in resp.headers.get("Content-Type", ''):
289
+ try:
290
+ # TODO: The zip contains actors.xml and banners.xml, which are currently ignored [GH-20]
291
+ log().debug("We recived a zip file unpacking now ...")
292
+ from io import BytesIO
293
+ myzipfile = zipfile.ZipFile(BytesIO(resp.content))
294
+ return myzipfile.read('%s.xml' % language)
295
+ except zipfile.BadZipfile:
296
+ self.session.cache.delete_url(url)
297
+ raise tvdb_error("Bad zip file received from thetvdb.com, could not read it")
298
+ return resp.content
299
300
- if 'application/zip' in resp.headers.get("Content-Type", ''):
301
+ else:
302
+ global lastTimeout
303
try:
304
- # TODO: The zip contains actors.xml and banners.xml, which are currently ignored [GH-20]
305
- log().debug("We recived a zip file unpacking now ...")
306
- zipdata = StringIO.StringIO()
307
- zipdata.write(resp.read())
308
- myzipfile = zipfile.ZipFile(zipdata)
309
- return myzipfile.read('%s.xml' % language)
310
- except zipfile.BadZipfile:
311
+ log().debug("Retrieving URL %s" % url)
312
+ resp = self.urlopener.open(url)
313
if 'x-local-cache' in resp.headers:
314
- resp.delete_cache()
315
- raise tvdb_error("Bad zip file received from thetvdb.com, could not read it")
316
-
317
- return resp.read()
318
+ log().debug("URL %s was cached in %s" % (
319
+ url,
320
+ resp.headers['x-local-cache'])
321
+ )
322
+ if recache:
323
+ log().debug("Attempting to recache %s" % url)
324
+ resp.recache()
325
+ except (IOError, urllib2.URLError) as errormsg:
326
+ if not str(errormsg).startswith('HTTP Error'):
327
+ lastTimeout = datetime.datetime.now()
328
+ raise tvdb_error("Could not connect to server: %s" % (errormsg))
329
+
330
+
331
+ # handle gzipped content,
332
+ # http://dbr.lighthouseapp.com/projects/13342/tickets/72-gzipped-data-patch
333
+ if 'gzip' in resp.headers.get("Content-Encoding", ''):
334
+ if gzip:
335
+ from StringIO import StringIO
336
+ stream = StringIO(resp.read())
337
+ gz = gzip.GzipFile(fileobj=stream)
338
+ return gz.read()
339
+
340
+ raise tvdb_error("Received gzip data from thetvdb.com, but could not correctly handle it")
341
+
342
+ if 'application/zip' in resp.headers.get("Content-Type", ''):
343
+ try:
344
+ # TODO: The zip contains actors.xml and banners.xml, which are currently ignored [GH-20]
345
+ log().debug("We recived a zip file unpacking now ...")
346
+ from StringIO import StringIO
347
+ zipdata = StringIO()
348
+ zipdata.write(resp.read())
349
+ myzipfile = zipfile.ZipFile(zipdata)
350
+ return myzipfile.read('%s.xml' % language)
351
+ except zipfile.BadZipfile:
352
+ if 'x-local-cache' in resp.headers:
353
+ resp.delete_cache()
354
+ raise tvdb_error("Bad zip file received from thetvdb.com, could not read it")
355
+
356
+ return resp.read()
357
358
def _getetsrc(self, url, language=None):
359
"""Loads a URL using caching, returns an ElementTree of the source
360
"""
361
src = self._loadUrl(url, language=language)
362
+
363
+
364
+ # TVDB doesn't sanitize \r (CR) from user input in some fields,
365
+ # remove it to avoid errors. Change from SickBeard, from will14m
366
+ if not IS_PY2:
367
+ # Remove trailing \r byte
368
+ src = src.replace(b"\r", b"")
369
+ else:
370
+ src = src.rstrip("\r") # FIXME: this seems wrong
371
+
372
try:
373
- # TVDB doesn't sanitize \r (CR) from user input in some fields,
374
- # remove it to avoid errors. Change from SickBeard, from will14m
375
- return ElementTree.fromstring(src.rstrip("\r"))
376
+ return ElementTree.fromstring(src)
377
except SyntaxError:
378
src = self._loadUrl(url, recache=True, language=language)
379
try:
380
- return ElementTree.fromstring(src.rstrip("\r"))
381
- except SyntaxError, exceptionmsg:
382
+ return ElementTree.fromstring(src)
383
+ except SyntaxError as exceptionmsg:
384
errormsg = "There was an error with the XML retrieved from thetvdb.com:\n%s" % (
385
exceptionmsg
386
)
387
388
errormsg += "\nIf this does not resolve the issue, please try again later. If the error persists, report a bug on"
389
errormsg += "\nhttp://dbr.lighthouseapp.com/projects/13342-tvdb_api/overview\n"
390
raise tvdb_error(errormsg)
391
- #end _getetsrc
392
393
def _setItem(self, sid, seas, ep, attrib, value):
394
"""Creates a new episode, creating Show(), Season() and
395
396
if ep not in self.shows[sid][seas]:
397
self.shows[sid][seas][ep] = Episode(season = self.shows[sid][seas])
398
self.shows[sid][seas][ep][attrib] = value
399
- #end _set_item
400
401
def _setShowData(self, sid, key, value):
402
"""Sets self.shows[sid] to a new Show instance, or sets the data
403
404
data = data.replace(u"&", u"&")
405
data = data.strip()
406
return data
407
- #end _cleanData
408
409
- def _getSeries(self, series):
410
- """This searches TheTVDB.com for the series name,
411
- If a custom_ui UI is configured, it uses this to select the correct
412
- series. If not, and interactive == True, ConsoleUI is used, if not
413
- BaseUI is used to select the first result.
414
+ def search(self, series):
415
+ """This searches TheTVDB.com for the series name
416
+ and returns the result list
417
"""
418
- series = urllib.quote(series.encode("utf-8"))
419
+ series = url_quote(series.encode("utf-8"))
420
log().debug("Searching for show %s" % series)
421
seriesEt = self._getetsrc(self.config['url_getSeries'] % (series))
422
allSeries = []
423
424
result = dict((k.tag.lower(), k.text) for k in series.getchildren())
425
result['id'] = int(result['id'])
426
result['lid'] = self.config['langabbv_to_id'][result['language']]
427
+ if 'aliasnames' in result:
428
+ result['aliasnames'] = result['aliasnames'].split("|")
429
log().debug('Found series %(seriesname)s' % result)
430
allSeries.append(result)
431
- #end for series
432
+
433
+ return allSeries
434
+
435
+ def _getSeries(self, series):
436
+ """This searches TheTVDB.com for the series name,
437
+ If a custom_ui UI is configured, it uses this to select the correct
438
+ series. If not, and interactive == True, ConsoleUI is used, if not
439
+ BaseUI is used to select the first result.
440
+ """
441
+ allSeries = self.search(series)
442
443
if len(allSeries) == 0:
444
log().debug('Series result returned zero')
445
446
else:
447
log().debug('Interactively selecting show using ConsoleUI')
448
ui = ConsoleUI(config = self.config)
449
- #end if config['interactive]
450
- #end if custom_ui != None
451
452
return ui.selectSeries(allSeries)
453
454
- #end _getSeries
455
-
456
def _parseBanners(self, sid):
457
"""Parses banners XML, from
458
- http://www.thetvdb.com/api/[APIKEY]/series/[SERIES ID]/banners.xml
459
+ http://thetvdb.com/api/[APIKEY]/series/[SERIES ID]/banners.xml
460
461
Banners are retrieved using t['show name]['_banners'], for example:
462
463
464
>>> t['scrubs']['_banners'].keys()
465
['fanart', 'poster', 'series', 'season']
466
>>> t['scrubs']['_banners']['poster']['680x1000']['35308']['_bannerpath']
467
- u'http://www.thetvdb.com/banners/posters/76156-2.jpg'
468
+ u'http://thetvdb.com/banners/posters/76156-2.jpg'
469
>>>
470
471
Any key starting with an underscore has been processed (not the raw
472
473
tag, value = tag.lower(), value.lower()
474
banners[btype][btype2][bid][tag] = value
475
476
- for k, v in banners[btype][btype2][bid].items():
477
+ for k, v in list(banners[btype][btype2][bid].items()):
478
if k.endswith("path"):
479
new_key = "_%s" % (k)
480
log().debug("Transforming %s to %s" % (k, new_key))
481
482
483
def _parseActors(self, sid):
484
"""Parsers actors XML, from
485
- http://www.thetvdb.com/api/[APIKEY]/series/[SERIES ID]/actors.xml
486
+ http://thetvdb.com/api/[APIKEY]/series/[SERIES ID]/actors.xml
487
488
Actors are retrieved using t['show name]['_actors'], for example:
489
490
491
>>> actors[0]['name']
492
u'Zach Braff'
493
>>> actors[0]['image']
494
- u'http://www.thetvdb.com/banners/actors/43640.jpg'
495
+ u'http://thetvdb.com/banners/actors/43640.jpg'
496
497
Any key starting with an underscore has been processed (not the raw
498
data from the XML)
499
500
value = self._cleanData(value)
501
502
self._setShowData(sid, tag, value)
503
- #end for series
504
505
# Parse banners
506
if self.config['banners_enabled']:
507
508
epsEt = self._getetsrc( url, language=language)
509
510
for cur_ep in epsEt.findall("Episode"):
511
- seas_no = int(cur_ep.find('SeasonNumber').text)
512
- ep_no = int(cur_ep.find('EpisodeNumber').text)
513
+
514
+ if self.config['dvdorder']:
515
+ log().debug('Using DVD ordering.')
516
+ use_dvd = cur_ep.find('DVD_season').text != None and cur_ep.find('DVD_episodenumber').text != None
517
+ else:
518
+ use_dvd = False
519
+
520
+ if use_dvd:
521
+ elem_seasnum, elem_epno = cur_ep.find('DVD_season'), cur_ep.find('DVD_episodenumber')
522
+ else:
523
+ elem_seasnum, elem_epno = cur_ep.find('SeasonNumber'), cur_ep.find('EpisodeNumber')
524
+
525
+ if elem_seasnum is None or elem_epno is None:
526
+ log().warning("An episode has incomplete season/episode number (season: %r, episode: %r)" % (
527
+ elem_seasnum, elem_epno))
528
+ log().debug(
529
+ " ".join(
530
+ "%r is %r" % (child.tag, child.text) for child in cur_ep.getchildren()))
531
+ # TODO: Should this happen?
532
+ continue # Skip to next episode
533
+
534
+ # float() is because https://github.com/dbr/tvnamer/issues/95 - should probably be fixed in TVDB data
535
+ seas_no = int(float(elem_seasnum.text))
536
+ ep_no = int(float(elem_epno.text))
537
+
538
for cur_item in cur_ep.getchildren():
539
tag = cur_item.tag.lower()
540
value = cur_item.text
541
542
else:
543
value = self._cleanData(value)
544
self._setItem(sid, seas_no, ep_no, tag, value)
545
- #end for cur_ep
546
- #end _geEps
547
548
def _nameToSid(self, name):
549
"""Takes show name, returns the correct series ID (if the show has
550
551
552
self.corrections[name] = sid
553
self._getShowData(selected_series['id'], selected_series['language'])
554
- #end if name in self.corrections
555
+
556
return sid
557
- #end _nameToSid
558
559
def __getitem__(self, key):
560
"""Handles tvdb_instance['seriesname'] calls.
561
The dict index should be the show id
562
"""
563
- if isinstance(key, (int, long)):
564
+ if isinstance(key, int_types):
565
# Item is integer, treat as show id
566
if key not in self.shows:
567
self._getShowData(key, self.config['language'])
568
569
sid = self._nameToSid(key)
570
log().debug('Got series id %s' % (sid))
571
return self.shows[sid]
572
- #end __getitem__
573
574
def __repr__(self):
575
return str(self.shows)
576
- #end __repr__
577
-#end Tvdb
578
+
579
580
def main():
581
"""Simple example of using tvdb_api - it just
582
583
logging.basicConfig(level=logging.DEBUG)
584
585
tvdb_instance = Tvdb(interactive=True, cache=False)
586
- print tvdb_instance['Lost']['seriesname']
587
- print tvdb_instance['Lost'][1][4]['episodename']
588
+ print(tvdb_instance['Lost']['seriesname'])
589
+ print(tvdb_instance['Lost'][1][4]['episodename'])
590
591
if __name__ == '__main__':
592
main()
593
tvdb_api-1.8.2.tar.bz2/tvdb_cache.py -> tvdb_api-1.10.tar.gz/tvdb_cache.py
Changed
18
1
2
from __future__ import with_statement
3
4
__author__ = "dbr/Ben"
5
-__version__ = "1.8.2"
6
+__version__ = "1.10"
7
8
import os
9
import time
10
11
)
12
else:
13
set_cache_header = True
14
- #end if x-cache in response
15
16
return CachedResponse(
17
self.cache_location,
18
tvdb_api-1.8.2.tar.bz2/tvdb_exceptions.py -> tvdb_api-1.10.tar.gz/tvdb_exceptions.py
Changed
40
1
2
"""
3
4
__author__ = "dbr/Ben"
5
-__version__ = "1.8.2"
6
+__version__ = "1.10"
7
8
__all__ = ["tvdb_error", "tvdb_userabort", "tvdb_shownotfound",
9
"tvdb_seasonnotfound", "tvdb_episodenotfound", "tvdb_attributenotfound"]
10
11
pass
12
13
class tvdb_error(tvdb_exception):
14
- """An error with www.thetvdb.com (Cannot connect, for example)
15
+ """An error with thetvdb.com (Cannot connect, for example)
16
"""
17
pass
18
19
20
pass
21
22
class tvdb_shownotfound(tvdb_exception):
23
- """Show cannot be found on www.thetvdb.com (non-existant show)
24
+ """Show cannot be found on thetvdb.com (non-existant show)
25
"""
26
pass
27
28
class tvdb_seasonnotfound(tvdb_exception):
29
- """Season cannot be found on www.thetvdb.com
30
+ """Season cannot be found on thetvdb.com
31
"""
32
pass
33
34
class tvdb_episodenotfound(tvdb_exception):
35
- """Episode cannot be found on www.thetvdb.com
36
+ """Episode cannot be found on thetvdb.com
37
"""
38
pass
39
40
tvdb_api-1.8.2.tar.bz2/tvdb_ui.py -> tvdb_api-1.10.tar.gz/tvdb_ui.py
Changed
109
1
2
"""
3
4
__author__ = "dbr/Ben"
5
-__version__ = "1.8.2"
6
+__version__ = "1.10"
7
8
+import sys
9
import logging
10
import warnings
11
12
from tvdb_exceptions import tvdb_userabort
13
14
+
15
+IS_PY2 = sys.version_info[0] == 2
16
+
17
+if IS_PY2:
18
+ user_input = raw_input
19
+else:
20
+ user_input = input
21
+
22
+
23
def log():
24
return logging.getLogger(__name__)
25
26
27
else:
28
toshow = allSeries
29
30
- print "TVDB Search Results:"
31
+ print("TVDB Search Results:")
32
for i, cshow in enumerate(toshow):
33
i_show = i + 1 # Start at more human readable number 1 (not 0)
34
log().debug('Showing allSeries[%s], series %s)' % (i_show, allSeries[i]['seriesname']))
35
36
else:
37
extra = ""
38
39
- print "%s -> %s [%s] # http://thetvdb.com/?tab=series&id=%s&lid=%s%s" % (
40
+ output = "%s -> %s [%s] # http://thetvdb.com/?tab=series&id=%s&lid=%s%s" % (
41
i_show,
42
- cshow['seriesname'].encode("UTF-8", "ignore"),
43
- cshow['language'].encode("UTF-8", "ignore"),
44
+ cshow['seriesname'],
45
+ cshow['language'],
46
str(cshow['id']),
47
cshow['lid'],
48
extra
49
)
50
+ if IS_PY2:
51
+ print(output.encode("UTF-8", "ignore"))
52
+ else:
53
+ print(output)
54
55
def selectSeries(self, allSeries):
56
self._displaySeries(allSeries)
57
58
if len(allSeries) == 1:
59
# Single result, return it!
60
- print "Automatically selecting only result"
61
+ print("Automatically selecting only result")
62
return allSeries[0]
63
64
if self.config['select_first'] is True:
65
- print "Automatically returning first search result"
66
+ print("Automatically returning first search result")
67
return allSeries[0]
68
69
while True: # return breaks this loop
70
try:
71
- print "Enter choice (first number, return for default, 'all', ? for help):"
72
- ans = raw_input()
73
+ print("Enter choice (first number, return for default, 'all', ? for help):")
74
+ ans = user_input()
75
except KeyboardInterrupt:
76
raise tvdb_userabort("User aborted (^c keyboard interupt)")
77
except EOFError:
78
79
log().debug('Got quit command (q)')
80
raise tvdb_userabort("User aborted ('q' quit command)")
81
elif ans == "?":
82
- print "## Help"
83
- print "# Enter the number that corresponds to the correct show."
84
- print "# a - display all results"
85
- print "# all - display all results"
86
- print "# ? - this help"
87
- print "# q - abort tvnamer"
88
- print "# Press return with no input to select first result"
89
+ print("## Help")
90
+ print("# Enter the number that corresponds to the correct show.")
91
+ print("# a - display all results")
92
+ print("# all - display all results")
93
+ print("# ? - this help")
94
+ print("# q - abort tvnamer")
95
+ print("# Press return with no input to select first result")
96
elif ans.lower() in ["a", "all"]:
97
self._displaySeries(allSeries, limit = None)
98
else:
99
100
return allSeries[selected_id]
101
except IndexError:
102
log().debug('Invalid show number entered!')
103
- print "Invalid number (%s) selected!"
104
+ print("Invalid number (%s) selected!")
105
self._displaySeries(allSeries)
106
- #end try
107
- #end while not valid_input
108
109
Refresh
No build results available
Refresh
No rpmlint results available
Login required, please
login
or
signup
in order to comment