]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/client175_0.7-convert-to-python3-using-2to3-converter.patch
core160: apply ssh config, start/stop IPSec and set need_reboot flag
[ipfire-2.x.git] / src / patches / client175_0.7-convert-to-python3-using-2to3-converter.patch
1 diff -Naur client175_0.7-original/BeautifulSoup.py client175_0.7/BeautifulSoup.py
2 --- client175_0.7-original/BeautifulSoup.py 2010-05-14 12:57:39.000000000 +0200
3 +++ client175_0.7/BeautifulSoup.py 2021-08-03 14:39:30.213509172 +0200
4 @@ -76,7 +76,7 @@
5 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE, DAMMIT.
6
7 """
8 -from __future__ import generators
9 +
10
11 __author__ = "Leonard Richardson (leonardr@segfault.org)"
12 __version__ = "3.0.8.1"
13 @@ -85,12 +85,12 @@
14
15 from sgmllib import SGMLParser, SGMLParseError
16 import codecs
17 -import markupbase
18 +import _markupbase
19 import types
20 import re
21 import sgmllib
22 try:
23 - from htmlentitydefs import name2codepoint
24 + from html.entities import name2codepoint
25 except ImportError:
26 name2codepoint = {}
27 try:
28 @@ -100,7 +100,7 @@
29
30 #These hacks make Beautiful Soup able to parse XML with namespaces
31 sgmllib.tagfind = re.compile('[a-zA-Z][-_.:a-zA-Z0-9]*')
32 -markupbase._declname_match = re.compile(r'[a-zA-Z][-_.:a-zA-Z0-9]*\s*').match
33 +_markupbase._declname_match = re.compile(r'[a-zA-Z][-_.:a-zA-Z0-9]*\s*').match
34
35 DEFAULT_OUTPUT_ENCODING = "utf-8"
36
37 @@ -162,7 +162,7 @@
38 #this element (and any children) hadn't been parsed. Connect
39 #the two.
40 lastChild = self._lastRecursiveChild()
41 - nextElement = lastChild.next
42 + nextElement = lastChild.__next__
43
44 if self.previous:
45 self.previous.next = nextElement
46 @@ -187,7 +187,7 @@
47 return lastChild
48
49 def insert(self, position, newChild):
50 - if isinstance(newChild, basestring) \
51 + if isinstance(newChild, str) \
52 and not isinstance(newChild, NavigableString):
53 newChild = NavigableString(newChild)
54
55 @@ -241,7 +241,7 @@
56 newChild.nextSibling.previousSibling = newChild
57 newChildsLastElement.next = nextChild
58
59 - if newChildsLastElement.next:
60 + if newChildsLastElement.__next__:
61 newChildsLastElement.next.previous = newChildsLastElement
62 self.contents.insert(position, newChild)
63
64 @@ -342,7 +342,7 @@
65 return [element for element in generator()
66 if isinstance(element, Tag)]
67 # findAll*('tag-name')
68 - elif isinstance(name, basestring):
69 + elif isinstance(name, str):
70 return [element for element in generator()
71 if isinstance(element, Tag) and
72 element.name == name]
73 @@ -355,7 +355,7 @@
74 g = generator()
75 while True:
76 try:
77 - i = g.next()
78 + i = next(g)
79 except StopIteration:
80 break
81 if i:
82 @@ -371,7 +371,7 @@
83 def nextGenerator(self):
84 i = self
85 while i is not None:
86 - i = i.next
87 + i = i.__next__
88 yield i
89
90 def nextSiblingGenerator(self):
91 @@ -406,22 +406,22 @@
92 def toEncoding(self, s, encoding=None):
93 """Encodes an object to a string in some encoding, or to Unicode.
94 ."""
95 - if isinstance(s, unicode):
96 + if isinstance(s, str):
97 if encoding:
98 s = s.encode(encoding)
99 elif isinstance(s, str):
100 if encoding:
101 s = s.encode(encoding)
102 else:
103 - s = unicode(s)
104 + s = str(s)
105 else:
106 if encoding:
107 s = self.toEncoding(str(s), encoding)
108 else:
109 - s = unicode(s)
110 + s = str(s)
111 return s
112
113 -class NavigableString(unicode, PageElement):
114 +class NavigableString(str, PageElement):
115
116 def __new__(cls, value):
117 """Create a new NavigableString.
118 @@ -431,9 +431,9 @@
119 passed in to the superclass's __new__ or the superclass won't know
120 how to handle non-ASCII characters.
121 """
122 - if isinstance(value, unicode):
123 - return unicode.__new__(cls, value)
124 - return unicode.__new__(cls, value, DEFAULT_OUTPUT_ENCODING)
125 + if isinstance(value, str):
126 + return str.__new__(cls, value)
127 + return str.__new__(cls, value, DEFAULT_OUTPUT_ENCODING)
128
129 def __getnewargs__(self):
130 return (NavigableString.__str__(self),)
131 @@ -445,7 +445,7 @@
132 if attr == 'string':
133 return self
134 else:
135 - raise AttributeError, "'%s' object has no attribute '%s'" % (self.__class__.__name__, attr)
136 + raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, attr))
137
138 def __unicode__(self):
139 return str(self).decode(DEFAULT_OUTPUT_ENCODING)
140 @@ -483,7 +483,7 @@
141 def _invert(h):
142 "Cheap function to invert a hash."
143 i = {}
144 - for k,v in h.items():
145 + for k,v in list(h.items()):
146 i[v] = k
147 return i
148
149 @@ -502,23 +502,23 @@
150 escaped."""
151 x = match.group(1)
152 if self.convertHTMLEntities and x in name2codepoint:
153 - return unichr(name2codepoint[x])
154 + return chr(name2codepoint[x])
155 elif x in self.XML_ENTITIES_TO_SPECIAL_CHARS:
156 if self.convertXMLEntities:
157 return self.XML_ENTITIES_TO_SPECIAL_CHARS[x]
158 else:
159 - return u'&%s;' % x
160 + return '&%s;' % x
161 elif len(x) > 0 and x[0] == '#':
162 # Handle numeric entities
163 if len(x) > 1 and x[1] == 'x':
164 - return unichr(int(x[2:], 16))
165 + return chr(int(x[2:], 16))
166 else:
167 - return unichr(int(x[1:]))
168 + return chr(int(x[1:]))
169
170 elif self.escapeUnrecognizedEntities:
171 - return u'&%s;' % x
172 + return '&%s;' % x
173 else:
174 - return u'&%s;' % x
175 + return '&%s;' % x
176
177 def __init__(self, parser, name, attrs=None, parent=None,
178 previous=None):
179 @@ -541,11 +541,11 @@
180 self.escapeUnrecognizedEntities = parser.escapeUnrecognizedEntities
181
182 # Convert any HTML, XML, or numeric entities in the attribute values.
183 - convert = lambda(k, val): (k,
184 + convert = lambda k_val: (k_val[0],
185 re.sub("&(#\d+|#x[0-9a-fA-F]+|\w+);",
186 self._convertEntities,
187 - val))
188 - self.attrs = map(convert, self.attrs)
189 + k_val[1]))
190 + self.attrs = list(map(convert, self.attrs))
191
192 def getString(self):
193 if (len(self.contents) == 1
194 @@ -559,16 +559,16 @@
195
196 string = property(getString, setString)
197
198 - def getText(self, separator=u""):
199 + def getText(self, separator=""):
200 if not len(self.contents):
201 - return u""
202 - stopNode = self._lastRecursiveChild().next
203 + return ""
204 + stopNode = self._lastRecursiveChild().__next__
205 strings = []
206 current = self.contents[0]
207 while current is not stopNode:
208 if isinstance(current, NavigableString):
209 strings.append(current.strip())
210 - current = current.next
211 + current = current.__next__
212 return separator.join(strings)
213
214 text = property(getText)
215 @@ -591,7 +591,7 @@
216 raise ValueError("Tag.index: element not in tag")
217
218 def has_key(self, key):
219 - return self._getAttrMap().has_key(key)
220 + return key in self._getAttrMap()
221
222 def __getitem__(self, key):
223 """tag[key] returns the value of the 'key' attribute for the tag,
224 @@ -609,7 +609,7 @@
225 def __contains__(self, x):
226 return x in self.contents
227
228 - def __nonzero__(self):
229 + def __bool__(self):
230 "A tag is non-None even if it has no contents."
231 return True
232
233 @@ -635,14 +635,14 @@
234 #We don't break because bad HTML can define the same
235 #attribute multiple times.
236 self._getAttrMap()
237 - if self.attrMap.has_key(key):
238 + if key in self.attrMap:
239 del self.attrMap[key]
240
241 def __call__(self, *args, **kwargs):
242 """Calling a tag like a function is the same as calling its
243 findAll() method. Eg. tag('a') returns a list of all the A tags
244 found within this tag."""
245 - return apply(self.findAll, args, kwargs)
246 + return self.findAll(*args, **kwargs)
247
248 def __getattr__(self, tag):
249 #print "Getattr %s.%s" % (self.__class__, tag)
250 @@ -650,7 +650,7 @@
251 return self.find(tag[:-3])
252 elif tag.find('__') != 0:
253 return self.find(tag)
254 - raise AttributeError, "'%s' object has no attribute '%s'" % (self.__class__, tag)
255 + raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__, tag))
256
257 def __eq__(self, other):
258 """Returns true iff this tag has the same name, the same attributes,
259 @@ -703,7 +703,7 @@
260 if self.attrs:
261 for key, val in self.attrs:
262 fmt = '%s="%s"'
263 - if isinstance(val, basestring):
264 + if isinstance(val, str):
265 if self.containsSubstitutions and '%SOUP-ENCODING%' in val:
266 val = self.substituteEncoding(val, encoding)
267
268 @@ -780,7 +780,7 @@
269 return
270 current = self.contents[0]
271 while current is not None:
272 - next = current.next
273 + next = current.__next__
274 if isinstance(current, Tag):
275 del current.contents[:]
276 current.parent = None
277 @@ -873,11 +873,11 @@
278 def recursiveChildGenerator(self):
279 if not len(self.contents):
280 raise StopIteration
281 - stopNode = self._lastRecursiveChild().next
282 + stopNode = self._lastRecursiveChild().__next__
283 current = self.contents[0]
284 while current is not stopNode:
285 yield current
286 - current = current.next
287 + current = current.__next__
288
289
290 # Next, a couple classes to represent queries and their results.
291 @@ -887,7 +887,7 @@
292
293 def __init__(self, name=None, attrs={}, text=None, **kwargs):
294 self.name = name
295 - if isinstance(attrs, basestring):
296 + if isinstance(attrs, str):
297 kwargs['class'] = _match_css_class(attrs)
298 attrs = None
299 if kwargs:
300 @@ -923,7 +923,7 @@
301 else:
302 match = True
303 markupAttrMap = None
304 - for attr, matchAgainst in self.attrs.items():
305 + for attr, matchAgainst in list(self.attrs.items()):
306 if not markupAttrMap:
307 if hasattr(markupAttrs, 'get'):
308 markupAttrMap = markupAttrs
309 @@ -961,12 +961,12 @@
310 found = self.searchTag(markup)
311 # If it's text, make sure the text matches.
312 elif isinstance(markup, NavigableString) or \
313 - isinstance(markup, basestring):
314 + isinstance(markup, str):
315 if self._matches(markup, self.text):
316 found = markup
317 else:
318 - raise Exception, "I don't know how to match against a %s" \
319 - % markup.__class__
320 + raise Exception("I don't know how to match against a %s" \
321 + % markup.__class__)
322 return found
323
324 def _matches(self, markup, matchAgainst):
325 @@ -981,8 +981,8 @@
326 #other ways of matching match the tag name as a string.
327 if isinstance(markup, Tag):
328 markup = markup.name
329 - if markup and not isinstance(markup, basestring):
330 - markup = unicode(markup)
331 + if markup and not isinstance(markup, str):
332 + markup = str(markup)
333 #Now we know that chunk is either a string, or None.
334 if hasattr(matchAgainst, 'match'):
335 # It's a regexp object.
336 @@ -990,10 +990,10 @@
337 elif hasattr(matchAgainst, '__iter__'): # list-like
338 result = markup in matchAgainst
339 elif hasattr(matchAgainst, 'items'):
340 - result = markup.has_key(matchAgainst)
341 - elif matchAgainst and isinstance(markup, basestring):
342 - if isinstance(markup, unicode):
343 - matchAgainst = unicode(matchAgainst)
344 + result = matchAgainst in markup
345 + elif matchAgainst and isinstance(markup, str):
346 + if isinstance(markup, str):
347 + matchAgainst = str(matchAgainst)
348 else:
349 matchAgainst = str(matchAgainst)
350
351 @@ -1018,7 +1018,7 @@
352 for portion in args:
353 if hasattr(portion, 'items'):
354 #It's a map. Merge it.
355 - for k,v in portion.items():
356 + for k,v in list(portion.items()):
357 built[k] = v
358 elif hasattr(portion, '__iter__'): # is a list
359 #It's a list. Map each item to the default.
360 @@ -1061,7 +1061,7 @@
361 lambda x: '<!' + x.group(1) + '>')
362 ]
363
364 - ROOT_TAG_NAME = u'[document]'
365 + ROOT_TAG_NAME = '[document]'
366
367 HTML_ENTITIES = "html"
368 XML_ENTITIES = "xml"
369 @@ -1157,14 +1157,14 @@
370 def _feed(self, inDocumentEncoding=None, isHTML=False):
371 # Convert the document to Unicode.
372 markup = self.markup
373 - if isinstance(markup, unicode):
374 + if isinstance(markup, str):
375 if not hasattr(self, 'originalEncoding'):
376 self.originalEncoding = None
377 else:
378 dammit = UnicodeDammit\
379 (markup, [self.fromEncoding, inDocumentEncoding],
380 smartQuotesTo=self.smartQuotesTo, isHTML=isHTML)
381 - markup = dammit.unicode
382 + markup = dammit.str
383 self.originalEncoding = dammit.originalEncoding
384 self.declaredHTMLEncoding = dammit.declaredHTMLEncoding
385 if markup:
386 @@ -1203,8 +1203,8 @@
387 def isSelfClosingTag(self, name):
388 """Returns true iff the given string is the name of a
389 self-closing tag according to this parser."""
390 - return self.SELF_CLOSING_TAGS.has_key(name) \
391 - or self.instanceSelfClosingTags.has_key(name)
392 + return name in self.SELF_CLOSING_TAGS \
393 + or name in self.instanceSelfClosingTags
394
395 def reset(self):
396 Tag.__init__(self, self, self.ROOT_TAG_NAME)
397 @@ -1233,7 +1233,7 @@
398
399 def endData(self, containerClass=NavigableString):
400 if self.currentData:
401 - currentData = u''.join(self.currentData)
402 + currentData = ''.join(self.currentData)
403 if (currentData.translate(self.STRIP_ASCII_SPACES) == '' and
404 not set([tag.name for tag in self.tagStack]).intersection(
405 self.PRESERVE_WHITESPACE_TAGS)):
406 @@ -1296,7 +1296,7 @@
407
408 nestingResetTriggers = self.NESTABLE_TAGS.get(name)
409 isNestable = nestingResetTriggers != None
410 - isResetNesting = self.RESET_NESTING_TAGS.has_key(name)
411 + isResetNesting = name in self.RESET_NESTING_TAGS
412 popTo = None
413 inclusive = True
414 for i in range(len(self.tagStack)-1, 0, -1):
415 @@ -1309,7 +1309,7 @@
416 if (nestingResetTriggers is not None
417 and p.name in nestingResetTriggers) \
418 or (nestingResetTriggers is None and isResetNesting
419 - and self.RESET_NESTING_TAGS.has_key(p.name)):
420 + and p.name in self.RESET_NESTING_TAGS):
421
422 #If we encounter one of the nesting reset triggers
423 #peculiar to this tag, or we encounter another tag
424 @@ -1380,7 +1380,7 @@
425 object, possibly one with a %SOUP-ENCODING% slot into which an
426 encoding will be plugged later."""
427 if text[:3] == "xml":
428 - text = u"xml version='1.0' encoding='%SOUP-ENCODING%'"
429 + text = "xml version='1.0' encoding='%SOUP-ENCODING%'"
430 self._toStringSubclass(text, ProcessingInstruction)
431
432 def handle_comment(self, text):
433 @@ -1390,7 +1390,7 @@
434 def handle_charref(self, ref):
435 "Handle character references as data."
436 if self.convertEntities:
437 - data = unichr(int(ref))
438 + data = chr(int(ref))
439 else:
440 data = '&#%s;' % ref
441 self.handle_data(data)
442 @@ -1402,7 +1402,7 @@
443 data = None
444 if self.convertHTMLEntities:
445 try:
446 - data = unichr(name2codepoint[ref])
447 + data = chr(name2codepoint[ref])
448 except KeyError:
449 pass
450
451 @@ -1511,7 +1511,7 @@
452 BeautifulStoneSoup before writing your own subclass."""
453
454 def __init__(self, *args, **kwargs):
455 - if not kwargs.has_key('smartQuotesTo'):
456 + if 'smartQuotesTo' not in kwargs:
457 kwargs['smartQuotesTo'] = self.HTML_ENTITIES
458 kwargs['isHTML'] = True
459 BeautifulStoneSoup.__init__(self, *args, **kwargs)
460 @@ -1694,7 +1694,7 @@
461 parent._getAttrMap()
462 if (isinstance(tag, Tag) and len(tag.contents) == 1 and
463 isinstance(tag.contents[0], NavigableString) and
464 - not parent.attrMap.has_key(tag.name)):
465 + tag.name not in parent.attrMap):
466 parent[tag.name] = tag.contents[0]
467 BeautifulStoneSoup.popTag(self)
468
469 @@ -1768,9 +1768,9 @@
470 self._detectEncoding(markup, isHTML)
471 self.smartQuotesTo = smartQuotesTo
472 self.triedEncodings = []
473 - if markup == '' or isinstance(markup, unicode):
474 + if markup == '' or isinstance(markup, str):
475 self.originalEncoding = None
476 - self.unicode = unicode(markup)
477 + self.str = str(markup)
478 return
479
480 u = None
481 @@ -1783,7 +1783,7 @@
482 if u: break
483
484 # If no luck and we have auto-detection library, try that:
485 - if not u and chardet and not isinstance(self.markup, unicode):
486 + if not u and chardet and not isinstance(self.markup, str):
487 u = self._convertFrom(chardet.detect(self.markup)['encoding'])
488
489 # As a last resort, try utf-8 and windows-1252:
490 @@ -1792,7 +1792,7 @@
491 u = self._convertFrom(proposed_encoding)
492 if u: break
493
494 - self.unicode = u
495 + self.str = u
496 if not u: self.originalEncoding = None
497
498 def _subMSChar(self, orig):
499 @@ -1819,7 +1819,7 @@
500 "iso-8859-1",
501 "iso-8859-2"):
502 markup = re.compile("([\x80-\x9f])").sub \
503 - (lambda(x): self._subMSChar(x.group(1)),
504 + (lambda x: self._subMSChar(x.group(1)),
505 markup)
506
507 try:
508 @@ -1827,7 +1827,7 @@
509 u = self._toUnicode(markup, proposed)
510 self.markup = u
511 self.originalEncoding = proposed
512 - except Exception, e:
513 + except Exception as e:
514 # print "That didn't work!"
515 # print e
516 return None
517 @@ -1856,7 +1856,7 @@
518 elif data[:4] == '\xff\xfe\x00\x00':
519 encoding = 'utf-32le'
520 data = data[4:]
521 - newdata = unicode(data, encoding)
522 + newdata = str(data, encoding)
523 return newdata
524
525 def _detectEncoding(self, xml_data, isHTML=False):
526 @@ -1869,41 +1869,41 @@
527 elif xml_data[:4] == '\x00\x3c\x00\x3f':
528 # UTF-16BE
529 sniffed_xml_encoding = 'utf-16be'
530 - xml_data = unicode(xml_data, 'utf-16be').encode('utf-8')
531 + xml_data = str(xml_data, 'utf-16be').encode('utf-8')
532 elif (len(xml_data) >= 4) and (xml_data[:2] == '\xfe\xff') \
533 and (xml_data[2:4] != '\x00\x00'):
534 # UTF-16BE with BOM
535 sniffed_xml_encoding = 'utf-16be'
536 - xml_data = unicode(xml_data[2:], 'utf-16be').encode('utf-8')
537 + xml_data = str(xml_data[2:], 'utf-16be').encode('utf-8')
538 elif xml_data[:4] == '\x3c\x00\x3f\x00':
539 # UTF-16LE
540 sniffed_xml_encoding = 'utf-16le'
541 - xml_data = unicode(xml_data, 'utf-16le').encode('utf-8')
542 + xml_data = str(xml_data, 'utf-16le').encode('utf-8')
543 elif (len(xml_data) >= 4) and (xml_data[:2] == '\xff\xfe') and \
544 (xml_data[2:4] != '\x00\x00'):
545 # UTF-16LE with BOM
546 sniffed_xml_encoding = 'utf-16le'
547 - xml_data = unicode(xml_data[2:], 'utf-16le').encode('utf-8')
548 + xml_data = str(xml_data[2:], 'utf-16le').encode('utf-8')
549 elif xml_data[:4] == '\x00\x00\x00\x3c':
550 # UTF-32BE
551 sniffed_xml_encoding = 'utf-32be'
552 - xml_data = unicode(xml_data, 'utf-32be').encode('utf-8')
553 + xml_data = str(xml_data, 'utf-32be').encode('utf-8')
554 elif xml_data[:4] == '\x3c\x00\x00\x00':
555 # UTF-32LE
556 sniffed_xml_encoding = 'utf-32le'
557 - xml_data = unicode(xml_data, 'utf-32le').encode('utf-8')
558 + xml_data = str(xml_data, 'utf-32le').encode('utf-8')
559 elif xml_data[:4] == '\x00\x00\xfe\xff':
560 # UTF-32BE with BOM
561 sniffed_xml_encoding = 'utf-32be'
562 - xml_data = unicode(xml_data[4:], 'utf-32be').encode('utf-8')
563 + xml_data = str(xml_data[4:], 'utf-32be').encode('utf-8')
564 elif xml_data[:4] == '\xff\xfe\x00\x00':
565 # UTF-32LE with BOM
566 sniffed_xml_encoding = 'utf-32le'
567 - xml_data = unicode(xml_data[4:], 'utf-32le').encode('utf-8')
568 + xml_data = str(xml_data[4:], 'utf-32le').encode('utf-8')
569 elif xml_data[:3] == '\xef\xbb\xbf':
570 # UTF-8 with BOM
571 sniffed_xml_encoding = 'utf-8'
572 - xml_data = unicode(xml_data[3:], 'utf-8').encode('utf-8')
573 + xml_data = str(xml_data[3:], 'utf-8').encode('utf-8')
574 else:
575 sniffed_xml_encoding = 'ascii'
576 pass
577 @@ -1966,7 +1966,7 @@
578 250,251,252,253,254,255)
579 import string
580 c.EBCDIC_TO_ASCII_MAP = string.maketrans( \
581 - ''.join(map(chr, range(256))), ''.join(map(chr, emap)))
582 + ''.join(map(chr, list(range(256)))), ''.join(map(chr, emap)))
583 return s.translate(c.EBCDIC_TO_ASCII_MAP)
584
585 MS_CHARS = { '\x80' : ('euro', '20AC'),
586 @@ -2009,4 +2009,4 @@
587 if __name__ == '__main__':
588 import sys
589 soup = BeautifulSoup(sys.stdin)
590 - print soup.prettify()
591 + print(soup.prettify())
592 diff -Naur client175_0.7-original/cherrypy/cherryd client175_0.7/cherrypy/cherryd
593 --- client175_0.7-original/cherrypy/cherryd 2010-04-20 13:10:10.000000000 +0200
594 +++ client175_0.7/cherrypy/cherryd 2021-08-03 15:37:40.098963967 +0200
595 @@ -12,7 +12,7 @@
596 """Subscribe all engine plugins and start the engine."""
597 sys.path = [''] + sys.path
598 for i in imports or []:
599 - exec "import %s" % i
600 + exec("import %s" % i)
601
602 for c in configfiles or []:
603 cherrypy.config.update(c)
604 diff -Naur client175_0.7-original/cherrypy/_cpcgifs.py client175_0.7/cherrypy/_cpcgifs.py
605 --- client175_0.7-original/cherrypy/_cpcgifs.py 2010-04-20 13:10:10.000000000 +0200
606 +++ client175_0.7/cherrypy/_cpcgifs.py 2021-08-03 14:41:19.199896214 +0200
607 @@ -6,7 +6,7 @@
608 def __init__(self, *args, **kwds):
609 try:
610 cgi.FieldStorage.__init__(self, *args, **kwds)
611 - except ValueError, ex:
612 + except ValueError as ex:
613 if str(ex) == 'Maximum content length exceeded':
614 raise cherrypy.HTTPError(status=413)
615 else:
616 diff -Naur client175_0.7-original/cherrypy/_cpchecker.py client175_0.7/cherrypy/_cpchecker.py
617 --- client175_0.7-original/cherrypy/_cpchecker.py 2010-04-20 13:10:10.000000000 +0200
618 +++ client175_0.7/cherrypy/_cpchecker.py 2021-08-03 14:41:30.971721551 +0200
619 @@ -47,7 +47,7 @@
620 global_config_contained_paths = False
621
622 def check_skipped_app_config(self):
623 - for sn, app in cherrypy.tree.apps.iteritems():
624 + for sn, app in cherrypy.tree.apps.items():
625 if not isinstance(app, cherrypy.Application):
626 continue
627 if not app.config:
628 @@ -64,7 +64,7 @@
629 def check_static_paths(self):
630 # Use the dummy Request object in the main thread.
631 request = cherrypy.request
632 - for sn, app in cherrypy.tree.apps.iteritems():
633 + for sn, app in cherrypy.tree.apps.items():
634 if not isinstance(app, cherrypy.Application):
635 continue
636 request.app = app
637 @@ -130,9 +130,9 @@
638
639 def _compat(self, config):
640 """Process config and warn on each obsolete or deprecated entry."""
641 - for section, conf in config.iteritems():
642 + for section, conf in config.items():
643 if isinstance(conf, dict):
644 - for k, v in conf.iteritems():
645 + for k, v in conf.items():
646 if k in self.obsolete:
647 warnings.warn("%r is obsolete. Use %r instead.\n"
648 "section: [%s]" %
649 @@ -152,7 +152,7 @@
650 def check_compatibility(self):
651 """Process config and warn on each obsolete or deprecated entry."""
652 self._compat(cherrypy.config)
653 - for sn, app in cherrypy.tree.apps.iteritems():
654 + for sn, app in cherrypy.tree.apps.items():
655 if not isinstance(app, cherrypy.Application):
656 continue
657 self._compat(app.config)
658 @@ -164,16 +164,16 @@
659
660 def _known_ns(self, app):
661 ns = ["wsgi"]
662 - ns.extend(app.toolboxes.keys())
663 - ns.extend(app.namespaces.keys())
664 - ns.extend(app.request_class.namespaces.keys())
665 - ns.extend(cherrypy.config.namespaces.keys())
666 + ns.extend(list(app.toolboxes.keys()))
667 + ns.extend(list(app.namespaces.keys()))
668 + ns.extend(list(app.request_class.namespaces.keys()))
669 + ns.extend(list(cherrypy.config.namespaces.keys()))
670 ns += self.extra_config_namespaces
671
672 - for section, conf in app.config.iteritems():
673 + for section, conf in app.config.items():
674 is_path_section = section.startswith("/")
675 if is_path_section and isinstance(conf, dict):
676 - for k, v in conf.iteritems():
677 + for k, v in conf.items():
678 atoms = k.split(".")
679 if len(atoms) > 1:
680 if atoms[0] not in ns:
681 @@ -197,7 +197,7 @@
682
683 def check_config_namespaces(self):
684 """Process config and warn on each unknown config namespace."""
685 - for sn, app in cherrypy.tree.apps.iteritems():
686 + for sn, app in cherrypy.tree.apps.items():
687 if not isinstance(app, cherrypy.Application):
688 continue
689 self._known_ns(app)
690 @@ -210,8 +210,8 @@
691 known_config_types = {}
692
693 def _populate_known_types(self):
694 - import __builtin__
695 - builtins = [x for x in vars(__builtin__).values()
696 + import builtins
697 + builtins = [x for x in list(vars(__builtin__).values())
698 if type(x) is type(str)]
699
700 def traverse(obj, namespace):
701 @@ -230,9 +230,9 @@
702 msg = ("The config entry %r in section %r is of type %r, "
703 "which does not match the expected type %r.")
704
705 - for section, conf in config.iteritems():
706 + for section, conf in config.items():
707 if isinstance(conf, dict):
708 - for k, v in conf.iteritems():
709 + for k, v in conf.items():
710 if v is not None:
711 expected_type = self.known_config_types.get(k, None)
712 vtype = type(v)
713 @@ -251,7 +251,7 @@
714 def check_config_types(self):
715 """Assert that config values are of the same type as default values."""
716 self._known_types(cherrypy.config)
717 - for sn, app in cherrypy.tree.apps.iteritems():
718 + for sn, app in cherrypy.tree.apps.items():
719 if not isinstance(app, cherrypy.Application):
720 continue
721 self._known_types(app.config)
722 @@ -261,7 +261,7 @@
723
724 def check_localhost(self):
725 """Warn if any socket_host is 'localhost'. See #711."""
726 - for k, v in cherrypy.config.iteritems():
727 + for k, v in cherrypy.config.items():
728 if k == 'server.socket_host' and v == 'localhost':
729 warnings.warn("The use of 'localhost' as a socket host can "
730 "cause problems on newer systems, since 'localhost' can "
731 diff -Naur client175_0.7-original/cherrypy/_cpconfig.py client175_0.7/cherrypy/_cpconfig.py
732 --- client175_0.7-original/cherrypy/_cpconfig.py 2010-04-20 13:10:10.000000000 +0200
733 +++ client175_0.7/cherrypy/_cpconfig.py 2021-08-03 14:41:39.459596077 +0200
734 @@ -93,7 +93,7 @@
735 style) context manager.
736 """
737
738 -import ConfigParser
739 +import configparser
740 try:
741 set
742 except NameError:
743 @@ -138,7 +138,7 @@
744
745 def as_dict(config):
746 """Return a dict from 'config' whether it is a dict, file, or filename."""
747 - if isinstance(config, basestring):
748 + if isinstance(config, str):
749 config = _Parser().dict_from_file(config)
750 elif hasattr(config, 'read'):
751 config = _Parser().dict_from_file(config)
752 @@ -150,11 +150,11 @@
753 If the given config is a filename, it will be appended to
754 the list of files to monitor for "autoreload" changes.
755 """
756 - if isinstance(other, basestring):
757 + if isinstance(other, str):
758 cherrypy.engine.autoreload.files.add(other)
759
760 # Load other into base
761 - for section, value_map in as_dict(other).iteritems():
762 + for section, value_map in as_dict(other).items():
763 base.setdefault(section, {}).update(value_map)
764
765
766 @@ -196,14 +196,14 @@
767 # with handler as callable:
768 # for k, v in ns_confs.get(ns, {}).iteritems():
769 # callable(k, v)
770 - for ns, handler in self.iteritems():
771 + for ns, handler in self.items():
772 exit = getattr(handler, "__exit__", None)
773 if exit:
774 callable = handler.__enter__()
775 no_exc = True
776 try:
777 try:
778 - for k, v in ns_confs.get(ns, {}).iteritems():
779 + for k, v in ns_confs.get(ns, {}).items():
780 callable(k, v)
781 except:
782 # The exceptional case is handled here
783 @@ -218,7 +218,7 @@
784 if no_exc and exit:
785 exit(None, None, None)
786 else:
787 - for k, v in ns_confs.get(ns, {}).iteritems():
788 + for k, v in ns_confs.get(ns, {}).items():
789 handler(k, v)
790
791 def __repr__(self):
792 @@ -257,7 +257,7 @@
793
794 def update(self, config):
795 """Update self from a dict, file or filename."""
796 - if isinstance(config, basestring):
797 + if isinstance(config, str):
798 # Filename
799 cherrypy.engine.autoreload.files.add(config)
800 config = _Parser().dict_from_file(config)
801 @@ -333,7 +333,7 @@
802 Config.namespaces["tree"] = _tree_namespace_handler
803
804
805 -class _Parser(ConfigParser.ConfigParser):
806 +class _Parser(configparser.ConfigParser):
807 """Sub-class of ConfigParser that keeps the case of options and that raises
808 an exception if the file cannot be read.
809 """
810 @@ -342,7 +342,7 @@
811 return optionstr
812
813 def read(self, filenames):
814 - if isinstance(filenames, basestring):
815 + if isinstance(filenames, str):
816 filenames = [filenames]
817 for filename in filenames:
818 # try:
819 @@ -367,7 +367,7 @@
820 value = self.get(section, option, raw, vars)
821 try:
822 value = unrepr(value)
823 - except Exception, x:
824 + except Exception as x:
825 msg = ("Config error in section: %r, option: %r, "
826 "value: %r. Config values must be valid Python." %
827 (section, option, value))
828 diff -Naur client175_0.7-original/cherrypy/_cpdispatch.py client175_0.7/cherrypy/_cpdispatch.py
829 --- client175_0.7-original/cherrypy/_cpdispatch.py 2010-04-20 13:10:10.000000000 +0200
830 +++ client175_0.7/cherrypy/_cpdispatch.py 2021-08-03 14:41:48.627460479 +0200
831 @@ -23,7 +23,7 @@
832 def __call__(self):
833 try:
834 return self.callable(*self.args, **self.kwargs)
835 - except TypeError, x:
836 + except TypeError as x:
837 test_callable_spec(self.callable, self.args, self.kwargs)
838 raise
839
840 @@ -62,7 +62,7 @@
841 except IndexError:
842 vararg_usage += 1
843
844 - for key in callable_kwargs.keys():
845 + for key in list(callable_kwargs.keys()):
846 try:
847 arg_usage[key] += 1
848 except KeyError:
849 @@ -76,7 +76,7 @@
850
851 missing_args = []
852 multiple_args = []
853 - for key, usage in arg_usage.iteritems():
854 + for key, usage in arg_usage.items():
855 if usage == 0:
856 missing_args.append(key)
857 elif usage > 1:
858 @@ -258,7 +258,7 @@
859
860 # Try successive objects (reverse order)
861 num_candidates = len(object_trail) - 1
862 - for i in xrange(num_candidates, -1, -1):
863 + for i in range(num_candidates, -1, -1):
864
865 name, candidate, nodeconf, curpath = object_trail[i]
866 if candidate is None:
867 diff -Naur client175_0.7-original/cherrypy/_cperror.py client175_0.7/cherrypy/_cperror.py
868 --- client175_0.7-original/cherrypy/_cperror.py 2010-04-20 13:10:10.000000000 +0200
869 +++ client175_0.7/cherrypy/_cperror.py 2021-08-03 14:41:56.939337474 +0200
870 @@ -3,7 +3,7 @@
871 from cgi import escape as _escape
872 from sys import exc_info as _exc_info
873 from traceback import format_exception as _format_exception
874 -from urlparse import urljoin as _urljoin
875 +from urllib.parse import urljoin as _urljoin
876 from cherrypy.lib import http as _http
877
878
879 @@ -57,7 +57,7 @@
880 import cherrypy
881 request = cherrypy.request
882
883 - if isinstance(urls, basestring):
884 + if isinstance(urls, str):
885 urls = [urls]
886
887 abs_urls = []
888 @@ -161,7 +161,7 @@
889 for key in ["Accept-Ranges", "Age", "ETag", "Location", "Retry-After",
890 "Vary", "Content-Encoding", "Content-Length", "Expires",
891 "Content-Location", "Content-MD5", "Last-Modified"]:
892 - if respheaders.has_key(key):
893 + if key in respheaders:
894 del respheaders[key]
895
896 if status != 416:
897 @@ -171,7 +171,7 @@
898 # specifies the current length of the selected resource.
899 # A response with status code 206 (Partial Content) MUST NOT
900 # include a Content-Range field with a byte-range- resp-spec of "*".
901 - if respheaders.has_key("Content-Range"):
902 + if "Content-Range" in respheaders:
903 del respheaders["Content-Range"]
904
905
906 @@ -277,7 +277,7 @@
907
908 try:
909 code, reason, message = _http.valid_status(status)
910 - except ValueError, x:
911 + except ValueError as x:
912 raise cherrypy.HTTPError(500, x.args[0])
913
914 # We can't use setdefault here, because some
915 @@ -291,7 +291,7 @@
916 if kwargs.get('version') is None:
917 kwargs['version'] = cherrypy.__version__
918
919 - for k, v in kwargs.iteritems():
920 + for k, v in kwargs.items():
921 if v is None:
922 kwargs[k] = ""
923 else:
924 diff -Naur client175_0.7-original/cherrypy/_cplogging.py client175_0.7/cherrypy/_cplogging.py
925 --- client175_0.7-original/cherrypy/_cplogging.py 2010-04-20 13:10:10.000000000 +0200
926 +++ client175_0.7/cherrypy/_cplogging.py 2021-08-03 14:42:04.739222052 +0200
927 @@ -88,8 +88,8 @@
928 'f': inheaders.get('Referer', ''),
929 'a': inheaders.get('User-Agent', ''),
930 }
931 - for k, v in atoms.items():
932 - if isinstance(v, unicode):
933 + for k, v in list(atoms.items()):
934 + if isinstance(v, str):
935 v = v.encode('utf8')
936 elif not isinstance(v, str):
937 v = str(v)
938 diff -Naur client175_0.7-original/cherrypy/_cpmodpy.py client175_0.7/cherrypy/_cpmodpy.py
939 --- client175_0.7-original/cherrypy/_cpmodpy.py 2010-04-20 13:10:10.000000000 +0200
940 +++ client175_0.7/cherrypy/_cpmodpy.py 2021-08-03 14:42:11.807117510 +0200
941 @@ -56,7 +56,7 @@
942 """
943
944 import logging
945 -import StringIO
946 +import io
947
948 import cherrypy
949 from cherrypy._cperror import format_exc, bare_error
950 @@ -183,7 +183,7 @@
951 path = req.uri
952 qs = req.args or ""
953 reqproto = req.protocol
954 - headers = req.headers_in.items()
955 + headers = list(req.headers_in.items())
956 rfile = _ReadOnlyRequest(req)
957 prev = None
958
959 @@ -202,7 +202,7 @@
960 try:
961 request.run(method, path, qs, reqproto, headers, rfile)
962 break
963 - except cherrypy.InternalRedirect, ir:
964 + except cherrypy.InternalRedirect as ir:
965 app.release_serving()
966 prev = request
967
968 @@ -220,7 +220,7 @@
969 method = "GET"
970 path = ir.path
971 qs = ir.query_string
972 - rfile = StringIO.StringIO()
973 + rfile = io.StringIO()
974
975 send_response(req, response.status, response.header_list,
976 response.body, response.stream)
977 @@ -251,7 +251,7 @@
978 req.flush()
979
980 # Set response body
981 - if isinstance(body, basestring):
982 + if isinstance(body, str):
983 req.write(body)
984 else:
985 for seg in body:
986 diff -Naur client175_0.7-original/cherrypy/_cprequest.py client175_0.7/cherrypy/_cprequest.py
987 --- client175_0.7-original/cherrypy/_cprequest.py 2010-04-20 13:10:10.000000000 +0200
988 +++ client175_0.7/cherrypy/_cprequest.py 2021-08-03 14:42:19.091009678 +0200
989 @@ -1,5 +1,5 @@
990
991 -import Cookie
992 +import http.cookies
993 import os
994 import sys
995 import time
996 @@ -11,11 +11,9 @@
997 from cherrypy.lib import http, file_generator
998
999
1000 -class Hook(object):
1001 +class Hook(object, metaclass=cherrypy._AttributeDocstrings):
1002 """A callback and its metadata: failsafe, priority, and kwargs."""
1003
1004 - __metaclass__ = cherrypy._AttributeDocstrings
1005 -
1006 callback = None
1007 callback__doc = """
1008 The bare callable that this Hook object is wrapping, which will
1009 @@ -63,7 +61,7 @@
1010 % (cls.__module__, cls.__name__, self.callback,
1011 self.failsafe, self.priority,
1012 ", ".join(['%s=%r' % (k, v)
1013 - for k, v in self.kwargs.iteritems()])))
1014 + for k, v in self.kwargs.items()])))
1015
1016
1017 class HookMap(dict):
1018 @@ -111,14 +109,14 @@
1019 newmap = self.__class__()
1020 # We can't just use 'update' because we want copies of the
1021 # mutable values (each is a list) as well.
1022 - for k, v in self.iteritems():
1023 + for k, v in self.items():
1024 newmap[k] = v[:]
1025 return newmap
1026 copy = __copy__
1027
1028 def __repr__(self):
1029 cls = self.__class__
1030 - return "%s.%s(points=%r)" % (cls.__module__, cls.__name__, self.keys())
1031 + return "%s.%s(points=%r)" % (cls.__module__, cls.__name__, list(self.keys()))
1032
1033
1034 # Config namespace handlers
1035 @@ -129,7 +127,7 @@
1036 # hookpoint per path (e.g. "hooks.before_handler.1").
1037 # Little-known fact you only get from reading source ;)
1038 hookpoint = k.split(".", 1)[0]
1039 - if isinstance(v, basestring):
1040 + if isinstance(v, str):
1041 v = cherrypy.lib.attributes(v)
1042 if not isinstance(v, Hook):
1043 v = Hook(v)
1044 @@ -156,7 +154,7 @@
1045 'before_error_response', 'after_error_response']
1046
1047
1048 -class Request(object):
1049 +class Request(object, metaclass=cherrypy._AttributeDocstrings):
1050 """An HTTP request.
1051
1052 This object represents the metadata of an HTTP request message;
1053 @@ -169,8 +167,6 @@
1054 the given URL, and the execution plan for generating a response.
1055 """
1056
1057 - __metaclass__ = cherrypy._AttributeDocstrings
1058 -
1059 prev = None
1060 prev__doc = """
1061 The previous Request object (if any). This should be None
1062 @@ -251,7 +247,7 @@
1063 values (decoded according to RFC 2047 if necessary). See also:
1064 http.HeaderMap, http.HeaderElement."""
1065
1066 - cookie = Cookie.SimpleCookie()
1067 + cookie = http.cookies.SimpleCookie()
1068 cookie__doc = """See help(Cookie)."""
1069
1070 rfile = None
1071 @@ -529,7 +525,7 @@
1072 self.header_list = list(headers)
1073 self.rfile = rfile
1074 self.headers = http.HeaderMap()
1075 - self.cookie = Cookie.SimpleCookie()
1076 + self.cookie = http.cookies.SimpleCookie()
1077 self.handler = None
1078
1079 # path_info should be the path from the
1080 @@ -608,7 +604,7 @@
1081 self.stage = 'before_finalize'
1082 self.hooks.run('before_finalize')
1083 cherrypy.response.finalize()
1084 - except (cherrypy.HTTPRedirect, cherrypy.HTTPError), inst:
1085 + except (cherrypy.HTTPRedirect, cherrypy.HTTPError) as inst:
1086 inst.set_response()
1087 self.stage = 'before_finalize (HTTPError)'
1088 self.hooks.run('before_finalize')
1089 @@ -648,7 +644,7 @@
1090 if name == 'Cookie':
1091 try:
1092 self.cookie.load(value)
1093 - except Cookie.CookieError:
1094 + except http.cookies.CookieError:
1095 msg = "Illegal cookie name %s" % value.split('=')[0]
1096 raise cherrypy.HTTPError(400, msg)
1097
1098 @@ -709,7 +705,7 @@
1099 # won't parse the request body for params if the client
1100 # didn't provide a "Content-Type" header.
1101 if 'Content-Type' not in self.headers:
1102 - h = http.HeaderMap(self.headers.items())
1103 + h = http.HeaderMap(list(self.headers.items()))
1104 h['Content-Type'] = ''
1105 else:
1106 h = self.headers
1107 @@ -720,7 +716,7 @@
1108 # FieldStorage only recognizes POST.
1109 environ={'REQUEST_METHOD': "POST"},
1110 keep_blank_values=1)
1111 - except Exception, e:
1112 + except Exception as e:
1113 if e.__class__.__name__ == 'MaxSizeExceeded':
1114 # Post data is too big
1115 raise cherrypy.HTTPError(413)
1116 @@ -746,7 +742,7 @@
1117 self.error_response()
1118 self.hooks.run("after_error_response")
1119 cherrypy.response.finalize()
1120 - except cherrypy.HTTPRedirect, inst:
1121 + except cherrypy.HTTPRedirect as inst:
1122 inst.set_response()
1123 cherrypy.response.finalize()
1124
1125 @@ -763,7 +759,7 @@
1126
1127 def __set__(self, obj, value):
1128 # Convert the given value to an iterable object.
1129 - if isinstance(value, basestring):
1130 + if isinstance(value, str):
1131 # strings get wrapped in a list because iterating over a single
1132 # item list is much faster than iterating over every character
1133 # in a long string.
1134 @@ -779,7 +775,7 @@
1135 obj._body = value
1136
1137
1138 -class Response(object):
1139 +class Response(object, metaclass=cherrypy._AttributeDocstrings):
1140 """An HTTP Response, including status, headers, and body.
1141
1142 Application developers should use Response.headers (a dict) to
1143 @@ -788,8 +784,6 @@
1144 (key, value) tuples.
1145 """
1146
1147 - __metaclass__ = cherrypy._AttributeDocstrings
1148 -
1149 # Class attributes for dev-time introspection.
1150 status = ""
1151 status__doc = """The HTTP Status-Code and Reason-Phrase."""
1152 @@ -808,7 +802,7 @@
1153 values (decoded according to RFC 2047 if necessary). See also:
1154 http.HeaderMap, http.HeaderElement."""
1155
1156 - cookie = Cookie.SimpleCookie()
1157 + cookie = http.cookies.SimpleCookie()
1158 cookie__doc = """See help(Cookie)."""
1159
1160 body = Body()
1161 @@ -842,7 +836,7 @@
1162 "Server": "CherryPy/" + cherrypy.__version__,
1163 "Date": http.HTTPDate(self.time),
1164 })
1165 - self.cookie = Cookie.SimpleCookie()
1166 + self.cookie = http.cookies.SimpleCookie()
1167
1168 def collapse_body(self):
1169 """Collapse self.body to a single string; replace it and return it."""
1170 @@ -854,7 +848,7 @@
1171 """Transform headers (and cookies) into self.header_list. (Core)"""
1172 try:
1173 code, reason, _ = http.valid_status(self.status)
1174 - except ValueError, x:
1175 + except ValueError as x:
1176 raise cherrypy.HTTPError(500, x.args[0])
1177
1178 self.status = "%s %s" % (code, reason)
1179 diff -Naur client175_0.7-original/cherrypy/_cpserver.py client175_0.7/cherrypy/_cpserver.py
1180 --- client175_0.7-original/cherrypy/_cpserver.py 2010-04-20 13:10:10.000000000 +0200
1181 +++ client175_0.7/cherrypy/_cpserver.py 2021-08-03 14:42:27.582884114 +0200
1182 @@ -73,7 +73,7 @@
1183 if httpserver is None:
1184 from cherrypy import _cpwsgi_server
1185 httpserver = _cpwsgi_server.CPWSGIServer()
1186 - if isinstance(httpserver, basestring):
1187 + if isinstance(httpserver, str):
1188 httpserver = attributes(httpserver)()
1189
1190 if self.socket_file:
1191 diff -Naur client175_0.7-original/cherrypy/_cptools.py client175_0.7/cherrypy/_cptools.py
1192 --- client175_0.7-original/cherrypy/_cptools.py 2010-04-20 13:10:10.000000000 +0200
1193 +++ client175_0.7/cherrypy/_cptools.py 2021-08-03 14:43:38.721831788 +0200
1194 @@ -30,8 +30,8 @@
1195 # Use this instead of importing inspect for less mem overhead.
1196 import types
1197 if isinstance(func, types.MethodType):
1198 - func = func.im_func
1199 - co = func.func_code
1200 + func = func.__func__
1201 + co = func.__code__
1202 return co.co_varnames[:co.co_argcount]
1203
1204
1205 @@ -105,7 +105,7 @@
1206 f._cp_config = {}
1207 subspace = self.namespace + "." + self._name + "."
1208 f._cp_config[subspace + "on"] = True
1209 - for k, v in kwargs.iteritems():
1210 + for k, v in kwargs.items():
1211 f._cp_config[subspace + k] = v
1212 return f
1213 return tool_decorator
1214 @@ -286,7 +286,7 @@
1215 sess.regenerate()
1216
1217 # Grab cookie-relevant tool args
1218 - conf = dict([(k, v) for k, v in self._merged_args().iteritems()
1219 + conf = dict([(k, v) for k, v in self._merged_args().items()
1220 if k in ('path', 'path_header', 'name', 'timeout',
1221 'domain', 'secure')])
1222 _sessions.set_response_cookie(**conf)
1223 @@ -346,7 +346,7 @@
1224 # if a method is not found, an xmlrpclib.Fault should be returned
1225 # raising an exception here will do that; see
1226 # cherrypy.lib.xmlrpc.on_error
1227 - raise Exception, 'method "%s" is not supported' % attr
1228 + raise Exception('method "%s" is not supported' % attr)
1229
1230 conf = cherrypy.request.toolmaps['tools'].get("xmlrpc", {})
1231 _xmlrpc.respond(body,
1232 @@ -399,7 +399,7 @@
1233 cherrypy._cache = kwargs.pop("cache_class", _caching.MemoryCache)()
1234
1235 # Take all remaining kwargs and set them on the Cache object.
1236 - for k, v in kwargs.iteritems():
1237 + for k, v in kwargs.items():
1238 setattr(cherrypy._cache, k, v)
1239
1240 if _caching.get(invalid_methods=invalid_methods):
1241 @@ -452,7 +452,7 @@
1242 """Run tool._setup() for each tool in our toolmap."""
1243 map = cherrypy.request.toolmaps.get(self.namespace)
1244 if map:
1245 - for name, settings in map.items():
1246 + for name, settings in list(map.items()):
1247 if settings.get("on", False):
1248 tool = getattr(self, name)
1249 tool._setup()
1250 diff -Naur client175_0.7-original/cherrypy/_cptree.py client175_0.7/cherrypy/_cptree.py
1251 --- client175_0.7-original/cherrypy/_cptree.py 2010-04-20 13:10:10.000000000 +0200
1252 +++ client175_0.7/cherrypy/_cptree.py 2021-08-03 14:43:50.457658068 +0200
1253 @@ -6,7 +6,7 @@
1254 from cherrypy.lib import http as _http
1255
1256
1257 -class Application(object):
1258 +class Application(object, metaclass=cherrypy._AttributeDocstrings):
1259 """A CherryPy Application.
1260
1261 Servers and gateways should not instantiate Request objects directly.
1262 @@ -16,8 +16,6 @@
1263 (WSGI application object) for itself.
1264 """
1265
1266 - __metaclass__ = cherrypy._AttributeDocstrings
1267 -
1268 root = None
1269 root__doc = """
1270 The top-most container of page handlers for this app. Handlers should
1271 @@ -103,7 +101,7 @@
1272 req = self.request_class(local, remote, scheme, sproto)
1273 req.app = self
1274
1275 - for name, toolbox in self.toolboxes.iteritems():
1276 + for name, toolbox in self.toolboxes.items():
1277 req.namespaces[name] = toolbox
1278
1279 resp = self.response_class()
1280 @@ -171,7 +169,7 @@
1281 if isinstance(root, Application):
1282 app = root
1283 if script_name != "" and script_name != app.script_name:
1284 - raise ValueError, "Cannot specify a different script name and pass an Application instance to cherrypy.mount"
1285 + raise ValueError("Cannot specify a different script name and pass an Application instance to cherrypy.mount")
1286 script_name = app.script_name
1287 else:
1288 app = Application(root, script_name)
1289 diff -Naur client175_0.7-original/cherrypy/_cpwsgi.py client175_0.7/cherrypy/_cpwsgi.py
1290 --- client175_0.7-original/cherrypy/_cpwsgi.py 2010-04-20 13:10:10.000000000 +0200
1291 +++ client175_0.7/cherrypy/_cpwsgi.py 2021-08-03 14:44:08.117396886 +0200
1292 @@ -1,6 +1,6 @@
1293 """WSGI interface (see PEP 333)."""
1294
1295 -import StringIO as _StringIO
1296 +import io as _StringIO
1297 import sys as _sys
1298
1299 import cherrypy as _cherrypy
1300 @@ -82,7 +82,7 @@
1301 except self.throws:
1302 self.close()
1303 raise
1304 - except _cherrypy.InternalRedirect, ir:
1305 + except _cherrypy.InternalRedirect as ir:
1306 self.environ['cherrypy.previous_request'] = _cherrypy.serving.request
1307 self.close()
1308 self.iredirect(ir.path, ir.query_string)
1309 @@ -158,9 +158,9 @@
1310 def __iter__(self):
1311 return self
1312
1313 - def next(self):
1314 + def __next__(self):
1315 try:
1316 - chunk = self.iter_response.next()
1317 + chunk = next(self.iter_response)
1318 # WSGI requires all data to be of type "str". This coercion should
1319 # not take any time at all if chunk is already of type "str".
1320 # If it's unicode, it could be a big performance hit (x ~500).
1321 @@ -170,7 +170,7 @@
1322 except self.throws:
1323 self.close()
1324 raise
1325 - except _cherrypy.InternalRedirect, ir:
1326 + except _cherrypy.InternalRedirect as ir:
1327 self.environ['cherrypy.previous_request'] = _cherrypy.serving.request
1328 self.close()
1329 self.iredirect(ir.path, ir.query_string)
1330 diff -Naur client175_0.7-original/cherrypy/__init__.py client175_0.7/cherrypy/__init__.py
1331 --- client175_0.7-original/cherrypy/__init__.py 2010-04-20 13:10:10.000000000 +0200
1332 +++ client175_0.7/cherrypy/__init__.py 2021-08-03 14:44:38.280950778 +0200
1333 @@ -59,7 +59,7 @@
1334
1335 __version__ = "3.1.2"
1336
1337 -from urlparse import urljoin as _urljoin
1338 +from urllib.parse import urljoin as _urljoin
1339
1340
1341 class _AttributeDocstrings(type):
1342 @@ -126,7 +126,7 @@
1343
1344 newdoc = [cls.__doc__ or ""]
1345
1346 - dctnames = dct.keys()
1347 + dctnames = list(dct.keys())
1348 dctnames.sort()
1349
1350 for name in dctnames:
1351 @@ -254,7 +254,7 @@
1352 except ImportError:
1353 from cherrypy._cpthreadinglocal import local as _local
1354
1355 -class _Serving(_local):
1356 +class _Serving(_local, metaclass=_AttributeDocstrings):
1357 """An interface for registering request and response objects.
1358
1359 Rather than have a separate "thread local" object for the request and
1360 @@ -265,8 +265,6 @@
1361 thread-safe way.
1362 """
1363
1364 - __metaclass__ = _AttributeDocstrings
1365 -
1366 request = _cprequest.Request(_http.Host("127.0.0.1", 80),
1367 _http.Host("127.0.0.1", 1111))
1368 request__doc = """
1369 @@ -338,7 +336,7 @@
1370 child = getattr(serving, self.__attrname__)
1371 return len(child)
1372
1373 - def __nonzero__(self):
1374 + def __bool__(self):
1375 child = getattr(serving, self.__attrname__)
1376 return bool(child)
1377
1378 @@ -410,7 +408,7 @@
1379 def expose_(func):
1380 func.exposed = True
1381 if alias is not None:
1382 - if isinstance(alias, basestring):
1383 + if isinstance(alias, str):
1384 parents[alias.replace(".", "_")] = func
1385 else:
1386 for a in alias:
1387 diff -Naur client175_0.7-original/cherrypy/lib/auth.py client175_0.7/cherrypy/lib/auth.py
1388 --- client175_0.7-original/cherrypy/lib/auth.py 2010-04-20 13:10:10.000000000 +0200
1389 +++ client175_0.7/cherrypy/lib/auth.py 2021-08-03 14:45:01.296612330 +0200
1390 @@ -19,7 +19,7 @@
1391 users = users() # expect it to return a dictionary
1392
1393 if not isinstance(users, dict):
1394 - raise ValueError, "Authentication users must be a dictionary"
1395 + raise ValueError("Authentication users must be a dictionary")
1396
1397 # fetch the user password
1398 password = users.get(ah["username"], None)
1399 @@ -28,7 +28,7 @@
1400 password = users(ah["username"])
1401 else:
1402 if not isinstance(users, dict):
1403 - raise ValueError, "Authentication users must be a dictionary"
1404 + raise ValueError("Authentication users must be a dictionary")
1405
1406 # fetch the user password
1407 password = users.get(ah["username"], None)
1408 diff -Naur client175_0.7-original/cherrypy/lib/caching.py client175_0.7/cherrypy/lib/caching.py
1409 --- client175_0.7-original/cherrypy/lib/caching.py 2010-04-20 13:10:10.000000000 +0200
1410 +++ client175_0.7/cherrypy/lib/caching.py 2021-08-03 14:45:08.464504417 +0200
1411 @@ -45,7 +45,7 @@
1412 # See tickets #99 and #180 for more information.
1413 while time:
1414 now = time.time()
1415 - for expiration_time, objects in self.expirations.items():
1416 + for expiration_time, objects in list(self.expirations.items()):
1417 if expiration_time <= now:
1418 for obj_size, obj_key in objects:
1419 try:
1420 @@ -161,7 +161,7 @@
1421 # this was put into the cached copy, and should have been
1422 # resurrected just above (response.headers = cache_data[1]).
1423 cptools.validate_since()
1424 - except cherrypy.HTTPRedirect, x:
1425 + except cherrypy.HTTPRedirect as x:
1426 if x.status == 304:
1427 cherrypy._cache.tot_non_modified += 1
1428 raise
1429 @@ -188,7 +188,7 @@
1430 cherrypy.response.headers.elements('Vary')]
1431 if vary:
1432 sel_headers = dict([(k, v) for k, v
1433 - in cherrypy.request.headers.iteritems()
1434 + in cherrypy.request.headers.items()
1435 if k in vary])
1436 else:
1437 sel_headers = {}
1438 diff -Naur client175_0.7-original/cherrypy/lib/covercp.py client175_0.7/cherrypy/lib/covercp.py
1439 --- client175_0.7-original/cherrypy/lib/covercp.py 2010-04-20 13:10:10.000000000 +0200
1440 +++ client175_0.7/cherrypy/lib/covercp.py 2021-08-03 14:45:14.876409627 +0200
1441 @@ -21,14 +21,14 @@
1442 import re
1443 import sys
1444 import cgi
1445 -import urllib
1446 +import urllib.request, urllib.parse, urllib.error
1447 import os, os.path
1448 localFile = os.path.join(os.path.dirname(__file__), "coverage.cache")
1449
1450 try:
1451 - import cStringIO as StringIO
1452 + import io as StringIO
1453 except ImportError:
1454 - import StringIO
1455 + import io
1456
1457 try:
1458 from coverage import the_coverage as coverage
1459 @@ -190,7 +190,7 @@
1460 def _show_branch(root, base, path, pct=0, showpct=False, exclude=""):
1461
1462 # Show the directory name and any of our children
1463 - dirs = [k for k, v in root.iteritems() if v]
1464 + dirs = [k for k, v in root.items() if v]
1465 dirs.sort()
1466 for name in dirs:
1467 newpath = os.path.join(path, name)
1468 @@ -199,7 +199,7 @@
1469 relpath = newpath[len(base):]
1470 yield "| " * relpath.count(os.sep)
1471 yield "<a class='directory' href='menu?base=%s&exclude=%s'>%s</a>\n" % \
1472 - (newpath, urllib.quote_plus(exclude), name)
1473 + (newpath, urllib.parse.quote_plus(exclude), name)
1474
1475 for chunk in _show_branch(root[name], base, newpath, pct, showpct, exclude):
1476 yield chunk
1477 @@ -207,7 +207,7 @@
1478 # Now list the files
1479 if path.lower().startswith(base):
1480 relpath = path[len(base):]
1481 - files = [k for k, v in root.iteritems() if not v]
1482 + files = [k for k, v in root.items() if not v]
1483 files.sort()
1484 for name in files:
1485 newpath = os.path.join(path, name)
1486 @@ -257,7 +257,7 @@
1487 """Return covered module names as a nested dict."""
1488 tree = {}
1489 coverage.get_ready()
1490 - runs = coverage.cexecuted.keys()
1491 + runs = list(coverage.cexecuted.keys())
1492 if runs:
1493 for path in runs:
1494 if not _skip_file(path, exclude) and not os.path.isdir(path):
1495 @@ -287,7 +287,7 @@
1496 for atom in atoms:
1497 path += atom + os.sep
1498 yield ("<a href='menu?base=%s&exclude=%s'>%s</a> %s"
1499 - % (path, urllib.quote_plus(exclude), atom, os.sep))
1500 + % (path, urllib.parse.quote_plus(exclude), atom, os.sep))
1501 yield "</div>"
1502
1503 yield "<div id='tree'>"
1504 diff -Naur client175_0.7-original/cherrypy/lib/cptools.py client175_0.7/cherrypy/lib/cptools.py
1505 --- client175_0.7-original/cherrypy/lib/cptools.py 2010-04-20 13:10:10.000000000 +0200
1506 +++ client175_0.7/cherrypy/lib/cptools.py 2021-08-03 14:45:22.384298594 +0200
1507 @@ -236,7 +236,7 @@
1508 if error_msg:
1509 body = self.login_screen(from_page, username, error_msg)
1510 cherrypy.response.body = body
1511 - if cherrypy.response.headers.has_key("Content-Length"):
1512 + if "Content-Length" in cherrypy.response.headers:
1513 # Delete Content-Length header so finalize() recalcs it.
1514 del cherrypy.response.headers["Content-Length"]
1515 return True
1516 @@ -265,7 +265,7 @@
1517 sess[self.session_key] = username = self.anonymous()
1518 if not username:
1519 cherrypy.response.body = self.login_screen(cherrypy.url(qs=request.query_string))
1520 - if cherrypy.response.headers.has_key("Content-Length"):
1521 + if "Content-Length" in cherrypy.response.headers:
1522 # Delete Content-Length header so finalize() recalcs it.
1523 del cherrypy.response.headers["Content-Length"]
1524 return True
1525 @@ -287,7 +287,7 @@
1526
1527 def session_auth(**kwargs):
1528 sa = SessionAuth()
1529 - for k, v in kwargs.iteritems():
1530 + for k, v in kwargs.items():
1531 setattr(sa, k, v)
1532 return sa.run()
1533 session_auth.__doc__ = """Session authentication hook.
1534 @@ -314,7 +314,7 @@
1535 # Sort by the standard points if possible.
1536 from cherrypy import _cprequest
1537 points = _cprequest.hookpoints
1538 - for k in cherrypy.request.hooks.keys():
1539 + for k in list(cherrypy.request.hooks.keys()):
1540 if k not in points:
1541 points.append(k)
1542
1543 @@ -395,7 +395,7 @@
1544 """
1545 if not media:
1546 return
1547 - if isinstance(media, basestring):
1548 + if isinstance(media, str):
1549 media = [media]
1550
1551 # Parse the Accept request header, and try to match one
1552 diff -Naur client175_0.7-original/cherrypy/lib/encoding.py client175_0.7/cherrypy/lib/encoding.py
1553 --- client175_0.7-original/cherrypy/lib/encoding.py 2010-04-20 13:10:10.000000000 +0200
1554 +++ client175_0.7/cherrypy/lib/encoding.py 2021-08-03 14:45:29.700190398 +0200
1555 @@ -33,7 +33,7 @@
1556
1557 def decode_params(encoding):
1558 decoded_params = {}
1559 - for key, value in cherrypy.request.params.items():
1560 + for key, value in list(cherrypy.request.params.items()):
1561 if not hasattr(value, 'file'):
1562 # Skip the value if it is an uploaded file
1563 if isinstance(value, list):
1564 @@ -73,7 +73,7 @@
1565 """
1566 def encoder(body):
1567 for chunk in body:
1568 - if isinstance(chunk, unicode):
1569 + if isinstance(chunk, str):
1570 chunk = chunk.encode(encoding, errors)
1571 yield chunk
1572 cherrypy.response.body = encoder(cherrypy.response.body)
1573 @@ -84,7 +84,7 @@
1574 try:
1575 body = []
1576 for chunk in cherrypy.response.body:
1577 - if isinstance(chunk, unicode):
1578 + if isinstance(chunk, str):
1579 chunk = chunk.encode(encoding, errors)
1580 body.append(chunk)
1581 cherrypy.response.body = body
1582 @@ -101,7 +101,7 @@
1583 else:
1584 response.collapse_body()
1585 encoder = encode_string
1586 - if response.headers.has_key("Content-Length"):
1587 + if "Content-Length" in response.headers:
1588 # Delete Content-Length header so finalize() recalcs it.
1589 # Encoded strings may be of different lengths from their
1590 # unicode equivalents, and even from each other. For example:
1591 @@ -179,7 +179,7 @@
1592 yield '\037\213' # magic header
1593 yield '\010' # compression method
1594 yield '\0'
1595 - yield struct.pack("<L", long(time.time()))
1596 + yield struct.pack("<L", int(time.time()))
1597 yield '\002'
1598 yield '\377'
1599
1600 @@ -194,12 +194,12 @@
1601 yield zobj.compress(line)
1602 yield zobj.flush()
1603 yield struct.pack("<l", crc)
1604 - yield struct.pack("<L", size & 0xFFFFFFFFL)
1605 + yield struct.pack("<L", size & 0xFFFFFFFF)
1606
1607 def decompress(body):
1608 - import gzip, StringIO
1609 + import gzip, io
1610
1611 - zbuf = StringIO.StringIO()
1612 + zbuf = io.StringIO()
1613 zbuf.write(body)
1614 zbuf.seek(0)
1615 zfile = gzip.GzipFile(mode='rb', fileobj=zbuf)
1616 @@ -258,7 +258,7 @@
1617
1618 response.headers['Content-Encoding'] = 'gzip'
1619 response.body = compress(response.body, compress_level)
1620 - if response.headers.has_key("Content-Length"):
1621 + if "Content-Length" in response.headers:
1622 # Delete Content-Length header so finalize() recalcs it.
1623 del response.headers["Content-Length"]
1624 return
1625 diff -Naur client175_0.7-original/cherrypy/lib/httpauth.py client175_0.7/cherrypy/lib/httpauth.py
1626 --- client175_0.7-original/cherrypy/lib/httpauth.py 2010-04-20 13:10:10.000000000 +0200
1627 +++ client175_0.7/cherrypy/lib/httpauth.py 2021-08-03 14:45:46.595938962 +0200
1628 @@ -68,7 +68,7 @@
1629
1630 import time
1631 import base64
1632 -import urllib2
1633 +import urllib.request, urllib.error, urllib.parse
1634
1635 MD5 = "MD5"
1636 MD5_SESS = "MD5-sess"
1637 @@ -144,17 +144,17 @@
1638 # Check for required parameters
1639 required = ["username", "realm", "nonce", "uri", "response"]
1640 for k in required:
1641 - if not params.has_key(k):
1642 + if k not in params:
1643 return None
1644
1645 # If qop is sent then cnonce and nc MUST be present
1646 - if params.has_key("qop") and not (params.has_key("cnonce") \
1647 - and params.has_key("nc")):
1648 + if "qop" in params and not ("cnonce" in params \
1649 + and "nc" in params):
1650 return None
1651
1652 # If qop is not sent, neither cnonce nor nc can be present
1653 - if (params.has_key("cnonce") or params.has_key("nc")) and \
1654 - not params.has_key("qop"):
1655 + if ("cnonce" in params or "nc" in params) and \
1656 + "qop" not in params:
1657 return None
1658
1659 return params
1660 diff -Naur client175_0.7-original/cherrypy/lib/http.py client175_0.7/cherrypy/lib/http.py
1661 --- client175_0.7-original/cherrypy/lib/http.py 2010-04-20 13:10:10.000000000 +0200
1662 +++ client175_0.7/cherrypy/lib/http.py 2021-08-03 14:45:40.288033948 +0200
1663 @@ -6,7 +6,7 @@
1664 # FuManChu will personally hang you up by your thumbs and submit you
1665 # to a public caning.
1666
1667 -from BaseHTTPServer import BaseHTTPRequestHandler
1668 +from http.server import BaseHTTPRequestHandler
1669 response_codes = BaseHTTPRequestHandler.responses.copy()
1670
1671 # From http://www.cherrypy.org/ticket/361
1672 @@ -61,7 +61,7 @@
1673 if start:
1674 if not stop:
1675 stop = content_length - 1
1676 - start, stop = map(int, (start, stop))
1677 + start, stop = list(map(int, (start, stop)))
1678 if start >= content_length:
1679 # From rfc 2616 sec 14.16:
1680 # "If the server receives a request (other than one
1681 @@ -101,8 +101,8 @@
1682 self.params = params
1683
1684 def __unicode__(self):
1685 - p = [";%s=%s" % (k, v) for k, v in self.params.iteritems()]
1686 - return u"%s%s" % (self.value, "".join(p))
1687 + p = [";%s=%s" % (k, v) for k, v in self.params.items()]
1688 + return "%s%s" % (self.value, "".join(p))
1689
1690 def __str__(self):
1691 return str(self.__unicode__())
1692 @@ -264,14 +264,14 @@
1693 pm = {'x': int(pm[0]), 'y': int(pm[1])}
1694 else:
1695 pm = cgi.parse_qs(query_string, keep_blank_values)
1696 - for key, val in pm.items():
1697 + for key, val in list(pm.items()):
1698 if len(val) == 1:
1699 pm[key] = val[0]
1700 return pm
1701
1702 def params_from_CGI_form(form):
1703 params = {}
1704 - for key in form.keys():
1705 + for key in list(form.keys()):
1706 value_list = form[key]
1707 if isinstance(value_list, list):
1708 params[key] = []
1709 @@ -315,7 +315,7 @@
1710 return dict.has_key(self, str(key).title())
1711
1712 def update(self, E):
1713 - for k in E.keys():
1714 + for k in list(E.keys()):
1715 self[str(k).title()] = E[k]
1716
1717 def fromkeys(cls, seq, value=None):
1718 @@ -357,8 +357,8 @@
1719 def output(self, protocol=(1, 1)):
1720 """Transform self into a list of (name, value) tuples."""
1721 header_list = []
1722 - for key, v in self.iteritems():
1723 - if isinstance(v, unicode):
1724 + for key, v in self.items():
1725 + if isinstance(v, str):
1726 # HTTP/1.0 says, "Words of *TEXT may contain octets
1727 # from character sets other than US-ASCII." and
1728 # "Recipients of header field TEXT containing octets
1729 diff -Naur client175_0.7-original/cherrypy/lib/__init__.py client175_0.7/cherrypy/lib/__init__.py
1730 --- client175_0.7-original/cherrypy/lib/__init__.py 2010-04-20 13:10:10.000000000 +0200
1731 +++ client175_0.7/cherrypy/lib/__init__.py 2021-08-03 14:46:02.407667654 +0200
1732 @@ -18,7 +18,7 @@
1733 """Load a module and retrieve an attribute of that module."""
1734
1735 # Parse out the path, module, and attribute
1736 - last_dot = full_attribute_name.rfind(u".")
1737 + last_dot = full_attribute_name.rfind(".")
1738 attr_name = full_attribute_name[last_dot + 1:]
1739 mod_path = full_attribute_name[:last_dot]
1740
1741 @@ -52,7 +52,7 @@
1742 return expr[subs]
1743
1744 def build_CallFunc(self, o):
1745 - children = map(self.build, o.getChildren())
1746 + children = list(map(self.build, o.getChildren()))
1747 callee = children.pop(0)
1748 kwargs = children.pop() or {}
1749 starargs = children.pop() or ()
1750 @@ -60,7 +60,7 @@
1751 return callee(*args, **kwargs)
1752
1753 def build_List(self, o):
1754 - return map(self.build, o.getChildren())
1755 + return list(map(self.build, o.getChildren()))
1756
1757 def build_Const(self, o):
1758 return o.value
1759 @@ -69,7 +69,7 @@
1760 d = {}
1761 i = iter(map(self.build, o.getChildren()))
1762 for el in i:
1763 - d[el] = i.next()
1764 + d[el] = next(i)
1765 return d
1766
1767 def build_Tuple(self, o):
1768 @@ -91,7 +91,7 @@
1769
1770 # See if the Name is in __builtin__.
1771 try:
1772 - import __builtin__
1773 + import builtins
1774 return getattr(__builtin__, o.name)
1775 except AttributeError:
1776 pass
1777 @@ -99,7 +99,7 @@
1778 raise TypeError("unrepr could not resolve the name %s" % repr(o.name))
1779
1780 def build_Add(self, o):
1781 - left, right = map(self.build, o.getChildren())
1782 + left, right = list(map(self.build, o.getChildren()))
1783 return left + right
1784
1785 def build_Getattr(self, o):
1786 diff -Naur client175_0.7-original/cherrypy/lib/profiler.py client175_0.7/cherrypy/lib/profiler.py
1787 --- client175_0.7-original/cherrypy/lib/profiler.py 2010-04-20 13:10:10.000000000 +0200
1788 +++ client175_0.7/cherrypy/lib/profiler.py 2021-08-03 14:46:29.643218230 +0200
1789 @@ -61,9 +61,9 @@
1790 import sys
1791
1792 try:
1793 - import cStringIO as StringIO
1794 + import io as StringIO
1795 except ImportError:
1796 - import StringIO
1797 + import io
1798
1799
1800 _count = 0
1801 @@ -94,7 +94,7 @@
1802
1803 def stats(self, filename, sortby='cumulative'):
1804 """stats(index) -> output of print_stats() for the given profile."""
1805 - sio = StringIO.StringIO()
1806 + sio = io.StringIO()
1807 if sys.version_info >= (2, 5):
1808 s = pstats.Stats(os.path.join(self.path, filename), stream=sio)
1809 s.strip_dirs()
1810 diff -Naur client175_0.7-original/cherrypy/lib/safemime.py client175_0.7/cherrypy/lib/safemime.py
1811 --- client175_0.7-original/cherrypy/lib/safemime.py 2010-04-20 13:10:10.000000000 +0200
1812 +++ client175_0.7/cherrypy/lib/safemime.py 2021-08-03 14:46:40.883037698 +0200
1813 @@ -95,13 +95,13 @@
1814 def __iter__(self):
1815 return self.rfile
1816
1817 - def next(self):
1818 + def __next__(self):
1819 if self.clen:
1820 # Return '' if we've read all the data.
1821 if self.bytes_read >= self.clen:
1822 return ''
1823
1824 - data = self.rfile.next()
1825 + data = next(self.rfile)
1826 self.bytes_read += len(data)
1827 return data
1828
1829 diff -Naur client175_0.7-original/cherrypy/lib/sessions.py client175_0.7/cherrypy/lib/sessions.py
1830 --- client175_0.7-original/cherrypy/lib/sessions.py 2010-04-20 13:10:10.000000000 +0200
1831 +++ client175_0.7/cherrypy/lib/sessions.py 2021-08-03 14:46:48.498916658 +0200
1832 @@ -9,7 +9,7 @@
1833 import datetime
1834 import os
1835 try:
1836 - import cPickle as pickle
1837 + import pickle as pickle
1838 except ImportError:
1839 import pickle
1840 import random
1841 @@ -31,11 +31,9 @@
1842
1843 missing = object()
1844
1845 -class Session(object):
1846 +class Session(object, metaclass=cherrypy._AttributeDocstrings):
1847 """A CherryPy dict-like Session object (one per request)."""
1848
1849 - __metaclass__ = cherrypy._AttributeDocstrings
1850 -
1851 _id = None
1852 id_observers = None
1853 id_observers__doc = "A list of callbacks to which to pass new id's."
1854 @@ -72,7 +70,7 @@
1855 self.id_observers = []
1856 self._data = {}
1857
1858 - for k, v in kwargs.iteritems():
1859 + for k, v in kwargs.items():
1860 setattr(self, k, v)
1861
1862 if id is None:
1863 @@ -192,7 +190,7 @@
1864 def has_key(self, key):
1865 """D.has_key(k) -> True if D has a key k, else False."""
1866 if not self.loaded: self.load()
1867 - return self._data.has_key(key)
1868 + return key in self._data
1869
1870 def get(self, key, default=None):
1871 """D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None."""
1872 @@ -217,17 +215,17 @@
1873 def keys(self):
1874 """D.keys() -> list of D's keys."""
1875 if not self.loaded: self.load()
1876 - return self._data.keys()
1877 + return list(self._data.keys())
1878
1879 def items(self):
1880 """D.items() -> list of D's (key, value) pairs, as 2-tuples."""
1881 if not self.loaded: self.load()
1882 - return self._data.items()
1883 + return list(self._data.items())
1884
1885 def values(self):
1886 """D.values() -> list of D's values."""
1887 if not self.loaded: self.load()
1888 - return self._data.values()
1889 + return list(self._data.values())
1890
1891
1892 class RamSession(Session):
1893 @@ -239,7 +237,7 @@
1894 def clean_up(self):
1895 """Clean up expired sessions."""
1896 now = datetime.datetime.now()
1897 - for id, (data, expiration_time) in self.cache.items():
1898 + for id, (data, expiration_time) in list(self.cache.items()):
1899 if expiration_time < now:
1900 try:
1901 del self.cache[id]
1902 @@ -302,7 +300,7 @@
1903 # The 'storage_path' arg is required for file-based sessions.
1904 kwargs['storage_path'] = os.path.abspath(kwargs['storage_path'])
1905
1906 - for k, v in kwargs.iteritems():
1907 + for k, v in kwargs.items():
1908 setattr(cls, k, v)
1909
1910 # Warn if any lock files exist at startup.
1911 @@ -426,7 +424,7 @@
1912 This should only be called once per process; this will be done
1913 automatically when using sessions.init (as the built-in Tool does).
1914 """
1915 - for k, v in kwargs.iteritems():
1916 + for k, v in kwargs.items():
1917 setattr(cls, k, v)
1918
1919 self.db = self.get_db()
1920 @@ -502,7 +500,7 @@
1921 This should only be called once per process; this will be done
1922 automatically when using sessions.init (as the built-in Tool does).
1923 """
1924 - for k, v in kwargs.iteritems():
1925 + for k, v in kwargs.items():
1926 setattr(cls, k, v)
1927
1928 import memcache
1929 diff -Naur client175_0.7-original/cherrypy/lib/static.py client175_0.7/cherrypy/lib/static.py
1930 --- client175_0.7-original/cherrypy/lib/static.py 2010-04-20 13:10:10.000000000 +0200
1931 +++ client175_0.7/cherrypy/lib/static.py 2021-08-03 14:46:56.870784689 +0200
1932 @@ -7,7 +7,7 @@
1933 import re
1934 import stat
1935 import time
1936 -import urllib
1937 +import urllib.request, urllib.parse, urllib.error
1938
1939 import cherrypy
1940 from cherrypy.lib import cptools, http, file_generator_limited
1941 @@ -99,7 +99,7 @@
1942 boundary = mimetools.choose_boundary()
1943 ct = "multipart/byteranges; boundary=%s" % boundary
1944 response.headers['Content-Type'] = ct
1945 - if response.headers.has_key("Content-Length"):
1946 + if "Content-Length" in response.headers:
1947 # Delete Content-Length header so finalize() recalcs it.
1948 del response.headers["Content-Length"]
1949
1950 @@ -189,7 +189,7 @@
1951 section = "/"
1952 section = section.rstrip(r"\/")
1953 branch = cherrypy.request.path_info[len(section) + 1:]
1954 - branch = urllib.unquote(branch.lstrip(r"\/"))
1955 + branch = urllib.parse.unquote(branch.lstrip(r"\/"))
1956
1957 # If branch is "", filename will end in a slash
1958 filename = os.path.join(dir, branch)
1959 diff -Naur client175_0.7-original/cherrypy/lib/tidy.py client175_0.7/cherrypy/lib/tidy.py
1960 --- client175_0.7-original/cherrypy/lib/tidy.py 2010-04-20 13:10:10.000000000 +0200
1961 +++ client175_0.7/cherrypy/lib/tidy.py 2021-08-03 14:47:04.222669487 +0200
1962 @@ -2,7 +2,7 @@
1963
1964 import cgi
1965 import os
1966 -import StringIO
1967 +import io
1968 import traceback
1969
1970 import cherrypy
1971 @@ -79,7 +79,7 @@
1972
1973 if new_errs:
1974 response.body = wrong_content('<br />'.join(new_errs), orig_body)
1975 - if response.headers.has_key("Content-Length"):
1976 + if "Content-Length" in response.headers:
1977 # Delete Content-Length header so finalize() recalcs it.
1978 del response.headers["Content-Length"]
1979 return
1980 @@ -95,23 +95,23 @@
1981 enctag = '<?xml version="1.0" encoding="%s"?>' % encoding
1982 orig_body = enctag + orig_body
1983
1984 - f = StringIO.StringIO(orig_body)
1985 + f = io.StringIO(orig_body)
1986 try:
1987 tree = parse(f)
1988 except:
1989 # Wrong XML
1990 - body_file = StringIO.StringIO()
1991 + body_file = io.StringIO()
1992 traceback.print_exc(file = body_file)
1993 body_file = '<br />'.join(body_file.getvalue())
1994 response.body = wrong_content(body_file, orig_body, "XML")
1995 - if response.headers.has_key("Content-Length"):
1996 + if "Content-Length" in response.headers:
1997 # Delete Content-Length header so finalize() recalcs it.
1998 del response.headers["Content-Length"]
1999 return
2000
2001 if use_output:
2002 response.body = [output]
2003 - if response.headers.has_key("Content-Length"):
2004 + if "Content-Length" in response.headers:
2005 # Delete Content-Length header so finalize() recalcs it.
2006 del response.headers["Content-Length"]
2007
2008 @@ -178,7 +178,7 @@
2009
2010 if new_errs:
2011 response.body = wrong_content('<br />'.join(new_errs), orig_body)
2012 - if response.headers.has_key("Content-Length"):
2013 + if "Content-Length" in response.headers:
2014 # Delete Content-Length header so finalize() recalcs it.
2015 del response.headers["Content-Length"]
2016
2017 diff -Naur client175_0.7-original/cherrypy/lib/wsgiapp.py client175_0.7/cherrypy/lib/wsgiapp.py
2018 --- client175_0.7-original/cherrypy/lib/wsgiapp.py 2010-04-20 13:10:10.000000000 +0200
2019 +++ client175_0.7/cherrypy/lib/wsgiapp.py 2021-08-03 14:47:15.738490577 +0200
2020 @@ -43,7 +43,7 @@
2021 headers = request.headers
2022 environ["CONTENT_TYPE"] = headers.get("Content-type", "")
2023 environ["CONTENT_LENGTH"] = headers.get("Content-length", "")
2024 - for (k, v) in headers.iteritems():
2025 + for (k, v) in headers.items():
2026 envname = "HTTP_" + k.upper().replace("-","_")
2027 environ[envname] = v
2028 return environ
2029 diff -Naur client175_0.7-original/cherrypy/lib/xmlrpc.py client175_0.7/cherrypy/lib/xmlrpc.py
2030 --- client175_0.7-original/cherrypy/lib/xmlrpc.py 2010-04-20 13:10:10.000000000 +0200
2031 +++ client175_0.7/cherrypy/lib/xmlrpc.py 2021-08-03 14:47:22.378387654 +0200
2032 @@ -6,8 +6,8 @@
2033 def process_body():
2034 """Return (params, method) from request body."""
2035 try:
2036 - import xmlrpclib
2037 - return xmlrpclib.loads(cherrypy.request.body.read())
2038 + import xmlrpc.client
2039 + return xmlrpc.client.loads(cherrypy.request.body.read())
2040 except Exception:
2041 return ('ERROR PARAMS', ), 'ERRORMETHOD'
2042
2043 @@ -35,15 +35,15 @@
2044
2045
2046 def respond(body, encoding='utf-8', allow_none=0):
2047 - import xmlrpclib
2048 - if not isinstance(body, xmlrpclib.Fault):
2049 + import xmlrpc.client
2050 + if not isinstance(body, xmlrpc.client.Fault):
2051 body = (body,)
2052 - _set_response(xmlrpclib.dumps(body, methodresponse=1,
2053 + _set_response(xmlrpc.client.dumps(body, methodresponse=1,
2054 encoding=encoding,
2055 allow_none=allow_none))
2056
2057 def on_error(*args, **kwargs):
2058 body = str(sys.exc_info()[1])
2059 - import xmlrpclib
2060 - _set_response(xmlrpclib.dumps(xmlrpclib.Fault(1, body)))
2061 + import xmlrpc.client
2062 + _set_response(xmlrpc.client.dumps(xmlrpc.client.Fault(1, body)))
2063
2064 diff -Naur client175_0.7-original/cherrypy/process/plugins.py client175_0.7/cherrypy/process/plugins.py
2065 --- client175_0.7-original/cherrypy/process/plugins.py 2010-04-20 13:10:10.000000000 +0200
2066 +++ client175_0.7/cherrypy/process/plugins.py 2021-08-03 14:48:07.409700439 +0200
2067 @@ -49,7 +49,7 @@
2068
2069 # Map from signal numbers to names
2070 signals = {}
2071 - for k, v in vars(_signal).items():
2072 + for k, v in list(vars(_signal).items()):
2073 if k.startswith('SIG') and not k.startswith('SIG_'):
2074 signals[v] = k
2075 del k, v
2076 @@ -65,14 +65,14 @@
2077 self._previous_handlers = {}
2078
2079 def subscribe(self):
2080 - for sig, func in self.handlers.iteritems():
2081 + for sig, func in self.handlers.items():
2082 try:
2083 self.set_handler(sig, func)
2084 except ValueError:
2085 pass
2086
2087 def unsubscribe(self):
2088 - for signum, handler in self._previous_handlers.iteritems():
2089 + for signum, handler in self._previous_handlers.items():
2090 signame = self.signals[signum]
2091
2092 if handler is None:
2093 @@ -100,7 +100,7 @@
2094 If the given signal name or number is not available on the current
2095 platform, ValueError is raised.
2096 """
2097 - if isinstance(signal, basestring):
2098 + if isinstance(signal, str):
2099 signum = getattr(_signal, signal, None)
2100 if signum is None:
2101 raise ValueError("No such signal: %r" % signal)
2102 @@ -162,7 +162,7 @@
2103 self.bus.log("pwd module not available; ignoring uid.",
2104 level=30)
2105 val = None
2106 - elif isinstance(val, basestring):
2107 + elif isinstance(val, str):
2108 val = pwd.getpwnam(val)[2]
2109 self._uid = val
2110 uid = property(_get_uid, _set_uid, doc="The uid under which to run.")
2111 @@ -175,7 +175,7 @@
2112 self.bus.log("grp module not available; ignoring gid.",
2113 level=30)
2114 val = None
2115 - elif isinstance(val, basestring):
2116 + elif isinstance(val, str):
2117 val = grp.getgrnam(val)[2]
2118 self._gid = val
2119 gid = property(_get_gid, _set_gid, doc="The gid under which to run.")
2120 @@ -296,7 +296,7 @@
2121 # This is the first parent. Exit, now that we've forked.
2122 self.bus.log('Forking once.')
2123 os._exit(0)
2124 - except OSError, exc:
2125 + except OSError as exc:
2126 # Python raises OSError rather than returning negative numbers.
2127 sys.exit("%s: fork #1 failed: (%d) %s\n"
2128 % (sys.argv[0], exc.errno, exc.strerror))
2129 @@ -309,7 +309,7 @@
2130 if pid > 0:
2131 self.bus.log('Forking twice.')
2132 os._exit(0) # Exit second parent
2133 - except OSError, exc:
2134 + except OSError as exc:
2135 sys.exit("%s: fork #2 failed: (%d) %s\n"
2136 % (sys.argv[0], exc.errno, exc.strerror))
2137
2138 @@ -440,7 +440,7 @@
2139 def run(self):
2140 """Reload the process if registered files have been modified."""
2141 sysfiles = set()
2142 - for k, m in sys.modules.items():
2143 + for k, m in list(sys.modules.items()):
2144 if re.match(self.match, k):
2145 if hasattr(m, '__loader__'):
2146 if hasattr(m.__loader__, 'archive'):
2147 @@ -522,7 +522,7 @@
2148
2149 def stop(self):
2150 """Release all threads and run all 'stop_thread' listeners."""
2151 - for thread_ident, i in self.threads.iteritems():
2152 + for thread_ident, i in self.threads.items():
2153 self.bus.publish('stop_thread', i)
2154 self.threads.clear()
2155 graceful = stop
2156 diff -Naur client175_0.7-original/cherrypy/process/servers.py client175_0.7/cherrypy/process/servers.py
2157 --- client175_0.7-original/cherrypy/process/servers.py 2010-04-20 13:10:10.000000000 +0200
2158 +++ client175_0.7/cherrypy/process/servers.py 2021-08-03 14:48:16.165568167 +0200
2159 @@ -71,11 +71,11 @@
2160 """
2161 try:
2162 self.httpserver.start()
2163 - except KeyboardInterrupt, exc:
2164 + except KeyboardInterrupt as exc:
2165 self.bus.log("<Ctrl-C> hit: shutting down HTTP server")
2166 self.interrupt = exc
2167 self.bus.exit()
2168 - except SystemExit, exc:
2169 + except SystemExit as exc:
2170 self.bus.log("SystemExit raised: shutting down HTTP server")
2171 self.interrupt = exc
2172 self.bus.exit()
2173 @@ -238,7 +238,7 @@
2174 if not host:
2175 raise ValueError("Host values of '' or None are not allowed.")
2176
2177 - for trial in xrange(50):
2178 + for trial in range(50):
2179 try:
2180 # we are expecting a free port, so reduce the timeout
2181 check_port(host, port, timeout=0.1)
2182 @@ -255,7 +255,7 @@
2183 if not host:
2184 raise ValueError("Host values of '' or None are not allowed.")
2185
2186 - for trial in xrange(50):
2187 + for trial in range(50):
2188 try:
2189 check_port(host, port)
2190 except IOError:
2191 diff -Naur client175_0.7-original/cherrypy/process/win32.py client175_0.7/cherrypy/process/win32.py
2192 --- client175_0.7-original/cherrypy/process/win32.py 2010-04-20 13:10:10.000000000 +0200
2193 +++ client175_0.7/cherrypy/process/win32.py 2021-08-03 14:48:22.801468164 +0200
2194 @@ -1,7 +1,7 @@
2195 """Windows service. Requires pywin32."""
2196
2197 import os
2198 -import thread
2199 +import _thread
2200 import win32api
2201 import win32con
2202 import win32event
2203 @@ -84,7 +84,7 @@
2204 return self.events[state]
2205 except KeyError:
2206 event = win32event.CreateEvent(None, 0, 0,
2207 - u"WSPBus %s Event (pid=%r)" %
2208 + "WSPBus %s Event (pid=%r)" %
2209 (state.name, os.getpid()))
2210 self.events[state] = event
2211 return event
2212 @@ -128,7 +128,7 @@
2213
2214 def key_for(self, obj):
2215 """For the given value, return its corresponding key."""
2216 - for key, val in self.iteritems():
2217 + for key, val in self.items():
2218 if val is obj:
2219 return key
2220 raise ValueError("The given object could not be found: %r" % obj)
2221 diff -Naur client175_0.7-original/cherrypy/process/wspbus.py client175_0.7/cherrypy/process/wspbus.py
2222 --- client175_0.7-original/cherrypy/process/wspbus.py 2010-04-20 13:10:10.000000000 +0200
2223 +++ client175_0.7/cherrypy/process/wspbus.py 2021-08-03 14:48:29.181372091 +0200
2224 @@ -147,7 +147,7 @@
2225 output.append(listener(*args, **kwargs))
2226 except KeyboardInterrupt:
2227 raise
2228 - except SystemExit, e:
2229 + except SystemExit as e:
2230 # If we have previous errors ensure the exit code is non-zero
2231 if exc and e.code == 0:
2232 e.code = 1
2233 @@ -195,7 +195,7 @@
2234 except:
2235 # Any stop/exit errors will be logged inside publish().
2236 pass
2237 - raise e_info[0], e_info[1], e_info[2]
2238 + raise e_info[0](e_info[1]).with_traceback(e_info[2])
2239
2240 def exit(self):
2241 """Stop all services and prepare to exit the process."""
2242 diff -Naur client175_0.7-original/cherrypy/wsgiserver/__init__.py client175_0.7/cherrypy/wsgiserver/__init__.py
2243 --- client175_0.7-original/cherrypy/wsgiserver/__init__.py 2010-04-20 13:10:10.000000000 +0200
2244 +++ client175_0.7/cherrypy/wsgiserver/__init__.py 2021-08-03 14:49:05.556826062 +0200
2245 @@ -79,24 +79,24 @@
2246
2247 import base64
2248 import os
2249 -import Queue
2250 +import queue
2251 import re
2252 quoted_slash = re.compile("(?i)%2F")
2253 import rfc822
2254 import socket
2255 try:
2256 - import cStringIO as StringIO
2257 + import io as StringIO
2258 except ImportError:
2259 - import StringIO
2260 + import io
2261
2262 -_fileobject_uses_str_type = isinstance(socket._fileobject(None)._rbuf, basestring)
2263 +_fileobject_uses_str_type = isinstance(socket._fileobject(None)._rbuf, str)
2264
2265 import sys
2266 import threading
2267 import time
2268 import traceback
2269 -from urllib import unquote
2270 -from urlparse import urlparse
2271 +from urllib.parse import unquote
2272 +from urllib.parse import urlparse
2273 import warnings
2274
2275 try:
2276 @@ -117,7 +117,7 @@
2277 errno_names = dir(errno)
2278 nums = [getattr(errno, k) for k in errnames if k in errno_names]
2279 # de-dupe the list
2280 - return dict.fromkeys(nums).keys()
2281 + return list(dict.fromkeys(nums).keys())
2282
2283 socket_error_eintr = plat_specific_errors("EINTR", "WSAEINTR")
2284
2285 @@ -153,7 +153,7 @@
2286
2287 def __init__(self, apps):
2288 try:
2289 - apps = apps.items()
2290 + apps = list(apps.items())
2291 except AttributeError:
2292 pass
2293
2294 @@ -239,8 +239,8 @@
2295 def __iter__(self):
2296 return self
2297
2298 - def next(self):
2299 - data = self.rfile.next()
2300 + def __next__(self):
2301 + data = next(self.rfile)
2302 self.bytes_read += len(data)
2303 self._check_length()
2304 return data
2305 @@ -401,7 +401,7 @@
2306 # then all the http headers
2307 try:
2308 self.read_headers()
2309 - except ValueError, ex:
2310 + except ValueError as ex:
2311 self.simple_response("400 Bad Request", repr(ex.args))
2312 return
2313
2314 @@ -500,7 +500,7 @@
2315 def decode_chunked(self):
2316 """Decode the 'chunked' transfer coding."""
2317 cl = 0
2318 - data = StringIO.StringIO()
2319 + data = io.StringIO()
2320 while True:
2321 line = self.rfile.readline().strip().split(";", 1)
2322 chunk_size = int(line.pop(0), 16)
2323 @@ -592,7 +592,7 @@
2324
2325 try:
2326 self.wfile.sendall("".join(buf))
2327 - except socket.error, x:
2328 + except socket.error as x:
2329 if x.args[0] not in socket_errors_to_ignore:
2330 raise
2331
2332 @@ -609,7 +609,7 @@
2333 # exc_info tuple."
2334 if self.sent_headers:
2335 try:
2336 - raise exc_info[0], exc_info[1], exc_info[2]
2337 + raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
2338 finally:
2339 exc_info = None
2340
2341 @@ -728,7 +728,7 @@
2342 try:
2343 bytes_sent = self.send(data)
2344 data = data[bytes_sent:]
2345 - except socket.error, e:
2346 + except socket.error as e:
2347 if e.args[0] not in socket_errors_nonblocking:
2348 raise
2349
2350 @@ -745,7 +745,7 @@
2351 while True:
2352 try:
2353 return self._sock.recv(size)
2354 - except socket.error, e:
2355 + except socket.error as e:
2356 if (e.args[0] not in socket_errors_nonblocking
2357 and e.args[0] not in socket_error_eintr):
2358 raise
2359 @@ -762,7 +762,7 @@
2360 buf.seek(0, 2) # seek end
2361 if size < 0:
2362 # Read until EOF
2363 - self._rbuf = StringIO.StringIO() # reset _rbuf. we consume it via buf.
2364 + self._rbuf = io.StringIO() # reset _rbuf. we consume it via buf.
2365 while True:
2366 data = self.recv(rbufsize)
2367 if not data:
2368 @@ -776,11 +776,11 @@
2369 # Already have size bytes in our buffer? Extract and return.
2370 buf.seek(0)
2371 rv = buf.read(size)
2372 - self._rbuf = StringIO.StringIO()
2373 + self._rbuf = io.StringIO()
2374 self._rbuf.write(buf.read())
2375 return rv
2376
2377 - self._rbuf = StringIO.StringIO() # reset _rbuf. we consume it via buf.
2378 + self._rbuf = io.StringIO() # reset _rbuf. we consume it via buf.
2379 while True:
2380 left = size - buf_len
2381 # recv() will malloc the amount of memory given as its
2382 @@ -818,7 +818,7 @@
2383 buf.seek(0)
2384 bline = buf.readline(size)
2385 if bline.endswith('\n') or len(bline) == size:
2386 - self._rbuf = StringIO.StringIO()
2387 + self._rbuf = io.StringIO()
2388 self._rbuf.write(buf.read())
2389 return bline
2390 del bline
2391 @@ -828,7 +828,7 @@
2392 # Speed up unbuffered case
2393 buf.seek(0)
2394 buffers = [buf.read()]
2395 - self._rbuf = StringIO.StringIO() # reset _rbuf. we consume it via buf.
2396 + self._rbuf = io.StringIO() # reset _rbuf. we consume it via buf.
2397 data = None
2398 recv = self.recv
2399 while data != "\n":
2400 @@ -839,7 +839,7 @@
2401 return "".join(buffers)
2402
2403 buf.seek(0, 2) # seek end
2404 - self._rbuf = StringIO.StringIO() # reset _rbuf. we consume it via buf.
2405 + self._rbuf = io.StringIO() # reset _rbuf. we consume it via buf.
2406 while True:
2407 data = self.recv(self._rbufsize)
2408 if not data:
2409 @@ -860,10 +860,10 @@
2410 if buf_len >= size:
2411 buf.seek(0)
2412 rv = buf.read(size)
2413 - self._rbuf = StringIO.StringIO()
2414 + self._rbuf = io.StringIO()
2415 self._rbuf.write(buf.read())
2416 return rv
2417 - self._rbuf = StringIO.StringIO() # reset _rbuf. we consume it via buf.
2418 + self._rbuf = io.StringIO() # reset _rbuf. we consume it via buf.
2419 while True:
2420 data = self.recv(self._rbufsize)
2421 if not data:
2422 @@ -906,7 +906,7 @@
2423 try:
2424 bytes_sent = self.send(data)
2425 data = data[bytes_sent:]
2426 - except socket.error, e:
2427 + except socket.error as e:
2428 if e.args[0] not in socket_errors_nonblocking:
2429 raise
2430
2431 @@ -923,7 +923,7 @@
2432 while True:
2433 try:
2434 return self._sock.recv(size)
2435 - except socket.error, e:
2436 + except socket.error as e:
2437 if (e.args[0] not in socket_errors_nonblocking
2438 and e.args[0] not in socket_error_eintr):
2439 raise
2440 @@ -1065,7 +1065,7 @@
2441 time.sleep(self.ssl_retry)
2442 except SSL.WantWriteError:
2443 time.sleep(self.ssl_retry)
2444 - except SSL.SysCallError, e:
2445 + except SSL.SysCallError as e:
2446 if is_reader and e.args == (-1, 'Unexpected EOF'):
2447 return ""
2448
2449 @@ -1073,7 +1073,7 @@
2450 if is_reader and errnum in socket_errors_to_ignore:
2451 return ""
2452 raise socket.error(errnum)
2453 - except SSL.Error, e:
2454 + except SSL.Error as e:
2455 if is_reader and e.args == (-1, 'Unexpected EOF'):
2456 return ""
2457
2458 @@ -1175,7 +1175,7 @@
2459 if req.close_connection:
2460 return
2461
2462 - except socket.error, e:
2463 + except socket.error as e:
2464 errnum = e.args[0]
2465 if errnum == 'timed out':
2466 if req and not req.sent_headers:
2467 @@ -1187,7 +1187,7 @@
2468 return
2469 except (KeyboardInterrupt, SystemExit):
2470 raise
2471 - except FatalSSLAlert, e:
2472 + except FatalSSLAlert as e:
2473 # Close the connection.
2474 return
2475 except NoSSLError:
2476 @@ -1198,7 +1198,7 @@
2477 "The client sent a plain HTTP request, but "
2478 "this server only speaks HTTPS on this port.")
2479 self.linger = True
2480 - except Exception, e:
2481 + except Exception as e:
2482 if req and not req.sent_headers:
2483 req.simple_response("500 Internal Server Error", format_exc())
2484
2485 @@ -1272,7 +1272,7 @@
2486 finally:
2487 conn.close()
2488 self.conn = None
2489 - except (KeyboardInterrupt, SystemExit), exc:
2490 + except (KeyboardInterrupt, SystemExit) as exc:
2491 self.server.interrupt = exc
2492
2493
2494 @@ -1288,12 +1288,12 @@
2495 self.min = min
2496 self.max = max
2497 self._threads = []
2498 - self._queue = Queue.Queue()
2499 + self._queue = queue.Queue()
2500 self.get = self._queue.get
2501
2502 def start(self):
2503 """Start the pool of threads."""
2504 - for i in xrange(self.min):
2505 + for i in range(self.min):
2506 self._threads.append(WorkerThread(self.server))
2507 for worker in self._threads:
2508 worker.setName("CP WSGIServer " + worker.getName())
2509 @@ -1314,7 +1314,7 @@
2510
2511 def grow(self, amount):
2512 """Spawn new worker threads (not above self.max)."""
2513 - for i in xrange(amount):
2514 + for i in range(amount):
2515 if self.max > 0 and len(self._threads) >= self.max:
2516 break
2517 worker = WorkerThread(self.server)
2518 @@ -1332,7 +1332,7 @@
2519 amount -= 1
2520
2521 if amount > 0:
2522 - for i in xrange(min(amount, len(self._threads) - self.min)):
2523 + for i in range(min(amount, len(self._threads) - self.min)):
2524 # Put a number of shutdown requests on the queue equal
2525 # to 'amount'. Once each of those is processed by a worker,
2526 # that worker will terminate and be culled from our list
2527 @@ -1369,7 +1369,7 @@
2528 except (AssertionError,
2529 # Ignore repeated Ctrl-C.
2530 # See http://www.cherrypy.org/ticket/691.
2531 - KeyboardInterrupt), exc1:
2532 + KeyboardInterrupt) as exc1:
2533 pass
2534
2535
2536 @@ -1392,13 +1392,13 @@
2537 'sock_shutdown', 'get_peer_certificate', 'want_read',
2538 'want_write', 'set_connect_state', 'set_accept_state',
2539 'connect_ex', 'sendall', 'settimeout'):
2540 - exec """def %s(self, *args):
2541 + exec("""def %s(self, *args):
2542 self._lock.acquire()
2543 try:
2544 return self._ssl_conn.%s(*args)
2545 finally:
2546 self._lock.release()
2547 -""" % (f, f)
2548 +""" % (f, f))
2549
2550
2551 try:
2552 @@ -1557,7 +1557,7 @@
2553 self._interrupt = None
2554
2555 # Select the appropriate socket
2556 - if isinstance(self.bind_addr, basestring):
2557 + if isinstance(self.bind_addr, str):
2558 # AF_UNIX socket
2559
2560 # So we can reuse the socket...
2561 @@ -1565,7 +1565,7 @@
2562 except: pass
2563
2564 # So everyone can access the socket...
2565 - try: os.chmod(self.bind_addr, 0777)
2566 + try: os.chmod(self.bind_addr, 0o777)
2567 except: pass
2568
2569 info = [(socket.AF_UNIX, socket.SOCK_STREAM, 0, "", self.bind_addr)]
2570 @@ -1586,14 +1586,14 @@
2571 af, socktype, proto, canonname, sa = res
2572 try:
2573 self.bind(af, socktype, proto)
2574 - except socket.error, msg:
2575 + except socket.error as msg:
2576 if self.socket:
2577 self.socket.close()
2578 self.socket = None
2579 continue
2580 break
2581 if not self.socket:
2582 - raise socket.error, msg
2583 + raise socket.error(msg)
2584
2585 # Timeout so KeyboardInterrupt can be caught on Win32
2586 self.socket.settimeout(1)
2587 @@ -1632,7 +1632,7 @@
2588
2589 # If listening on the IPV6 any address ('::' = IN6ADDR_ANY),
2590 # activate dual-stack. See http://www.cherrypy.org/ticket/871.
2591 - if (not isinstance(self.bind_addr, basestring)
2592 + if (not isinstance(self.bind_addr, str)
2593 and self.bind_addr[0] == '::' and family == socket.AF_INET6):
2594 try:
2595 self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
2596 @@ -1664,7 +1664,7 @@
2597 environ["ACTUAL_SERVER_PROTOCOL"] = self.protocol
2598 environ["SERVER_NAME"] = self.server_name
2599
2600 - if isinstance(self.bind_addr, basestring):
2601 + if isinstance(self.bind_addr, str):
2602 # AF_UNIX. This isn't really allowed by WSGI, which doesn't
2603 # address unix domain sockets. But it's better than nothing.
2604 environ["SERVER_PORT"] = ""
2605 @@ -1682,7 +1682,7 @@
2606 # notice keyboard interrupts on Win32, which don't interrupt
2607 # accept() by default
2608 return
2609 - except socket.error, x:
2610 + except socket.error as x:
2611 if x.args[0] in socket_error_eintr:
2612 # I *think* this is right. EINTR should occur when a signal
2613 # is received during the accept() call; all docs say retry
2614 @@ -1715,11 +1715,11 @@
2615
2616 sock = getattr(self, "socket", None)
2617 if sock:
2618 - if not isinstance(self.bind_addr, basestring):
2619 + if not isinstance(self.bind_addr, str):
2620 # Touch our own socket to make accept() return immediately.
2621 try:
2622 host, port = sock.getsockname()[:2]
2623 - except socket.error, x:
2624 + except socket.error as x:
2625 if x.args[0] not in socket_errors_to_ignore:
2626 raise
2627 else:
2628 diff -Naur client175_0.7-original/covers.py client175_0.7/covers.py
2629 --- client175_0.7-original/covers.py 2011-04-02 03:51:24.000000000 +0200
2630 +++ client175_0.7/covers.py 2021-08-03 14:39:46.713265947 +0200
2631 @@ -23,7 +23,7 @@
2632 # Exaile (http://www.exaile.org/).
2633
2634
2635 -import hashlib, re, urllib, os, time, shutil, threading
2636 +import hashlib, re, urllib.request, urllib.parse, urllib.error, os, time, shutil, threading
2637 from xml.etree import ElementTree as ET
2638 from datetime import datetime, timedelta
2639
2640 @@ -76,7 +76,7 @@
2641
2642 def _findMusicBrainz(self, vars):
2643 self._delay('last_MB_lookup')
2644 - data = urllib.urlopen(self.urlMB % vars).read()
2645 + data = urllib.request.urlopen(self.urlMB % vars).read()
2646 m = self.regexMB.search(data)
2647 if not m:
2648 return False
2649 @@ -85,7 +85,7 @@
2650 url = "http://images.amazon.com/images/P/%s.01.%sZZZZZZZ.jpg"
2651 for sz in ['L', 'M']:
2652 image = url % (asin, sz)
2653 - h = urllib.urlopen(image)
2654 + h = urllib.request.urlopen(image)
2655 data = h.read()
2656 h.close()
2657 if len(data) > 1000:
2658 @@ -95,21 +95,21 @@
2659
2660 def _findLastFM_album(self, vars):
2661 self._delay('last_FM_lookup')
2662 - data = urllib.urlopen(self.urlFM % vars).read()
2663 + data = urllib.request.urlopen(self.urlFM % vars).read()
2664 x = ET.XML(data)
2665 if len(x) == 0:
2666 - print 'LASTFM SEARCH: ERROR PARSING LASTFM DATA!'
2667 + print('LASTFM SEARCH: ERROR PARSING LASTFM DATA!')
2668 return False
2669
2670 c = x.find('coverart')
2671 if len(c) == 0:
2672 - print 'LASTFM SEARCH: NO COVERART NODE IN LASTFM DATA!'
2673 + print('LASTFM SEARCH: NO COVERART NODE IN LASTFM DATA!')
2674 return False
2675
2676 for sz in ['large', 'medium', 'small']:
2677 image = c.findtext(sz, '')
2678 if image > '' and not image.lower().endswith('.gif'):
2679 - h = urllib.urlopen(image)
2680 + h = urllib.request.urlopen(image)
2681 data = h.read()
2682 h.close()
2683 if hashlib.sha1(data).hexdigest() != "57b2c37343f711c94e83a37bd91bc4d18d2ed9d5":
2684 @@ -120,13 +120,13 @@
2685
2686 def _findLastFM_artist(self, vars):
2687 self._delay('last_FM_lookup')
2688 - data = urllib.urlopen(self.urlFM_artist % vars['artist']).read()
2689 + data = urllib.request.urlopen(self.urlFM_artist % vars['artist']).read()
2690 m = self.regexFM_artist.search(data)
2691 if m:
2692 image = m.group(1)
2693 if image.lower().endswith('.gif'):
2694 return False
2695 - h = urllib.urlopen(image)
2696 + h = urllib.request.urlopen(image)
2697 data = h.read()
2698 h.close()
2699 if hashlib.sha1(data).hexdigest() != "57b2c37343f711c94e83a37bd91bc4d18d2ed9d5":
2700 @@ -147,8 +147,8 @@
2701 try:
2702 shutil.copy2(coverpath, cover_destination)
2703 except IOError:
2704 - print "Could not save cover to: " + cover_destination
2705 - print "For best performance, please ensure that the directory exists and is writable."
2706 + print("Could not save cover to: " + cover_destination)
2707 + print("For best performance, please ensure that the directory exists and is writable.")
2708 h = open(coverpath, 'r')
2709 data = h.read()
2710 h.close()
2711 @@ -175,8 +175,8 @@
2712 return covername, None
2713
2714 vars = {
2715 - 'album': urllib.quote_plus(album.encode("utf-8")),
2716 - 'artist': urllib.quote_plus(artist.encode("utf-8"))
2717 + 'album': urllib.parse.quote_plus(album.encode("utf-8")),
2718 + 'artist': urllib.parse.quote_plus(artist.encode("utf-8"))
2719 }
2720
2721 for fn in lookups:
2722 @@ -188,8 +188,8 @@
2723 h.write(data)
2724 h.close()
2725 except:
2726 - print "Could not save cover to: " + coverpath
2727 - print "For best performance, please ensure that the directory exists and is writable."
2728 + print("Could not save cover to: " + coverpath)
2729 + print("For best performance, please ensure that the directory exists and is writable.")
2730 covername = ""
2731 return covername, data
2732 except:
2733 diff -Naur client175_0.7-original/lyricwiki.py client175_0.7/lyricwiki.py
2734 --- client175_0.7-original/lyricwiki.py 2010-11-20 18:43:24.000000000 +0100
2735 +++ client175_0.7/lyricwiki.py 2021-08-03 14:40:00.301064572 +0200
2736 @@ -18,7 +18,7 @@
2737 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
2738 # MA 02110-1301, USA.
2739
2740 -import json, urllib, os, hashlib, time
2741 +import json, urllib.request, urllib.parse, urllib.error, os, hashlib, time
2742
2743 def _download(args):
2744 """
2745 @@ -31,9 +31,9 @@
2746 for key in args:
2747 str_args[key] = args[key].encode("utf-8")
2748
2749 - args = urllib.urlencode(str_args)
2750 + args = urllib.parse.urlencode(str_args)
2751
2752 - return urllib.urlopen(base + args).read()
2753 + return urllib.request.urlopen(base + args).read()
2754
2755 def _get_page_titles(artist, title):
2756 """
2757 diff -Naur client175_0.7-original/metadata/_base.py client175_0.7/metadata/_base.py
2758 --- client175_0.7-original/metadata/_base.py 2010-05-01 21:15:15.000000000 +0200
2759 +++ client175_0.7/metadata/_base.py 2021-08-03 14:51:24.062763658 +0200
2760 @@ -66,7 +66,7 @@
2761 self.mutagen = None
2762 self.load()
2763 self._reverse_mapping = dict((
2764 - (v,k) for k,v in self.tag_mapping.iteritems() ))
2765 + (v,k) for k,v in self.tag_mapping.items() ))
2766
2767 def load(self):
2768 """
2769 @@ -99,7 +99,7 @@
2770
2771 def _get_keys(self):
2772 keys = []
2773 - for k in self._get_raw().keys():
2774 + for k in list(self._get_raw().keys()):
2775 if k in self._reverse_mapping:
2776 keys.append(self._reverse_mapping[k])
2777 else:
2778 @@ -149,11 +149,11 @@
2779 if t == None and tag in self.tag_mapping:
2780 try:
2781 t = self._get_tag(raw, self.tag_mapping[tag])
2782 - if type(t) in [str, unicode]:
2783 + if type(t) in [str, str]:
2784 t = [t]
2785 else:
2786 try:
2787 - t = [unicode(u) for u in list(t)]
2788 + t = [str(u) for u in list(t)]
2789 except UnicodeDecodeError:
2790 t = t
2791 except (KeyError, TypeError):
2792 @@ -161,10 +161,10 @@
2793 if t == None and self.others:
2794 try:
2795 t = self._get_tag(raw, tag)
2796 - if type(t) in [str, unicode]:
2797 + if type(t) in [str, str]:
2798 t = [t]
2799 else:
2800 - t = [unicode(u) for u in list(t)]
2801 + t = [str(u) for u in list(t)]
2802 except (KeyError, TypeError):
2803 pass
2804
2805 @@ -207,7 +207,7 @@
2806 pass
2807
2808 # tags starting with __ are internal and should not be written
2809 - for tag in tagdict.keys():
2810 + for tag in list(tagdict.keys()):
2811 if tag.startswith("__"):
2812 try:
2813 del tagdict[tag]
2814 diff -Naur client175_0.7-original/metadata/_id3.py client175_0.7/metadata/_id3.py
2815 --- client175_0.7-original/metadata/_id3.py 2010-05-04 23:50:41.000000000 +0200
2816 +++ client175_0.7/metadata/_id3.py 2021-08-03 14:51:42.866483930 +0200
2817 @@ -70,7 +70,7 @@
2818
2819 def _get_tag(self, raw, t):
2820 if not raw.tags: return []
2821 - if t not in self.tag_mapping.itervalues():
2822 + if t not in iter(self.tag_mapping.values()):
2823 t = "TXXX:" + t
2824 field = raw.tags.getall(t)
2825 if len(field) <= 0:
2826 @@ -78,27 +78,27 @@
2827 ret = []
2828 if t == 'TDRC' or t == 'TDOR': # values are ID3TimeStamps
2829 for value in field:
2830 - ret.extend([unicode(x) for x in value.text])
2831 + ret.extend([str(x) for x in value.text])
2832 elif t == 'USLT': # Lyrics are stored in plain old strings
2833 for value in field:
2834 - ret.append(unicode(value.text))
2835 + ret.append(str(value.text))
2836 elif t == 'WOAR': # URLS are stored in url not text
2837 for value in field:
2838 - ret.extend([unicode(x.replace('\n','').replace('\r','')) \
2839 + ret.extend([str(x.replace('\n','').replace('\r','')) \
2840 for x in value.url])
2841 elif t == 'APIC':
2842 ret = [x.data for x in field]
2843 else:
2844 for value in field:
2845 try:
2846 - ret.extend([unicode(x.replace('\n','').replace('\r','')) \
2847 + ret.extend([str(x.replace('\n','').replace('\r','')) \
2848 for x in value.text])
2849 except:
2850 pass
2851 return ret
2852
2853 def _set_tag(self, raw, tag, data):
2854 - if tag not in self.tag_mapping.itervalues():
2855 + if tag not in iter(self.tag_mapping.values()):
2856 tag = "TXXX:" + tag
2857 if raw.tags is not None:
2858 raw.tags.delall(tag)
2859 @@ -107,7 +107,7 @@
2860 raw.tags.add(frame)
2861
2862 def _del_tag(self, raw, tag):
2863 - if tag not in self.tag_mapping.itervalues():
2864 + if tag not in iter(self.tag_mapping.values()):
2865 tag = "TXXX:" + tag
2866 if raw.tags is not None:
2867 raw.tags.delall(tag)
2868 diff -Naur client175_0.7-original/metadata/__init__.py client175_0.7/metadata/__init__.py
2869 --- client175_0.7-original/metadata/__init__.py 2010-05-01 21:15:15.000000000 +0200
2870 +++ client175_0.7/metadata/__init__.py 2021-08-03 14:50:50.391263894 +0200
2871 @@ -30,7 +30,7 @@
2872 import os
2873
2874 from metadata._base import BaseFormat, NotWritable, NotReadable
2875 -import urlparse
2876 +import urllib.parse
2877
2878 from metadata import (ape, asf, flac, mod, mp3, mp4, mpc, ogg, sid, speex,
2879 tta, wav, wv)
2880 diff -Naur client175_0.7-original/metadata/mp4.py client175_0.7/metadata/mp4.py
2881 --- client175_0.7-original/metadata/mp4.py 2010-05-01 21:15:15.000000000 +0200
2882 +++ client175_0.7/metadata/mp4.py 2021-08-03 14:52:08.706100110 +0200
2883 @@ -45,7 +45,7 @@
2884 writable = True
2885
2886 def _get_tag(self, f, name):
2887 - if not f.has_key(name):
2888 + if name not in f:
2889 return []
2890 elif name in ['trkn', 'disk']:
2891 ret = []
2892 @@ -60,7 +60,7 @@
2893 try:
2894 f[name] = []
2895 for val in value:
2896 - tmp = map(int, val.split('/'))
2897 + tmp = list(map(int, val.split('/')))
2898 f[name].append(tuple(tmp))
2899 except TypeError:
2900 pass
2901 diff -Naur client175_0.7-original/mpd.py client175_0.7/mpd.py
2902 --- client175_0.7-original/mpd.py 2010-08-27 00:38:39.000000000 +0200
2903 +++ client175_0.7/mpd.py 2021-08-03 14:40:15.808834774 +0200
2904 @@ -64,7 +64,7 @@
2905
2906
2907 def extend_database(item):
2908 - keys = item.keys()
2909 + keys = list(item.keys())
2910 if 'file' in keys:
2911 item = extend_file(item)
2912 elif 'directory' in keys:
2913 @@ -192,8 +192,8 @@
2914 self.lock.acquire()
2915 try:
2916 return self._execute(command, args, retval)
2917 - except (ConnectionError, socket.error), e:
2918 - print "%s\n reconnecting..." % e
2919 + except (ConnectionError, socket.error) as e:
2920 + print("%s\n reconnecting..." % e)
2921 try:
2922 self.disconnect()
2923 except:
2924 @@ -343,13 +343,13 @@
2925 raise StopIteration
2926
2927 def _fetch_songs(self):
2928 - return map(extend_file, self._read_songs())
2929 + return list(map(extend_file, self._read_songs()))
2930
2931 def _fetch_playlists(self):
2932 return self._fetch_objects(["playlist"])
2933
2934 def _fetch_database(self):
2935 - return map(extend_database, self._read_objects(["file", "directory", "playlist"]))
2936 + return list(map(extend_database, self._read_objects(["file", "directory", "playlist"])))
2937
2938 def _fetch_outputs(self):
2939 return self._fetch_objects(["outputid"])
2940 @@ -397,7 +397,7 @@
2941 try:
2942 sock = socket.socket(af, socktype, proto)
2943 sock.connect(sa)
2944 - except socket.error, msg:
2945 + except socket.error as msg:
2946 if sock:
2947 sock.close()
2948 sock = None
2949 @@ -425,8 +425,8 @@
2950 self.password(_password)
2951 self._TAGS = self.tagtypes()
2952 self._TAGS.extend(['Pos', 'Time', 'Id'])
2953 - self._TAGS_LOWER = map(str.lower, self._TAGS)
2954 - self._TAGMAP = dict(zip(self._TAGS, self._TAGS_LOWER))
2955 + self._TAGS_LOWER = list(map(str.lower, self._TAGS))
2956 + self._TAGMAP = dict(list(zip(self._TAGS, self._TAGS_LOWER)))
2957 except:
2958 self.disconnect()
2959 raise
2960 diff -Naur client175_0.7-original/mutagen/apev2.py client175_0.7/mutagen/apev2.py
2961 --- client175_0.7-original/mutagen/apev2.py 2010-05-15 00:42:14.000000000 +0200
2962 +++ client175_0.7/mutagen/apev2.py 2021-08-03 14:53:33.292843836 +0200
2963 @@ -33,7 +33,7 @@
2964 __all__ = ["APEv2", "APEv2File", "Open", "delete"]
2965
2966 import struct
2967 -from cStringIO import StringIO
2968 +from io import StringIO
2969
2970 def is_valid_apev2_key(key):
2971 return (2 <= len(key) <= 255 and min(key) >= ' ' and max(key) <= '~' and
2972 @@ -44,11 +44,11 @@
2973 # 1: Item contains binary information
2974 # 2: Item is a locator of external stored information [e.g. URL]
2975 # 3: reserved"
2976 -TEXT, BINARY, EXTERNAL = range(3)
2977 +TEXT, BINARY, EXTERNAL = list(range(3))
2978
2979 -HAS_HEADER = 1L << 31
2980 -HAS_NO_FOOTER = 1L << 30
2981 -IS_HEADER = 1L << 29
2982 +HAS_HEADER = 1 << 31
2983 +HAS_NO_FOOTER = 1 << 30
2984 +IS_HEADER = 1 << 29
2985
2986 class error(IOError): pass
2987 class APENoHeaderError(error, ValueError): pass
2988 @@ -199,7 +199,7 @@
2989
2990 def pprint(self):
2991 """Return tag key=value pairs in a human-readable format."""
2992 - items = self.items()
2993 + items = list(self.items())
2994 items.sort()
2995 return "\n".join(["%s=%s" % (k, v.pprint()) for k, v in items])
2996
2997 @@ -271,7 +271,7 @@
2998
2999 if not isinstance(value, _APEValue):
3000 # let's guess at the content if we're not already a value...
3001 - if isinstance(value, unicode):
3002 + if isinstance(value, str):
3003 # unicode? we've got to be text.
3004 value = APEValue(utf8(value), TEXT)
3005 elif isinstance(value, list):
3006 @@ -289,7 +289,7 @@
3007 self.__dict[key.lower()] = value
3008
3009 def keys(self):
3010 - return [self.__casemap.get(key, key) for key in self.__dict.keys()]
3011 + return [self.__casemap.get(key, key) for key in list(self.__dict.keys())]
3012
3013 def save(self, filename=None):
3014 """Save changes to a file.
3015 @@ -318,7 +318,7 @@
3016 # "APE tags items should be sorted ascending by size... This is
3017 # not a MUST, but STRONGLY recommended. Actually the items should
3018 # be sorted by importance/byte, but this is not feasible."
3019 - tags = [v._internal(k) for k, v in self.items()]
3020 + tags = [v._internal(k) for k, v in list(self.items())]
3021 tags.sort(lambda a, b: cmp(len(a), len(b)))
3022 num_tags = len(tags)
3023 tags = "".join(tags)
3024 @@ -401,20 +401,20 @@
3025 strings (with a null seperating the values), or arrays of strings."""
3026
3027 def __unicode__(self):
3028 - return unicode(str(self), "utf-8")
3029 + return str(str(self), "utf-8")
3030
3031 def __iter__(self):
3032 """Iterate over the strings of the value (not the characters)"""
3033 - return iter(unicode(self).split("\0"))
3034 + return iter(str(self).split("\0"))
3035
3036 def __getitem__(self, index):
3037 - return unicode(self).split("\0")[index]
3038 + return str(self).split("\0")[index]
3039
3040 def __len__(self):
3041 return self.value.count("\0") + 1
3042
3043 def __cmp__(self, other):
3044 - return cmp(unicode(self), other)
3045 + return cmp(str(self), other)
3046
3047 def __setitem__(self, index, value):
3048 values = list(self)
3049 @@ -434,7 +434,7 @@
3050
3051 External values are usually URI or IRI strings.
3052 """
3053 - def pprint(self): return "[External] %s" % unicode(self)
3054 + def pprint(self): return "[External] %s" % str(self)
3055
3056 class APEv2File(FileType):
3057 class _Info(object):
3058 diff -Naur client175_0.7-original/mutagen/asf.py client175_0.7/mutagen/asf.py
3059 --- client175_0.7-original/mutagen/asf.py 2010-05-15 00:42:14.000000000 +0200
3060 +++ client175_0.7/mutagen/asf.py 2021-08-03 14:53:40.512736644 +0200
3061 @@ -49,14 +49,14 @@
3062
3063 """
3064 values = [value for (k, value) in self if k == key]
3065 - if not values: raise KeyError, key
3066 + if not values: raise KeyError(key)
3067 else: return values
3068
3069 def __delitem__(self, key):
3070 """Delete all values associated with the key."""
3071 - to_delete = filter(lambda x: x[0] == key, self)
3072 - if not to_delete: raise KeyError, key
3073 - else: map(self.remove, to_delete)
3074 + to_delete = [x for x in self if x[0] == key]
3075 + if not to_delete: raise KeyError(key)
3076 + else: list(map(self.remove, to_delete))
3077
3078 def __contains__(self, key):
3079 """Return true if the key has any values."""
3080 @@ -78,15 +78,15 @@
3081 except KeyError: pass
3082 for value in values:
3083 if key in _standard_attribute_names:
3084 - value = unicode(value)
3085 + value = str(value)
3086 elif not isinstance(value, ASFBaseAttribute):
3087 - if isinstance(value, basestring):
3088 + if isinstance(value, str):
3089 value = ASFUnicodeAttribute(value)
3090 elif isinstance(value, bool):
3091 value = ASFBoolAttribute(value)
3092 elif isinstance(value, int):
3093 value = ASFDWordAttribute(value)
3094 - elif isinstance(value, long):
3095 + elif isinstance(value, int):
3096 value = ASFQWordAttribute(value)
3097 self.append((key, value))
3098
3099 @@ -162,7 +162,7 @@
3100 return self.value
3101
3102 def __cmp__(self, other):
3103 - return cmp(unicode(self), other)
3104 + return cmp(str(self), other)
3105
3106
3107 class ASFByteArrayAttribute(ASFBaseAttribute):
3108 @@ -294,7 +294,7 @@
3109 GUID = ASFGUIDAttribute.TYPE
3110
3111 def ASFValue(value, kind, **kwargs):
3112 - for t, c in _attribute_types.items():
3113 + for t, c in list(_attribute_types.items()):
3114 if kind == t:
3115 return c(value=value, **kwargs)
3116 raise ValueError("Unknown value type")
3117 @@ -362,12 +362,12 @@
3118 texts.append(None)
3119 pos = end
3120 title, author, copyright, desc, rating = texts
3121 - for key, value in dict(
3122 + for key, value in list(dict(
3123 Title=title,
3124 Author=author,
3125 Copyright=copyright,
3126 Description=desc,
3127 - Rating=rating).items():
3128 + Rating=rating).items()):
3129 if value is not None:
3130 asf.tags[key] = value
3131
3132 @@ -378,8 +378,8 @@
3133 return value[0].encode("utf-16-le") + "\x00\x00"
3134 else:
3135 return ""
3136 - texts = map(render_text, _standard_attribute_names)
3137 - data = struct.pack("<HHHHH", *map(len, texts)) + "".join(texts)
3138 + texts = list(map(render_text, _standard_attribute_names))
3139 + data = struct.pack("<HHHHH", *list(map(len, texts))) + "".join(texts)
3140 return self.GUID + struct.pack("<Q", 24 + len(data)) + data
3141
3142
3143 @@ -405,7 +405,7 @@
3144 asf.tags.append((name, attr))
3145
3146 def render(self, asf):
3147 - attrs = asf.to_extended_content_description.items()
3148 + attrs = list(asf.to_extended_content_description.items())
3149 data = "".join([attr.render(name) for (name, attr) in attrs])
3150 data = struct.pack("<QH", 26 + len(data), len(attrs)) + data
3151 return self.GUID + data
3152 @@ -485,7 +485,7 @@
3153 asf.tags.append((name, attr))
3154
3155 def render(self, asf):
3156 - attrs = asf.to_metadata.items()
3157 + attrs = list(asf.to_metadata.items())
3158 data = "".join([attr.render_m(name) for (name, attr) in attrs])
3159 return (self.GUID + struct.pack("<QH", 26 + len(data), len(attrs)) +
3160 data)
3161 @@ -614,7 +614,7 @@
3162 def __read_file(self, fileobj):
3163 header = fileobj.read(30)
3164 if len(header) != 30 or header[:16] != HeaderObject.GUID:
3165 - raise ASFHeaderError, "Not an ASF file."
3166 + raise ASFHeaderError("Not an ASF file.")
3167
3168 self.extended_content_description_obj = None
3169 self.content_description_obj = None
3170 diff -Naur client175_0.7-original/mutagen/_constants.py client175_0.7/mutagen/_constants.py
3171 --- client175_0.7-original/mutagen/_constants.py 2010-05-15 00:42:14.000000000 +0200
3172 +++ client175_0.7/mutagen/_constants.py 2021-08-03 14:54:27.292044501 +0200
3173 @@ -1,153 +1,153 @@
3174 """Constants used by Mutagen."""
3175
3176 GENRES = [
3177 - u"Blues",
3178 - u"Classic Rock",
3179 - u"Country",
3180 - u"Dance",
3181 - u"Disco",
3182 - u"Funk",
3183 - u"Grunge",
3184 - u"Hip-Hop",
3185 - u"Jazz",
3186 - u"Metal",
3187 - u"New Age",
3188 - u"Oldies",
3189 - u"Other",
3190 - u"Pop",
3191 - u"R&B",
3192 - u"Rap",
3193 - u"Reggae",
3194 - u"Rock",
3195 - u"Techno",
3196 - u"Industrial",
3197 - u"Alternative",
3198 - u"Ska",
3199 - u"Death Metal",
3200 - u"Pranks",
3201 - u"Soundtrack",
3202 - u"Euro-Techno",
3203 - u"Ambient",
3204 - u"Trip-Hop",
3205 - u"Vocal",
3206 - u"Jazz+Funk",
3207 - u"Fusion",
3208 - u"Trance",
3209 - u"Classical",
3210 - u"Instrumental",
3211 - u"Acid",
3212 - u"House",
3213 - u"Game",
3214 - u"Sound Clip",
3215 - u"Gospel",
3216 - u"Noise",
3217 - u"Alt. Rock",
3218 - u"Bass",
3219 - u"Soul",
3220 - u"Punk",
3221 - u"Space",
3222 - u"Meditative",
3223 - u"Instrumental Pop",
3224 - u"Instrumental Rock",
3225 - u"Ethnic",
3226 - u"Gothic",
3227 - u"Darkwave",
3228 - u"Techno-Industrial",
3229 - u"Electronic",
3230 - u"Pop-Folk",
3231 - u"Eurodance",
3232 - u"Dream",
3233 - u"Southern Rock",
3234 - u"Comedy",
3235 - u"Cult",
3236 - u"Gangsta",
3237 - u"Top 40",
3238 - u"Christian Rap",
3239 - u"Pop/Funk",
3240 - u"Jungle",
3241 - u"Native American",
3242 - u"Cabaret",
3243 - u"New Wave",
3244 - u"Psychadelic",
3245 - u"Rave",
3246 - u"Showtunes",
3247 - u"Trailer",
3248 - u"Lo-Fi",
3249 - u"Tribal",
3250 - u"Acid Punk",
3251 - u"Acid Jazz",
3252 - u"Polka",
3253 - u"Retro",
3254 - u"Musical",
3255 - u"Rock & Roll",
3256 - u"Hard Rock",
3257 - u"Folk",
3258 - u"Folk/Rock",
3259 - u"National Folk",
3260 - u"Swing",
3261 - u"Fusion",
3262 - u"Bebob",
3263 - u"Latin",
3264 - u"Revival",
3265 - u"Celtic",
3266 - u"Bluegrass",
3267 - u"Avantgarde",
3268 - u"Gothic Rock",
3269 - u"Progressive Rock",
3270 - u"Psychadelic Rock",
3271 - u"Symphonic Rock",
3272 - u"Slow Rock",
3273 - u"Big Band",
3274 - u"Chorus",
3275 - u"Easy Listening",
3276 - u"Acoustic",
3277 - u"Humour",
3278 - u"Speech",
3279 - u"Chanson",
3280 - u"Opera",
3281 - u"Chamber Music",
3282 - u"Sonata",
3283 - u"Symphony",
3284 - u"Booty Bass",
3285 - u"Primus",
3286 - u"Porn Groove",
3287 - u"Satire",
3288 - u"Slow Jam",
3289 - u"Club",
3290 - u"Tango",
3291 - u"Samba",
3292 - u"Folklore",
3293 - u"Ballad",
3294 - u"Power Ballad",
3295 - u"Rhythmic Soul",
3296 - u"Freestyle",
3297 - u"Duet",
3298 - u"Punk Rock",
3299 - u"Drum Solo",
3300 - u"A Capella",
3301 - u"Euro-House",
3302 - u"Dance Hall",
3303 - u"Goa",
3304 - u"Drum & Bass",
3305 - u"Club-House",
3306 - u"Hardcore",
3307 - u"Terror",
3308 - u"Indie",
3309 - u"BritPop",
3310 - u"Negerpunk",
3311 - u"Polsk Punk",
3312 - u"Beat",
3313 - u"Christian Gangsta Rap",
3314 - u"Heavy Metal",
3315 - u"Black Metal",
3316 - u"Crossover",
3317 - u"Contemporary Christian",
3318 - u"Christian Rock",
3319 - u"Merengue",
3320 - u"Salsa",
3321 - u"Thrash Metal",
3322 - u"Anime",
3323 - u"Jpop",
3324 - u"Synthpop"
3325 + "Blues",
3326 + "Classic Rock",
3327 + "Country",
3328 + "Dance",
3329 + "Disco",
3330 + "Funk",
3331 + "Grunge",
3332 + "Hip-Hop",
3333 + "Jazz",
3334 + "Metal",
3335 + "New Age",
3336 + "Oldies",
3337 + "Other",
3338 + "Pop",
3339 + "R&B",
3340 + "Rap",
3341 + "Reggae",
3342 + "Rock",
3343 + "Techno",
3344 + "Industrial",
3345 + "Alternative",
3346 + "Ska",
3347 + "Death Metal",
3348 + "Pranks",
3349 + "Soundtrack",
3350 + "Euro-Techno",
3351 + "Ambient",
3352 + "Trip-Hop",
3353 + "Vocal",
3354 + "Jazz+Funk",
3355 + "Fusion",
3356 + "Trance",
3357 + "Classical",
3358 + "Instrumental",
3359 + "Acid",
3360 + "House",
3361 + "Game",
3362 + "Sound Clip",
3363 + "Gospel",
3364 + "Noise",
3365 + "Alt. Rock",
3366 + "Bass",
3367 + "Soul",
3368 + "Punk",
3369 + "Space",
3370 + "Meditative",
3371 + "Instrumental Pop",
3372 + "Instrumental Rock",
3373 + "Ethnic",
3374 + "Gothic",
3375 + "Darkwave",
3376 + "Techno-Industrial",
3377 + "Electronic",
3378 + "Pop-Folk",
3379 + "Eurodance",
3380 + "Dream",
3381 + "Southern Rock",
3382 + "Comedy",
3383 + "Cult",
3384 + "Gangsta",
3385 + "Top 40",
3386 + "Christian Rap",
3387 + "Pop/Funk",
3388 + "Jungle",
3389 + "Native American",
3390 + "Cabaret",
3391 + "New Wave",
3392 + "Psychadelic",
3393 + "Rave",
3394 + "Showtunes",
3395 + "Trailer",
3396 + "Lo-Fi",
3397 + "Tribal",
3398 + "Acid Punk",
3399 + "Acid Jazz",
3400 + "Polka",
3401 + "Retro",
3402 + "Musical",
3403 + "Rock & Roll",
3404 + "Hard Rock",
3405 + "Folk",
3406 + "Folk/Rock",
3407 + "National Folk",
3408 + "Swing",
3409 + "Fusion",
3410 + "Bebob",
3411 + "Latin",
3412 + "Revival",
3413 + "Celtic",
3414 + "Bluegrass",
3415 + "Avantgarde",
3416 + "Gothic Rock",
3417 + "Progressive Rock",
3418 + "Psychadelic Rock",
3419 + "Symphonic Rock",
3420 + "Slow Rock",
3421 + "Big Band",
3422 + "Chorus",
3423 + "Easy Listening",
3424 + "Acoustic",
3425 + "Humour",
3426 + "Speech",
3427 + "Chanson",
3428 + "Opera",
3429 + "Chamber Music",
3430 + "Sonata",
3431 + "Symphony",
3432 + "Booty Bass",
3433 + "Primus",
3434 + "Porn Groove",
3435 + "Satire",
3436 + "Slow Jam",
3437 + "Club",
3438 + "Tango",
3439 + "Samba",
3440 + "Folklore",
3441 + "Ballad",
3442 + "Power Ballad",
3443 + "Rhythmic Soul",
3444 + "Freestyle",
3445 + "Duet",
3446 + "Punk Rock",
3447 + "Drum Solo",
3448 + "A Capella",
3449 + "Euro-House",
3450 + "Dance Hall",
3451 + "Goa",
3452 + "Drum & Bass",
3453 + "Club-House",
3454 + "Hardcore",
3455 + "Terror",
3456 + "Indie",
3457 + "BritPop",
3458 + "Negerpunk",
3459 + "Polsk Punk",
3460 + "Beat",
3461 + "Christian Gangsta Rap",
3462 + "Heavy Metal",
3463 + "Black Metal",
3464 + "Crossover",
3465 + "Contemporary Christian",
3466 + "Christian Rock",
3467 + "Merengue",
3468 + "Salsa",
3469 + "Thrash Metal",
3470 + "Anime",
3471 + "Jpop",
3472 + "Synthpop"
3473 ]
3474 """The ID3v1 genre list."""
3475 diff -Naur client175_0.7-original/mutagen/easyid3.py client175_0.7/mutagen/easyid3.py
3476 --- client175_0.7-original/mutagen/easyid3.py 2010-05-15 00:42:14.000000000 +0200
3477 +++ client175_0.7/mutagen/easyid3.py 2021-08-03 14:54:43.607811287 +0200
3478 @@ -146,7 +146,7 @@
3479 enc = 0
3480 # Store 8859-1 if we can, per MusicBrainz spec.
3481 for v in value:
3482 - if max(v) > u'\x7f':
3483 + if max(v) > '\x7f':
3484 enc = 3
3485 id3.add(mutagen.id3.TXXX(encoding=enc, text=value, desc=desc))
3486 else:
3487 @@ -182,7 +182,7 @@
3488
3489 def __setitem__(self, key, value):
3490 key = key.lower()
3491 - if isinstance(value, basestring):
3492 + if isinstance(value, str):
3493 value = [value]
3494 func = dict_match(self.Set, key, self.SetFallback)
3495 if func is not None:
3496 @@ -200,7 +200,7 @@
3497
3498 def keys(self):
3499 keys = []
3500 - for key in self.Get.keys():
3501 + for key in list(self.Get.keys()):
3502 if key in self.List:
3503 keys.extend(self.List[key](self.__id3, key))
3504 elif key in self:
3505 @@ -332,7 +332,7 @@
3506 except KeyError:
3507 raise EasyID3KeyError(key)
3508 else:
3509 - return [u"%+f dB" % frame.gain]
3510 + return ["%+f dB" % frame.gain]
3511
3512 def gain_set(id3, key, value):
3513 if len(value) != 1:
3514 @@ -362,7 +362,7 @@
3515 except KeyError:
3516 raise EasyID3KeyError(key)
3517 else:
3518 - return [u"%f" % frame.peak]
3519 + return ["%f" % frame.peak]
3520
3521 def peak_set(id3, key, value):
3522 if len(value) != 1:
3523 @@ -423,7 +423,7 @@
3524 "TSOT": "titlesort",
3525 "TSRC": "isrc",
3526 "TSST": "discsubtitle",
3527 - }.iteritems():
3528 + }.items():
3529 EasyID3.RegisterTextKey(key, frameid)
3530
3531 EasyID3.RegisterKey("genre", genre_get, genre_set, genre_delete)
3532 @@ -444,20 +444,20 @@
3533 # http://bugs.musicbrainz.org/ticket/1383
3534 # http://musicbrainz.org/doc/MusicBrainzTag
3535 for desc, key in {
3536 - u"MusicBrainz Artist Id": "musicbrainz_artistid",
3537 - u"MusicBrainz Album Id": "musicbrainz_albumid",
3538 - u"MusicBrainz Album Artist Id": "musicbrainz_albumartistid",
3539 - u"MusicBrainz TRM Id": "musicbrainz_trmid",
3540 - u"MusicIP PUID": "musicip_puid",
3541 - u"MusicMagic Fingerprint": "musicip_fingerprint",
3542 - u"MusicBrainz Album Status": "musicbrainz_albumstatus",
3543 - u"MusicBrainz Album Type": "musicbrainz_albumtype",
3544 - u"MusicBrainz Album Release Country": "releasecountry",
3545 - u"MusicBrainz Disc Id": "musicbrainz_discid",
3546 - u"ASIN": "asin",
3547 - u"ALBUMARTISTSORT": "albumartistsort",
3548 - u"BARCODE": "barcode",
3549 - }.iteritems():
3550 + "MusicBrainz Artist Id": "musicbrainz_artistid",
3551 + "MusicBrainz Album Id": "musicbrainz_albumid",
3552 + "MusicBrainz Album Artist Id": "musicbrainz_albumartistid",
3553 + "MusicBrainz TRM Id": "musicbrainz_trmid",
3554 + "MusicIP PUID": "musicip_puid",
3555 + "MusicMagic Fingerprint": "musicip_fingerprint",
3556 + "MusicBrainz Album Status": "musicbrainz_albumstatus",
3557 + "MusicBrainz Album Type": "musicbrainz_albumtype",
3558 + "MusicBrainz Album Release Country": "releasecountry",
3559 + "MusicBrainz Disc Id": "musicbrainz_discid",
3560 + "ASIN": "asin",
3561 + "ALBUMARTISTSORT": "albumartistsort",
3562 + "BARCODE": "barcode",
3563 + }.items():
3564 EasyID3.RegisterTXXXKey(key, desc)
3565
3566 class EasyID3FileType(ID3FileType):
3567 diff -Naur client175_0.7-original/mutagen/easymp4.py client175_0.7/mutagen/easymp4.py
3568 --- client175_0.7-original/mutagen/easymp4.py 2010-05-15 00:42:14.000000000 +0200
3569 +++ client175_0.7/mutagen/easymp4.py 2021-08-03 14:54:50.039718986 +0200
3570 @@ -86,11 +86,11 @@
3571 """
3572
3573 def getter(tags, key):
3574 - return map(unicode, tags[atomid])
3575 + return list(map(str, tags[atomid]))
3576
3577 def setter(tags, key, value):
3578 clamp = lambda x: int(min(max(min_value, x), max_value))
3579 - tags[atomid] = map(clamp, map(int, value))
3580 + tags[atomid] = list(map(clamp, list(map(int, value))))
3581
3582 def deleter(tags, key):
3583 del(tags[atomid])
3584 @@ -103,9 +103,9 @@
3585 ret = []
3586 for (track, total) in tags[atomid]:
3587 if total:
3588 - ret.append(u"%d/%d" % (track, total))
3589 + ret.append("%d/%d" % (track, total))
3590 else:
3591 - ret.append(unicode(track))
3592 + ret.append(str(track))
3593 return ret
3594
3595 def setter(tags, key, value):
3596 @@ -143,7 +143,7 @@
3597 return [s.decode("utf-8", "replace") for s in tags[atomid]]
3598
3599 def setter(tags, key, value):
3600 - tags[atomid] = map(utf8, value)
3601 + tags[atomid] = list(map(utf8, value))
3602
3603 def deleter(tags, key):
3604 del(tags[atomid])
3605 @@ -161,7 +161,7 @@
3606
3607 def __setitem__(self, key, value):
3608 key = key.lower()
3609 - if isinstance(value, basestring):
3610 + if isinstance(value, str):
3611 value = [value]
3612 func = dict_match(self.Set, key)
3613 if func is not None:
3614 @@ -179,7 +179,7 @@
3615
3616 def keys(self):
3617 keys = []
3618 - for key in self.Get.keys():
3619 + for key in list(self.Get.keys()):
3620 if key in self.List:
3621 keys.extend(self.List[key](self.__mp4, key))
3622 elif key in self:
3623 @@ -195,7 +195,7 @@
3624 strings.append("%s=%s" % (key, value))
3625 return "\n".join(strings)
3626
3627 -for atomid, key in {
3628 +for atomid, key in list({
3629 '\xa9nam': 'title',
3630 '\xa9alb': 'album',
3631 '\xa9ART': 'artist',
3632 @@ -211,10 +211,10 @@
3633 'soar': 'artistsort',
3634 'sonm': 'titlesort',
3635 'soco': 'composersort',
3636 - }.items():
3637 + }.items()):
3638 EasyMP4Tags.RegisterTextKey(key, atomid)
3639
3640 -for name, key in {
3641 +for name, key in list({
3642 'MusicBrainz Artist Id': 'musicbrainz_artistid',
3643 'MusicBrainz Track Id': 'musicbrainz_trackid',
3644 'MusicBrainz Album Id': 'musicbrainz_albumid',
3645 @@ -223,18 +223,18 @@
3646 'MusicBrainz Album Status': 'musicbrainz_albumstatus',
3647 'MusicBrainz Album Type': 'musicbrainz_albumtype',
3648 'MusicBrainz Release Country': 'releasecountry',
3649 - }.items():
3650 + }.items()):
3651 EasyMP4Tags.RegisterFreeformKey(key, name)
3652
3653 -for name, key in {
3654 +for name, key in list({
3655 "tmpo": "bpm",
3656 - }.items():
3657 + }.items()):
3658 EasyMP4Tags.RegisterIntKey(key, name)
3659
3660 -for name, key in {
3661 +for name, key in list({
3662 "trkn": "tracknumber",
3663 "disk": "discnumber",
3664 - }.items():
3665 + }.items()):
3666 EasyMP4Tags.RegisterIntPairKey(key, name)
3667
3668 class EasyMP4(MP4):
3669 diff -Naur client175_0.7-original/mutagen/flac.py client175_0.7/mutagen/flac.py
3670 --- client175_0.7-original/mutagen/flac.py 2010-05-15 00:42:14.000000000 +0200
3671 +++ client175_0.7/mutagen/flac.py 2021-08-03 14:54:56.799621843 +0200
3672 @@ -22,11 +22,12 @@
3673 __all__ = ["FLAC", "Open", "delete"]
3674
3675 import struct
3676 -from cStringIO import StringIO
3677 -from _vorbis import VCommentDict
3678 +from io import StringIO
3679 +from ._vorbis import VCommentDict
3680 from mutagen import FileType
3681 from mutagen._util import insert_bytes
3682 from mutagen.id3 import BitPaddedInt
3683 +from functools import reduce
3684
3685 class error(IOError): pass
3686 class FLACNoHeaderError(error): pass
3687 @@ -35,7 +36,7 @@
3688 def to_int_be(string):
3689 """Convert an arbitrarily-long string to a long using big-endian
3690 byte order."""
3691 - return reduce(lambda a, b: (a << 8) + ord(b), string, 0L)
3692 + return reduce(lambda a, b: (a << 8) + ord(b), string, 0)
3693
3694 class MetadataBlock(object):
3695 """A generic block of FLAC metadata.
3696 @@ -79,8 +80,8 @@
3697
3698 The overall size of the rendered blocks does not change, so
3699 this adds several bytes of padding for each merged block."""
3700 - paddings = filter(lambda x: isinstance(x, Padding), blocks)
3701 - map(blocks.remove, paddings)
3702 + paddings = [x for x in blocks if isinstance(x, Padding)]
3703 + list(map(blocks.remove, paddings))
3704 padding = Padding()
3705 # total padding size is the sum of padding sizes plus 4 bytes
3706 # per removed header.
3707 @@ -137,7 +138,7 @@
3708 bps_tail = bps_total >> 36
3709 bps_head = (sample_channels_bps & 1) << 4
3710 self.bits_per_sample = int(bps_head + bps_tail + 1)
3711 - self.total_samples = bps_total & 0xFFFFFFFFFL
3712 + self.total_samples = bps_total & 0xFFFFFFFFF
3713 self.length = self.total_samples / float(self.sample_rate)
3714
3715 self.md5_signature = to_int_be(data.read(16))
3716 @@ -161,12 +162,12 @@
3717 byte += (self.total_samples >> 32) & 0xF
3718 f.write(chr(byte))
3719 # last 32 of sample count
3720 - f.write(struct.pack(">I", self.total_samples & 0xFFFFFFFFL))
3721 + f.write(struct.pack(">I", self.total_samples & 0xFFFFFFFF))
3722 # MD5 signature
3723 sig = self.md5_signature
3724 f.write(struct.pack(
3725 - ">4I", (sig >> 96) & 0xFFFFFFFFL, (sig >> 64) & 0xFFFFFFFFL,
3726 - (sig >> 32) & 0xFFFFFFFFL, sig & 0xFFFFFFFFL))
3727 + ">4I", (sig >> 96) & 0xFFFFFFFF, (sig >> 64) & 0xFFFFFFFF,
3728 + (sig >> 32) & 0xFFFFFFFF, sig & 0xFFFFFFFF))
3729 return f.getvalue()
3730
3731 def pprint(self):
3732 @@ -425,8 +426,8 @@
3733
3734 def __init__(self, data=None):
3735 self.type = 0
3736 - self.mime = u''
3737 - self.desc = u''
3738 + self.mime = ''
3739 + self.desc = ''
3740 self.width = 0
3741 self.height = 0
3742 self.depth = 0
3743 @@ -601,11 +602,10 @@
3744
3745 def clear_pictures(self):
3746 """Delete all pictures from the file."""
3747 - self.metadata_blocks = filter(lambda b: b.code != Picture.code,
3748 - self.metadata_blocks)
3749 + self.metadata_blocks = [b for b in self.metadata_blocks if b.code != Picture.code]
3750
3751 def __get_pictures(self):
3752 - return filter(lambda b: b.code == Picture.code, self.metadata_blocks)
3753 + return [b for b in self.metadata_blocks if b.code == Picture.code]
3754 pictures = property(__get_pictures, doc="List of embedded pictures")
3755
3756 def save(self, filename=None, deleteid3=False):
3757 diff -Naur client175_0.7-original/mutagen/id3.py client175_0.7/mutagen/id3.py
3758 --- client175_0.7-original/mutagen/id3.py 2010-05-15 00:42:14.000000000 +0200
3759 +++ client175_0.7/mutagen/id3.py 2021-08-03 14:55:05.431497226 +0200
3760 @@ -79,7 +79,7 @@
3761 raise ValueError('Requested bytes (%s) less than zero' % size)
3762 if size > self.__filesize:
3763 raise EOFError('Requested %#x of %#x (%s)' %
3764 - (long(size), long(self.__filesize), self.filename))
3765 + (int(size), int(self.__filesize), self.filename))
3766 except AttributeError: pass
3767 data = self.__fileobj.read(size)
3768 if len(data) != size: raise EOFError
3769 @@ -115,18 +115,18 @@
3770 self.size = 0
3771 raise ID3NoHeaderError("%s: too small (%d bytes)" %(
3772 filename, self.__filesize))
3773 - except (ID3NoHeaderError, ID3UnsupportedVersionError), err:
3774 + except (ID3NoHeaderError, ID3UnsupportedVersionError) as err:
3775 self.size = 0
3776 import sys
3777 stack = sys.exc_info()[2]
3778 try: self.__fileobj.seek(-128, 2)
3779 - except EnvironmentError: raise err, None, stack
3780 + except EnvironmentError: raise err.with_traceback(stack)
3781 else:
3782 frames = ParseID3v1(self.__fileobj.read(128))
3783 if frames is not None:
3784 self.version = (1, 1)
3785 - map(self.add, frames.values())
3786 - else: raise err, None, stack
3787 + list(map(self.add, list(frames.values())))
3788 + else: raise err.with_traceback(stack)
3789 else:
3790 frames = self.__known_frames
3791 if frames is None:
3792 @@ -159,14 +159,14 @@
3793 if key in self: return [self[key]]
3794 else:
3795 key = key + ":"
3796 - return [v for s,v in self.items() if s.startswith(key)]
3797 + return [v for s,v in list(self.items()) if s.startswith(key)]
3798
3799 def delall(self, key):
3800 """Delete all tags of a given kind; see getall."""
3801 if key in self: del(self[key])
3802 else:
3803 key = key + ":"
3804 - for k in filter(lambda s: s.startswith(key), self.keys()):
3805 + for k in [s for s in list(self.keys()) if s.startswith(key)]:
3806 del(self[k])
3807
3808 def setall(self, key, values):
3809 @@ -184,7 +184,7 @@
3810 However, ID3 frames can have multiple keys:
3811 POPM=user@example.org=3 128/255
3812 """
3813 - return "\n".join(map(Frame.pprint, self.values()))
3814 + return "\n".join(map(Frame.pprint, list(self.values())))
3815
3816 def loaded_frame(self, tag):
3817 """Deprecated; use the add method."""
3818 @@ -343,9 +343,9 @@
3819
3820 # Sort frames by 'importance'
3821 order = ["TIT2", "TPE1", "TRCK", "TALB", "TPOS", "TDRC", "TCON"]
3822 - order = dict(zip(order, range(len(order))))
3823 + order = dict(list(zip(order, list(range(len(order))))))
3824 last = len(order)
3825 - frames = self.items()
3826 + frames = list(self.items())
3827 frames.sort(lambda a, b: cmp(order.get(a[0][:4], last),
3828 order.get(b[0][:4], last)))
3829
3830 @@ -355,7 +355,7 @@
3831 if not framedata:
3832 try:
3833 self.delete(filename)
3834 - except EnvironmentError, err:
3835 + except EnvironmentError as err:
3836 from errno import ENOENT
3837 if err.errno != ENOENT: raise
3838 return
3839 @@ -365,7 +365,7 @@
3840
3841 if filename is None: filename = self.filename
3842 try: f = open(filename, 'rb+')
3843 - except IOError, err:
3844 + except IOError as err:
3845 from errno import ENOENT
3846 if err.errno != ENOENT: raise
3847 f = open(filename, 'ab') # create, then reopen
3848 @@ -393,7 +393,7 @@
3849
3850 try:
3851 f.seek(-128, 2)
3852 - except IOError, err:
3853 + except IOError as err:
3854 from errno import EINVAL
3855 if err.errno != EINVAL: raise
3856 f.seek(0, 2) # ensure read won't get "TAG"
3857 @@ -540,7 +540,7 @@
3858 def __new__(cls, value, bits=7, bigendian=True):
3859 "Strips 8-bits bits out of every byte"
3860 mask = (1<<(bits))-1
3861 - if isinstance(value, (int, long)):
3862 + if isinstance(value, int):
3863 bytes = []
3864 while value:
3865 bytes.append(value & ((1<<bits)-1))
3866 @@ -549,10 +549,10 @@
3867 bytes = [ord(byte) & mask for byte in value]
3868 if bigendian: bytes.reverse()
3869 numeric_value = 0
3870 - for shift, byte in zip(range(0, len(bytes)*bits, bits), bytes):
3871 + for shift, byte in zip(list(range(0, len(bytes)*bits, bits)), bytes):
3872 numeric_value += byte << shift
3873 - if isinstance(numeric_value, long):
3874 - self = long.__new__(BitPaddedLong, numeric_value)
3875 + if isinstance(numeric_value, int):
3876 + self = int.__new__(BitPaddedLong, numeric_value)
3877 else:
3878 self = int.__new__(BitPaddedInt, numeric_value)
3879 self.bits = bits
3880 @@ -571,7 +571,7 @@
3881 # PCNT and POPM use growing integers of at least 4 bytes as counters.
3882 if width == -1: width = max(4, len(bytes))
3883 if len(bytes) > width:
3884 - raise ValueError, 'Value too wide (%d bytes)' % len(bytes)
3885 + raise ValueError('Value too wide (%d bytes)' % len(bytes))
3886 else: bytes.extend([0] * (width-len(bytes)))
3887 if bigendian: bytes.reverse()
3888 return ''.join(map(chr, bytes))
3889 @@ -654,7 +654,7 @@
3890 def validate(self, frame, value):
3891 if 0 <= value <= 3: return value
3892 if value is None: return None
3893 - raise ValueError, 'Invalid Encoding: %r' % value
3894 + raise ValueError('Invalid Encoding: %r' % value)
3895
3896 class StringSpec(Spec):
3897 def __init__(self, name, length):
3898 @@ -666,8 +666,8 @@
3899 else: return (str(value) + '\x00' * s.len)[:s.len]
3900 def validate(s, frame, value):
3901 if value is None: return None
3902 - if isinstance(value, basestring) and len(value) == s.len: return value
3903 - raise ValueError, 'Invalid StringSpec[%d] data: %r' % (s.len, value)
3904 + if isinstance(value, str) and len(value) == s.len: return value
3905 + raise ValueError('Invalid StringSpec[%d] data: %r' % (s.len, value))
3906
3907 class BinaryDataSpec(Spec):
3908 def read(self, frame, data): return data, ''
3909 @@ -696,14 +696,14 @@
3910 data, ret = data[0:offset], data[offset+2:]; break
3911 except ValueError: pass
3912
3913 - if len(data) < len(term): return u'', ret
3914 + if len(data) < len(term): return '', ret
3915 return data.decode(enc), ret
3916
3917 def write(self, frame, value):
3918 enc, term = self._encodings[frame.encoding]
3919 return value.encode(enc) + term
3920
3921 - def validate(self, frame, value): return unicode(value)
3922 + def validate(self, frame, value): return str(value)
3923
3924 class MultiSpec(Spec):
3925 def __init__(self, name, *specs, **kw):
3926 @@ -735,7 +735,7 @@
3927
3928 def validate(self, frame, value):
3929 if value is None: return []
3930 - if self.sep and isinstance(value, basestring):
3931 + if self.sep and isinstance(value, str):
3932 value = value.split(self.sep)
3933 if isinstance(value, list):
3934 if len(self.specs) == 1:
3935 @@ -744,7 +744,7 @@
3936 return [
3937 [s.validate(frame, v) for (v,s) in zip(val, self.specs)]
3938 for val in value ]
3939 - raise ValueError, 'Invalid MultiSpec data: %r' % value
3940 + raise ValueError('Invalid MultiSpec data: %r' % value)
3941
3942 class EncodedNumericTextSpec(EncodedTextSpec): pass
3943 class EncodedNumericPartTextSpec(EncodedTextSpec): pass
3944 @@ -758,7 +758,7 @@
3945 def write(self, data, value):
3946 return value.encode('latin1') + '\x00'
3947
3948 - def validate(self, frame, value): return unicode(value)
3949 + def validate(self, frame, value): return str(value)
3950
3951 class ID3TimeStamp(object):
3952 """A time stamp in ID3v2 format.
3953 @@ -782,9 +782,9 @@
3954 parts = [self.year, self.month, self.day,
3955 self.hour, self.minute, self.second]
3956 pieces = []
3957 - for i, part in enumerate(iter(iter(parts).next, None)):
3958 + for i, part in enumerate(iter(iter(parts).__next__, None)):
3959 pieces.append(self.__formats[i]%part + self.__seps[i])
3960 - return u''.join(pieces)[:-1]
3961 + return ''.join(pieces)[:-1]
3962
3963 def set_text(self, text, splitre=re.compile('[-T:/.]|\s+')):
3964 year, month, day, hour, minute, second = \
3965 @@ -812,11 +812,11 @@
3966
3967 def validate(self, frame, value):
3968 try: return ID3TimeStamp(value)
3969 - except TypeError: raise ValueError, "Invalid ID3TimeStamp: %r" % value
3970 + except TypeError: raise ValueError("Invalid ID3TimeStamp: %r" % value)
3971
3972 class ChannelSpec(ByteSpec):
3973 (OTHER, MASTER, FRONTRIGHT, FRONTLEFT, BACKRIGHT, BACKLEFT, FRONTCENTRE,
3974 - BACKCENTRE, SUBWOOFER) = range(9)
3975 + BACKCENTRE, SUBWOOFER) = list(range(9))
3976
3977 class VolumeAdjustmentSpec(Spec):
3978 def read(self, frame, data):
3979 @@ -900,7 +900,7 @@
3980 freq /= 2.0
3981 adj /= 512.0
3982 adjustments[freq] = adj
3983 - adjustments = adjustments.items()
3984 + adjustments = list(adjustments.items())
3985 adjustments.sort()
3986 return adjustments, data
3987
3988 @@ -1033,21 +1033,21 @@
3989 data = data[4:]
3990 if tflags & Frame.FLAG24_UNSYNCH or id3.f_unsynch:
3991 try: data = unsynch.decode(data)
3992 - except ValueError, err:
3993 + except ValueError as err:
3994 if id3.PEDANTIC:
3995 - raise ID3BadUnsynchData, '%s: %r' % (err, data)
3996 + raise ID3BadUnsynchData('%s: %r' % (err, data))
3997 if tflags & Frame.FLAG24_ENCRYPT:
3998 raise ID3EncryptionUnsupportedError
3999 if tflags & Frame.FLAG24_COMPRESS:
4000 try: data = data.decode('zlib')
4001 - except zlibError, err:
4002 + except zlibError as err:
4003 # the initial mutagen that went out with QL 0.12 did not
4004 # write the 4 bytes of uncompressed size. Compensate.
4005 data = datalen_bytes + data
4006 try: data = data.decode('zlib')
4007 - except zlibError, err:
4008 + except zlibError as err:
4009 if id3.PEDANTIC:
4010 - raise ID3BadCompressedData, '%s: %r' % (err, data)
4011 + raise ID3BadCompressedData('%s: %r' % (err, data))
4012
4013 elif (2,3,0) <= id3.version:
4014 if tflags & Frame.FLAG23_COMPRESS:
4015 @@ -1057,9 +1057,9 @@
4016 raise ID3EncryptionUnsupportedError
4017 if tflags & Frame.FLAG23_COMPRESS:
4018 try: data = data.decode('zlib')
4019 - except zlibError, err:
4020 + except zlibError as err:
4021 if id3.PEDANTIC:
4022 - raise ID3BadCompressedData, '%s: %r' % (err, data)
4023 + raise ID3BadCompressedData('%s: %r' % (err, data))
4024
4025 frame = cls()
4026 frame._rawdata = data
4027 @@ -1138,12 +1138,12 @@
4028 """
4029
4030 _framespec = [ EncodingSpec('encoding'),
4031 - MultiSpec('text', EncodedTextSpec('text'), sep=u'\u0000') ]
4032 + MultiSpec('text', EncodedTextSpec('text'), sep='\u0000') ]
4033 def __str__(self): return self.__unicode__().encode('utf-8')
4034 - def __unicode__(self): return u'\u0000'.join(self.text)
4035 + def __unicode__(self): return '\u0000'.join(self.text)
4036 def __eq__(self, other):
4037 if isinstance(other, str): return str(self) == other
4038 - elif isinstance(other, unicode): return unicode(self) == other
4039 + elif isinstance(other, str): return str(self) == other
4040 return self.text == other
4041 def __getitem__(self, item): return self.text[item]
4042 def __iter__(self): return iter(self.text)
4043 @@ -1160,7 +1160,7 @@
4044 """
4045
4046 _framespec = [ EncodingSpec('encoding'),
4047 - MultiSpec('text', EncodedNumericTextSpec('text'), sep=u'\u0000') ]
4048 + MultiSpec('text', EncodedNumericTextSpec('text'), sep='\u0000') ]
4049
4050 def __pos__(self):
4051 """Return the numerical value of the string."""
4052 @@ -1176,7 +1176,7 @@
4053 """
4054
4055 _framespec = [ EncodingSpec('encoding'),
4056 - MultiSpec('text', EncodedNumericPartTextSpec('text'), sep=u'\u0000') ]
4057 + MultiSpec('text', EncodedNumericPartTextSpec('text'), sep='\u0000') ]
4058 def __pos__(self):
4059 return int(self.text[0].split("/")[0])
4060
4061 @@ -1188,7 +1188,7 @@
4062 """
4063
4064 _framespec = [ EncodingSpec('encoding'),
4065 - MultiSpec('text', TimeStampSpec('stamp'), sep=u',') ]
4066 + MultiSpec('text', TimeStampSpec('stamp'), sep=',') ]
4067 def __str__(self): return self.__unicode__().encode('utf-8')
4068 def __unicode__(self): return ','.join([stamp.text for stamp in self.text])
4069 def _pprint(self):
4070 @@ -1235,9 +1235,9 @@
4071 for value in self.text:
4072 if value.isdigit():
4073 try: genres.append(self.GENRES[int(value)])
4074 - except IndexError: genres.append(u"Unknown")
4075 - elif value == "CR": genres.append(u"Cover")
4076 - elif value == "RX": genres.append(u"Remix")
4077 + except IndexError: genres.append("Unknown")
4078 + elif value == "CR": genres.append("Cover")
4079 + elif value == "RX": genres.append("Remix")
4080 elif value:
4081 newgenres = []
4082 genreid, dummy, genrename = genre_re.match(value).groups()
4083 @@ -1245,11 +1245,11 @@
4084 if genreid:
4085 for gid in genreid[1:-1].split(")("):
4086 if gid.isdigit() and int(gid) < len(self.GENRES):
4087 - gid = unicode(self.GENRES[int(gid)])
4088 + gid = str(self.GENRES[int(gid)])
4089 newgenres.append(gid)
4090 - elif gid == "CR": newgenres.append(u"Cover")
4091 - elif gid == "RX": newgenres.append(u"Remix")
4092 - else: newgenres.append(u"Unknown")
4093 + elif gid == "CR": newgenres.append("Cover")
4094 + elif gid == "RX": newgenres.append("Remix")
4095 + else: newgenres.append("Unknown")
4096
4097 if genrename:
4098 # "Unescaping" the first parenthesis
4099 @@ -1261,8 +1261,8 @@
4100 return genres
4101
4102 def __set_genres(self, genres):
4103 - if isinstance(genres, basestring): genres = [genres]
4104 - self.text = map(self.__decode, genres)
4105 + if isinstance(genres, str): genres = [genres]
4106 + self.text = list(map(self.__decode, genres))
4107
4108 def __decode(self, value):
4109 if isinstance(value, str):
4110 @@ -1333,7 +1333,7 @@
4111 the same). Many taggers use this frame to store freeform keys.
4112 """
4113 _framespec = [ EncodingSpec('encoding'), EncodedTextSpec('desc'),
4114 - MultiSpec('text', EncodedTextSpec('text'), sep=u'\u0000') ]
4115 + MultiSpec('text', EncodedTextSpec('text'), sep='\u0000') ]
4116 HashKey = property(lambda s: '%s:%s' % (s.FrameID, s.desc))
4117 def _pprint(self): return "%s=%s" % (self.desc, " / ".join(self.text))
4118
4119 @@ -1448,7 +1448,7 @@
4120 """
4121 _framespec = [ EncodingSpec('encoding'), StringSpec('lang', 3),
4122 EncodedTextSpec('desc'),
4123 - MultiSpec('text', EncodedTextSpec('text'), sep=u'\u0000') ]
4124 + MultiSpec('text', EncodedTextSpec('text'), sep='\u0000') ]
4125 HashKey = property(lambda s: '%s:%s:%r' % (s.FrameID, s.desc, s.lang))
4126 def _pprint(self): return "%s=%r=%s" % (
4127 self.desc, self.lang, " / ".join(self.text))
4128 @@ -1545,7 +1545,7 @@
4129
4130 def __eq__(self, other): return self.count == other
4131 def __pos__(self): return self.count
4132 - def _pprint(self): return unicode(self.count)
4133 + def _pprint(self): return str(self.count)
4134
4135 class POPM(FrameOpt):
4136 """Popularimeter.
4137 @@ -1774,7 +1774,7 @@
4138 ASPIIndexSpec("Fi") ]
4139 def __eq__(self, other): return self.Fi == other
4140
4141 -Frames = dict([(k,v) for (k,v) in globals().items()
4142 +Frames = dict([(k,v) for (k,v) in list(globals().items())
4143 if len(k)==4 and isinstance(v, type) and issubclass(v, Frame)])
4144 """All supported ID3v2 frames, keyed by frame name."""
4145 del(k); del(v)
4146 @@ -1867,7 +1867,7 @@
4147 _framespec = [ StringSpec('frameid', 3), Latin1TextSpec('url') ]
4148 _optionalspec = [ BinaryDataSpec('data') ]
4149
4150 -Frames_2_2 = dict([(k,v) for (k,v) in globals().items()
4151 +Frames_2_2 = dict([(k,v) for (k,v) in list(globals().items())
4152 if len(k)==3 and isinstance(v, type) and issubclass(v, Frame)])
4153
4154 # support open(filename) as interface
4155 @@ -1886,8 +1886,8 @@
4156 if tag != "TAG": return None
4157 def fix(string):
4158 return string.split("\x00")[0].strip().decode('latin1')
4159 - title, artist, album, year, comment = map(
4160 - fix, [title, artist, album, year, comment])
4161 + title, artist, album, year, comment = list(map(
4162 + fix, [title, artist, album, year, comment]))
4163
4164 if title: frames["TIT2"] = TIT2(encoding=0, text=title)
4165 if artist: frames["TPE1"] = TPE1(encoding=0, text=[artist])
4166 @@ -1907,8 +1907,8 @@
4167
4168 v1 = {}
4169
4170 - for v2id, name in {"TIT2": "title", "TPE1": "artist",
4171 - "TALB": "album"}.items():
4172 + for v2id, name in list({"TIT2": "title", "TPE1": "artist",
4173 + "TALB": "album"}.items()):
4174 if v2id in id3:
4175 text = id3[v2id].text[0].encode('latin1', 'replace')[:30]
4176 else:
4177 diff -Naur client175_0.7-original/mutagen/__init__.py client175_0.7/mutagen/__init__.py
4178 --- client175_0.7-original/mutagen/__init__.py 2010-05-15 00:42:14.000000000 +0200
4179 +++ client175_0.7/mutagen/__init__.py 2021-08-03 14:55:18.899303101 +0200
4180 @@ -82,7 +82,7 @@
4181
4182 If the file has no tags at all, a KeyError is raised.
4183 """
4184 - if self.tags is None: raise KeyError, key
4185 + if self.tags is None: raise KeyError(key)
4186 else: return self.tags[key]
4187
4188 def __setitem__(self, key, value):
4189 @@ -100,7 +100,7 @@
4190
4191 If the file has no tags at all, a KeyError is raised.
4192 """
4193 - if self.tags is None: raise KeyError, key
4194 + if self.tags is None: raise KeyError(key)
4195 else: del(self.tags[key])
4196
4197 def keys(self):
4198 @@ -109,7 +109,7 @@
4199 If the file has no tags at all, an empty list is returned.
4200 """
4201 if self.tags is None: return []
4202 - else: return self.tags.keys()
4203 + else: return list(self.tags.keys())
4204
4205 def delete(self, filename=None):
4206 """Remove tags from a file."""
4207 @@ -210,7 +210,7 @@
4208 for Kind in options]
4209 finally:
4210 fileobj.close()
4211 - results = zip(results, options)
4212 + results = list(zip(results, options))
4213 results.sort()
4214 (score, name), Kind = results[-1]
4215 if score > 0: return Kind(filename)
4216 diff -Naur client175_0.7-original/mutagen/m4a.py client175_0.7/mutagen/m4a.py
4217 --- client175_0.7-original/mutagen/m4a.py 2010-05-15 00:42:14.000000000 +0200
4218 +++ client175_0.7/mutagen/m4a.py 2021-08-03 14:55:39.954998104 +0200
4219 @@ -25,7 +25,7 @@
4220 import struct
4221 import sys
4222
4223 -from cStringIO import StringIO
4224 +from io import StringIO
4225
4226 from mutagen import FileType, Metadata
4227 from mutagen._constants import GENRES
4228 @@ -119,7 +119,7 @@
4229 if child.name == remaining[0]:
4230 return child[remaining[1:]]
4231 else:
4232 - raise KeyError, "%r not found" % remaining[0]
4233 + raise KeyError("%r not found" % remaining[0])
4234
4235 def __repr__(self):
4236 klass = self.__class__.__name__
4237 @@ -166,13 +166,13 @@
4238 'names' may be a list of atoms (['moov', 'udta']) or a string
4239 specifying the complete path ('moov.udta').
4240 """
4241 - if isinstance(names, basestring):
4242 + if isinstance(names, str):
4243 names = names.split(".")
4244 for child in self.atoms:
4245 if child.name == names[0]:
4246 return child[names[1:]]
4247 else:
4248 - raise KeyError, "%s not found" % names[0]
4249 + raise KeyError("%s not found" % names[0])
4250
4251 def __repr__(self):
4252 return "\n".join([repr(child) for child in self.atoms])
4253 @@ -202,7 +202,7 @@
4254
4255 def load(self, atoms, fileobj):
4256 try: ilst = atoms["moov.udta.meta.ilst"]
4257 - except KeyError, key:
4258 + except KeyError as key:
4259 raise M4AMetadataError(key)
4260 for atom in ilst.children:
4261 fileobj.seek(atom.offset + 8)
4262 @@ -210,14 +210,16 @@
4263 parse = self.__atoms.get(atom.name, (M4ATags.__parse_text,))[0]
4264 parse(self, atom, data)
4265
4266 - def __key_sort((key1, v1), (key2, v2)):
4267 + def __key_sort(xxx_todo_changeme, xxx_todo_changeme1):
4268 # iTunes always writes the tags in order of "relevance", try
4269 # to copy it as closely as possible.
4270 + (key1, v1) = xxx_todo_changeme
4271 + (key2, v2) = xxx_todo_changeme1
4272 order = ["\xa9nam", "\xa9ART", "\xa9wrt", "\xa9alb",
4273 "\xa9gen", "gnre", "trkn", "disk",
4274 "\xa9day", "cpil", "tmpo", "\xa9too",
4275 "----", "covr", "\xa9lyr"]
4276 - order = dict(zip(order, range(len(order))))
4277 + order = dict(list(zip(order, list(range(len(order))))))
4278 last = len(order)
4279 # If there's no key-based way to distinguish, order by length.
4280 # If there's still no way, go by string comparison on the
4281 @@ -229,7 +231,7 @@
4282 def save(self, filename):
4283 """Save the metadata to the given filename."""
4284 values = []
4285 - items = self.items()
4286 + items = list(self.items())
4287 items.sort(self.__key_sort)
4288 for key, value in items:
4289 render = self.__atoms.get(
4290 @@ -411,7 +413,7 @@
4291
4292 def pprint(self):
4293 values = []
4294 - for key, value in self.iteritems():
4295 + for key, value in self.items():
4296 key = key.decode('latin1')
4297 try: values.append("%s=%s" % (key, value))
4298 except UnicodeDecodeError:
4299 @@ -475,13 +477,13 @@
4300 try:
4301 atoms = Atoms(fileobj)
4302 try: self.info = M4AInfo(atoms, fileobj)
4303 - except StandardError, err:
4304 - raise M4AStreamInfoError, err, sys.exc_info()[2]
4305 + except Exception as err:
4306 + raise M4AStreamInfoError(err).with_traceback(sys.exc_info()[2])
4307 try: self.tags = M4ATags(atoms, fileobj)
4308 except M4AMetadataError:
4309 self.tags = None
4310 - except StandardError, err:
4311 - raise M4AMetadataError, err, sys.exc_info()[2]
4312 + except Exception as err:
4313 + raise M4AMetadataError(err).with_traceback(sys.exc_info()[2])
4314 finally:
4315 fileobj.close()
4316
4317 diff -Naur client175_0.7-original/mutagen/mp3.py client175_0.7/mutagen/mp3.py
4318 --- client175_0.7-original/mutagen/mp3.py 2010-05-15 00:42:14.000000000 +0200
4319 +++ client175_0.7/mutagen/mp3.py 2021-08-03 14:55:59.774710002 +0200
4320 @@ -19,7 +19,7 @@
4321 class InvalidMPEGHeader(error, IOError): pass
4322
4323 # Mode values.
4324 -STEREO, JOINTSTEREO, DUALCHANNEL, MONO = range(4)
4325 +STEREO, JOINTSTEREO, DUALCHANNEL, MONO = list(range(4))
4326
4327 class MPEGInfo(object):
4328 """MPEG audio stream information
4329 @@ -46,7 +46,7 @@
4330
4331 # Map (version, layer) tuples to bitrates.
4332 __BITRATE = {
4333 - (1, 1): range(0, 480, 32),
4334 + (1, 1): list(range(0, 480, 32)),
4335 (1, 2): [0, 32, 48, 56, 64, 80, 96, 112,128,160,192,224,256,320,384],
4336 (1, 3): [0, 32, 40, 48, 56, 64, 80, 96, 112,128,160,192,224,256,320],
4337 (2, 1): [0, 32, 48, 56, 64, 80, 96, 112,128,144,160,176,192,224,256],
4338 @@ -95,7 +95,7 @@
4339 # and 90% through the file.
4340 for i in [offset, 0.3 * size, 0.6 * size, 0.9 * size]:
4341 try: self.__try(fileobj, int(i), size - offset)
4342 - except error, e: pass
4343 + except error as e: pass
4344 else: break
4345 # If we can't find any two consecutive frames, try to find just
4346 # one frame back at the original offset given.
4347 diff -Naur client175_0.7-original/mutagen/mp4.py client175_0.7/mutagen/mp4.py
4348 --- client175_0.7-original/mutagen/mp4.py 2010-05-15 00:42:14.000000000 +0200
4349 +++ client175_0.7/mutagen/mp4.py 2021-08-03 14:56:05.542625890 +0200
4350 @@ -121,7 +121,7 @@
4351 if child.name == remaining[0]:
4352 return child[remaining[1:]]
4353 else:
4354 - raise KeyError, "%r not found" % remaining[0]
4355 + raise KeyError("%r not found" % remaining[0])
4356
4357 def __repr__(self):
4358 klass = self.__class__.__name__
4359 @@ -168,13 +168,13 @@
4360 'names' may be a list of atoms (['moov', 'udta']) or a string
4361 specifying the complete path ('moov.udta').
4362 """
4363 - if isinstance(names, basestring):
4364 + if isinstance(names, str):
4365 names = names.split(".")
4366 for child in self.atoms:
4367 if child.name == names[0]:
4368 return child[names[1:]]
4369 else:
4370 - raise KeyError, "%s not found" % names[0]
4371 + raise KeyError("%s not found" % names[0])
4372
4373 def __repr__(self):
4374 return "\n".join([repr(child) for child in self.atoms])
4375 @@ -242,7 +242,7 @@
4376
4377 def load(self, atoms, fileobj):
4378 try: ilst = atoms["moov.udta.meta.ilst"]
4379 - except KeyError, key:
4380 + except KeyError as key:
4381 raise MP4MetadataError(key)
4382 for atom in ilst.children:
4383 fileobj.seek(atom.offset + 8)
4384 @@ -250,14 +250,16 @@
4385 info = self.__atoms.get(atom.name, (type(self).__parse_text, None))
4386 info[0](self, atom, data, *info[2:])
4387
4388 - def __key_sort((key1, v1), (key2, v2)):
4389 + def __key_sort(xxx_todo_changeme, xxx_todo_changeme1):
4390 # iTunes always writes the tags in order of "relevance", try
4391 # to copy it as closely as possible.
4392 + (key1, v1) = xxx_todo_changeme
4393 + (key2, v2) = xxx_todo_changeme1
4394 order = ["\xa9nam", "\xa9ART", "\xa9wrt", "\xa9alb",
4395 "\xa9gen", "gnre", "trkn", "disk",
4396 "\xa9day", "cpil", "pgap", "pcst", "tmpo",
4397 "\xa9too", "----", "covr", "\xa9lyr"]
4398 - order = dict(zip(order, range(len(order))))
4399 + order = dict(list(zip(order, list(range(len(order))))))
4400 last = len(order)
4401 # If there's no key-based way to distinguish, order by length.
4402 # If there's still no way, go by string comparison on the
4403 @@ -269,14 +271,14 @@
4404 def save(self, filename):
4405 """Save the metadata to the given filename."""
4406 values = []
4407 - items = self.items()
4408 + items = list(self.items())
4409 items.sort(self.__key_sort)
4410 for key, value in items:
4411 info = self.__atoms.get(key[:4], (None, type(self).__render_text))
4412 try:
4413 values.append(info[1](self, key, value, *info[2:]))
4414 - except (TypeError, ValueError), s:
4415 - raise MP4MetadataValueError, s, sys.exc_info()[2]
4416 + except (TypeError, ValueError) as s:
4417 + raise MP4MetadataValueError(s).with_traceback(sys.exc_info()[2])
4418 data = Atom.render("ilst", "".join(values))
4419
4420 # Find the old atoms.
4421 @@ -440,7 +442,7 @@
4422 dummy, mean, name = key.split(":", 2)
4423 mean = struct.pack(">I4sI", len(mean) + 12, "mean", 0) + mean
4424 name = struct.pack(">I4sI", len(name) + 12, "name", 0) + name
4425 - if isinstance(value, basestring):
4426 + if isinstance(value, str):
4427 value = [value]
4428 return Atom.render("----", mean + name + "".join([
4429 struct.pack(">I4s2I", len(data) + 16, "data", 1, 0) + data
4430 @@ -492,7 +494,7 @@
4431 raise MP4MetadataValueError(
4432 "tmpo must be a list of 16 bit integers")
4433
4434 - values = map(cdata.to_ushort_be, value)
4435 + values = list(map(cdata.to_ushort_be, value))
4436 return self.__render_data(key, 0x15, values)
4437
4438 def __parse_bool(self, atom, data):
4439 @@ -531,10 +533,10 @@
4440 if value:
4441 self[atom.name] = value
4442 def __render_text(self, key, value, flags=1):
4443 - if isinstance(value, basestring):
4444 + if isinstance(value, str):
4445 value = [value]
4446 return self.__render_data(
4447 - key, flags, map(utf8, value))
4448 + key, flags, list(map(utf8, value)))
4449
4450 def delete(self, filename):
4451 self.clear()
4452 @@ -556,13 +558,13 @@
4453
4454 def pprint(self):
4455 values = []
4456 - for key, value in self.iteritems():
4457 + for key, value in self.items():
4458 key = key.decode('latin1')
4459 if key == "covr":
4460 values.append("%s=%s" % (key, ", ".join(
4461 ["[%d bytes of data]" % len(data) for data in value])))
4462 elif isinstance(value, list):
4463 - values.append("%s=%s" % (key, " / ".join(map(unicode, value))))
4464 + values.append("%s=%s" % (key, " / ".join(map(str, value))))
4465 else:
4466 values.append("%s=%s" % (key, value))
4467 return "\n".join(values)
4468 @@ -658,13 +660,13 @@
4469 try:
4470 atoms = Atoms(fileobj)
4471 try: self.info = MP4Info(atoms, fileobj)
4472 - except StandardError, err:
4473 - raise MP4StreamInfoError, err, sys.exc_info()[2]
4474 + except Exception as err:
4475 + raise MP4StreamInfoError(err).with_traceback(sys.exc_info()[2])
4476 try: self.tags = self.MP4Tags(atoms, fileobj)
4477 except MP4MetadataError:
4478 self.tags = None
4479 - except StandardError, err:
4480 - raise MP4MetadataError, err, sys.exc_info()[2]
4481 + except Exception as err:
4482 + raise MP4MetadataError(err).with_traceback(sys.exc_info()[2])
4483 finally:
4484 fileobj.close()
4485
4486 diff -Naur client175_0.7-original/mutagen/oggflac.py client175_0.7/mutagen/oggflac.py
4487 --- client175_0.7-original/mutagen/oggflac.py 2010-05-15 00:42:14.000000000 +0200
4488 +++ client175_0.7/mutagen/oggflac.py 2021-08-03 14:56:29.786272048 +0200
4489 @@ -21,7 +21,7 @@
4490
4491 import struct
4492
4493 -from cStringIO import StringIO
4494 +from io import StringIO
4495
4496 from mutagen.flac import StreamInfo, VCFLACDict
4497 from mutagen.ogg import OggPage, OggFileType, error as OggError
4498 diff -Naur client175_0.7-original/mutagen/ogg.py client175_0.7/mutagen/ogg.py
4499 --- client175_0.7-original/mutagen/ogg.py 2010-05-15 00:42:14.000000000 +0200
4500 +++ client175_0.7/mutagen/ogg.py 2021-08-03 14:56:22.722375298 +0200
4501 @@ -20,7 +20,7 @@
4502 import sys
4503 import zlib
4504
4505 -from cStringIO import StringIO
4506 +from io import StringIO
4507
4508 from mutagen import FileType
4509 from mutagen._util import cdata, insert_bytes, delete_bytes
4510 @@ -57,7 +57,7 @@
4511
4512 version = 0
4513 __type_flags = 0
4514 - position = 0L
4515 + position = 0
4516 serial = 0
4517 sequence = 0
4518 offset = None
4519 @@ -103,8 +103,8 @@
4520 lacings.append(total)
4521 self.complete = False
4522
4523 - self.packets = map(fileobj.read, lacings)
4524 - if map(len, self.packets) != lacings:
4525 + self.packets = list(map(fileobj.read, lacings))
4526 + if list(map(len, self.packets)) != lacings:
4527 raise error("unable to read full data")
4528
4529 def __eq__(self, other):
4530 @@ -301,7 +301,7 @@
4531 if page.packets[-1]:
4532 page.complete = False
4533 if len(page.packets) == 1:
4534 - page.position = -1L
4535 + page.position = -1
4536 else:
4537 page.packets.pop(-1)
4538 pages.append(page)
4539 @@ -334,7 +334,7 @@
4540
4541 # Number the new pages starting from the first old page.
4542 first = old_pages[0].sequence
4543 - for page, seq in zip(new_pages, range(first, first + len(new_pages))):
4544 + for page, seq in zip(new_pages, list(range(first, first + len(new_pages)))):
4545 page.sequence = seq
4546 page.serial = old_pages[0].serial
4547
4548 @@ -346,7 +346,7 @@
4549 new_pages[-1].last = old_pages[-1].last
4550 new_pages[-1].complete = old_pages[-1].complete
4551 if not new_pages[-1].complete and len(new_pages[-1].packets) == 1:
4552 - new_pages[-1].position = -1L
4553 + new_pages[-1].position = -1
4554
4555 new_data = "".join(map(klass.write, new_pages))
4556
4557 @@ -454,10 +454,10 @@
4558 denom = self.info.fps
4559 self.info.length = samples / float(denom)
4560
4561 - except error, e:
4562 - raise self._Error, e, sys.exc_info()[2]
4563 + except error as e:
4564 + raise self._Error(e).with_traceback(sys.exc_info()[2])
4565 except EOFError:
4566 - raise self._Error, "no appropriate stream found"
4567 + raise self._Error("no appropriate stream found")
4568 finally:
4569 fileobj.close()
4570
4571 @@ -473,10 +473,10 @@
4572 fileobj = file(filename, "rb+")
4573 try:
4574 try: self.tags._inject(fileobj)
4575 - except error, e:
4576 - raise self._Error, e, sys.exc_info()[2]
4577 + except error as e:
4578 + raise self._Error(e).with_traceback(sys.exc_info()[2])
4579 except EOFError:
4580 - raise self._Error, "no appropriate stream found"
4581 + raise self._Error("no appropriate stream found")
4582 finally:
4583 fileobj.close()
4584
4585 @@ -490,9 +490,9 @@
4586 fileobj = file(filename, "rb+")
4587 try:
4588 try: self.tags._inject(fileobj)
4589 - except error, e:
4590 - raise self._Error, e, sys.exc_info()[2]
4591 + except error as e:
4592 + raise self._Error(e).with_traceback(sys.exc_info()[2])
4593 except EOFError:
4594 - raise self._Error, "no appropriate stream found"
4595 + raise self._Error("no appropriate stream found")
4596 finally:
4597 fileobj.close()
4598 diff -Naur client175_0.7-original/mutagen/_util.py client175_0.7/mutagen/_util.py
4599 --- client175_0.7-original/mutagen/_util.py 2010-05-15 00:42:14.000000000 +0200
4600 +++ client175_0.7/mutagen/_util.py 2021-08-03 14:57:18.085567569 +0200
4601 @@ -32,7 +32,7 @@
4602 """
4603
4604 def __iter__(self):
4605 - return iter(self.keys())
4606 + return iter(list(self.keys()))
4607
4608 def has_key(self, key):
4609 try: self[key]
4610 @@ -40,18 +40,18 @@
4611 else: return True
4612 __contains__ = has_key
4613
4614 - iterkeys = lambda self: iter(self.keys())
4615 + iterkeys = lambda self: iter(list(self.keys()))
4616
4617 def values(self):
4618 - return map(self.__getitem__, self.keys())
4619 - itervalues = lambda self: iter(self.values())
4620 + return list(map(self.__getitem__, list(self.keys())))
4621 + itervalues = lambda self: iter(list(self.values()))
4622
4623 def items(self):
4624 - return zip(self.keys(), self.values())
4625 - iteritems = lambda s: iter(s.items())
4626 + return list(zip(list(self.keys()), list(self.values())))
4627 + iteritems = lambda s: iter(list(s.items()))
4628
4629 def clear(self):
4630 - map(self.__delitem__, self.keys())
4631 + list(map(self.__delitem__, list(self.keys())))
4632
4633 def pop(self, key, *args):
4634 if len(args) > 1:
4635 @@ -65,7 +65,7 @@
4636
4637 def popitem(self):
4638 try:
4639 - key = self.keys()[0]
4640 + key = list(self.keys())[0]
4641 return key, self.pop(key)
4642 except IndexError: raise KeyError("dictionary is empty")
4643
4644 @@ -74,7 +74,7 @@
4645 self.update(kwargs)
4646 other = {}
4647
4648 - try: map(self.__setitem__, other.keys(), other.values())
4649 + try: list(map(self.__setitem__, list(other.keys()), list(other.values())))
4650 except AttributeError:
4651 for key, value in other:
4652 self[key] = value
4653 @@ -90,14 +90,14 @@
4654 except KeyError: return default
4655
4656 def __repr__(self):
4657 - return repr(dict(self.items()))
4658 + return repr(dict(list(self.items())))
4659
4660 def __cmp__(self, other):
4661 if other is None: return 1
4662 - else: return cmp(dict(self.items()), other)
4663 + else: return cmp(dict(list(self.items())), other)
4664
4665 def __len__(self):
4666 - return len(self.keys())
4667 + return len(list(self.keys()))
4668
4669 class DictProxy(DictMixin):
4670 def __init__(self, *args, **kwargs):
4671 @@ -114,7 +114,7 @@
4672 del(self.__dict[key])
4673
4674 def keys(self):
4675 - return self.__dict.keys()
4676 + return list(self.__dict.keys())
4677
4678 class cdata(object):
4679 """C character buffer to Python numeric type conversions."""
4680 @@ -300,7 +300,7 @@
4681 """Convert a basestring to a valid UTF-8 str."""
4682 if isinstance(data, str):
4683 return data.decode("utf-8", "replace").encode("utf-8")
4684 - elif isinstance(data, unicode):
4685 + elif isinstance(data, str):
4686 return data.encode("utf-8")
4687 else: raise TypeError("only unicode/str types can be converted to UTF-8")
4688
4689 @@ -308,7 +308,7 @@
4690 try:
4691 return d[key]
4692 except KeyError:
4693 - for pattern, value in d.iteritems():
4694 + for pattern, value in d.items():
4695 if fnmatchcase(key, pattern):
4696 return value
4697 return default
4698 diff -Naur client175_0.7-original/mutagen/_vorbis.py client175_0.7/mutagen/_vorbis.py
4699 --- client175_0.7-original/mutagen/_vorbis.py 2010-05-15 00:42:14.000000000 +0200
4700 +++ client175_0.7/mutagen/_vorbis.py 2021-08-03 14:57:26.321443147 +0200
4701 @@ -16,7 +16,7 @@
4702
4703 import sys
4704
4705 -from cStringIO import StringIO
4706 +from io import StringIO
4707
4708 import mutagen
4709 from mutagen._util import DictMixin, cdata
4710 @@ -54,7 +54,7 @@
4711 vendor -- the stream 'vendor' (i.e. writer); default 'Mutagen'
4712 """
4713
4714 - vendor = u"Mutagen " + mutagen.version_string
4715 + vendor = "Mutagen " + mutagen.version_string
4716
4717 def __init__(self, data=None, *args, **kwargs):
4718 # Collect the args to pass to load, this lets child classes
4719 @@ -90,16 +90,16 @@
4720 except (OverflowError, MemoryError):
4721 raise error("cannot read %d bytes, too large" % length)
4722 try: tag, value = string.split('=', 1)
4723 - except ValueError, err:
4724 + except ValueError as err:
4725 if errors == "ignore":
4726 continue
4727 elif errors == "replace":
4728 - tag, value = u"unknown%d" % i, string
4729 + tag, value = "unknown%d" % i, string
4730 else:
4731 - raise VorbisEncodingError, str(err), sys.exc_info()[2]
4732 + raise VorbisEncodingError(str(err)).with_traceback(sys.exc_info()[2])
4733 try: tag = tag.encode('ascii', errors)
4734 except UnicodeEncodeError:
4735 - raise VorbisEncodingError, "invalid tag name %r" % tag
4736 + raise VorbisEncodingError("invalid tag name %r" % tag)
4737 else:
4738 if is_valid_key(tag): self.append((tag, value))
4739 if framing and not ord(fileobj.read(1)) & 0x01:
4740 @@ -115,7 +115,7 @@
4741 any invalid keys or values are found, a ValueError is raised.
4742 """
4743
4744 - if not isinstance(self.vendor, unicode):
4745 + if not isinstance(self.vendor, str):
4746 try: self.vendor.decode('utf-8')
4747 except UnicodeDecodeError: raise ValueError
4748
4749 @@ -123,7 +123,7 @@
4750 try:
4751 if not is_valid_key(key): raise ValueError
4752 except: raise ValueError("%r is not a valid key" % key)
4753 - if not isinstance(value, unicode):
4754 + if not isinstance(value, str):
4755 try: value.encode("utf-8")
4756 except: raise ValueError("%r is not a valid value" % value)
4757 else: return True
4758 @@ -181,15 +181,15 @@
4759 """
4760 key = key.lower().encode('ascii')
4761 values = [value for (k, value) in self if k.lower() == key]
4762 - if not values: raise KeyError, key
4763 + if not values: raise KeyError(key)
4764 else: return values
4765
4766 def __delitem__(self, key):
4767 """Delete all values associated with the key."""
4768 key = key.lower().encode('ascii')
4769 - to_delete = filter(lambda x: x[0].lower() == key, self)
4770 - if not to_delete:raise KeyError, key
4771 - else: map(self.remove, to_delete)
4772 + to_delete = [x for x in self if x[0].lower() == key]
4773 + if not to_delete:raise KeyError(key)
4774 + else: list(map(self.remove, to_delete))
4775
4776 def __contains__(self, key):
4777 """Return true if the key has any values."""
4778 @@ -220,4 +220,4 @@
4779
4780 def as_dict(self):
4781 """Return a copy of the comment data in a real dict."""
4782 - return dict((key, self[key]) for key in self.keys())
4783 + return dict((key, self[key]) for key in list(self.keys()))
4784 diff -Naur client175_0.7-original/server.py client175_0.7/server.py
4785 --- client175_0.7-original/server.py 2011-04-06 13:18:04.000000000 +0200
4786 +++ client175_0.7/server.py 2021-08-03 14:40:26.132681859 +0200
4787 @@ -20,7 +20,7 @@
4788 # MA 02110-1301, USA.
4789
4790
4791 -import cherrypy, json, os, pwd, urllib, urllib2, sys
4792 +import cherrypy, json, os, pwd, urllib.request, urllib.parse, urllib.error, urllib.request, urllib.error, urllib.parse, sys
4793 from BeautifulSoup import BeautifulSoup
4794 from time import sleep
4795 from datetime import datetime, timedelta
4796 @@ -55,7 +55,7 @@
4797 PASSWORD = None
4798 RUN_AS = pwd.getpwuid(os.getuid())[0]
4799
4800 -if os.environ.has_key("MPD_HOST"):
4801 +if "MPD_HOST" in os.environ:
4802 mpd_host = str(os.environ["MPD_HOST"])
4803 if "@" in mpd_host:
4804 mpd_host = mpd_host.split("@")
4805 @@ -64,7 +64,7 @@
4806 else:
4807 HOST = mpd_host
4808
4809 -if os.environ.has_key("MPD_PORT"):
4810 +if "MPD_PORT" in os.environ:
4811 PORT = int(os.environ["MPD_PORT"])
4812
4813 HOST = cherrypy.config.get('mpd_host', HOST)
4814 @@ -124,7 +124,7 @@
4815
4816 def add(self, *args, **kwargs):
4817 if len(kwargs) > 0:
4818 - args = list(args) + kwargs.values()
4819 + args = list(args) + list(kwargs.values())
4820 if len(args) == 2:
4821 if args[0] in ('file', 'directory'):
4822 d = args[1]
4823 @@ -146,7 +146,7 @@
4824 if ext in ['mp3', 'pgg', 'wav', 'flac', 'aac', 'mod', 'wma']:
4825 mpd.add(d)
4826 else:
4827 - sock = urllib2.urlopen(d)
4828 + sock = urllib.request.urlopen(d)
4829 data = sock.read()
4830 info = sock.info()
4831 mime = info.gettype()
4832 @@ -201,13 +201,13 @@
4833 """
4834
4835 if len(kwargs) > 0:
4836 - args = list(args) + kwargs.values()
4837 + args = list(args) + list(kwargs.values())
4838 try:
4839 if len(args) == 1:
4840 args = args[0]
4841 - print args
4842 + print(args)
4843 result = mpd.execute(args)
4844 - except MPDError, e:
4845 + except MPDError as e:
4846 raise cherrypy.HTTPError(501, message=str(e))
4847 return json.dumps(result)
4848 default.exposed = True
4849 @@ -231,7 +231,7 @@
4850 return "WAV editing not supported."
4851
4852 tags = {}
4853 - for tag, val in kwargs.items():
4854 + for tag, val in list(kwargs.items()):
4855 tag = tag.lower()
4856 if tag == 'track':
4857 tags['tracknumber'] = val
4858 @@ -239,7 +239,7 @@
4859 tags['discnumber'] = val
4860 else:
4861 tags[tag] = val
4862 - print '%s[%s] = "%s"' % (id, tag, val)
4863 + print('%s[%s] = "%s"' % (id, tag, val))
4864
4865 f = metadata.get_format(loc)
4866 f.write_tags(tags)
4867 @@ -249,7 +249,7 @@
4868 try:
4869 mpd.update(id)
4870 updating = True
4871 - except MPDError, e:
4872 + except MPDError as e:
4873 if str(e) == "[54@0] {update} already updating":
4874 sleep(0.01)
4875 else:
4876 @@ -327,7 +327,7 @@
4877 d = []
4878 skip = ('type', 'time', 'ptime', 'songs')
4879 for item in data:
4880 - for key, val in item.items():
4881 + for key, val in list(item.items()):
4882 if key not in skip:
4883 if filter in str(val).lower():
4884 d.append(item)
4885 @@ -444,7 +444,7 @@
4886 """
4887 try:
4888 return mpd.raw(cmd)
4889 - except MPDError, e:
4890 + except MPDError as e:
4891 raise cherrypy.HTTPError(501, message=str(e))
4892 protocol.exposed = True
4893
4894 @@ -514,9 +514,9 @@
4895 return json.dumps(s)
4896 n = 0
4897 while n < 50:
4898 - if mpd.state.get('uptime', '') <> client_uptime:
4899 + if mpd.state.get('uptime', '') != client_uptime:
4900 return json.dumps(mpd.state)
4901 - if mpd.state.get('updating_db', '') <> client_updating_db:
4902 + if mpd.state.get('updating_db', '') != client_updating_db:
4903 return json.dumps(mpd.state)
4904 sleep(0.1)
4905 n += 1
4906 @@ -649,11 +649,11 @@
4907 if sport is None:
4908 sport = "8080"
4909
4910 - print ""
4911 - print "=" * 60
4912 - print "Server Ready."
4913 - print "Client175 is available at: http://%s%s:%s" % (shost, sport, SERVER_ROOT)
4914 - print "=" * 60
4915 - print ""
4916 + print("")
4917 + print("=" * 60)
4918 + print("Server Ready.")
4919 + print("Client175 is available at: http://%s%s:%s" % (shost, sport, SERVER_ROOT))
4920 + print("=" * 60)
4921 + print("")
4922
4923 serve()