[gen] Changes in parameters of some basic field methods to enable field.languages to be defined dymanically via a method.
This commit is contained in:
parent
18afb4416c
commit
f8a7103c7a
|
@ -63,7 +63,7 @@ class Field:
|
||||||
value=not isSearch and \
|
value=not isSearch and \
|
||||||
field.getFormattedValue(zobj, rawValue, showChanges);
|
field.getFormattedValue(zobj, rawValue, showChanges);
|
||||||
requestValue=not isSearch and zobj.getRequestFieldValue(name);
|
requestValue=not isSearch and zobj.getRequestFieldValue(name);
|
||||||
inRequest=field.valueIsInRequest(req, name);
|
inRequest=field.valueIsInRequest(zobj, req, name);
|
||||||
error=req.get('%s_error' % name);
|
error=req.get('%s_error' % name);
|
||||||
isMultiple=(field.multiplicity[1] == None) or \
|
isMultiple=(field.multiplicity[1] == None) or \
|
||||||
(field.multiplicity[1] > 1);
|
(field.multiplicity[1] > 1);
|
||||||
|
@ -360,7 +360,7 @@ class Field:
|
||||||
else:
|
else:
|
||||||
master, masterValue = masterData
|
master, masterValue = masterData
|
||||||
if masterValue and callable(masterValue): return True
|
if masterValue and callable(masterValue): return True
|
||||||
reqValue = master.getRequestValue(obj.REQUEST)
|
reqValue = master.getRequestValue(obj)
|
||||||
# reqValue can be a list or not
|
# reqValue can be a list or not
|
||||||
if type(reqValue) not in sutils.sequenceTypes:
|
if type(reqValue) not in sutils.sequenceTypes:
|
||||||
return reqValue in masterValue
|
return reqValue in masterValue
|
||||||
|
@ -517,7 +517,7 @@ class Field:
|
||||||
def getValue(self, obj):
|
def getValue(self, obj):
|
||||||
'''Gets, on_obj, the value conforming to self's type definition.'''
|
'''Gets, on_obj, the value conforming to self's type definition.'''
|
||||||
value = getattr(obj.aq_base, self.name, None)
|
value = getattr(obj.aq_base, self.name, None)
|
||||||
if self.isEmptyValue(value):
|
if self.isEmptyValue(obj, value):
|
||||||
# If there is no value, get the default value if any: return
|
# If there is no value, get the default value if any: return
|
||||||
# self.default, of self.default() if it is a method.
|
# self.default, of self.default() if it is a method.
|
||||||
if callable(self.default):
|
if callable(self.default):
|
||||||
|
@ -539,7 +539,7 @@ class Field:
|
||||||
purposes. Needs to be overridden by some child classes. If
|
purposes. Needs to be overridden by some child classes. If
|
||||||
p_showChanges is True, the result must also include the changes that
|
p_showChanges is True, the result must also include the changes that
|
||||||
occurred on p_value across the ages.'''
|
occurred on p_value across the ages.'''
|
||||||
if self.isEmptyValue(value): return ''
|
if self.isEmptyValue(obj, value): return ''
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def getIndexType(self):
|
def getIndexType(self):
|
||||||
|
@ -573,7 +573,7 @@ class Field:
|
||||||
res = str(res)
|
res = str(res)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def valueIsInRequest(self, request, name):
|
def valueIsInRequest(self, obj, request, name):
|
||||||
'''Is there a value corresponding to this field in the request? p_name
|
'''Is there a value corresponding to this field in the request? p_name
|
||||||
can be different from self.name (ie, if it is a field within another
|
can be different from self.name (ie, if it is a field within another
|
||||||
(List) field). In most cases, checking that this p_name is in the
|
(List) field). In most cases, checking that this p_name is in the
|
||||||
|
@ -581,7 +581,7 @@ class Field:
|
||||||
for string multilingual fields.'''
|
for string multilingual fields.'''
|
||||||
return request.has_key(name)
|
return request.has_key(name)
|
||||||
|
|
||||||
def getRequestValue(self, request, requestName=None):
|
def getRequestValue(self, obj, requestName=None):
|
||||||
'''Gets a value for this field as carried in the request object. In the
|
'''Gets a value for this field as carried in the request object. In the
|
||||||
simplest cases, the request value is a single value whose name in the
|
simplest cases, the request value is a single value whose name in the
|
||||||
request is the name of the field.
|
request is the name of the field.
|
||||||
|
@ -595,15 +595,15 @@ class Field:
|
||||||
the container field). In this case, p_requestName must be used for
|
the container field). In this case, p_requestName must be used for
|
||||||
searching into the request, instead of the field name (self.name).'''
|
searching into the request, instead of the field name (self.name).'''
|
||||||
name = requestName or self.name
|
name = requestName or self.name
|
||||||
return request.get(name, None)
|
return obj.REQUEST.get(name, None)
|
||||||
|
|
||||||
def getStorableValue(self, value):
|
def getStorableValue(self, obj, value):
|
||||||
'''p_value is a valid value initially computed through calling
|
'''p_value is a valid value initially computed through calling
|
||||||
m_getRequestValue. So, it is a valid string (or list of strings)
|
m_getRequestValue. So, it is a valid string (or list of strings)
|
||||||
representation of the field value coming from the request.
|
representation of the field value coming from the request.
|
||||||
This method computes the real (potentially converted or manipulated
|
This method computes the real (potentially converted or manipulated
|
||||||
in some other way) value as can be stored in the database.'''
|
in some other way) value as can be stored in the database.'''
|
||||||
if self.isEmptyValue(value): return
|
if self.isEmptyValue(obj, value): return
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def getMasterData(self):
|
def getMasterData(self):
|
||||||
|
@ -634,11 +634,11 @@ class Field:
|
||||||
return 'updateSlaves(this,null,%s,%s,null,null%s)' % \
|
return 'updateSlaves(this,null,%s,%s,null,null%s)' % \
|
||||||
(q(zobj.absolute_url()), q(layoutType), cName)
|
(q(zobj.absolute_url()), q(layoutType), cName)
|
||||||
|
|
||||||
def isEmptyValue(self, value, obj=None):
|
def isEmptyValue(self, obj, value):
|
||||||
'''Returns True if the p_value must be considered as an empty value.'''
|
'''Returns True if the p_value must be considered as an empty value.'''
|
||||||
return value in self.nullValues
|
return value in self.nullValues
|
||||||
|
|
||||||
def isCompleteValue(self, value, obj=None):
|
def isCompleteValue(self, obj, value):
|
||||||
'''Returns True if the p_value must be considered as "complete". While,
|
'''Returns True if the p_value must be considered as "complete". While,
|
||||||
in most cases, a "complete" value simply means a "non empty" value
|
in most cases, a "complete" value simply means a "non empty" value
|
||||||
(see m_isEmptyValue above), in some special cases it is more subtle.
|
(see m_isEmptyValue above), in some special cases it is more subtle.
|
||||||
|
@ -648,7 +648,7 @@ class Field:
|
||||||
a Date with the "hour" part required will not be considered as empty
|
a Date with the "hour" part required will not be considered as empty
|
||||||
if the "day, month, year" part is present but will not be considered
|
if the "day, month, year" part is present but will not be considered
|
||||||
as complete without the "hour, minute" part.'''
|
as complete without the "hour, minute" part.'''
|
||||||
return not self.isEmptyValue(value, obj)
|
return not self.isEmptyValue(obj, value)
|
||||||
|
|
||||||
def validateValue(self, obj, value):
|
def validateValue(self, obj, value):
|
||||||
'''This method may be overridden by child classes and will be called at
|
'''This method may be overridden by child classes and will be called at
|
||||||
|
@ -673,7 +673,7 @@ class Field:
|
||||||
definition. If it is the case, None is returned. Else, a translated
|
definition. If it is the case, None is returned. Else, a translated
|
||||||
error message is returned.'''
|
error message is returned.'''
|
||||||
# If the value is required, check that a (complete) value is present.
|
# If the value is required, check that a (complete) value is present.
|
||||||
if not self.isCompleteValue(value, obj):
|
if not self.isCompleteValue(obj, value):
|
||||||
if self.required and self.isClientVisible(obj):
|
if self.required and self.isClientVisible(obj):
|
||||||
# If the field is required, but not visible according to
|
# If the field is required, but not visible according to
|
||||||
# master/slave relationships, we consider it not to be required.
|
# master/slave relationships, we consider it not to be required.
|
||||||
|
@ -686,7 +686,7 @@ class Field:
|
||||||
message = self.validateValue(obj, value)
|
message = self.validateValue(obj, value)
|
||||||
if message: return message
|
if message: return message
|
||||||
# Evaluate the custom validator if one has been specified
|
# Evaluate the custom validator if one has been specified
|
||||||
value = self.getStorableValue(value)
|
value = self.getStorableValue(obj, value)
|
||||||
if self.validator and (type(self.validator) in self.validatorTypes):
|
if self.validator and (type(self.validator) in self.validatorTypes):
|
||||||
obj = obj.appy()
|
obj = obj.appy()
|
||||||
if type(self.validator) != self.validatorTypes[-1]:
|
if type(self.validator) != self.validatorTypes[-1]:
|
||||||
|
|
|
@ -117,8 +117,8 @@ class Boolean(Field):
|
||||||
def getFormattedValue(self, obj, value, showChanges=False):
|
def getFormattedValue(self, obj, value, showChanges=False):
|
||||||
return obj.translate(self.getValueLabel(value))
|
return obj.translate(self.getValueLabel(value))
|
||||||
|
|
||||||
def getStorableValue(self, value):
|
def getStorableValue(self, obj, value):
|
||||||
if not self.isEmptyValue(value):
|
if not self.isEmptyValue(obj, value):
|
||||||
exec 'res = %s' % value
|
exec 'res = %s' % value
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
|
@ -207,7 +207,7 @@ class Date(Field):
|
||||||
return obj.translate('bad_date')
|
return obj.translate('bad_date')
|
||||||
|
|
||||||
def getFormattedValue(self, obj, value, showChanges=False):
|
def getFormattedValue(self, obj, value, showChanges=False):
|
||||||
if self.isEmptyValue(value): return ''
|
if self.isEmptyValue(obj, value): return ''
|
||||||
tool = obj.getTool().appy()
|
tool = obj.getTool().appy()
|
||||||
# A problem may occur with some extreme year values. Replace the "year"
|
# A problem may occur with some extreme year values. Replace the "year"
|
||||||
# part "by hand".
|
# part "by hand".
|
||||||
|
@ -219,7 +219,8 @@ class Date(Field):
|
||||||
res += ' %s' % value.strftime(tool.hourFormat)
|
res += ' %s' % value.strftime(tool.hourFormat)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getRequestValue(self, request, requestName=None):
|
def getRequestValue(self, obj, requestName=None):
|
||||||
|
request = obj.REQUEST
|
||||||
name = requestName or self.name
|
name = requestName or self.name
|
||||||
# Manage the "date" part
|
# Manage the "date" part
|
||||||
value = ''
|
value = ''
|
||||||
|
@ -238,8 +239,8 @@ class Date(Field):
|
||||||
value = value[:-1]
|
value = value[:-1]
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def getStorableValue(self, value):
|
def getStorableValue(self, obj, value):
|
||||||
if not self.isEmptyValue(value):
|
if not self.isEmptyValue(obj, value):
|
||||||
import DateTime
|
import DateTime
|
||||||
return DateTime.DateTime(value)
|
return DateTime.DateTime(value)
|
||||||
|
|
||||||
|
|
|
@ -327,16 +327,15 @@ class File(Field):
|
||||||
historized, mapping, label, sdefault, scolspan, swidth,
|
historized, mapping, label, sdefault, scolspan, swidth,
|
||||||
sheight, True)
|
sheight, True)
|
||||||
|
|
||||||
def getRequestValue(self, request, requestName=None):
|
def getRequestValue(self, obj, requestName=None):
|
||||||
name = requestName or self.name
|
name = requestName or self.name
|
||||||
return request.get('%s_file' % name)
|
return obj.REQUEST.get('%s_file' % name)
|
||||||
|
|
||||||
def getDefaultLayouts(self): return {'view':'l-f','edit':'lrv-f'}
|
def getDefaultLayouts(self): return {'view':'l-f','edit':'lrv-f'}
|
||||||
|
|
||||||
def isEmptyValue(self, value, obj=None):
|
def isEmptyValue(self, obj, value):
|
||||||
'''Must p_value be considered as empty?'''
|
'''Must p_value be considered as empty?'''
|
||||||
if not obj: return Field.isEmptyValue(self, value)
|
if value: return
|
||||||
if value: return False
|
|
||||||
# If "nochange", the value must not be considered as empty
|
# If "nochange", the value must not be considered as empty
|
||||||
return obj.REQUEST.get('%s_delete' % self.name) != 'nochange'
|
return obj.REQUEST.get('%s_delete' % self.name) != 'nochange'
|
||||||
|
|
||||||
|
|
|
@ -94,8 +94,8 @@ class Float(Field):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return obj.translate('bad_%s' % self.pythonType.__name__)
|
return obj.translate('bad_%s' % self.pythonType.__name__)
|
||||||
|
|
||||||
def getStorableValue(self, value):
|
def getStorableValue(self, obj, value):
|
||||||
if not self.isEmptyValue(value):
|
if not self.isEmptyValue(obj, value):
|
||||||
for sep in self.sep: value = value.replace(sep, '.')
|
for sep in self.sep: value = value.replace(sep, '.')
|
||||||
value = value.replace(self.tsep, '')
|
value = value.replace(self.tsep, '')
|
||||||
return self.pythonType(value)
|
return self.pythonType(value)
|
||||||
|
|
|
@ -68,10 +68,10 @@ class Integer(Field):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return obj.translate('bad_%s' % self.pythonType.__name__)
|
return obj.translate('bad_%s' % self.pythonType.__name__)
|
||||||
|
|
||||||
def getStorableValue(self, value):
|
def getStorableValue(self, obj, value):
|
||||||
if not self.isEmptyValue(value): return self.pythonType(value)
|
if not self.isEmptyValue(obj, value): return self.pythonType(value)
|
||||||
|
|
||||||
def getFormattedValue(self, obj, value, showChanges=False):
|
def getFormattedValue(self, obj, value, showChanges=False):
|
||||||
if self.isEmptyValue(value): return ''
|
if self.isEmptyValue(obj, value): return ''
|
||||||
return str(value)
|
return str(value)
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -119,8 +119,9 @@ class List(Field):
|
||||||
res.append(elem)
|
res.append(elem)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getRequestValue(self, request, requestName=None):
|
def getRequestValue(self, obj, requestName=None):
|
||||||
'''Concatenates the list from distinct form elements in the request.'''
|
'''Concatenates the list from distinct form elements in the request.'''
|
||||||
|
request = obj.REQUEST
|
||||||
name = requestName or self.name # A List may be into another List (?)
|
name = requestName or self.name # A List may be into another List (?)
|
||||||
prefix = name + '*' + self.fields[0][0] + '*'
|
prefix = name + '*' + self.fields[0][0] + '*'
|
||||||
res = {}
|
res = {}
|
||||||
|
@ -133,7 +134,7 @@ class List(Field):
|
||||||
if rowIndex == -1: continue # Ignore the template row.
|
if rowIndex == -1: continue # Ignore the template row.
|
||||||
for subName, subField in self.fields:
|
for subName, subField in self.fields:
|
||||||
keyName = '%s*%s*%s' % (name, subName, rowIndex)
|
keyName = '%s*%s*%s' % (name, subName, rowIndex)
|
||||||
v = subField.getRequestValue(request, requestName=keyName)
|
v = subField.getRequestValue(obj, requestName=keyName)
|
||||||
setattr(row, subName, v)
|
setattr(row, subName, v)
|
||||||
res[rowIndex] = row
|
res[rowIndex] = row
|
||||||
# Produce a sorted list.
|
# Produce a sorted list.
|
||||||
|
@ -148,7 +149,7 @@ class List(Field):
|
||||||
request.set(name, res)
|
request.set(name, res)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getStorableValue(self, value):
|
def getStorableValue(self, obj, value):
|
||||||
'''Gets p_value in a form that can be stored in the database.'''
|
'''Gets p_value in a form that can be stored in the database.'''
|
||||||
res = []
|
res = []
|
||||||
for v in value:
|
for v in value:
|
||||||
|
@ -156,11 +157,11 @@ class List(Field):
|
||||||
for name, field in self.fields:
|
for name, field in self.fields:
|
||||||
subValue = getattr(v, name)
|
subValue = getattr(v, name)
|
||||||
try:
|
try:
|
||||||
setattr(sv, name, field.getStorableValue(subValue))
|
setattr(sv, name, field.getStorableValue(obj, subValue))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# The value for this field for this specific row is
|
# The value for this field for this specific row is
|
||||||
# incorrect. It can happen in the process of validating the
|
# incorrect. It can happen in the process of validating the
|
||||||
# whole List field (a call to getStorableValue occurs at
|
# whole List field (a call to m_getStorableValue occurs at
|
||||||
# this time). We don't care about it, because later on we
|
# this time). We don't care about it, because later on we
|
||||||
# will have sub-field specific validation that will also
|
# will have sub-field specific validation that will also
|
||||||
# detect the error and will prevent storing the wrong value
|
# detect the error and will prevent storing the wrong value
|
||||||
|
|
|
@ -295,7 +295,7 @@ class Pod(Field):
|
||||||
tool = obj.tool
|
tool = obj.tool
|
||||||
diskFolder = tool.getDiskFolder()
|
diskFolder = tool.getDiskFolder()
|
||||||
# Get the path to the pod template.
|
# Get the path to the pod template.
|
||||||
templatePath = os.path.join(diskFolder, template)
|
templatePath = sutils.resolvePath(os.path.join(diskFolder, template))
|
||||||
if not os.path.isfile(templatePath):
|
if not os.path.isfile(templatePath):
|
||||||
raise Exception(self.TEMPLATE_NOT_FOUND % templatePath)
|
raise Exception(self.TEMPLATE_NOT_FOUND % templatePath)
|
||||||
# Get or compute the specific POD context
|
# Get or compute the specific POD context
|
||||||
|
|
|
@ -130,8 +130,8 @@ class String(Field):
|
||||||
pxMultilingual = Px('''
|
pxMultilingual = Px('''
|
||||||
<!-- Horizontally-layouted multilingual field -->
|
<!-- Horizontally-layouted multilingual field -->
|
||||||
<table if="mLayout == 'horizontal'" width="100%"
|
<table if="mLayout == 'horizontal'" width="100%"
|
||||||
var="count=len(field.languages)">
|
var="count=len(languages)">
|
||||||
<tr valign="top"><x for="lg in field.languages"><x>:field.pxLanguage</x>
|
<tr valign="top"><x for="lg in languages"><x>:field.pxLanguage</x>
|
||||||
<td width=":'%d%%' % int(100.0/count)"
|
<td width=":'%d%%' % int(100.0/count)"
|
||||||
var="requestValue=requestValue[lg]|None;
|
var="requestValue=requestValue[lg]|None;
|
||||||
value=value[lg]|emptyDefault">:field.subPx[layoutType][fmt]</td>
|
value=value[lg]|emptyDefault">:field.subPx[layoutType][fmt]</td>
|
||||||
|
@ -139,7 +139,7 @@ class String(Field):
|
||||||
|
|
||||||
<!-- Vertically-layouted multilingual field -->
|
<!-- Vertically-layouted multilingual field -->
|
||||||
<table if="mLayout == 'vertical'">
|
<table if="mLayout == 'vertical'">
|
||||||
<tr valign="top" height="20px" for="lg in field.languages">
|
<tr valign="top" height="20px" for="lg in languages">
|
||||||
<x>:field.pxLanguage</x>
|
<x>:field.pxLanguage</x>
|
||||||
<td var="requestValue=requestValue[lg]|None;
|
<td var="requestValue=requestValue[lg]|None;
|
||||||
value=value[lg]|emptyDefault">:field.subPx[layoutType][fmt]</td>
|
value=value[lg]|emptyDefault">:field.subPx[layoutType][fmt]</td>
|
||||||
|
@ -147,7 +147,8 @@ class String(Field):
|
||||||
|
|
||||||
pxView = Px('''
|
pxView = Px('''
|
||||||
<x var="fmt=field.format; isUrl=field.isUrl;
|
<x var="fmt=field.format; isUrl=field.isUrl;
|
||||||
multilingual=field.isMultilingual();
|
languages=field.getAttribute(zobj, 'languages');
|
||||||
|
multilingual=len(languages) > 1;
|
||||||
mLayout=multilingual and field.getLanguagesLayout('view');
|
mLayout=multilingual and field.getLanguagesLayout('view');
|
||||||
mayAjaxEdit=not showChanges and field.inlineEdit and \
|
mayAjaxEdit=not showChanges and field.inlineEdit and \
|
||||||
zobj.mayEdit(field.writePermission)">
|
zobj.mayEdit(field.writePermission)">
|
||||||
|
@ -193,7 +194,8 @@ class String(Field):
|
||||||
|
|
||||||
pxEdit = Px('''
|
pxEdit = Px('''
|
||||||
<x var="fmt=field.format;
|
<x var="fmt=field.format;
|
||||||
multilingual=field.isMultilingual();
|
languages=field.getAttribute(zobj, 'languages');
|
||||||
|
multilingual=len(languages) > 1;
|
||||||
mLayout=multilingual and field.getLanguagesLayout('edit')">
|
mLayout=multilingual and field.getLanguagesLayout('edit')">
|
||||||
<select if="field.isSelect"
|
<select if="field.isSelect"
|
||||||
var2="possibleValues=field.getPossibleValues(zobj, \
|
var2="possibleValues=field.getPossibleValues(zobj, \
|
||||||
|
@ -447,7 +449,7 @@ class String(Field):
|
||||||
def checkParameters(self):
|
def checkParameters(self):
|
||||||
'''Ensures this String is correctly defined.'''
|
'''Ensures this String is correctly defined.'''
|
||||||
error = None
|
error = None
|
||||||
if self.isMultilingual():
|
if self.isMultilingual(None):
|
||||||
if self.isSelect:
|
if self.isSelect:
|
||||||
error = "A selection field can't be multilingual."
|
error = "A selection field can't be multilingual."
|
||||||
elif self.format in (String.PASSWORD, String.CAPTCHA):
|
elif self.format in (String.PASSWORD, String.CAPTCHA):
|
||||||
|
@ -468,7 +470,11 @@ class String(Field):
|
||||||
res = False
|
res = False
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def isMultilingual(self): return len(self.languages) > 1
|
def isMultilingual(self, obj):
|
||||||
|
'''Is this field multilingual ?.'''
|
||||||
|
# In the following case, impossible to know: we say no.
|
||||||
|
if not obj and callable(self.languages): return
|
||||||
|
return len(self.getAttribute(obj, 'languages')) > 1
|
||||||
|
|
||||||
def getDefaultLayouts(self):
|
def getDefaultLayouts(self):
|
||||||
'''Returns the default layouts for this type. Default layouts can vary
|
'''Returns the default layouts for this type. Default layouts can vary
|
||||||
|
@ -507,45 +513,50 @@ class String(Field):
|
||||||
value = list(value)
|
value = list(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def valueIsInRequest(self, request, name):
|
def valueIsInRequest(self, obj, request, name):
|
||||||
if not self.isMultilingual():
|
languages = self.getAttribute(obj, 'languages')
|
||||||
return Field.valueIsInRequest(self, request, name)
|
if len(languages) == 1:
|
||||||
return request.has_key('%s_%s' % (name, self.languages[0]))
|
return Field.valueIsInRequest(self, obj, request, name)
|
||||||
|
# Is is sufficient to check that at least one of the language-specific
|
||||||
|
# values is in the request.
|
||||||
|
return request.has_key('%s_%s' % (name, languages[0]))
|
||||||
|
|
||||||
def getRequestValue(self, request, requestName=None):
|
def getRequestValue(self, obj, requestName=None):
|
||||||
'''The request value may be multilingual.'''
|
'''The request value may be multilingual.'''
|
||||||
|
request = obj.REQUEST
|
||||||
name = requestName or self.name
|
name = requestName or self.name
|
||||||
|
languages = self.getAttribute(obj, 'languages')
|
||||||
# A unilingual field.
|
# A unilingual field.
|
||||||
if not self.isMultilingual(): return request.get(name, None)
|
if len(languages) == 1: return request.get(name, None)
|
||||||
# A multilingual field.
|
# A multilingual field.
|
||||||
res = {}
|
res = {}
|
||||||
for language in self.languages:
|
for language in languages:
|
||||||
res[language] = request.get('%s_%s' % (name, language), None)
|
res[language] = request.get('%s_%s' % (name, language), None)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def isEmptyValue(self, value, obj=None):
|
def isEmptyValue(self, obj, value):
|
||||||
'''Returns True if the p_value must be considered as an empty value.'''
|
'''Returns True if the p_value must be considered as an empty value.'''
|
||||||
if not self.isMultilingual():
|
if not self.isMultilingual(obj):
|
||||||
return Field.isEmptyValue(self, value, obj)
|
return Field.isEmptyValue(self, obj, value)
|
||||||
# For a multilingual value, as soon as a value is not empty for a given
|
# For a multilingual value, as soon as a value is not empty for a given
|
||||||
# language, the whole value is considered as not being empty.
|
# language, the whole value is considered as not being empty.
|
||||||
if not value: return True
|
if not value: return True
|
||||||
for v in value.itervalues():
|
for v in value.itervalues():
|
||||||
if not Field.isEmptyValue(self, v, obj): return
|
if not Field.isEmptyValue(self, obj, v): return
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def isCompleteValue(self, value, obj=None):
|
def isCompleteValue(self, obj, value):
|
||||||
'''Returns True if the p_value must be considered as complete. For a
|
'''Returns True if the p_value must be considered as complete. For a
|
||||||
unilingual field, being complete simply means not being empty. For a
|
unilingual field, being complete simply means not being empty. For a
|
||||||
multilingual field, being complete means that a value is present for
|
multilingual field, being complete means that a value is present for
|
||||||
every language'''
|
every language.'''
|
||||||
if not self.isMultilingual():
|
if not self.isMultilingual(obj):
|
||||||
return Field.isCompleteValue(self, value, obj)
|
return Field.isCompleteValue(self, obj, value)
|
||||||
# As soon as a given language value is empty, the global value is not
|
# As soon as a given language value is empty, the global value is not
|
||||||
# complete.
|
# complete.
|
||||||
if not value: return True
|
if not value: return True
|
||||||
for v in value.itervalues():
|
for v in value.itervalues():
|
||||||
if Field.isEmptyValue(self, v, obj): return
|
if Field.isEmptyValue(self, obj, v): return
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def getDiffValue(self, obj, value, language):
|
def getDiffValue(self, obj, value, language):
|
||||||
|
@ -581,7 +592,7 @@ class String(Field):
|
||||||
m_getFormattedValue for getting a non-multilingual value (ie, in
|
m_getFormattedValue for getting a non-multilingual value (ie, in
|
||||||
most cases). Else, this method returns a formatted value for the
|
most cases). Else, this method returns a formatted value for the
|
||||||
p_language-specific part of a multilingual value.'''
|
p_language-specific part of a multilingual value.'''
|
||||||
if Field.isEmptyValue(self, value): return ''
|
if Field.isEmptyValue(self, obj, value): return ''
|
||||||
res = value
|
res = value
|
||||||
if self.isSelect:
|
if self.isSelect:
|
||||||
if isinstance(self.validator, Selection):
|
if isinstance(self.validator, Selection):
|
||||||
|
@ -609,13 +620,14 @@ class String(Field):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getFormattedValue(self, obj, value, showChanges=False):
|
def getFormattedValue(self, obj, value, showChanges=False):
|
||||||
if not self.isMultilingual():
|
languages = self.getAttribute(obj, 'languages')
|
||||||
|
if len(languages) == 1:
|
||||||
return self.getUnilingualFormattedValue(obj, value, showChanges)
|
return self.getUnilingualFormattedValue(obj, value, showChanges)
|
||||||
# Return the dict of values whose individual, language-specific values
|
# Return the dict of values whose individual, language-specific values
|
||||||
# have been formatted via m_getUnilingualFormattedValue.
|
# have been formatted via m_getUnilingualFormattedValue.
|
||||||
if not value: return value
|
if not value: return value
|
||||||
res = {}
|
res = {}
|
||||||
for lg in self.languages:
|
for lg in languages:
|
||||||
res[lg] = self.getUnilingualFormattedValue(obj, value[lg],
|
res[lg] = self.getUnilingualFormattedValue(obj, value[lg],
|
||||||
showChanges, lg)
|
showChanges, lg)
|
||||||
return res
|
return res
|
||||||
|
@ -631,7 +643,7 @@ class String(Field):
|
||||||
'''Pure text must be extracted from rich content; multilingual content
|
'''Pure text must be extracted from rich content; multilingual content
|
||||||
must be concatenated.'''
|
must be concatenated.'''
|
||||||
isXhtml = self.format == String.XHTML
|
isXhtml = self.format == String.XHTML
|
||||||
if self.isMultilingual():
|
if self.isMultilingual(obj):
|
||||||
res = self.getValue(obj)
|
res = self.getValue(obj)
|
||||||
if res:
|
if res:
|
||||||
vals = []
|
vals = []
|
||||||
|
@ -775,9 +787,9 @@ class String(Field):
|
||||||
elif self.transform == 'capitalize': return value.capitalize()
|
elif self.transform == 'capitalize': return value.capitalize()
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def getUnilingualStorableValue(self, value):
|
def getUnilingualStorableValue(self, obj, value):
|
||||||
isString = isinstance(value, basestring)
|
isString = isinstance(value, basestring)
|
||||||
isEmpty = Field.isEmptyValue(self, value)
|
isEmpty = Field.isEmptyValue(self, obj, value)
|
||||||
# Apply transform if required
|
# Apply transform if required
|
||||||
if isString and not isEmpty and (self.transform != 'none'):
|
if isString and not isEmpty and (self.transform != 'none'):
|
||||||
value = self.applyTransform(value)
|
value = self.applyTransform(value)
|
||||||
|
@ -804,21 +816,23 @@ class String(Field):
|
||||||
value = [value]
|
value = [value]
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def getStorableValue(self, value):
|
def getStorableValue(self, obj, value):
|
||||||
if not self.isMultilingual():
|
languages = self.getAttribute(obj, 'languages')
|
||||||
return self.getUnilingualStorableValue(value)
|
if len(languages) == 1:
|
||||||
|
return self.getUnilingualStorableValue(obj, value)
|
||||||
# A multilingual value is stored as a dict whose keys are ISO 2-letters
|
# A multilingual value is stored as a dict whose keys are ISO 2-letters
|
||||||
# language codes and whose values are strings storing content in the
|
# language codes and whose values are strings storing content in the
|
||||||
# language ~{s_language: s_content}~.
|
# language ~{s_language: s_content}~.
|
||||||
if not value: return
|
if not value: return
|
||||||
for lg in self.languages:
|
for lg in languages:
|
||||||
value[lg] = self.getUnilingualStorableValue(value[lg])
|
value[lg] = self.getUnilingualStorableValue(obj, value[lg])
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def store(self, obj, value):
|
def store(self, obj, value):
|
||||||
'''Stores p_value on p_obj for this field.'''
|
'''Stores p_value on p_obj for this field.'''
|
||||||
if self.isMultilingual() and value and \
|
languages = self.getAttribute(obj, 'languages')
|
||||||
(not isinstance(value, dict) or (len(value) != len(self.languages))):
|
if (len(languages) > 1) and value and \
|
||||||
|
(not isinstance(value, dict) or (len(value) != len(languages))):
|
||||||
raise Exception('Multilingual field "%s" accepts a dict whose '\
|
raise Exception('Multilingual field "%s" accepts a dict whose '\
|
||||||
'keys are in field.languages and whose ' \
|
'keys are in field.languages and whose ' \
|
||||||
'values are strings.' % self.name)
|
'values are strings.' % self.name)
|
||||||
|
@ -832,16 +846,16 @@ class String(Field):
|
||||||
requestValue = rq['fieldContent']
|
requestValue = rq['fieldContent']
|
||||||
# Remember previous value if the field is historized.
|
# Remember previous value if the field is historized.
|
||||||
previousData = obj.rememberPreviousData([self])
|
previousData = obj.rememberPreviousData([self])
|
||||||
if self.isMultilingual():
|
if self.isMultilingual(obj):
|
||||||
# We take a copy of previousData because it is mutable (dict).
|
# We take a copy of previousData because it is mutable (dict).
|
||||||
previousData[self.name] = previousData[self.name].copy()
|
previousData[self.name] = previousData[self.name].copy()
|
||||||
# We get a partial value, for one language only.
|
# We get a partial value, for one language only.
|
||||||
language = rq['languageOnly']
|
language = rq['languageOnly']
|
||||||
v = self.getUnilingualStorableValue(requestValue)
|
v = self.getUnilingualStorableValue(obj, requestValue)
|
||||||
getattr(obj.aq_base, self.name)[language] = v
|
getattr(obj.aq_base, self.name)[language] = v
|
||||||
part = ' (%s)' % language
|
part = ' (%s)' % language
|
||||||
else:
|
else:
|
||||||
self.store(obj, self.getStorableValue(requestValue))
|
self.store(obj, self.getStorableValue(obj, requestValue))
|
||||||
part = ''
|
part = ''
|
||||||
# Update the object history when relevant
|
# Update the object history when relevant
|
||||||
if previousData: obj.historizeData(previousData)
|
if previousData: obj.historizeData(previousData)
|
||||||
|
@ -892,11 +906,12 @@ class String(Field):
|
||||||
'fi': 'fi_FI', 'fr': 'fr_FR', 'de': 'de_DE', 'el': 'el_GR',
|
'fi': 'fi_FI', 'fr': 'fr_FR', 'de': 'de_DE', 'el': 'el_GR',
|
||||||
'it': 'it_IT', 'nb': 'nb_NO', 'pt': 'pt_PT', 'es': 'es_ES',
|
'it': 'it_IT', 'nb': 'nb_NO', 'pt': 'pt_PT', 'es': 'es_ES',
|
||||||
'sv': 'sv_SE'}
|
'sv': 'sv_SE'}
|
||||||
def getCkLanguage(self, language):
|
def getCkLanguage(self, obj, language):
|
||||||
'''Gets the language for CK editor SCAYT. p_language is one of
|
'''Gets the language for CK editor SCAYT. p_language is one of
|
||||||
self.languages if the field is multilingual, None else. If p_language
|
self.languages if the field is multilingual, None else. If p_language
|
||||||
is not supported by CK, we use english.'''
|
is not supported by CK, we use english.'''
|
||||||
if not language: language = self.languages[0]
|
if not language:
|
||||||
|
language = self.getAttribute(obj, 'languages')[0]
|
||||||
if language in self.ckLanguages: return self.ckLanguages[language]
|
if language in self.ckLanguages: return self.ckLanguages[language]
|
||||||
return 'en_US'
|
return 'en_US'
|
||||||
|
|
||||||
|
@ -904,7 +919,7 @@ class String(Field):
|
||||||
'''Gets the base params to set on a rich text field.'''
|
'''Gets the base params to set on a rich text field.'''
|
||||||
ckAttrs = {'toolbar': 'Appy',
|
ckAttrs = {'toolbar': 'Appy',
|
||||||
'format_tags': ';'.join(self.styles),
|
'format_tags': ';'.join(self.styles),
|
||||||
'scayt_sLang': self.getCkLanguage(language)}
|
'scayt_sLang': self.getCkLanguage(obj, language)}
|
||||||
if self.width: ckAttrs['width'] = self.width
|
if self.width: ckAttrs['width'] = self.width
|
||||||
if self.spellcheck: ckAttrs['scayt_autoStartup'] = True
|
if self.spellcheck: ckAttrs['scayt_autoStartup'] = True
|
||||||
if self.allowImageUpload:
|
if self.allowImageUpload:
|
||||||
|
|
|
@ -1246,12 +1246,27 @@ class ToolMixin(BaseMixin):
|
||||||
return [f for f in self.getAllAppyTypes(contentType) \
|
return [f for f in self.getAllAppyTypes(contentType) \
|
||||||
if (f.type == 'Pod') and (f.show == 'result')]
|
if (f.type == 'Pod') and (f.show == 'result')]
|
||||||
|
|
||||||
def formatDate(self, date, withHour=True):
|
def formatDate(self, date, format=None, withHour=True, language=None):
|
||||||
'''Returns p_date formatted as specified by tool.dateFormat.
|
'''Returns p_date formatted as specified by p_format, or tool.dateFormat
|
||||||
If p_withHour is True, hour is appended, with a format specified
|
if not specified. If p_withHour is True, hour is appended, with a
|
||||||
in tool.hourFormat.'''
|
format specified in tool.hourFormat.'''
|
||||||
tool = self.appy()
|
tool = self.appy()
|
||||||
res = date.strftime(tool.dateFormat)
|
fmt = format or tool.dateFormat
|
||||||
|
# Resolve appy-specific formatting symbols used for getting translated
|
||||||
|
# names of days or months:
|
||||||
|
# - %dt: translated name of day
|
||||||
|
# - %DT: translated name of day, capitalized
|
||||||
|
# - %mt: translated name of month
|
||||||
|
# - %MT: translated name of month, capitalized
|
||||||
|
if ('%dt' in fmt) or ('%DT' in fmt):
|
||||||
|
day = self.translate('day_%s' % date._aday, language=language)
|
||||||
|
fmt = fmt.replace('%dt', day.lower()).replace('%DT', day)
|
||||||
|
if ('%mt' in fmt) or ('%MT' in fmt):
|
||||||
|
month = self.translate('month_%s' % date._amon, language=language)
|
||||||
|
fmt = fmt.replace('%mt', month.lower()).replace('%MT', month)
|
||||||
|
# Resolve all other, standard, symbols
|
||||||
|
res = date.strftime(fmt)
|
||||||
|
# Append hour from tool.hourFormat
|
||||||
if withHour: res += ' (%s)' % date.strftime(tool.hourFormat)
|
if withHour: res += ' (%s)' % date.strftime(tool.hourFormat)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
|
@ -337,12 +337,12 @@ class BaseMixin:
|
||||||
rq = self.REQUEST
|
rq = self.REQUEST
|
||||||
for field in self.getAppyTypes('edit', rq.form.get('page')):
|
for field in self.getAppyTypes('edit', rq.form.get('page')):
|
||||||
if not field.validable or not field.isClientVisible(self): continue
|
if not field.validable or not field.isClientVisible(self): continue
|
||||||
value = field.getRequestValue(rq)
|
value = field.getRequestValue(self)
|
||||||
message = field.validate(self, value)
|
message = field.validate(self, value)
|
||||||
if message:
|
if message:
|
||||||
setattr(errors, field.name, message)
|
setattr(errors, field.name, message)
|
||||||
else:
|
else:
|
||||||
setattr(values, field.name, field.getStorableValue(value))
|
setattr(values, field.name, field.getStorableValue(self, value))
|
||||||
# Validate sub-fields within Lists
|
# Validate sub-fields within Lists
|
||||||
if field.type != 'List': continue
|
if field.type != 'List': continue
|
||||||
i = -1
|
i = -1
|
||||||
|
@ -634,7 +634,7 @@ class BaseMixin:
|
||||||
if lg:
|
if lg:
|
||||||
isEmpty = not changes[name] or not changes[name].get(lg)
|
isEmpty = not changes[name] or not changes[name].get(lg)
|
||||||
else:
|
else:
|
||||||
isEmpty = field.isEmptyValue(changes[name], self)
|
isEmpty = field.isEmptyValue(self, changes[name])
|
||||||
if isEmpty:
|
if isEmpty:
|
||||||
del changes[name]
|
del changes[name]
|
||||||
else:
|
else:
|
||||||
|
@ -664,14 +664,17 @@ class BaseMixin:
|
||||||
# In some cases the old value must be formatted.
|
# In some cases the old value must be formatted.
|
||||||
if field.type == 'Ref':
|
if field.type == 'Ref':
|
||||||
previousData[name] = [r.title for r in previousData[name]]
|
previousData[name] = [r.title for r in previousData[name]]
|
||||||
elif (field.type == 'String') and field.isMultilingual():
|
elif field.type == 'String':
|
||||||
# Consider every language-specific value as a first-class value
|
languages = field.getAttribute(self, 'languages')
|
||||||
del previousData[name]
|
if len(languages) > 1:
|
||||||
for lg in field.languages:
|
# Consider every language-specific value as a first-class
|
||||||
lgPrev = prev and prev.get(lg) or None
|
# value.
|
||||||
lgCurr = curr and curr.get(lg) or None
|
del previousData[name]
|
||||||
if lgPrev == lgCurr: continue
|
for lg in languages:
|
||||||
previousData['%s-%s' % (name, lg)] = lgPrev
|
lgPrev = prev and prev.get(lg) or None
|
||||||
|
lgCurr = curr and curr.get(lg) or None
|
||||||
|
if lgPrev == lgCurr: continue
|
||||||
|
previousData['%s-%s' % (name, lg)] = lgPrev
|
||||||
if previousData:
|
if previousData:
|
||||||
self.addDataChange(previousData)
|
self.addDataChange(previousData)
|
||||||
|
|
||||||
|
@ -714,7 +717,7 @@ class BaseMixin:
|
||||||
'''Gets the value of field p_name as may be present in the request.'''
|
'''Gets the value of field p_name as may be present in the request.'''
|
||||||
# Return the request value for standard fields.
|
# Return the request value for standard fields.
|
||||||
if '*' not in name:
|
if '*' not in name:
|
||||||
return self.getAppyType(name).getRequestValue(self.REQUEST)
|
return self.getAppyType(name).getRequestValue(self)
|
||||||
# For sub-fields within Lists, the corresponding request values have
|
# For sub-fields within Lists, the corresponding request values have
|
||||||
# already been computed in the request key corresponding to the whole
|
# already been computed in the request key corresponding to the whole
|
||||||
# List.
|
# List.
|
||||||
|
@ -1083,7 +1086,11 @@ class BaseMixin:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
field = self.getAppyType(name)
|
field = self.getAppyType(name)
|
||||||
multilingual = (field.type == 'String') and field.isMultilingual()
|
# Is this field a multilingual field ?
|
||||||
|
languages = None
|
||||||
|
if field.type == 'String':
|
||||||
|
languages = field.getAttribute(self, 'languages')
|
||||||
|
multilingual = len(languages) > 1
|
||||||
for event in history:
|
for event in history:
|
||||||
if event['action'] != '_datachange_': continue
|
if event['action'] != '_datachange_': continue
|
||||||
# Is there a value present for this field in this data change?
|
# Is there a value present for this field in this data change?
|
||||||
|
@ -1093,7 +1100,7 @@ class BaseMixin:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
# At least one language-specific value must be present
|
# At least one language-specific value must be present
|
||||||
for lg in field.languages:
|
for lg in languages:
|
||||||
lgName = '%s-%s' % (field.name, lg)
|
lgName = '%s-%s' % (field.name, lg)
|
||||||
if (lgName in event['changes']) and \
|
if (lgName in event['changes']) and \
|
||||||
event['changes'][lgName][0]:
|
event['changes'][lgName][0]:
|
||||||
|
@ -1142,7 +1149,7 @@ class BaseMixin:
|
||||||
# previous value, we propose a diff with the next
|
# previous value, we propose a diff with the next
|
||||||
# version, excepted if the previous value is empty.
|
# version, excepted if the previous value is empty.
|
||||||
if lg: isEmpty = not oldValue[0]
|
if lg: isEmpty = not oldValue[0]
|
||||||
else: isEmpty = field.isEmptyValue(oldValue[0])
|
else: isEmpty = field.isEmptyValue(self, oldValue[0])
|
||||||
if isEmpty:
|
if isEmpty:
|
||||||
val = '-'
|
val = '-'
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -627,15 +627,6 @@ class ToolWrapper(AbstractWrapper):
|
||||||
(user.o.absolute_url(), user.title,access))
|
(user.o.absolute_url(), user.title,access))
|
||||||
return res + '\n'.join(rows) + '</table>'
|
return res + '\n'.join(rows) + '</table>'
|
||||||
|
|
||||||
def getInitiator(self, field=False):
|
|
||||||
'''Retrieves the object that triggered the creation of the object
|
|
||||||
being currently created (if any), or the name of the field in this
|
|
||||||
object if p_field is given.'''
|
|
||||||
nav = self.o.REQUEST.get('nav', '')
|
|
||||||
if not nav or not nav.startswith('ref.'): return
|
|
||||||
if not field: return self.getObject(nav.split('.')[1])
|
|
||||||
return nav.split('.')[2].split(':')[0]
|
|
||||||
|
|
||||||
def getObject(self, uid):
|
def getObject(self, uid):
|
||||||
'''Allow to retrieve an object from its unique identifier p_uid.'''
|
'''Allow to retrieve an object from its unique identifier p_uid.'''
|
||||||
return self.o.getObject(uid, appy=True)
|
return self.o.getObject(uid, appy=True)
|
||||||
|
@ -666,10 +657,10 @@ class ToolWrapper(AbstractWrapper):
|
||||||
'''Sends a mail. See doc for appy.gen.mail.sendMail.'''
|
'''Sends a mail. See doc for appy.gen.mail.sendMail.'''
|
||||||
sendMail(self, to, subject, body, attachments=attachments)
|
sendMail(self, to, subject, body, attachments=attachments)
|
||||||
|
|
||||||
def formatDate(self, date, withHour=True):
|
def formatDate(self, date, format=None, withHour=True, language=None):
|
||||||
'''Check doc @ToolMixin::formatDate.'''
|
'''Check doc @ToolMixin::formatDate.'''
|
||||||
if not date: return
|
if not date: return
|
||||||
return self.o.formatDate(date, withHour=withHour)
|
return self.o.formatDate(date, format, withHour, language)
|
||||||
|
|
||||||
def getUserName(self, login=None, normalized=False):
|
def getUserName(self, login=None, normalized=False):
|
||||||
return self.o.getUserName(login=login, normalized=normalized)
|
return self.o.getUserName(login=login, normalized=normalized)
|
||||||
|
|
|
@ -43,10 +43,11 @@ class TranslationWrapper(AbstractWrapper):
|
||||||
if field.type == 'Computed': name = field.name[:-6]
|
if field.type == 'Computed': name = field.name[:-6]
|
||||||
else: name = field.name
|
else: name = field.name
|
||||||
# Get the source message
|
# Get the source message
|
||||||
sourceLanguage = self.o.getProductConfig(True).sourceLanguage
|
obj = self.o
|
||||||
|
sourceLanguage = obj.getProductConfig(True).sourceLanguage
|
||||||
sourceTranslation = getattr(tool.o, sourceLanguage).appy()
|
sourceTranslation = getattr(tool.o, sourceLanguage).appy()
|
||||||
sourceMsg = getattr(sourceTranslation, name)
|
sourceMsg = getattr(sourceTranslation, name)
|
||||||
if field.isEmptyValue(sourceMsg): return False
|
if field.isEmptyValue(obj, sourceMsg): return
|
||||||
return True
|
return True
|
||||||
|
|
||||||
poReplacements = ( ('\r\n', '<br/>'), ('\n', '<br/>'), ('"', '\\"') )
|
poReplacements = ( ('\r\n', '<br/>'), ('\n', '<br/>'), ('"', '\\"') )
|
||||||
|
|
|
@ -788,7 +788,7 @@ class AbstractWrapper(object):
|
||||||
obj = self.o
|
obj = self.o
|
||||||
if hasattr(obj.aq_base, name):
|
if hasattr(obj.aq_base, name):
|
||||||
field = obj.getAppyType(name)
|
field = obj.getAppyType(name)
|
||||||
return field.isEmptyValue(getattr(obj, name))
|
return field.isEmptyValue(obj, getattr(obj, name))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def isTemp(self):
|
def isTemp(self):
|
||||||
|
|
|
@ -72,6 +72,17 @@ def cleanFolder(folder, exts=extsToClean, folders=(), verbose=False):
|
||||||
if verbose: print('Removing folder %s...' % toDelete)
|
if verbose: print('Removing folder %s...' % toDelete)
|
||||||
FolderDeleter.delete(toDelete)
|
FolderDeleter.delete(toDelete)
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
def resolvePath(path):
|
||||||
|
'''p_path is a file path that can contain occurences of "." and "..". This
|
||||||
|
function resolves them and procuces a minimal path.'''
|
||||||
|
res = []
|
||||||
|
for elem in path.split(os.sep):
|
||||||
|
if elem == '.': pass
|
||||||
|
elif elem == '..': res.pop()
|
||||||
|
else: res.append(elem)
|
||||||
|
return os.sep.join(res)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
def copyFolder(source, dest, cleanDest=False):
|
def copyFolder(source, dest, cleanDest=False):
|
||||||
'''Copies the content of folder p_source to folder p_dest. p_dest is
|
'''Copies the content of folder p_source to folder p_dest. p_dest is
|
||||||
|
|
Loading…
Reference in a new issue