Support for Berkeley DB XML 2.1.
This commit breaks existing code in third party apps such as Amedes.
This commit is contained in:
parent
3e3e524358
commit
2a65f76d3e
|
@ -27,7 +27,6 @@
|
|||
|
||||
import os
|
||||
|
||||
import bsddb.db
|
||||
import dbxml
|
||||
import libxml2
|
||||
import urllib
|
||||
|
@ -53,63 +52,42 @@ class DbXmlContainerHolder(dataholders.DataHolder):
|
|||
isTemporary = False
|
||||
isUriDirectory = True
|
||||
mimeType = "application/x-dbxml"
|
||||
queryContext = None
|
||||
updateContext = None
|
||||
|
||||
def __del__(self):
|
||||
if self.container is not None:
|
||||
if self.container.isOpen():
|
||||
logs.info("DbXml Container was not closed! Closing it.")
|
||||
self.container.close(0)
|
||||
|
||||
def __init__(self, *arguments, **keywords):
|
||||
if self._dbxmlContainerHolderInited:
|
||||
return
|
||||
self._dbxmlContainerHolderInited = True
|
||||
|
||||
def __init__(self, container, *arguments, **keywords):
|
||||
super(DbXmlContainerHolder, self).__init__(*arguments, **keywords)
|
||||
# FIXME : we assume self.getAbsolutePath() is a correct .dbxml filename
|
||||
self.container = dbxml.XmlContainer(None, self.getAbsolutePath())
|
||||
|
||||
self.queryContext = dbxml.XmlQueryContext()
|
||||
self.container = container
|
||||
self.queryContext = container.getManager().createQueryContext()
|
||||
for ns in namespaces.nsList:
|
||||
self.queryContext.setNamespace(ns.name, ns.uri)
|
||||
self.updateContext = container.getManager().createUpdateContext()
|
||||
|
||||
def addDocument(self, documentSource, name=""):
|
||||
def addDocument(self, contents, name=""):
|
||||
""" appends a document to the container
|
||||
|
||||
returns the new XmlDocument
|
||||
returns the new XmlDocument name
|
||||
"""
|
||||
doc = dbxml.XmlDocument()
|
||||
doc.setContent(documentSource)
|
||||
doc.setName(name)
|
||||
self.container.open(None, 0)
|
||||
try:
|
||||
self.container.putDocument(None, doc)
|
||||
name = self.container.putDocument(name, contents, self.updateContext, name and DBXML_GEN_NAME or 0)
|
||||
except RuntimeError, e:
|
||||
logs.error("Could not put document in container: %s" % e)
|
||||
logs.debug(doc.getContent())
|
||||
self.container.close(0)
|
||||
logs.debug(contents,)
|
||||
raise
|
||||
self.container.close(0)
|
||||
return doc
|
||||
return name
|
||||
|
||||
def close(self):
|
||||
self.container.close(0)
|
||||
|
||||
def deleteDocument(self, documentId):
|
||||
def deleteDocument(self, name):
|
||||
""" removes a document from the container
|
||||
|
||||
Handles HTTP GET.
|
||||
"""
|
||||
self.container.open(None, 0)
|
||||
self.container.deleteDocument(None, documentId)
|
||||
self.container.close(0)
|
||||
self.container.deleteDocument(name, self.updateContext)
|
||||
return self.doHttpGet()
|
||||
|
||||
def docSelect(self, xpathExpression, *uriPathFragments):
|
||||
"""
|
||||
Handles HTTP GET.
|
||||
"""
|
||||
|
||||
command = environs.getVar("httpCommand")
|
||||
if command != "GET":
|
||||
raise faults.PathNotFound("")
|
||||
|
@ -129,11 +107,11 @@ class DbXmlContainerHolder(dataholders.DataHolder):
|
|||
return super(DbXmlContainerHolder, self).doHttpGet()
|
||||
|
||||
def generateXml(self, layout):
|
||||
result = self.getDbXmlDocumentResultFromXpath("*")
|
||||
result = self.getDbXmlDocumentResultFromXpath("/*")
|
||||
return result.generateXml(layout)
|
||||
|
||||
def generateXmlDocument(self):
|
||||
result = self.getDbXmlDocumentResultFromXpath("*")
|
||||
result = self.getDbXmlDocumentResultFromXpath("/*")
|
||||
return result.generateXmlDocument()
|
||||
|
||||
def getContainer(self):
|
||||
|
@ -152,19 +130,17 @@ class DbXmlContainerHolder(dataholders.DataHolder):
|
|||
results = self.getResultFetchedFromXpath(xpathExpression)
|
||||
return results.size()
|
||||
|
||||
def getDbXmlDocument(self, id):
|
||||
""" returns container document number <id>
|
||||
def getDbXmlDocument(self, name):
|
||||
""" returns container document <name>
|
||||
|
||||
the return type is dbxml.DbXmlDocument
|
||||
the return type is dbxml.XmlDocument
|
||||
or None if the document doesn't exist
|
||||
"""
|
||||
document = None
|
||||
self.container.open(None, dbxml.DB_RDONLY)
|
||||
try:
|
||||
document = self.container.getDocument(None, int(id))
|
||||
document = self.container.getDocument(name, 0)
|
||||
except RuntimeError:
|
||||
pass
|
||||
self.container.close(0)
|
||||
return document
|
||||
|
||||
def getDbXmlDocumentResultFromXpath(self, xpathExpression):
|
||||
|
@ -172,11 +148,12 @@ class DbXmlContainerHolder(dataholders.DataHolder):
|
|||
resultNode = resultDocument.node.newTextChild(None, "dbXmlDocumentResult", None)
|
||||
namespace = resultNode.newNs(namespaces.yep.uri, namespaces.yep.name)
|
||||
resultNode.setNs(namespace)
|
||||
results = self.getResultFetchedFromXpath(xpathExpression)
|
||||
results = self.getResultCursorFromXpath(xpathExpression)
|
||||
results.reset()
|
||||
for value in results:
|
||||
document = value.asDocument()
|
||||
childNode = resultNode.newChild(None, "item", None)
|
||||
childNode.newProp("id", str(document.getID()))
|
||||
childNode.newProp("id", self.getActionUri(document.getName()))
|
||||
childNode.newProp("name", document.getName())
|
||||
return resultDocument
|
||||
|
||||
|
@ -196,7 +173,17 @@ class DbXmlContainerHolder(dataholders.DataHolder):
|
|||
childNode.addChild(doc.getRootElement())
|
||||
return resultDocument
|
||||
|
||||
def getIds(self, xpathExpression = "*"):
|
||||
def getFileSystemPath(self):
|
||||
return os.path.normpath(
|
||||
os.path.join(
|
||||
self.container.getManager().getHome(), self.container.getName()
|
||||
)
|
||||
)
|
||||
|
||||
def getConfigDoc(self):
|
||||
return None
|
||||
|
||||
def getIds(self, xpathExpression = "/*"):
|
||||
""" returns an id list of all documents
|
||||
|
||||
id is not the numeric dbxml:id, but the Uri of the document
|
||||
|
@ -205,9 +192,9 @@ class DbXmlContainerHolder(dataholders.DataHolder):
|
|||
"""
|
||||
uriBase = self.getUriAbsolutePath()
|
||||
results = self.getResultFetchedFromXpath(xpathExpression)
|
||||
return ["%s/%s" % (uriBase, value.asDocument().getID()) for value in results]
|
||||
return ["%s/%s" % (uriBase, value.asDocument().getName()) for value in results]
|
||||
|
||||
def getNames(self, xpathExpression = "*"):
|
||||
def getNames(self, xpathExpression = "/*"):
|
||||
""" returns a hash {id: name} of all documents
|
||||
|
||||
id is not the numeric dbxml:id, but the Uri of the document
|
||||
|
@ -219,25 +206,23 @@ class DbXmlContainerHolder(dataholders.DataHolder):
|
|||
results = self.getResultFetchedFromXpath(xpathExpression)
|
||||
for value in results:
|
||||
document = value.asDocument()
|
||||
uri = "%s/%s" % (uriBase, document.getID())
|
||||
name = document.getName()
|
||||
uri = "%s/%s" % (uriBase, name)
|
||||
names[uri] = name
|
||||
return names
|
||||
|
||||
def getPresence(self, xpathExpression):
|
||||
""" Returns whether at least one document matches xpathExpression.
|
||||
"""
|
||||
presence = False
|
||||
for value in self.getResultCursorFromXpath(xpathExpression):
|
||||
presence = True
|
||||
break
|
||||
self.close()
|
||||
return presence
|
||||
results = self.getResultCursorFromXpath(xpathExpression)
|
||||
for value in result:
|
||||
return True
|
||||
return False
|
||||
|
||||
def getIdsAndNames(self, xpathExpression = "*"):
|
||||
def getIdsAndNames(self, xpathExpression = "/*"):
|
||||
""" returns a tuple (id, name) list of all documents
|
||||
|
||||
id is not the numeric dbxml:id, but the Uri of the document
|
||||
id is the Uri of the document
|
||||
|
||||
argument xpathExpression can be specified to restrict the list
|
||||
"""
|
||||
|
@ -246,52 +231,40 @@ class DbXmlContainerHolder(dataholders.DataHolder):
|
|||
results = self.getResultFetchedFromXpath(xpathExpression)
|
||||
for value in results:
|
||||
document = value.asDocument()
|
||||
uri = "%s/%s" % (uriBase, document.getID())
|
||||
uri = "%s/%s" % (uriBase, document.getName())
|
||||
name = document.getName()
|
||||
documentList.append(
|
||||
(uri, name)
|
||||
)
|
||||
return documentList
|
||||
|
||||
def getIdsOnly(self, xpathExpression = "*"):
|
||||
""" returns an id list of all documents
|
||||
|
||||
id is the numeric dbxml:id
|
||||
def getIdsOnly(self, xpathExpression = "/*"):
|
||||
""" returns a name list of all documents
|
||||
|
||||
argument xpathExpression can be specified to restrict the list
|
||||
"""
|
||||
results = self.getResultFetchedFromXpath(xpathExpression)
|
||||
return [value.asDocument().getID() for value in results]
|
||||
return [value.asDocument().getName() for value in results]
|
||||
|
||||
def getResultCursorFromXpath(self, xpathExpression, returnType = dbxml.XmlQueryContextPtr.ResultDocuments):
|
||||
def getResultCursorFromXpath(self, xpathExpression, returnType = dbxml.XmlQueryContext.LiveValues):
|
||||
""" Returns a raw dbxml.XmlResults instance, leaving the data in the container.
|
||||
|
||||
Result contents are not loaded in memory, but waiting to be fetched iteratively.
|
||||
The calling program MUST call close() after this method, since we can not close the container here.
|
||||
|
||||
Set returnType argument to dbxml.XmlQueryContextPtr.ResultValues to get nodes rather than documents
|
||||
"""
|
||||
context = self.queryContext
|
||||
context.setReturnType(returnType)
|
||||
context.setEvaluationType(dbxml.XmlQueryContext.Lazy)
|
||||
self.container.open(None, dbxml.DB_RDONLY)
|
||||
results = self.container.queryWithXPath(None, xpathExpression, context)
|
||||
results = self.container.getManager().query("collection('%s')%s" % (self.container.getName(), xpathExpression), context)
|
||||
return results
|
||||
|
||||
def getResultFetchedFromXpath(self, xpathExpression, returnType = dbxml.XmlQueryContextPtr.ResultDocuments):
|
||||
def getResultFetchedFromXpath(self, xpathExpression, returnType = dbxml.XmlQueryContext.LiveValues):
|
||||
""" Returns a raw dbxml.XmlResults instance, with all data fetched from the container.
|
||||
|
||||
All data is loaded in memory.
|
||||
Consider using getResultCursorFromXpath instead of this method if you expect a large result.
|
||||
|
||||
Set returnType argument to dbxml.XmlQueryContextPtr.ResultValues to get nodes rather than documents
|
||||
"""
|
||||
context = self.queryContext
|
||||
context.setReturnType(returnType)
|
||||
context.setEvaluationType(dbxml.XmlQueryContext.Eager)
|
||||
self.container.open(None, dbxml.DB_RDONLY)
|
||||
results = self.container.queryWithXPath(None, xpathExpression, context)
|
||||
self.container.close(0)
|
||||
results = self.container.getManager().query("collection('%s')%s" % (self.container.getName(), xpathExpression), context)
|
||||
results.reset()
|
||||
return results
|
||||
|
||||
|
@ -302,31 +275,26 @@ class DbXmlContainerHolder(dataholders.DataHolder):
|
|||
return [value.asString() for value in results]
|
||||
|
||||
def list(self):
|
||||
return self.docSelect("*")
|
||||
return self.docSelect("/*")
|
||||
|
||||
def nodeSelect(self, xpathExpression, *uriPathFragments):
|
||||
"""
|
||||
Handles HTTP GET.
|
||||
"""
|
||||
|
||||
command = environs.getVar("httpCommand")
|
||||
if command != "GET":
|
||||
raise faults.PathNotFound("")
|
||||
|
||||
result = self.getDbXmlNodeResultFromXpath(xpathExpression)
|
||||
return result.checkAccessAndWalk(uriPathFragments, command, environs.getVar("instruction"))
|
||||
|
||||
def parsableXpath(self, xpath):
|
||||
""" returns True if the given xpath expression is parsable, False otherwise
|
||||
"""
|
||||
parsable = True
|
||||
self.container.open(None, dbxml.DB_RDONLY)
|
||||
try:
|
||||
self.container.parseXPathExpression(None, xpath, self.queryContext)
|
||||
self.container.getManager().prepare("collection('%s')%s" % (self.container.getName(), xpath), self.queryContext)
|
||||
except RuntimeError:
|
||||
parsable = False
|
||||
self.container.close(0)
|
||||
return parsable
|
||||
return False
|
||||
return True
|
||||
|
||||
def walkToAction(self, uriPathFragments, command = None, instruction = None):
|
||||
actionName = uriPathFragments[0]
|
||||
|
@ -380,12 +348,11 @@ class DbXmlContainerHolder(dataholders.DataHolder):
|
|||
|
||||
def walkToItem(self, uriPathFragments, command = None, instruction = None):
|
||||
itemName = uriPathFragments[0]
|
||||
if itemName.isdigit():
|
||||
document = self.getDbXmlDocument(itemName)
|
||||
if document:
|
||||
documentStation = DbXmlDocumentStation(
|
||||
document, previous = self, uriPathFragment = itemName)
|
||||
return documentStation, uriPathFragments[1:]
|
||||
document = self.getDbXmlDocument(itemName)
|
||||
if document:
|
||||
documentStation = DbXmlDocumentStation(
|
||||
document, previous = self, uriPathFragment = itemName)
|
||||
return documentStation, uriPathFragments[1:]
|
||||
return super(DbXmlContainerHolder, self).walkToItem(uriPathFragments, command, instruction)
|
||||
|
||||
|
||||
|
@ -393,7 +360,7 @@ class DbXmlDocumentConstructorStation(stations.HolderConstructorStation):
|
|||
def walk(self, uriPathFragments, command = None, instruction = None):
|
||||
namespaceUri = self.elementFeature.namespaceUri
|
||||
elementName = self.elementFeature.elementName
|
||||
document = dbxml.XmlDocument()
|
||||
document = self.getParent().container.getManager().createDocument()
|
||||
document.setContent("""\
|
||||
<?xml version="1.0"?>
|
||||
<%(elementName)s xmlns="%(namespaceUri)s"/>
|
||||
|
@ -432,10 +399,7 @@ class DbXmlDocumentStation(stations.AbstractStation, documents.AbstractDocument)
|
|||
def delete(self):
|
||||
""" Deletes the document from its container.
|
||||
"""
|
||||
container = self.getParent().getContainer()
|
||||
container.open(None, 0)
|
||||
container.deleteDocument(None, self.dbxmlDocument)
|
||||
container.close(0)
|
||||
self.getParent().getContainer().deleteDocument(self.dbxmlDocument.getName(), self.getParent().updateContext)
|
||||
|
||||
def doHttpGet(self):
|
||||
if not self.getInRawMode():
|
||||
|
@ -464,9 +428,7 @@ class DbXmlDocumentStation(stations.AbstractStation, documents.AbstractDocument)
|
|||
return super(DbXmlDocumentStation, self).doHttpPost()
|
||||
|
||||
def generatePlainText(self):
|
||||
# FIXME: The following line assumes that getContentAsString returns an
|
||||
# unicode string. If this is not the case, append ".decode("UTF-8")".
|
||||
return self.dbxmlDocument.getContentAsString()
|
||||
return self.dbxmlDocument.getContent()
|
||||
|
||||
def generateXml(self, layout):
|
||||
rootElement = self.getRootElement()
|
||||
|
@ -480,6 +442,9 @@ class DbXmlDocumentStation(stations.AbstractStation, documents.AbstractDocument)
|
|||
return rootElement.generateXmlDocument()
|
||||
return super(DbXmlDocumentStation, self).generateXmlDocument()
|
||||
|
||||
def getAbsolutePath(self):
|
||||
return os.path.normpath(os.path.join(self.getParent().getAbsolutePath(), self.dbxmlDocument.getName()))
|
||||
|
||||
def getBind(self, context, modelContext):
|
||||
return None
|
||||
|
||||
|
@ -490,7 +455,7 @@ class DbXmlDocumentStation(stations.AbstractStation, documents.AbstractDocument)
|
|||
return self
|
||||
|
||||
def getLocalId(self):
|
||||
return str(self.dbxmlDocument.getID())
|
||||
return self.dbxmlDocument.getName()
|
||||
|
||||
def getModelId(self):
|
||||
return None
|
||||
|
@ -504,7 +469,7 @@ class DbXmlDocumentStation(stations.AbstractStation, documents.AbstractDocument)
|
|||
return publicName
|
||||
|
||||
def outputHttpSource(self):
|
||||
data = self.dbxmlDocument.getContentAsString()
|
||||
data = self.dbxmlDocument.getContent()
|
||||
dataHolder = self.getDataHolder()
|
||||
environs.getVar("httpRequestHandler").outputData(
|
||||
data, mimeType = dataholders.mimeTypes[".xml"],
|
||||
|
@ -512,40 +477,40 @@ class DbXmlDocumentStation(stations.AbstractStation, documents.AbstractDocument)
|
|||
|
||||
def save(self):
|
||||
self.dbxmlDocument.setContent(self.serialize())
|
||||
name = self.getPublicName()
|
||||
if not name:
|
||||
element = self.getRootElement()
|
||||
try:
|
||||
name = element.getLabel()
|
||||
except AttributeError:
|
||||
name = ""
|
||||
self.dbxmlDocument.setName(name)
|
||||
container = self.getParent().getContainer()
|
||||
container.open(None, 0)
|
||||
if self.getLocalId() == "0":
|
||||
if self.isTemporary:
|
||||
name = self.getPublicName()
|
||||
if name is None:
|
||||
element = self.getRootElement()
|
||||
try:
|
||||
name = element.getLabel()
|
||||
except AttributeError:
|
||||
pass
|
||||
if name is not None:
|
||||
self.dbxmlDocument.setName(name)
|
||||
try:
|
||||
container.putDocument(None, self.dbxmlDocument)
|
||||
container.putDocument(
|
||||
self.dbxmlDocument,
|
||||
self.getParent().updateContext,
|
||||
name is None and dbxml.DBXML_GEN_NAME or 0
|
||||
)
|
||||
except RuntimeError, e:
|
||||
logs.error("Could not put document in container: %s" % e)
|
||||
logs.debug(self.dbxmlDocument.getContent())
|
||||
container.close(0)
|
||||
raise
|
||||
self.uriPathFragment = self.getLocalId()
|
||||
if self.isTemporary:
|
||||
del self.isTemporary
|
||||
del self.isTemporary
|
||||
else:
|
||||
try:
|
||||
container.updateDocument(None, self.dbxmlDocument)
|
||||
container.updateDocument(self.dbxmlDocument, self.getParent().updateContext)
|
||||
except RuntimeError, e:
|
||||
logs.error("Could not update document in container: %s" % e)
|
||||
logs.debug(self.dbxmlDocument.getContent())
|
||||
container.close(0)
|
||||
raise
|
||||
container.close(0)
|
||||
|
||||
def setPermanentLocalId(self):
|
||||
# We do not need to set a permanentLocalId here.
|
||||
# The document will have it's own id once inside the dbxml.
|
||||
# The document will have it's own id once inside the container.
|
||||
pass
|
||||
|
||||
def walk(self, uriPathFragments, command = None, instruction = None):
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
# -*- coding: UTF-8 -*-
|
||||
|
||||
|
||||
# Expression
|
||||
# By: Frederic Peters <fpeters@entrouvert.com>
|
||||
# Emmanuel Raviart <eraviart@entrouvert.com>
|
||||
# Sébastien Ducoulombier <sebastien.ducoulombier@lesdeveloppementsdurables.com>
|
||||
#
|
||||
# Copyright (C) 2004 Entr'ouvert, Frederic Peters & Emmanuel Raviart
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
"""Berkeley DB XML Database Manager Module"""
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
import bsddb3.db as db
|
||||
import dbxml
|
||||
|
||||
import expression.core.environs as environs
|
||||
import expression.core.dataholders as dataholders
|
||||
import expression.core.html as html
|
||||
import expression.core.logs as logs
|
||||
|
||||
import expression.modules.dbxmlcontainers as dbxmlcontainers
|
||||
|
||||
|
||||
class DbXmlDatabase(dataholders.DataHolder):
|
||||
""" A directory-like station that maps to the database environment manager. """
|
||||
_environment = None
|
||||
_manager = None
|
||||
_containers = None
|
||||
isUriDirectory = True
|
||||
|
||||
def generateXml(self, layout):
|
||||
""" Just generates a page that confirms this station is the database station. """
|
||||
layout.append(
|
||||
html.html(
|
||||
html.body(
|
||||
html.p(
|
||||
"Berkeley DB XML database at %s" % DbXmlDatabase._manager.getHome()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
return True
|
||||
|
||||
def walkToItem(self, uriPathFragments, command = None, instruction = None):
|
||||
""" Returns the next station if the uriPathFragment is a container name. """
|
||||
name = uriPathFragments[0]
|
||||
if name in DbXmlDatabase._containers:
|
||||
item = dbxmlcontainers.DbXmlContainerHolder(
|
||||
DbXmlDatabase._containers[name],
|
||||
pathFragment = name,
|
||||
previous = self,
|
||||
parent = self,
|
||||
uriPathFragment = name,
|
||||
)
|
||||
return item, uriPathFragments[1:]
|
||||
return super(DbXmlDatabase, self).walkToItem(uriPathFragments, command, instruction)
|
||||
|
||||
|
||||
def __init__():
|
||||
""" Opens a Berkeley DB environment and an XmlManager around it.
|
||||
Then opens all configured containers.
|
||||
"""
|
||||
DbXmlDatabase._environment = db.DBEnv()
|
||||
DbXmlDatabase._environment.set_shm_key(35)
|
||||
dbHome = environs.getVar("configuration").getConfigAbsolutePath(
|
||||
"""yep:module[@name="%s"]/yep:environment/@dbHome""" % __init__.__module__,
|
||||
"/var/lib/expression/db"
|
||||
)
|
||||
DbXmlDatabase._environment.open(
|
||||
dbHome, 0
|
||||
|db.DB_INIT_LOCK
|
||||
|db.DB_INIT_LOG
|
||||
|db.DB_INIT_MPOOL
|
||||
|db.DB_INIT_REP
|
||||
|db.DB_INIT_TXN
|
||||
|db.DB_CREATE
|
||||
|db.DB_SYSTEM_MEM
|
||||
|db.DB_THREAD
|
||||
,
|
||||
0
|
||||
)
|
||||
DbXmlDatabase._manager = dbxml.XmlManager(DbXmlDatabase._environment, dbxml.DBXML_ADOPT_DBENV)
|
||||
DbXmlDatabase._containers = {}
|
||||
for name in environs.getVar("configuration").getConfigList("""yep:module[@name="%s"]/yep:container/@name""" % __init__.__module__):
|
||||
try:
|
||||
DbXmlDatabase._containers[name] = DbXmlDatabase._manager.openContainer(
|
||||
name, 0
|
||||
|db.DB_CREATE
|
||||
|dbxml.DBXML_CHKSUM
|
||||
)
|
||||
except RuntimeError:
|
||||
logs.error("Could not open container %s" % name)
|
||||
__del__()
|
||||
raise
|
||||
|
||||
def __del__():
|
||||
""" Closes containers and the database environment.
|
||||
"""
|
||||
del DbXmlDatabase._containers
|
||||
DbXmlDatabase._environment.close()
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
<xforms:label yep:translatable="true">Documents</xforms:label>
|
||||
<xforms:repeat nodeset="yep:item">
|
||||
<xforms:trigger>
|
||||
<xforms:label><xforms:output ref="@id"/>. <xforms:output ref="@name"/></xforms:label>
|
||||
<xforms:label><xforms:output ref="@name"/></xforms:label>
|
||||
<xforms:load ev:event="DOMActivate" ref="@id" show="replace"/>
|
||||
</xforms:trigger>
|
||||
</xforms:repeat>
|
||||
|
|
Reference in New Issue