* support "string" attributes, starting with s_,
test it in xmlfiletests * fix: handle unicode in output formatting
This commit is contained in:
+1
-1
@@ -97,7 +97,7 @@ class Path:
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
class Dependency:
|
class Dependency:
|
||||||
t_Package = [xmlfile.String, xmlfile.mandatory]
|
s_Package = [xmlfile.String, xmlfile.mandatory]
|
||||||
a_versionFrom = [xmlfile.String, xmlfile.optional]
|
a_versionFrom = [xmlfile.String, xmlfile.optional]
|
||||||
a_versionTo = [xmlfile.String, xmlfile.optional]
|
a_versionTo = [xmlfile.String, xmlfile.optional]
|
||||||
a_releaseFrom = [xmlfile.String, xmlfile.optional]
|
a_releaseFrom = [xmlfile.String, xmlfile.optional]
|
||||||
|
|||||||
+43
-10
@@ -37,6 +37,8 @@ from xml.parsers.expat import ExpatError
|
|||||||
import locale
|
import locale
|
||||||
import codecs
|
import codecs
|
||||||
import types
|
import types
|
||||||
|
import formatter
|
||||||
|
import sys
|
||||||
|
|
||||||
import gettext
|
import gettext
|
||||||
__trans = gettext.translation('pisi', fallback=True)
|
__trans = gettext.translation('pisi', fallback=True)
|
||||||
@@ -94,7 +96,7 @@ class LocalText(object):
|
|||||||
if not lang:
|
if not lang:
|
||||||
lang = 'en'
|
lang = 'en'
|
||||||
self.locs[lang] = c
|
self.locs[lang] = c
|
||||||
|
|
||||||
def encode(self, xml, node, errs):
|
def encode(self, xml, node, errs):
|
||||||
for key in self.locs.iterkeys():
|
for key in self.locs.iterkeys():
|
||||||
newnode = newNode(node, self.tag)
|
newnode = newNode(node, self.tag)
|
||||||
@@ -123,6 +125,23 @@ class LocalText(object):
|
|||||||
else:
|
else:
|
||||||
errs.append(_("Tag should have at least an English or Turkish version"))
|
errs.append(_("Tag should have at least an English or Turkish version"))
|
||||||
|
|
||||||
|
class Writer(formatter.DumbWriter):
|
||||||
|
"""adds unicode support"""
|
||||||
|
|
||||||
|
def __init__(self, file=None, maxcol=78):
|
||||||
|
formatter.DumbWriter.__init__(self, file, maxcol)
|
||||||
|
|
||||||
|
def send_literal_data(self, data):
|
||||||
|
self.file.write(data.encode("utf-8"))
|
||||||
|
i = data.rfind('\n')
|
||||||
|
if i >= 0:
|
||||||
|
self.col = 0
|
||||||
|
data = data[i+1:]
|
||||||
|
data = data.expandtabs()
|
||||||
|
self.col = self.col + len(data)
|
||||||
|
self.atbreak = 0
|
||||||
|
|
||||||
|
|
||||||
class autoxml(oo.autosuper):
|
class autoxml(oo.autosuper):
|
||||||
"""High-level automatic XML transformation interface for xmlfile.
|
"""High-level automatic XML transformation interface for xmlfile.
|
||||||
The idea is to declare a class for each XML tag. Inside the
|
The idea is to declare a class for each XML tag. Inside the
|
||||||
@@ -218,18 +237,20 @@ class autoxml(oo.autosuper):
|
|||||||
order = dict.keys()
|
order = dict.keys()
|
||||||
order.sort()
|
order.sort()
|
||||||
for var in order:
|
for var in order:
|
||||||
if var.startswith('t_') or var.startswith('a_'):
|
if var.startswith('t_') or var.startswith('a_') or var.startswith('s_'):
|
||||||
name = var[2:]
|
name = var[2:]
|
||||||
if var.startswith('a_'):
|
if var.startswith('a_'):
|
||||||
x = autoxml.gen_attr_member(cls, name)
|
x = autoxml.gen_attr_member(cls, name)
|
||||||
elif var.startswith('t_'):
|
elif var.startswith('t_'):
|
||||||
x = autoxml.gen_tag_member(cls, name)
|
x = autoxml.gen_tag_member(cls, name)
|
||||||
(init, decoder, encoder, checker, formatter) = x
|
elif var.startswith('s_'):
|
||||||
|
x = autoxml.gen_str_member(cls, name)
|
||||||
|
(init, decoder, encoder, checker, format_x) = x
|
||||||
inits.append(init)
|
inits.append(init)
|
||||||
decoders.append(decoder)
|
decoders.append(decoder)
|
||||||
encoders.append(encoder)
|
encoders.append(encoder)
|
||||||
checkers.append(checker)
|
checkers.append(checker)
|
||||||
formatters.append(formatter)
|
formatters.append(format_x)
|
||||||
|
|
||||||
# generate top-level helper functions
|
# generate top-level helper functions
|
||||||
cls.initializers = inits
|
cls.initializers = inits
|
||||||
@@ -275,8 +296,7 @@ class autoxml(oo.autosuper):
|
|||||||
formatter(self, f, errs)
|
formatter(self, f, errs)
|
||||||
cls.format = format
|
cls.format = format
|
||||||
def print_text(self):
|
def print_text(self):
|
||||||
import formatter
|
w = Writer() # plain text
|
||||||
w = formatter.DumbWriter() # plain text
|
|
||||||
f = formatter.AbstractFormatter(w)
|
f = formatter.AbstractFormatter(w)
|
||||||
errs = []
|
errs = []
|
||||||
self.format(f, errs)
|
self.format(f, errs)
|
||||||
@@ -307,7 +327,7 @@ class autoxml(oo.autosuper):
|
|||||||
spec = getattr(cls, 't_' + tag)
|
spec = getattr(cls, 't_' + tag)
|
||||||
anonfuns = cls.gen_tag(tag, spec)
|
anonfuns = cls.gen_tag(tag, spec)
|
||||||
return cls.gen_named_comp(tag, spec, anonfuns)
|
return cls.gen_named_comp(tag, spec, anonfuns)
|
||||||
|
|
||||||
def gen_tag(cls, tag, spec):
|
def gen_tag(cls, tag, spec):
|
||||||
"""generate readers and writers for the tag"""
|
"""generate readers and writers for the tag"""
|
||||||
tag_type = spec[0]
|
tag_type = spec[0]
|
||||||
@@ -330,6 +350,19 @@ class autoxml(oo.autosuper):
|
|||||||
raise Error(_('gen_tag: unrecognized tag type %s in spec') %
|
raise Error(_('gen_tag: unrecognized tag type %s in spec') %
|
||||||
str(tag_type))
|
str(tag_type))
|
||||||
|
|
||||||
|
def gen_str_member(cls, token):
|
||||||
|
"""generate readers and writers for a string member"""
|
||||||
|
spec = getattr(cls, 's_' + token)
|
||||||
|
tag_type = spec[0]
|
||||||
|
assert type(tag_type) == type(type)
|
||||||
|
def readtext(node, blah):
|
||||||
|
node.normalize()
|
||||||
|
return getNodeText(node)
|
||||||
|
def writetext(xml, node, blah, text):
|
||||||
|
addText(node, "", text)
|
||||||
|
anonfuns = cls.gen_anon_basic(token, spec, readtext, writetext)
|
||||||
|
return cls.gen_named_comp(token, spec, anonfuns)
|
||||||
|
|
||||||
def gen_named_comp(cls, token, spec, anonfuns):
|
def gen_named_comp(cls, token, spec, anonfuns):
|
||||||
"""generate a named component tag/attr. a decoration of
|
"""generate a named component tag/attr. a decoration of
|
||||||
anonymous functions that do not bind to variable names"""
|
anonymous functions that do not bind to variable names"""
|
||||||
@@ -430,14 +463,14 @@ class autoxml(oo.autosuper):
|
|||||||
return value
|
return value
|
||||||
else:
|
else:
|
||||||
if req == mandatory:
|
if req == mandatory:
|
||||||
errs.append(_('Mandatory token %s not available') % token)
|
errs.append(where + _('Mandatory token %s not available') % token)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def encode(xml, node, value, errs):
|
def encode(xml, node, value, errs):
|
||||||
"""encode given value inside DOM node"""
|
"""encode given value inside DOM node"""
|
||||||
if value:
|
if value:
|
||||||
#FIXME: unicode() here?
|
#FIXME: unicode() here?
|
||||||
writetext(xml, node, token, str(value))
|
writetext(xml, node, token, unicode(value))
|
||||||
else:
|
else:
|
||||||
if req == mandatory:
|
if req == mandatory:
|
||||||
errs.append(_('Mandatory argument not available'))
|
errs.append(_('Mandatory argument not available'))
|
||||||
@@ -528,7 +561,7 @@ class autoxml(oo.autosuper):
|
|||||||
l = []
|
l = []
|
||||||
nodes = getAllNodes(node, path)
|
nodes = getAllNodes(node, path)
|
||||||
#print node, tag + '/' + comp_tag, nodes
|
#print node, tag + '/' + comp_tag, nodes
|
||||||
if len(nodes) is 0 and req is mandatory:
|
if len(nodes)==0 and req==mandatory:
|
||||||
errs.append(where + _('Mandatory list empty'))
|
errs.append(where + _('Mandatory list empty'))
|
||||||
for ix in range(len(nodes)):
|
for ix in range(len(nodes)):
|
||||||
node = nodes[ix]
|
node = nodes[ix]
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
|
|
||||||
<A href="http://www.cs.bilkent.edu.tr/~erayo">
|
<A href="http://www.cs.bilkent.edu.tr/~erayo">
|
||||||
|
cıvık mantardır bu
|
||||||
<Name>Eray Ozkural</Name>
|
<Name>Eray Ozkural</Name>
|
||||||
<Number>868</Number>
|
<Number>868</Number>
|
||||||
<Description>Lazy Tin</Description>
|
<Description>Lazy Tin</Description>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class SpecFileNewTestCase(testcase.TestCase):
|
|||||||
self.spec = specfile.SpecFile()
|
self.spec = specfile.SpecFile()
|
||||||
self.spec.read("tests/popt/pspec.xml")
|
self.spec.read("tests/popt/pspec.xml")
|
||||||
|
|
||||||
def testReadSpec(self):
|
def testFields(self):
|
||||||
self.assertEqual(self.spec.source.name, "popt")
|
self.assertEqual(self.spec.source.name, "popt")
|
||||||
|
|
||||||
self.assertEqual(self.spec.source.version, "1.7")
|
self.assertEqual(self.spec.source.version, "1.7")
|
||||||
@@ -32,7 +32,7 @@ class SpecFileNewTestCase(testcase.TestCase):
|
|||||||
self.assertEqual(self.spec.source.release, "3")
|
self.assertEqual(self.spec.source.release, "3")
|
||||||
|
|
||||||
self.assertEqual(self.spec.source.archiveSHA1,
|
self.assertEqual(self.spec.source.archiveSHA1,
|
||||||
"66f3c77b87a160951b180447f4a6dce68ad2f71b")
|
"66f3c77b87a160951b180447f4a6dce68ad2f71b")
|
||||||
|
|
||||||
patches = self.spec.source.patches
|
patches = self.spec.source.patches
|
||||||
self.assertEqual(len(patches), 1)
|
self.assertEqual(len(patches), 1)
|
||||||
@@ -72,7 +72,7 @@ class SpecFileNewTestCase(testcase.TestCase):
|
|||||||
self.fail("Failed to match PartOf in Package")
|
self.fail("Failed to match PartOf in Package")
|
||||||
|
|
||||||
def testVerify(self):
|
def testVerify(self):
|
||||||
if self.spec.has_errors():
|
if self.spec.check() != []:
|
||||||
self.fail("Failed to verify specfile")
|
self.fail("Failed to verify specfile")
|
||||||
|
|
||||||
def testCopy(self):
|
def testCopy(self):
|
||||||
|
|||||||
@@ -43,11 +43,12 @@ class AutoXmlTestCase(testcase.TestCase):
|
|||||||
a_href = [types.StringType, xmlfile.mandatory]
|
a_href = [types.StringType, xmlfile.mandatory]
|
||||||
t_Projects = [ [types.StringType], xmlfile.mandatory, 'Project']
|
t_Projects = [ [types.StringType], xmlfile.mandatory, 'Project']
|
||||||
t_OtherInfo = [ OtherInfo, xmlfile.optional ]
|
t_OtherInfo = [ OtherInfo, xmlfile.optional ]
|
||||||
|
s_Comment = [ xmlfile.Text, xmlfile.mandatory]
|
||||||
|
|
||||||
self.A = A
|
self.A = A
|
||||||
|
|
||||||
def testDeclaration(self):
|
def testDeclaration(self):
|
||||||
self.assertEqual(len(self.A.decoders), 7) # we have seven fields
|
self.assertEqual(len(self.A.decoders), 8) # how many fields in A?
|
||||||
self.assert_(hasattr(self.A, 'encode'))
|
self.assert_(hasattr(self.A, 'encode'))
|
||||||
|
|
||||||
def testReadWrite(self):
|
def testReadWrite(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user