/odoo/tools/pycompat.py

https://gitlab.com/padjis/mapan · Python · 115 lines · 77 code · 22 blank · 16 comment · 15 complexity · 83239fe87bb2dc8d1cf759cd8beca442 MD5 · raw file

  1. # -*- coding: utf-8 -*-
  2. # to remove if we decide to add a dependency on six or future
  3. # very strongly inspired by https://github.com/pallets/werkzeug/blob/master/werkzeug/_compat.py
  4. #pylint: disable=deprecated-module
  5. import csv
  6. import codecs
  7. import collections
  8. import io
  9. import sys
  10. PY2 = sys.version_info[0] == 2
  11. _Writer = collections.namedtuple('_Writer', 'writerow writerows')
  12. if PY2:
  13. # pylint: disable=long-builtin,unichr-builtin,unicode-builtin,undefined-variable
  14. unichr = unichr
  15. text_type = unicode
  16. string_types = (str, unicode)
  17. def to_native(source, encoding='utf-8', falsy_empty=False):
  18. if not source and falsy_empty:
  19. return ''
  20. if isinstance(source, text_type):
  21. return source.encode(encoding)
  22. return str(source)
  23. integer_types = (int, long)
  24. # noinspection PyUnresolvedReferences
  25. from itertools import imap, izip, ifilter
  26. def implements_to_string(cls):
  27. cls.__unicode__ = cls.__str__
  28. cls.__str__ = lambda x: x.__unicode__().encode('utf-8')
  29. return cls
  30. def implements_iterator(cls):
  31. cls.next = cls.__next__
  32. del cls.__next__
  33. return cls
  34. exec ('def reraise(tp, value, tb=None):\n raise tp, value, tb')
  35. def csv_reader(stream, **params):
  36. for row in csv.reader(stream, **params):
  37. yield [c.decode('utf-8') for c in row]
  38. def csv_writer(stream, **params):
  39. w = csv.writer(stream, **params)
  40. return _Writer(
  41. writerow=lambda r: w.writerow([c.encode('utf-8') for c in r]),
  42. writerows=lambda rs: w.writerows(
  43. [c.encode('utf-8') for c in r]
  44. for r in rs
  45. )
  46. )
  47. else:
  48. # pylint: disable=bad-functions
  49. unichr = chr
  50. text_type = str
  51. string_types = (str,)
  52. def to_native(source, encoding='utf-8', falsy_empty=False):
  53. if not source and falsy_empty:
  54. return ''
  55. if isinstance(source, bytes):
  56. return source.decode(encoding)
  57. return str(source)
  58. integer_types = (int,)
  59. imap = map
  60. izip = zip
  61. ifilter = filter
  62. def implements_to_string(cls):
  63. return cls
  64. def implements_iterator(cls):
  65. return cls
  66. def reraise(tp, value, tb=None):
  67. if value.__traceback__ != tb:
  68. raise value.with_traceback(tb)
  69. raise value
  70. _reader = codecs.getreader('utf-8')
  71. _writer = codecs.getwriter('utf-8')
  72. def csv_reader(stream, **params):
  73. assert not isinstance(stream, io.TextIOBase),\
  74. "For cross-compatibility purposes, csv_reader takes a bytes stream"
  75. return csv.reader(_reader(stream), **params)
  76. def csv_writer(stream, **params):
  77. assert not isinstance(stream, io.TextIOBase), \
  78. "For cross-compatibility purposes, csv_writer takes a bytes stream"
  79. return csv.writer(_writer(stream), **params)
  80. def to_text(source):
  81. """ Generates a text value (an instance of text_type) from an arbitrary
  82. source.
  83. * False and None are converted to empty strings
  84. * text is passed through
  85. * bytes are decoded as UTF-8
  86. * rest is textified via the current version's relevant data model method
  87. """
  88. if source is None or source is False:
  89. return u''
  90. if isinstance(source, bytes):
  91. return source.decode('utf-8')
  92. return text_type(source)