Commit 9a277f14 authored by dkuhlman's avatar dkuhlman
Browse files

New version -- 2.10a

parent e1b79548
No related merge requests found
Showing with 886 additions and 494 deletions
+886 -494
...@@ -141,11 +141,45 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ...@@ -141,11 +141,45 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Change history Change history
-------------- --------------
Version 2.9b (03/01/2013) Version 2.10a (05/29/2013)
- Added ability to produce mapping (a dict) during call to - Added ability to produce mapping (a dict) during call to
to_etree() that maps gDS instances to their associated etree to_etree() that maps gDS instances to their associated etree
elements. Also added convenience method gds_reverse_node_mapping elements. Also added convenience method gds_reverse_node_mapping
to reverse the order of keys and values in a mapping/dict. to reverse the order of keys and values in a mapping/dict. See
function parseEtree in the generated code for hints about how to
produce these mappings. There is also a note on generating the
Lxml Element tree in the docs (generateDS.txt/generateDS.html).
- Python datetime.date objects don't have tzinfo, so trying to
access it in gds_format_date was throwing an error. According to
http://stackoverflow.com/a/610923, the best way to avoid that type
of error is to use a try/catch for AttributeError. Thanks to
Logan Owen for this fix.
- Fixed bug so that gDS will now handle a simpleType nested inside a
restriction nested inside a simpleType. Thanks to Christian
Kaiser for finding this, for focusing my attention on it, and for
providing the sample files to test it with.
- Fixed bug where gDS was failing to resolve defined a simpleType
correctly. It was failing to add the XSchema namespace (usually
xs:). Thanks again to Christian Kaiser for focusing me on this
one.
- Fixes to handling of xs:dateTime when the XML schema specifies a
default value and the XML instance document omits the value.
Also, fixed formatting because datetime.strftime does not handle
dates outside of range (e.g. earlier then 19000). Attempts to use
a consistent internal representation across xs:dateTime, xs:date,
and xs:time, specifically instances of datetime.datetime,
datetime.date, and datetime.time from the Python standard library.
Thanks to Shahaf Abileah for reporting this and for providing an
example of the schema. *Caution*: Because this changes the
internal representation of dates and times used by the generated
code, this fix may break some existing applications.
- Various fixes to generation of method exportLiteral in generated
classes.
- More code clean-up in generateDS.py to eliminate coding style
warnings and errors reported by flake8. Ditto for
process_includes.py. Also, made a few changes to reduce the
warnings and errors reported by flake8 when run on code generated
by gDS.
Version 2.9a (02/21/2013) Version 2.9a (02/21/2013)
- Added support for exporting to an Lxml element tree. The element - Added support for exporting to an Lxml element tree. The element
......
This diff is collapsed.
This diff is collapsed.
...@@ -11,7 +11,7 @@ generateDS -- Generate Data Structures from XML Schema ...@@ -11,7 +11,7 @@ generateDS -- Generate Data Structures from XML Schema
.. version .. version
:revision: 2.9a :revision: 2.10a
.. version .. version
...@@ -1518,6 +1518,53 @@ When you starting developing your implementation of ...@@ -1518,6 +1518,53 @@ When you starting developing your implementation of
copy, paste, and edit code from there. copy, paste, and edit code from there.
Generating Lxml Element tree
------------------------------
Once you have build the tree of objects that are instances of the
classes generated by ``generateDS.py``, you can use this to produce
a tree of instances of the Lxml Element instances. See
http://lxml.de/ for more about Lxml. And, see the function
``parseEtree`` in the generated code for an example of how to
produce the Lxml Element tree::
def parseEtree(inFileName):
doc = parsexml_(inFileName)
rootNode = doc.getroot()
rootTag, rootClass = get_root_tag(rootNode)
if rootClass is None:
rootTag = 'test'
rootClass = Test
rootObj = rootClass.factory()
rootObj.build(rootNode)
# Enable Python to collect the space used by the DOM.
doc = None
mapping = {}
rootElement = rootObj.to_etree(None, name_=rootTag, mapping_=mapping)
reverse_mapping = rootObj.gds_reverse_node_mapping(mapping)
content = etree_.tostring(
rootElement, pretty_print=True,
xml_declaration=True, encoding="utf-8")
sys.stdout.write(content)
sys.stdout.write('\n')
return rootObj, rootElement, mapping, reverse_mapping
Mapping generateDS objects to Lxml Elements and back
......................................................
Now suppose that you have produced the tree of instances of the
generated classes, and suppose that you have used that to produce a
tree of instances of the Element class from Lxml. It may be useful
to have a dictionary that maps instances in one tree to the
corresponding instances in the other. You can create that
dictionary by passing an empty dictionary as the value of the
optional parameter ``mapping_`` in the call to the ``to_tree``
method. And, you can produce the reverse mapping by calling the
convenience method ``gds_reverse_node_mapping`` from superclass
``GeneratedsSuper``. Again, see the code above for an example.
How-to Use the generated source code How-to Use the generated source code
======================================= =======================================
......
...@@ -214,7 +214,7 @@ tt.docutils { ...@@ -214,7 +214,7 @@ tt.docutils {
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
<tbody valign="top"> <tbody valign="top">
<tr class="field"><th class="field-name">revision:</th><td class="field-body">2.8c</td> <tr class="field"><th class="field-name">revision:</th><td class="field-body">2.10a</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
...@@ -223,7 +223,7 @@ tt.docutils { ...@@ -223,7 +223,7 @@ tt.docutils {
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
<tbody valign="top"> <tbody valign="top">
<tr class="field"><th class="field-name">date:</th><td class="field-body">January 31, 2013</td> <tr class="field"><th class="field-name">date:</th><td class="field-body">May 29, 2013</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
......
...@@ -8,7 +8,7 @@ How to package a generateDS.py generated library ...@@ -8,7 +8,7 @@ How to package a generateDS.py generated library
.. version .. version
:revision: 2.9a :revision: 2.10a
.. version .. version
......
...@@ -30,7 +30,7 @@ from lxml import etree ...@@ -30,7 +30,7 @@ from lxml import etree
# Do not modify the following VERSION comments. # Do not modify the following VERSION comments.
# Used by updateversion.py. # Used by updateversion.py.
##VERSION## ##VERSION##
VERSION = '2.9a' VERSION = '2.10a'
##VERSION## ##VERSION##
Namespaces = {'xs': 'http://www.w3.org/2001/XMLSchema'} Namespaces = {'xs': 'http://www.w3.org/2001/XMLSchema'}
...@@ -43,7 +43,7 @@ Xsd_namespace_uri = 'http://www.w3.org/2001/XMLSchema' ...@@ -43,7 +43,7 @@ Xsd_namespace_uri = 'http://www.w3.org/2001/XMLSchema'
def process_include_files(infile, outfile, inpath=''): def process_include_files(infile, outfile, inpath=''):
options = Values({ options = Values({
'force': False, 'force': False,
}) })
prep_schema_doc(infile, outfile, inpath, options) prep_schema_doc(infile, outfile, inpath, options)
...@@ -94,24 +94,23 @@ def resolve_ref(node, params, options): ...@@ -94,24 +94,23 @@ def resolve_ref(node, params, options):
params.parent_url, ) params.parent_url, )
sys.stderr.write(msg) sys.stderr.write(msg)
return None return None
# Uncomment the next line to help track down missing schemaLocation etc. # Uncomment the next lines to help track down missing schemaLocation etc.
# print '(resolve_ref) url: %s\n parent-url: %s' % (url, params.parent_url, ) # print '(resolve_ref) url: %s\n parent-url: %s' % (
# url, params.parent_url, )
if params.base_url and not ( if params.base_url and not (
url.startswith('/') or url.startswith('/') or
url.startswith('http:') or url.startswith('http:') or
url.startswith('ftp:') url.startswith('ftp:')):
):
locn = '%s/%s' % (params.base_url, url, ) locn = '%s/%s' % (params.base_url, url, )
schema_name = locn schema_name = locn
else: else:
locn = url locn = url
schema_name = url schema_name = url
if not ( if not (
url.startswith('/') or url.startswith('/') or
url.startswith('http:') or url.startswith('http:') or
url.startswith('ftp:') url.startswith('ftp:')):
):
schema_name = os.path.abspath(locn) schema_name = os.path.abspath(locn)
if locn is not None: if locn is not None:
if schema_name not in params.already_processed: if schema_name not in params.already_processed:
...@@ -129,7 +128,7 @@ def resolve_ref(node, params, options): ...@@ -129,7 +128,7 @@ def resolve_ref(node, params, options):
urlfile.close() urlfile.close()
params.parent_url = locn params.parent_url = locn
params.base_url = os.path.split(locn)[0] params.base_url = os.path.split(locn)[0]
except urllib2.HTTPError, exp: except urllib2.HTTPError:
msg = "Can't find file %s referenced in %s." % ( msg = "Can't find file %s referenced in %s." % (
locn, params.parent_url, ) locn, params.parent_url, )
raise SchemaIOError(msg) raise SchemaIOError(msg)
...@@ -168,7 +167,7 @@ def collect_inserts_aux(child, params, inserts, options): ...@@ -168,7 +167,7 @@ def collect_inserts_aux(child, params, inserts, options):
if not isinstance(child1, etree._Comment): if not isinstance(child1, etree._Comment):
namespace = child1.nsmap[child1.prefix] namespace = child1.nsmap[child1.prefix]
if (child1.tag != '{%s}include' % (namespace, ) and if (child1.tag != '{%s}include' % (namespace, ) and
child1.tag != '{%s' % (namespace, )): child1.tag != '{%s' % (namespace, )):
comment = etree.Comment(etree.tostring(child)) comment = etree.Comment(etree.tostring(child))
comment.tail = '\n' comment.tail = '\n'
inserts.append(comment) inserts.append(comment)
...@@ -246,7 +245,8 @@ def replace_group_defs(def_dict, refs): ...@@ -246,7 +245,8 @@ def replace_group_defs(def_dict, refs):
continue continue
def_node = def_dict.get(name) def_node = def_dict.get(name)
if def_node is not None: if def_node is not None:
content = def_node.xpath('./xs:sequence|./xs:choice|./xs:all', content = def_node.xpath(
'./xs:sequence|./xs:choice|./xs:all',
namespaces=Namespaces) namespaces=Namespaces)
if content: if content:
content = content[0] content = content[0]
...@@ -337,7 +337,8 @@ def usage(parser): ...@@ -337,7 +337,8 @@ def usage(parser):
def main(): def main():
parser = OptionParser(USAGE_TEXT) parser = OptionParser(USAGE_TEXT)
parser.add_option("-f", "--force", action="store_true", parser.add_option(
"-f", "--force", action="store_true",
dest="force", default=False, dest="force", default=False,
help="force overwrite without asking") help="force overwrite without asking")
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
......
...@@ -7,7 +7,7 @@ setup(name="generateDS", ...@@ -7,7 +7,7 @@ setup(name="generateDS",
# Do not modify the following VERSION comments. # Do not modify the following VERSION comments.
# Used by updateversion.py. # Used by updateversion.py.
##VERSION## ##VERSION##
version="2.9a", version="2.10a",
##VERSION## ##VERSION##
author="Dave Kuhlman", author="Dave Kuhlman",
author_email="dkuhlman@rexx.com", author_email="dkuhlman@rexx.com",
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment