Mercurial > p > roundup > code
annotate roundup/cgi/TAL/TALParser.py @ 6433:c1d3fbcdbfbd
issue2551142 - Import of retired node ... unique constraint failure.
Title: Import of retired node with username after active node fails
with unique constraint failure.
More fixes needed for mysql and postgresql.
mysql: add unique constraint for (keyvalue, __retired__) when
creating class in the database.
On schema change if class is changed, remove the unique
constraint too.
upgrade version of rdbms database from 5 to 6 to add constraint
to all version 5 databases that were created as version 5
and didn't get the unique constraint. Make no changes
on version 5 databases upgraded from version 4, the upgrade
process to 5 added the constraint. Make no changes
to other databases (sqlite, postgres) during upgrade from
version 5 to 6.
postgres: Handle the exception raised on unique constraint violation.
The exception invalidates the database connection so it
can't be used to recover from the exception.
Added two new database methods:
checkpoint_data - performs a db.commit under postgres
does nothing on other backends
restore_connection_on_error - does a db.rollback on
postgres, does nothing on other
backends
with the rollback() done on the connection I can use the
database connection to fixup the import that failed on the
unique constraint. This makes postgres slower but without the
commit after every imported object, the rollback will delete
all the entries done up to this point.
Trying to figure out how to make the caller do_import batch
and recover from this failure is beyond me.
Also dismissed having to process the export csv file before
importing. Pushing that onto a user just seems wrong. Also
since import/export isn't frequently done the lack of
surprise on having a failing import and reduced
load/frustration for the user seems worth it. Also the import
can be run in verbose mode where it prints out a row as it is
processed, so it may take a while, ut the user can get
feedback.
db_test-base.py: add test for upgrade from 5 to 6.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Thu, 10 Jun 2021 12:52:05 -0400 |
| parents | 23b8e6067f7c |
| children |
| rev | line source |
|---|---|
| 1049 | 1 ############################################################################## |
| 2 # | |
| 3 # Copyright (c) 2001, 2002 Zope Corporation and Contributors. | |
| 4 # All Rights Reserved. | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
5 # |
| 1049 | 6 # This software is subject to the provisions of the Zope Public License, |
| 7 # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. | |
| 8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | |
| 9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
11 # FOR A PARTICULAR PURPOSE. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
12 # |
| 1049 | 13 ############################################################################## |
| 14 """ | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
15 Parse XML and compile to TALInterpreter intermediate code. |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
16 """ |
| 1049 | 17 |
|
5388
d26921b851c3
Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5377
diff
changeset
|
18 from .XMLParser import XMLParser |
|
d26921b851c3
Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5377
diff
changeset
|
19 from .TALDefs import XML_NS, ZOPE_I18N_NS, ZOPE_METAL_NS, ZOPE_TAL_NS |
|
d26921b851c3
Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5377
diff
changeset
|
20 from .TALGenerator import TALGenerator |
| 1049 | 21 |
| 22 class TALParser(XMLParser): | |
| 23 | |
| 24 ordered_attributes = 1 | |
| 25 | |
| 26 def __init__(self, gen=None): # Override | |
| 27 XMLParser.__init__(self) | |
| 28 if gen is None: | |
| 29 gen = TALGenerator() | |
| 30 self.gen = gen | |
| 31 self.nsStack = [] | |
| 32 self.nsDict = {XML_NS: 'xml'} | |
| 33 self.nsNew = [] | |
| 34 | |
| 35 def getCode(self): | |
| 36 return self.gen.getCode() | |
| 37 | |
| 38 def getWarnings(self): | |
| 39 return () | |
| 40 | |
| 41 def StartNamespaceDeclHandler(self, prefix, uri): | |
| 42 self.nsStack.append(self.nsDict.copy()) | |
| 43 self.nsDict[uri] = prefix | |
| 44 self.nsNew.append((prefix, uri)) | |
| 45 | |
| 46 def EndNamespaceDeclHandler(self, prefix): | |
| 47 self.nsDict = self.nsStack.pop() | |
| 48 | |
| 49 def StartElementHandler(self, name, attrs): | |
| 50 if self.ordered_attributes: | |
| 51 # attrs is a list of alternating names and values | |
| 52 attrlist = [] | |
| 53 for i in range(0, len(attrs), 2): | |
| 54 key = attrs[i] | |
| 55 value = attrs[i+1] | |
| 56 attrlist.append((key, value)) | |
| 57 else: | |
| 58 # attrs is a dict of {name: value} | |
|
5395
23b8e6067f7c
Python 3 preparation: update calls to dict methods.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5388
diff
changeset
|
59 attrlist = sorted(attrs.items()) # Sorted for definiteness |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
60 name, attrlist, taldict, metaldict, i18ndict \ |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
61 = self.process_ns(name, attrlist) |
| 1049 | 62 attrlist = self.xmlnsattrs() + attrlist |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
63 self.gen.emitStartElement(name, attrlist, taldict, metaldict, i18ndict) |
| 1049 | 64 |
| 65 def process_ns(self, name, attrlist): | |
| 66 taldict = {} | |
| 67 metaldict = {} | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
68 i18ndict = {} |
| 1049 | 69 fixedattrlist = [] |
| 70 name, namebase, namens = self.fixname(name) | |
| 71 for key, value in attrlist: | |
| 72 key, keybase, keyns = self.fixname(key) | |
| 73 ns = keyns or namens # default to tag namespace | |
| 74 item = key, value | |
| 75 if ns == 'metal': | |
| 76 metaldict[keybase] = value | |
| 77 item = item + ("metal",) | |
| 78 elif ns == 'tal': | |
| 79 taldict[keybase] = value | |
| 80 item = item + ("tal",) | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
81 elif ns == 'i18n': |
|
5377
12fe83f90f0d
Python 3 preparation: use repr() instead of ``.
Joseph Myers <jsm@polyomino.org.uk>
parents:
2348
diff
changeset
|
82 assert 0, "dealing with i18n: " + repr((keybase, value)) |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
83 i18ndict[keybase] = value |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
84 item = item + ('i18n',) |
| 1049 | 85 fixedattrlist.append(item) |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
86 if namens in ('metal', 'tal', 'i18n'): |
| 1049 | 87 taldict['tal tag'] = namens |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
88 return name, fixedattrlist, taldict, metaldict, i18ndict |
| 1049 | 89 |
| 90 def xmlnsattrs(self): | |
| 91 newlist = [] | |
| 92 for prefix, uri in self.nsNew: | |
| 93 if prefix: | |
| 94 key = "xmlns:" + prefix | |
| 95 else: | |
| 96 key = "xmlns" | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
97 if uri in (ZOPE_METAL_NS, ZOPE_TAL_NS, ZOPE_I18N_NS): |
| 1049 | 98 item = (key, uri, "xmlns") |
| 99 else: | |
| 100 item = (key, uri) | |
| 101 newlist.append(item) | |
| 102 self.nsNew = [] | |
| 103 return newlist | |
| 104 | |
| 105 def fixname(self, name): | |
| 106 if ' ' in name: | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
107 uri, name = name.split(' ') |
| 1049 | 108 prefix = self.nsDict[uri] |
| 109 prefixed = name | |
| 110 if prefix: | |
| 111 prefixed = "%s:%s" % (prefix, name) | |
| 112 ns = 'x' | |
| 113 if uri == ZOPE_TAL_NS: | |
| 114 ns = 'tal' | |
| 115 elif uri == ZOPE_METAL_NS: | |
| 116 ns = 'metal' | |
|
2348
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
117 elif uri == ZOPE_I18N_NS: |
|
8c2402a78bb0
beginning getting ZPT up to date: TAL first
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
118 ns = 'i18n' |
| 1049 | 119 return (prefixed, name, ns) |
| 120 return (name, name, None) | |
| 121 | |
| 122 def EndElementHandler(self, name): | |
| 123 name = self.fixname(name)[0] | |
| 124 self.gen.emitEndElement(name) | |
| 125 | |
| 126 def DefaultHandler(self, text): | |
| 127 self.gen.emitRawText(text) | |
| 128 | |
| 129 def test(): | |
| 130 import sys | |
| 131 p = TALParser() | |
| 132 file = "tests/input/test01.xml" | |
| 133 if sys.argv[1:]: | |
| 134 file = sys.argv[1] | |
| 135 p.parseFile(file) | |
| 136 program, macros = p.getCode() | |
|
5388
d26921b851c3
Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5377
diff
changeset
|
137 from .TALInterpreter import TALInterpreter |
|
d26921b851c3
Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5377
diff
changeset
|
138 from .DummyEngine import DummyEngine |
| 1049 | 139 engine = DummyEngine(macros) |
| 140 TALInterpreter(program, macros, engine, sys.stdout, wrap=0)() | |
| 141 | |
| 142 if __name__ == "__main__": | |
| 143 test() |
