Ran update-copyright.py.
[be.git] / libbe / storage / util / mapfile.py
1 # Copyright (C) 2005-2012 Aaron Bentley <abentley@panoramicfeedback.com>
2 #                         Chris Ball <cjb@laptop.org>
3 #                         Gianluca Montecchi <gian@grys.it>
4 #                         W. Trevor King <wking@tremily.us>
5 #
6 # This file is part of Bugs Everywhere.
7 #
8 # Bugs Everywhere is free software: you can redistribute it and/or modify it
9 # under the terms of the GNU General Public License as published by the Free
10 # Software Foundation, either version 2 of the License, or (at your option) any
11 # later version.
12 #
13 # Bugs Everywhere is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16 # more details.
17 #
18 # You should have received a copy of the GNU General Public License along with
19 # Bugs Everywhere.  If not, see <http://www.gnu.org/licenses/>.
20
21 """Serializing and deserializing dictionaries of parameters.
22
23 The serialized "mapfiles" should be clear, flat-text strings, and allow
24 easy merging of independent/conflicting changes.
25 """
26
27 import errno
28 import json
29 import os.path
30
31 import libbe
32 if libbe.TESTING == True:
33     import doctest
34
35
36 class InvalidMapfileContents (Exception):
37     def __init__(self, contents):
38         super(InvalidMapfileContents, self).__init__('Invalid JSON contents')
39         self.contents = contents
40
41
42 def generate(map):
43     """Generate a YAML mapfile content string.
44
45     Examples
46     --------
47
48     >>> import sys
49     >>> sys.stdout.write(generate({'q':'p'}))
50     {
51     <BLANKLINE>
52     <BLANKLINE>
53     <BLANKLINE>
54     <BLANKLINE>
55     <BLANKLINE>
56     <BLANKLINE>
57         "q": "p"
58     <BLANKLINE>
59     <BLANKLINE>
60     <BLANKLINE>
61     <BLANKLINE>
62     <BLANKLINE>
63     <BLANKLINE>
64     }
65     >>> generate({'q':u'Fran\u00e7ais'})
66     '{\\n\\n\\n\\n\\n\\n\\n    "q": "Fran\\\\u00e7ais"\\n\\n\\n\\n\\n\\n\\n}\\n'
67     >>> generate({'q':u'hello'})
68     '{\\n\\n\\n\\n\\n\\n\\n    "q": "hello"\\n\\n\\n\\n\\n\\n\\n}\\n'
69     >>> sys.stdout.write(generate(
70     ...         {'p':'really long line\\n'*10, 'q': 'the next entry'}))
71     {
72     <BLANKLINE>
73     <BLANKLINE>
74     <BLANKLINE>
75     <BLANKLINE>
76     <BLANKLINE>
77     <BLANKLINE>
78         "p": "really long line\\nreally long line\\nreally long line\\nreally long line\\nreally long line\\nreally long line\\nreally long line\\nreally long line\\nreally long line\\nreally long line\\n", 
79     <BLANKLINE>
80     <BLANKLINE>
81     <BLANKLINE>
82     <BLANKLINE>
83     <BLANKLINE>
84     <BLANKLINE>
85         "q": "the next entry"
86     <BLANKLINE>
87     <BLANKLINE>
88     <BLANKLINE>
89     <BLANKLINE>
90     <BLANKLINE>
91     <BLANKLINE>
92     }
93
94     See Also
95     --------
96     parse : inverse
97     """
98     lines = json.dumps(map, sort_keys=True, indent=4).splitlines()
99     # add blank lines for context-less merging
100     return '\n\n\n\n\n\n\n'.join(lines) + '\n'
101
102 def parse(contents):
103     """Parse a YAML mapfile string.
104
105     Examples
106     --------
107
108     >>> parse('{"q": "p"}')['q']
109     u'p'
110     >>> contents = generate({'a':'b', 'c':'d', 'e':'f'})
111     >>> dict = parse(contents)
112     >>> dict['a']
113     u'b'
114     >>> dict['c']
115     u'd'
116     >>> dict['e']
117     u'f'
118     >>> contents = generate({'q':u'Fran\u00e7ais'})
119     >>> dict = parse(contents)
120     >>> dict['q']
121     u'Fran\\xe7ais'
122     >>> dict = parse('a!')
123     Traceback (most recent call last):
124       ...
125     InvalidMapfileContents: Invalid JSON contents
126
127     See Also
128     --------
129     generate : inverse
130
131     """
132     try:
133         return json.loads(contents)
134     except ValueError:
135         raise InvalidMapfileContents(contents)
136
137 if libbe.TESTING == True:
138     suite = doctest.DocTestSuite()