diff options
Diffstat (limited to 'ishtar_common')
| -rw-r--r-- | ishtar_common/admin.py | 4 | ||||
| -rw-r--r-- | ishtar_common/migrations/0010_auto__del_wizardstep__del_wizard__add_globalvar__chg_field_person_atta.py | 236 | ||||
| -rw-r--r-- | ishtar_common/models.py | 52 | ||||
| -rw-r--r-- | ishtar_common/ooo_replace.py | 38 | ||||
| -rw-r--r-- | ishtar_common/tests.py | 36 | ||||
| -rw-r--r-- | ishtar_common/tests/test-file.odt | bin | 0 -> 9571 bytes | 
6 files changed, 344 insertions, 22 deletions
| diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py index cfbed2f66..9d164a626 100644 --- a/ishtar_common/admin.py +++ b/ishtar_common/admin.py @@ -81,6 +81,10 @@ class PersonTypeAdmin(admin.ModelAdmin):  admin.site.register(models.PersonType, PersonTypeAdmin) +class GlobalVarAdmin(admin.ModelAdmin): +    list_display = ['slug', 'description', 'value'] +admin.site.register(models.GlobalVar, GlobalVarAdmin) +  class GeneralTypeAdmin(admin.ModelAdmin):      list_display = ['label', 'txt_idx', 'available'] diff --git a/ishtar_common/migrations/0010_auto__del_wizardstep__del_wizard__add_globalvar__chg_field_person_atta.py b/ishtar_common/migrations/0010_auto__del_wizardstep__del_wizard__add_globalvar__chg_field_person_atta.py new file mode 100644 index 000000000..4bba74da9 --- /dev/null +++ b/ishtar_common/migrations/0010_auto__del_wizardstep__del_wizard__add_globalvar__chg_field_person_atta.py @@ -0,0 +1,236 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + +    def forwards(self, orm): +        # Deleting model 'WizardStep' +        db.delete_table('ishtar_common_wizardstep') + +        # Deleting model 'Wizard' +        db.delete_table('ishtar_common_wizard') + +        # Adding model 'GlobalVar' +        db.create_table('ishtar_common_globalvar', ( +            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), +            ('slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=50)), +            ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), +            ('value', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), +        )) +        db.send_create_signal('ishtar_common', ['GlobalVar']) + + +        # Changing field 'Person.attached_to' +        db.alter_column('ishtar_common_person', 'attached_to_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, on_delete=models.SET_NULL, to=orm['ishtar_common.Organization'])) + +    def backwards(self, orm): +        # Adding model 'WizardStep' +        db.create_table('ishtar_common_wizardstep', ( +            ('url_name', self.gf('django.db.models.fields.CharField')(max_length=128)), +            ('name', self.gf('django.db.models.fields.CharField')(max_length=128)), +            ('wizard', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ishtar_common.Wizard'])), +            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), +            ('order', self.gf('django.db.models.fields.IntegerField')()), +        )) +        db.send_create_signal('ishtar_common', ['WizardStep']) + +        # Adding model 'Wizard' +        db.create_table('ishtar_common_wizard', ( +            ('url_name', self.gf('django.db.models.fields.CharField')(max_length=128, unique=True)), +            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), +        )) +        db.send_create_signal('ishtar_common', ['Wizard']) + +        # Deleting model 'GlobalVar' +        db.delete_table('ishtar_common_globalvar') + + +        # Changing field 'Person.attached_to' +        db.alter_column('ishtar_common_person', 'attached_to_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['ishtar_common.Organization'])) + +    models = { +        'auth.group': { +            'Meta': {'object_name': 'Group'}, +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), +            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) +        }, +        'auth.permission': { +            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, +            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) +        }, +        'auth.user': { +            'Meta': {'object_name': 'User'}, +            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), +            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), +            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), +            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), +            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), +            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), +            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), +            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), +            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) +        }, +        'contenttypes.contenttype': { +            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, +            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) +        }, +        'ishtar_common.arrondissement': { +            'Meta': {'object_name': 'Arrondissement'}, +            'department': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Department']"}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '30'}) +        }, +        'ishtar_common.author': { +            'Meta': {'object_name': 'Author'}, +            'author_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.AuthorType']"}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'person': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'author'", 'to': "orm['ishtar_common.Person']"}) +        }, +        'ishtar_common.authortype': { +            'Meta': {'object_name': 'AuthorType'}, +            'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +            'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) +        }, +        'ishtar_common.canton': { +            'Meta': {'object_name': 'Canton'}, +            'arrondissement': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Arrondissement']"}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '30'}) +        }, +        'ishtar_common.department': { +            'Meta': {'ordering': "['number']", 'object_name': 'Department'}, +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'label': ('django.db.models.fields.CharField', [], {'max_length': '30'}), +            'number': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '3'}) +        }, +        'ishtar_common.documenttemplate': { +            'Meta': {'ordering': "['associated_object_name']", 'object_name': 'DocumentTemplate'}, +            'associated_object_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'template': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}) +        }, +        'ishtar_common.globalvar': { +            'Meta': {'ordering': "['slug']", 'object_name': 'GlobalVar'}, +            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}), +            'value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) +        }, +        'ishtar_common.historicalorganization': { +            'Meta': {'ordering': "('-history_date', '-history_id')", 'object_name': 'HistoricalOrganization'}, +            'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), +            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), +            'history_creator_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), +            'history_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), +            'history_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'history_modifier_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), +            'history_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), +            'history_user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}), +            'id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}), +            'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '300'}), +            'organization_type_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), +            'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), +            'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), +            'town': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}) +        }, +        'ishtar_common.ishtaruser': { +            'Meta': {'object_name': 'IshtarUser', '_ormbases': ['auth.User']}, +            'person': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ishtaruser'", 'unique': 'True', 'to': "orm['ishtar_common.Person']"}), +            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}) +        }, +        'ishtar_common.organization': { +            'Meta': {'object_name': 'Organization'}, +            'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), +            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), +            'history_creator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['auth.User']"}), +            'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '300'}), +            'organization_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.OrganizationType']"}), +            'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), +            'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), +            'town': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}) +        }, +        'ishtar_common.organizationtype': { +            'Meta': {'ordering': "('label',)", 'object_name': 'OrganizationType'}, +            'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +            'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) +        }, +        'ishtar_common.person': { +            'Meta': {'object_name': 'Person'}, +            'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'attached_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'members'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['ishtar_common.Organization']"}), +            'country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), +            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), +            'history_creator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['auth.User']"}), +            'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '30'}), +            'person_types': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ishtar_common.PersonType']", 'symmetrical': 'False'}), +            'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), +            'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), +            'surname': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}), +            'title': ('django.db.models.fields.CharField', [], {'max_length': '2'}), +            'town': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}) +        }, +        'ishtar_common.persontype': { +            'Meta': {'ordering': "('label',)", 'object_name': 'PersonType'}, +            'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +            'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) +        }, +        'ishtar_common.sourcetype': { +            'Meta': {'object_name': 'SourceType'}, +            'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +            'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) +        }, +        'ishtar_common.town': { +            'Meta': {'ordering': "['numero_insee']", 'object_name': 'Town'}, +            'canton': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Canton']", 'null': 'True', 'blank': 'True'}), +            'center': ('django.contrib.gis.db.models.fields.PointField', [], {'srid': '27572', 'null': 'True', 'blank': 'True'}), +            'departement': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Department']", 'null': 'True', 'blank': 'True'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'numero_insee': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '6'}), +            'surface': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) +        } +    } + +    complete_apps = ['ishtar_common'] diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 460612e17..6c4ec2e49 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -28,6 +28,7 @@ import tempfile  import copy  from django.conf import settings +from django.core.cache import cache  from django.core.exceptions import ObjectDoesNotExist, ValidationError  from django.core.files.uploadedfile import SimpleUploadedFile  from django.core.validators import validate_slug @@ -45,7 +46,8 @@ from django.contrib import admin  from simple_history.models import HistoricalRecords as BaseHistoricalRecords -from ooo_replace import ooo_replace +from ishtar_common.ooo_replace import ooo_replace +from ishtar_common.utils import get_cache  def post_save_user(sender, **kwargs):      user = kwargs['instance'] @@ -85,6 +87,8 @@ class ValueGetter(object):          values['VALUES'] = u'\n'.join(                          [u"%s: %s" % (k, v) for k, v in sorted(value_list,                                                          key=lambda x:x[0])]) +        for global_var in GlobalVar.objects.all(): +            values[global_var.slug] = global_var.value or ""          return values      @classmethod @@ -525,7 +529,6 @@ class BaseHistorizedItem(models.Model):              items.append('00000000')          return u"-".join([unicode(item) for item in items]) -  class ShortMenuItem(object):      def get_short_menu_class(self):          return '' @@ -539,26 +542,39 @@ class LightHistorizedItem(BaseHistorizedItem):          super(LightHistorizedItem, self).save(*args, **kwargs)          return True -class Wizard(models.Model): -    url_name = models.CharField(_(u"URL name"), max_length=128, unique=True) +class GlobalVar(models.Model): +    slug = models.SlugField(_(u"Variable name"), unique=True) +    description = models.TextField(_(u"Description of the variable"), +                                   null=True, blank=True) +    value = models.TextField(_(u"Value"), null=True, blank=True)      class Meta: -        verbose_name = _(u"Wizard") -        ordering = ['url_name'] +        verbose_name = _(u"Global variable") +        verbose_name_plural = _(u"Global variables") +        ordering = ['slug']      def __unicode__(self): -        return unicode(self.url_name) - -class WizardStep(models.Model): -    order = models.IntegerField(_(u"Order")) -    wizard = models.ForeignKey(Wizard, verbose_name=_(u"Wizard")) -    url_name = models.CharField(_(u"URL name"), max_length=128) -    name = models.CharField(_(u"Label"), max_length=128) -    class Meta: -        verbose_name = _(u"Wizard step") -        ordering = ['wizard', 'order'] +        return unicode(self.slug) -    def __unicode__(self): -        return u"%s » %s" % (unicode(self.wizard), unicode(self.name)) +    @classmethod +    def get_cache(cls, slug): +        cache_key, value = get_cache(cls, slug) +        if value: +            return value +        try: +            obj = cls.objects.get(slug=slug) +            cache.set(cache_key, obj.value, settings.CACHE_TIMEOUT) +            return obj.value +        except cls.DoesNotExist: +            return None + +def cached_globalvar_changed(sender, **kwargs): +    if not kwargs['instance']: +        return +    var = kwargs['instance'] +    cache_key, value = get_cache(GlobalVar, var.slug) +    cache.set(cache_key, var.value, settings.CACHE_TIMEOUT) + +post_save.connect(cached_globalvar_changed, sender=GlobalVar)  class UserDashboard:      def __init__(self): diff --git a/ishtar_common/ooo_replace.py b/ishtar_common/ooo_replace.py index 346ef75a4..2fb01724b 100644 --- a/ishtar_common/ooo_replace.py +++ b/ishtar_common/ooo_replace.py @@ -17,7 +17,7 @@  # See the file COPYING for details. -import locale +import locale, re  from zipfile import ZipFile, ZIP_DEFLATED  from cStringIO import StringIO  from xml.etree.cElementTree import ElementTree, fromstring @@ -78,9 +78,34 @@ def _format_value(value, default_value):      value = unicode(value) if value else default_value      return value +VAR_EXPR = u"###VAR %s###" +RE_VAR = re.compile(u"###VAR %s###" % u"([-a-zA-Z0-9_]+)") +IF_EXPR = u"###IF %s###(.*)###ENDIF###" +RE_IF = re.compile(IF_EXPR % u"([-a-zA-Z0-9_]+)") + +def _ishtar_parsing(context, value): +    """ +    ###VAR nom_var### for displaying a variable name +    ###IF nom_var### ###ENDIF### for conditionnal display +    Be carreful nested condition are not yet managed! +    """ +    for key, val in RE_IF.findall(value): +        v = "" +        if key in context and context[key]: +            v = _ishtar_parsing(context, val) +        value = re.sub(IF_EXPR % key, v, value) +    for key in RE_VAR.findall(value): +        v = "" +        if key in context and context[key]: +            v = unicode(context[key]) +        value = re.sub(VAR_EXPR % key, v, value) +    return value +  def ooo_replace(infile, outfile, context, default_value=''):      inzip = ZipFile(infile, 'r', ZIP_DEFLATED)      outzip = ZipFile(outfile, 'w', ZIP_DEFLATED) + +    # regular ooo parsing      content = ElementTree(fromstring(inzip.read('content.xml')))      missing_keys = set()      for xp in ('variable-set', 'variable-get'): @@ -102,11 +127,16 @@ def ooo_replace(infile, outfile, context, default_value=''):          if value.strip() in context:              value = context[value.strip()]          p.text = value + +    # raw content parsing +    str_io = StringIO() +    content.write(str_io) +    value = str_io.getvalue() +    value = _ishtar_parsing(context, value).encode('utf-8') +      for f in inzip.infolist():          if f.filename == 'content.xml': -            s = StringIO() -            content.write(s) -            outzip.writestr('content.xml', s.getvalue()) +            outzip.writestr('content.xml', value)          else:              outzip.writestr(f, inzip.read(f.filename))      inzip.close() diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py new file mode 100644 index 000000000..cdcb42103 --- /dev/null +++ b/ishtar_common/tests.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2014 Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet> + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. + +# See the file COPYING for details. + +import tempfile +from zipfile import ZipFile, ZIP_DEFLATED + +from django.test import TestCase + +from ishtar_common import models, ooo_replace +from ishtar_common.ooo_replace import ooo_replace + +class OOOGenerationTest(TestCase): +    def testGeneration(self): +        context = {'test-var':u"Testé", 'test-var2':u""} +        tmp = tempfile.TemporaryFile() +        ooo_replace("../ishtar_common/tests/test-file.odt", tmp, context) +        inzip = ZipFile(tmp, 'r', ZIP_DEFLATED) +        value = inzip.read('content.xml') +        self.assertTrue("Testé" in value) +        self.assertTrue("testé 2" not in value) diff --git a/ishtar_common/tests/test-file.odt b/ishtar_common/tests/test-file.odtBinary files differ new file mode 100644 index 000000000..2e73fe0ee --- /dev/null +++ b/ishtar_common/tests/test-file.odt | 
