NCCOOS Trac Projects: Top | Web | Platforms | Processing | Viz | Sprints | Sandbox | (Wind)

root/spongenet/trunk/spongenet/expand.py

Revision 338 (checked in by cbc, 14 years ago)

Add doctest comment for module level test.

Line 
1 """
2 Expand zipped sponge data files.
3
4 Usage:
5
6    > python expand.py path/to/config/file
7
8 Test for silent import.
9
10 >>> import expand
11 """
12
13 __author__ = "Chris Calloway"
14 __email__ = "cbc@chriscalloway.org"
15 __copyright__ = "Copyright 2010 UNC-CH Department of Marine Science"
16 __license__ = "GPL2"
17
18 import sys
19 import os
20 import glob
21 import zipfile
22 import shutil
23 import fileinput
24 from StringIO import StringIO
25
26 usage = "\n".join(__doc__.splitlines()[3:6])
27 test_path = "tests/expand"
28
29
30 def config_path():
31     """
32     Return the configuration file path from the command line.
33
34     Supply too few arguments on command line.
35
36     >>> save_stdout = sys.stdout
37     >>> temp_stdout = StringIO()
38     >>> sys.stdout = temp_stdout
39     >>> sys.argv = []
40     >>> _config_path = config_path()
41     >>> sys.stdout = save_stdout
42     >>> usage == temp_stdout.getvalue()[:-1]
43     True
44
45     Supply too many arguments on the command line.
46
47     >>> save_stdout = sys.stdout
48     >>> temp_stdout = StringIO()
49     >>> sys.stdout = temp_stdout
50     >>> sys.argv = ["", "", "",]
51     >>> _config_path = config_path()
52     >>> sys.stdout = save_stdout
53     >>> usage == temp_stdout.getvalue()[:-1]
54     True
55
56     Supply non-file argument.
57
58     >>> save_stdout = sys.stdout
59     >>> temp_stdout = StringIO()
60     >>> sys.stdout = temp_stdout
61     >>> _config_path = os.path.join(
62     ...                    os.path.dirname(
63     ...                        os.path.abspath(__file__)),
64     ...                    test_path)
65     >>> sys.argv = ["", _config_path]
66     >>> _config_path = config_path()
67     >>> sys.stdout = save_stdout
68     >>> usage == temp_stdout.getvalue()[:-1]
69     True
70
71     Supply nonexistent file argument.
72
73     >>> save_stdout = sys.stdout
74     >>> temp_stdout = StringIO()
75     >>> sys.stdout = temp_stdout
76     >>> _config_path = os.path.join(
77     ...                    os.path.dirname(
78     ...                        os.path.abspath(__file__)),
79     ...                    test_path, "xxxxx")
80     >>> sys.argv = ["", _config_path]
81     >>> _config_path = config_path()
82     >>> sys.stdout = save_stdout
83     >>> usage == temp_stdout.getvalue()[:-1]
84     True
85
86     Supply valid config path argument.
87
88     >>> _config_path = os.path.join(
89     ...                    os.path.dirname(
90     ...                        os.path.abspath(__file__)),
91     ...                    test_path, "config.py")
92     >>> sys.argv = ["", _config_path]
93     >>> _config_path == config_path()
94     True
95     """
96
97     path = None
98     try:
99         if len(sys.argv) == 2:
100             path = sys.argv[1]
101             if not os.path.exists(path):
102                 raise IOError(path + \
103                               " does not exist.")
104             elif not os.path.isfile(path):
105                 raise IOError(path + \
106                               " is not a file.")
107         else:
108             raise IOError("Incorrect number of arguments supplied.")
109     except IOError:
110         print usage
111     return path
112
113
114 def config(path):
115     """
116     Return the configuration from a file.
117
118     Execute empty configuration.
119
120     >>> _config_path = os.path.join(
121     ...                    os.path.dirname(
122     ...                        os.path.abspath(__file__)),
123     ...                    test_path, "empty_config.py")
124     >>> zipdir,xmldir,zipdir_pattern,zipfile_pattern,xmlfile_pattern = \
125             config(_config_path)
126     >>> zipdir
127     >>> xmldir
128     >>> zipdir_pattern
129     >>> zipfile_pattern
130     >>> xmlfile_pattern
131
132     Execute nonexistent configuration.
133
134     >>> save_stdout = sys.stdout
135     >>> temp_stdout = StringIO()
136     >>> sys.stdout = temp_stdout
137     >>> _config_path = os.path.join(
138     ...                    os.path.dirname(
139     ...                        os.path.abspath(__file__)),
140     ...                    test_path, "xxxxx")
141     >>> zipdir,xmldir,zipdir_pattern,zipfile_pattern,xmlfile_pattern = \
142             config(_config_path)
143     >>> sys.stdout = save_stdout
144     >>> usage == temp_stdout.getvalue()[:-1]
145     True
146     >>> zipdir
147     >>> xmldir
148     >>> zipdir_pattern
149     >>> zipfile_pattern
150     >>> xmlfile_pattern
151
152     Execute bad configuration.
153
154     >>> save_stdout = sys.stdout
155     >>> temp_stdout = StringIO()
156     >>> sys.stdout = temp_stdout
157     >>> _config_path = os.path.join(
158     ...                    os.path.dirname(
159     ...                        os.path.abspath(__file__)),
160     ...                    test_path, "bad_config.py")
161     >>> zipdir,xmldir,zipdir_pattern,zipfile_pattern,xmlfile_pattern = \
162             config(_config_path)
163     >>> sys.stdout = save_stdout
164     >>> usage == temp_stdout.getvalue()[:-1]
165     True
166     >>>
167     >>> zipdir
168     >>> xmldir
169     >>> zipdir_pattern
170     >>> zipfile_pattern
171     >>> xmlfile_pattern
172
173     Execute valid configuration.
174
175     >>> _config_path = os.path.join(
176     ...                    os.path.dirname(
177     ...                        os.path.abspath(__file__)),
178     ...                    test_path, "config.py")
179     >>> zipdir,xmldir,zipdir_pattern,zipfile_pattern,xmlfile_pattern = \
180             config(_config_path)
181     >>> zipdir == os.path.join(os.path.dirname(os.path.abspath(__file__)),
182     ...                        test_path, "zip")
183     True
184     >>> xmldir == os.path.join(os.path.dirname(os.path.abspath(__file__)),
185     ...                        test_path, "xml")
186     True
187     >>> zipdir_pattern == "[0-9][0-9][0-9][0-9]_[0-9][0-9]"
188     True
189     >>> zipfile_pattern == "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]T" \
190                            "[0-9][0-9][0-9][0-9][0-9][0-9]-" \
191                            "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]T" \
192                            "[0-9][0-9][0-9][0-9][0-9][0-9].zip"
193     True
194     >>> xmlfile_pattern == "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]T" \
195                            "[0-9][0-9][0-9][0-9][0-9][0-9].xml"
196     True
197     """
198
199     namespace = {}
200     namespace["zipdir"] = None
201     namespace["xmldir"] = None
202     namespace["zipdir_pattern"] = None
203     namespace["zipfile_pattern"] = None
204     namespace["xmlfile_pattern"] = None
205     try:
206         execfile(path, globals(), namespace)
207     except IOError:
208         print usage
209     except SyntaxError:
210         print usage
211     return (namespace["zipdir"],
212             namespace["xmldir"],
213             namespace["zipdir_pattern"],
214             namespace["zipfile_pattern"],
215             namespace["xmlfile_pattern"],)
216
217
218 def combine(xml_subdir, xmlfile_pattern):
219     """
220     Combine the xml sponge data files from a subdirectory.
221
222     Combine test subdirectory.
223
224     >>> xmlref_path = os.path.join(
225     ...                   os.path.dirname(
226     ...                       os.path.abspath(__file__)),
227     ...                   test_path, "xmlref")
228     >>> xmlref = glob.glob(os.path.join(xmlref_path, "*"))
229     >>> xmlref_path = [path for path in xmlref if os.path.isdir(path)][0]
230     >>> xmltest_path = os.path.join(
231     ...                    os.path.dirname(
232     ...                        os.path.abspath(__file__)),
233     ...                    test_path, "xmltest")
234     >>> if os.path.exists(xmltest_path):
235     ...     shutil.rmtree(xmltest_path)
236     >>> shutil.copytree(xmlref_path, xmltest_path)
237     >>> xmltest = glob.glob(os.path.join(xmltest_path, "*"))
238     >>> xml_subdir = [path for path in xmltest if os.path.isdir(path)][0]
239     >>> xmlfile_pattern = "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]T" \
240                           "[0-9][0-9][0-9][0-9][0-9][0-9].xml"
241     >>> combine(xml_subdir, xmlfile_pattern)
242     >>> ref_path = xml_subdir + os.extsep + "ref"
243     >>> xml_path = xml_subdir + os.extsep + "xml"
244     >>> ref_handle = open(ref_path)
245     >>> xml_handle = open(xml_path)
246     >>> reffile = ref_handle.read()
247     >>> xmlfile = xml_handle.read()
248     >>> reffile == xmlfile
249     True
250     >>> ref_handle.close()
251     >>> xml_handle.close()
252     >>> os.path.exists(xml_subdir)
253     False
254     """
255
256     # Find all the xml sponge data files.
257     xmlfiles = glob.glob(os.path.join(xml_subdir, xmlfile_pattern))
258     xmlfiles = [xmlfile
259                 for xmlfile in xmlfiles
260                 if os.path.isfile(xmlfile)]
261
262     # Read all the xml sponge data files.
263     files = fileinput.FileInput(xmlfiles)
264     header = files.readline()
265     lines = [line for line in files if not files.isfirstline()]
266
267     # Write a combined xml sponge data file.
268     path = xml_subdir + os.extsep + "xml"
269     handle = open(path, "w")
270     handle.write(header)
271     handle.write("<root>\r\n")
272     handle.writelines(lines)
273     handle.write("\r\n</root>")
274     handle.close()
275
276     # Remove the xml sponge data file subdirectory.
277     shutil.rmtree(xml_subdir)
278
279     return
280
281
282 def expand(zipdir, xmldir, zipdir_pattern, zipfile_pattern, xmlfile_pattern):
283     """
284     Expand zipped sponge data files.
285
286     Expand valid tree.
287
288     >>> _config_path = os.path.join(
289     ...                    os.path.dirname(
290     ...                        os.path.abspath(__file__)),
291     ...                    test_path, "config.py")
292     >>> zipdir,xmldir,zipdir_pattern,zipfile_pattern,xmlfile_pattern = \
293             config(_config_path)
294     >>> if os.path.exists(xmldir):
295     ...     shutil.rmtree(xmldir)
296     >>> expand(zipdir,xmldir,zipdir_pattern,zipfile_pattern,xmlfile_pattern)
297     """
298
299     # Find all the monthly directories of zipped files.
300     zip_months = glob.glob(os.path.join(zipdir, zipdir_pattern))
301     zip_months = [zip_month
302                   for zip_month in zip_months
303                   if os.path.isdir(zip_month)]
304
305     # Create a directory for monthly XML subdirectories.
306     if not os.path.exists(xmldir):
307         os.mkdir(xmldir, 0755)
308     elif not os.path.isdir(xmldir):
309         raise IOError("XML directory name " + \
310                        xmldir + \
311                        " exists and is not a directory.")
312
313     for zip_month in zip_months:
314         # Create each monthly XML subdirectory.
315         xml_month = os.path.join(xmldir, os.path.split(zip_month)[1])
316         if not os.path.exists(xml_month):
317             os.mkdir(xml_month, 0755)
318         elif not os.path.isdir(xml_month):
319             raise IOError("XML month subdirectory name " + \
320                           xml_month + \
321                           " exists and is not a directory.")
322
323         # Find all the zip files for each month.
324         zipfiles = glob.glob(os.path.join(zip_month, zipfile_pattern))
325         zipfiles = [zip_file
326                     for zip_file in zipfiles
327                     if os.path.isfile(zip_file)]
328
329         for zip_file in zipfiles:
330             # Create an XML subdirectory for each zip file.
331             xml_subdir = os.path.splitext(os.path.split(zip_file)[1])[0]
332             xml_subdir = os.path.join(xml_month, xml_subdir)
333             if not os.path.exists(xml_subdir):
334                 os.mkdir(xml_subdir, 0755)
335                 # Extract all the xml files in the zip file.
336                 archive = zipfile.ZipFile(zip_file, "r")
337                 archive.extractall(xml_subdir)
338                 combine(xml_subdir, xmlfile_pattern)
339             elif not os.path.isdir(xml_subdir):
340                 raise IOError("XML file subdirectory name " + \
341                               xml_subdir + \
342                               " exists and is not a directory.")
343
344     return
345
346 if __name__ == "__main__":
347     _config_path = config_path()
348     if _config_path:
349         _config = config(_config_path)
350         if all(_config):
351             expand(*_config)
Note: See TracBrowser for help on using the browser.