diff --git a/apps/acls/locale/it/LC_MESSAGES/django.mo b/apps/acls/locale/it/LC_MESSAGES/django.mo index 62329ea64c..69fc2a3746 100644 Binary files a/apps/acls/locale/it/LC_MESSAGES/django.mo and b/apps/acls/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/acls/locale/it/LC_MESSAGES/django.po b/apps/acls/locale/it/LC_MESSAGES/django.po index 232cf6fbab..21fcbe7eca 100644 --- a/apps/acls/locale/it/LC_MESSAGES/django.po +++ b/apps/acls/locale/it/LC_MESSAGES/django.po @@ -3,14 +3,15 @@ # This file is distributed under the same license as the PACKAGE package. # # Translators: +# Pierpaolo Baldan , 2012. # Roberto Rosario , 2012. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" "Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" -"PO-Revision-Date: 2012-02-21 00:41+0000\n" -"Last-Translator: Roberto Rosario \n" +"PO-Revision-Date: 2012-03-21 14:55+0000\n" +"Last-Translator: Pierpaolo Baldan \n" "Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -20,7 +21,7 @@ msgstr "" #: __init__.py:14 msgid "ACLs" -msgstr "" +msgstr "ACL" #: __init__.py:15 __init__.py:23 msgid "details" @@ -36,19 +37,19 @@ msgstr "revocare" #: __init__.py:18 __init__.py:24 forms.py:21 msgid "New holder" -msgstr "" +msgstr "Nuovo titolare" #: __init__.py:20 msgid "Default ACLs" -msgstr "" +msgstr "Default ACL" #: __init__.py:21 msgid "List of classes" -msgstr "" +msgstr "Elenco delle classi" #: __init__.py:22 msgid "ACLs for class" -msgstr "" +msgstr "ACL per la classe" #: forms.py:38 msgid "Users" @@ -60,7 +61,7 @@ msgstr "Gruppi" #: forms.py:44 msgid "Roles" -msgstr "" +msgstr "Ruoli" #: forms.py:47 msgid "Special" @@ -68,7 +69,7 @@ msgstr "Speciale" #: managers.py:116 managers.py:128 msgid "Insufficient access." -msgstr "" +msgstr "Accesso insufficiente." #: models.py:27 models.py:69 msgid "permission" @@ -76,19 +77,19 @@ msgstr "autorizzazione" #: models.py:53 msgid "access entry" -msgstr "" +msgstr "voce di accesso" #: models.py:54 msgid "access entries" -msgstr "" +msgstr "voci di accesso" #: models.py:90 msgid "default access entry" -msgstr "" +msgstr "accesso voce predefinita" #: models.py:91 msgid "default access entries" -msgstr "" +msgstr "voci di accesso predefinite " #: models.py:109 msgid "Creator" @@ -100,32 +101,32 @@ msgstr "creatore" #: permissions.py:7 permissions.py:8 msgid "Access control lists" -msgstr "" +msgstr "Liste di controllo accessi" #: permissions.py:10 msgid "Edit ACLs" -msgstr "" +msgstr "Modifica ACL" #: permissions.py:11 msgid "View ACLs" -msgstr "" +msgstr "Visualizza ACL" #: permissions.py:13 msgid "Edit class default ACLs" -msgstr "" +msgstr "Modifica ACL predefiniti di classe" #: permissions.py:14 msgid "View class default ACLs" -msgstr "" +msgstr "Visualizza classi ACL predefinite" #: views.py:47 #, python-format msgid "access control lists for: %s" -msgstr "" +msgstr "lista controllo accessi per: %s" #: views.py:49 views.py:411 msgid "holder" -msgstr "" +msgstr "titolare" #: views.py:50 views.py:412 msgid "permissions" @@ -138,11 +139,11 @@ msgstr "autorizzazioni disponibili per: %(actor)s per %(obj)s " #: views.py:104 views.py:444 msgid "namespace" -msgstr "" +msgstr "namespace" #: views.py:105 views.py:445 msgid "label" -msgstr "" +msgstr "etichetta" #: views.py:107 views.py:447 msgid "has permission" @@ -175,14 +176,14 @@ msgstr "Sei sicuro di voler concedere permessi %(title_suffix)s?" #: views.py:199 views.py:542 #, python-format msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s." -msgstr "" +msgstr "Permesso \"%(permission)s\" concesso%(actor)s per %(object)s." #: views.py:205 views.py:548 #, python-format msgid "" "%(actor)s, already had the permission \"%(permission)s\" granted for " "%(object)s." -msgstr "" +msgstr "%(actor)s, ha già i permessi\"%(permission)s\" concessi per%(object)s." #: views.py:281 views.py:610 #, python-format @@ -202,17 +203,17 @@ msgstr "Sei sicuro di voler revocare permessi %(title_suffix)s?" #: views.py:293 views.py:622 #, python-format msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s." -msgstr "" +msgstr "Permessi \"%(permission)s\" revocati al %(actor)s per %(object)s." #: views.py:299 views.py:628 #, python-format msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s." -msgstr "" +msgstr "%(actor)s, non ha i permessi\"%(permission)s\" per %(object)s." #: views.py:355 #, python-format msgid "add new holder for: %s" -msgstr "" +msgstr "aggiungi nuovo titolare per: %s" #: views.py:356 views.py:488 msgid "Select" @@ -220,23 +221,23 @@ msgstr "Selezionare" #: views.py:388 msgid "classes" -msgstr "" +msgstr "classi" #: views.py:390 msgid "class" -msgstr "" +msgstr "classe" #: views.py:409 #, python-format msgid "default access control lists for class: %s" -msgstr "" +msgstr "lista di default per il controllo accessi per la classe: %s" #: views.py:437 #, python-format msgid "permissions available to: %(actor)s for class %(class)s" -msgstr "" +msgstr "permessi disponibili per: %(actor)s per la classe %(class)s" #: views.py:486 #, python-format msgid "add new holder for class: %s" -msgstr "" +msgstr "aggiungi un nuovo titolare per la calsse: %s" diff --git a/apps/common/locale/it/LC_MESSAGES/django.mo b/apps/common/locale/it/LC_MESSAGES/django.mo index 6e25f2e7c5..330436c3e8 100644 Binary files a/apps/common/locale/it/LC_MESSAGES/django.mo and b/apps/common/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/common/locale/it/LC_MESSAGES/django.po b/apps/common/locale/it/LC_MESSAGES/django.po index 365d59fa16..479b0fd546 100644 --- a/apps/common/locale/it/LC_MESSAGES/django.po +++ b/apps/common/locale/it/LC_MESSAGES/django.po @@ -4,14 +4,15 @@ # # Translators: # , 2011. +# Pierpaolo Baldan , 2012. # Roberto Rosario , 2012. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" "Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" -"PO-Revision-Date: 2012-02-21 16:35+0000\n" -"Last-Translator: Roberto Rosario \n" +"PO-Revision-Date: 2012-03-21 13:21+0000\n" +"Last-Translator: Pierpaolo Baldan \n" "Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -99,7 +100,7 @@ msgstr "Orizontale" #: models.py:16 msgid "lock field" -msgstr "" +msgstr "blocca campo" #: models.py:43 msgid "Anonymous user" diff --git a/apps/common/utils.py b/apps/common/utils.py index 37188b5aec..962f6193f1 100644 --- a/apps/common/utils.py +++ b/apps/common/utils.py @@ -396,3 +396,38 @@ def encapsulate(function): def id_generator(size=6, chars=string.ascii_uppercase + string.digits): return ''.join(random.choice(chars) for x in range(size)) + + +def get_descriptor(file_input, read=True): + try: + # Is it a file like object? + file_input.seek(0) + except AttributeError: + # If not, try open it. + if read: + return open(file_input, 'rb') + else: + return open(file_input, 'wb') + else: + return file_input + + +#http://stackoverflow.com/questions/123198/how-do-i-copy-a-file-in-python +def copyfile(source, destination, buffer_size=1024 * 1024): + """ + Copy a file from source to dest. source and dest + can either be strings or any object with a read or + write method, like StringIO for example. + """ + source_descriptor = get_descriptor(source) + destination_descriptor = get_descriptor(destination, read=False) + + while True: + copy_buffer = source_descriptor.read(buffer_size) + if copy_buffer: + destination_descriptor.write(copy_buffer) + else: + break + + source_descriptor.close() + destination_descriptor.close() diff --git a/apps/converter/api.py b/apps/converter/api.py index fb6bfaa8ec..c09ce336aa 100644 --- a/apps/converter/api.py +++ b/apps/converter/api.py @@ -3,6 +3,7 @@ from __future__ import absolute_import import os import subprocess import hashlib +import logging from django.utils.encoding import smart_str @@ -20,6 +21,8 @@ from .exceptions import OfficeConversionError, UnknownFileFormat HASH_FUNCTION = lambda x: hashlib.sha256(x).hexdigest() +logger = logging.getLogger(__name__) + def cache_cleanup(input_filepath, *args, **kwargs): try: @@ -100,9 +103,11 @@ def convert(input_filepath, output_filepath=None, cleanup_files=False, mimetype= def get_page_count(input_filepath): + logger.debug('office_converter: %s' % office_converter) if office_converter: try: office_converter.convert(input_filepath) + logger.debug('office_converter.exists: %s' % office_converter.exists) if office_converter.exists: input_filepath = office_converter.output_filepath diff --git a/apps/converter/conf/settings.py b/apps/converter/conf/settings.py index 3d4b1e27f4..7960f4b832 100644 --- a/apps/converter/conf/settings.py +++ b/apps/converter/conf/settings.py @@ -15,15 +15,6 @@ Setting( exists=True, ) -Setting( - namespace=namespace, - name='IM_CONVERT_PATH', - global_name='CONVERTER_IM_CONVERT_PATH', - default=u'/usr/bin/convert', - description=_(u'File path to imagemagick\'s convert program.'), - exists=True, -) - Setting( namespace=namespace, name='IM_IDENTIFY_PATH', @@ -75,6 +66,16 @@ Setting( description=_(u'Use alternate method of connection to LibreOffice using a pipe, it is slower but less prone to segmentation faults.'), ) +Setting( + namespace=namespace, + name='LIBREOFFICE_PATH', + global_name='CONVERTER_LIBREOFFICE_PATH', + default=u'/usr/bin/libreoffice', + description=_(u'Path to the libreoffice program.'), + exists=True +) + + #{'name': u'OCR_OPTIONS', 'global_name': u'CONVERTER_OCR_OPTIONS', 'default': u'-colorspace Gray -depth 8 -resample 200x200'}, #{'name': u'HIGH_QUALITY_OPTIONS', 'global_name': u'CONVERTER_HIGH_QUALITY_OPTIONS', 'default': u'-density 400'}, #{'name': u'PRINT_QUALITY_OPTIONS', 'global_name': u'CONVERTER_PRINT_QUALITY_OPTIONS', 'default': u'-density 500'}, diff --git a/apps/converter/locale/it/LC_MESSAGES/django.mo b/apps/converter/locale/it/LC_MESSAGES/django.mo index 2b4b16da2c..fafebbc57b 100644 Binary files a/apps/converter/locale/it/LC_MESSAGES/django.mo and b/apps/converter/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/converter/locale/it/LC_MESSAGES/django.po b/apps/converter/locale/it/LC_MESSAGES/django.po index 3ddbf49310..b5cb89a843 100644 --- a/apps/converter/locale/it/LC_MESSAGES/django.po +++ b/apps/converter/locale/it/LC_MESSAGES/django.po @@ -1,22 +1,21 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # , 2011. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" "PO-Revision-Date: 2011-12-09 14:53+0000\n" "Last-Translator: Pierpaolo Baldan \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: __init__.py:15 @@ -474,8 +473,7 @@ msgstr "Magick Image File Format" #: literals.py:177 msgid "" "Multiple-image Network Graphics (libpng 1.2.42,1.2.44, zlib 1.2.3.3,1.2.3.4)" -msgstr "" -"Multiple-image Network Graphics (libpng 1.2.42,1.2.44, zlib 1.2.3.3,1.2.3.4)" +msgstr "Multiple-image Network Graphics (libpng 1.2.42,1.2.44, zlib 1.2.3.3,1.2.3.4)" #: literals.py:178 msgid "Raw Bi-level bitmap in least-significant-byte first order" @@ -636,24 +634,19 @@ msgstr "Portable Network Graphics (libpng 1.2.42,1.2.44, zlib 1.2.3.3,1.2.3.4)" #: literals.py:227 msgid "" "24-bit RGB PNG, opaque only (libpng 1.2.42,1.2.44, zlib 1.2.3.3,1.2.3.4)" -msgstr "" -"24-bit RGB PNG, opaque only (libpng 1.2.42,1.2.44, zlib 1.2.3.3,1.2.3.4)" +msgstr "24-bit RGB PNG, opaque only (libpng 1.2.42,1.2.44, zlib 1.2.3.3,1.2.3.4)" #: literals.py:228 msgid "" "32-bit RGBA PNG, semitransparency OK (libpng 1.2.42,1.2.44, zlib " "1.2.3.3,1.2.3.4)" -msgstr "" -"32-bit RGBA PNG, semitransparency OK (libpng 1.2.42,1.2.44, zlib " -"1.2.3.3,1.2.3.4)" +msgstr "32-bit RGBA PNG, semitransparency OK (libpng 1.2.42,1.2.44, zlib 1.2.3.3,1.2.3.4)" #: literals.py:229 msgid "" "8-bit indexed PNG, binary transparency only (libpng 1.2.42,1.2.44, zlib " "1.2.3.3,1.2.3.4)" -msgstr "" -"8-bit indexed PNG, binary transparency only (libpng 1.2.42,1.2.44, zlib " -"1.2.3.3,1.2.3.4)" +msgstr "8-bit indexed PNG, binary transparency only (libpng 1.2.42,1.2.44, zlib 1.2.3.3,1.2.3.4)" #: literals.py:230 msgid "Portable anymap" @@ -913,12 +906,10 @@ msgstr "File path per il progarmma " #: conf/settings.py:15 msgid "" -"Graphics conversion backend to use. Options are: converter.backends." -"imagemagick, converter.backends.graphicsmagick and converter.backends.python." -msgstr "" -"Backend da usare per la conversione grafica. Le opzioni sono: converter." -"backends.imagemagick, converter.backends.graphicsmagick e converter.backends." -"python." +"Graphics conversion backend to use. Options are: " +"converter.backends.imagemagick, converter.backends.graphicsmagick and " +"converter.backends.python." +msgstr "Backend da usare per la conversione grafica. Le opzioni sono: converter.backends.imagemagick, converter.backends.graphicsmagick e converter.backends.python." #: conf/settings.py:16 msgid "Path to the unoconv program." @@ -926,11 +917,9 @@ msgstr "Path per il programma unoconv" #: conf/settings.py:17 msgid "" -"Use alternate method of connection to LibreOffice using a pipe, it is slower " -"but less prone to segmentation faults." -msgstr "" -"Utilizzare il metodo alternativo di collegamento a LibreOffice utilizzando " -"questo collegamento, è più lento ma meno soggetto a errori di segmentazione." +"Use alternate method of connection to LibreOffice using a pipe, it is slower" +" but less prone to segmentation faults." +msgstr "Utilizzare il metodo alternativo di collegamento a LibreOffice utilizzando questo collegamento, è più lento ma meno soggetto a errori di segmentazione." #: templates/converter_file_formats_help.html:3 msgid "Help" @@ -941,6 +930,4 @@ msgstr "Aiuto" msgid "" "These are the file formats supported by the currently selected converter " "backend. In this case: '%(backend)s'" -msgstr "" -"Questi sono il formati file supportati dal backend selezionato.In questo " -"caso : '%(backend)s'" +msgstr "Questi sono il formati file supportati dal backend selezionato.In questo caso : '%(backend)s'" diff --git a/apps/converter/office_converter.py b/apps/converter/office_converter.py index 07c7a28f62..bdf9e36419 100644 --- a/apps/converter/office_converter.py +++ b/apps/converter/office_converter.py @@ -8,7 +8,7 @@ from mimetype.api import get_mimetype from common.conf.settings import TEMPORARY_DIRECTORY from common.utils import id_generator -from .conf.settings import UNOCONV_PATH, UNOCONV_USE_PIPE +from .conf.settings import UNOCONV_PATH, UNOCONV_USE_PIPE, LIBREOFFICE_PATH from .exceptions import (OfficeConversionError, OfficeBackendError, UnknownFileFormat) @@ -38,7 +38,7 @@ logger = logging.getLogger(__name__) class OfficeConverter(object): def __init__(self): - self.backend_class = OfficeConverterBackendUnoconv + self.backend_class = OfficeConverterBackendDirect self.backend = self.backend_class() self.exists = False self.mimetype = None @@ -86,9 +86,9 @@ class OfficeConverterBackendUnoconv(object): raise OfficeBackendError('cannot find unoconv executable') def convert(self, input_filepath, output_filepath): - ''' + """ Executes the program unoconv using subprocess's Popen - ''' + """ self.input_filepath = input_filepath self.output_filepath = output_filepath @@ -118,3 +118,54 @@ class OfficeConverterBackendUnoconv(object): raise OfficeBackendError(msg) except Exception, msg: logger.error('Unhandled exception', exc_info=msg) + + +class OfficeConverterBackendDirect(object): + def __init__(self): + self.libreoffice_path = LIBREOFFICE_PATH if LIBREOFFICE_PATH else u'/usr/bin/libreoffice' + if not os.path.exists(self.libreoffice_path): + raise OfficeBackendError('cannot find LibreOffice executable') + logger.debug('self.libreoffice_path: %s' % self.libreoffice_path) + + def convert(self, input_filepath, output_filepath): + """ + Executes libreoffice using subprocess's Popen + """ + self.input_filepath = input_filepath + self.output_filepath = output_filepath + + command = [] + command.append(self.libreoffice_path) + + command.append(u'--headless') + command.append(u'--convert-to') + command.append(u'pdf') + command.append(self.input_filepath) + command.append(u'--outdir') + command.append(TEMPORARY_DIRECTORY) + + logger.debug('command: %s' % command) + + try: + os.environ['HOME'] = TEMPORARY_DIRECTORY + proc = subprocess.Popen(command, close_fds=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) + return_code = proc.wait() + logger.debug('return_code: %s' % return_code) + + readline = proc.stderr.readline() + logger.debug('stderr: %s' % readline) + if return_code != 0: + raise OfficeBackendError(readline) + filename, extension = os.path.splitext(os.path.basename(self.input_filepath)) + logger.debug('filename: %s' % filename) + logger.debug('extension: %s' % extension) + + converted_output = os.path.join(TEMPORARY_DIRECTORY, os.path.extsep.join([filename, 'pdf'])) + logger.debug('converted_output: %s' % converted_output) + + os.rename(converted_output, self.output_filepath) + except OSError, msg: + raise OfficeBackendError(msg) + except Exception, msg: + logger.error('Unhandled exception', exc_info=msg) + diff --git a/apps/converter/utils.py b/apps/converter/utils.py index 1544db04ee..d85157ff2b 100644 --- a/apps/converter/utils.py +++ b/apps/converter/utils.py @@ -4,29 +4,6 @@ from django.core.exceptions import ImproperlyConfigured from django.utils.importlib import import_module -#http://stackoverflow.com/questions/123198/how-do-i-copy-a-file-in-python -def copyfile(source, dest, buffer_size=1024 * 1024): - """ - Copy a file from source to dest. source and dest - can either be strings or any object with a read or - write method, like StringIO for example. - """ - if not hasattr(source, 'read'): - source = open(source, 'rb') - if not hasattr(dest, 'write'): - dest = open(dest, 'wb') - - while 1: - copy_buffer = source.read(buffer_size) - if copy_buffer: - dest.write(copy_buffer) - else: - break - - source.close() - dest.close() - - def _lazy_load(fn): _cached = [] diff --git a/apps/django_gpg/locale/it/LC_MESSAGES/django.mo b/apps/django_gpg/locale/it/LC_MESSAGES/django.mo index f6df524b0b..72364733cd 100644 Binary files a/apps/django_gpg/locale/it/LC_MESSAGES/django.mo and b/apps/django_gpg/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/django_gpg/locale/it/LC_MESSAGES/django.po b/apps/django_gpg/locale/it/LC_MESSAGES/django.po index f636d037db..e1408d3b5b 100644 --- a/apps/django_gpg/locale/it/LC_MESSAGES/django.po +++ b/apps/django_gpg/locale/it/LC_MESSAGES/django.po @@ -1,22 +1,22 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # , 2011. +# Pierpaolo Baldan , 2012. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" -"PO-Revision-Date: 2012-02-02 18:20+0000\n" -"Last-Translator: Roberto Rosario \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"PO-Revision-Date: 2012-03-21 13:33+0000\n" +"Last-Translator: Pierpaolo Baldan \n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: __init__.py:14 views.py:67 @@ -77,9 +77,7 @@ msgstr "Errore di firma" #: api.py:60 msgid "Document is signed but no public key is available for verification." -msgstr "" -"Il documento è stato firmato, ma la chiave pubblica non è disponibile per la " -"verifica" +msgstr "Il documento è stato firmato, ma la chiave pubblica non è disponibile per la verifica" #: api.py:64 msgid "Document is signed, and signature is good." @@ -103,7 +101,7 @@ msgstr "Nome, e-mail,key ID , impronte digitali per cercare" #: permissions.py:7 msgid "Key management" -msgstr "" +msgstr "Gestione delle chiavi" #: permissions.py:9 msgid "View keys" @@ -119,7 +117,7 @@ msgstr "Interroga l'autorità per le chiavi" #: permissions.py:12 msgid "Import keys from keyservers" -msgstr "" +msgstr "Importa le chiavi dal server di chiavi" #: views.py:38 #, python-format @@ -129,7 +127,7 @@ msgstr "Chiave: %s, importata con successo." #: views.py:43 #, python-format msgid "Unable to import key id: %(key_id)s; %(error)s" -msgstr "" +msgstr "Impossibile importare chiave id: %(key_id)s ; %(error)s " #: views.py:52 msgid "Import key" @@ -163,10 +161,7 @@ msgid "" "Are you sure you wish to delete key: %s? If you try to delete a public key " "that is part of a public/private pair the private key will be deleted as " "well." -msgstr "" -"Sei sicuro di voler cancellare la chiave: %s? Se provi a cancellare una " -"chiave pubblica che è parte di una coppia publica/privata anche la chiave " -"privata sarà cancellata" +msgstr "Sei sicuro di voler cancellare la chiave: %s? Se provi a cancellare una chiave pubblica che è parte di una coppia publica/privata anche la chiave privata sarà cancellata" #: views.py:129 msgid "Query key server" @@ -218,4 +213,4 @@ msgstr "Lista di server per chiavi che si possono interrogare." #: conf/settings.py:16 msgid "Home directory used to store keys as well as configuration files." -msgstr "" +msgstr "Home directory utilizzata per memorizzare le chiavi così come i file di configurazione." diff --git a/apps/document_comments/locale/it/LC_MESSAGES/django.mo b/apps/document_comments/locale/it/LC_MESSAGES/django.mo index abb91fe5a9..ba9668087f 100644 Binary files a/apps/document_comments/locale/it/LC_MESSAGES/django.mo and b/apps/document_comments/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/document_comments/locale/it/LC_MESSAGES/django.po b/apps/document_comments/locale/it/LC_MESSAGES/django.po index dfa8084546..76c6c822ac 100644 --- a/apps/document_comments/locale/it/LC_MESSAGES/django.po +++ b/apps/document_comments/locale/it/LC_MESSAGES/django.po @@ -1,22 +1,21 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # , 2011. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" "PO-Revision-Date: 2012-02-02 18:20+0000\n" "Last-Translator: Roberto Rosario \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: __init__.py:19 __init__.py:20 diff --git a/apps/document_indexing/locale/it/LC_MESSAGES/django.mo b/apps/document_indexing/locale/it/LC_MESSAGES/django.mo index 666b1225ac..d8f677d171 100644 Binary files a/apps/document_indexing/locale/it/LC_MESSAGES/django.mo and b/apps/document_indexing/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/document_indexing/locale/it/LC_MESSAGES/django.po b/apps/document_indexing/locale/it/LC_MESSAGES/django.po index 4559e02b61..0e382aa1f5 100644 --- a/apps/document_indexing/locale/it/LC_MESSAGES/django.po +++ b/apps/document_indexing/locale/it/LC_MESSAGES/django.po @@ -1,22 +1,22 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # , 2011. +# Pierpaolo Baldan , 2012. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" -"PO-Revision-Date: 2012-02-02 18:18+0000\n" -"Last-Translator: Roberto Rosario \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"PO-Revision-Date: 2012-03-21 14:44+0000\n" +"Last-Translator: Pierpaolo Baldan \n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: __init__.py:31 __init__.py:45 __init__.py:47 models.py:42 views.py:36 @@ -30,23 +30,23 @@ msgstr "lista indici" #: __init__.py:33 views.py:74 msgid "create index" -msgstr "" +msgstr "creare un indice" #: __init__.py:34 __init__.py:39 msgid "edit" -msgstr "" +msgstr "modificare" #: __init__.py:35 __init__.py:40 msgid "delete" -msgstr "" +msgstr "cancellare" #: __init__.py:36 msgid "tree template" -msgstr "" +msgstr "albero di template" #: __init__.py:38 msgid "new child node" -msgstr "" +msgstr "nuovo nodo figlio" #: __init__.py:44 msgid "go up one level" @@ -73,17 +73,13 @@ msgstr "Massimo dei suffissi contati (%s) ." #, python-format msgid "" "Error in document indexing update expression: %(expression)s; %(exception)s" -msgstr "" -"Errore nella creazione dell'indice per l'espressione: %(expression)s; " -"%(exception)s" +msgstr "Errore nella creazione dell'indice per l'espressione: %(expression)s; %(exception)s" #: api.py:96 api.py:111 #, python-format msgid "" "Error updating document index, expression: %(expression)s; %(exception)s" -msgstr "" -"Errore nell'aggiornamento delle'indice documento per l'espressione: " -"%(expression)s; %(exception)s" +msgstr "Errore nell'aggiornamento delle'indice documento per l'espressione: %(expression)s; %(exception)s" #: api.py:150 #, python-format @@ -100,9 +96,7 @@ msgstr "Impossibile creare la directory per gli indici; %s" msgid "" "Unable to create symbolic link, file exists and could not be deleted: " "%(filepath)s; %(exc)s" -msgstr "" -"Impossibile creare un link simbolico, il file già esiste e non può essere " -"cancellato: %(filepath)s; %(exc)s" +msgstr "Impossibile creare un link simbolico, il file già esiste e non può essere cancellato: %(filepath)s; %(exc)s" #: filesystem.py:71 #, python-format @@ -126,27 +120,28 @@ msgstr "Funzioni disponibili: %s" #: models.py:17 views.py:40 msgid "name" -msgstr "" +msgstr "nome" #: models.py:17 msgid "Internal name used to reference this index." -msgstr "" +msgstr "Nome interno utilizzato per fare riferimento a questo indice." #: models.py:18 views.py:41 msgid "title" -msgstr "" +msgstr "titolo" #: models.py:18 msgid "The name that will be visible to users." -msgstr "" +msgstr "Il nome che sarà visibile agli utenti." #: models.py:19 models.py:50 msgid "enabled" msgstr "abilitato" #: models.py:19 -msgid "Causes this index to be visible and updated when document data changes." -msgstr "" +msgid "" +"Causes this index to be visible and updated when document data changes." +msgstr "Fa sì che questo indice possa essere visibile e aggiornato quando i dati del documento cambiano." #: models.py:41 models.py:47 views.py:101 views.py:132 views.py:159 #: views.py:195 views.py:225 views.py:265 @@ -163,7 +158,7 @@ msgstr "Inserisci una espressione python perchè possa essere valutata." #: models.py:50 msgid "Causes this node to be visible and updated when document data changes." -msgstr "" +msgstr "Fa sì che questo nodo possa essere visibili e aggiornato quando i dati del documento cambiano." #: models.py:51 msgid "link documents" @@ -171,17 +166,17 @@ msgstr "link al documento" #: models.py:51 msgid "" -"Check this option to have this node act as a container for documents and not " -"as a parent for further nodes." -msgstr "" +"Check this option to have this node act as a container for documents and not" +" as a parent for further nodes." +msgstr "Selezionare questa opzione per questo specifico nodo quale contenitore per i documenti e non come un genitore per ulteriori nodi." #: models.py:57 models.py:63 msgid "index template node" -msgstr "" +msgstr "indice di nodo modello" #: models.py:58 msgid "indexes template nodes" -msgstr "" +msgstr "indici nodi modello" #: models.py:64 msgid "value" @@ -193,11 +188,11 @@ msgstr "documenti" #: models.py:75 msgid "index instance node" -msgstr "" +msgstr "indice dell'istanza nodo" #: models.py:76 msgid "indexes instance nodes" -msgstr "" +msgstr "indici esempio di nodi" #: models.py:80 msgid "index instance" @@ -221,19 +216,19 @@ msgstr "Indicizzazione" #: permissions.py:9 msgid "Configure document indexes" -msgstr "" +msgstr "Configura gli indici dei documenti" #: permissions.py:10 msgid "Create new document indexes" -msgstr "" +msgstr "Creare nuovi indici documento" #: permissions.py:11 msgid "Edit document indexes" -msgstr "" +msgstr "Modifica gli indici dei documenti" #: permissions.py:12 msgid "Delete document indexes" -msgstr "" +msgstr "Eliminare gli indici dei documenti" #: permissions.py:14 msgid "View document indexes" @@ -249,80 +244,80 @@ msgstr "indici dei documenti" #: views.py:68 msgid "Index created successfully." -msgstr "" +msgstr "Indice creato con successo." #: views.py:92 msgid "Index edited successfully" -msgstr "" +msgstr "Indice modificato con successo" #: views.py:98 #, python-format msgid "edit index: %s" -msgstr "" +msgstr "modifica indice: %s" #: views.py:123 #, python-format msgid "Index: %s deleted successfully." -msgstr "" +msgstr "Indice: %s cancellato con successo." #: views.py:125 #, python-format msgid "Index: %(index)s delete error: %(error)s" -msgstr "" +msgstr "Indice: %(index)s errore di cancellazione: %(error)s" #: views.py:137 #, python-format msgid "Are you sure you with to delete the index: %s?" -msgstr "" +msgstr "Sei sicuro di voler cancella l'indice: %s?" #: views.py:162 #, python-format msgid "tree template nodes for index: %s" -msgstr "" +msgstr "modello nodi della struttura per l'indice: %s" #: views.py:165 msgid "level" -msgstr "" +msgstr "livello" #: views.py:186 msgid "Index template node created successfully." -msgstr "" +msgstr "Modello nodo indice creato con successo." #: views.py:192 msgid "create child node" -msgstr "" +msgstr "creare nodo figlio" #: views.py:213 msgid "Index template node edited successfully" -msgstr "" +msgstr "Template nodo Indice modificato con successo" #: views.py:219 #, python-format msgid "edit index template node: %s" -msgstr "" +msgstr "modifica index template node: %s" #: views.py:226 views.py:266 views.py:334 msgid "node" -msgstr "" +msgstr "nodo" #: views.py:248 #, python-format msgid "Node: %s deleted successfully." -msgstr "" +msgstr "Nodo: %s cancellato con succcesso." #: views.py:250 #, python-format msgid "Node: %(node)s delete error: %(error)s" -msgstr "" +msgstr "Nodo: %(node)s errore di cancellazione: %(error)s" #: views.py:259 #, python-format msgid "Are you sure you with to delete the index template node: %s?" -msgstr "" +msgstr "Sei sicuro di voler cancellare index template node: %s?" #: views.py:283 msgid "nodes" -msgstr "" +msgstr "nodi" #: views.py:316 #, python-format @@ -339,9 +334,7 @@ msgstr "Sei sicuro di voler ricostruire l'indice ?" #: views.py:364 msgid "On large databases this operation may take some time to execute." -msgstr "" -"Per un database di grosse dimensioni l'operazione protrebbe aver bisogno di " -"tempo." +msgstr "Per un database di grosse dimensioni l'operazione protrebbe aver bisogno di tempo." #: views.py:370 msgid "Index rebuild completed successfully." @@ -359,9 +352,9 @@ msgstr "Gli indici contengono: %s" #: conf/settings.py:22 msgid "" -"A dictionary that maps the index name and where on the filesystem that index " -"will be mirrored." -msgstr "" +"A dictionary that maps the index name and where on the filesystem that index" +" will be mirrored." +msgstr "Un dizionario che associa il nome dell'indice e dove sul filesystem verrà copiato." #: templates/indexing_help.html:3 msgid "What are indexes?" @@ -369,6 +362,4 @@ msgstr "Cosa sono gli indici ?" #: templates/indexing_help.html:4 msgid "Indexes group documents into a tree like hierarchical structure." -msgstr "" -"Gli Indici dei documenti rappresentano , nella forma di albero, la struttura " -"gerarchica dei documenti stessi.." +msgstr "Gli Indici dei documenti rappresentano , nella forma di albero, la struttura gerarchica dei documenti stessi.." diff --git a/apps/document_signatures/locale/it/LC_MESSAGES/django.mo b/apps/document_signatures/locale/it/LC_MESSAGES/django.mo index fe8816f982..fa6bcfe257 100644 Binary files a/apps/document_signatures/locale/it/LC_MESSAGES/django.mo and b/apps/document_signatures/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/document_signatures/locale/it/LC_MESSAGES/django.po b/apps/document_signatures/locale/it/LC_MESSAGES/django.po index 2555341d9b..853d1c1b5d 100644 --- a/apps/document_signatures/locale/it/LC_MESSAGES/django.po +++ b/apps/document_signatures/locale/it/LC_MESSAGES/django.po @@ -1,21 +1,21 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: +# Pierpaolo Baldan , 2012. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" -"PO-Revision-Date: 2012-02-02 18:20+0000\n" -"Last-Translator: Roberto Rosario \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"PO-Revision-Date: 2012-03-21 14:23+0000\n" +"Last-Translator: Pierpaolo Baldan \n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: __init__.py:83 @@ -36,7 +36,7 @@ msgstr "File della firma" #: models.py:20 msgid "document version" -msgstr "" +msgstr "versione del documento" #: models.py:21 msgid "signature file" @@ -44,19 +44,19 @@ msgstr "file della firma" #: models.py:22 msgid "has embedded signature" -msgstr "" +msgstr "ha incorporato la firma" #: models.py:35 msgid "document version signature" -msgstr "" +msgstr "versione della firma del documento" #: models.py:36 msgid "document version signatures" -msgstr "" +msgstr "versione delle firme documento " #: permissions.py:7 msgid "Document signatures" -msgstr "" +msgstr "Firme documento" #: permissions.py:8 msgid "Verify document signatures" diff --git a/apps/documents/locale/it/LC_MESSAGES/django.mo b/apps/documents/locale/it/LC_MESSAGES/django.mo index d9194843bd..2c1c8afe64 100644 Binary files a/apps/documents/locale/it/LC_MESSAGES/django.mo and b/apps/documents/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/documents/locale/it/LC_MESSAGES/django.po b/apps/documents/locale/it/LC_MESSAGES/django.po index e8312c5918..44890d1870 100644 --- a/apps/documents/locale/it/LC_MESSAGES/django.po +++ b/apps/documents/locale/it/LC_MESSAGES/django.po @@ -4,14 +4,15 @@ # # Translators: # , 2011. +# Pierpaolo Baldan , 2012. # Roberto Rosario , 2012. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" "Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" -"PO-Revision-Date: 2012-02-21 00:37+0000\n" -"Last-Translator: Roberto Rosario \n" +"PO-Revision-Date: 2012-03-21 13:44+0000\n" +"Last-Translator: Pierpaolo Baldan \n" "Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -102,13 +103,13 @@ msgstr "Trovare i file di documenti mancanti" #: __init__.py:86 msgid "Clear the document image cache" -msgstr "" +msgstr "Svuota la cache immagine del documento" #: __init__.py:86 msgid "" "Clear the graphics representations used to speed up the documents' display " "and interactive transformations results." -msgstr "" +msgstr "Cancella le rappresentazioni grafiche utilizzate per accellerare la visualizzazione dei documenti e dei risultati interattivi trasformazioni." #: __init__.py:89 msgid "page transformations" @@ -241,7 +242,7 @@ msgstr "Pagine nel documento (%s)" #: forms.py:162 msgid "Use the new version filename as the document filename" -msgstr "" +msgstr "Utilizza il nuovo nome di versione il nome del documento" #: forms.py:178 msgid "Quick document rename" @@ -253,11 +254,11 @@ msgstr "Versione aggiornamento" #: forms.py:190 msgid "Release level" -msgstr "" +msgstr "Livello di versione" #: forms.py:196 msgid "Release level serial" -msgstr "" +msgstr "Livello di versione sequenziale" #: forms.py:204 msgid "Comment" @@ -280,7 +281,7 @@ msgid "" "Download the document in the original format or in a compressed manner. " "This option is selectable only when downloading one document, for multiple " "documents, the bundle will always be downloads as a compressed file." -msgstr "" +msgstr "Scarica il documento nel formato originale o in modo compresso. Questa opzione è selezionabile solo quando il download di un documento, per i documenti multipli, il bundle sarà sempre download come un file compresso." #: literals.py:10 msgid "Document creation" @@ -328,23 +329,23 @@ msgstr "Documento \"%(document)s\" cancellato il %(datetime)s da %(fullname)s." #: literals.py:42 msgid "final" -msgstr "" +msgstr "finale" #: literals.py:43 msgid "alpha" -msgstr "" +msgstr "alfa" #: literals.py:44 msgid "beta" -msgstr "" +msgstr "beta" #: literals.py:45 msgid "release candidate" -msgstr "" +msgstr "Release Candidate" #: literals.py:46 msgid "hotfix" -msgstr "" +msgstr "hotfix" #: models.py:61 msgid "name" @@ -375,37 +376,37 @@ msgstr "documento" #: models.py:287 #, python-format msgid "Major %(major)i.%(minor)i, (new release)" -msgstr "" +msgstr "Magiore %(major)i.%(minor)i, (new release)" #: models.py:288 #, python-format msgid "Minor %(major)i.%(minor)i, (some updates)" -msgstr "" +msgstr "Minore %(major)i.%(minor)i, (some updates)" #: models.py:289 #, python-format msgid "Micro %(major)i.%(minor)i.%(micro)i, (fixes)" -msgstr "" +msgstr "Micro %(major)i.%(minor)i.%(micro)i, (fixes)" #: models.py:301 msgid "mayor" -msgstr "" +msgstr "maggiore" #: models.py:302 msgid "minor" -msgstr "" +msgstr "minore" #: models.py:303 msgid "micro" -msgstr "" +msgstr "micro" #: models.py:304 msgid "release level" -msgstr "" +msgstr "Livello di release" #: models.py:305 msgid "serial" -msgstr "" +msgstr "sequenziale" #: models.py:306 msgid "timestamp" @@ -732,7 +733,7 @@ msgstr "Il documento \"%s\" è ancora in modifica" #: views.py:342 msgid "documents to be downloaded" -msgstr "" +msgstr "documenti da scaricare" #: views.py:352 views.py:1337 msgid "version" @@ -740,11 +741,11 @@ msgstr "versione" #: views.py:409 msgid "Download" -msgstr "" +msgstr "Scarica" #: views.py:411 msgid "Return" -msgstr "" +msgstr "Ritorno" #: views.py:445 #, python-format @@ -980,16 +981,16 @@ msgstr "crea il nome file per i documenti di tipo:%s" #: views.py:1306 msgid "Document image cache cleared successfully" -msgstr "" +msgstr "Cancellata con successo la cache delle immagini dei documenti" #: views.py:1308 #, python-format msgid "Error clearing document image cache; %s" -msgstr "" +msgstr "Errore nella pulizia della cache del documento; %s" #: views.py:1314 msgid "Are you sure you wish to clear the document image cache?" -msgstr "" +msgstr "Sei sicuro di voler cancellare la cache delle immagini del documento?" #: views.py:1331 #, python-format @@ -998,15 +999,15 @@ msgstr "versioni per documento: %s" #: views.py:1341 msgid "time and date" -msgstr "" +msgstr "data e ora" #: views.py:1345 msgid "mimetype" -msgstr "" +msgstr "mimetype" #: views.py:1349 msgid "encoding" -msgstr "" +msgstr "codifica" #: views.py:1380 msgid "Document version reverted successfully" diff --git a/apps/documents/migrations/0014_change_document_mimetype_encoding_null.py b/apps/documents/migrations/0014_change_document_mimetype_encoding_null.py new file mode 100644 index 0000000000..57288c6aa8 --- /dev/null +++ b/apps/documents/migrations/0014_change_document_mimetype_encoding_null.py @@ -0,0 +1,160 @@ +# -*- 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): + + # Changing field 'DocumentVersion.mimetype' + db.alter_column('documents_documentversion', 'mimetype', self.gf('django.db.models.fields.CharField')(max_length=64, null=True)) + + # Changing field 'DocumentVersion.encoding' + db.alter_column('documents_documentversion', 'encoding', self.gf('django.db.models.fields.CharField')(max_length=64, null=True)) + + def backwards(self, orm): + + # Changing field 'DocumentVersion.mimetype' + db.alter_column('documents_documentversion', 'mimetype', self.gf('django.db.models.fields.CharField')(max_length=64)) + + # Changing field 'DocumentVersion.encoding' + db.alter_column('documents_documentversion', 'encoding', self.gf('django.db.models.fields.CharField')(max_length=64)) + + 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'}) + }, + 'comments.comment': { + 'Meta': {'ordering': "('submit_date',)", 'object_name': 'Comment', 'db_table': "'django_comments'"}, + 'comment': ('django.db.models.fields.TextField', [], {'max_length': '3000'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'content_type_set_for_comment'", 'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}), + 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_removed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'object_pk': ('django.db.models.fields.TextField', [], {}), + 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}), + 'submit_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comment_comments'", 'null': 'True', 'to': "orm['auth.User']"}), + 'user_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'user_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'user_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + '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'}) + }, + 'documents.document': { + 'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'}, + 'date_added': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']", 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '48', 'blank': 'True'}) + }, + 'documents.documentpage': { + 'Meta': {'ordering': "['page_number']", 'object_name': 'DocumentPage'}, + 'content': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'document_version': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentVersion']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'page_label': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), + 'page_number': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'}) + }, + 'documents.documentpagetransformation': { + 'Meta': {'ordering': "('order',)", 'object_name': 'DocumentPageTransformation'}, + 'arguments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'document_page': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentPage']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'transformation': ('django.db.models.fields.CharField', [], {'max_length': '128'}) + }, + 'documents.documenttype': { + 'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}) + }, + 'documents.documenttypefilename': { + 'Meta': {'ordering': "['filename']", 'object_name': 'DocumentTypeFilename'}, + 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']"}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'documents.documentversion': { + 'Meta': {'unique_together': "(('document', 'major', 'minor', 'micro', 'release_level', 'serial'),)", 'object_name': 'DocumentVersion'}, + 'checksum': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}), + 'encoding': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'filename': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'major': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'micro': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'mimetype': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'minor': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'release_level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'serial': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {}) + }, + 'documents.recentdocument': { + 'Meta': {'ordering': "('-datetime_accessed',)", 'object_name': 'RecentDocument'}, + 'datetime_accessed': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}), + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'sites.site': { + 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"}, + 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'taggit.tag': { + 'Meta': {'object_name': 'Tag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}) + }, + 'taggit.taggeditem': { + 'Meta': {'object_name': 'TaggedItem'}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"}) + } + } + + complete_apps = ['documents'] \ No newline at end of file diff --git a/apps/documents/models.py b/apps/documents/models.py index 57b2f2be51..8dfbe3d5d7 100644 --- a/apps/documents/models.py +++ b/apps/documents/models.py @@ -331,8 +331,8 @@ class DocumentVersion(models.Model): # File related fields file = models.FileField(upload_to=get_filename_from_uuid, storage=STORAGE_BACKEND(), verbose_name=_(u'file')) - mimetype = models.CharField(max_length=64, default='', editable=False) - encoding = models.CharField(max_length=64, default='', editable=False) + mimetype = models.CharField(max_length=64, null=True, blank=True, editable=False) + encoding = models.CharField(max_length=64, null=True, blank=True, editable=False) filename = models.CharField(max_length=255, default=u'', editable=False, db_index=True) checksum = models.TextField(blank=True, null=True, verbose_name=_(u'checksum'), editable=False) diff --git a/apps/documents/statistics.py b/apps/documents/statistics.py index 508d699a49..5c4eb46773 100644 --- a/apps/documents/statistics.py +++ b/apps/documents/statistics.py @@ -21,16 +21,20 @@ def get_used_size(path, file_list): def storage_count(path=u'.'): - directories, files = STORAGE_BACKEND().listdir(path) - total_count = len(files) - total_size = get_used_size(path, files) + try: + directories, files = STORAGE_BACKEND().listdir(path) + except OSError: + return 0, 0 + else: + total_count = len(files) + total_size = get_used_size(path, files) - for directory in directories: - file_count, files_size = storage_count(directory) - total_count += file_count - total_size += files_size + for directory in directories: + file_count, files_size = storage_count(directory) + total_count += file_count + total_size += files_size - return total_count, total_size + return total_count, total_size def get_statistics(): @@ -53,15 +57,15 @@ def get_statistics(): except NotImplementedError: pass + document_stats = DocumentVersion.objects.annotate(page_count=Count('documentpage')).aggregate(Min('page_count'), Max('page_count'), Avg('page_count')) paragraphs.extend( [ _(u'Document pages in database: %d') % DocumentPage.objects.only('pk',).count(), - _(u'Minimum amount of pages per document: %(page_count__min)d') % DocumentVersion.objects.annotate(page_count=Count('documentpage')).aggregate(Min('page_count')), - _(u'Maximum amount of pages per document: %(page_count__max)d') % DocumentVersion.objects.annotate(page_count=Count('documentpage')).aggregate(Max('page_count')), - _(u'Average amount of pages per document: %(page_count__avg)f') % DocumentVersion.objects.annotate(page_count=Count('documentpage')).aggregate(Avg('page_count')), + _(u'Minimum amount of pages per document: %d') % (document_stats['page_count__max'] or 0), + _(u'Maximum amount of pages per document: %d') % (document_stats['page_count__max'] or 0), + _(u'Average amount of pages per document: %f') % (document_stats['page_count__avg'] or 0), ] ) - #[(day_count['date_added'].strftime('%Y-%m-%d'), day_count['id__count']) for day_count in Document.objects.values('date_added').annotate(Count("id"))] return { 'title': _(u'Document statistics'), diff --git a/apps/documents/utils.py b/apps/documents/utils.py index 32658d5f43..cae8b87a5f 100644 --- a/apps/documents/utils.py +++ b/apps/documents/utils.py @@ -2,30 +2,6 @@ import os from common.conf.settings import TEMPORARY_DIRECTORY - -#http://stackoverflow.com/questions/123198/how-do-i-copy-a-file-in-python -def copyfile(source, dest, buffer_size=1024 * 1024): - """ - Copy a file from source to dest. source and dest - can either be strings or any object with a read or - write method, like StringIO for example. - """ - if not hasattr(source, 'read'): - source = open(source, 'rb') - if not hasattr(dest, 'write'): - dest = open(dest, 'wb') - - while True: - copy_buffer = source.read(buffer_size) - if copy_buffer: - dest.write(copy_buffer) - else: - break - - source.close() - dest.close() - - def document_save_to_temp_dir(document, filename, buffer_size=1024 * 1024): temporary_path = os.path.join(TEMPORARY_DIRECTORY, filename) return document.save_to_file(temporary_path, buffer_size) diff --git a/apps/documents/views.py b/apps/documents/views.py index 17e6ff9950..db3fe4f4b1 100644 --- a/apps/documents/views.py +++ b/apps/documents/views.py @@ -129,8 +129,8 @@ def document_view(request, document_id, advanced=False): if advanced: document_properties_form = DocumentPropertiesForm(instance=document, extra_fields=[ {'label': _(u'Filename'), 'field': 'filename'}, - {'label': _(u'File mimetype'), 'field': 'file_mimetype'}, - {'label': _(u'File mime encoding'), 'field': 'file_mime_encoding'}, + {'label': _(u'File mimetype'), 'field': lambda x: x.file_mimetype or _(u'None')}, + {'label': _(u'File mime encoding'), 'field': lambda x: x.file_mime_encoding or _(u'None')}, {'label': _(u'File size'), 'field':lambda x: pretty_size(x.size) if x.size else '-'}, {'label': _(u'Exists in storage'), 'field': 'exists'}, {'label': _(u'File path in storage'), 'field': 'file'}, diff --git a/apps/dynamic_search/locale/it/LC_MESSAGES/django.mo b/apps/dynamic_search/locale/it/LC_MESSAGES/django.mo index 3de067b8dc..51351035ec 100644 Binary files a/apps/dynamic_search/locale/it/LC_MESSAGES/django.mo and b/apps/dynamic_search/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/dynamic_search/locale/it/LC_MESSAGES/django.po b/apps/dynamic_search/locale/it/LC_MESSAGES/django.po index 9d354393b5..efb6829e14 100644 --- a/apps/dynamic_search/locale/it/LC_MESSAGES/django.po +++ b/apps/dynamic_search/locale/it/LC_MESSAGES/django.po @@ -1,22 +1,21 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # , 2011. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" "PO-Revision-Date: 2011-12-09 15:32+0000\n" "Last-Translator: Pierpaolo Baldan \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: __init__.py:5 @@ -62,8 +61,7 @@ msgstr "risultati della ricerca" #: views.py:33 #, python-format msgid "results, (showing only %(shown_result_count)s out of %(result_count)s)" -msgstr "" -"risultati, (mostra esclusivamente %(shown_result_count)s di %(result_count)s)" +msgstr "risultati, (mostra esclusivamente %(shown_result_count)s di %(result_count)s)" #: views.py:37 msgid "results" @@ -100,9 +98,7 @@ msgstr "Aiuto" msgid "" "Enter the desired search keywords separated by space. Only the top " "%(search_results_limit)s results will be available." -msgstr "" -"Inserisci le parole da cercare separate da spazzi. Solo i primi " -"%(search_results_limit)s saranno disponibili." +msgstr "Inserisci le parole da cercare separate da spazzi. Solo i primi %(search_results_limit)s saranno disponibili." #: templates/search_results.html:3 msgid "Search results" diff --git a/apps/folders/locale/it/LC_MESSAGES/django.mo b/apps/folders/locale/it/LC_MESSAGES/django.mo index a1af93bc03..a2bb375e3e 100644 Binary files a/apps/folders/locale/it/LC_MESSAGES/django.mo and b/apps/folders/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/folders/locale/it/LC_MESSAGES/django.po b/apps/folders/locale/it/LC_MESSAGES/django.po index 882101fe06..86cbc42c74 100644 --- a/apps/folders/locale/it/LC_MESSAGES/django.po +++ b/apps/folders/locale/it/LC_MESSAGES/django.po @@ -4,14 +4,15 @@ # # Translators: # , 2011. +# Pierpaolo Baldan , 2012. # Roberto Rosario , 2012. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" "Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" -"PO-Revision-Date: 2012-02-21 00:25+0000\n" -"Last-Translator: Roberto Rosario \n" +"PO-Revision-Date: 2012-03-21 13:23+0000\n" +"Last-Translator: Pierpaolo Baldan \n" "Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -53,7 +54,7 @@ msgstr "cartelle" #: __init__.py:27 msgid "ACLs" -msgstr "" +msgstr "ACL" #: forms.py:38 msgid "Folder" diff --git a/apps/history/locale/it/LC_MESSAGES/django.mo b/apps/history/locale/it/LC_MESSAGES/django.mo index 66749bbcf5..b342cca91c 100644 Binary files a/apps/history/locale/it/LC_MESSAGES/django.mo and b/apps/history/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/history/locale/it/LC_MESSAGES/django.po b/apps/history/locale/it/LC_MESSAGES/django.po index 823f6912a8..9f0a07d367 100644 --- a/apps/history/locale/it/LC_MESSAGES/django.po +++ b/apps/history/locale/it/LC_MESSAGES/django.po @@ -1,22 +1,22 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # , 2011. +# Pierpaolo Baldan , 2012. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" -"PO-Revision-Date: 2012-02-02 18:19+0000\n" -"Last-Translator: Roberto Rosario \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"PO-Revision-Date: 2012-03-21 13:30+0000\n" +"Last-Translator: Pierpaolo Baldan \n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: __init__.py:10 models.py:71 @@ -57,7 +57,7 @@ msgstr "Versioni" #: permissions.py:8 msgid "Access the history of an object" -msgstr "" +msgstr "Accedi alla storia di un oggetto" #: views.py:27 msgid "history events" diff --git a/apps/linking/locale/it/LC_MESSAGES/django.mo b/apps/linking/locale/it/LC_MESSAGES/django.mo index 0fd371e57b..ca7ddf5b92 100644 Binary files a/apps/linking/locale/it/LC_MESSAGES/django.mo and b/apps/linking/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/linking/locale/it/LC_MESSAGES/django.po b/apps/linking/locale/it/LC_MESSAGES/django.po index 5951339586..897b6b241f 100644 --- a/apps/linking/locale/it/LC_MESSAGES/django.po +++ b/apps/linking/locale/it/LC_MESSAGES/django.po @@ -1,22 +1,22 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # , 2011. +# Pierpaolo Baldan , 2012. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" -"PO-Revision-Date: 2012-02-02 18:19+0000\n" -"Last-Translator: Roberto Rosario \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"PO-Revision-Date: 2012-03-21 13:18+0000\n" +"Last-Translator: Pierpaolo Baldan \n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: __init__.py:17 @@ -53,7 +53,7 @@ msgstr "crea condizioni" #: __init__.py:31 msgid "ACLs" -msgstr "" +msgstr "ACL" #: forms.py:50 msgid "Pages" @@ -148,10 +148,7 @@ msgid "" "This expression will be evaluated against the current selected document. " "The document metadata is available as variables `metadata` and document " "properties under the variable `document`." -msgstr "" -"Questa espressione sarà valutata per il documento corrente selezionato. I " -"metadati del documento sono disponibile come variabili `metadati` e le " -"proprietà dei documenti sotto la variabile `documento`." +msgstr "Questa espressione sarà valutata per il documento corrente selezionato. I metadati del documento sono disponibile come variabili `metadati` e le proprietà dei documenti sotto la variabile `documento`." #: models.py:14 models.py:33 views.py:136 views.py:232 msgid "enabled" @@ -173,9 +170,7 @@ msgstr "dati del documento estero" msgid "" "This represents the metadata of all other documents. Available objects: " "`document.` and `metadata.`." -msgstr "" -"Questo rappresenta i metadati di tutti gli altri documenti. Oggetti " -"disponibili: `document.` e `metadata.`." +msgstr "Questo rappresenta i metadati di tutti gli altri documenti. Oggetti disponibili: `document.` e `metadata.`." #: models.py:31 msgid "expression" @@ -315,16 +310,12 @@ msgstr "Condizioni per il link intelligente: \"%s\" cancellato con successo." #, python-format msgid "" "Error deleting smart link condition: %(smart_link_condition)s; %(error)s." -msgstr "" -"Errore nella cancellazione del link intelligente: %(smart_link_condition)s; " -"%(error)s." +msgstr "Errore nella cancellazione del link intelligente: %(smart_link_condition)s; %(error)s." #: views.py:333 #, python-format msgid "Are you sure you wish to delete smart link condition: \"%s\"?" -msgstr "" -"Sei sicuro di voler cancellare le condizioni per il link intelligente : \"%s" -"\"?" +msgstr "Sei sicuro di voler cancellare le condizioni per il link intelligente : \"%s\"?" #: conf/settings.py:11 msgid "Show smart link that don't return any documents." @@ -341,10 +332,4 @@ msgid "" "source, the results of these queries are a list of documents that relate in " "some manner to the document being displayed and allow users the ability to " "jump to and from linked documents very easily." -msgstr "" -"Collegamenti intelligenti sono un insieme di istruzioni condizionali che " -"vengono utilizzati per interrogare il database utilizzando il documento " -"corrente l'utente sta accedendo come origine dati, i risultati di queste " -"query sono un elenco di documenti che riguardano in qualche modo al " -"documento e consentire la visualizzazione agli utenti la possibilità di " -"saltare da e per i documenti collegati molto facilmente." +msgstr "Collegamenti intelligenti sono un insieme di istruzioni condizionali che vengono utilizzati per interrogare il database utilizzando il documento corrente l'utente sta accedendo come origine dati, i risultati di queste query sono un elenco di documenti che riguardano in qualche modo al documento e consentire la visualizzazione agli utenti la possibilità di saltare da e per i documenti collegati molto facilmente." diff --git a/apps/metadata/locale/it/LC_MESSAGES/django.mo b/apps/metadata/locale/it/LC_MESSAGES/django.mo index 0303c94f85..a19c3e68e7 100644 Binary files a/apps/metadata/locale/it/LC_MESSAGES/django.mo and b/apps/metadata/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/metadata/locale/it/LC_MESSAGES/django.po b/apps/metadata/locale/it/LC_MESSAGES/django.po index a37122bdee..1ead75e3b6 100644 --- a/apps/metadata/locale/it/LC_MESSAGES/django.po +++ b/apps/metadata/locale/it/LC_MESSAGES/django.po @@ -4,14 +4,15 @@ # # Translators: # , 2011. +# Pierpaolo Baldan , 2012. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" "Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" -"PO-Revision-Date: 2012-02-12 19:24+0000\n" -"Last-Translator: Roberto Rosario \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/it/)\n" +"PO-Revision-Date: 2012-03-21 13:22+0000\n" +"Last-Translator: Pierpaolo Baldan \n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -139,9 +140,7 @@ msgstr "lookup" msgid "" "Enter a string to be evaluated. Example: [user.get_full_name() for user in " "User.objects.all()].%s" -msgstr "" -"Inserisci una stringa per la valutazione. Esempio: [user.get_full_name() " -"per l'utente User.objects.all()].%s" +msgstr "Inserisci una stringa per la valutazione. Esempio: [user.get_full_name() per l'utente User.objects.all()].%s" #: models.py:33 models.py:58 views.py:353 views.py:398 msgid "metadata type" @@ -259,8 +258,7 @@ msgstr "Errore nella cancellazione degli indici di documento;%s" #: views.py:99 #, python-format msgid "Error editing metadata for document %(document)s; %(error)s." -msgstr "" -"Errore nella modifica dei metadata per il documento %(document)s; %(error)s." +msgstr "Errore nella modifica dei metadata per il documento %(document)s; %(error)s." #: views.py:102 #, python-format @@ -291,16 +289,13 @@ msgstr "Modifica metadata per i documenti: %s" msgid "" "Metadata type: %(metadata_type)s successfully added to document " "%(document)s." -msgstr "" -"Tipo metadata: %(metadata_type)s aggiunto con successo al documento " -"%(document)s." +msgstr "Tipo metadata: %(metadata_type)s aggiunto con successo al documento %(document)s." #: views.py:164 #, python-format msgid "" "Metadata type: %(metadata_type)s already present in document %(document)s." -msgstr "" -"Tipo Metadata: %(metadata_type)s già presente per il documento %(document)s." +msgstr "Tipo Metadata: %(metadata_type)s già presente per il documento %(document)s." #: views.py:188 #, python-format @@ -317,17 +312,13 @@ msgstr "Aggiungi tipo metadata ai documents: %s" msgid "" "Successfully remove metadata type: %(metadata_type)s from document: " "%(document)s." -msgstr "" -"Rimuovere con successo tipo di metadati: %(metadata_type)s per il " -"documento: %(document)s." +msgstr "Rimuovere con successo tipo di metadati: %(metadata_type)s per il documento: %(document)s." #: views.py:262 #, python-format msgid "" "Error removing metadata type: %(metadata_type)s from document: %(document)s." -msgstr "" -"Errore durante la rimozione dei metadati di tipo: %(metadata_type)s per il " -"documento: %(document)s." +msgstr "Errore durante la rimozione dei metadati di tipo: %(metadata_type)s per il documento: %(document)s." #: views.py:281 #, python-format @@ -424,7 +415,7 @@ msgstr "Sei sicuro di voler eliminare il set di metadati: %s?" #: views.py:538 views.py:556 msgid "Metadata types" -msgstr "" +msgstr "Tipi di Metadati" #: views.py:594 #, python-format @@ -445,11 +436,7 @@ msgid "" "A metadata set is a group of one or more metadata types. Metadata sets are " "useful when creating new documents; selecing a metadata set automatically " "attaches it's member metadata types to said document." -msgstr "" -"Un insieme di metadati è un gruppo di uno o più tipi di metadati. Set di " -"metadati sono utili durante la creazione di nuovi documenti e, selezionando " -"un set di metadati allega automaticamente è membro tipi di metadati per " -"documentare detto." +msgstr "Un insieme di metadati è un gruppo di uno o più tipi di metadati. Set di metadati sono utili durante la creazione di nuovi documenti e, selezionando un set di metadati allega automaticamente è membro tipi di metadati per documentare detto." #: templates/metadata_type_help.html:3 msgid "What are metadata types?" @@ -466,16 +453,4 @@ msgid "" " will have initially, and the lookup value turns an instance of a metadata " "of this type into a choice list which options are the result of the lookup's" " code execution." -msgstr "" -"Un tipo di metadati definisce le caratteristiche di un valore di qualche " -"tipo che può essere collegato a un documento. Esempi di tipi di metadati: il" -" nome del client, una data o un progetto a cui appartengono diversi " -"documenti. Il nome di un tipo di metadati è l'identificatore interno con il " -"quale possono essere pubblicati da altri moduli come il modulo di " -"indicizzazione, il titolo è il valore che viene mostrato agli utenti, il " -"valore predefinito è il valore di un'istanza di questo tipo di metadati avrà" -" inizialmente, e il valore di ricerca si trasforma un'istanza di metadati di" -" questo tipo in un elenco di opzioni di scelta che sono il risultato della " -"esecuzione di codice la ricerca di." - - +msgstr "Un tipo di metadati definisce le caratteristiche di un valore di qualche tipo che può essere collegato a un documento. Esempi di tipi di metadati: il nome del client, una data o un progetto a cui appartengono diversi documenti. Il nome di un tipo di metadati è l'identificatore interno con il quale possono essere pubblicati da altri moduli come il modulo di indicizzazione, il titolo è il valore che viene mostrato agli utenti, il valore predefinito è il valore di un'istanza di questo tipo di metadati avrà inizialmente, e il valore di ricerca si trasforma un'istanza di metadati di questo tipo in un elenco di opzioni di scelta che sono il risultato della esecuzione di codice la ricerca di." diff --git a/apps/mimetype/api.py b/apps/mimetype/api.py index cc7e93db32..1580493a7e 100644 --- a/apps/mimetype/api.py +++ b/apps/mimetype/api.py @@ -94,8 +94,8 @@ def get_mimetype(file_description, filepath, mimetype_only=False): library via python-magic or fallback to use python's mimetypes library """ - file_mimetype = u'' - file_mime_encoding = u'' + file_mimetype = None + file_mime_encoding = None if USE_PYTHON_MAGIC: mime = magic.Magic(mime=True) file_mimetype = mime.from_buffer(file_description.read()) diff --git a/apps/navigation/locale/it/LC_MESSAGES/django.mo b/apps/navigation/locale/it/LC_MESSAGES/django.mo index bdb151f775..be999a7a8d 100644 Binary files a/apps/navigation/locale/it/LC_MESSAGES/django.mo and b/apps/navigation/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/navigation/locale/it/LC_MESSAGES/django.po b/apps/navigation/locale/it/LC_MESSAGES/django.po index 957fcd5f25..bae0bf6670 100644 --- a/apps/navigation/locale/it/LC_MESSAGES/django.po +++ b/apps/navigation/locale/it/LC_MESSAGES/django.po @@ -1,22 +1,21 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # , 2011. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" "PO-Revision-Date: 2011-12-09 18:00+0000\n" "Last-Translator: Pierpaolo Baldan \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: forms.py:14 diff --git a/apps/navigation/templatetags/navigation_tags.py b/apps/navigation/templatetags/navigation_tags.py index aefcef42af..e71ce6409c 100644 --- a/apps/navigation/templatetags/navigation_tags.py +++ b/apps/navigation/templatetags/navigation_tags.py @@ -3,11 +3,14 @@ from __future__ import absolute_import import copy import re import logging +#import urlparse +#import urllib from django.core.urlresolvers import reverse from django.template import (TemplateSyntaxError, Library, Node, Variable, VariableDoesNotExist) from django.utils.translation import ugettext as _ +from django.utils.encoding import smart_str, force_unicode, smart_unicode from ..api import (link_binding, multi_object_navigation, sidebar_templates, get_context_navigation_links) @@ -30,6 +33,184 @@ def get_top_menu_links(parser, token): return TopMenuNavigationNode() +''' +def resolve_arguments(context, src_args): + args = [] + kwargs = {} + if type(src_args) == type([]): + for i in src_args: + val = resolve_template_variable(context, i) + if val: + args.append(val) + elif type(src_args) == type({}): + for key, value in src_args.items(): + val = resolve_template_variable(context, value) + if val: + kwargs[key] = val + else: + val = resolve_template_variable(context, src_args) + if val: + args.append(val) + + return args, kwargs + + +def resolve_links(context, links, current_view, current_path, parsed_query_string=None): + """ + Express a list of links from definition to final values + """ + context_links = [] + for link in links: + # Check to see if link has conditional display + if 'condition' in link: + condition_result = link['condition'](context) + else: + condition_result = True + + if condition_result: + new_link = copy.copy(link) + try: + args, kwargs = resolve_arguments(context, link.get('args', {})) + except VariableDoesNotExist: + args = [] + kwargs = {} + + if 'view' in link: + if not link.get('dont_mark_active', False): + new_link['active'] = link['view'] == current_view + + try: + if kwargs: + new_link['url'] = reverse(link['view'], kwargs=kwargs) + else: + new_link['url'] = reverse(link['view'], args=args) + if link.get('keep_query', False): + print 'parsed_query_string', parsed_query_string + new_link['url'] = urlquote(new_link['url'], parsed_query_string) + except NoReverseMatch, err: + new_link['url'] = '#' + new_link['error'] = err + elif 'url' in link: + if not link.get('dont_mark_active', False): + new_link['active'] = link['url'] == current_path + + if kwargs: + new_link['url'] = link['url'] % kwargs + else: + new_link['url'] = link['url'] % args + if link.get('keep_query', False): + new_link['url'] = urlquote(new_link['url'], parsed_query_string) + else: + new_link['active'] = False + + if 'conditional_highlight' in link: + new_link['active'] = link['conditional_highlight'](context) + + if 'conditional_disable' in link: + new_link['disabled'] = link['conditional_disable'](context) + else: + new_link['disabled'] = False + + if current_view in link.get('children_views', []): + new_link['active'] = True + + for child_url_regex in link.get('children_url_regex', []): + if re.compile(child_url_regex).match(current_path.lstrip('/')): + new_link['active'] = True + + for children_view_regex in link.get('children_view_regex', []): + if re.compile(children_view_regex).match(current_view): + new_link['active'] = True + + for cls in link.get('children_classes', []): + obj, object_name = get_navigation_object(context) + if type(obj) == cls or obj == cls: + new_link['active'] = True + + context_links.append(new_link) + return context_links + + +def get_navigation_object(context): + try: + object_name = Variable('navigation_object_name').resolve(context) + except VariableDoesNotExist: + object_name = 'object' + + try: + obj = Variable(object_name).resolve(context) + except VariableDoesNotExist: + obj = None + + return obj, object_name + + +def _get_object_navigation_links(context, menu_name=None, links_dict=object_navigation): + request = Variable('request').resolve(context) + current_path = request.META['PATH_INFO'] + current_view = resolve_to_name(current_path) + context_links = [] + + # Don't fudge with the original global dictionary + links_dict = links_dict.copy() + + # Preserve unicode data in URL query + previous_path = smart_unicode(urllib.unquote_plus(smart_str(request.get_full_path()) or smart_str(request.META.get('HTTP_REFERER', u'/')))) + query_string = urlparse.urlparse(previous_path).query + parsed_query_string = urlparse.parse_qs(query_string) + + try: + """ + Override the navigation links dictionary with the provided + link list + """ + navigation_object_links = Variable('overrided_object_links').resolve(context) + if navigation_object_links: + return [link for link in resolve_links(context, navigation_object_links, current_view, current_path, parsed_query_string)] + except VariableDoesNotExist: + pass + + try: + """ + Check for and inject a temporary navigation dictionary + """ + temp_navigation_links = Variable('temporary_navigation_links').resolve(context) + if temp_navigation_links: + links_dict.update(temp_navigation_links) + except VariableDoesNotExist: + pass + + try: + links = links_dict[menu_name][current_view]['links'] + for link in resolve_links(context, links, current_view, current_path, parsed_query_string): + context_links.append(link) + except KeyError: + pass + + obj, object_name = get_navigation_object(context) + + try: + links = links_dict[menu_name][type(obj)]['links'] + for link in resolve_links(context, links, current_view, current_path, parsed_query_string): + context_links.append(link) + except KeyError: + pass + + return context_links + + +def resolve_template_variable(context, name): + try: + return unescape_string_literal(name) + except ValueError: + #return Variable(name).resolve(context) + #TODO: Research if should return always as a str + return str(Variable(name).resolve(context)) + except TypeError: + return name + + +''' class GetNavigationLinks(Node): def __init__(self, menu_name=None, links_dict=link_binding, var_name='object_navigation_links'): self.menu_name = menu_name diff --git a/apps/ocr/__init__.py b/apps/ocr/__init__.py index dac5f496d2..a667448a1a 100644 --- a/apps/ocr/__init__.py +++ b/apps/ocr/__init__.py @@ -50,7 +50,6 @@ setup_queue_transformation_edit = Link(text=_(u'edit'),view='setup_queue_transfo setup_queue_transformation_delete = Link(text=_(u'delete'),view='setup_queue_transformation_delete',args='transformation.pk',sprite='shape_square_delete') bind_links([Document], [submit_document]) - bind_links([DocumentQueue], [document_queue_disable, document_queue_enable, setup_queue_transformation_list]) bind_links([QueueTransformation], [setup_queue_transformation_edit, setup_queue_transformation_delete]) diff --git a/apps/ocr/conf/settings.py b/apps/ocr/conf/settings.py index 67fad8653e..1055e7c068 100644 --- a/apps/ocr/conf/settings.py +++ b/apps/ocr/conf/settings.py @@ -2,6 +2,7 @@ from django.utils.translation import ugettext_lazy as _ +<<<<<<< HEAD from smart_settings.api import Setting, SettingNamespace namespace = SettingNamespace('ocr', _(u'OCR'), module='ocr.conf.settings') @@ -61,3 +62,12 @@ Setting( description=_(u'File path to unpaper program.'), exists=True ) + +Setting( + namespace=namespace, + name='PDFTOTEXT_PATH', + global_name='OCR_PDFTOTEXT_PATH', + default=u'/usr/bin/pdftotext', + description=_(u'File path to poppler\'s pdftotext program used to extract text from PDF files.'), + exists=True +) diff --git a/apps/ocr/locale/it/LC_MESSAGES/django.mo b/apps/ocr/locale/it/LC_MESSAGES/django.mo index 75ac3ea7ef..d6e0cfd360 100644 Binary files a/apps/ocr/locale/it/LC_MESSAGES/django.mo and b/apps/ocr/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/ocr/locale/it/LC_MESSAGES/django.po b/apps/ocr/locale/it/LC_MESSAGES/django.po index 18fd6b973a..4b53d3edd8 100644 --- a/apps/ocr/locale/it/LC_MESSAGES/django.po +++ b/apps/ocr/locale/it/LC_MESSAGES/django.po @@ -1,22 +1,22 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # , 2011. +# Pierpaolo Baldan , 2012. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" -"PO-Revision-Date: 2012-02-02 18:19+0000\n" -"Last-Translator: Roberto Rosario \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"PO-Revision-Date: 2012-03-21 13:29+0000\n" +"Last-Translator: Pierpaolo Baldan \n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: __init__.py:32 __init__.py:33 @@ -47,9 +47,7 @@ msgstr "ripulisci il contenuto delle pagine" msgid "" "Runs a language filter to remove common OCR mistakes from document pages " "content." -msgstr "" -"Esegue un filtro per rimuovere i comuni errori di OCR dal contenuto del " -"documento pagine." +msgstr "Esegue un filtro per rimuovere i comuni errori di OCR dal contenuto del documento pagine." #: __init__.py:44 msgid "queue document list" @@ -187,19 +185,19 @@ msgstr "code dei documenti in trasformazione" #: permissions.py:8 msgid "Submit documents for OCR" -msgstr "" +msgstr "Inviare documenti all OCR" #: permissions.py:9 msgid "Delete documents from OCR queue" -msgstr "" +msgstr "Cancella documenti dalla coda OCR" #: permissions.py:10 msgid "Can enable/disable the OCR queue" -msgstr "" +msgstr "Puoi abilitare/disabilitare la coda OCR" #: permissions.py:11 msgid "Can execute the OCR clean up on all document pages" -msgstr "" +msgstr "Posso effettuare la pulizia dell OCR di tutte le pagine dei documenti" #: permissions.py:12 msgid "Can edit an OCR queue properties" @@ -269,8 +267,7 @@ msgstr "Sei sicuro di voler cancellare queste code documento: %s?" #: views.py:148 #, python-format msgid "Document: %(document)s was added to the OCR queue: %(queue)s." -msgstr "" -"Il documento: %(document)s è stato aggiunto alla coda %(queue)s per OCR." +msgstr "Il documento: %(document)s è stato aggiunto alla coda %(queue)s per OCR." #: views.py:151 #, python-format @@ -381,9 +378,7 @@ msgstr "Errore nella cancellazione della coda di trasformazione; %(error)s" #, python-format msgid "" "Are you sure you wish to delete queue transformation \"%(transformation)s\"" -msgstr "" -"Sei sicuro di voler cancellare la coda di trasformazione \"%(transformation)s" -"\"" +msgstr "Sei sicuro di voler cancellare la coda di trasformazione \"%(transformation)s\"" #: views.py:412 msgid "Queue transformation created successfully" @@ -403,15 +398,11 @@ msgstr "Crea una nuova coda di trasformazione:%s" msgid "" "Amount of seconds to delay OCR of documents to allow for the node's storage " "replication overhead." -msgstr "" -"Quantità di secondi di ritardo OCR di documenti per consentire lo stoccaggio " -"nel nodo di replica." +msgstr "Quantità di secondi di ritardo OCR di documenti per consentire lo stoccaggio nel nodo di replica." #: conf/settings.py:14 msgid "Maximum amount of concurrent document OCRs a node can perform." -msgstr "" -"Importo massimo di documenti concorrenti per OCR che un nodo è in grado di " -"eseguire." +msgstr "Importo massimo di documenti concorrenti per OCR che un nodo è in grado di eseguire." #: conf/settings.py:15 msgid "Automatically queue newly created documents for OCR." diff --git a/apps/ocr/models.py b/apps/ocr/models.py index 3717f0ffe9..895ad38999 100644 --- a/apps/ocr/models.py +++ b/apps/ocr/models.py @@ -17,7 +17,8 @@ from sources.managers import SourceTransformationManager from .literals import (DOCUMENTQUEUE_STATE_STOPPED, DOCUMENTQUEUE_STATE_CHOICES, QUEUEDOCUMENT_STATE_PENDING, - QUEUEDOCUMENT_STATE_CHOICES, QUEUEDOCUMENT_STATE_PROCESSING) + QUEUEDOCUMENT_STATE_CHOICES, QUEUEDOCUMENT_STATE_PROCESSING, + DOCUMENTQUEUE_STATE_ACTIVE) from .managers import DocumentQueueManager from .exceptions import ReQueueError @@ -27,7 +28,7 @@ class DocumentQueue(models.Model): label = models.CharField(max_length=64, verbose_name=_(u'label')) state = models.CharField(max_length=4, choices=DOCUMENTQUEUE_STATE_CHOICES, - default=DOCUMENTQUEUE_STATE_STOPPED, + default=DOCUMENTQUEUE_STATE_ACTIVE, verbose_name=_(u'state')) objects = DocumentQueueManager() diff --git a/apps/ocr/parsers/__init__.py b/apps/ocr/parsers/__init__.py index 6a91d392d4..c9be3f7eed 100644 --- a/apps/ocr/parsers/__init__.py +++ b/apps/ocr/parsers/__init__.py @@ -1,5 +1,8 @@ +import os import slate import logging +import tempfile +import subprocess from django.utils.translation import ugettext as _ @@ -7,68 +10,160 @@ from converter import office_converter from converter.office_converter import OfficeConverter from converter.exceptions import OfficeConversionError from documents.utils import document_save_to_temp_dir +from common.utils import copyfile +from common.conf.settings import TEMPORARY_DIRECTORY from ocr.parsers.exceptions import ParserError, ParserUnknownFile +from ocr.conf.settings import PDFTOTEXT_PATH mimetype_registry = {} logger = logging.getLogger(__name__) -def register_parser(function, mimetype=None, mimetypes=None): - if mimetypes: - for mimetype in mimetypes: - mimetype_registry[mimetype] = {'function': function} - else: - mimetype_registry[mimetype] = {'function': function} +def register_parser(mimetypes, parsers): + for mimetype in mimetypes: + for parser in parsers: + try: + parser_instance = parser() + except ParserError: + # If parser fails initialization is not added to the list for this mimetype + pass + else: + mimetype_registry.setdefault(mimetype, []).append(parser_instance) -def pdf_parser(document_page, descriptor=None): - if not descriptor: - descriptor = document_page.document_version.open() - - pdf_pages = slate.PDF(descriptor) - descriptor.close() - - if pdf_pages[document_page.page_number - 1] == '\x0c': - raise ParserError - - document_page.content = pdf_pages[document_page.page_number - 1] - document_page.page_label = _(u'Text extracted from PDF') - document_page.save() - - -def office_parser(document_page): - logger.debug('executing') - try: - office_converter = OfficeConverter() - document_file = document_save_to_temp_dir(document_page.document, document_page.document.checksum) - logger.debug('document_file: %s', document_file) - - office_converter.convert(document_file, mimetype=document_page.document.file_mimetype) - if office_converter.exists: - input_filepath = office_converter.output_filepath - logger.debug('office_converter.output_filepath: %s', input_filepath) - - pdf_parser(document_page, descriptor=open(input_filepath)) - else: - raise ParserError - - except OfficeConversionError, msg: - print msg - raise ParserError - - -def parse_document_page(document_page): +def parse_document_page(document_page, descriptor=None, mimetype=None): logger.debug('executing') logger.debug('document_page: %s' % document_page) logger.debug('mimetype: %s' % document_page.document.file_mimetype) + if not mimetype: + mimetype = document_page.document.file_mimetype + try: - mimetype_registry[document_page.document.file_mimetype]['function'](document_page) + for parser in mimetype_registry[mimetype]: + try: + parser.parse(document_page, descriptor) + except ParserError: + # If parser raises error, try next parser in the list + pass + else: + # If parser was successfull there is no need to try + # others in the list for this mimetype + return + + raise ParserError('Parser list exhausted') except KeyError: raise ParserUnknownFile -register_parser(mimetype=u'application/pdf', function=pdf_parser) -register_parser(mimetypes=office_converter.CONVERTER_OFFICE_FILE_MIMETYPES, function=office_parser) +class Parser(object): + """ + Parser base class + """ + + def parse(self, document_page, descriptor=None): + raise NotImplementedError("Your %s class has not defined a parse() method, which is required." % self.__class__.__name__) + + +class SlateParser(Parser): + """ + Parser for PDF files using the slate library for Python + """ + def parse(self, document_page, descriptor=None): + logger.debug('Starting SlateParser') + + if not descriptor: + descriptor = document_page.document_version.open() + + pdf_pages = slate.PDF(descriptor) + descriptor.close() + + if pdf_pages[document_page.page_number - 1] == '\x0c': + raise ParserError + + document_page.content = pdf_pages[document_page.page_number - 1] + document_page.page_label = _(u'Text extracted from PDF') + document_page.save() + + +class OfficeParser(Parser): + """ + Parser for office document formats + """ + def parse(self, document_page, descriptor=None): + logger.debug('executing') + try: + office_converter = OfficeConverter() + document_file = document_save_to_temp_dir(document_page.document, document_page.document.checksum) + logger.debug('document_file: %s', document_file) + + office_converter.convert(document_file, mimetype=document_page.document.file_mimetype) + if office_converter.exists: + input_filepath = office_converter.output_filepath + logger.debug('office_converter.output_filepath: %s', input_filepath) + + # Now that the office document has been converted to PDF + # call the coresponding PDF parser in this new file + parse_document_page(document_page, descriptor=open(input_filepath), mimetype=u'application/pdf') + else: + raise ParserError + + except OfficeConversionError, msg: + logger.error(msg) + raise ParserError + + +class PopplerParser(Parser): + """ + PDF parser using the pdftotext execute from the poppler package + """ + def __init__(self): + self.pdftotext_path = PDFTOTEXT_PATH if PDFTOTEXT_PATH else u'/usr/bin/pdftotext' + if not os.path.exists(self.pdftotext_path): + raise ParserError('cannot find pdftotext executable') + logger.debug('self.pdftotext_path: %s' % self.pdftotext_path) + + def parse(self, document_page, descriptor=None): + logger.debug('parsing PDF with PopplerParser') + pagenum = str(document_page.page_number) + + if descriptor: + destination_descriptor, temp_filepath = tempfile.mkstemp(dir=TEMPORARY_DIRECTORY) + copyfile(descriptor, temp_filepath) + document_file = temp_filepath + else: + document_file = document_save_to_temp_dir(document_page.document, document_page.document.checksum) + + logger.debug('document_file: %s', document_file) + + logger.debug('parsing PDF page %s' % pagenum) + + command = [] + command.append(self.pdftotext_path) + command.append('-f') + command.append(pagenum) + command.append('-l') + command.append(pagenum) + command.append(document_file) + command.append('-') + + proc = subprocess.Popen(command, close_fds=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) + return_code = proc.wait() + if return_code != 0: + logger.error(proc.stderr.readline()) + raise ParserError + + output = proc.stdout.read() + if output == '\x0c': + logger.debug('Parser didn\'t any output') + raise ParserError('No output') + + document_page.content = output + document_page.page_label = _(u'Text extracted from PDF') + document_page.save() + + +register_parser(mimetypes=[u'application/pdf'], parsers=[PopplerParser, SlateParser]) +register_parser(mimetypes=office_converter.CONVERTER_OFFICE_FILE_MIMETYPES, parsers=[OfficeParser]) diff --git a/apps/ocr/tasks.py b/apps/ocr/tasks.py index 800d0623d2..c1b9c937d4 100644 --- a/apps/ocr/tasks.py +++ b/apps/ocr/tasks.py @@ -66,8 +66,7 @@ def task_process_document_queues(): oldest_queued_document = oldest_queued_document_qs.order_by('datetime_submitted')[0] process_job(task_process_queue_document, oldest_queued_document.pk) except Exception, e: - pass - #print 'DocumentQueueWatcher exception: %s' % e + logger.error('unhandled exception: %s' % e) finally: # Don't process anymore from this queryset, might be stale break diff --git a/apps/permissions/locale/it/LC_MESSAGES/django.mo b/apps/permissions/locale/it/LC_MESSAGES/django.mo index 1662db40f5..629ce70c6d 100644 Binary files a/apps/permissions/locale/it/LC_MESSAGES/django.mo and b/apps/permissions/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/permissions/locale/it/LC_MESSAGES/django.po b/apps/permissions/locale/it/LC_MESSAGES/django.po index c9c70931c1..030957dca2 100644 --- a/apps/permissions/locale/it/LC_MESSAGES/django.po +++ b/apps/permissions/locale/it/LC_MESSAGES/django.po @@ -1,22 +1,22 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # , 2011. +# Pierpaolo Baldan , 2012. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" -"PO-Revision-Date: 2012-02-02 18:18+0000\n" -"Last-Translator: Roberto Rosario \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"PO-Revision-Date: 2012-03-21 13:31+0000\n" +"Last-Translator: Pierpaolo Baldan \n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: __init__.py:17 models.py:209 views.py:40 @@ -151,9 +151,7 @@ msgstr "%(requester)s, ha già il permesso \"%(permission)s\" concesso." #, python-format msgid "" "Are you sure you wish to grant the %(permissions_label)s %(title_suffix)s?" -msgstr "" -"Sei sicuro che tu voglia concedere questo permesso %(permissions_label)s " -"%(title_suffix)s?" +msgstr "Sei sicuro che tu voglia concedere questo permesso %(permissions_label)s %(title_suffix)s?" #: views.py:222 #, python-format @@ -169,21 +167,19 @@ msgstr "%(requester)s, non ha i permessi \"%(permission)s\" consentiti." #, python-format msgid "" "Are you sure you wish to revoke the %(permissions_label)s %(title_suffix)s?" -msgstr "" -"Sei sicuro di voler revocare questo permesso %(permissions_label)s " -"%(title_suffix)s?" +msgstr "Sei sicuro di voler revocare questo permesso %(permissions_label)s %(title_suffix)s?" #: views.py:271 views.py:295 msgid "Users" -msgstr "" +msgstr "Utenti" #: views.py:274 views.py:298 msgid "Groups" -msgstr "" +msgstr "Gruppi" #: views.py:277 views.py:301 msgid "Special" -msgstr "" +msgstr "Speciale" #: views.py:330 #, python-format @@ -207,6 +203,4 @@ msgstr "Concessione" msgid "" "A list of existing roles that are automatically assigned to newly created " "users" -msgstr "" -"Un elenco di ruoli esistenti che vengono automaticamente assegnati agli " -"utenti appena creati" +msgstr "Un elenco di ruoli esistenti che vengono automaticamente assegnati agli utenti appena creati" diff --git a/apps/project_setup/locale/it/LC_MESSAGES/django.mo b/apps/project_setup/locale/it/LC_MESSAGES/django.mo index 8147693df5..552b7388f3 100644 Binary files a/apps/project_setup/locale/it/LC_MESSAGES/django.mo and b/apps/project_setup/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/project_setup/locale/it/LC_MESSAGES/django.po b/apps/project_setup/locale/it/LC_MESSAGES/django.po index 647c2314ad..e4cc8b132d 100644 --- a/apps/project_setup/locale/it/LC_MESSAGES/django.po +++ b/apps/project_setup/locale/it/LC_MESSAGES/django.po @@ -1,22 +1,21 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # , 2011. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" "PO-Revision-Date: 2011-12-09 18:08+0000\n" "Last-Translator: Pierpaolo Baldan \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: __init__.py:6 diff --git a/apps/project_tools/locale/it/LC_MESSAGES/django.mo b/apps/project_tools/locale/it/LC_MESSAGES/django.mo index de891e390b..9febddf279 100644 Binary files a/apps/project_tools/locale/it/LC_MESSAGES/django.mo and b/apps/project_tools/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/project_tools/locale/it/LC_MESSAGES/django.po b/apps/project_tools/locale/it/LC_MESSAGES/django.po index ca3f7d9be2..4c2ca80d19 100644 --- a/apps/project_tools/locale/it/LC_MESSAGES/django.po +++ b/apps/project_tools/locale/it/LC_MESSAGES/django.po @@ -1,22 +1,21 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # , 2011. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" "PO-Revision-Date: 2011-12-09 18:01+0000\n" "Last-Translator: Pierpaolo Baldan \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: __init__.py:7 views.py:15 diff --git a/apps/smart_settings/locale/it/LC_MESSAGES/django.mo b/apps/smart_settings/locale/it/LC_MESSAGES/django.mo index d36c2eacdc..179c3d6ef8 100644 Binary files a/apps/smart_settings/locale/it/LC_MESSAGES/django.mo and b/apps/smart_settings/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/smart_settings/locale/it/LC_MESSAGES/django.po b/apps/smart_settings/locale/it/LC_MESSAGES/django.po index ddd908c065..c830f284f7 100644 --- a/apps/smart_settings/locale/it/LC_MESSAGES/django.po +++ b/apps/smart_settings/locale/it/LC_MESSAGES/django.po @@ -1,22 +1,21 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # , 2011. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" "PO-Revision-Date: 2011-12-09 17:38+0000\n" "Last-Translator: Pierpaolo Baldan \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: __init__.py:9 views.py:28 diff --git a/apps/sources/locale/it/LC_MESSAGES/django.mo b/apps/sources/locale/it/LC_MESSAGES/django.mo index 73223cfe1a..0224510929 100644 Binary files a/apps/sources/locale/it/LC_MESSAGES/django.mo and b/apps/sources/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/sources/locale/it/LC_MESSAGES/django.po b/apps/sources/locale/it/LC_MESSAGES/django.po index 3905bd9f58..be78eff9df 100644 --- a/apps/sources/locale/it/LC_MESSAGES/django.po +++ b/apps/sources/locale/it/LC_MESSAGES/django.po @@ -4,14 +4,15 @@ # # Translators: # , 2011. +# Pierpaolo Baldan , 2012. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" "Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" -"PO-Revision-Date: 2012-02-12 19:23+0000\n" -"Last-Translator: Roberto Rosario \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/it/)\n" +"PO-Revision-Date: 2012-03-21 14:07+0000\n" +"Last-Translator: Pierpaolo Baldan \n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -64,7 +65,7 @@ msgstr "Sorgente del documento" #: __init__.py:38 msgid "upload new version" -msgstr "" +msgstr "Carica nuova versione" #: __init__.py:68 widgets.py:39 msgid "thumbnail" @@ -84,7 +85,7 @@ msgstr "Mostra file" #: forms.py:50 msgid "File" -msgstr "" +msgstr "File" #: literals.py:8 literals.py:13 msgid "Always" @@ -196,9 +197,7 @@ msgstr "anteprima larghezza" #: models.py:159 msgid "Width value to be passed to the converter backend." -msgstr "" -"valore della larghezza da passare per le operazioni di conversione in " -"backend" +msgstr "valore della larghezza da passare per le operazioni di conversione in backend" #: models.py:160 msgid "preview height" @@ -206,8 +205,7 @@ msgstr "anteprima altezza" #: models.py:160 msgid "Height value to be passed to the converter backend." -msgstr "" -"valore dell'altezza da passare per le operazioni di conversione in backend" +msgstr "valore dell'altezza da passare per le operazioni di conversione in backend" #: models.py:161 models.py:198 models.py:211 msgid "uncompress" @@ -237,9 +235,7 @@ msgstr "intervallo" msgid "" "Inverval in seconds where the watch folder path is checked for new " "documents." -msgstr "" -"Invervallo di pochi secondi in cui viene controllato il percorso cartella di" -" controllo per i nuovi documenti." +msgstr "Invervallo di pochi secondi in cui viene controllato il percorso cartella di controllo per i nuovi documenti." #: models.py:237 msgid "watch folder" @@ -276,7 +272,7 @@ msgstr "trasformazioni dei documenti sorgente" #: models.py:290 models.py:291 msgid "out of process" -msgstr "" +msgstr "fuori del processo" #: permissions.py:7 msgid "Sources setup" @@ -328,41 +324,38 @@ msgstr "Sorgenti caricamento" #: views.py:105 msgid "" "No interactive document sources have been defined or none have been enabled." -msgstr "" -"Nessuna fonte interattiva dei documenti sono state definite o non ne sono " -"state attivate." +msgstr "Nessuna fonte interattiva dei documenti sono state definite o non ne sono state attivate." #: views.py:106 #, python-format msgid "Click %(setup_link)s to add or enable some document sources." -msgstr "" -"Click %(setup_link)s per aggiungere o abilitare una sorgente documenti." +msgstr "Click %(setup_link)s per aggiungere o abilitare una sorgente documenti." #: views.py:163 msgid "New document version uploaded successfully." -msgstr "" +msgstr "Nuova versione del documento caricata con successo." #: views.py:167 msgid "File uploaded successfully." -msgstr "" +msgstr "File caricato con successo." #: views.py:170 msgid "File uncompressed successfully and uploaded as individual files." -msgstr "" +msgstr "File non compresso e caricato con successo come singolo file." #: views.py:173 msgid "File was not a compressed file, uploaded as it was." -msgstr "" +msgstr "Il file non era un file compresso,è stato caricato così com'era." #: views.py:179 views.py:258 #, python-format msgid "Unhandled exception: %s" -msgstr "" +msgstr "Eccezione non gestita: %s" #: views.py:188 #, python-format msgid "upload a new version from source: %s" -msgstr "" +msgstr "caricata una nuova versione da: %s" #: views.py:190 #, python-format @@ -372,7 +365,7 @@ msgstr "carica un documento in locale dalla sorgente: %s" #: views.py:236 #, python-format msgid "Document version from staging file: %s, uploaded successfully." -msgstr "" +msgstr "Versione documento da gestione temporanea file: %s,caricata con successo" #: views.py:239 #, python-format @@ -384,12 +377,12 @@ msgstr "File in allestimento:%s, caricato con successo." msgid "" "Staging file: %s, uncompressed successfully and uploaded as individual " "files." -msgstr "" +msgstr "file temporaneo: %s, non compresso e caricato come file singolo" #: views.py:245 #, python-format msgid "Staging file: %s, was not compressed, uploaded as a single file." -msgstr "" +msgstr "file temporaneo: %s, non è stato compresso, caricato come file singolo." #: views.py:250 #, python-format @@ -399,7 +392,7 @@ msgstr "File in allestimento:%s, cancellato con successo." #: views.py:273 #, python-format msgid "upload a new version from staging source: %s" -msgstr "" +msgstr "caricata una nuova versione da file temporaneo: %s" #: views.py:275 #, python-format @@ -412,11 +405,11 @@ msgstr "path dei file in allestimento" #: views.py:320 msgid "Current document type" -msgstr "" +msgstr "Tipo di documento corrente" #: views.py:321 msgid "None" -msgstr "" +msgstr "Nessuno" #: views.py:328 msgid "Current metadata" @@ -510,16 +503,13 @@ msgstr "Sorgente per la trasformazione cancellata con successo." #: views.py:646 #, python-format msgid "Error deleting source transformation; %(error)s" -msgstr "" -"Erroro nella cancellazione della sorgente per la trasformazione; %(error)s" +msgstr "Erroro nella cancellazione della sorgente per la trasformazione; %(error)s" #: views.py:659 #, python-format msgid "" "Are you sure you wish to delete source transformation \"%(transformation)s\"" -msgstr "" -"Sei sicuro di voler cancellare la sorgente di trasformazione " -"\"%(transformation)s\"" +msgstr "Sei sicuro di voler cancellare la sorgente di trasformazione \"%(transformation)s\"" #: views.py:689 msgid "Source transformation created successfully" @@ -534,5 +524,3 @@ msgstr "Errore nella creazione della sorgente di trasformazione; %s" #, python-format msgid "Create new transformation for source: %s" msgstr "Crea una nuova sorgente per la trasformazione:%s" - - diff --git a/apps/tags/locale/it/LC_MESSAGES/django.mo b/apps/tags/locale/it/LC_MESSAGES/django.mo index 053f74c273..32ff33bacb 100644 Binary files a/apps/tags/locale/it/LC_MESSAGES/django.mo and b/apps/tags/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/tags/locale/it/LC_MESSAGES/django.po b/apps/tags/locale/it/LC_MESSAGES/django.po index 34e4aceea0..8b4d43b544 100644 --- a/apps/tags/locale/it/LC_MESSAGES/django.po +++ b/apps/tags/locale/it/LC_MESSAGES/django.po @@ -4,15 +4,16 @@ # # Translators: # , 2011. +# Pierpaolo Baldan , 2012. # Roberto Rosario , 2011. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" "Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" -"PO-Revision-Date: 2012-02-12 19:23+0000\n" -"Last-Translator: Roberto Rosario \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/it/)\n" +"PO-Revision-Date: 2012-03-21 13:46+0000\n" +"Last-Translator: Pierpaolo Baldan \n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -53,11 +54,11 @@ msgstr "documenti etichettati" #: __init__.py:30 msgid "ACLs" -msgstr "" +msgstr "ACLs" #: __init__.py:34 msgid "preview" -msgstr "" +msgstr "anteprima" #: __init__.py:38 msgid "tagged items" @@ -137,19 +138,19 @@ msgstr "Crea un nuova etichetta" #: permissions.py:10 msgid "Delete tags" -msgstr "" +msgstr "Eliminare i tag" #: permissions.py:11 msgid "Edit tags" -msgstr "" +msgstr "Modificare i tag" #: permissions.py:12 msgid "View tags" -msgstr "" +msgstr "Visualizzare i tag" #: permissions.py:13 msgid "Attach tags to documents" -msgstr "" +msgstr "Applicare i tag ai documenti" #: permissions.py:14 msgid "Remove tags from documents" @@ -247,5 +248,3 @@ msgstr "Sei sicuro di voler rimuovere le etichette: %s ?" #: templatetags/tags_tags.py:17 msgid "Add tag to document" msgstr "Aggiungi l'etichetta al documento" - - diff --git a/apps/web_theme/locale/it/LC_MESSAGES/django.mo b/apps/web_theme/locale/it/LC_MESSAGES/django.mo index 989093a22a..12ad99730e 100644 Binary files a/apps/web_theme/locale/it/LC_MESSAGES/django.mo and b/apps/web_theme/locale/it/LC_MESSAGES/django.mo differ diff --git a/apps/web_theme/locale/it/LC_MESSAGES/django.po b/apps/web_theme/locale/it/LC_MESSAGES/django.po index 26968a531a..07d019a4b5 100644 --- a/apps/web_theme/locale/it/LC_MESSAGES/django.po +++ b/apps/web_theme/locale/it/LC_MESSAGES/django.po @@ -1,22 +1,21 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # , 2011. msgid "" msgstr "" "Project-Id-Version: Mayan EDMS\n" -"Report-Msgid-Bugs-To: \n" +"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n" "POT-Creation-Date: 2012-02-12 15:20-0400\n" "PO-Revision-Date: 2011-12-09 18:07+0000\n" "Last-Translator: Pierpaolo Baldan \n" -"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/" -"it/)\n" -"Language: it\n" +"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" #: conf/settings.py:10 @@ -24,10 +23,7 @@ msgid "" "CSS theme to apply, options are: amro, bec, bec-green, blue, default, djime-" "cerulean, drastic-dark, kathleene, olive, orange, red, reidb-greenish and " "warehouse." -msgstr "" -"Tema CSS da applicare, le opzioni sono: ABN AMRO, bec, bec-verde, blu, di " -"default, djime-ceruleo, drastica-scuro, kathleene, oliva, arancio, rosso, " -"reidb-verdastro e magazzino." +msgstr "Tema CSS da applicare, le opzioni sono: ABN AMRO, bec, bec-verde, blu, di default, djime-ceruleo, drastica-scuro, kathleene, oliva, arancio, rosso, reidb-verdastro e magazzino." #: conf/settings.py:12 msgid "Display extra information in the login screen." @@ -66,9 +62,7 @@ msgstr "Reindirizzamento al tuo punto di ingresso al sito in 5 secondi." msgid "" "Or click here if redirection doesn't " "work." -msgstr "" -"Oppure click qui if per essere " -"rimandato al tuo sito nel caso non funzioni." +msgstr "Oppure click qui if per essere rimandato al tuo sito nel caso non funzioni." #: templates/pagination/pagination.html:6 #: templates/pagination/pagination.html:8 diff --git a/contrib/fabfile.tar.gz b/contrib/fabfile.tar.gz new file mode 100644 index 0000000000..14cd5c4c2e Binary files /dev/null and b/contrib/fabfile.tar.gz differ diff --git a/contrib/metadata_conversion.txt b/contrib/metadata_conversion.txt deleted file mode 100644 index f21d250da9..0000000000 --- a/contrib/metadata_conversion.txt +++ /dev/null @@ -1,7 +0,0 @@ -mysqldump mayan documents_metadatatype -u root -p | replace 'documents_metadatatype' 'metadata_metadatatype' > new_types.mysql -cat new_types.mysql | mysql -u root -p mayan - -mysqldump mayan documents_documentmetadata -u root -p | replace 'documents_documentmetadata' 'metadata_documentmetadata' > new_metadata.mysql -cat new_metadata.mysql | mysql -u root -p mayan - - diff --git a/docs/conf.py b/docs/conf.py index ded1ddc7f8..c5b1ad6046 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -52,10 +52,10 @@ copyright = u'2011, Roberto Rosario' # built documents. # # The short X.Y version. -version = '0.12' +version = '0.12.1' # The full version, including alpha/beta/rc tags. -release = '0.12' +release = '0.12.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/credits/contributors.rst b/docs/credits/contributors.rst index 7d015e8d78..1b34f42e0f 100644 --- a/docs/credits/contributors.rst +++ b/docs/credits/contributors.rst @@ -15,7 +15,7 @@ Bug fixes --------- * Aziz M. Bookwala (https://github.com/azizmb) * IHLeanne (https://github.com/IHLeanne) -* Сергей Глита [Sergey Glita] (s.v.glita@gmail.com) +* Sergey Glita (s.v.glita@gmail.com) * Meurig Freeman (https://github.com/meurig) * David Herring (https://github.com/abadger1406) @@ -27,24 +27,27 @@ Bug reports * Joost Cassee (joost@cassee.net, https://github.com/jcassee) * Brian Huxley * dAnjou (https://github.com/dAnjou) -* Сергей Глита [Sergey Glita] (s.v.glita@gmail.com) +* Sergey Glita (s.v.glita@gmail.com) * IHLeanne (https://github.com/IHLeanne) * valterwill (https://github.com/valterwill) * David Herring (https://github.com/abadger1406) +* Alexandru Kiss (usurel@gmail.com) Patches ------- * Meurig Freeman (https://github.com/meurig) -* Сергей Глита [Sergey Glita] (s.v.glita@gmail.com) +* Sergey Glita (s.v.glita@gmail.com) +* Brian E (brian@realize.org) Suggestions ----------- * Cezar Jenkins (https://twitter.com/#!/emperorcezar) -* Сергей Глита [Sergey Glita] (s.v.glita@gmail.com) +* Sergey Glita (s.v.glita@gmail.com) * Barry Rowlingson (http://geospaced.blogspot.com) * Gour (https://github.com/gour) +* Alexandru Kiss (usurel@gmail.com) Translations @@ -56,7 +59,7 @@ Translations * Russian - - Сергей Глита [Sergey Glita] (s.v.glita@gmail.com) + - Sergey Glita (s.v.glita@gmail.com) * Italian @@ -69,9 +72,10 @@ Translations Remote access for debugging --------------------------- -* Сергей Глита [Sergey Glita] (s.v.glita@gmail.com) +* Sergey Glita (s.v.glita@gmail.com) * David Herring (https://github.com/abadger1406) * Michael Terretta (terretta@gmail.com) +* Alexandru Kiss (usurel@gmail.com) Monetary donations diff --git a/docs/index.rst b/docs/index.rst index 0079a21776..fe94d819c9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -23,6 +23,7 @@ On the Web * Website: http://www.mayan-edms.com * Source: http://github.com/rosarior/mayan * Video: http://bit.ly/Mayan-Intro +* Mailing list: http://groups.google.com/group/mayan-edms/ Looking for specific information? Try the :doc:`detailed table of contents ` otherwise below are the different part of the documentation. diff --git a/docs/intro/installation.rst b/docs/intro/installation.rst index 6bf8dcfec4..780724d8d9 100644 --- a/docs/intro/installation.rst +++ b/docs/intro/installation.rst @@ -2,14 +2,90 @@ Installation ============ -Local or managed server ------------------------ +Automatic install using included fabfile +---------------------------------------- +A Fabric_ file is included to help users not very familiar with Ubuntu_, +Python_ and Django_ install **Mayan EDMS**, or for system administrators +looking to automate the install whether in a local or remote system. + +To bootstrap **Mayan EDMS** via the fabfile without having to clone the +entire repository, run the following command, replacing the part that +reads: with your current MySQL root password +or the MySQL root password you plan to assign to it, during the MySQL +installation when executing the fabfile. + +* Debian or Ubuntu:: + + $ cd /tmp && sudo apt-get install -y fabric wget tar gzip && wget https://raw.github.com/rosarior/mayan/contrib/fabfile.tar.gz -O - | tar -xvzf - && echo "database_manager_admin_password=" > ~/.fabricrc && fab -H localhost install + +* Fedora:: + + $ cd /tmp && sudo yum install -y fabric wget tar gzip && wget https://raw.github.com/rosarior/mayan/contrib/fabfile.tar.gz -O - | tar -xvzf - && echo "database_manager_admin_password=" > ~/.fabricrc && fab -H localhost install + + +The ``fabfile`` also supports deploying to more than one server whether +the they same configuration or not, via a ``server_config.json`` file. +The fabfile also supports YAML server configuration +files but requires installing ``pyyaml`` via ``pip``, ``python-yaml`` +via ``apt`` (Debian_, Ubuntu_) or ``PyYAML`` via ``yum`` (Fedora_) + +A sample ``server_config.yaml`` would be as follows:: + + debian_server: + host: 192.168.1.1 + database_manager_admin_password: my_debian_mysql_pa$$word + drop_database: True + os: debian + ubuntu_server: + host: 192.168.1.2 + database_manager_admin_password: my_ubuntu_mysql_pa$$word + drop_database: True + os: ubuntu + database_username: mayan_release_12 + database_name: mayan_release_12 + all_servers: [debian_server, ubuntu_server] + +To install **Mayan EDMS** to these servers the ``fabfile`` should be called in the following manner:: + + $ fab servers:debian_server install + +or:: + + $ fab servers:ubuntu_server,debian_server install + +or:: + + $ fab servers:all_servers install + + +Configuration options for the ``fabfile``: + +* ``host`` Hostname or address of the host to which to install **Mayan EDMS**. Required setting. +* ``os`` Operating system of the target host. Options: ubuntu, debian, fedora. default: ubuntu +* ``install_path`` Installation path. Default: /usr/share +* ``virtualenv_name`` Name of the directory that will house the virtualenv under the ``install_path``. Default: mayan +* ``repository_name`` Name of the directory where the repository will be clone under the ``virtualenv_name`` directory. Default: mayan +* ``database_manager`` Database manager to use. Options: mysql. Default: mysql +* ``database_username`` Username that will be created and used to access the database. Default: mayan +* ``database_password`` Password of the database user account. Default: random autogenerated password +* ``database_host`` Address of the database manager host. Default: 127.0.0.1 +* ``drop_database`` Weather or not to drop the database when uninstalling **Mayan EDMS** via the fabfile. Default: False +* ``database_manager_admin_password`` Administrator password of the database manager, only used to create the **Mayan EDMS** database and user. Required setting. +* ``database_name`` Name of the **Mayan EDMS** database. Default: mayan +* ``webserver`` Web server that will be install and configure to server **Mayan EDMS**. Options: apache. Default: apache + + +Only the options: ``host``, ``os`` and ``database_manager_admin_password`` should be required for most installations. + + +Local or managed Ubuntu or Debian server +---------------------------------------- **Mayan EDMS** should be deployed_ like any other Django_ project and preferably using virtualenv_. If using a Debian_ or Ubuntu_ based Linux distribution getting the executable requirements is as easy as:: - $ apt-get install tesseract-ocr unpaper python-virtualenv ghostscript -y + $ sudo apt-get install python-dev gcc tesseract-ocr unpaper python-virtualenv ghostscript libjpeg-dev libpng-dev poppler-utils -y To initialize a ``virtualenv`` to deploy the project do:: @@ -34,19 +110,35 @@ To install the python dependencies ``easy_install`` can be used, however for eas Create the database that will hold the data. Install any corresponding python database drivers. Update the settings.py file with you database settings. If using the ``MySQL`` database manager, use the following commands:: - $ apt-get install python-dev libmysqlclient-dev gcc -y + $ sudo apt-get install libmysqlclient-dev -y $ pip install MySQL-python -If using PostgreSQL, enter the following:: +If using ``PostgreSQL``, enter the following:: - $ apt-get install python-dev libpq-dev gcc-y - $ pip install pip install psycopg2 + $ sudo apt-get install libpq-dev -y + $ pip install psycopg2 Populate the database with the project's schema doing:: $ ./manage.py syncdb --migrate -Collect the static files of the project into the ``static`` folder for serving via a webserver:: +To test your installation, create a file called settings_local.py with the following content:: + + DEBUG=True + DEVELOPMENT=True + +Execute Django’s development server using the ``runserver`` command to launch a local instance of Mayan EDMS:: + + $ ./manager.py runserver + +Point your browser to http://127:0.0.1:8000, if everything was installed +correctly you should see the login screen. After making sure everything +is running correctly, stop the runserver command and delete the settings_local.py. +Deploy **Mayan EDMS** using the webserver of your preference. If your are +using Apache_, a sample site file is included under the contrib directory. + +Before finally deploying to your favorite webserver don't forget to collect the +static files of the project into the ``static`` folder for serving via a webserver:: $ ./manage.py collectstatic @@ -59,6 +151,85 @@ Execute Django's runserver command to launch a local instance of **Mayan EDMS** After making sure everything is running correctly, stop the runserver command, delete the settings_local.py and deploy **Mayan EDMS** using the webserver of your preference. If your are using Apache_, a sample site file is included under the contrib directory. +Local or managed Fedora server +------------------------------ + +**Mayan EDMS** should be deployed_ like any other Django_ project and preferably using virtualenv_. + +If using a Fedora_ based Linux distribution getting the executable requirements is as easy as:: + + $ sudo yum install -y git gcc tesseract unpaper python-virtualenv ghostscript libjpeg-turbo-devel libpng-devel poppler-util python-devel + +To initialize a ``virtualenv`` to deploy the project do:: + + $ virtualenv --no-site-packages mayan + +Download_ and decompress the latest version of **Mayan EDMS**:: + + $ cd mayan + $ tar -xvzf mayan.tar.gz + +Or clone the latest development version straight from github:: + + $ cd mayan + $ git clone git://github.com/rosarior/mayan.git + +To install the python dependencies ``easy_install`` can be used, however for easier retrieval a production dependencies file is included, to use it execute:: + + $ cd mayan + $ source ../bin/activate + $ pip install -r requirements/production.txt + +Create the database that will hold the data. Install any corresponding python database drivers. Update the settings.py file with you database settings. +If using the ``MySQL`` database manager, use the following commands:: + + $ sudo yum install -y mysql-devel + $ pip install MySQL-python + +If using ``PostgreSQL``, enter the following:: + + $ sudo yum install -y postgresql-devel + $ pip install psycopg2 + +Populate the database with the project's schema doing:: + + $ ./manage.py syncdb --migrate + +To test your installation, create a file called settings_local.py with the following content:: + + DEBUG=True + DEVELOPMENT=True + +Execute Django’s development server using the ``runserver`` command to launch a local instance of Mayan EDMS:: + + $ ./manager.py runserver + +Point your browser to http://127:0.0.1:8000, if everything was installed +correctly you should see the login screen. After making sure everything +is running correctly, stop the runserver command and delete the settings_local.py. +Deploy **Mayan EDMS** using the webserver of your preference. If your are +using Apache_, a sample site file is included under the contrib directory. + +Before finally deploying to your favorite webserver don't forget to collect the +static files of the project into the ``static`` folder for serving via a webserver:: + + $ ./manage.py collectstatic + + +Cloud install +------------- +SaaS provied Appsembler_ has started providing a "1-click install" cloud +offering of **Mayan EDMS**. Go to their website and click on apps to start +your trial period of **Mayan EDMS** on the cloud. + + +DjangoZoom +---------- +For instructions on how to deploy **Mayan EDMS** on DjangoZoom, watch the screencast: + +"Deploying Mayan EDMS on DjangoZoom.net" available on Youtube_ + + Webfaction ---------- @@ -168,11 +339,6 @@ To install **Mayan EDMS** on Webfaction_, follow these steps: apache2/bin/restart -DjangoZoom ----------- -For instructions on how to deploy **Mayan EDMS** on DjangoZoom, watch the screencast: - -"Deploying Mayan EDMS on DjangoZoom.net" available on Youtube_ .. _`vendor lock-in`: https://secure.wikimedia.org/wikipedia/en/wiki/Vendor_lock-in @@ -193,3 +359,6 @@ For instructions on how to deploy **Mayan EDMS** on DjangoZoom, watch the screen .. _deployed: https://docs.djangoproject.com/en/1.3/howto/deployment/ .. _virtualenv: http://www.virtualenv.org/en/latest/index.html .. _`Reducing mod_wsgi Memory Consumption`: http://docs.webfaction.com/software/mod-wsgi.html#mod-wsgi-reducing-memory-consumption +.. _Fedora: http://fedoraproject.org/ +.. _Fabric: http://docs.fabfile.org/ +.. _Appsembler: http://appsembler.com/ diff --git a/docs/releases/0.10.rst b/docs/releases/0.10.rst index cbe2f65ff5..9fa5065a30 100644 --- a/docs/releases/0.10.rst +++ b/docs/releases/0.10.rst @@ -39,7 +39,7 @@ Version 0.10 * Document image serving response now specifies a MIME type for increased browser compatibility. * Small change in the scheduler that increases stability. -* Russian translation updates (Сергей Глита [Sergey Glita]) +* Russian translation updates Sergey Glita * Improved and generalized the OCR queue locking mechanism, this should eliminate any posibility of race conditions between Mayan EDMS OCR nodes. * Added support for signals to the OCR queue, this results in instant OCR diff --git a/docs/releases/0.12.1.rst b/docs/releases/0.12.1.rst new file mode 100644 index 0000000000..75379ea8d7 --- /dev/null +++ b/docs/releases/0.12.1.rst @@ -0,0 +1,116 @@ +================================ +Mayan EDMS v0.12.1 release notes +================================ + +*May 2012* + +This is the first maintenance release of the 0.12 series. + +Overview +======== + +While bug fixes and minor feature were the focus for this release, some +bigger changes were included because of their importance. The parsing of +documents saw a complete rewrite being now class based and allows for more +than one parser per mimetype with sequencial fallback. This provides the +best text extraction on deployments where users have control over the +installation and basic extraction when deploying on the cloud or other +environments where users don't have the ability to install OS level +binaries. + + +What's new in Mayan EDMS v0.12.1 +================================ + +Fabric file (fabfile) +~~~~~~~~~~~~~~~~~~~~~ +A Fabric file is included to help users not very familiar with Ubuntu, +Python and Django install **Mayan EDMS**, or for system administrators +looking to automate the install whether in local or remote systems. +At the moment the fabfile will install **Mayan EDMS** in the same configurations +listed in this documentation, that is: (Ubuntu/Debian/Fedora) + virtualenv + Apache + MySQL. +Feel free to submit your configuration settings and files for different databases, +webserver or Linux distribution. More configurations will be added to +the fabfile as more are tested. + +Documentation update +~~~~~~~~~~~~~~~~~~~~ +The installation instructions were updated to include the installation of +the libpng-dev and libjpeg-dev libraries as well as the installation of +the poppler-utils package. An additional step to help users test their +new installation of **Mayan EDMS** was also added. + +Translations +~~~~~~~~~~~~ +The Italian translation has been synchronized with the source files at +Transifex and finished to %100 completion. + +Usability improvements +~~~~~~~~~~~~~~~~~~~~~~ +The index instance view now feature the same multi document action +buttons (Submit to OCR, delete, download, etc) as the mail and recent +document views. + +Better office document conversion +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A new method of converting office documents has been implemented, this +new method doesn't require the use of the command line utility ``UNOCONV``. +If this new method proves to work better than previous solutions the use +of ``UNOCONV`` may be deprecated in the future. The conversion method +adds just one new configuration option: :setting:`CONVERTER_LIBREOFFICE_PATH` +which defaults to '/usr/bin/libreoffice'. + +Better PDF text parsing +~~~~~~~~~~~~~~~~~~~~~~~ +Brian E. submitted a patch to use the Poppler package pdftotext utility to +extract text from PDF files. This is now the default method Mayan EDMS +will execute to try to extract text from a PDF and failing that will +fallback to the previous method. This change add a new configuration +option: :setting:`OCR_PDFTOTEXT_PATH` to specify the location of the ``pdftotext`` +executable, it defaults to '/usr/bin/pdftotext'. Be sure to install the +``poppler-utils`` os package to take advantage of this new parser. + +Changed defaults +~~~~~~~~~~~~~~~~ +The OCR queue is now active by default when first created during the +``syncdb`` phase and the :setting:`OCR_AUTOMATIC_OCR` option now defaults +to ``True``. These two changes are made to reduce the steps required for +new users to start enjoying the benefits of automatic text extraction from +uploaded documents without having to read the documentation and have a more +functional default install. + +Upgrading from a previous version +================================= + +Start off by adding the new requirements:: + + $ pip install -r requirements/production.txt + +Migrate existing database schema with:: + + $ ./manage.py migrate documents + +Install the ``poppler-utils`` package: + +* Ubuntu, Debian:: + + $ apt-get install -y poppler-utils + +* Fedora:: + + $ yum install -y poppler-utils + +The upgrade procedure is now complete. + + +Backward incompatible changes +============================= +* None + +Bugs fixed +========== +* Issue #25 "Office document conversion error" + +Stuff removed +============= +* None diff --git a/docs/releases/0.9.1.rst b/docs/releases/0.9.1.rst index 2dc29b1a65..62c45bdf11 100644 --- a/docs/releases/0.9.1.rst +++ b/docs/releases/0.9.1.rst @@ -1,7 +1,7 @@ Version 0.9.1 ------------- * Added handling percent encoded unicode query strings in search URL, - thanks to (Сергей Глита [Sergei Glita]) for reporting. + thanks to Sergei Glita for reporting. * Added a FAQ explaing how to fix MySQL collation related error when - doing searches also thanks to (Сергей Глита [Sergei Glita]) for + doing searches also thanks to Sergei Glita for reporting this one. diff --git a/docs/releases/0.9.rst b/docs/releases/0.9.rst index c3709ffe2f..be8714217b 100644 --- a/docs/releases/0.9.rst +++ b/docs/releases/0.9.rst @@ -16,11 +16,11 @@ Version 0.9 * Changed to Semantic Versioning (http://semver.org/), with recommendations 7, 8 and 9 causing the most effect in the versioning number. -* Added Russian locale post OCR cleanup backend (Сергей Глита [Sergei Glita]) +* Added Russian locale post OCR cleanup backend Sergei Glita * Reduced severity of the messages displayed when no OCR cleanup backend is found for a language * Complete Portuguese translation (Emerson Soares and Renata Oliveira) -* Complete Russian translation (Сергей Глита [Sergei Glita]) +* Complete Russian translation Sergei Glita) * Added animate.css to use CSS to animate flash messages with better fallback on non JS browsers * The admin and sentry links are no longer hard-coded (Meurig Freeman) diff --git a/docs/releases/index.rst b/docs/releases/index.rst index a51dcf09ac..5987c7f0d7 100644 --- a/docs/releases/index.rst +++ b/docs/releases/index.rst @@ -9,7 +9,7 @@ changes made in that version. For those upgrading to a new version of **Mayan EDMS**, you will need to check all the backwards-incompatible changes and deprecated features for each 'final' release from the one after your current **Mayan EDMS** version, -up to and including the new version. +up to and including the latest version. Latest version (0.13) --------------------- @@ -17,6 +17,7 @@ Latest version (0.13) :maxdepth: 1 0.13 + 0.12.1 0.12 Historic changelogs diff --git a/docs/topics/settings.rst b/docs/topics/settings.rst index b3af96d500..b79900d4ff 100644 --- a/docs/topics/settings.rst +++ b/docs/topics/settings.rst @@ -200,7 +200,7 @@ fine tune it's functionality as explained in the `GraphicsMagick documentation`_ Default: ``/usr/bin/unoconv`` -Path to the unoconv program used to call LibreOffice for office document convertion. +Path to the unoconv program used to call LibreOffice for office document conversion. .. setting:: CONVERTER_UNOCONV_USE_PIPE @@ -211,8 +211,19 @@ Path to the unoconv program used to call LibreOffice for office document convert Default: ``True`` Use alternate method of connection to LibreOffice using a pipe, it is slower but less prone to segmentation faults. + + +.. setting:: CONVERTER_LIBREOFFICE_PATH + + +**CONVERTER_LIBREOFFICE_PATH** + +Default: ``/usr/bin/libreoffice`` + +Path to the libreoffice binary used to call LibreOffice for office document conversion. - + + Linking ======= @@ -341,7 +352,7 @@ Maximum amount of concurrent document OCRs a node can perform. **OCR_AUTOMATIC_OCR** -Default: ``False`` +Default: ``True`` Automatically queue newly created documents or newly uploaded versions of existing documents for OCR. @@ -362,7 +373,17 @@ Default: ``/usr/bin/unpaper`` File path to the ``unpaper`` executable, used to clean up images before doing OCR. + +.. setting:: OCR_PDFTOTEXT_PATH + +**OCR_PDFTOTEXT_PATH** + +Default: ``/usr/bin/pdftotext`` + +File path to ``poppler's`` ``pdftotext`` program used to extract text +from PDF files. + Metadata ======== diff --git a/fabfile/__init__.py b/fabfile/__init__.py new file mode 100644 index 0000000000..40f2c894ff --- /dev/null +++ b/fabfile/__init__.py @@ -0,0 +1,61 @@ +import sys + +from fabric.api import task, env +from fabric.colors import white + +import databases as database +import platforms as platform +import webservers as webserver +import django +from conf import print_supported_configs +from server_config import servers + +print(white('\n\n ######## ', bold=True)) +print(white(' ######## ', bold=True)) +print(white(' ### ### ', bold=True)) +print(white(' ##### ##### ', bold=True)) +print(white(' ############## ', bold=True)) +print(white(' ####### ####### ', bold=True)) +print(white(' ################## ', bold=True)) +print(white(' ######### ######### ', bold=True)) +print(white(' ###################### ', bold=True)) +print(white(' ########### ########### ', bold=True)) +print(white(' ########################## ', bold=True)) +print(white('############# #############', bold=True)) + +print(white('\nMayan EDMS Fabric installation file\n\n', bold=True)) + +print_supported_configs() + + +@task +def install(): + """ + Perform a complete install of Mayan EDMS on a host + """ + platform.install_dependencies() + platform.install_mayan() + platform.install_database_manager() + database.create_database() + django.database_config() + django.syncdb() + django.collectstatic() + platform.fix_permissions() + platform.install_webserver() + webserver.install_site() + webserver.restart() + platform.post_install() + + +@task +def uninstall(): + """ + Perform a complete removal of Mayan EDMS from a host + """ + platform.delete_mayan() + webserver.remove_site() + webserver.restart() + + if env.drop_database: + database.drop_database() + database.drop_username() diff --git a/fabfile/conf.py b/fabfile/conf.py new file mode 100644 index 0000000000..16e380234d --- /dev/null +++ b/fabfile/conf.py @@ -0,0 +1,60 @@ +import os +import string +import random + +from fabric.api import env +from fabric.colors import green + +from literals import (DEFAULT_INSTALL_PATH, DEFAULT_VIRTUALENV_NAME, + DEFAULT_REPOSITORY_NAME, DEFAULT_OS, OS_CHOICES, + DEFAULT_DATABASE_MANAGER, DB_CHOICES, DEFAULT_DATABASE_NAME, + DEFAULT_WEBSERVER, WEB_CHOICES, DEFAULT_DATABASE_USERNAME, + DJANGO_DB_DRIVERS, DEFAULT_DATABASE_HOST, DEFAULT_PASSWORD_LENGTH) +from server_config import reduce_env + + +def password_generator(): + # http://snipplr.com/view/63223/python-password-generator/ + chars = string.ascii_letters + string.digits + return ''.join(random.choice(chars) for x in range(DEFAULT_PASSWORD_LENGTH)) + + +@reduce_env +def setup_environment(): + env['os'] = getattr(env, 'os', DEFAULT_OS) + env['os_name'] = OS_CHOICES[env.os] + + env['install_path'] = getattr(env, 'install_path', DEFAULT_INSTALL_PATH[env.os]) + env['virtualenv_name'] = getattr(env, 'virtualenv_name', DEFAULT_VIRTUALENV_NAME[env.os]) + env['repository_name'] = getattr(env, 'repository_name', DEFAULT_REPOSITORY_NAME[env.os]) + env['virtualenv_path'] = os.path.join(env.install_path, env.virtualenv_name) + env['repository_path'] = os.path.join(env.virtualenv_path, env.repository_name) + + env['database_manager'] = getattr(env, 'database_manager', DEFAULT_DATABASE_MANAGER) + env['database_manager_name'] = DB_CHOICES[env.database_manager] + env['database_username'] = getattr(env, 'database_username', DEFAULT_DATABASE_USERNAME) + env['database_password'] = getattr(env, 'database_password', password_generator()) + env['database_host'] = getattr(env, 'database_host', DEFAULT_DATABASE_HOST) + env['drop_database'] = getattr(env, 'drop_database', False) + + if not getattr(env, 'database_manager_admin_password', None): + print('Must set the database_manager_admin_password entry in the fabric settings file (~/.fabricrc by default)') + exit(1) + + env['database_name'] = getattr(env, 'database_name', DEFAULT_DATABASE_NAME) + + env['webserver'] = getattr(env, 'webserver', DEFAULT_WEBSERVER) + env['webserver_name'] = WEB_CHOICES[env.webserver] + + env['django_database_driver'] = DJANGO_DB_DRIVERS[env.database_manager] + + +def print_supported_configs(): + print('Supported operating systems (os=): %s, default=\'%s\'' % (dict(OS_CHOICES).keys(), green(DEFAULT_OS))) + print('Supported database managers (database_manager=): %s, default=\'%s\'' % (dict(DB_CHOICES).keys(), green(DEFAULT_DATABASE_MANAGER))) + print('Supported webservers (webserver=): %s, default=\'%s\'' % (dict(WEB_CHOICES).keys(), green(DEFAULT_WEBSERVER))) + print('\n') + + + + diff --git a/fabfile/databases/__init__.py b/fabfile/databases/__init__.py new file mode 100644 index 0000000000..8afccd8032 --- /dev/null +++ b/fabfile/databases/__init__.py @@ -0,0 +1,42 @@ +from fabric.api import env, task +from fabric.colors import green + +from ..conf import setup_environment +from ..literals import DB_MYSQL +import mysql + + +@task +def create_database(): + """ + Create the Mayan EDMS database + """ + setup_environment() + print(green('Creating Mayan EDMS database', bold=True)) + + if env.database_manager == DB_MYSQL: + mysql.create_database() + + +@task +def drop_database(): + """ + Drop Mayan EDMS's database + """ + setup_environment() + print(green('Droping Mayan EDMS database', bold=True)) + + if env.database_manager == DB_MYSQL: + mysql.drop_database() + + +@task +def drop_username(): + """ + Drop Mayan EDMS's username + """ + setup_environment() + print(green('Droping Mayan EDMS username', bold=True)) + + if env.database_manager == DB_MYSQL: + mysql.drop_username() diff --git a/fabfile/databases/mysql.py b/fabfile/databases/mysql.py new file mode 100644 index 0000000000..7a41f9f5f0 --- /dev/null +++ b/fabfile/databases/mysql.py @@ -0,0 +1,30 @@ +from fabric.api import run, env, task, settings +from fabric.colors import green + + +def create_database(): + """ + Create the MySQL Mayan EDMS database + """ + run('echo "CREATE DATABASE %(database_name)s;" | mysql -u root --password=%(database_manager_admin_password)s' % env) + run('echo "CREATE USER \'%(database_username)s\'@\'%(database_host)s\' IDENTIFIED BY \'%(database_password)s\';" | mysql -u root --password=%(database_manager_admin_password)s' % env) + run('echo "GRANT ALL PRIVILEGES ON %(database_name)s.* TO \'%(database_username)s\'@\'%(database_host)s\' WITH GRANT OPTION;" | mysql -u root --password=%(database_manager_admin_password)s' % env) + + print(green('Password used for Mayan EDMS database account: %s' % env.database_password, bold=True)) + + +def drop_database(): + """ + Drop MySQL's Mayan EDMS's database + """ + with settings(warn_only=True): + run('echo "DROP DATABASE %(database_name)s;" | mysql -u root --password=%(database_manager_admin_password)s' % env) + + +def drop_username(): + """ + Drop MySQL's Mayan EDMS's username + """ + with settings(warn_only=True): + run('echo "DROP USER \'%(database_username)s\'@\'%(database_host)s\';" | mysql -u root --password=%(database_manager_admin_password)s' % env) + diff --git a/fabfile/django/__init__.py b/fabfile/django/__init__.py new file mode 100644 index 0000000000..9ce0309435 --- /dev/null +++ b/fabfile/django/__init__.py @@ -0,0 +1,34 @@ +import os + +from fabric.api import env, task, cd, sudo +from fabric.contrib.files import upload_template + +from ..conf import setup_environment + + +@task +def syncdb(): + """ + Perform Django's syncdb command + """ + setup_environment() + with cd(env.virtualenv_path): + sudo('source bin/activate; %(repository_name)s/manage.py syncdb --noinput; %(repository_name)s/manage.py migrate' % (env)) + +@task +def database_config(): + """ + Create a settings_local.py file tailored to the database manager selected + """ + setup_environment() + upload_template(filename=os.path.join('fabfile', 'templates', 'settings_local.py'), destination=env.repository_path, context=env, use_sudo=True) + + +@task +def collectstatic(): + """ + Perform Django's collectstatic command + """ + setup_environment() + with cd(env.virtualenv_path): + sudo('source bin/activate; %(repository_name)s/manage.py collectstatic --noinput' % (env)) diff --git a/fabfile/literals.py b/fabfile/literals.py new file mode 100644 index 0000000000..b1fb4f9c91 --- /dev/null +++ b/fabfile/literals.py @@ -0,0 +1,70 @@ +OS_UBUNTU = 'ubuntu' +OS_REDHAT = 'redhat' +OS_CENTOS = 'centos' +OS_FEDORA = 'fedora' +OS_WINDOWS = 'windows' +OS_FREEBSD = 'freebds' +OS_DEBIAN = 'debian' + +OS_CHOICES = { + OS_UBUNTU: 'Ubuntu', + OS_FEDORA: 'Fedora', + OS_DEBIAN: 'Debian', + #OS_REDHAT: 'RedHat', + #OS_CENTOS: 'CentOS', + #OS_WINDOWS: 'MS Windows', + #OS_FREEBSD: 'FreeBSD', +} + +DEFAULT_INSTALL_PATH = { + OS_UBUNTU: '/usr/share', + OS_FEDORA: '/usr/share', + OS_DEBIAN: '/usr/share', +} + +DEFAULT_VIRTUALENV_NAME = { + OS_UBUNTU: 'mayan', + OS_FEDORA: 'mayan', + OS_DEBIAN: 'mayan', +} + +DEFAULT_REPOSITORY_NAME = { + OS_UBUNTU: 'mayan', + OS_FEDORA: 'mayan', + OS_DEBIAN: 'mayan', +} + +DB_MYSQL = 'mysql' +DB_PGSQL = 'pgsql' +DB_SQLITE = 'sqlite' +DB_ORACLE = 'oracle' + +DB_CHOICES = { + DB_MYSQL: 'MySQL', + #DB_PGSQL: 'PostgreSQL', + #DB_SQLITE: 'SQLite', + #DB_ORACLE: 'ORACLE' +} + +DJANGO_DB_DRIVERS = { + DB_MYSQL: 'mysql', + DB_PGSQL: 'postgresql_psycopg2', + DB_SQLITE: 'sqlite3', + DB_ORACLE: 'oracle', +} + +WEB_APACHE = 'apache' +WEB_NGINX = 'nginx' + +WEB_CHOICES = { + WEB_APACHE: 'Apache', + #WEB_NGINX: 'Nginx', +} + +DEFAULT_OS = OS_UBUNTU +DEFAULT_DATABASE_MANAGER = DB_MYSQL +DEFAULT_DATABASE_NAME = 'mayan' +DEFAULT_WEBSERVER = WEB_APACHE +DEFAULT_DATABASE_USERNAME = 'mayan' +DEFAULT_DATABASE_HOST = '127.0.0.1' +DEFAULT_PASSWORD_LENGTH = 10 diff --git a/fabfile/platforms/__init__.py b/fabfile/platforms/__init__.py new file mode 100644 index 0000000000..5a8ec61da4 --- /dev/null +++ b/fabfile/platforms/__init__.py @@ -0,0 +1,100 @@ +from fabric.api import run, sudo, cd, env, task +from fabric.colors import green + +from ..literals import OS_UBUNTU, OS_FEDORA, OS_DEBIAN +from ..conf import setup_environment +import linux, ubuntu, fedora, debian + + +@task +def install_dependencies(): + """ + Install OS dependencies + """ + setup_environment() + print(green('Installing dependencies for %s' % env.os_name, bold=True)) + + if env.os in [OS_UBUNTU, OS_DEBIAN]: + debian.install_dependencies() + elif env.os == OS_FEDORA: + fedora.install_dependencies() + + +@task +def install_mayan(): + """ + Install Mayan EDMS + """ + setup_environment() + print(green('Installing Mayan EDMS from git repository', bold=True)) + + if env.os in [OS_UBUNTU, OS_FEDORA, OS_DEBIAN]: + linux.install_mayan() + + +@task +def install_database_manager(): + """ + Install the selected database manager + """ + setup_environment() + print(green('Installing database manager: %s' % env.database_manager_name, bold=True)) + + if env.os in [OS_UBUNTU, OS_DEBIAN]: + debian.install_database_manager() + elif env.os == OS_FEDORA: + fedora.install_database_manager() + + +@task +def fix_permissions(): + """ + Fix installation files' permissions + """ + setup_environment() + print(green('Fixing installation files\' permissions', bold=True)) + + if env.os in [OS_UBUNTU, OS_DEBIAN]: + debian.fix_permissions() + elif env.os == OS_FEDORA: + fedora.fix_permissions() + + +@task +def install_webserver(): + """ + Installing the OS packages for the webserver + """ + setup_environment() + print(green('Installing webserver: %s' % env.webserver_name, bold=True)) + + if env.os in [OS_UBUNTU, OS_DEBIAN]: + debian.install_webserver() + elif env.os == OS_FEDORA: + fedora.install_webserver() + + +@task +def delete_mayan(): + """ + Delete Mayan EDMS from the OS + """ + setup_environment() + print(green('Deleting Mayan EDMS files', bold=True)) + + if env.os in [OS_UBUNTU, OS_FEDORA, OS_DEBIAN]: + linux.delete_mayan() + + +@task +def post_install(): + """ + Perform post install operations + """ + setup_environment() + if env.os == OS_UBUNTU: + ubuntu.post_install() + elif env.os == OS_FEDORA: + fedora.post_install() + elif env.os == OS_DEBIAN: + debian.post_install() diff --git a/fabfile/platforms/debian.py b/fabfile/platforms/debian.py new file mode 100644 index 0000000000..64df1bc608 --- /dev/null +++ b/fabfile/platforms/debian.py @@ -0,0 +1,50 @@ +from fabric.api import run, sudo, cd, env, task, settings + +from ..literals import DB_MYSQL, WEB_APACHE + + +def install_dependencies(): + """ + Install Debian dependencies + """ + sudo('apt-get install -y git-core gcc tesseract-ocr unpaper python-virtualenv ghostscript libjpeg-dev libpng-dev poppler-utils python-dev') + + +def install_database_manager(): + """ + Install the database manager on an Ubuntu system + """ + + if env.database_manager == DB_MYSQL: + sudo('apt-get install -y mysql-server libmysqlclient-dev') + + with cd(env.virtualenv_path): + sudo('source bin/activate; pip install MySQL-python') + + +def install_webserver(): + """ + Installing the Debian packages for the webserver + """ + + if env.webserver == WEB_APACHE: + sudo('apt-get install -y apache2 libapache2-mod-wsgi') + + with settings(warn_only=True): + # Get rid of Apache's default site + sudo('a2dissite default') + + +def fix_permissions(): + """ + Fix installation files' permissions on a Debian system + """ + sudo('chmod 770 %s -R' % env.virtualenv_path) + sudo('chgrp www-data %s -R' % env.virtualenv_path) + + +def post_install(): + """ + Post install operations on a Debian system + """ + pass diff --git a/fabfile/platforms/fedora.py b/fabfile/platforms/fedora.py new file mode 100644 index 0000000000..4bc8bdd3fb --- /dev/null +++ b/fabfile/platforms/fedora.py @@ -0,0 +1,62 @@ +import os + +from fabric.api import run, sudo, cd, env, task, settings +from fabric.operations import put, reboot + +from ..literals import DB_MYSQL, WEB_APACHE + + +def install_dependencies(): + """ + Install Fedora dependencies + """ + sudo('yum install -y git gcc tesseract unpaper python-virtualenv ghostscript libjpeg-turbo-devel libpng-devel poppler-utils') + + +def install_database_manager(): + """ + Install the database manager on a Fedora system + """ + + if env.database_manager == DB_MYSQL: + sudo('yum install -y mysql-server mysql-devel') + sudo('systemctl enable mysqld.service') + sudo('systemctl start mysqld.service') + sudo('mysql_secure_installation') + + with cd(env.virtualenv_path): + sudo('source bin/activate; pip install MySQL-python') + + +def install_webserver(): + """ + Installing the Fedora packages for the webserver + """ + + if env.webserver == WEB_APACHE: + sudo('yum install -y httpd mod_wsgi') + sudo('systemctl enable httpd.service') + sudo('systemctl start httpd.service') + + with settings(warn_only=True): + # Get rid of Apache's default site + sudo('rm /etc/httpd/conf.d/welcome.conf') + + # Disable SELinux as it blocks mod_wsgi's file access + # TODO: implement a proper solution is implemented + put(local_path=os.path.join('fabfile', 'templates', 'selinux.config'), remote_path='/etc/selinux/config', use_sudo=True) + + +def fix_permissions(): + """ + Fix installation files' permissions on a Fedora system + """ + sudo('chmod 770 %s -R' % env.virtualenv_path) + sudo('chgrp apache %s -R' % env.virtualenv_path) + + +def post_install(): + """ + Post install operations on a Fedora system + """ + reboot() diff --git a/fabfile/platforms/linux.py b/fabfile/platforms/linux.py new file mode 100644 index 0000000000..c95b5114bb --- /dev/null +++ b/fabfile/platforms/linux.py @@ -0,0 +1,20 @@ +from fabric.api import run, sudo, cd, env, task, settings + + +def delete_mayan(): + """ + Delete Mayan EDMS files from an Ubuntu system + """ + sudo('rm %(virtualenv_path)s -Rf' % env) + + +def install_mayan(): + """ + Install Mayan EDMS on an Ubuntu system + """ + with cd(env.install_path): + sudo('virtualenv --no-site-packages %(virtualenv_name)s' % env) + + with cd(env.virtualenv_path): + sudo('git clone git://github.com/rosarior/mayan.git %(repository_name)s' % env) + sudo('source bin/activate; pip install -r %(repository_name)s/requirements/production.txt' % env) diff --git a/fabfile/platforms/ubuntu.py b/fabfile/platforms/ubuntu.py new file mode 100644 index 0000000000..501785f545 --- /dev/null +++ b/fabfile/platforms/ubuntu.py @@ -0,0 +1,5 @@ +def post_install(): + """ + Post install operations on an Ubuntu system + """ + pass diff --git a/fabfile/server_config.py b/fabfile/server_config.py new file mode 100644 index 0000000000..29228e4a74 --- /dev/null +++ b/fabfile/server_config.py @@ -0,0 +1,141 @@ +"""Fabric server config management fabfile. +If you need additional configuration, setup ~/.fabricrc file: + + user = your_remote_server_username + +To get specific command help type: + fab -d command_name + +""" +# From http://fueledbylemons.com/blog/2011/04/09/server-configs-and-fabric/ + + +import os + +from fabric.api import env, task +from fabric.utils import puts +from fabric import colors +import fabric.network +import fabric.state + + +YAML_AVAILABLE = True +try: + import yaml +except ImportError: + YAML_AVAILABLE = False + + +JSON_AVAILABLE = True +try: + import simplejson as json +except ImportError: + try: + import json + except ImportError: + JSON_AVAILABLE = False + +################################ +# ENVIRONMENTS # +################################ + +def _load_config(**kwargs): + """Find and parse server config file. + + If `config` keyword argument wasn't set look for default + 'server_config.yaml' or 'server_config.json' file. + + """ + config, ext = os.path.splitext(kwargs.get('config', + 'server_config.yaml' if os.path.exists('server_config.yaml') else 'server_config.json')) + + if not os.path.exists(config + ext): + print colors.red('Error. "%s" file not found.' % (config + ext)) + return {} + if YAML_AVAILABLE and ext == '.yaml': + loader = yaml + elif JSON_AVAILABLE and ext =='.json': + loader = json + else: + print colors.red('Parser package not available') + return {} + # Open file and deserialize settings. + with open(config + ext) as config_file: + return loader.load(config_file) + +@task +def servers(*args, **kwargs): + """Set destination servers or server groups by comma delimited list of names""" + # Load config + servers = _load_config(**kwargs) + # If no arguments were recieved, print a message with a list of available configs. + if not args: + print 'No server name given. Available configs:' + for key in servers: + print colors.green('\t%s' % key) + + # Create `group` - a dictionary, containing copies of configs for selected servers. Server hosts + # are used as dictionary keys, which allows us to connect current command destination host with + # the correct config. This is important, because somewhere along the way fabric messes up the + # hosts order, so simple list index incrementation won't suffice. + env.group = {} + # For each given server name + for name in args: + # Recursive function call to retrieve all server records. If `name` is a group(e.g. `all`) + # - get it's members, iterate through them and create `group` + # record. Else, get fields from `name` server record. + # If requested server is not in the settings dictionary output error message and list all + # available servers. + _build_group(name, servers) + + + # Copy server hosts from `env.group` keys - this gives us a complete list of unique hosts to + # operate on. No host is added twice, so we can safely add overlaping groups. Each added host is + # guaranteed to have a config record in `env.group`. + env.hosts = env.group.keys() + +def _build_group(name, servers): + """Recursively walk through servers dictionary and search for all server records.""" + # We're going to reference server a lot, so we'd better store it. + server = servers.get(name, None) + # If `name` exists in servers dictionary we + if server: + # check whether it's a group by looking for `members` + if isinstance(server, list): + if fabric.state.output['debug']: + puts("%s is a group, getting members" % name) + for item in server: + # and call this function for each of them. + _build_group(item, servers) + # When, finally, we dig through to the standalone server records, we retrieve + # configs and store them in `env.group` + else: + if fabric.state.output['debug']: + puts("%s is a server, filling up env.group" % name) + env.group[server['host']] = server + else: + print colors.red('Error. "%s" config not found. Run `fab servers` to list all available configs' % name) + +def reduce_env(task): + """ + Copies server config settings from `env.group` dictionary to env variable. + + This way, tasks have easier access to server-specific variables: + `env.owner` instead of `env.group[env.host]['owner']` + + """ + def task_with_setup(*args, **kwargs): + # If `s:server` was run before the current command - then we should copy values to + # `env`. Otherwise, hosts were passed through command line with `fab -H host1,host2 + # command` and we skip. + if env.get("group", None): + for key,val in env.group[env.host].items(): + setattr(env, key, val) + if fabric.state.output['debug']: + puts("[env] %s : %s" % (key, val)) + + task(*args, **kwargs) + # Don't keep host connections open, disconnect from each host after each task. + # Function will be available in fabric 1.0 release. + # fabric.network.disconnect_all() + return task_with_setup diff --git a/fabfile/templates/apache_site b/fabfile/templates/apache_site new file mode 100644 index 0000000000..6df729225e --- /dev/null +++ b/fabfile/templates/apache_site @@ -0,0 +1,20 @@ + + # Uncomment if libapache2-mod-xsendfile is installed + # XSendFile On + # XSendFileAllowAbove On + + WSGIScriptAlias / %(repository_path)s/wsgi/dispatch.wsgi + + + Order deny,allow + Allow from all + + #ErrorLog /var/log/apache2/mayan_error.log + LogLevel warn + #CustomLog /var/log/apache2/mayan_access.log combined + + Alias /mayan-static "%(repository_path)s/static/" + + SetHandler None + + diff --git a/fabfile/templates/selinux.config b/fabfile/templates/selinux.config new file mode 100644 index 0000000000..2f8cc2e2c4 --- /dev/null +++ b/fabfile/templates/selinux.config @@ -0,0 +1,10 @@ +# This file controls the state of SELinux on the system. +# SELINUX= can take one of these three values: +# enforcing - SELinux security policy is enforced. +# permissive - SELinux prints warnings instead of enforcing. +# disabled - No SELinux policy is loaded. +SELINUX=disabled +# SELINUXTYPE= can take one of these two values: +# targeted - Only targeted network daemons are protected. +# strict - Full SELinux protection. +SELINUXTYPE=targeted diff --git a/fabfile/webservers/__init__.py b/fabfile/webservers/__init__.py new file mode 100644 index 0000000000..d6084a6fbe --- /dev/null +++ b/fabfile/webservers/__init__.py @@ -0,0 +1,55 @@ +from fabric.api import run, sudo, cd, env, task +from fabric.colors import green + +from ..conf import setup_environment +from ..literals import WEB_APACHE + +import apache + + +@task +def install_site(): + """ + Install Mayan EDMS site in the webserver configuration files + """ + setup_environment() + print(green('Adding Mayan EDMS\'s site files to: %s' % env.webserver_name, bold=True)) + + if env.webserver == WEB_APACHE: + apache.install_site() + + +@task +def remove_site(): + """ + Install Mayan EDMS's site file from the webserver's configuration + """ + setup_environment() + print(green('Removing Mayan EDMS\'s site file from %s configuration' % env.webserver_name, bold=True)) + + if env.webserver == WEB_APACHE: + apache.remove_site() + + +@task +def restart(): + """ + Restart the webserver + """ + setup_environment() + print(green('Restarting the web server: %s' % env.webserver_name, bold=True)) + + if env.webserver == WEB_APACHE: + apache.restart() + + +@task +def reload(): + """ + Reload webserver configuration files + """ + setup_environment() + print(green('Reloading the web server configuration files', bold=True)) + + if env.webserver == WEB_APACHE: + apache.reload() diff --git a/fabfile/webservers/apache.py b/fabfile/webservers/apache.py new file mode 100644 index 0000000000..7b33b5fa83 --- /dev/null +++ b/fabfile/webservers/apache.py @@ -0,0 +1,50 @@ +import os + +from fabric.api import run, sudo, cd, env, task, settings +from fabric.contrib.files import upload_template + +from ..literals import OS_UBUNTU, OS_FEDORA, OS_DEBIAN + + +def install_site(): + """ + Install Mayan EDMS's site file in Apache configuration + """ + # TODO: configurable site name + if env.os in [OS_UBUNTU, OS_DEBIAN]: + upload_template(filename=os.path.join('fabfile', 'templates', 'apache_site'), destination='/etc/apache2/sites-available/mayan', context=env, use_sudo=True) + sudo('a2ensite mayan') + elif env.os == OS_FEDORA: + upload_template(filename=os.path.join('fabfile', 'templates', 'apache_site'), destination='/etc/httpd/conf.d/mayan.conf', context=env, use_sudo=True) + + +def remove_site(): + """ + Install Mayan EDMS's site file from Apache's configuration + """ + if env.os in [OS_UBUNTU, OS_DEBIAN]: + with settings(warn_only=True): + sudo('a2dissite mayan') + elif env.os == OS_FEDORA: + with settings(warn_only=True): + sudo('rm /etc/httpd/conf.d/mayan.conf') + + +def restart(): + """ + Restart Apache + """ + if env.os in [OS_UBUNTU, OS_DEBIAN]: + sudo('/etc/init.d/apache2 restart') + elif env.os == OS_FEDORA: + sudo('systemctl restart httpd.service') + + +def reload(): + """ + Reload Apache configuration files + """ + if env.os in [OS_UBUNTU, OS_DEBIAN]: + sudo('/etc/init.d/apache2 reload') + elif env.os == OS_FEDORA: + sudo('systemctl reload httpd.service') diff --git a/misc/make_fabfile_tar.sh b/misc/make_fabfile_tar.sh new file mode 100755 index 0000000000..ee8714609b --- /dev/null +++ b/misc/make_fabfile_tar.sh @@ -0,0 +1,3 @@ +#!/bin/sh +find 'fabfile' -depth -name '*.pyc' -exec rm {} \; +tar -czvf contrib/fabfile.tar.gz fabfile diff --git a/wsgi/dispatch.wsgi b/wsgi/dispatch.wsgi index 68cd5368ac..3736618102 100644 --- a/wsgi/dispatch.wsgi +++ b/wsgi/dispatch.wsgi @@ -1,11 +1,11 @@ import os import sys import site +import platform sys.stdout = sys.stderr -#TODO fix properly -ve_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'lib/python2.7/site-packages')) # Change python 2.6 to the python version you are using +ve_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'lib/python%s/site-packages' % platform.python_version()[:3])) # Add the virtual Python environment site-packages directory to the path site.addsitedir(ve_path)