aboutsummaryrefslogblamecommitdiffstats
path: root/libbe/storage/util/mapfile.py
blob: 609f7827ae504ebd4880d7589b6ff6994e432717 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
                                                                        
                                                     
                                                           
                                                           
 
                                       
 



                                                                               
 
                                                                        


                                                                               
 

                                                                              
 



                                                                       

   
            
           
              



                         
 
 
                                         
                                 
                                                                             
                                
 
 
                             
                                              



            
                  

                                      















                                             





                                                                    
                                                                      






                                                             
                                  

                                                                      

               

                                                                                                                                                                                                               

                             
     



                   
       
                                                                  

                                 
 
                    
                                   



            

                                
                                                        
                              
                 
        
                 
        
                 
        
                                                    
                              
                 
                   


                                      
                                                 




                      
       



                                              
 

                                  
# Copyright (C) 2005-2012 Aaron Bentley <abentley@panoramicfeedback.com>
#                         Chris Ball <cjb@laptop.org>
#                         Gianluca Montecchi <gian@grys.it>
#                         W. Trevor King <wking@tremily.us>
#
# This file is part of Bugs Everywhere.
#
# Bugs Everywhere is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 2 of the License, or (at your option) any
# later version.
#
# Bugs Everywhere is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# Bugs Everywhere.  If not, see <http://www.gnu.org/licenses/>.

"""Serializing and deserializing dictionaries of parameters.

The serialized "mapfiles" should be clear, flat-text strings, and allow
easy merging of independent/conflicting changes.
"""

import errno
import json
import os.path

import libbe
if libbe.TESTING == True:
    import doctest


class InvalidMapfileContents (Exception):
    def __init__(self, contents):
        super(InvalidMapfileContents, self).__init__('Invalid JSON contents')
        self.contents = contents


def generate(map, context=6):
    """Generate a JSON mapfile content string.

    Examples
    --------

    >>> import sys
    >>> sys.stdout.write(generate({}))
    {}
    >>> sys.stdout.write(generate({'q':'p'}))
    {
    <BLANKLINE>
    <BLANKLINE>
    <BLANKLINE>
    <BLANKLINE>
    <BLANKLINE>
    <BLANKLINE>
        "q": "p"
    <BLANKLINE>
    <BLANKLINE>
    <BLANKLINE>
    <BLANKLINE>
    <BLANKLINE>
    <BLANKLINE>
    }

    The blank lines ensure that merging occurs independent of
    surrounding content.  Because the mapfile format is also used by
    the :py:mod:`~libbe.command.serve_commands` where merging is not
    important, the amount of context is controllable.

    >>> sys.stdout.write(generate({'q':u'Fran\\u00e7ais'}, context=0))
    {
        "q": "Fran\\u00e7ais"
    }
    >>> sys.stdout.write(generate({'q':u'hello'}, context=0))
    {
        "q": "hello"
    }
    >>> sys.stdout.write(generate(
    ...         {'p':'really long line\\n'*10, 'q': 'the next entry'},
    ...         context=1))
    {
    <BLANKLINE>
        "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", 
    <BLANKLINE>
        "q": "the next entry"
    <BLANKLINE>
    }

    See Also
    --------
    parse : inverse
    """
    lines = json.dumps(map, sort_keys=True, indent=4).splitlines()
    sep = '\n' * (1 + context)
    return sep.join(lines) + '\n'

def parse(contents):
    """Parse a JSON mapfile string.

    Examples
    --------

    >>> parse('{"q": "p"}')['q']
    u'p'
    >>> contents = generate({'a':'b', 'c':'d', 'e':'f'})
    >>> dict = parse(contents)
    >>> dict['a']
    u'b'
    >>> dict['c']
    u'd'
    >>> dict['e']
    u'f'
    >>> contents = generate({'q':u'Fran\\u00e7ais'})
    >>> dict = parse(contents)
    >>> dict['q']
    u'Fran\\xe7ais'
    >>> dict = parse('a!')
    Traceback (most recent call last):
      ...
    InvalidMapfileContents: Invalid JSON contents

    See Also
    --------
    generate : inverse

    """
    try:
        return json.loads(contents)
    except ValueError:
        raise InvalidMapfileContents(contents)

if libbe.TESTING == True:
    suite = doctest.DocTestSuite()