Bugfix in the search engine, implemented float fields in the advanced search, execute batchjobs as Zope admin.
This commit is contained in:
parent
d192496c88
commit
bdc7baf25a
|
@ -247,10 +247,10 @@ class ZodbBackupScript:
|
||||||
# Check command format
|
# Check command format
|
||||||
if options.command:
|
if options.command:
|
||||||
parts = options.command.split(':')
|
parts = options.command.split(':')
|
||||||
if len(parts) not in (3,4):
|
if len(parts) not in (4,5):
|
||||||
raise BackupError('Command format must be ' \
|
raise BackupError('Command format must be ' \
|
||||||
'<PloneInstancePath>:<ApplicationName>:<ToolMethodName>' \
|
'<ZopeAdmin><PloneInstancePath>:<ApplicationName>:' \
|
||||||
'[:<args>]')
|
'<ToolMethodName>[:<args>]')
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
optParser = OptionParser(usage=ZodbBackupScript.__doc__)
|
optParser = OptionParser(usage=ZodbBackupScript.__doc__)
|
||||||
|
@ -313,10 +313,11 @@ class ZodbBackupScript:
|
||||||
type='string')
|
type='string')
|
||||||
optParser.add_option("-c", "--command", dest="command",
|
optParser.add_option("-c", "--command", dest="command",
|
||||||
help="Command to execute while Zope is running. It must have the " \
|
help="Command to execute while Zope is running. It must have the " \
|
||||||
"following format: <PloneInstancePath>:<ApplicationName>:" \
|
"following format: <ZopeAdmin>:<PloneInstancePath>:" \
|
||||||
"<ToolMethodName>[:<args>]. <PloneInstancePath> is the path, " \
|
"<ApplicationName>:<ToolMethodName>[:<args>]. <ZopeAdmin> is the " \
|
||||||
"within Zope, to the Plone Site object (if not at the root of " \
|
"user name of the Zope administrator; <PloneInstancePath> is the " \
|
||||||
"the Zope hierarchy, use '/' as folder separator); " \
|
"path, within Zope, to the Plone Site object (if not at the " \
|
||||||
|
"root of the Zope hierarchy, use '/' as folder separator); " \
|
||||||
"<ApplicationName> is the name of the Appy application; " \
|
"<ApplicationName> is the name of the Appy application; " \
|
||||||
"<ToolMethodName> is the name of the method to call on the tool " \
|
"<ToolMethodName> is the name of the method to call on the tool " \
|
||||||
"in this Appy application; (optional) <args> are the arguments " \
|
"in this Appy application; (optional) <args> are the arguments " \
|
||||||
|
|
25
bin/job.py
25
bin/job.py
|
@ -1,8 +1,9 @@
|
||||||
'''job.py must be executed by a "zopectl run" command and, as single arg,
|
'''job.py must be executed by a "zopectl run" command and, as single arg,
|
||||||
must get a string with the following format:
|
must get a string with the following format:
|
||||||
|
|
||||||
<PloneInstancePath>:<ApplicationName>:<ToolMethodName>[:<args>].
|
<ZopeAdmin><PloneInstancePath>:<ApplicationName>:<ToolMethodName>[:<args>].
|
||||||
|
|
||||||
|
<ZopeAdmin> is the userName of the Zope administrator for this instance.
|
||||||
<PloneInstancePath> is the path, within Zope, to the Plone Site object (if
|
<PloneInstancePath> is the path, within Zope, to the Plone Site object (if
|
||||||
not at the root of the Zope hierarchy, use '/' as
|
not at the root of the Zope hierarchy, use '/' as
|
||||||
folder separator);
|
folder separator);
|
||||||
|
@ -16,7 +17,8 @@
|
||||||
are supported). Several arguments must be separated by '*'.'''
|
are supported). Several arguments must be separated by '*'.'''
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import sys
|
import sys, transaction
|
||||||
|
|
||||||
# Check that job.py is called with the right parameters.
|
# Check that job.py is called with the right parameters.
|
||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
print 'job.py was called with wrong args.'
|
print 'job.py was called with wrong args.'
|
||||||
|
@ -24,20 +26,26 @@ if len(sys.argv) != 2:
|
||||||
else:
|
else:
|
||||||
command = sys.argv[1]
|
command = sys.argv[1]
|
||||||
parts = command.split(':')
|
parts = command.split(':')
|
||||||
if len(parts) not in (3,4):
|
if len(parts) not in (4,5):
|
||||||
print 'job.py was called with wrong args.'
|
print 'job.py was called with wrong args.'
|
||||||
print __doc__
|
print __doc__
|
||||||
else:
|
else:
|
||||||
# Unwrap parameters
|
# Unwrap parameters
|
||||||
if len(parts) == 3:
|
if len(parts) == 4:
|
||||||
plonePath, appName, toolMethod = parts
|
zopeUser, plonePath, appName, toolMethod = parts
|
||||||
args = ()
|
args = ()
|
||||||
else:
|
else:
|
||||||
plonePath, appName, toolMethod, args = parts
|
zopeUser, plonePath, appName, toolMethod, args = parts
|
||||||
# Zope was initialized in a minimal way. Complete Zope and Plone
|
# Zope was initialized in a minimal way. Complete Zope install.
|
||||||
# installation.
|
|
||||||
from Testing import makerequest
|
from Testing import makerequest
|
||||||
app = makerequest.makerequest(app)
|
app = makerequest.makerequest(app)
|
||||||
|
# Log as Zope admin
|
||||||
|
from AccessControl.SecurityManagement import newSecurityManager
|
||||||
|
user = app.acl_users.getUserById(zopeUser)
|
||||||
|
if not hasattr(user, 'aq_base'):
|
||||||
|
user = user.__of__(uf)
|
||||||
|
newSecurityManager(None, user)
|
||||||
|
|
||||||
# Get the Plone site
|
# Get the Plone site
|
||||||
ploneSite = app # Initialised with the Zope root object.
|
ploneSite = app # Initialised with the Zope root object.
|
||||||
for elem in plonePath.split('/'):
|
for elem in plonePath.split('/'):
|
||||||
|
@ -48,4 +56,5 @@ else:
|
||||||
# Execute the method on the tool
|
# Execute the method on the tool
|
||||||
if args: args = args.split('*')
|
if args: args = args.split('*')
|
||||||
exec 'tool.%s(*args)' % toolMethod
|
exec 'tool.%s(*args)' % toolMethod
|
||||||
|
transaction.commit()
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -176,7 +176,12 @@ class ToolMixin(AbstractMixin):
|
||||||
v = fieldValue[:-1]
|
v = fieldValue[:-1]
|
||||||
params[attrName] = {'query':(v,v+'Z'), 'range':'minmax'}
|
params[attrName] = {'query':(v,v+'Z'), 'range':'minmax'}
|
||||||
elif type(fieldValue) in sequenceTypes:
|
elif type(fieldValue) in sequenceTypes:
|
||||||
# We have a range of values instead of a single value
|
if fieldValue and isinstance(fieldValue[0], basestring):
|
||||||
|
# We have a list of string values (ie: we need to
|
||||||
|
# search v1 or v2 or...)
|
||||||
|
params[attrName] = fieldValue
|
||||||
|
else:
|
||||||
|
# We have a range of (int, float, DateTime...) values
|
||||||
minv, maxv = fieldValue
|
minv, maxv = fieldValue
|
||||||
rangev = 'minmax'
|
rangev = 'minmax'
|
||||||
queryv = fieldValue
|
queryv = fieldValue
|
||||||
|
@ -405,9 +410,9 @@ class ToolMixin(AbstractMixin):
|
||||||
'''Returns True if request value in key p_key can be considered as
|
'''Returns True if request value in key p_key can be considered as
|
||||||
empty.'''
|
empty.'''
|
||||||
rq = self.REQUEST.form
|
rq = self.REQUEST.form
|
||||||
if key.endswith('*int'):
|
if key.endswith('*int') or key.endswith('*float'):
|
||||||
# We return True if "from" AND "to" values are empty.
|
# We return True if "from" AND "to" values are empty.
|
||||||
toKey = '%s_to' % key[2:-4]
|
toKey = '%s_to' % key[2:key.find('*')]
|
||||||
return not rq[key].strip() and not rq[toKey].strip()
|
return not rq[key].strip() and not rq[toKey].strip()
|
||||||
elif key.endswith('*date'):
|
elif key.endswith('*date'):
|
||||||
# We return True if "from" AND "to" values are empty. A value is
|
# We return True if "from" AND "to" values are empty. A value is
|
||||||
|
@ -459,14 +464,16 @@ class ToolMixin(AbstractMixin):
|
||||||
attrName, attrType = attrName.split('*')
|
attrName, attrType = attrName.split('*')
|
||||||
if attrType == 'bool':
|
if attrType == 'bool':
|
||||||
exec 'attrValue = %s' % attrValue
|
exec 'attrValue = %s' % attrValue
|
||||||
elif attrType == 'int':
|
elif attrType in ('int', 'float'):
|
||||||
# Get the "from" value
|
# Get the "from" value
|
||||||
if not attrValue.strip(): attrValue = None
|
if not attrValue.strip(): attrValue = None
|
||||||
else: attrValue = int(attrValue)
|
else:
|
||||||
|
exec 'attrValue = %s(attrValue)' % attrType
|
||||||
# Get the "to" value
|
# Get the "to" value
|
||||||
toValue = rq.form['%s_to' % attrName[2:]].strip()
|
toValue = rq.form['%s_to' % attrName[2:]].strip()
|
||||||
if not toValue: toValue = None
|
if not toValue: toValue = None
|
||||||
else: toValue = int(toValue)
|
else:
|
||||||
|
exec 'toValue = %s(toValue)' % attrType
|
||||||
attrValue = (attrValue, toValue)
|
attrValue = (attrValue, toValue)
|
||||||
elif attrType == 'date':
|
elif attrType == 'date':
|
||||||
prefix = attrName[2:]
|
prefix = attrName[2:]
|
||||||
|
@ -703,6 +710,6 @@ class ToolMixin(AbstractMixin):
|
||||||
res = []
|
res = []
|
||||||
for v in validator:
|
for v in validator:
|
||||||
text = self.translate('%s_list_%s' % (appyType['label'], v))
|
text = self.translate('%s_list_%s' % (appyType['label'], v))
|
||||||
res.append((v, self.truncate(text, 50)))
|
res.append((v, self.truncate(text, 30)))
|
||||||
return res
|
return res
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -11,7 +11,15 @@
|
||||||
</metal:searchInteger>
|
</metal:searchInteger>
|
||||||
|
|
||||||
<metal:searchFloat define-macro="searchFloat">
|
<metal:searchFloat define-macro="searchFloat">
|
||||||
<p tal:content="fieldName">Hello</p>
|
<label tal:content="python: tool.translate(appyType['label'])"></label><br>
|
||||||
|
<tal:from define="fromName python: '%s*float' % widgetName">
|
||||||
|
<label tal:attributes="for fromName" tal:content="python: tool.translate('search_from')"></label>
|
||||||
|
<input type="text" tal:attributes="name fromName" size="4"/>
|
||||||
|
</tal:from>
|
||||||
|
<tal:to define="toName python: '%s_to' % fieldName">
|
||||||
|
<label tal:attributes="for toName" tal:content="python: tool.translate('search_to')"></label>
|
||||||
|
<input type="text" tal:attributes="name toName" size="4"/>
|
||||||
|
</tal:to><br/>
|
||||||
</metal:searchFloat>
|
</metal:searchFloat>
|
||||||
|
|
||||||
<metal:searchString define-macro="searchString">
|
<metal:searchString define-macro="searchString">
|
||||||
|
|
|
@ -283,7 +283,7 @@ class AbstractWrapper:
|
||||||
maxResults=maxResults, noSecurity=noSecurity)
|
maxResults=maxResults, noSecurity=noSecurity)
|
||||||
return [o.appy() for o in res['objects']]
|
return [o.appy() for o in res['objects']]
|
||||||
|
|
||||||
def count(self, klass, **fields):
|
def count(self, klass, noSecurity=False, **fields):
|
||||||
'''Identical to m_search above, but returns the number of objects that
|
'''Identical to m_search above, but returns the number of objects that
|
||||||
match the search instead of returning the objects themselves. Use
|
match the search instead of returning the objects themselves. Use
|
||||||
this method instead of writing len(self.search(...)).'''
|
this method instead of writing len(self.search(...)).'''
|
||||||
|
@ -291,7 +291,7 @@ class AbstractWrapper:
|
||||||
contentType = flavour.o.getPortalType(klass)
|
contentType = flavour.o.getPortalType(klass)
|
||||||
search = Search('customSearch', **fields)
|
search = Search('customSearch', **fields)
|
||||||
res = self.tool.o.executeQuery(contentType,flavour.number,search=search,
|
res = self.tool.o.executeQuery(contentType,flavour.number,search=search,
|
||||||
brainsOnly=True)
|
brainsOnly=True, noSecurity=noSecurity)
|
||||||
if res: return res._len # It is a LazyMap instance
|
if res: return res._len # It is a LazyMap instance
|
||||||
else: return 0
|
else: return 0
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue