Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

compat.py 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. from django.utils import six
  2. from django.conf import settings
  3. from django.contrib.auth.models import User
  4. from django.core.exceptions import ImproperlyConfigured
  5. from oscar.core.loading import get_model
  6. # A setting that can be used in foreign key declarations
  7. AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
  8. # Two additional settings that are useful in South migrations when
  9. # specifying the user model in the FakeORM
  10. try:
  11. AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME = AUTH_USER_MODEL.rsplit('.', 1)
  12. except ValueError:
  13. raise ImproperlyConfigured("AUTH_USER_MODEL must be of the form"
  14. " 'app_label.model_name'")
  15. def get_user_model():
  16. """
  17. Return the User model. Doesn't require the app cache to be fully
  18. initialised.
  19. This used to live in compat to support both Django 1.4's fixed User model
  20. and custom user models introduced thereafter.
  21. Support for Django 1.4 has since been dropped in Oscar, but our
  22. get_user_model remains because code relies on us annotating the _meta class
  23. with the additional fields, and other code might rely on it as well.
  24. """
  25. try:
  26. model = get_model(AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME)
  27. except LookupError:
  28. # Convert exception to an ImproperlyConfigured exception for
  29. # backwards compatibility with previous Oscar versions and the
  30. # original get_user_model method in Django.
  31. raise ImproperlyConfigured(
  32. "AUTH_USER_MODEL refers to model '%s' that has not been installed"
  33. % settings.AUTH_USER_MODEL)
  34. # Test if user model has any custom fields and add attributes to the _meta
  35. # class
  36. core_fields = set([f.name for f in User._meta.fields])
  37. model_fields = set([f.name for f in model._meta.fields])
  38. new_fields = model_fields.difference(core_fields)
  39. model._meta.has_additional_fields = len(new_fields) > 0
  40. model._meta.additional_fields = new_fields
  41. return model
  42. def existing_user_fields(fields):
  43. """
  44. Starting with Django 1.6, the User model can be overridden and it is no
  45. longer safe to assume the User model has certain fields. This helper
  46. function assists in writing portable forms Meta.fields definitions
  47. when those contain fields on the User model
  48. Usage:
  49. class UserForm(forms.Form):
  50. ...
  51. class Meta:
  52. # won't break if first_name is not defined on User model
  53. fields = existing_user_fields(['first_name', 'last_name'])
  54. """
  55. user_fields = get_user_model()._meta.fields
  56. user_field_names = [field.name for field in user_fields]
  57. return list(set(fields) & set(user_field_names))
  58. # Python3 compatibility layer
  59. # Make backwards-compatible atomic decorator available
  60. try:
  61. from django.db.transaction import atomic as atomic_compat
  62. except ImportError:
  63. from django.db.transaction import commit_on_success as atomic_compat
  64. atomic_compat = atomic_compat
  65. """
  66. Unicode compatible wrapper for CSV reader and writer that abstracts away
  67. differences between Python 2 and 3. A package like unicodecsv would be
  68. preferable, but it's not Python 3 compatible yet.
  69. Code from http://python3porting.com/problems.html
  70. Changes:
  71. - Classes renamed to include CSV.
  72. - Unused 'codecs' import is dropped.
  73. - Added possibility to specify an open file to the writer to send as response
  74. of a view
  75. """
  76. import sys
  77. import csv
  78. PY3 = sys.version > '3'
  79. class UnicodeCSVReader:
  80. def __init__(self, filename, dialect=csv.excel,
  81. encoding="utf-8", **kw):
  82. self.filename = filename
  83. self.dialect = dialect
  84. self.encoding = encoding
  85. self.kw = kw
  86. def __enter__(self):
  87. if PY3:
  88. self.f = open(self.filename, 'rt',
  89. encoding=self.encoding, newline='')
  90. else:
  91. self.f = open(self.filename, 'rbU')
  92. self.reader = csv.reader(self.f, dialect=self.dialect,
  93. **self.kw)
  94. return self
  95. def __exit__(self, type, value, traceback):
  96. self.f.close()
  97. def next(self):
  98. row = next(self.reader)
  99. if PY3:
  100. return row
  101. return [s.decode("utf-8") for s in row]
  102. __next__ = next
  103. def __iter__(self):
  104. return self
  105. class UnicodeCSVWriter:
  106. """
  107. Python 2 and 3 compatible CSV writer. Supports two modes:
  108. * Writing to an open file or file-like object:
  109. writer = UnicodeCSVWriter(open_file=your_file)
  110. ...
  111. your_file.close()
  112. * Writing to a new file:
  113. with UnicodeCSVWriter(filename=filename) as writer:
  114. ...
  115. """
  116. def __init__(self, filename=None, open_file=None, dialect=csv.excel,
  117. encoding="utf-8", **kw):
  118. if filename is open_file is None:
  119. raise ImproperlyConfigured(
  120. "You need to specify either a filename or an open file")
  121. self.filename = filename
  122. self.f = open_file
  123. self.dialect = dialect
  124. self.encoding = encoding
  125. self.kw = kw
  126. self.writer = None
  127. def __enter__(self):
  128. assert self.filename is not None
  129. if PY3:
  130. self.f = open(self.filename, 'wt',
  131. encoding=self.encoding, newline='')
  132. else:
  133. self.f = open(self.filename, 'wb')
  134. def __exit__(self, type, value, traceback):
  135. assert self.filename is not None
  136. if self.filename is not None:
  137. self.f.close()
  138. def writerow(self, row):
  139. if self.writer is None:
  140. self.writer = csv.writer(self.f, dialect=self.dialect, **self.kw)
  141. if not PY3:
  142. row = [six.text_type(s).encode(self.encoding) for s in row]
  143. self.writer.writerow(list(row))
  144. def writerows(self, rows):
  145. for row in rows:
  146. self.writerow(row)