diff --git a/apps/common/utils.py b/apps/common/utils.py index 47b3bbea29..18f1f2ef03 100644 --- a/apps/common/utils.py +++ b/apps/common/utils.py @@ -1,4 +1,6 @@ +# -*- coding: iso-8859-1 -*- import os +import re import types from django.utils.http import urlquote as django_urlquote @@ -88,3 +90,194 @@ def exists_with_famfam(path): return '' except Exception, exc: return exc + + +# The code here is based loosely on John Cardinal's notes found at: +# http://www.johncardinal.com/tmgutil/capitalizenames.htm + +# 2006-03-16 +# Thanks to David Kern for fixing some bugs. + +suffixes = [u"II", u"(II)", u"III", u"(III)", u"IV", u"(IV)", u"VI", u"(VI)", + u"VII", u"(VII)", u"2nd", u"(2nd)", u"3rd", u"(3rd)", u"4th", u"(4th)", + u"5th", u"(5th)"] + +# The names listed here are included by permission from John Cardinal's TMG Utility. +# http://www.johncardinal.com/tmgutil/index.htm +# John Cardinal maintains the copyright for this list of names. +surnames = [ + u"ApShaw", u"d'Albini", "d'Aubigney", u"d'Aubigné", u"d'Autry", + u"d'Entremont", u"d'Hurst", u"D'ovidio", u"da Graça", u"DaSilva", + u"DeAnda", u"deAnnethe", u"deAubigne", u"deAubigny", u"DeBardelaben", + u"DeBardeleben", u"DeBaugh", u"deBeauford", u"DeBerry", u"deBethune", + u"DeBetuile", u"DeBoard", u"DeBoer", u"DeBohun", u"DeBord", u"DeBose", + u"DeBrouwer", u"DeBroux", u"DeBruhl", u"deBruijn", u"deBrus", u"deBruse", + u"deBrusse", u"DeBruyne", u"DeBusk", u"DeCamp", u"deCastilla", u"DeCello", + u"deClare", u"DeClark", u"DeClerck", u"DeCoste", u"deCote", u"DeCoudres", + u"DeCoursey", u"DeCredico", u"deCuire", u"DeCuyre", u"DeDominicios", + u"DeDuyster", u"DeDuytscher", u"DeDuytser", u"deFiennes", u"DeFord", + u"DeForest", u"DeFrance", u"DeFriece", u"DeGarmo", u"deGraaff", u"DeGraff", + u"DeGraffenreid", u"DeGraw", u"DeGrenier", u"DeGroats", u"DeGroft", + u"DeGrote", u"DeHaan", u"DeHaas", u"DeHaddeclive", u"deHannethe", + u"DeHatclyf", u"DeHaven", u"DeHeer", u"DeJager", u"DeJarnette", u"DeJean", + u"DeJong", u"deJonge", u"deKemmeter", u"deKirketon", u"DeKroon", + u"deKype", u"del-Rosario", u"dela Chamotte", u"DeLa Cuadra", + u"DeLa Force", u"dela Fountaine", u"dela Greña", u"dela Place", + u"DeLa Ward", u"DeLaci", u"DeLacy", u"DeLaet", u"DeLalonde", u"DelAmarre", + u"DeLancey", u"DeLascy", u"DelAshmutt", u"DeLassy", u"DeLattre", + u"DeLaughter", u"DeLay", u"deLessine", u"DelGado", u"DelGaudio", + u"DeLiberti", u"DeLoache", u"DeLoatch", u"DeLoch", u"DeLockwood", + u"DeLong", u"DeLozier", u"DeLuca", u"DeLucenay", u"deLucy", u"DeMars", + u"DeMartino", u"deMaule", u"DeMello", u"DeMinck", u"DeMink", u"DeMoree", + u"DeMoss", u"DeMott", u"DeMuynck", u"deNiet", u"DeNise", u"DeNure", + u"DePalma", u"DePasquale", u"dePender", u"dePercy", u"DePoe", u"DePriest", + u"DePu", u"DePui", u"DePuis", u"DeReeper", u"deRochette", u"deRose", + u"DeRossett", u"DeRover", u"deRuggele", u"deRuggle", u"DeRuyter", + u"deSaint-Sauveur", u"DeSantis", u"desCuirs", u"DeSentis", u"DeShane", + u"DeSilva", u"DesJardins", u"DesMarest", u"deSoleure", u"DeSoto", + u"DeSpain", u"DeStefano", u"deSwaert", u"deSwart", u"DeVall", u"DeVane", + u"DeVasher", u"DeVasier", u"DeVaughan", u"DeVaughn", u"DeVault", u"DeVeau", + u"DeVeault", u"deVilleneuve", u"DeVilliers", u"DeVinney", u"DeVito", + u"deVogel", u"DeVolder", u"DeVolld", u"DeVore", u"deVos", u"DeVries", + u"deVries", u"DeWall", u"DeWaller", u"DeWalt", u"deWashington", + u"deWerly", u"deWessyngton", u"DeWet", u"deWinter", u"DeWitt", u"DeWolf", + u"DeWolfe", u"DeWolff", u"DeWoody", u"DeYager", u"DeYarmett", u"DeYoung", + u"DiCicco", u"DiCredico", u"DiFillippi", u"DiGiacomo", u"DiMarco", + u"DiMeo", u"DiMonte", u"DiNonno", u"DiPietro", u"diPilato", u"DiPrima", + u"DiSalvo", u"du Bosc", u"du Hurst", u"DuFort", u"DuMars", u"DuPre", + u"DuPue", u"DuPuy", u"FitzUryan", u"kummel", u"LaBarge", u"LaBarr", + u"LaBauve", u"LaBean", u"LaBelle", u"LaBerteaux", u"LaBine", u"LaBonte", + u"LaBorde", u"LaBounty", u"LaBranche", u"LaBrash", u"LaCaille", u"LaCasse", + u"LaChapelle", u"LaClair", u"LaComb", u"LaCoste", u"LaCount", u"LaCour", + u"LaCroix", u"LaFarlett", u"LaFarlette", u"LaFerry", u"LaFlamme", + u"LaFollette", u"LaForge", u"LaFortune", u"LaFoy", u"LaFramboise", + u"LaFrance", u"LaFuze", u"LaGioia", u"LaGrone", u"LaLiberte", u"LaLonde", + u"LaLone", u"LaMaster", u"LaMay", u"LaMere", u"LaMont", u"LaMotte", + u"LaPeer", u"LaPierre", u"LaPlante", u"LaPoint", u"LaPointe", u"LaPorte", + u"LaPrade", u"LaRocca", u"LaRochelle", u"LaRose", u"LaRue", u"LaVallee", + u"LaVaque", u"LaVeau", u"LeBleu", u"LeBoeuf", u"LeBoiteaux", u"LeBoyteulx", + u"LeCheminant", u"LeClair", u"LeClerc", u"LeCompte", u"LeCroy", u"LeDuc", + u"LeFevbre", u"LeFever", u"LeFevre", u"LeFlore", u"LeGette", u"LeGrand", + u"LeGrave", u"LeGro", u"LeGros", u"LeJeune", u"LeMaistre", u"LeMaitre", + u"LeMaster", u"LeMesurier", u"LeMieux", u"LeMoe", u"LeMoigne", u"LeMoine", + u"LeNeve", u"LePage", u"LeQuire", u"LeQuyer", u"LeRou", u"LeRoy", u"LeSuer", + u"LeSueur", u"LeTardif", u"LeVally", u"LeVert", u"LoMonaco", u"Macabe", + u"Macaluso", u"MacaTasney", u"Macaulay", u"Macchitelli", u"Maccoone", + u"Maccurry", u"Macdermattroe", u"Macdiarmada", u"Macelvaine", u"Macey", + u"Macgraugh", u"Machan", u"Machann", u"Machum", u"Maciejewski", u"Maciel", + u"Mackaben", u"Mackall", u"Mackartee", u"Mackay", u"Macken", u"Mackert", + u"Mackey", u"Mackie", u"Mackin", u"Mackins", u"Macklin", u"Macko", + u"Macksey", u"Mackwilliams", u"Maclean", u"Maclinden", u"Macomb", + u"Macomber", u"Macon", u"Macoombs", u"Macraw", u"Macumber", u"Macurdy", + u"Macwilliams", u"MaGuinness", u"MakCubyn", u"MakCumby", u"Mcelvany", + u"Mcsherry", u"Op den Dyck", u"Op den Graeff", u"regory", u"Schweißguth", + u"StElmo", u"StGelais", u"StJacques", u"te Boveldt", u"VanAernam", + u"VanAken", u"VanAlstine", u"VanAmersfoort", u"VanAntwerp", u"VanArlem", + u"VanArnam", u"VanArnem", u"VanArnhem", u"VanArnon", u"VanArsdale", + u"VanArsdalen", u"VanArsdol", u"vanAssema", u"vanAsten", u"VanAuken", + u"VanAwman", u"VanBaucom", u"VanBebber", u"VanBeber", u"VanBenschoten", + u"VanBibber", u"VanBilliard", u"vanBlare", u"vanBlaricom", u"VanBuren", + u"VanBuskirk", u"VanCamp", u"VanCampen", u"VanCleave", u"VanCleef", + u"VanCleve", u"VanCouwenhoven", u"VanCovenhoven", u"VanCowenhoven", + u"VanCuren", u"VanDalsem", u"VanDam", u"VanDe Poel", u"vanden Dijkgraaf", + u"vanden Kommer", u"VanDer Aar", u"vander Gouwe", u"VanDer Honing", + u"VanDer Hooning", u"vander Horst", u"vander Kroft", u"vander Krogt", + u"VanDer Meer", u"vander Meulen", u"vander Putte", u"vander Schooren", + u"VanDer Veen", u"VanDer Ven", u"VanDer Wal", u"VanDer Weide", + u"VanDer Willigen", u"vander Wulp", u"vander Zanden", u"vander Zwan", + u"VanDer Zweep", u"VanDeren", u"VanDerlaan", u"VanDerveer", + u"VanderWoude", u"VanDeursen", u"VanDeusen", u"vanDijk", u"VanDoren", + u"VanDorn", u"VanDort", u"VanDruff", u"VanDryer", u"VanDusen", u"VanDuzee", + u"VanDuzen", u"VanDuzer", u"VanDyck", u"VanDyke", u"VanEman", u"VanEmmen", + u"vanEmmerik", u"VanEngen", u"vanErp", u"vanEssen", u"VanFleet", + u"VanGalder", u"VanGelder", u"vanGerrevink", u"VanGog", u"vanGogh", + u"VanGorder", u"VanGordon", u"VanGroningen", u"VanGuilder", u"VanGundy", + u"VanHaaften", u"VanHaute", u"VanHees", u"vanHeugten", u"VanHise", + u"VanHoeck", u"VanHoek", u"VanHook", u"vanHoorn", u"VanHoornbeeck", + u"VanHoose", u"VanHooser", u"VanHorn", u"VanHorne", u"VanHouten", + u"VanHoye", u"VanHuijstee", u"VanHuss", u"VanImmon", u"VanKersschaever", + u"VanKeuren", u"VanKleeck", u"VanKoughnet", u"VanKouwenhoven", + u"VanKuykendaal", u"vanLeeuwen", u"vanLent", u"vanLet", u"VanLeuven", + u"vanLingen", u"VanLoozen", u"VanLopik", u"VanLuven", u"vanMaasdijk", + u"VanMele", u"VanMeter", u"vanMoorsel", u"VanMoorst", u"VanMossevelde", + u"VanNaarden", u"VanNamen", u"VanNemon", u"VanNess", u"VanNest", + u"VanNimmen", u"vanNobelen", u"VanNorman", u"VanNormon", u"VanNostrunt", + u"VanNote", u"VanOker", u"vanOosten", u"VanOrden", u"VanOrder", + u"VanOrma", u"VanOrman", u"VanOrnum", u"VanOstrander", u"VanOvermeire", + u"VanPelt", u"VanPool", u"VanPoole", u"VanPoorvliet", u"VanPutten", + u"vanRee", u"VanRhijn", u"vanRijswijk", u"VanRotmer", u"VanSchaick", + u"vanSchelt", u"VanSchoik", u"VanSchoonhoven", u"VanSciver", u"VanScoy", + u"VanScoyoc", u"vanSeters", u"VanSickle", u"VanSky", u"VanSnellenberg", + u"vanStaveren", u"VanStraten", u"VanSuijdam", u"VanTassel", u"VanTassell", + u"VanTessel", u"VanTexel", u"VanTuyl", u"VanValckenburgh", u"vanValen", + u"VanValkenburg", u"VanVelsor", u"VanVelzor", u"VanVlack", u"VanVleck", + u"VanVleckeren", u"VanWaard", u"VanWart", u"VanWassenhove", u"VanWinkle", + u"VanWoggelum", u"vanWordragen", u"VanWormer", u"VanZuidam", + u"VanZuijdam", u"VonAdenbach", u"vonAllmen", u"vonBardeleben", + u"vonBerckefeldt", u"VonBergen", u"vonBreyman", u"VonCannon", + u"vonFreymann", u"vonHeimburg", u"VonHuben", u"vonKramer", + u"vonKruchenburg", u"vonPostel", u"VonRohr", u"VonRohrbach", + u"VonSass", u"VonSasse", u"vonSchlotte", u"VonSchneider", u"VonSeldern", + u"VonSpringer", u"VonVeyelmann", u"VonZweidorff"] + +#class Name(str): +# """A Class (based on the string type) that properly capitalizes a name.""" +# +# def __new__(cls, value=''): +# original = value +# proper = Capitalize(value) +# obj = str.__new__(cls, proper) +# obj.original = original +# return obj + +def proper_name(name): + """Does the work of capitalizing a name (can be a full name).""" + hyphen_indexes = [] + while name.find('-') > -1: + index = name.find('-') + hyphen_indexes.append(index) + name = name[:index] + ' ' + name[index+1:] + name = name.split() + name = [w.capitalize() for w in name] # standard capitalization + # "Mcx" should be "McX" + index = 0 + for w in name: + try: + name[index] = mc.sub("Mc"+w[2].upper(), w) + except: + pass + index += 1 + # "Macx" should be "MacX" + index = 0 + for w in name: + try: + name[index] = mac.sub("Mac"+w[3].upper(), w) + except: + pass + index += 1 + name = ' '.join( name ) + for index in hyphen_indexes: + name = name[:index] + '-' + name[index+1:] + + # funky stuff (no capitalization) + name = name.replace(" Dit ", " dit ") + name = name.replace(" Van ", " van ") + name = name.replace(" De ", " de ") + + # special surnames and suffixes + name += ' ' + for surname in surnames + suffixes: + pos = name.lower().find(surname.lower()) + if pos > -1: + # surname/suffix must be: + # 1. at start of name or after a space + # -and- + # 2. followed by the end of string or a space + if (((pos == 0) or (pos > 0 and name[pos-1] == ' ')) + and ((len(name) == pos+len(surname)) + or (name[pos+len(surname)] == ' '))): + name = name[:pos] + surname + name[pos+len(surname):] + return name.strip() + +mc = re.compile(r"^Mc(\w)(?=\w)", re.I) +mac = re.compile(r"^Mac(\w)(?=\w)", re.I) diff --git a/apps/documents/models.py b/apps/documents/models.py index cd727dd749..bac1373775 100644 --- a/apps/documents/models.py +++ b/apps/documents/models.py @@ -12,6 +12,7 @@ from python_magic import magic from dynamic_search.api import register from converter.api import get_page_count +from filesystem_serving.conf.settings import AVAILABLE_INDEXING_FUNCTIONS from documents.conf.settings import AVAILABLE_FUNCTIONS from documents.conf.settings import AVAILABLE_MODELS @@ -246,11 +247,14 @@ class DocumentTypeMetadataType(models.Model): verbose_name_plural = _(u'document type metadata type connectors') + +available_indexing_functions_string = (_(u' Available functions: %s') % ','.join(['%s()' % name for name, function in AVAILABLE_INDEXING_FUNCTIONS.items()])) if AVAILABLE_INDEXING_FUNCTIONS else '' + class MetadataIndex(models.Model): document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type')) expression = models.CharField(max_length=128, verbose_name=_(u'indexing expression'), - help_text=_(u'Enter a python string expression to be evaluated. The slash caracter "/" acts as a directory delimiter.')) + help_text=_(u'Enter a python string expression to be evaluated. The slash caracter "/" acts as a directory delimiter.%s') % available_indexing_functions_string) enabled = models.BooleanField(default=True, verbose_name=_(u'enabled')) def __unicode__(self): diff --git a/apps/filesystem_serving/api.py b/apps/filesystem_serving/api.py index 8f912c4c80..0d43550d8f 100644 --- a/apps/filesystem_serving/api.py +++ b/apps/filesystem_serving/api.py @@ -8,6 +8,7 @@ from filesystem_serving.conf.settings import FILESERVING_ENABLE from filesystem_serving.conf.settings import FILESERVING_PATH from filesystem_serving.conf.settings import SLUGIFY_PATHS from filesystem_serving.conf.settings import MAX_RENAME_COUNT +from filesystem_serving.conf.settings import AVAILABLE_INDEXING_FUNCTIONS from models import DocumentMetadataIndex, Document @@ -27,7 +28,7 @@ def document_create_fs_links(document): for metadata_index in document.document_type.metadataindex_set.all(): if metadata_index.enabled: try: - fabricated_directory = eval(metadata_index.expression, metadata_dict) + fabricated_directory = eval(metadata_index.expression, metadata_dict, AVAILABLE_INDEXING_FUNCTIONS) target_directory = os.path.join(FILESERVING_PATH, fabricated_directory) try: os.makedirs(target_directory) diff --git a/apps/filesystem_serving/conf/settings.py b/apps/filesystem_serving/conf/settings.py index 205f64c819..28e1d23ed7 100644 --- a/apps/filesystem_serving/conf/settings.py +++ b/apps/filesystem_serving/conf/settings.py @@ -1,7 +1,15 @@ from django.conf import settings +from common.utils import proper_name + +available_indexing_functions = { + 'proper_name':proper_name +} + + # Serving FILESERVING_ENABLE = getattr(settings, 'FILESYSTEM_FILESERVING_ENABLE', True) FILESERVING_PATH = getattr(settings, 'FILESYSTEM_FILESERVING_PATH', u'/tmp/mayan/documents') SLUGIFY_PATHS = getattr(settings, 'FILESYSTEM_SLUGIFY_PATHS', False) MAX_RENAME_COUNT = getattr(settings, 'FILESYSTEM_MAX_RENAME_COUNT', 200) +AVAILABLE_INDEXING_FUNCTIONS = getattr(settings, 'FILESYSTEM_INDEXING_AVAILABLE_FUNCTIONS', available_indexing_functions) diff --git a/apps/main/views.py b/apps/main/views.py index 06c83b7a44..c34e4074e7 100644 --- a/apps/main/views.py +++ b/apps/main/views.py @@ -54,7 +54,8 @@ def check_settings(request): {'name':'FILESYSTEM_FILESERVING_PATH', 'value':filesystem_serving_settings.FILESERVING_PATH, 'exists':True}, {'name':'FILESYSTEM_SLUGIFY_PATHS', 'value':filesystem_serving_settings.SLUGIFY_PATHS}, {'name':'FILESYSTEM_MAX_RENAME_COUNT', 'value':filesystem_serving_settings.MAX_RENAME_COUNT}, - + {'name':'FILESYSTEM_INDEXING_AVAILABLE_INDEXING_FUNCTIONS', 'value':filesystem_serving_settings.AVAILABLE_INDEXING_FUNCTIONS}, + # Common {'name':'COMMON_TEMPORARY_DIRECTORY', 'value':common_settings.TEMPORARY_DIRECTORY, 'exists':True, diff --git a/docs/Changelog.txt b/docs/Changelog.txt index c9ba04c206..5a30a79fab 100644 --- a/docs/Changelog.txt +++ b/docs/Changelog.txt @@ -1,3 +1,8 @@ +2011-Apr-04 +* Added a new setup option: + FILESYSTEM_INDEXING_AVAILABLE_FUNCTIONS - a dictionary to allow users + to add custom functions + 2011-Apr-01 * Added support for editing the metadata of multiple documents at the same time diff --git a/settings.py b/settings.py index af91f835ea..e37d276e77 100644 --- a/settings.py +++ b/settings.py @@ -201,6 +201,7 @@ TEMPLATE_CONTEXT_PROCESSORS = ( # Serving #FILESYSTEM_FILESERVING_ENABLE = True +#FILESYSTEM_INDEXING_AVAILABLE_FUNCTIONS = {} #FILESYSTEM_FILESERVING_PATH = u'/tmp/mayan/documents' #FILESYSTEM_SLUGIFY_PATHS = False #FILESYSTEM_MAX_RENAME_COUNT = 200