~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/xml.py

  • Committer: mbp at sourcefrog
  • Date: 2005-03-21 22:29:49 UTC
  • Revision ID: mbp@sourcefrog.net-20050321222949-232c2093a6eadd80
fixup doctest for new module structure

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/env python
1
2
# -*- coding: UTF-8 -*-
2
 
#
 
3
 
3
4
# This program is free software; you can redistribute it and/or modify
4
5
# it under the terms of the GNU General Public License as published by
5
6
# the Free Software Foundation; either version 2 of the License, or
6
7
# (at your option) any later version.
7
 
#
 
8
 
8
9
# This program is distributed in the hope that it will be useful,
9
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
12
# GNU General Public License for more details.
12
 
#
 
13
 
13
14
# You should have received a copy of the GNU General Public License
14
15
# along with this program; if not, write to the Free Software
15
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20
# "XML is like violence: if it doesn't solve your problem, you aren't
20
21
# using enough of it." -- various
21
22
 
22
 
# importing this module is fairly slow because it has to load several
23
 
# ElementTree bits
24
23
 
25
 
from bzrlib.trace import mutter, warning
 
24
__copyright__ = "Copyright (C) 2005 Canonical Ltd."
 
25
__author__ = "Martin Pool <mbp@canonical.com>"
26
26
 
27
27
try:
28
 
    from cElementTree import (ElementTree, SubElement, Element,
29
 
                              XMLTreeBuilder, fromstring, tostring)
30
 
    import elementtree
 
28
    from cElementTree import Element, ElementTree, SubElement
31
29
except ImportError:
32
 
    mutter('WARNING: using slower ElementTree; consider installing cElementTree'
33
 
           " and make sure it's on your PYTHONPATH")
34
 
    from util.elementtree.ElementTree import (ElementTree, SubElement,
35
 
                                              Element, XMLTreeBuilder,
36
 
                                              fromstring, tostring)
37
 
    import util.elementtree as elementtree
38
 
 
39
 
from bzrlib import errors
40
 
 
41
 
 
42
 
class Serializer(object):
43
 
    """Abstract object serialize/deserialize"""
44
 
    def write_inventory(self, inv, f):
45
 
        """Write inventory to a file"""
46
 
        elt = self._pack_inventory(inv)
47
 
        self._write_element(elt, f)
48
 
 
49
 
    def write_inventory_to_string(self, inv):
50
 
        return tostring(self._pack_inventory(inv)) + '\n'
51
 
 
52
 
    def read_inventory_from_string(self, xml_string):
53
 
        try:
54
 
            return self._unpack_inventory(fromstring(xml_string))
55
 
        except SyntaxError, e:
56
 
            raise errors.UnexpectedInventoryFormat(e)
57
 
 
58
 
    def read_inventory(self, f):
59
 
        try:
60
 
            return self._unpack_inventory(self._read_element(f))
61
 
        except SyntaxError, e:
62
 
            raise errors.UnexpectedInventoryFormat(e)
63
 
 
64
 
    def write_revision(self, rev, f):
65
 
        self._write_element(self._pack_revision(rev), f)
66
 
 
67
 
    def write_revision_to_string(self, rev):
68
 
        return tostring(self._pack_revision(rev)) + '\n'
69
 
 
70
 
    def read_revision(self, f):
71
 
        return self._unpack_revision(self._read_element(f))
72
 
 
73
 
    def read_revision_from_string(self, xml_string):
74
 
        return self._unpack_revision(fromstring(xml_string))
75
 
 
76
 
    def _write_element(self, elt, f):
77
 
        ElementTree(elt).write(f, 'utf-8')
 
30
    from elementtree.ElementTree import Element, ElementTree, SubElement
 
31
 
 
32
import os, time
 
33
from trace import mutter
 
34
 
 
35
class XMLMixin:
 
36
    def to_element(self):
 
37
        raise Exception("XMLMixin.to_element must be overridden in concrete classes")
 
38
    
 
39
    def write_xml(self, f):
 
40
        ElementTree(self.to_element()).write(f, 'utf-8')
78
41
        f.write('\n')
79
42
 
80
 
    def _read_element(self, f):
81
 
        return ElementTree().parse(f)
82
 
 
83
 
 
84
 
# performance tuning for elementree's serialiser. This should be
85
 
# sent upstream - RBC 20060523.
86
 
# the functions here are patched into elementtree at runtime.
87
 
import re
88
 
escape_re = re.compile("[&'\"<>]")
89
 
escape_map = {
90
 
    "&":'&amp;',
91
 
    "'":"&apos;", # FIXME: overkill
92
 
    "\"":"&quot;",
93
 
    "<":"&lt;",
94
 
    ">":"&gt;",
95
 
    }
96
 
def _escape_replace(match, map=escape_map):
97
 
    return map[match.group()]
98
 
 
99
 
def _escape_attrib(text, encoding=None, replace=None):
100
 
    # escape attribute value
101
 
    try:
102
 
        if encoding:
103
 
            try:
104
 
                text = elementtree.ElementTree._encode(text, encoding)
105
 
            except UnicodeError:
106
 
                return elementtree.ElementTree._encode_entity(text)
107
 
        if replace is None:
108
 
            return escape_re.sub(_escape_replace, text)
109
 
        else:
110
 
            text = replace(text, "&", "&amp;")
111
 
            text = replace(text, "'", "&apos;") # FIXME: overkill
112
 
            text = replace(text, "\"", "&quot;")
113
 
            text = replace(text, "<", "&lt;")
114
 
            text = replace(text, ">", "&gt;")
115
 
            return text
116
 
    except (TypeError, AttributeError):
117
 
        elementtree.ElementTree._raise_serialization_error(text)
118
 
 
119
 
elementtree.ElementTree._escape_attrib = _escape_attrib
120
 
 
121
 
escape_cdata_re = re.compile("[&<>]")
122
 
escape_cdata_map = {
123
 
    "&":'&amp;',
124
 
    "<":"&lt;",
125
 
    ">":"&gt;",
126
 
    }
127
 
def _escape_cdata_replace(match, map=escape_cdata_map):
128
 
    return map[match.group()]
129
 
 
130
 
def _escape_cdata(text, encoding=None, replace=None):
131
 
    # escape character data
132
 
    try:
133
 
        if encoding:
134
 
            try:
135
 
                text = elementtree.ElementTree._encode(text, encoding)
136
 
            except UnicodeError:
137
 
                return elementtree.ElementTree._encode_entity(text)
138
 
        if replace is None:
139
 
            return escape_cdata_re.sub(_escape_cdata_replace, text)
140
 
        else:
141
 
            text = replace(text, "&", "&amp;")
142
 
            text = replace(text, "<", "&lt;")
143
 
            text = replace(text, ">", "&gt;")
144
 
            return text
145
 
    except (TypeError, AttributeError):
146
 
        elementtree.ElementTree._raise_serialization_error(text)
147
 
 
148
 
elementtree.ElementTree._escape_cdata = _escape_cdata
 
43
    def read_xml(cls, f):
 
44
        return cls.from_element(ElementTree().parse(f))
 
45
 
 
46
    read_xml = classmethod(read_xml)
 
47
 
 
48
 
 
49