Skip to content

Commit 4100d60

Browse files
author
James William Pye
committed
Add XML tests and expand functionality.
Use a tuple to identify a sequence of fragments instead of a list, this allows for unambiguous usage with arrays. Also, if given text, just submit the encoded text, don't bother parsing and serializing it.. (still not sure about this one, but it allows the user to submit fragments).
1 parent 1cbe14e commit 4100d60

2 files changed

Lines changed: 58 additions & 2 deletions

File tree

postgresql/protocol/typio.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -620,15 +620,25 @@ def anyarray_unpack(self, adata):
620620
return anyarray_unpack(self.resolve_unpack, adata)
621621

622622
def xml_pack(self, xml):
623-
return self._encode(etree.tostring(xml))[0]
623+
if isinstance(xml, str):
624+
# if it's a string, encode and return.
625+
return self._encode(xml)[0]
626+
elif isinstance(xml, tuple):
627+
# if it's a tuple, encode and return the joined items.
628+
return b''.join((
629+
self._encode(
630+
x if isinstance(x, str) else pg_types.etree.tostring(x)
631+
)[0] for x in xml
632+
))
633+
return self._encode(pg_types.etree.tostring(xml))[0]
624634

625635
def xml_unpack(self, xmldata):
626636
xml_or_frag = self._decode(xmldata)[0]
627637
try:
628638
return pg_types.etree.XML(xml_or_frag)
629639
except Exception:
630640
# try it again, but return the sequence of children.
631-
return list(pg_types.etree.XML('<x>' + xml_or_frag + '</x>'))
641+
return tuple(pg_types.etree.XML('<x>' + xml_or_frag + '</x>'))
632642

633643
def attribute_map(self, pq_descriptor):
634644
return zip(self.decodes(pq_descriptor.keys()), count())

postgresql/test/test_driver.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,52 @@ def testTypes(self):
672672
)
673673
)
674674

675+
def testXML(self):
676+
try:
677+
xml = self.db.prepare('select $1::xml')
678+
textxml = self.db.prepare('select $1::text::xml')
679+
r = textxml.first('<foo/>')
680+
except (pg_exc.FeatureError, pg_exc.UndefinedObjectError):
681+
return
682+
foo = pg_types.etree.XML('<foo/>')
683+
bar = pg_types.etree.XML('<bar/>')
684+
tostr = pg_types.etree.tostring
685+
self.failUnlessEqual(tostr(xml.first(foo)), tostr(foo))
686+
self.failUnlessEqual(tostr(xml.first(bar)), tostr(bar))
687+
self.failUnlessEqual(tostr(textxml.first('<foo/>')), tostr(foo))
688+
self.failUnlessEqual(tostr(textxml.first('<foo/>')), tostr(foo))
689+
self.failUnlessEqual(tostr(xml.first(pg_types.etree.XML('<foo/>'))), tostr(foo))
690+
self.failUnlessEqual(tostr(textxml.first('<foo/>')), tostr(foo))
691+
# test fragments
692+
self.failUnlessEqual(
693+
tuple(
694+
tostr(x) for x in xml.first('<foo/><bar/>')
695+
), (tostr(foo), tostr(bar))
696+
)
697+
self.failUnlessEqual(
698+
tuple(
699+
tostr(x) for x in textxml.first('<foo/><bar/>')
700+
),
701+
(tostr(foo), tostr(bar))
702+
)
703+
# mixed text and etree.
704+
self.failUnlessEqual(
705+
tuple(
706+
tostr(x) for x in xml.first((
707+
'<foo/>', bar,
708+
))
709+
),
710+
(tostr(foo), tostr(bar))
711+
)
712+
self.failUnlessEqual(
713+
tuple(
714+
tostr(x) for x in xml.first((
715+
'<foo/>', bar,
716+
))
717+
),
718+
(tostr(foo), tostr(bar))
719+
)
720+
675721
def testSyntaxError(self):
676722
self.failUnlessRaises(
677723
pg_exc.SyntaxError,

0 commit comments

Comments
 (0)