diff options
Diffstat (limited to 'ishtar_common/models.py')
| -rw-r--r-- | ishtar_common/models.py | 1354 | 
1 files changed, 655 insertions, 699 deletions
diff --git a/ishtar_common/models.py b/ishtar_common/models.py index e8f40a01c..b535d9bf7 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -33,7 +33,7 @@ import re  import shutil  import tempfile  import time -from cStringIO import StringIO +from io import BytesIO  from subprocess import Popen, PIPE  from PIL import Image @@ -61,7 +61,7 @@ from django.db.models.fields.related import ManyToManyField, ManyToManyRel  from django.db.utils import DatabaseError  from django.template.defaultfilters import slugify  from django.utils.functional import lazy -from django.utils.safestring import SafeUnicode, mark_safe +from django.utils.safestring import SafeText, mark_safe  from django.utils.translation import ugettext_lazy as _, ugettext, \      pgettext_lazy, activate, deactivate  from ishtar_common.utils_secretary import IshtarSecretaryRenderer @@ -154,11 +154,11 @@ class ValueGetter(object):                  val = ''              elif (key in self.GET_VALUES_EXTRA_TYPES or "type" in key) and (                    val.__class__.__name__.split('.')[0] == 'ManyRelatedManager'): -                val = u" ; ".join([unicode(v) for v in val.all()]) +                val = u" ; ".join([str(v) for v in val.all()])              elif isinstance(val, (tuple, list, dict)):                  pass              else: -                val = unicode(val) +                val = str(val)                  if val.endswith('.None'):                      val = ''              values[key] = val @@ -169,7 +169,7 @@ class ValueGetter(object):          for key in values.keys():              if key in ('KEYS', 'VALUES'):                  continue -            value_list.append((key, unicode(values[key]))) +            value_list.append((key, str(values[key])))          for global_var in GlobalVar.objects.all():              values[global_var.slug] = global_var.value or ""          values['VALUES'] = json.dumps( @@ -260,7 +260,7 @@ def valid_id(cls):          try:              cls.objects.get(pk=value)          except ObjectDoesNotExist: -            raise ValidationError(_(u"Not a valid item.")) +            raise ValidationError(_("Not a valid item."))      return func @@ -276,7 +276,7 @@ def valid_ids(cls):                  cls.objects.get(pk=v)              except ObjectDoesNotExist:                  raise ValidationError( -                    _(u"A selected item is not a valid item.")) +                    _("A selected item is not a valid item."))      return func @@ -288,7 +288,7 @@ def is_unique(cls, field):          try:              assert cls.objects.filter(**query).count() == 0          except AssertionError: -            raise ValidationError(_(u"This item already exists.")) +            raise ValidationError(_("This item already exists."))      return func @@ -562,23 +562,23 @@ class GeneralType(Cached, models.Model):      """      Abstract class for "types"      """ -    label = models.TextField(_(u"Label")) +    label = models.TextField(_("Label"))      txt_idx = models.TextField( -        _(u"Textual ID"), validators=[validate_slug], +        _("Textual ID"), validators=[validate_slug],          unique=True,          help_text=_( -            u"The slug is the standardized version of the name. It contains " -            u"only lowercase letters, numbers and hyphens. Each slug must " -            u"be unique.")) -    comment = models.TextField(_(u"Comment"), blank=True, null=True) -    available = models.BooleanField(_(u"Available"), default=True) -    HELP_TEXT = u"" +            "The slug is the standardized version of the name. It contains " +            "only lowercase letters, numbers and hyphens. Each slug must " +            "be unique.")) +    comment = models.TextField(_("Comment"), blank=True, null=True) +    available = models.BooleanField(_("Available"), default=True) +    HELP_TEXT = ""      objects = TypeManager()      class Meta:          abstract = True -    def __unicode__(self): +    def __str__(self):          return self.label      def natural_key(self): @@ -601,7 +601,7 @@ class GeneralType(Cached, models.Model):      @property      def explicit_label(self): -        return u"{} ({})".format(self.label, self._meta.verbose_name) +        return "{} ({})".format(self.label, self._meta.verbose_name)      @classmethod      def create_default_for_test(cls): @@ -643,7 +643,7 @@ class GeneralType(Cached, models.Model):          :return: id of the item (string)          """ -        return unicode(cls.get_or_create(slug).pk) +        return str(cls.get_or_create(slug).pk)      @classmethod      def get_or_create_pks(cls, slugs): @@ -658,19 +658,19 @@ class GeneralType(Cached, models.Model):          items = []          for slug in slugs:              items.append(str(cls.get_or_create(slug).pk)) -        return u"_".join(items) +        return "_".join(items)      @classmethod      def get_help(cls, dct={}, exclude=[], force=False):          keys = ['__get_help'] -        keys += [u"{}".format(ex) for ex in exclude] -        keys += [u'{}-{}'.format(unicode(k), dct[k]) for k in dct] +        keys += ["{}".format(ex) for ex in exclude] +        keys += ['{}-{}'.format(str(k), dct[k]) for k in dct]          cache_key, value = get_cache(cls, keys)          if value and not force:              return mark_safe(value)          help_text = cls.HELP_TEXT          c_rank = -1 -        help_items = u"\n" +        help_items = "\n"          for item in cls.get_types(dct=dct, instances=True, exclude=exclude):              if hasattr(item, '__iter__'):                  pk = item[0] @@ -684,23 +684,23 @@ class GeneralType(Cached, models.Model):                          c_item = c_item.parent                      parents.reverse()                      parents.append(item.label) -                    item.label = u" / ".join(parents) +                    item.label = " / ".join(parents)              if not item.comment:                  continue              if c_rank > item.rank: -                help_items += u"</dl>\n" +                help_items += "</dl>\n"              elif c_rank < item.rank: -                help_items += u"<dl>\n" +                help_items += "<dl>\n"              c_rank = item.rank -            help_items += u"<dt>%s</dt><dd>%s</dd>" % ( -                item.label, u"<br/>".join(item.comment.split('\n'))) +            help_items += "<dt>%s</dt><dd>%s</dd>" % ( +                item.label, "<br/>".join(item.comment.split('\n')))          c_rank += 1          if c_rank: -            help_items += c_rank * u"</dl>" +            help_items += c_rank * "</dl>"          if help_text or help_items != u'\n':              help_text = help_text + help_items          else: -            help_text = u"" +            help_text = ""          cache.set(cache_key, help_text, settings.CACHE_TIMEOUT)          return mark_safe(help_text) @@ -723,7 +723,7 @@ class GeneralType(Cached, models.Model):                  if instance:                      new_vals.append(extra_type)                  else: -                    new_vals.append((extra_type.pk, unicode(extra_type))) +                    new_vals.append((extra_type.pk, str(extra_type)))              except cls.DoesNotExist:                  continue          return new_vals @@ -749,9 +749,9 @@ class GeneralType(Cached, models.Model):          cache_key = None          if not instances:              keys = ['__get_types'] -            keys += [u"{}".format(ex) for ex in exclude] + \ -                    [u"{}".format(default)] -            keys += [u'{}-{}'.format(unicode(k), dct[k]) for k in dct] +            keys += ["{}".format(ex) for ex in exclude] + \ +                    ["{}".format(default)] +            keys += ['{}-{}'.format(str(k), dct[k]) for k in dct]              cache_key, value = get_cache(cls, keys)              if value and not force:                  return value @@ -787,7 +787,7 @@ class GeneralType(Cached, models.Model):          if default:              try:                  default = cls.objects.get(txt_idx=default) -                yield (default.pk, _(unicode(default))) +                yield (default.pk, _(str(default)))              except cls.DoesNotExist:                  pass          items = cls.objects.filter(**dct) @@ -803,8 +803,7 @@ class GeneralType(Cached, models.Model):                  item.rank = 0                  yield item              else: -                yield (item.pk, _(unicode(item)) -                if item and unicode(item) else '') +                yield (item.pk, _(str(item)) if item and str(item) else '')      @classmethod      def _get_childs_list(cls, dct=None, exclude=None, instances=False): @@ -838,7 +837,7 @@ class GeneralType(Cached, models.Model):      PREFIX_EMPTY = "  "      PREFIX_MEDIUM = "├ "      PREFIX_LAST = "└ " -    PREFIX_CODES = [u"\u2502", u"\u251C", u"\u2514"] +    PREFIX_CODES = ["\u2502", "\u251C", "\u2514"]      @classmethod      def _get_childs(cls, item, child_list, prefix=0, instances=False, @@ -880,7 +879,7 @@ class GeneralType(Cached, models.Model):                      else:                          p += cls.PREFIX                  lst.append(( -                    child[0], SafeUnicode(p + unicode(_(child[1]))) +                    child[0], SafeText(p + str(_(child[1])))                  ))              clast_of = last_of[:]              clast_of.append(idx + 1 == total) @@ -922,8 +921,8 @@ class GeneralType(Cached, models.Model):      def save(self, *args, **kwargs):          if not self.id and not self.label: -            self.label = u" ".join(u" ".join(self.txt_idx.split('-')) -                                   .split('_')).title() +            self.label = " ".join(" ".join(self.txt_idx.split('-')) +                                  .split('_')).title()          if not self.txt_idx:              self.txt_idx = slugify(self.label)[:100] @@ -995,7 +994,7 @@ class GeneralType(Cached, models.Model):  class HierarchicalType(GeneralType):      parent = models.ForeignKey('self', blank=True, null=True,                                 on_delete=models.SET_NULL, -                               verbose_name=_(u"Parent")) +                               verbose_name=_("Parent"))      class Meta:          abstract = True @@ -1006,37 +1005,37 @@ class HierarchicalType(GeneralType):          while item.parent:              item = item.parent              lbls.append(item.label) -        return u" > ".join(reversed(lbls)) +        return " > ".join(reversed(lbls))  class ItemKey(models.Model): -    key = models.TextField(_(u"Key")) +    key = models.TextField(_("Key"))      content_type = models.ForeignKey(ContentType)      object_id = models.PositiveIntegerField()      content_object = GenericForeignKey('content_type', 'object_id')      importer = models.ForeignKey(          Import, null=True, blank=True, -        help_text=_(u"Specific key to an import")) +        help_text=_("Specific key to an import"))      user = models.ForeignKey('IshtarUser', blank=True, null=True)      group = models.ForeignKey(TargetKeyGroup, blank=True, null=True) -    def __unicode__(self): +    def __str__(self):          return self.key  def get_image_path(instance, filename):      # when using migrations instance is not a real ImageModel instance      if not hasattr(instance, '_get_image_path'): -        return u"upload/{}".format(filename) +        return "upload/{}".format(filename)      return instance._get_image_path(filename)  class ImageContainerModel(object):      def _get_image_path(self, filename): -        return u"{}/{}".format(self._get_base_image_path(), filename) +        return "{}/{}".format(self._get_base_image_path(), filename)      def _get_base_image_path(self): -        return u"upload" +        return "upload"  class ImageModel(models.Model, ImageContainerModel): @@ -1062,7 +1061,7 @@ class ImageModel(models.Model, ImageContainerModel):      def create_thumb(self, image, size):          """Returns the image resized to fit inside a box of the given size"""          image.thumbnail(size, Image.ANTIALIAS) -        temp = StringIO() +        temp = BytesIO()          image.save(temp, 'jpeg')          temp.seek(0)          return SimpleUploadedFile('temp', temp.read()) @@ -1115,8 +1114,8 @@ class ImageModel(models.Model, ImageContainerModel):      def _get_thumb_name(self, filename):          splited = filename.split('.') -        return u"{}-thumb.{}".format( -            u".".join(splited[:-1]), splited[-1] +        return "{}-thumb.{}".format( +            ".".join(splited[:-1]), splited[-1]          ) @@ -1144,7 +1143,7 @@ class BulkUpdatedItem(object):          :return: (transaction ID, is a recursion)          """          if not transaction_id: -            transaction_id = unicode(time.time()) +            transaction_id = str(time.time())          args = ['cached_label_bulk_update', transaction_id] + extra_args          key, val = get_cache(cls, args)          if val: @@ -1158,7 +1157,7 @@ class RelationItem(models.Model):      Items with relation between them      """      relation_image = models.FileField( -        _(u"Generated relation image (SVG)"), null=True, blank=True, +        _("Generated relation image (SVG)"), null=True, blank=True,          upload_to=get_image_path, help_text=max_size_help()      ) @@ -1171,43 +1170,43 @@ class RelationItem(models.Model):  class JsonDataSection(models.Model):      content_type = models.ForeignKey(ContentType) -    name = models.CharField(_(u"Name"), max_length=200) -    order = models.IntegerField(_(u"Order"), default=10) +    name = models.CharField(_("Name"), max_length=200) +    order = models.IntegerField(_("Order"), default=10)      class Meta: -        verbose_name = _(u"Json data - Menu") -        verbose_name_plural = _(u"Json data - Menus") +        verbose_name = _("Json data - Menu") +        verbose_name_plural = _("Json data - Menus")          ordering = ['order', 'name'] -    def __unicode__(self): -        return u"{} - {}".format(self.content_type, self.name) +    def __str__(self): +        return "{} - {}".format(self.content_type, self.name)  JSON_VALUE_TYPES = ( -    ('T', _(u"Text")), -    ('LT', _(u"Long text")), -    ('I', _(u"Integer")), -    ('B', _(u"Boolean")), -    ('F', _(u"Float")), -    ('D', _(u"Date")), -    ('C', _(u"Choices")), +    ('T', _("Text")), +    ('LT', _("Long text")), +    ('I', _("Integer")), +    ('B', _("Boolean")), +    ('F', _("Float")), +    ('D', _("Date")), +    ('C', _("Choices")),  )  class JsonDataField(models.Model): -    name = models.CharField(_(u"Name"), max_length=200) +    name = models.CharField(_("Name"), max_length=200)      content_type = models.ForeignKey(ContentType)      key = models.CharField( -        _(u"Key"), max_length=200, -        help_text=_(u"Value of the key in the JSON schema. For hierarchical " -                    u"key use \"__\" to explain it. For instance for the key " -                    u"'my_subkey' with data such as {'my_key': {'my_subkey': " -                    u"'value'}}, its value will be reached with my_key__my_subkey.")) -    display = models.BooleanField(_(u"Display"), default=True) -    value_type = models.CharField(_(u"Type"), default="T", max_length=10, +        _("Key"), max_length=200, +        help_text=_("Value of the key in the JSON schema. For hierarchical " +                    "key use \"__\" to explain it. For instance for the key " +                    "'my_subkey' with data such as {'my_key': {'my_subkey': " +                    "'value'}}, its value will be reached with my_key__my_subkey.")) +    display = models.BooleanField(_("Display"), default=True) +    value_type = models.CharField(_("Type"), default="T", max_length=10,                                    choices=JSON_VALUE_TYPES) -    order = models.IntegerField(_(u"Order"), default=10) -    search_index = models.BooleanField(_(u"Use in search indexes"), +    order = models.IntegerField(_("Order"), default=10) +    search_index = models.BooleanField(_("Use in search indexes"),                                         default=False)      section = models.ForeignKey(JsonDataSection, blank=True, null=True,                                  on_delete=models.SET_NULL) @@ -1215,19 +1214,19 @@ class JsonDataField(models.Model):          "CustomForm", blank=True, through="CustomFormJsonField")      class Meta: -        verbose_name = _(u"Json data - Field") -        verbose_name_plural = _(u"Json data - Fields") +        verbose_name = _("Json data - Field") +        verbose_name_plural = _("Json data - Fields")          ordering = ['order', 'name'] -    def __unicode__(self): -        return u"{} - {}".format(self.content_type, self.name) +    def __str__(self): +        return "{} - {}".format(self.content_type, self.name)      def clean(self):          if not self.section:              return          if self.section.content_type != self.content_type:              raise ValidationError( -                _(u"Content types of the field and of the menu do not match")) +                _("Content types of the field and of the menu do not match"))  class JsonData(models.Model, CachedGen): @@ -1268,7 +1267,7 @@ class JsonData(models.Model, CachedGen):              if value is None:                  continue              if type(value) in (list, tuple): -                value = u" ; ".join([unicode(v) for v in value]) +                value = " ; ".join([str(v) for v in value])              section_name = field.section.name if field.section else None              if not sections or section_name != sections[-1][0]:                  # if section name is identical it is the same @@ -1349,7 +1348,7 @@ class DynamicRequest(object):          fields = {}          for item in self.get_all_types().all():              fields[self.form_key + "-" + item.txt_idx] = forms.CharField( -                label=unicode(self.label) + u" " + unicode(item), +                label=str(self.label) + " " + str(item),                  required=False              )          return fields @@ -1430,7 +1429,7 @@ class FullSearch(models.Model):          for v in cls.get_alt_names().values():              for language_code, language_lbl in settings.LANGUAGES:                  activate(language_code) -                query_parameters[unicode(v.search_key)] = v +                query_parameters[str(v.search_key)] = v                  deactivate()          return query_parameters @@ -1523,7 +1522,7 @@ class FullSearch(models.Model):              res = q.all()[0]              for base_search_vector in self.BASE_SEARCH_VECTORS:                  data = res[base_search_vector.key] -                data = unidecode(unicode(data)) +                data = unidecode(str(data))                  self._update_search_field(base_search_vector,                                            search_vectors, data) @@ -1534,7 +1533,7 @@ class FullSearch(models.Model):                      data = data()                  if not data:                      continue -                data = unicode(data) +                data = str(data)                  self._update_search_field(property_search_vector,                                            search_vectors, data) @@ -1696,9 +1695,9 @@ class DocumentItem(object):                  (                      reverse("create-document") + "?{}={}".format(                          self.SLUG, self.pk), -                    _(u"Add document/image"), +                    _("Add document/image"),                      "fa fa-plus", -                    _(u"doc./image"), +                    _("doc./image"),                      "",                      False                  ) @@ -1707,14 +1706,14 @@ class DocumentItem(object):  class SpatialReferenceSystem(GeneralType): -    order = models.IntegerField(_(u"Order"), default=10) +    order = models.IntegerField(_("Order"), default=10)      auth_name = models.CharField( -        _(u"Authority name"), default=u'EPSG', max_length=256) -    srid = models.IntegerField(_(u"Authority SRID")) +        _("Authority name"), default=u'EPSG', max_length=256) +    srid = models.IntegerField(_("Authority SRID"))      class Meta: -        verbose_name = _(u"Spatial reference system") -        verbose_name_plural = _(u"Spatial reference systems") +        verbose_name = _("Spatial reference system") +        verbose_name_plural = _("Spatial reference systems")          ordering = ('label',) @@ -1724,8 +1723,7 @@ post_delete.connect(post_save_cache, sender=SpatialReferenceSystem)  class GeoItem(models.Model):      GEO_SOURCE = ( -        ('T', _(u"Town")), ('P', _(u"Precise")), -        ('M', _("Polygon")) +        ('T', _("Town")), ('P', _("Precise")), ('M', _("Polygon"))      )      # gis @@ -1739,22 +1737,22 @@ class GeoItem(models.Model):      estimated_error_z = models.FloatField(_(u'Estimated error for Z'),                                            blank=True, null=True)      spatial_reference_system = models.ForeignKey( -        SpatialReferenceSystem, verbose_name=_(u"Spatial Reference System"), +        SpatialReferenceSystem, verbose_name=_("Spatial Reference System"),          blank=True, null=True) -    point = models.PointField(_(u"Point"), blank=True, null=True, dim=3) -    point_2d = models.PointField(_(u"Point (2D)"), blank=True, null=True) +    point = models.PointField(_("Point"), blank=True, null=True, dim=3) +    point_2d = models.PointField(_("Point (2D)"), blank=True, null=True)      point_source = models.CharField( -        _(u"Point source"), choices=GEO_SOURCE, max_length=1, blank=True, +        _("Point source"), choices=GEO_SOURCE, max_length=1, blank=True,          null=True)      point_source_item = models.CharField( -        _(u"Point source item"), max_length=100, blank=True, null=True) -    multi_polygon = models.MultiPolygonField(_(u"Multi polygon"), blank=True, +        _("Point source item"), max_length=100, blank=True, null=True) +    multi_polygon = models.MultiPolygonField(_("Multi polygon"), blank=True,                                               null=True)      multi_polygon_source = models.CharField( -        _(u"Multi-polygon source"), choices=GEO_SOURCE, max_length=1, +        _("Multi-polygon source"), choices=GEO_SOURCE, max_length=1,          blank=True, null=True)      multi_polygon_source_item = models.CharField( -        _(u"Multi polygon source item"), max_length=100, blank=True, null=True) +        _("Multi polygon source item"), max_length=100, blank=True, null=True)      GEO_LABEL = "" @@ -1778,7 +1776,7 @@ class GeoItem(models.Model):      def most_precise_geo(self):          if self.point_source == 'M':              return 'multi_polygon' -        current_source = unicode(self.__class__._meta.verbose_name) +        current_source = str(self.__class__._meta.verbose_name)          if self.multi_polygon_source_item == current_source \                  and (self.multi_polygon_source == "P" or                       self.point_source_item != current_source): @@ -1798,7 +1796,7 @@ class GeoItem(models.Model):      def geo_point_source(self):          if not self.point_source:              return "" -        src = u"{} - {}".format( +        src = "{} - {}".format(              dict(self.GEO_SOURCE)[self.point_source],              self.point_source_item          ) @@ -1807,7 +1805,7 @@ class GeoItem(models.Model):      def geo_polygon_source(self):          if not self.multi_polygon_source:              return "" -        src = u"{} - {}".format( +        src = "{} - {}".format(              dict(self.GEO_SOURCE)[self.multi_polygon_source],              self.multi_polygon_source_item          ) @@ -1861,10 +1859,10 @@ class BaseHistorizedItem(FullSearch, Imported, JsonData, FixAssociated):      history_modifier = models.ForeignKey(          User, related_name='+', on_delete=models.SET_NULL, -        verbose_name=_(u"Last editor"), blank=True, null=True) +        verbose_name=_("Last editor"), blank=True, null=True)      history_creator = models.ForeignKey(          User, related_name='+', on_delete=models.SET_NULL, -        verbose_name=_(u"Creator"), blank=True, null=True) +        verbose_name=_("Creator"), blank=True, null=True)      last_modified = models.DateTimeField(auto_now=True)      history_m2m = JSONField(default={}, blank=True) @@ -1961,8 +1959,8 @@ class BaseHistorizedItem(FullSearch, Imported, JsonData, FixAssociated):                      setattr(item, k, val)                  except ObjectDoesNotExist:                      if strict: -                        raise HistoryError(u"The class %s has no pk %d" % ( -                            unicode(field.rel.to), val)) +                        raise HistoryError("The class %s has no pk %d" % ( +                            str(field.rel.to), val))                      setattr(item, k, None)          item.pk = self.pk          return item @@ -1992,7 +1990,7 @@ class BaseHistorizedItem(FullSearch, Imported, JsonData, FixAssociated):                  break              to_del.append(item)          if not new_item: -            raise HistoryError(u"The date to rollback to doesn't exist.") +            raise HistoryError("The date to rollback to doesn't exist.")          try:              field_keys = [f.name for f in self._meta.fields]              for k in field_keys: @@ -2021,7 +2019,7 @@ class BaseHistorizedItem(FullSearch, Imported, JsonData, FixAssociated):              self._cached_label_checked = False              self.save()          except ObjectDoesNotExist: -            raise HistoryError(u"The rollback has failed.") +            raise HistoryError("The rollback has failed.")          # clean the obsolete history          for historized_item in to_del:              historized_item.delete() @@ -2067,7 +2065,7 @@ class BaseHistorizedItem(FullSearch, Imported, JsonData, FixAssociated):              items.append(last_edition_date.strftime('%Y%m%d'))          else:              items.append('00000000') -        return u"-".join([unicode(item) for item in items]) +        return "-".join([str(item) for item in items])      def save(self, *args, **kwargs):          created = not self.pk @@ -2094,22 +2092,22 @@ class BaseHistorizedItem(FullSearch, Imported, JsonData, FixAssociated):  LOGICAL_TYPES = ( -    ('above', _(u"Above")), -    ('bellow', _(u"Bellow")), -    ('equal', _(u"Equal")) +    ('above', _("Above")), +    ('bellow', _("Bellow")), +    ('equal', _("Equal"))  )  class GeneralRelationType(GeneralType): -    order = models.IntegerField(_(u"Order"), default=1) -    symmetrical = models.BooleanField(_(u"Symmetrical")) -    tiny_label = models.CharField(_(u"Tiny label"), max_length=50, +    order = models.IntegerField(_("Order"), default=1) +    symmetrical = models.BooleanField(_("Symmetrical")) +    tiny_label = models.CharField(_("Tiny label"), max_length=50,                                    blank=True, null=True)      inverse_relation = models.ForeignKey( -        'self', verbose_name=_(u"Inverse relation"), blank=True, +        'self', verbose_name=_("Inverse relation"), blank=True,          null=True)      logical_relation = models.CharField( -        verbose_name=_(u"Logical relation"), max_length=10, +        verbose_name=_("Logical relation"), max_length=10,          choices=LOGICAL_TYPES, blank=True, null=True)      class Meta: @@ -2119,10 +2117,10 @@ class GeneralRelationType(GeneralType):          # cannot have symmetrical and an inverse_relation          if self.symmetrical and self.inverse_relation:              raise ValidationError( -                _(u"Cannot have symmetrical and an inverse_relation")) +                _("Cannot have symmetrical and an inverse_relation"))      def get_tiny_label(self): -        return self.tiny_label or self.label or u"" +        return self.tiny_label or self.label or ""      def save(self, *args, **kwargs):          obj = super(GeneralRelationType, self).save(*args, **kwargs) @@ -2179,20 +2177,20 @@ def post_delete_record_relation(sender, instance, **kwargs):  class SearchQuery(models.Model): -    label = models.TextField(_(u"Label"), blank=True) -    query = models.TextField(_(u"Query"), blank=True) +    label = models.TextField(_("Label"), blank=True) +    query = models.TextField(_("Query"), blank=True)      content_type = models.ForeignKey(ContentType, -                                     verbose_name=_(u"Content type")) -    profile = models.ForeignKey("UserProfile", verbose_name=_(u"Profile")) -    is_alert = models.BooleanField(_(u"Is an alert"), default=False) +                                     verbose_name=_("Content type")) +    profile = models.ForeignKey("UserProfile", verbose_name=_("Profile")) +    is_alert = models.BooleanField(_("Is an alert"), default=False)      class Meta: -        verbose_name = _(u"Search query") -        verbose_name_plural = _(u"Search queries") +        verbose_name = _("Search query") +        verbose_name_plural = _("Search queries")          ordering = ['label'] -    def __unicode__(self): -        return unicode(self.label) +    def __str__(self): +        return str(self.label)  class ShortMenuItem(object): @@ -2243,7 +2241,7 @@ class QuickAction(object):      def rendered_icon(self):          if not self.icon_class:              return "" -        return u"<i class='{}' aria-hidden='true'></i>".format(self.icon_class) +        return "<i class='{}' aria-hidden='true'></i>".format(self.icon_class)      @property      def base_url(self): @@ -2340,7 +2338,7 @@ def get_external_id(key, item):          if obj is None:              dct[initial_key] = ''          else: -            dct[initial_key] = unicode(obj) +            dct[initial_key] = str(obj)          for filtr in filters:              dct[initial_key] = filtr(dct[initial_key])      values = formula.format(**dct).split('||') @@ -2353,192 +2351,189 @@ def get_external_id(key, item):      return value -CURRENCY = ((u"€", _(u"Euro")), -            (u"$", _(u"US dollar"))) -FIND_INDEX_SOURCE = ((u"O", _(u"Operations")), -                     (u"CR", _(u"Context records"))) -SITE_LABELS = [('site', _(u"Site")), ('entity', _(u"Archaeological entity"))] +CURRENCY = (("€", _("Euro")), +            ("$", _("US dollar"))) +FIND_INDEX_SOURCE = (("O", _("Operations")), +                     ("CR", _("Context records"))) +SITE_LABELS = [('site', _("Site")), ('entity', _("Archaeological entity"))]  TRANSLATED_SITE_LABELS = {      'site': { -        'search': _(u"Site search"), -        'new': _(u"New site"), -        'modification': _(u"Site modification"), -        'deletion': _(u"Site deletion"), -        "attached-to-operation": _(u"Site (attached to the " -                                   u"operation)"), -        "name-attached-to-operation": _(u"Site name (attached " -                                        u"to the operation)"), -        "attached-to-cr": _(u"Site (attached to the context " -                            u"record)"), -        "name-attached-to-cr": -            _(u"Site name (attached to the context record)"), +        'search': _("Site search"), +        'new': _("New site"), +        'modification': _("Site modification"), +        'deletion': _("Site deletion"), +        "attached-to-operation": _("Site (attached to the operation)"), +        "name-attached-to-operation": +            _("Site name (attached to the operation)"), +        "attached-to-cr": _("Site (attached to the context record)"), +        "name-attached-to-cr": _("Site name (attached to the context record)"),      },      'entity': { -        'search': _(u"Archaeological entity search"), -        'new': _(u"New archaeological entity"), -        'modification': _(u"Archaeological entity modification"), -        'deletion': _(u"Archaeological entity deletion"), -        "attached-to-operation": _(u"Archaeological entity (attached to the " -                                   u"operation)"), -        "name-attached-to-operation": _(u"Archaeological entity name (attached " -                                        u"to the operation)"), -        "attached-to-cr": _(u"Archaeological entity (attached to the context " -                            u"record)"), +        'search': _("Archaeological entity search"), +        'new': _("New archaeological entity"), +        'modification': _("Archaeological entity modification"), +        'deletion': _("Archaeological entity deletion"), +        "attached-to-operation": _("Archaeological entity (attached to the " +                                   "operation)"), +        "name-attached-to-operation": _("Archaeological entity name (attached " +                                        "to the operation)"), +        "attached-to-cr": _("Archaeological entity (attached to the context " +                            "record)"),          "name-attached-to-cr": -            _(u"Archaeological entity name (attached to the context record)"), +            _("Archaeological entity name (attached to the context record)"),      },  }  class IshtarSiteProfile(models.Model, Cached):      slug_field = 'slug' -    label = models.TextField(_(u"Name")) -    slug = models.SlugField(_(u"Slug"), unique=True) -    active = models.BooleanField(_(u"Current active"), default=False) +    label = models.TextField(_("Name")) +    slug = models.SlugField(_("Slug"), unique=True) +    active = models.BooleanField(_("Current active"), default=False)      experimental_feature = models.BooleanField( -        _(u"Activate experimental feature"), default=False) -    description = models.TextField(_(u"Description"), null=True, blank=True) +        _("Activate experimental feature"), default=False) +    description = models.TextField(_("Description"), null=True, blank=True)      config = models.CharField( -        _(u"Alternate configuration"), max_length=200, +        _("Alternate configuration"), max_length=200,          choices=ALTERNATE_CONFIGS_CHOICES, -        help_text=_(u"Choose an alternate configuration for label, " -                    u"index management"), +        help_text=_("Choose an alternate configuration for label, " +                    "index management"),          null=True, blank=True      ) -    files = models.BooleanField(_(u"Files module"), default=False) +    files = models.BooleanField(_("Files module"), default=False)      archaeological_site = models.BooleanField( -        _(u"Archaeological site module"), default=False) +        _("Archaeological site module"), default=False)      archaeological_site_label = models.CharField( -        _(u"Archaeological site type"), max_length=200, +        _("Archaeological site type"), max_length=200,          choices=SITE_LABELS,          default='site'      ) -    context_record = models.BooleanField(_(u"Context records module"), +    context_record = models.BooleanField(_("Context records module"),                                           default=False) -    find = models.BooleanField(_(u"Finds module"), default=False, -                               help_text=_(u"Need context records module")) +    find = models.BooleanField(_("Finds module"), default=False, +                               help_text=_("Need context records module"))      find_index = models.CharField( -        _(u"Find index is based on"), default='O', max_length=2, +        _("Find index is based on"), default='O', max_length=2,          choices=FIND_INDEX_SOURCE, -        help_text=_(u"To prevent irrelevant indexes, change this parameter " -                    u"only if there is no find in the database")) +        help_text=_("To prevent irrelevant indexes, change this parameter " +                    "only if there is no find in the database"))      warehouse = models.BooleanField( -        _(u"Warehouses module"), default=False, -        help_text=_(u"Need finds module")) -    preservation = models.BooleanField(_(u"Preservation module"), +        _("Warehouses module"), default=False, +        help_text=_("Need finds module")) +    preservation = models.BooleanField(_("Preservation module"),                                         default=False) -    mapping = models.BooleanField(_(u"Mapping module"), default=False) +    mapping = models.BooleanField(_("Mapping module"), default=False)      locate_warehouses = models.BooleanField( -        _(u"Locate warehouse and containers"), default=False, +        _("Locate warehouse and containers"), default=False,          help_text=_( -            u"Mapping module must be activated. With many containers and " -            u"background task not activated, activating this option may " -            u"consume many resources.") +            "Mapping module must be activated. With many containers and " +            "background task not activated, activating this option may " +            "consume many resources.")      )      use_town_for_geo = models.BooleanField( -        _(u"Use town to locate when coordinates are missing"), default=True) -    underwater = models.BooleanField(_(u"Underwater module"), default=False) +        _("Use town to locate when coordinates are missing"), default=True) +    underwater = models.BooleanField(_("Underwater module"), default=False)      parcel_mandatory = models.BooleanField( -        _(u"Parcel are mandatory for context records"), default=True) +        _("Parcel are mandatory for context records"), default=True)      homepage = models.TextField( -        _(u"Home page"), null=True, blank=True, -        help_text=_(u"Homepage of Ishtar - if not defined a default homepage " -                    u"will appear. Use the markdown syntax. {random_image} " -                    u"can be used to display a random image.")) +        _("Home page"), null=True, blank=True, +        help_text=_("Homepage of Ishtar - if not defined a default homepage " +                    "will appear. Use the markdown syntax. {random_image} " +                    "can be used to display a random image."))      operation_prefix = models.CharField( -        _(u"Main operation code prefix"), default=u'OA', null=True, blank=True, +        _("Main operation code prefix"), default=u'OA', null=True, blank=True,          max_length=20      )      default_operation_prefix = models.CharField( -        _(u"Default operation code prefix"), default=u'OP', null=True, +        _("Default operation code prefix"), default=u'OP', null=True,          blank=True, max_length=20      )      operation_region_code = models.CharField( -        _(u"Operation region code"), null=True, blank=True, +        _("Operation region code"), null=True, blank=True,          max_length=5      )      file_external_id = models.TextField( -        _(u"File external id"), -        default=u"{year}-{numeric_reference}", -        help_text=_(u"Formula to manage file external ID. " -                    u"Change this with care. With incorrect formula, the " -                    u"application might be unusable and import of external " -                    u"data can be destructive.")) +        _("File external id"), +        default="{year}-{numeric_reference}", +        help_text=_("Formula to manage file external ID. " +                    "Change this with care. With incorrect formula, the " +                    "application might be unusable and import of external " +                    "data can be destructive."))      parcel_external_id = models.TextField( -        _(u"Parcel external id"), -        default=u"{associated_file__external_id}{operation__code_patriarche}-" -                u"{town__numero_insee}-{section}{parcel_number}", -        help_text=_(u"Formula to manage parcel external ID. " -                    u"Change this with care. With incorrect formula, the " -                    u"application might be unusable and import of external " -                    u"data can be destructive.")) +        _("Parcel external id"), +        default="{associated_file__external_id}{operation__code_patriarche}-" +                "{town__numero_insee}-{section}{parcel_number}", +        help_text=_("Formula to manage parcel external ID. " +                    "Change this with care. With incorrect formula, the " +                    "application might be unusable and import of external " +                    "data can be destructive."))      context_record_external_id = models.TextField( -        _(u"Context record external id"), -        default=u"{parcel__external_id}-{label}", -        help_text=_(u"Formula to manage context record external ID. " -                    u"Change this with care. With incorrect formula, the " -                    u"application might be unusable and import of external " -                    u"data can be destructive.")) +        _("Context record external id"), +        default="{parcel__external_id}-{label}", +        help_text=_("Formula to manage context record external ID. " +                    "Change this with care. With incorrect formula, the " +                    "application might be unusable and import of external " +                    "data can be destructive."))      base_find_external_id = models.TextField( -        _(u"Base find external id"), -        default=u"{context_record__external_id}-{label}", -        help_text=_(u"Formula to manage base find external ID. " -                    u"Change this with care. With incorrect formula, the " -                    u"application might be unusable and import of external " -                    u"data can be destructive.")) +        _("Base find external id"), +        default="{context_record__external_id}-{label}", +        help_text=_("Formula to manage base find external ID. " +                    "Change this with care. With incorrect formula, the " +                    "application might be unusable and import of external " +                    "data can be destructive."))      find_external_id = models.TextField( -        _(u"Find external id"), -        default=u"{get_first_base_find__context_record__external_id}-{label}", -        help_text=_(u"Formula to manage find external ID. " -                    u"Change this with care. With incorrect formula, the " -                    u"application might be unusable and import of external " -                    u"data can be destructive.")) +        _("Find external id"), +        default="{get_first_base_find__context_record__external_id}-{label}", +        help_text=_("Formula to manage find external ID. " +                    "Change this with care. With incorrect formula, the " +                    "application might be unusable and import of external " +                    "data can be destructive."))      container_external_id = models.TextField( -        _(u"Container external id"), -        default=u"{responsible__external_id}-{index}", -        help_text=_(u"Formula to manage container external ID. " -                    u"Change this with care. With incorrect formula, the " -                    u"application might be unusable and import of external " -                    u"data can be destructive.")) +        _("Container external id"), +        default="{responsible__external_id}-{index}", +        help_text=_("Formula to manage container external ID. " +                    "Change this with care. With incorrect formula, the " +                    "application might be unusable and import of external " +                    "data can be destructive."))      warehouse_external_id = models.TextField( -        _(u"Warehouse external id"), -        default=u"{name|slug}", -        help_text=_(u"Formula to manage warehouse external ID. " -                    u"Change this with care. With incorrect formula, the " -                    u"application might be unusable and import of external " -                    u"data can be destructive.")) +        _("Warehouse external id"), +        default="{name|slug}", +        help_text=_("Formula to manage warehouse external ID. " +                    "Change this with care. With incorrect formula, the " +                    "application might be unusable and import of external " +                    "data can be destructive."))      document_external_id = models.TextField( -        _(u"Document external id"), -        default=u"{index}", -        help_text=_(u"Formula to manage document external ID. " -                    u"Change this with care. With incorrect formula, the " -                    u"application might be unusable and import of external " -                    u"data can be destructive.")) +        _("Document external id"), +        default="{index}", +        help_text=_("Formula to manage document external ID. " +                    "Change this with care. With incorrect formula, the " +                    "application might be unusable and import of external " +                    "data can be destructive."))      person_raw_name = models.TextField( -        _(u"Raw name for person"), -        default=u"{name|upper} {surname}", -        help_text=_(u"Formula to manage person raw_name. " -                    u"Change this with care. With incorrect formula, the " -                    u"application might be unusable and import of external " -                    u"data can be destructive.")) -    find_use_index = models.BooleanField(_(u"Use auto index for finds"), +        _("Raw name for person"), +        default="{name|upper} {surname}", +        help_text=_("Formula to manage person raw_name. " +                    "Change this with care. With incorrect formula, the " +                    "application might be unusable and import of external " +                    "data can be destructive.")) +    find_use_index = models.BooleanField(_("Use auto index for finds"),                                           default=True) -    currency = models.CharField(_(u"Currency"), default=u"€", +    currency = models.CharField(_("Currency"), default="€",                                  choices=CURRENCY, max_length=5)      default_center = models.PointField( -        _(u"Maps - default center"), +        _("Maps - default center"),          default='SRID=4326;POINT(2.4397 46.5528)')      default_zoom = models.IntegerField( -        _(u"Maps - default zoom"), default=6) +        _("Maps - default zoom"), default=6)      class Meta: -        verbose_name = _(u"Ishtar site profile") -        verbose_name_plural = _(u"Ishtar site profiles") +        verbose_name = _("Ishtar site profile") +        verbose_name_plural = _("Ishtar site profiles")          ordering = ['label'] -    def __unicode__(self): -        return unicode(self.label) +    def __str__(self): +        return str(self.label)      def has_overload(self, key):          return self.config and self.config in ALTERNATE_CONFIGS and \ @@ -2564,8 +2559,8 @@ class IshtarSiteProfile(models.Model, Cached):      def get_site_label(self, key=None):          if not key: -            return unicode(dict(SITE_LABELS)[self.archaeological_site_label]) -        return unicode( +            return str(dict(SITE_LABELS)[self.archaeological_site_label]) +        return str(              TRANSLATED_SITE_LABELS[self.archaeological_site_label][key]          ) @@ -2614,39 +2609,39 @@ post_delete.connect(cached_site_changed, sender=IshtarSiteProfile)  class CustomForm(models.Model): -    name = models.CharField(_(u"Name"), max_length=250) -    form = models.CharField(_(u"Form"), max_length=250) -    available = models.BooleanField(_(u"Available"), default=True) +    name = models.CharField(_("Name"), max_length=250) +    form = models.CharField(_("Form"), max_length=250) +    available = models.BooleanField(_("Available"), default=True)      enabled = models.BooleanField( -        _(u"Enable this form"), default=True, -        help_text=_(u"Disable with caution: disabling a form with mandatory " -                    u"fields may lead to database errors.")) +        _("Enable this form"), default=True, +        help_text=_("Disable with caution: disabling a form with mandatory " +                    "fields may lead to database errors."))      apply_to_all = models.BooleanField( -        _(u"Apply to all"), default=False, -        help_text=_(u"Apply this form to all users. If set to True, selecting " -                    u"user and user type is useless.")) +        _("Apply to all"), default=False, +        help_text=_("Apply this form to all users. If set to True, selecting " +                    "user and user type is useless."))      users = models.ManyToManyField('IshtarUser', blank=True)      user_types = models.ManyToManyField('PersonType', blank=True)      class Meta: -        verbose_name = _(u"Custom form") -        verbose_name_plural = _(u"Custom forms") +        verbose_name = _("Custom form") +        verbose_name_plural = _("Custom forms")          ordering = ['name', 'form'] -    def __unicode__(self): -        return u"{} - {}".format(self.name, self.form) +    def __str__(self): +        return "{} - {}".format(self.name, self.form)      def users_lbl(self): -        users = [unicode(user) for user in self.users.all()] +        users = [str(user) for user in self.users.all()]          return " ; ".join(users) -    users_lbl.short_description = _(u"Users") +    users_lbl.short_description = _("Users")      def user_types_lbl(self): -        user_types = [unicode(u) for u in self.user_types.all()] +        user_types = [str(u) for u in self.user_types.all()]          return " ; ".join(user_types) -    user_types_lbl.short_description = _(u"User types") +    user_types_lbl.short_description = _("User types")      @classmethod      def register(cls): @@ -2711,7 +2706,7 @@ class CustomForm(models.Model):              ct = q.all()[0]              for json_field in JsonDataField.objects.filter(                      content_type=ct).all(): -                res.append((json_field.pk, u"{} ({})".format( +                res.append((json_field.pk, "{} ({})".format(                      json_field.name,                      dict(JSON_VALUE_TYPES)[json_field.value_type])))          return res @@ -2719,40 +2714,40 @@ class CustomForm(models.Model):  class ExcludedField(models.Model):      custom_form = models.ForeignKey(CustomForm, related_name='excluded_fields') -    field = models.CharField(_(u"Field"), max_length=250) +    field = models.CharField(_("Field"), max_length=250)      class Meta: -        verbose_name = _(u"Excluded field") -        verbose_name_plural = _(u"Excluded fields") +        verbose_name = _("Excluded field") +        verbose_name_plural = _("Excluded fields")  class CustomFormJsonField(models.Model):      custom_form = models.ForeignKey(CustomForm, related_name='json_fields')      json_field = models.ForeignKey(JsonDataField,                                     related_name='custom_form_details') -    label = models.CharField(_(u"Label"), max_length=200, blank=True, +    label = models.CharField(_("Label"), max_length=200, blank=True,                               default='') -    order = models.IntegerField(verbose_name=_(u"Order"), default=1) -    help_text = models.TextField(_(u"Help"), blank=True, null=True) +    order = models.IntegerField(verbose_name=_("Order"), default=1) +    help_text = models.TextField(_("Help"), blank=True, null=True)      class Meta: -        verbose_name = _(u"Custom form - Json data field") -        verbose_name_plural = _(u"Custom form - Json data fields") +        verbose_name = _("Custom form - Json data field") +        verbose_name_plural = _("Custom form - Json data fields")  class GlobalVar(models.Model, Cached): -    slug = models.SlugField(_(u"Variable name"), unique=True) -    description = models.TextField(_(u"Description of the variable"), +    slug = models.SlugField(_("Variable name"), unique=True) +    description = models.TextField(_("Description of the variable"),                                     null=True, blank=True) -    value = models.TextField(_(u"Value"), null=True, blank=True) +    value = models.TextField(_("Value"), null=True, blank=True)      class Meta: -        verbose_name = _(u"Global variable") -        verbose_name_plural = _(u"Global variables") +        verbose_name = _("Global variable") +        verbose_name_plural = _("Global variables")          ordering = ['slug'] -    def __unicode__(self): -        return unicode(self.slug) +    def __str__(self): +        return str(self.slug)  def cached_globalvar_changed(sender, **kwargs): @@ -2875,14 +2870,14 @@ class Dashboard(object):          if not self.total_number or not self.periods:              return          kwargs_num = copy.deepcopy(base_kwargs) -        self.serie_labels = [_(u"Total")] +        self.serie_labels = [_("Total")]          # numbers          if slice == 'year':              self.values = [('year', "",                              list(reversed(self.periods)))]              self.numbers = [model.get_by_year(year, **kwargs_num).count()                              for year in self.periods] -            self.values += [('number', _(u"Number"), +            self.values += [('number', _("Number"),                               list(reversed(self.numbers)))]          if slice == 'month':              periods = list(reversed(self.periods)) @@ -2891,10 +2886,10 @@ class Dashboard(object):              self.values = [('month', "", self.periods)]              if show_detail:                  for dpt, lbl in settings.ISHTAR_DPTS: -                    self.serie_labels.append(unicode(dpt)) -                    idx = 'number_' + unicode(dpt) +                    self.serie_labels.append(str(dpt)) +                    idx = 'number_' + str(dpt)                      kwargs_num['fltr']["towns__numero_insee__startswith"] = \ -                        unicode(dpt) +                        str(dpt)                      numbers = [model.get_by_month(*p.split('-')[:2],                                                    **kwargs_num).count()                                 for p in self.periods] @@ -2905,7 +2900,7 @@ class Dashboard(object):              self.numbers = [model.get_by_month(*p.split('-')[:2],                                                 **kwargs_num).count()                              for p in self.periods] -            self.values += [('number', _(u"Total"), +            self.values += [('number', _("Total"),                               list(self.numbers))]          # calculate          self.average = self.get_average() @@ -2929,8 +2924,8 @@ class Dashboard(object):                                                     operation_numbers)))          if operation_mode_pk:              from archaeological_operations.models import Operation -            self.operation_mode = unicode(Operation.objects -                                          .get(pk=operation_mode_pk)) +            self.operation_mode = str( +                Operation.objects.get(pk=operation_mode_pk))      def get_average(self, vals=[]):          if not vals: @@ -2954,9 +2949,10 @@ class Dashboard(object):          len_vals = len(vals)          vals.sort()          if (len_vals % 2) == 1: -            return vals[len_vals / 2] +            return vals[int(len_vals / 2)]          else: -            return (vals[len_vals / 2 - 1] + vals[len_vals / 2]) / 2.0 +            return (vals[int(len_vals / 2) - 1] + +                    vals[int(len_vals / 2)]) / 2.0      def get_mode(self, vals={}):          if not vals: @@ -2969,23 +2965,23 @@ class Dashboard(object):  class DocumentTemplate(models.Model):      CLASSNAMES = (('archaeological_operations.models.AdministrativeAct', -                   _(u"Administrative Act")),) -    name = models.CharField(_(u"Name"), max_length=100) -    slug = models.SlugField(_(u"Slug"), blank=True, null=True, max_length=100, +                   _("Administrative Act")),) +    name = models.CharField(_("Name"), max_length=100) +    slug = models.SlugField(_("Slug"), blank=True, null=True, max_length=100,                              unique=True)      template = models.FileField( -        _(u"Template"), upload_to="templates/%Y/", help_text=max_size_help()) +        _("Template"), upload_to="templates/%Y/", help_text=max_size_help())      associated_object_name = models.CharField( -        _(u"Associated object"), max_length=100, choices=CLASSNAMES) -    available = models.BooleanField(_(u"Available"), default=True) +        _("Associated object"), max_length=100, choices=CLASSNAMES) +    available = models.BooleanField(_("Available"), default=True)      objects = SlugModelManager()      class Meta: -        verbose_name = _(u"Document template") -        verbose_name_plural = _(u"Document templates") +        verbose_name = _("Document template") +        verbose_name_plural = _("Document templates")          ordering = ['associated_object_name', 'name'] -    def __unicode__(self): +    def __str__(self):          return self.name      def natural_key(self): @@ -3003,64 +2999,24 @@ class DocumentTemplate(models.Model):              yield ('', '----------')          items = cls.objects.filter(**dct)          for item in items.distinct().order_by(*cls._meta.ordering).all(): -            yield (item.pk, _(unicode(item))) +            yield (item.pk, _(str(item)))      def publish(self, c_object):          tempdir = tempfile.mkdtemp("-ishtardocs")          output_name = tempdir + os.path.sep + \                        slugify(self.name.replace(' ', '_').lower()) + u'-' + \                        datetime.date.today().strftime('%Y-%m-%d') + \ -                      u"." + self.template.name.split('.')[-1] +                      "." + self.template.name.split('.')[-1]          values = c_object.get_values()          engine = IshtarSecretaryRenderer()          try:              result = engine.render(self.template, **values)          except TemplateSyntaxError as e: -            raise TemplateSyntaxError(e.message, e.lineno) +            raise TemplateSyntaxError(str(e), e.lineno)          output = open(output_name, 'wb')          output.write(result)          return output_name -    def convert_from_v1(self): -        """ -        Convert the current template from v1 to v2. -        """ -        from old.ooo_replace import ooo_replace -        from archaeological_operations.models import AdministrativeAct - -        old_dir = settings.MEDIA_ROOT + "/templates/v1/" -        if not os.path.exists(old_dir): -            os.makedirs(old_dir) -        shutil.copy(settings.MEDIA_ROOT + self.template.name, old_dir) - -        tempdir = tempfile.mkdtemp("-ishtardocs") -        output_name = tempdir + os.path.sep + self.template.name.split( -            os.sep)[-1] - -        objects = [] -        filters = [ -            {'operation__isnull': False}, -            {'associated_file__isnull': False}, -            {'treatment_file__isnull': False}, -            {'treatment__isnull': False}, -        ] -        for filtr in filters: -            q = AdministrativeAct.objects.filter(**filtr) -            if q.count(): -                objects.append(q.all()[0]) - -        if not objects: -            return -        values = {} -        for obj in objects: -            values.update(obj.get_values()) -        for key in values: -            values[key] = "{{ " + key + " }}" - -        ooo_replace(self.template, output_name, values) -        shutil.move(output_name, settings.MEDIA_ROOT + self.template.name) -        return output_name -  class NumberManager(models.Manager):      def get_by_natural_key(self, number): @@ -3068,15 +3024,15 @@ class NumberManager(models.Manager):  class State(models.Model): -    label = models.CharField(_(u"Label"), max_length=30) -    number = models.CharField(_(u"Number"), unique=True, max_length=3) +    label = models.CharField(_("Label"), max_length=30) +    number = models.CharField(_("Number"), unique=True, max_length=3)      objects = NumberManager()      class Meta: -        verbose_name = _(u"State") +        verbose_name = _("State")          ordering = ['number'] -    def __unicode__(self): +    def __str__(self):          return self.label      def natural_key(self): @@ -3084,20 +3040,20 @@ class State(models.Model):  class Department(models.Model): -    label = models.CharField(_(u"Label"), max_length=30) -    number = models.CharField(_(u"Number"), unique=True, max_length=3) +    label = models.CharField(_("Label"), max_length=30) +    number = models.CharField(_("Number"), unique=True, max_length=3)      state = models.ForeignKey( -        'State', verbose_name=_(u"State"), blank=True, null=True, +        'State', verbose_name=_("State"), blank=True, null=True,          on_delete=models.SET_NULL,      )      objects = NumberManager()      class Meta: -        verbose_name = _(u"Department") -        verbose_name_plural = _(u"Departments") +        verbose_name = _("Department") +        verbose_name_plural = _("Departments")          ordering = ['number'] -    def __unicode__(self): +    def __str__(self):          return self.label      def natural_key(self): @@ -3120,21 +3076,21 @@ class Department(models.Model):  class Arrondissement(models.Model): -    name = models.CharField(u"Nom", max_length=30) -    department = models.ForeignKey(Department, verbose_name=u"Département") +    name = models.CharField("Nom", max_length=30) +    department = models.ForeignKey(Department, verbose_name="Département") -    def __unicode__(self): -        return settings.JOINT.join((self.name, unicode(self.department))) +    def __str__(self): +        return settings.JOINT.join((self.name, str(self.department)))  class Canton(models.Model): -    name = models.CharField(u"Nom", max_length=30) +    name = models.CharField("Nom", max_length=30)      arrondissement = models.ForeignKey(Arrondissement, -                                       verbose_name=u"Arrondissement") +                                       verbose_name="Arrondissement") -    def __unicode__(self): +    def __str__(self):          return settings.JOINT.join( -            (self.name, unicode(self.arrondissement))) +            (self.name, str(self.arrondissement)))  class TownManager(models.GeoManager): @@ -3143,30 +3099,30 @@ class TownManager(models.GeoManager):  class Town(Imported, models.Model): -    name = models.CharField(_(u"Name"), max_length=100) -    surface = models.IntegerField(_(u"Surface (m2)"), blank=True, null=True) -    center = models.PointField(_(u"Localisation"), srid=settings.SRID, +    name = models.CharField(_("Name"), max_length=100) +    surface = models.IntegerField(_("Surface (m2)"), blank=True, null=True) +    center = models.PointField(_("Localisation"), srid=settings.SRID,                                 blank=True, null=True) -    limit = models.MultiPolygonField(_(u"Limit"), blank=True, null=True) -    numero_insee = models.CharField(u"Code commune (numéro INSEE)", +    limit = models.MultiPolygonField(_("Limit"), blank=True, null=True) +    numero_insee = models.CharField("Code commune (numéro INSEE)",                                      max_length=120)      departement = models.ForeignKey( -        Department, verbose_name=_(u"Department"), +        Department, verbose_name=_("Department"),          on_delete=models.SET_NULL, null=True, blank=True)      year = models.IntegerField(          _("Year of creation"), null=True, blank=True, -        help_text=_(u"Filling this field is relevant to distinguish old towns " -                    u"from new towns.")) +        help_text=_("Filling this field is relevant to distinguish old towns " +                    "from new towns."))      children = models.ManyToManyField( -        'Town', verbose_name=_(u"Town children"), blank=True, +        'Town', verbose_name=_("Town children"), blank=True,          related_name='parents') -    cached_label = models.CharField(_(u"Cached name"), max_length=500, +    cached_label = models.CharField(_("Cached name"), max_length=500,                                      null=True, blank=True, db_index=True)      objects = TownManager()      class Meta: -        verbose_name = _(u"Town") -        verbose_name_plural = _(u"Towns") +        verbose_name = _("Town") +        verbose_name_plural = _("Towns")          if settings.COUNTRY == 'fr':              ordering = ['numero_insee']              unique_together = (('numero_insee', 'year'),) @@ -3193,7 +3149,7 @@ class Town(Imported, models.Model):                  continue          return res -    def __unicode__(self): +    def __str__(self):          if self.cached_label:              return self.cached_label          self.save() @@ -3203,11 +3159,11 @@ class Town(Imported, models.Model):      def label_with_areas(self):          label = [self.name]          if self.numero_insee: -            label.append(u"({})".format(self.numero_insee)) +            label.append("({})".format(self.numero_insee))          for area in self.areas.all(): -            label.append(u" - ") +            label.append(" - ")              label.append(area.full_label) -        return u" ".join(label) +        return " ".join(label)      def generate_geo(self, force=False):          force = self.generate_limit(force=force) @@ -3261,7 +3217,7 @@ class Town(Imported, models.Model):              return          old_num = self.numero_insee[:]          numero = old_num.split('-')[0] -        self.numero_insee = u"{}-{}".format(numero, self.year) +        self.numero_insee = "{}-{}".format(numero, self.year)          if self.numero_insee != old_num:              return True @@ -3274,9 +3230,9 @@ class Town(Imported, models.Model):                      self.numero_insee[0] not in ('0', '1', '2', '3', '4', '5',                                                   '6', '7', '8', '9'):                  dpt_len = 3 -            cached_label = u"%s - %s" % (self.name, self.numero_insee[:dpt_len]) +            cached_label = "%s - %s" % (self.name, self.numero_insee[:dpt_len])          if self.year and self.children.count(): -            cached_label += u" ({})".format(self.year) +            cached_label += " ({})".format(self.year)          return cached_label @@ -3301,74 +3257,74 @@ m2m_changed.connect(town_child_changed, sender=Town.children.through)  class Area(HierarchicalType): -    towns = models.ManyToManyField(Town, verbose_name=_(u"Towns"), blank=True, +    towns = models.ManyToManyField(Town, verbose_name=_("Towns"), blank=True,                                     related_name='areas') -    reference = models.CharField(_(u"Reference"), max_length=200, blank=True, +    reference = models.CharField(_("Reference"), max_length=200, blank=True,                                   null=True)      parent = models.ForeignKey( -        'self', blank=True, null=True, verbose_name=_(u"Parent"), -        help_text=_(u"Only four level of parent are managed."), +        'self', blank=True, null=True, verbose_name=_("Parent"), +        help_text=_("Only four level of parent are managed."),          related_name='children', on_delete=models.SET_NULL      )      class Meta: -        verbose_name = _(u"Area") -        verbose_name_plural = _(u"Areas") +        verbose_name = _("Area") +        verbose_name_plural = _("Areas")          ordering = ('label',) -    def __unicode__(self): +    def __str__(self):          if not self.reference:              return self.label -        return u"{} ({})".format(self.label, self.reference) +        return "{} ({})".format(self.label, self.reference)      @property      def full_label(self): -        label = [unicode(self)] +        label = [str(self)]          if self.parent:              label.append(self.parent.full_label) -        return u" / ".join(label) +        return " / ".join(label)  class Address(BaseHistorizedItem): -    address = models.TextField(_(u"Address"), null=True, blank=True) -    address_complement = models.TextField(_(u"Address complement"), null=True, +    address = models.TextField(_("Address"), null=True, blank=True) +    address_complement = models.TextField(_("Address complement"), null=True,                                            blank=True) -    postal_code = models.CharField(_(u"Postal code"), max_length=10, null=True, +    postal_code = models.CharField(_("Postal code"), max_length=10, null=True,                                     blank=True) -    town = models.CharField(_(u"Town (freeform)"), max_length=150, null=True, +    town = models.CharField(_("Town (freeform)"), max_length=150, null=True,                              blank=True)      precise_town = models.ForeignKey( -        Town, verbose_name=_(u"Town (precise)"), null=True, blank=True) -    country = models.CharField(_(u"Country"), max_length=30, null=True, +        Town, verbose_name=_("Town (precise)"), null=True, blank=True) +    country = models.CharField(_("Country"), max_length=30, null=True,                                 blank=True) -    alt_address = models.TextField(_(u"Other address: address"), null=True, +    alt_address = models.TextField(_("Other address: address"), null=True,                                     blank=True)      alt_address_complement = models.TextField( -        _(u"Other address: address complement"), null=True, blank=True) -    alt_postal_code = models.CharField(_(u"Other address: postal code"), +        _("Other address: address complement"), null=True, blank=True) +    alt_postal_code = models.CharField(_("Other address: postal code"),                                         max_length=10, null=True, blank=True) -    alt_town = models.CharField(_(u"Other address: town"), max_length=70, +    alt_town = models.CharField(_("Other address: town"), max_length=70,                                  null=True, blank=True) -    alt_country = models.CharField(_(u"Other address: country"), +    alt_country = models.CharField(_("Other address: country"),                                     max_length=30, null=True, blank=True) -    phone = models.CharField(_(u"Phone"), max_length=18, null=True, blank=True) -    phone_desc = models.CharField(_(u"Phone description"), max_length=300, +    phone = models.CharField(_("Phone"), max_length=18, null=True, blank=True) +    phone_desc = models.CharField(_("Phone description"), max_length=300,                                    null=True, blank=True) -    phone2 = models.CharField(_(u"Phone description 2"), max_length=18, +    phone2 = models.CharField(_("Phone description 2"), max_length=18,                                null=True, blank=True) -    phone_desc2 = models.CharField(_(u"Phone description 2"), max_length=300, +    phone_desc2 = models.CharField(_("Phone description 2"), max_length=300,                                     null=True, blank=True) -    phone3 = models.CharField(_(u"Phone 3"), max_length=18, null=True, +    phone3 = models.CharField(_("Phone 3"), max_length=18, null=True,                                blank=True) -    phone_desc3 = models.CharField(_(u"Phone description 3"), max_length=300, +    phone_desc3 = models.CharField(_("Phone description 3"), max_length=300,                                     null=True, blank=True) -    raw_phone = models.TextField(_(u"Raw phone"), blank=True, null=True) -    mobile_phone = models.CharField(_(u"Mobile phone"), max_length=18, +    raw_phone = models.TextField(_("Raw phone"), blank=True, null=True) +    mobile_phone = models.CharField(_("Mobile phone"), max_length=18,                                      null=True, blank=True)      email = models.EmailField( -        _(u"Email"), max_length=300, blank=True, null=True) +        _("Email"), max_length=300, blank=True, null=True)      alt_address_is_prefered = models.BooleanField( -        _(u"Alternative address is prefered"), default=False) +        _("Alternative address is prefered"), default=False)      history = HistoricalRecords()      class Meta: @@ -3383,12 +3339,12 @@ class Address(BaseHistorizedItem):              return self.precise_town.limit, self._meta.verbose_name      def simple_lbl(self): -        return unicode(self) +        return str(self)      def full_address(self):          lbl = self.simple_lbl()          if lbl: -            lbl += u"\n" +            lbl += "\n"          lbl += self.address_lbl()          return lbl @@ -3408,22 +3364,22 @@ class Address(BaseHistorizedItem):          if postal_code or town:              if lbl:                  lbl += "\n" -            lbl += u"{}{}{}".format( +            lbl += "{}{}{}".format(                  postal_code or '',                  " " if postal_code and town else '',                  town or '')          if self.phone:              if lbl: -                lbl += u"\n" -            lbl += u"{} {}".format(unicode(_("Tel: ")), self.phone) +                lbl += "\n" +            lbl += "{} {}".format(str(_("Tel: ")), self.phone)          if self.mobile_phone:              if lbl: -                lbl += u"\n" -            lbl += u"{} {}".format(unicode(_("Mobile: ")), self.mobile_phone) +                lbl += "\n" +            lbl += "{} {}".format(str(_("Mobile: ")), self.mobile_phone)          if self.email:              if lbl: -                lbl += u"\n" -            lbl += u"{} {}".format(unicode(_("Email: ")), self.email) +                lbl += "\n" +            lbl += "{} {}".format(str(_("Email: ")), self.email)          return lbl @@ -3464,9 +3420,9 @@ class Merge(models.Model):          if not self.MERGE_CLEMENCY:              q = q.filter(merge_key=self.merge_key)          else: -            subkeys_front = u"-".join( +            subkeys_front = "-".join(                  self.merge_key.split('-')[:self.MERGE_CLEMENCY]) -            subkeys_back = u"-".join( +            subkeys_back = "-".join(                  self.merge_key.split('-')[-self.MERGE_CLEMENCY:])              q = q.filter(Q(merge_key__istartswith=subkeys_front) |                           Q(merge_key__iendswith=subkeys_back)) @@ -3499,16 +3455,16 @@ class Merge(models.Model):  class OrganizationType(GeneralType):      class Meta: -        verbose_name = _(u"Organization type") -        verbose_name_plural = _(u"Organization types") +        verbose_name = _("Organization type") +        verbose_name_plural = _("Organization types")          ordering = ('label',)  post_save.connect(post_save_cache, sender=OrganizationType)  post_delete.connect(post_save_cache, sender=OrganizationType) -organization_type_pk_lazy = lazy(OrganizationType.get_or_create_pk, unicode) -organization_type_pks_lazy = lazy(OrganizationType.get_or_create_pks, unicode) +organization_type_pk_lazy = lazy(OrganizationType.get_or_create_pk, str) +organization_type_pks_lazy = lazy(OrganizationType.get_or_create_pks, str)  class OrganizationManager(models.Manager): @@ -3529,11 +3485,11 @@ class Organization(Address, Merge, OwnPerms, ValueGetter):      # alternative names of fields for searches      ALT_NAMES = {          'name': SearchAltName( -            pgettext_lazy("key for text search", u"name"), +            pgettext_lazy("key for text search", "name"),              'name__iexact'          ),          'organization_type': SearchAltName( -            pgettext_lazy("key for text search", u"type"), +            pgettext_lazy("key for text search", "type"),              'organization_type__label__iexact'          ),      } @@ -3541,34 +3497,34 @@ class Organization(Address, Merge, OwnPerms, ValueGetter):      objects = OrganizationManager()      # fields -    name = models.CharField(_(u"Name"), max_length=500) +    name = models.CharField(_("Name"), max_length=500)      organization_type = models.ForeignKey(OrganizationType, -                                          verbose_name=_(u"Type")) -    cached_label = models.TextField(_(u"Cached name"), null=True, blank=True, +                                          verbose_name=_("Type")) +    cached_label = models.TextField(_("Cached name"), null=True, blank=True,                                      db_index=True)      history = HistoricalRecords()      class Meta: -        verbose_name = _(u"Organization") -        verbose_name_plural = _(u"Organizations") +        verbose_name = _("Organization") +        verbose_name_plural = _("Organizations")          permissions = ( -            ("view_organization", u"Can view all Organizations"), -            ("view_own_organization", u"Can view own Organization"), -            ("add_own_organization", u"Can add own Organization"), -            ("change_own_organization", u"Can change own Organization"), -            ("delete_own_organization", u"Can delete own Organization"), +            ("view_organization", "Can view all Organizations"), +            ("view_own_organization", "Can view own Organization"), +            ("add_own_organization", "Can add own Organization"), +            ("change_own_organization", "Can change own Organization"), +            ("delete_own_organization", "Can delete own Organization"),          )      def simple_lbl(self):          if self.name:              return self.name -        return u"{} - {}".format(self.organization_type, +        return "{} - {}".format(self.organization_type,                                   self.town or "")      def natural_key(self):          return (self.name, self.organization_type.txt_idx) -    def __unicode__(self): +    def __str__(self):          if self.cached_label:              return self.cached_label          self.save() @@ -3578,11 +3534,11 @@ class Organization(Address, Merge, OwnPerms, ValueGetter):          if self.name:              return self.name          attrs = ["organization_type", "address", "town"] -        items = [unicode(getattr(self, attr)) +        items = [str(getattr(self, attr))                   for attr in attrs if getattr(self, attr)]          if not items: -            items = [unicode(_(u"unknown organization"))] -        return u" - ".join(items) +            items = [str(_("unknown organization"))] +        return " - ".join(items)      def generate_merge_key(self):          self.merge_key = slugify(self.name if self.name else '') @@ -3595,10 +3551,10 @@ class Organization(Address, Merge, OwnPerms, ValueGetter):      @property      def associated_filename(self): -        values = [unicode(getattr(self, attr)) +        values = [str(getattr(self, attr))                    for attr in ('organization_type', 'name')                    if getattr(self, attr)] -        return slugify(u"-".join(values)) +        return slugify("-".join(values))  post_save.connect(cached_label_changed, sender=Organization) @@ -3606,22 +3562,22 @@ post_save.connect(cached_label_changed, sender=Organization)  class PersonType(GeneralType):      class Meta: -        verbose_name = _(u"Person type") -        verbose_name_plural = _(u"Person types") +        verbose_name = _("Person type") +        verbose_name_plural = _("Person types")          ordering = ('label',)  post_save.connect(post_save_cache, sender=PersonType)  post_delete.connect(post_save_cache, sender=PersonType) -person_type_pk_lazy = lazy(PersonType.get_or_create_pk, unicode) -person_type_pks_lazy = lazy(PersonType.get_or_create_pks, unicode) +person_type_pk_lazy = lazy(PersonType.get_or_create_pk, str) +person_type_pks_lazy = lazy(PersonType.get_or_create_pks, str)  class TitleType(GeneralType):      class Meta: -        verbose_name = _(u"Title type") -        verbose_name_plural = _(u"Title types") +        verbose_name = _("Title type") +        verbose_name_plural = _("Title types")          ordering = ('label',) @@ -3673,33 +3629,33 @@ class Person(Address, Merge, OwnPerms, ValueGetter, MainItem):          'attached_to': 'attached_to',      }      COL_LABELS = { -        'attached_to': _(u"Organization") +        'attached_to': _("Organization")      }      # alternative names of fields for searches      ALT_NAMES = {          'name': SearchAltName( -            pgettext_lazy("key for text search", u"name"), +            pgettext_lazy("key for text search", "name"),              'name__iexact'          ),          'surname': SearchAltName( -            pgettext_lazy("key for text search", u"surname"), +            pgettext_lazy("key for text search", "surname"),              'surname__iexact'          ),          'email': SearchAltName( -            pgettext_lazy("key for text search", u"email"), +            pgettext_lazy("key for text search", "email"),              'email__iexact'          ),          'person_types': SearchAltName( -            pgettext_lazy("key for text search", u"type"), +            pgettext_lazy("key for text search", "type"),              'person_types__label__iexact'          ),          'attached_to': SearchAltName( -            pgettext_lazy("key for text search", u"organization"), +            pgettext_lazy("key for text search", "organization"),              'attached_to__cached_label__iexact'          ),          'ishtaruser__isnull': SearchAltName( -            pgettext_lazy("key for text search", u"has-account"), +            pgettext_lazy("key for text search", "has-account"),              'ishtaruser__isnull'          ),      } @@ -3714,39 +3670,39 @@ class Person(Address, Merge, OwnPerms, ValueGetter, MainItem):      objects = PersonManager()      # fields -    old_title = models.CharField(_(u"Title"), max_length=100, choices=TYPE, +    old_title = models.CharField(_("Title"), max_length=100, choices=TYPE,                                   blank=True, null=True) -    title = models.ForeignKey(TitleType, verbose_name=_(u"Title"), +    title = models.ForeignKey(TitleType, verbose_name=_("Title"),                                on_delete=models.SET_NULL,                                blank=True, null=True) -    salutation = models.CharField(_(u"Salutation"), max_length=200, +    salutation = models.CharField(_("Salutation"), max_length=200,                                    blank=True, null=True) -    surname = models.CharField(_(u"Surname"), max_length=50, blank=True, +    surname = models.CharField(_("Surname"), max_length=50, blank=True,                                 null=True) -    name = models.CharField(_(u"Name"), max_length=200, blank=True, +    name = models.CharField(_("Name"), max_length=200, blank=True,                              null=True) -    raw_name = models.CharField(_(u"Raw name"), max_length=300, blank=True, +    raw_name = models.CharField(_("Raw name"), max_length=300, blank=True,                                  null=True) -    contact_type = models.CharField(_(u"Contact type"), max_length=300, +    contact_type = models.CharField(_("Contact type"), max_length=300,                                      blank=True, null=True) -    comment = models.TextField(_(u"Comment"), blank=True, null=True) -    person_types = models.ManyToManyField(PersonType, verbose_name=_(u"Types")) +    comment = models.TextField(_("Comment"), blank=True, null=True) +    person_types = models.ManyToManyField(PersonType, verbose_name=_("Types"))      attached_to = models.ForeignKey(          'Organization', related_name='members', on_delete=models.SET_NULL, -        verbose_name=_(u"Is attached to"), blank=True, null=True) -    cached_label = models.TextField(_(u"Cached name"), null=True, blank=True, +        verbose_name=_("Is attached to"), blank=True, null=True) +    cached_label = models.TextField(_("Cached name"), null=True, blank=True,                                      db_index=True)      history = HistoricalRecords()      class Meta: -        verbose_name = _(u"Person") -        verbose_name_plural = _(u"Persons") +        verbose_name = _("Person") +        verbose_name_plural = _("Persons")          permissions = ( -            ("view_person", u"Can view all Persons"), -            ("view_own_person", u"Can view own Person"), -            ("add_own_person", u"Can add own Person"), -            ("change_own_person", u"Can change own Person"), -            ("delete_own_person", u"Can delete own Person"), +            ("view_person", "Can view all Persons"), +            ("view_own_person", "Can view own Person"), +            ("add_own_person", "Can add own Person"), +            ("change_own_person", "Can change own Person"), +            ("delete_own_person", "Can delete own Person"),          )      def natural_key(self): @@ -3757,8 +3713,8 @@ class Person(Address, Merge, OwnPerms, ValueGetter, MainItem):      @property      def full_title(self): -        return u" ".join( -            [unicode(getattr(self, attr)) +        return " ".join( +            [str(getattr(self, attr))               for attr in ['title', 'salutation'] if getattr(self, attr)])      @property @@ -3777,13 +3733,13 @@ class Person(Address, Merge, OwnPerms, ValueGetter, MainItem):          return profile      def simple_lbl(self): -        values = [unicode(getattr(self, attr)) for attr in ('surname', 'name') +        values = [str(getattr(self, attr)) for attr in ('surname', 'name')                    if getattr(self, attr)]          if not values and self.raw_name:              values = [self.raw_name] -        return u" ".join(values) +        return " ".join(values) -    def __unicode__(self): +    def __str__(self):          if self.cached_label:              return self.cached_label          self.save() @@ -3792,26 +3748,26 @@ class Person(Address, Merge, OwnPerms, ValueGetter, MainItem):      def _generate_cached_label(self):          lbl = get_external_id('person_raw_name', self)          if not lbl: -            return u"-" +            return "-"          if self.attached_to: -            attached_to = unicode(self.attached_to) -            lbl += u" ({})".format(attached_to) +            attached_to = str(self.attached_to) +            lbl += " ({})".format(attached_to)          return lbl      def fancy_str(self):          values = ["<strong>"] -        values += [unicode(getattr(self, attr)) for attr in ('surname', 'name') +        values += [str(getattr(self, attr)) for attr in ('surname', 'name')                     if getattr(self, attr)]          if not values and self.raw_name:              values += [self.raw_name]          values += ["</strong>"]          if self.attached_to: -            attached_to = unicode(self.attached_to) +            attached_to = str(self.attached_to)              if values:                  values.append(u'-')              values.append(attached_to) -        return u" ".join(values) +        return " ".join(values)      def get_values(self, prefix='', no_values=False):          values = super(Person, self).get_values(prefix=prefix, @@ -3821,17 +3777,17 @@ class Person(Address, Merge, OwnPerms, ValueGetter, MainItem):                  Person.get_empty_values(prefix=prefix + 'attached_to_'))          return values -    person_types_list_lbl = _(u"Types") +    person_types_list_lbl = _("Types")      @property      def person_types_list(self): -        return u", ".join([unicode(pt) for pt in self.person_types.all()]) +        return ", ".join([str(pt) for pt in self.person_types.all()]) -    profiles_list_lbl = _(u"Profiles") +    profiles_list_lbl = _("Profiles")      @property      def profiles_list(self): -        return u", ".join([unicode(p) for p in self.profiles.all()]) +        return ", ".join([str(p) for p in self.profiles.all()])      def generate_merge_key(self):          if self.name and self.name.strip(): @@ -3899,21 +3855,21 @@ class Person(Address, Merge, OwnPerms, ValueGetter, MainItem):          values = []          if self.title:              values = [self.title.label] -        values += [unicode(getattr(self, attr)) +        values += [str(getattr(self, attr))                     for attr in ('salutation', 'surname', 'name')                     if getattr(self, attr)]          if not values and self.raw_name:              values = [self.raw_name]          if self.attached_to: -            values.append(u"- " + unicode(self.attached_to)) -        return u" ".join(values) +            values.append("- " + str(self.attached_to)) +        return " ".join(values)      @property      def associated_filename(self): -        values = [unicode(getattr(self, attr)) +        values = [str(getattr(self, attr))                    for attr in ('surname', 'name', 'attached_to')                    if getattr(self, attr)] -        return slugify(u"-".join(values)) +        return slugify("-".join(values))      def docs_q(self):          return Document.objects.filter(authors__person=self) @@ -3959,12 +3915,12 @@ post_save.connect(cached_label_changed, sender=Person)  class ProfileType(GeneralType): -    groups = models.ManyToManyField(Group, verbose_name=_(u"Groups"), +    groups = models.ManyToManyField(Group, verbose_name=_("Groups"),                                      blank=True)      class Meta: -        verbose_name = _(u"Profile type") -        verbose_name_plural = _(u"Profile types") +        verbose_name = _("Profile type") +        verbose_name_plural = _("Profile types")          ordering = ('label',) @@ -3975,36 +3931,36 @@ post_delete.connect(post_save_cache, sender=ProfileType)  class ProfileTypeSummary(ProfileType):      class Meta:          proxy = True -        verbose_name = _(u"Profile type summary") -        verbose_name_plural = _(u"Profile types summary") +        verbose_name = _("Profile type summary") +        verbose_name_plural = _("Profile types summary")  class UserProfile(models.Model): -    name = models.CharField(_(u"Name"), blank=True, default=u"", max_length=100) +    name = models.CharField(_("Name"), blank=True, default="", max_length=100)      profile_type = models.ForeignKey( -        ProfileType, verbose_name=_(u"Profile type")) -    areas = models.ManyToManyField("Area", verbose_name=_(u"Areas"), +        ProfileType, verbose_name=_("Profile type")) +    areas = models.ManyToManyField("Area", verbose_name=_("Areas"),                                     blank=True, related_name='profiles') -    current = models.BooleanField(_(u"Current profile"), default=False) +    current = models.BooleanField(_("Current profile"), default=False)      show_field_number = models.BooleanField( -        _(u"Show field number"), default=False) -    auto_pin = models.BooleanField(_(u"Automatically pin"), default=False) -    display_pin_menu = models.BooleanField(_(u"Display pin menu"), +        _("Show field number"), default=False) +    auto_pin = models.BooleanField(_("Automatically pin"), default=False) +    display_pin_menu = models.BooleanField(_("Display pin menu"),                                             default=False)      person = models.ForeignKey( -        Person, verbose_name=_(u"Person"), related_name='profiles') +        Person, verbose_name=_("Person"), related_name='profiles')      class Meta: -        verbose_name = _(u"User profile") -        verbose_name_plural = _(u"User profiles") +        verbose_name = _("User profile") +        verbose_name_plural = _("User profiles")          unique_together = (('name', 'profile_type', 'person'),) -    def __unicode__(self): -        lbl = self.name or unicode(self.profile_type) +    def __str__(self): +        lbl = self.name or str(self.profile_type)          if not self.areas.count():              return lbl -        return u"{} ({})".format(lbl, u", ".join( -            [unicode(area) for area in self.areas.all()])) +        return "{} ({})".format(lbl, ", ".join( +            [str(area) for area in self.areas.all()]))      @property      def query_towns(self): @@ -4017,7 +3973,7 @@ class UserProfile(models.Model):      @property      def area_labels(self): -        return u", ".join([unicode(area) for area in self.areas.all()]) +        return ", ".join([str(area) for area in self.areas.all()])      def duplicate(self, **kwargs):          areas = [area for area in self.areas.all()] @@ -4031,7 +3987,7 @@ class UserProfile(models.Model):          while UserProfile.objects.filter(                  name=name, profile_type=self.profile_type,                  person=self.person).count(): -            name += unicode(_(u" - duplicate")) +            name += str(_(" - duplicate"))          new_item.name = name          new_item.save()          for area in areas: @@ -4090,34 +4046,34 @@ class IshtarUser(FullSearch):      }      COL_LABELS = { -        'person__attached_to__name': _(u"Organization"), -        'username': _(u"Username") +        'person__attached_to__name': _("Organization"), +        'username': _("Username")      }      # alternative names of fields for searches      ALT_NAMES = {          'username': SearchAltName( -            pgettext_lazy("key for text search", u"username"), +            pgettext_lazy("key for text search", "username"),              'user_ptr__username__iexact'          ),          'name': SearchAltName( -            pgettext_lazy("key for text search", u"name"), +            pgettext_lazy("key for text search", "name"),              'person__name__iexact'          ),          'surname': SearchAltName( -            pgettext_lazy("key for text search", u"surname"), +            pgettext_lazy("key for text search", "surname"),              'person__surname__iexact'          ),          'email': SearchAltName( -            pgettext_lazy("key for text search", u"email"), +            pgettext_lazy("key for text search", "email"),              'person__email__iexact'          ),          'person_types': SearchAltName( -            pgettext_lazy("key for text search", u"type"), +            pgettext_lazy("key for text search", "type"),              'person__person_types__label__iexact'          ),          'attached_to': SearchAltName( -            pgettext_lazy("key for text search", u"organization"), +            pgettext_lazy("key for text search", "organization"),              'person__attached_to__cached_label__iexact'          ),      } @@ -4125,17 +4081,17 @@ class IshtarUser(FullSearch):      # fields      user_ptr = models.OneToOneField(User, primary_key=True,                                      related_name='ishtaruser') -    person = models.OneToOneField(Person, verbose_name=_(u"Person"), +    person = models.OneToOneField(Person, verbose_name=_("Person"),                                    related_name='ishtaruser')      advanced_shortcut_menu = models.BooleanField( -        _(u"Advanced shortcut menu"), default=False) +        _("Advanced shortcut menu"), default=False)      class Meta: -        verbose_name = _(u"Ishtar user") -        verbose_name_plural = _(u"Ishtar users") +        verbose_name = _("Ishtar user") +        verbose_name_plural = _("Ishtar users") -    def __unicode__(self): -        return unicode(self.person) +    def __str__(self): +        return str(self.person)      def show_field_number(self, update=False):          cache_key, value = get_cache(self.__class__, ['show_field_number']) @@ -4155,8 +4111,8 @@ class IshtarUser(FullSearch):              return vals['name'] or vals['profile_type__label']          profile = self.person.current_profile          if not profile: -            return u"" -        return unicode(profile) +            return "" +        return str(profile)      @property      def current_profile(self): @@ -4210,19 +4166,19 @@ class Basket(FullSearch, OwnPerms):      Subclass must be defined with an "items" ManyToManyField      """      IS_BASKET = True -    label = models.CharField(_(u"Label"), max_length=1000) -    comment = models.TextField(_(u"Comment"), blank=True, null=True) +    label = models.CharField(_("Label"), max_length=1000) +    comment = models.TextField(_("Comment"), blank=True, null=True)      user = models.ForeignKey(          IshtarUser, blank=True, null=True, related_name='%(class)ss',          on_delete=models.SET_NULL, -        verbose_name=_(u"Owner")) -    available = models.BooleanField(_(u"Available"), default=True) +        verbose_name=_("Owner")) +    available = models.BooleanField(_("Available"), default=True)      shared_with = models.ManyToManyField( -        IshtarUser, verbose_name=_(u"Shared (read) with"), blank=True, +        IshtarUser, verbose_name=_("Shared (read) with"), blank=True,          related_name='shared_%(class)ss'      )      shared_write_with = models.ManyToManyField( -        IshtarUser, verbose_name=_(u"Shared (read/edit) with"), blank=True, +        IshtarUser, verbose_name=_("Shared (read/edit) with"), blank=True,          related_name='shared_write_%(class)ss'      ) @@ -4240,7 +4196,7 @@ class Basket(FullSearch, OwnPerms):          ordering = ('label', )          unique_together = (('label', 'user'),) -    def __unicode__(self): +    def __str__(self):          return self.label      @classmethod @@ -4253,11 +4209,11 @@ class Basket(FullSearch, OwnPerms):      @property      def cached_label(self): -        return unicode(self) +        return str(self)      @property      def full_label(self): -        return u"{} - {} ({})".format(self.label, self.user, self.items.count()) +        return "{} - {} ({})".format(self.label, self.user, self.items.count())      @classmethod      def get_short_menu_class(cls, pk): @@ -4293,7 +4249,7 @@ class Basket(FullSearch, OwnPerms):              label = new_item.label          while self.__class__.objects.filter(                  label=label, user=new_item.user).count(): -            label += unicode(_(u" - duplicate")) +            label += str(_(" - duplicate"))          new_item.label = label          new_item.save()          for item in items: @@ -4302,11 +4258,11 @@ class Basket(FullSearch, OwnPerms):  class AuthorType(GeneralType): -    order = models.IntegerField(_(u"Order"), default=1) +    order = models.IntegerField(_("Order"), default=1)      class Meta: -        verbose_name = _(u"Author type") -        verbose_name_plural = _(u"Author types") +        verbose_name = _("Author type") +        verbose_name_plural = _("Author types")          ordering = ['order', 'label'] @@ -4332,26 +4288,26 @@ class Author(FullSearch):      PARENT_SEARCH_VECTORS = ['person']      SLUG = "author" -    person = models.ForeignKey(Person, verbose_name=_(u"Person"), +    person = models.ForeignKey(Person, verbose_name=_("Person"),                                 related_name='author') -    author_type = models.ForeignKey(AuthorType, verbose_name=_(u"Author type")) -    cached_label = models.TextField(_(u"Cached name"), null=True, blank=True, +    author_type = models.ForeignKey(AuthorType, verbose_name=_("Author type")) +    cached_label = models.TextField(_("Cached name"), null=True, blank=True,                                      db_index=True)      objects = AuthorManager()      class Meta: -        verbose_name = _(u"Author") -        verbose_name_plural = _(u"Authors") +        verbose_name = _("Author") +        verbose_name_plural = _("Authors")          ordering = ('author_type__order', 'person__name')          permissions = ( -            ("view_author", u"Can view all Authors"), -            ("view_own_author", u"Can view own Author"), -            ("add_own_author", u"Can add own Author"), -            ("change_own_author", u"Can change own Author"), -            ("delete_own_author", u"Can delete own Author"), +            ("view_author", "Can view all Authors"), +            ("view_own_author", "Can view own Author"), +            ("add_own_author", "Can add own Author"), +            ("change_own_author", "Can change own Author"), +            ("delete_own_author", "Can delete own Author"),          ) -    def __unicode__(self): +    def __str__(self):          if self.cached_label:              return self.cached_label          self.save() @@ -4361,12 +4317,12 @@ class Author(FullSearch):          return self.person.natural_key() + (self.author_type.txt_idx,)      def _generate_cached_label(self): -        return unicode(self.person) + settings.JOINT + \ -               unicode(self.author_type) +        return str(self.person) + settings.JOINT + \ +               str(self.author_type)      def fancy_str(self):          return self.person.fancy_str() + settings.JOINT + \ -               unicode(self.author_type) +               str(self.author_type)      def related_sources(self):          return list(self.treatmentsource_related.all()) + \ @@ -4380,8 +4336,8 @@ post_save.connect(cached_label_changed, sender=Author)  class SourceType(HierarchicalType):      class Meta: -        verbose_name = _(u"Source type") -        verbose_name_plural = _(u"Source types") +        verbose_name = _("Source type") +        verbose_name_plural = _("Source types")          ordering = ['label'] @@ -4391,8 +4347,8 @@ post_delete.connect(post_save_cache, sender=SourceType)  class SupportType(GeneralType):      class Meta: -        verbose_name = _(u"Support type") -        verbose_name_plural = _(u"Support types") +        verbose_name = _("Support type") +        verbose_name_plural = _("Support types")  post_save.connect(post_save_cache, sender=SupportType) @@ -4401,8 +4357,8 @@ post_delete.connect(post_save_cache, sender=SupportType)  class Format(GeneralType):      class Meta: -        verbose_name = _(u"Format type") -        verbose_name_plural = _(u"Format types") +        verbose_name = _("Format type") +        verbose_name_plural = _("Format types")          ordering = ['label'] @@ -4411,11 +4367,11 @@ post_delete.connect(post_save_cache, sender=Format)  class LicenseType(GeneralType): -    url = models.URLField(_(u"URL"), blank=True, null=True) +    url = models.URLField(_("URL"), blank=True, null=True)      class Meta: -        verbose_name = _(u"License type") -        verbose_name_plural = _(u"License types") +        verbose_name = _("License type") +        verbose_name_plural = _("License types")          ordering = ('label',) @@ -4437,7 +4393,7 @@ class Document(BaseHistorizedItem, OwnPerms, ImageModel, ValueGetter, MainItem):          'warehouses', 'containers', 'treatments', 'treatment_files',      ]      SLUG = 'document' -    LINK_SPLIT = u"<||>" +    LINK_SPLIT = "<||>"      GET_VALUES_EXCLUDE_FIELDS = ValueGetter.GET_VALUES_EXCLUDE_FIELDS + [          "warehouses", "operations", "treatments", @@ -4469,7 +4425,7 @@ class Document(BaseHistorizedItem, OwnPerms, ImageModel, ValueGetter, MainItem):      BOOL_FIELDS = ['duplicate'] -    COL_LABELS = {"authors__cached_label": _(u"Authors")} +    COL_LABELS = {"authors__cached_label": _("Authors")}      CACHED_LABELS = ['cache_related_label']      EXTRA_REQUEST_KEYS = { @@ -4488,71 +4444,71 @@ class Document(BaseHistorizedItem, OwnPerms, ImageModel, ValueGetter, MainItem):      # alternative names of fields for searches      ALT_NAMES = {          'authors': SearchAltName( -            pgettext_lazy("key for text search", u"author"), +            pgettext_lazy("key for text search", "author"),              'authors__cached_label__iexact'          ),          'title': SearchAltName( -            pgettext_lazy("key for text search", u"title"), +            pgettext_lazy("key for text search", "title"),              'title__iexact'          ),          'source_type': SearchAltName( -            pgettext_lazy("key for text search", u"type"), +            pgettext_lazy("key for text search", "type"),              'source_type__label__iexact'          ),          'reference': SearchAltName( -            pgettext_lazy("key for text search", u"reference"), +            pgettext_lazy("key for text search", "reference"),              'reference__iexact'          ),          'internal_reference': SearchAltName( -            pgettext_lazy("key for text search", u"internal-reference"), +            pgettext_lazy("key for text search", "internal-reference"),              'internal_reference__iexact'          ),          'description': SearchAltName( -            pgettext_lazy("key for text search", u"description"), +            pgettext_lazy("key for text search", "description"),              'description__iexact'          ),          'comment': SearchAltName( -            pgettext_lazy("key for text search", u"comment"), +            pgettext_lazy("key for text search", "comment"),              'comment__iexact'          ),          'additional_information': SearchAltName( -            pgettext_lazy("key for text search", u"additional-information"), +            pgettext_lazy("key for text search", "additional-information"),              'additional_information__iexact'          ),          'duplicate': SearchAltName( -            pgettext_lazy("key for text search", u"has-duplicate"), +            pgettext_lazy("key for text search", "has-duplicate"),              'duplicate'          ),          'operation': SearchAltName( -            pgettext_lazy("key for text search", u"operation"), +            pgettext_lazy("key for text search", "operation"),              'operations__cached_label__iexact'          ),          'context_record': SearchAltName( -            pgettext_lazy("key for text search", u"context-record"), +            pgettext_lazy("key for text search", "context-record"),              'context_records__cached_label__iexact'          ),          'find': SearchAltName( -            pgettext_lazy("key for text search", u"find"), +            pgettext_lazy("key for text search", "find"),              'finds__cached_label__iexact'          ),          'find__denomination': SearchAltName( -            pgettext_lazy("key for text search", u"find-denomination"), +            pgettext_lazy("key for text search", "find-denomination"),              'finds__denomination__iexact'          ),          'file': SearchAltName( -            pgettext_lazy("key for text search", u"file"), +            pgettext_lazy("key for text search", "file"),              'files__cached_label__iexact'          ),          'container': SearchAltName( -            pgettext_lazy("key for text search", u"container"), +            pgettext_lazy("key for text search", "container"),              'containers__cached_label__iexact'          ),          'site': SearchAltName( -            pgettext_lazy("key for text search", u"site"), +            pgettext_lazy("key for text search", "site"),              'sites__cached_label__iexact'          ),          'warehouse': SearchAltName( -            pgettext_lazy("key for text search", u"warehouse"), +            pgettext_lazy("key for text search", "warehouse"),              'warehouses__name__iexact'          ),      } @@ -4571,19 +4527,19 @@ class Document(BaseHistorizedItem, OwnPerms, ImageModel, ValueGetter, MainItem):      ]      UP_MODEL_QUERY = { -        "operation": (pgettext_lazy("key for text search", u"operation"), +        "operation": (pgettext_lazy("key for text search", "operation"),                        'cached_label'),          "contextrecord": (pgettext_lazy("key for text search", -                                        u"context-record"), 'cached_label'), -        "file": (pgettext_lazy("key for text search", u"file"), 'cached_label'), -        "find": (pgettext_lazy("key for text search", u"find"), 'cached_label'), -        "site": (pgettext_lazy("key for text search", u"site"), 'cached_label'), -        "warehouse": (pgettext_lazy("key for text search", u"warehouse"), +                                        "context-record"), 'cached_label'), +        "file": (pgettext_lazy("key for text search", "file"), 'cached_label'), +        "find": (pgettext_lazy("key for text search", "find"), 'cached_label'), +        "site": (pgettext_lazy("key for text search", "site"), 'cached_label'), +        "warehouse": (pgettext_lazy("key for text search", "warehouse"),                        'cached_label'), -        "treatment": (pgettext_lazy("key for text search", u"treatment"), +        "treatment": (pgettext_lazy("key for text search", "treatment"),                        'cached_label'),          "treatmentfile": (pgettext_lazy("key for text search", -                                        u"treatment-file"), 'cached_label'), +                                        "treatment-file"), 'cached_label'),      }      QA_EDIT = QuickAction(          url="document-qa-bulk-update", icon_class="fa fa-pencil", @@ -4593,74 +4549,74 @@ class Document(BaseHistorizedItem, OwnPerms, ImageModel, ValueGetter, MainItem):          QA_EDIT      ] -    title = models.TextField(_(u"Title"), blank=True, default='') +    title = models.TextField(_("Title"), blank=True, default='')      associated_file = models.FileField(          upload_to=get_image_path, blank=True, null=True, max_length=255,          help_text=max_size_help()) -    index = models.IntegerField(verbose_name=_(u"Index"), blank=True, +    index = models.IntegerField(verbose_name=_("Index"), blank=True,                                  null=True) -    external_id = models.TextField(_(u"External ID"), null=True, blank=True) -    reference = models.TextField(_(u"Ref."), null=True, blank=True) -    internal_reference = models.TextField(_(u"Internal ref."), null=True, +    external_id = models.TextField(_("External ID"), null=True, blank=True) +    reference = models.TextField(_("Ref."), null=True, blank=True) +    internal_reference = models.TextField(_("Internal ref."), null=True,                                            blank=True) -    source_type = models.ForeignKey(SourceType, verbose_name=_(u"Type"), +    source_type = models.ForeignKey(SourceType, verbose_name=_("Type"),                                      on_delete=models.SET_NULL,                                      null=True, blank=True) -    licenses = models.ManyToManyField(LicenseType, verbose_name=_(u"License"), +    licenses = models.ManyToManyField(LicenseType, verbose_name=_("License"),                                        blank=True) -    support_type = models.ForeignKey(SupportType, verbose_name=_(u"Support"), +    support_type = models.ForeignKey(SupportType, verbose_name=_("Support"),                                       on_delete=models.SET_NULL,                                       blank=True, null=True, ) -    format_type = models.ForeignKey(Format, verbose_name=_(u"Format"), +    format_type = models.ForeignKey(Format, verbose_name=_("Format"),                                      on_delete=models.SET_NULL,                                      blank=True, null=True) -    scale = models.CharField(_(u"Scale"), max_length=30, null=True, +    scale = models.CharField(_("Scale"), max_length=30, null=True,                               blank=True) -    authors = models.ManyToManyField(Author, verbose_name=_(u"Authors"), +    authors = models.ManyToManyField(Author, verbose_name=_("Authors"),                                       related_name="documents") -    authors_raw = models.CharField(verbose_name=_(u"Authors (raw)"), +    authors_raw = models.CharField(verbose_name=_("Authors (raw)"),                                     blank=True, null=True, max_length=250)      associated_url = models.URLField(          blank=True, null=True, max_length=1000, -        verbose_name=_(u"Numerical ressource (web address)")) +        verbose_name=_("Numerical ressource (web address)"))      receipt_date = models.DateField(blank=True, null=True, -                                    verbose_name=_(u"Receipt date")) +                                    verbose_name=_("Receipt date"))      creation_date = models.DateField(blank=True, null=True, -                                     verbose_name=_(u"Creation date")) +                                     verbose_name=_("Creation date"))      receipt_date_in_documentation = models.DateField(          blank=True, null=True, -        verbose_name=_(u"Receipt date in documentation")) -    item_number = models.IntegerField(_(u"Number of items"), default=1) -    description = models.TextField(_(u"Description"), blank=True, null=True) -    comment = models.TextField(_(u"Comment"), blank=True, null=True) -    additional_information = models.TextField(_(u"Additional information"), +        verbose_name=_("Receipt date in documentation")) +    item_number = models.IntegerField(_("Number of items"), default=1) +    description = models.TextField(_("Description"), blank=True, null=True) +    comment = models.TextField(_("Comment"), blank=True, null=True) +    additional_information = models.TextField(_("Additional information"),                                                blank=True, null=True) -    duplicate = models.NullBooleanField(_(u"Has a duplicate"), blank=True, +    duplicate = models.NullBooleanField(_("Has a duplicate"), blank=True,                                          null=True) -    associated_links = models.TextField(_(u"Symbolic links"), blank=True, +    associated_links = models.TextField(_("Symbolic links"), blank=True,                                          null=True)      cache_related_label = models.TextField( -        _(u"Related"), blank=True, null=True, db_index=True, -        help_text=_(u"Cached value - do not edit")) +        _("Related"), blank=True, null=True, db_index=True, +        help_text=_("Cached value - do not edit"))      class Meta: -        verbose_name = _(u"Document") -        verbose_name_plural = _(u"Documents") +        verbose_name = _("Document") +        verbose_name_plural = _("Documents")          ordering = ('title',)          permissions = (              ("view_document", -             ugettext(u"Can view all Documents")), +             ugettext("Can view all Documents")),              ("view_own_document", -             ugettext(u"Can view own Document")), +             ugettext("Can view own Document")),              ("add_own_document", -             ugettext(u"Can add own Document")), +             ugettext("Can add own Document")),              ("change_own_document", -             ugettext(u"Can change own Document")), +             ugettext("Can change own Document")),              ("delete_own_document", -             ugettext(u"Can delete own Document")), +             ugettext("Can delete own Document")),          ) -    def __unicode__(self): +    def __str__(self):          return self.title      def natural_key(self): @@ -4670,8 +4626,8 @@ class Document(BaseHistorizedItem, OwnPerms, ImageModel, ValueGetter, MainItem):      @property      def code(self):          if not self.index: -            return u"{}-".format(self.operation.code_patriarche or '') -        return u"{}-{:04d}".format(self.operation.code_patriarche or '', +            return "{}-".format(self.operation.code_patriarche or '') +        return "{}-{:04d}".format(self.operation.code_patriarche or '',                                     self.index)      """ @@ -4738,10 +4694,10 @@ class Document(BaseHistorizedItem, OwnPerms, ImageModel, ValueGetter, MainItem):      @property      def associated_filename(self): -        values = [unicode(getattr(self, attr)) +        values = [str(getattr(self, attr))                    for attr in ('source_type', 'title')                    if getattr(self, attr)] -        return slugify(u"-".join(values)) +        return slugify("-".join(values))      def _get_base_image_paths(self):          if self.pk:  # m2m not available if not created... @@ -4754,7 +4710,7 @@ class Document(BaseHistorizedItem, OwnPerms, ImageModel, ValueGetter, MainItem):      def _get_base_image_path(self):          for path in self._get_base_image_paths():              return path -        return u"upload" +        return "upload"      def _get_available_filename(self, path, test_link=None):          """ @@ -4771,7 +4727,7 @@ class Document(BaseHistorizedItem, OwnPerms, ImageModel, ValueGetter, MainItem):          file_split = path.split('.')          suffix, base = "", ""          if len(file_split) > 1: -            base = u".".join(file_split[0:-1]) +            base = ".".join(file_split[0:-1])              suffix = file_split[-1]          else:              base = path @@ -4780,7 +4736,7 @@ class Document(BaseHistorizedItem, OwnPerms, ImageModel, ValueGetter, MainItem):          if len(base_split) > 1:              try:                  current_nb = int(base_split[-1]) -                base = u"-".join(base_split[0:-1]) + u"-" +                base = "-".join(base_split[0:-1]) + "-"              except ValueError:                  pass @@ -4789,7 +4745,7 @@ class Document(BaseHistorizedItem, OwnPerms, ImageModel, ValueGetter, MainItem):                      and os.readlink(path) == test_link:                  return path, True              current_nb += 1 -            path = u"{}-{}.{}".format(base, current_nb, suffix) +            path = "{}-{}.{}".format(base, current_nb, suffix)          if test_link:              return path, False          return path @@ -4812,7 +4768,7 @@ class Document(BaseHistorizedItem, OwnPerms, ImageModel, ValueGetter, MainItem):              if q.count():                  item = q.all()[0]                  base_path = item._get_base_image_path() -                new_path = base_path + u"/" + filename +                new_path = base_path + "/" + filename                  if not reference_path:                      reference_path = settings.MEDIA_ROOT + new_path                      # correct path @@ -4851,8 +4807,8 @@ class Document(BaseHistorizedItem, OwnPerms, ImageModel, ValueGetter, MainItem):          items = []          for rel_attr in reversed(self.RELATED_MODELS):              for item in getattr(self, rel_attr).all(): -                items.append(unicode(item)) -        return u" ; ".join(items) +                items.append(str(item)) +        return " ; ".join(items)      def _generate_cache_related_label(self):          return self.related_label() @@ -4935,13 +4891,13 @@ post_save.connect(cached_label_changed, sender=Document)  class OperationType(GeneralType): -    order = models.IntegerField(_(u"Order"), default=1) -    preventive = models.BooleanField(_(u"Is preventive"), default=True) -    judiciary = models.BooleanField(_(u"Is judiciary"), default=False) +    order = models.IntegerField(_("Order"), default=1) +    preventive = models.BooleanField(_("Is preventive"), default=True) +    judiciary = models.BooleanField(_("Is judiciary"), default=False)      class Meta: -        verbose_name = _(u"Operation type") -        verbose_name_plural = _(u"Operation types") +        verbose_name = _("Operation type") +        verbose_name_plural = _("Operation types")          ordering = ['judiciary', '-preventive', 'order', 'label']      @classmethod @@ -4957,7 +4913,7 @@ class OperationType(GeneralType):          if default and not instances:              try:                  default = cls.objects.get(txt_idx=default) -                tuples.append((default.pk, _(unicode(default)))) +                tuples.append((default.pk, _(str(default))))              except cls.DoesNotExist:                  pass          items = cls.objects.filter(**dct) @@ -4980,15 +4936,15 @@ class OperationType(GeneralType):                  if current_lst:                      tuples.append(current_lst)                  if item.judiciary: -                    gp_lbl = _(u"Judiciary") +                    gp_lbl = _("Judiciary")                  elif item.preventive: -                    gp_lbl = _(u"Preventive") +                    gp_lbl = _("Preventive")                  else: -                    gp_lbl = _(u"Research") +                    gp_lbl = _("Research")                  current_lst = [gp_lbl, []]                  current_preventive = item.preventive                  current_judiciary = item.judiciary -            current_lst[1].append((item.pk, _(unicode(item)))) +            current_lst[1].append((item.pk, _(str(item))))          if current_lst:              tuples.append(current_lst)          return tuples @@ -5017,23 +4973,23 @@ post_delete.connect(post_save_cache, sender=OperationType)  class AdministrationScript(models.Model): -    path = models.CharField(_(u"Filename"), max_length=30) -    name = models.TextField(_(u"Name"), +    path = models.CharField(_("Filename"), max_length=30) +    name = models.TextField(_("Name"),                              null=True, blank=True)      class Meta: -        verbose_name = _(u"Administration script") -        verbose_name_plural = _(u"Administration scripts") +        verbose_name = _("Administration script") +        verbose_name_plural = _("Administration scripts")          ordering = ['name'] -    def __unicode__(self): -        return unicode(self.name) +    def __str__(self): +        return str(self.name) -SCRIPT_STATE = (("S", _(u"Scheduled")), -                ("P", _(u"In progress")), -                ("FE", _(u"Finished with errors")), -                ("F", _(u"Finished")), +SCRIPT_STATE = (("S", _("Scheduled")), +                ("P", _("In progress")), +                ("FE", _("Finished with errors")), +                ("F", _("Finished")),                  )  SCRIPT_STATE_DCT = dict(SCRIPT_STATE) @@ -5041,24 +4997,24 @@ SCRIPT_STATE_DCT = dict(SCRIPT_STATE)  class AdministrationTask(models.Model):      script = models.ForeignKey(AdministrationScript) -    state = models.CharField(_(u"State"), max_length=2, choices=SCRIPT_STATE, +    state = models.CharField(_("State"), max_length=2, choices=SCRIPT_STATE,                               default='S')      creation_date = models.DateTimeField(default=datetime.datetime.now)      launch_date = models.DateTimeField(null=True, blank=True)      finished_date = models.DateTimeField(null=True, blank=True) -    result = models.TextField(_(u"Result"), null=True, blank=True) +    result = models.TextField(_("Result"), null=True, blank=True)      class Meta: -        verbose_name = _(u"Administration task") -        verbose_name_plural = _(u"Administration tasks") +        verbose_name = _("Administration task") +        verbose_name_plural = _("Administration tasks")          ordering = ['script'] -    def __unicode__(self): -        state = _(u"Unknown") +    def __str__(self): +        state = _("Unknown")          if self.state in SCRIPT_STATE_DCT: -            state = unicode(SCRIPT_STATE_DCT[self.state]) -        return u"{} - {} - {}".format(self.script, self.creation_date, -                                      state) +            state = str(SCRIPT_STATE_DCT[self.state]) +        return "{} - {} - {}".format(self.script, self.creation_date, +                                     state)      def execute(self):          if self.state != 'S': @@ -5068,28 +5024,28 @@ class AdministrationTask(models.Model):          script_dir = settings.ISHTAR_SCRIPT_DIR          if not script_dir: -            self.result = unicode( -                _(u"ISHTAR_SCRIPT_DIR is not set in your " -                  u"local_settings. Contact your administrator.")) +            self.result = str( +                _("ISHTAR_SCRIPT_DIR is not set in your " +                  "local_settings. Contact your administrator."))              self.state = 'FE'              self.finished_date = datetime.datetime.now()              self.save()              return          if '..' in script_dir: -            self.result = unicode( -                _(u"Your ISHTAR_SCRIPT_DIR is containing " -                  u"dots \"..\". As it can refer to relative " -                  u"paths, it can be a security issue and this is " -                  u"not allowed. Only put a full path.")) +            self.result = str( +                _("Your ISHTAR_SCRIPT_DIR is containing " +                  "dots \"..\". As it can refer to relative " +                  "paths, it can be a security issue and this is " +                  "not allowed. Only put a full path."))              self.state = 'FE'              self.finished_date = datetime.datetime.now()              self.save()              return          if not os.path.isdir(script_dir): -            self.result = unicode( -                _(u"Your ISHTAR_SCRIPT_DIR: \"{}\" is not a valid directory.") +            self.result = str( +                _("Your ISHTAR_SCRIPT_DIR: \"{}\" is not a valid directory.")              ).format(script_dir)              self.state = 'FE'              self.finished_date = datetime.datetime.now() @@ -5104,9 +5060,9 @@ class AdministrationTask(models.Model):                      script_name = os.path.join(script_dir, name)                  break          if not script_name: -            self.result = unicode( -                _(u"Script \"{}\" is not available in your script directory. " -                  u"Check your configuration.") +            self.result = str( +                _("Script \"{}\" is not available in your script directory. " +                  "Check your configuration.")              ).format(self.script.path)              self.state = 'FE'              self.finished_date = datetime.datetime.now() @@ -5121,7 +5077,7 @@ class AdministrationTask(models.Model):              stdout, stderr = session.communicate()          except OSError as e:              self.state = 'FE' -            self.result = u"Error executing \"{}\" script: {}".format( +            self.result = "Error executing \"{}\" script: {}".format(                  self.script.path, e)              self.save()              return @@ -5129,8 +5085,8 @@ class AdministrationTask(models.Model):          self.finished_date = datetime.datetime.now()          if stderr:              self.state = 'FE' -            self.result = u"Error: {}".format(stderr.decode('utf-8')) +            self.result = "Error: {}".format(stderr.decode('utf-8'))          else:              self.state = 'F' -            self.result = u"{}".format(stdout.decode('utf-8')) +            self.result = "{}".format(stdout.decode('utf-8'))          self.save()  | 
