You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

compat.py 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import six
  2. from six.moves import map
  3. from django.conf import settings
  4. from django.contrib.auth.models import User
  5. from django.core.exceptions import ImproperlyConfigured
  6. from django.utils.html import conditional_escape
  7. from django.utils.safestring import mark_safe
  8. def get_user_model():
  9. """
  10. Return the User model
  11. Using this function instead of Django 1.5's get_user_model allows backwards
  12. compatibility with Django 1.4.
  13. """
  14. try:
  15. # Django 1.5+
  16. from django.contrib.auth import get_user_model
  17. except ImportError:
  18. # Django <= 1.4
  19. model = User
  20. else:
  21. model = get_user_model()
  22. # Test if user model has any custom fields and add attributes to the _meta
  23. # class
  24. core_fields = set([f.name for f in User._meta.fields])
  25. model_fields = set([f.name for f in model._meta.fields])
  26. new_fields = model_fields.difference(core_fields)
  27. model._meta.has_additional_fields = len(new_fields) > 0
  28. model._meta.additional_fields = new_fields
  29. return model
  30. # A setting that can be used in foreign key declarations
  31. AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
  32. # Two additional settings that are useful in South migrations when
  33. # specifying the user model in the FakeORM
  34. try:
  35. AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME = AUTH_USER_MODEL.rsplit('.', 1)
  36. except ValueError:
  37. raise ImproperlyConfigured("AUTH_USER_MODEL must be of the form"
  38. " 'app_label.model_name'")
  39. def format_html(format_string, *args, **kwargs):
  40. """
  41. Backport of format_html from Django 1.5+ to support Django 1.4
  42. """
  43. args_safe = map(conditional_escape, args)
  44. kwargs_safe = dict([(k, conditional_escape(v)) for (k, v) in
  45. six.iteritems(kwargs)])
  46. return mark_safe(format_string.format(*args_safe, **kwargs_safe))
  47. #
  48. # Python3 compatibility layer
  49. #
  50. try:
  51. import urlparse as _urlparse
  52. except ImportError:
  53. from urllib import parse as _urlparse # NOQA
  54. urlparse = _urlparse
  55. #
  56. # Unicode compatible wrapper for CSV reader and writer that abstracts away
  57. # differences between Python 2 and 3. A package like unicodecsv would be
  58. # preferable, but it's not Python 3 compatible yet.
  59. # Code from http://python3porting.com/problems.html
  60. # Classes renamed to include CSV. Unused 'codecs' import is dropped.
  61. import sys
  62. import csv
  63. PY3 = sys.version > '3'
  64. class UnicodeCSVReader:
  65. def __init__(self, filename, dialect=csv.excel,
  66. encoding="utf-8", **kw):
  67. self.filename = filename
  68. self.dialect = dialect
  69. self.encoding = encoding
  70. self.kw = kw
  71. def __enter__(self):
  72. if PY3:
  73. self.f = open(self.filename, 'rt',
  74. encoding=self.encoding, newline='')
  75. else:
  76. self.f = open(self.filename, 'rb')
  77. self.reader = csv.reader(self.f, dialect=self.dialect,
  78. **self.kw)
  79. return self
  80. def __exit__(self, type, value, traceback):
  81. self.f.close()
  82. def next(self):
  83. row = next(self.reader)
  84. if PY3:
  85. return row
  86. return [s.decode("utf-8") for s in row]
  87. __next__ = next
  88. def __iter__(self):
  89. return self
  90. class UnicodeCSVWriter:
  91. def __init__(self, filename, dialect=csv.excel,
  92. encoding="utf-8", **kw):
  93. self.filename = filename
  94. self.dialect = dialect
  95. self.encoding = encoding
  96. self.kw = kw
  97. def __enter__(self):
  98. if PY3:
  99. self.f = open(self.filename, 'wt',
  100. encoding=self.encoding, newline='')
  101. else:
  102. self.f = open(self.filename, 'wb')
  103. self.writer = csv.writer(self.f, dialect=self.dialect,
  104. **self.kw)
  105. return self
  106. def __exit__(self, type, value, traceback):
  107. self.f.close()
  108. def writerow(self, row):
  109. if not PY3:
  110. row = [s.encode(self.encoding) for s in row]
  111. self.writer.writerow(row)
  112. def writerows(self, rows):
  113. for row in rows:
  114. self.writerow(row)