appy.gen: generalized use of appy.Object; existence of a field value (that triggers search for a default value) is now based on Type.isEmptyValue, and not '==None'; bugfix with default values for List fields; prevent search icon to be shown for a Ref when there is no linked object; appy.pod: added class appy.pod.parts.OdtTable that allows to create a complex (ie, with a dynamic number of columns) table programmatically (to be imported with a statement 'do ... from'); appy.shared.diff: improvements in the multiple XHTML diff; appy.shared.xml_parser.XmlMarshaller: support for default namespaces and 'any' tags.
This commit is contained in:
parent
1ebcbb7b34
commit
3ab6cec7d6
9 changed files with 147 additions and 68 deletions
|
@ -1,11 +1,12 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# ------------------------------------------------------------------------------
|
||||
import re, time, copy, sys, types, os, os.path, mimetypes, string, StringIO
|
||||
from appy import Object
|
||||
from appy.gen.layout import Table
|
||||
from appy.gen.layout import defaultFieldLayouts
|
||||
from appy.gen.po import PoMessage
|
||||
from appy.gen.utils import sequenceTypes, GroupDescr, Keywords, FileWrapper, \
|
||||
getClassName, SomeObjects, AppyObject
|
||||
getClassName, SomeObjects
|
||||
import appy.pod
|
||||
from appy.pod.renderer import Renderer
|
||||
from appy.shared.data import countries
|
||||
|
@ -16,7 +17,7 @@ r, w, d = ('read', 'write', 'delete')
|
|||
digit = re.compile('[0-9]')
|
||||
alpha = re.compile('[a-zA-Z0-9]')
|
||||
letter = re.compile('[a-zA-Z]')
|
||||
nullValues = (None, '', ' ')
|
||||
nullValues = (None, '', [])
|
||||
validatorTypes = (types.FunctionType, types.UnboundMethodType,
|
||||
type(re.compile('')))
|
||||
emptyTuple = ()
|
||||
|
@ -729,7 +730,7 @@ class Type:
|
|||
def getValue(self, obj):
|
||||
'''Gets, on_obj, the value conforming to self's type definition.'''
|
||||
value = getattr(obj.aq_base, self.name, None)
|
||||
if (value == None):
|
||||
if self.isEmptyValue(value):
|
||||
# If there is no value, get the default value if any
|
||||
if not self.editDefault:
|
||||
# Return self.default, of self.default() if it is a method
|
||||
|
@ -2243,10 +2244,6 @@ class List(Type):
|
|||
for n, field in self.fields:
|
||||
if n == name: return field
|
||||
|
||||
def isEmptyValue(self, value, obj=None):
|
||||
'''Returns True if the p_value must be considered as an empty value.'''
|
||||
return not value
|
||||
|
||||
def getRequestValue(self, request):
|
||||
'''Concatenates the list from distinct form elements in the request.'''
|
||||
prefix = self.name + '*' + self.fields[0][0] + '*'
|
||||
|
@ -2254,7 +2251,7 @@ class List(Type):
|
|||
for key in request.keys():
|
||||
if not key.startswith(prefix): continue
|
||||
# I have found a row. Gets its index
|
||||
row = AppyObject()
|
||||
row = Object()
|
||||
rowIndex = int(key.split('*')[-1])
|
||||
if rowIndex == -1: continue # Ignore the template row.
|
||||
for name, field in self.fields:
|
||||
|
@ -2271,10 +2268,6 @@ class List(Type):
|
|||
keys = res.keys()
|
||||
keys.sort()
|
||||
res = [res[key] for key in keys]
|
||||
print 'REQUEST VALUE FOR LIST (%d)' % len(res)
|
||||
for value in res:
|
||||
for k, v in value.__dict__.iteritems():
|
||||
print k, '=', v
|
||||
# I store in the request this computed value. This way, when individual
|
||||
# subFields will need to get their value, they will take it from here,
|
||||
# instead of taking it from the specific request key. Indeed, specific
|
||||
|
@ -2290,14 +2283,13 @@ class List(Type):
|
|||
setattr(v, name, field.getStorableValue(getattr(v, name)))
|
||||
return value
|
||||
|
||||
def getInnerValue(self, obj, name, i):
|
||||
def getInnerValue(self, outerValue, name, i):
|
||||
'''Returns the value of inner field named p_name in row number p_i
|
||||
with the list of values from this field on p_obj.'''
|
||||
within the whole list of values p_outerValue.'''
|
||||
if i == -1: return ''
|
||||
value = getattr(obj, self.name, None)
|
||||
if not value: return ''
|
||||
if i >= len(value): return ''
|
||||
return getattr(value[i], name, '')
|
||||
if not outerValue: return ''
|
||||
if i >= len(outerValue): return ''
|
||||
return getattr(outerValue[i], name, '')
|
||||
|
||||
# Workflow-specific types and default workflows --------------------------------
|
||||
appyToZopePermissions = {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
# ------------------------------------------------------------------------------
|
||||
import os, os.path, sys, types, mimetypes, urllib, cgi
|
||||
from appy import Object
|
||||
import appy.gen
|
||||
from appy.gen import Type, String, Selection, Role, No, WorkflowAnonymous, \
|
||||
Transition, Permission
|
||||
|
@ -206,9 +207,9 @@ class BaseMixin:
|
|||
return self.goto(urlBack)
|
||||
|
||||
# Object for storing validation errors
|
||||
errors = AppyObject()
|
||||
errors = Object()
|
||||
# Object for storing the (converted) values from the request
|
||||
values = AppyObject()
|
||||
values = Object()
|
||||
|
||||
# Trigger field-specific validation
|
||||
self.intraFieldValidation(errors, values)
|
||||
|
@ -435,7 +436,8 @@ class BaseMixin:
|
|||
# broken on returned object.
|
||||
return getattr(self, methodName, None)
|
||||
|
||||
def getFieldValue(self, name, onlyIfSync=False, layoutType=None):
|
||||
def getFieldValue(self, name, onlyIfSync=False, layoutType=None,
|
||||
outerValue=None):
|
||||
'''Returns the database value of field named p_name for p_self.
|
||||
If p_onlyIfSync is True, it returns the value only if appyType can be
|
||||
retrieved in synchronous mode.'''
|
||||
|
@ -445,7 +447,8 @@ class BaseMixin:
|
|||
if '*' not in name: return appyType.getValue(self)
|
||||
# The field is an inner field from a List.
|
||||
listName, name, i = name.split('*')
|
||||
return self.getAppyType(listName).getInnerValue(self, name, int(i))
|
||||
listType = self.getAppyType(listName)
|
||||
return listType.getInnerValue(outerValue, name, int(i))
|
||||
|
||||
def getFormattedFieldValue(self, name, value):
|
||||
'''Gets a nice, string representation of p_value which is a value from
|
||||
|
|
|
@ -145,7 +145,7 @@
|
|||
</tal:noObject>
|
||||
|
||||
<tal:comment replace="nothing">If there is an object...</tal:comment>
|
||||
<tal:objectIsPresent condition="objs">
|
||||
<tal:objectIsPresent condition="python: objs">
|
||||
<tal:obj repeat="obj objs">
|
||||
<td tal:define="includeShownInfo python:True"><metal:showObjectTitle use-macro="app/skyn/widgets/ref/macros/objectTitle" /></td>
|
||||
</tal:obj>
|
||||
|
@ -161,7 +161,7 @@
|
|||
(<span tal:replace="totalNumber"/>)
|
||||
<metal:plusIcon use-macro="app/skyn/widgets/ref/macros/plusIcon"/>
|
||||
<tal:comment replace="nothing">The search icon if field is queryable</tal:comment>
|
||||
<a tal:condition="appyType/queryable"
|
||||
<a tal:condition="python: objs and appyType['queryable']"
|
||||
tal:attributes="href python: '%s/skyn/search?type_name=%s&ref=%s:%s' % (tool.absolute_url(), linkedPortalType, contextObj.UID(), appyType['name'])">
|
||||
<img src="search.gif" tal:attributes="title python: _('search_objects')"/></a>
|
||||
</legend>
|
||||
|
|
|
@ -59,7 +59,8 @@
|
|||
layout python: widget['layouts'][layoutType];
|
||||
name widgetName| widget/name;
|
||||
sync python: widget['sync'][layoutType];
|
||||
rawValue python: contextObj.getFieldValue(name, onlyIfSync=True, layoutType=layoutType);
|
||||
outerValue value|nothing;
|
||||
rawValue python: contextObj.getFieldValue(name,onlyIfSync=True,layoutType=layoutType,outerValue=outerValue);
|
||||
value python: contextObj.getFormattedFieldValue(name, rawValue);
|
||||
requestValue python: contextObj.getRequestFieldValue(name);
|
||||
inRequest python: request.has_key(name);
|
||||
|
|
|
@ -158,9 +158,6 @@ def produceNiceMessage(msg):
|
|||
res += c
|
||||
return res
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
class AppyObject: pass
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
class SomeObjects:
|
||||
'''Represents a bunch of objects retrieved from a reference or a query in
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue