1 | Importing and Exporting Things |
---|
2 | ****************************** |
---|
3 | |
---|
4 | The waeup package tries to support all special object types to be |
---|
5 | exportable and importable. |
---|
6 | |
---|
7 | .. :doctest: |
---|
8 | .. :layer: waeup.kofa.testing.KofaUnitTestLayer |
---|
9 | |
---|
10 | As imports and exports of data are a cruical point when doing updates |
---|
11 | or to enable data backups, this support must be considered a serious |
---|
12 | topic for the base functionality of the whole software. |
---|
13 | |
---|
14 | Exports and imports are implemented using the Zope component framework |
---|
15 | capabilities. This means we need some adapters and utilities, which we |
---|
16 | register, by grokking the whole package. This is done on startup |
---|
17 | automatically, but in doctests (like this one) it is done by the |
---|
18 | testlayer. |
---|
19 | |
---|
20 | Furthermore we need something to import/export. As only pickable |
---|
21 | classes are importable/exportable and these have to be defined in some |
---|
22 | globally reachable module, we first define some silly object in |
---|
23 | filesystem and adjust the path to lookup modules: |
---|
24 | |
---|
25 | >>> import os |
---|
26 | >>> import sys |
---|
27 | >>> os.mkdir('stoneage') |
---|
28 | >>> old_sys_path = sys.path |
---|
29 | >>> open(os.path.join('stoneage', '__init__.py'), 'wb').write( |
---|
30 | ... """ |
---|
31 | ... class Cave(object): |
---|
32 | ... name = 'Unnamed cave' |
---|
33 | ... dinoports = 2 |
---|
34 | ... """) |
---|
35 | >>> sys.path.append(os.getcwd()) |
---|
36 | |
---|
37 | Now we can import stoneage.Cave objects. |
---|
38 | |
---|
39 | |
---|
40 | Exporting XML |
---|
41 | ============= |
---|
42 | |
---|
43 | One of the major formats we support for data export is XML. |
---|
44 | |
---|
45 | When we want to export an object, we can choose the destination |
---|
46 | file. If we do not give a file to write to, we get a StringIO object, |
---|
47 | i.e. an in-memory file. |
---|
48 | |
---|
49 | We can export caves. First we create a cave: |
---|
50 | |
---|
51 | >>> from stoneage import Cave |
---|
52 | >>> mycave = Cave() |
---|
53 | >>> mycave.name = 'Freds Cave' |
---|
54 | >>> mycave.dinoports = 1 |
---|
55 | |
---|
56 | Exporting plain XML |
---|
57 | ------------------- |
---|
58 | |
---|
59 | Now let's export it to XML. To do this we first ask the framework for |
---|
60 | an exporter:: |
---|
61 | |
---|
62 | >>> from waeup.kofa.interfaces import IKofaXMLExporter |
---|
63 | >>> exporter = IKofaXMLExporter(mycave) |
---|
64 | >>> exporter |
---|
65 | <waeup.kofa.utils.importexport.XMLExporter object at 0x...> |
---|
66 | |
---|
67 | All exporters provide an ``export(<obj>)`` method:: |
---|
68 | |
---|
69 | >>> result = exporter.export() |
---|
70 | |
---|
71 | The result is an object of type StringIO. We therefore use its |
---|
72 | `read()` method to get the actual XML data:: |
---|
73 | |
---|
74 | >>> print result.read() |
---|
75 | <?xml version="1.0" encoding="utf-8" ?>... |
---|
76 | |
---|
77 | |
---|
78 | Generating XML files |
---|
79 | -------------------- |
---|
80 | |
---|
81 | We can also let the results be written to a file:: |
---|
82 | |
---|
83 | >>> result = exporter.export('myexport.xml') |
---|
84 | >>> print open('myexport.xml', 'rb').read() |
---|
85 | <?xml version="1.0" encoding="utf-8" ?> |
---|
86 | <pickle> |
---|
87 | <object> |
---|
88 | ... |
---|
89 | </pickle> |
---|
90 | |
---|
91 | |
---|
92 | Importing XML |
---|
93 | ============= |
---|
94 | |
---|
95 | We can generate objects from XML. |
---|
96 | |
---|
97 | We change the name of the cave: |
---|
98 | |
---|
99 | >>> mycave.name = 'Another name' |
---|
100 | |
---|
101 | Now we create an importer for that object: |
---|
102 | |
---|
103 | >>> from waeup.kofa.interfaces import IKofaXMLImporter |
---|
104 | >>> importer = IKofaXMLImporter(mycave) |
---|
105 | |
---|
106 | Importing from filenames |
---|
107 | ------------------------ |
---|
108 | |
---|
109 | We can use a filepath to import from the denoted file:: |
---|
110 | |
---|
111 | >>> new_obj = importer.doImport('myexport.xml') |
---|
112 | |
---|
113 | The object created is indeed a cave:: |
---|
114 | |
---|
115 | >>> new_obj |
---|
116 | <stoneage.Cave object at 0x...> |
---|
117 | |
---|
118 | >>> new_obj.name |
---|
119 | 'Freds Cave' |
---|
120 | |
---|
121 | The new object is really a new object:: |
---|
122 | |
---|
123 | >>> new_obj is mycave |
---|
124 | False |
---|
125 | |
---|
126 | Importing from filelike objects |
---|
127 | ------------------------------- |
---|
128 | |
---|
129 | We can also pass a file-like object instead of a filepath:: |
---|
130 | |
---|
131 | >>> filelike_obj = open('myexport.xml', 'rb') |
---|
132 | >>> new_obj = importer.doImport(filelike_obj) |
---|
133 | |
---|
134 | The object created is indeed a faculty:: |
---|
135 | |
---|
136 | >>> new_obj |
---|
137 | <stoneage.Cave object at 0x...> |
---|
138 | |
---|
139 | Clean up:: |
---|
140 | |
---|
141 | >>> import os |
---|
142 | >>> import shutil |
---|
143 | >>> sys.path = old_sys_path |
---|
144 | >>> os.unlink('myexport.xml') |
---|
145 | >>> shutil.rmtree('stoneage') |
---|