pax_global_header00006660000000000000000000000064116652152630014521gustar00rootroot0000000000000052 comment=7b2e6089ff9182776b5cb5420e24536ab7479a34 pyjavaproperties-0.6/000077500000000000000000000000001166521526300147755ustar00rootroot00000000000000pyjavaproperties-0.6/MANIFEST.in000066400000000000000000000001041166521526300165260ustar00rootroot00000000000000include TODO include README recursive-include testdata *.properties pyjavaproperties-0.6/PKG-INFO000066400000000000000000000102711166521526300160730ustar00rootroot00000000000000Metadata-Version: 1.0 Name: pyjavaproperties Version: 0.6 Summary: Python replacement for java.util.Properties. Home-page: http://pypi.python.org/pypi/pyjavaproperties Author: Jesse Noller Author-email: jnoller@gmail.com License: PSF License Description: ================ pyjavaproperties ================ * Project hosting: .. contents:: About ------------------ This is a "fork" of the "python replacement for java.util.Properties" recipe on ASPN: and uploaded by Anand Balachandran Pillai. The project is maintained by Jesse Noller , Anand Pilla . License ------------------ As with all ASPN recipes not otherwise licensed prior to July 15, 2008 on aspn.activestate.com, the original recipe is under PSF License. For more information, see the ASPN terms of service here: While the licensing under the PSF license is sub-optimal, it is what it is. See for more information about the PSF license. What this is ------------------ This module is designed to be a python equivalent to the `java.util.Properties `_ class. Currently, the basic input/output methods are supported, and there are plans to add the XML input/output methods found in J2SE 5.0. Fundamentally, this module is designed so that users can easily parse and manipulate Java Properties files - that's it. There's a fair number of us pythonistas who work in multi-language shops, and constantly writing your own parsing mechanism is just painful. Not to mention Java guys are notoriously unwilling to use anything which is cross-language for configuration, unless it's XML, which is a form of self-punishment. :) Plans ------------------ Here is a rough plan of features: - Keep/maintain blank lines and comments found in the original file - Make the module compatible with the new methods in J2SE 5.0 - Switch to/add python property access rather than direct dictionary get/set - Add unit tests - Add unicode support - When-Pigs-Fly: If running within Jython, switch to java.util.Properties under the hood - Coercion/conversion to python types for values Usage ------------------ This is the easy part:: from pyjavaproperties import Properties p = Properties() p.load(open('test2.properties')) p.list() print p print p.items() print p['name3'] p['name3'] = 'changed = value' print p['name3'] p['new key'] = 'new value' p.store(open('test2.properties','w')) See also the Properties.list() method, which will return an iterator over the property keys Changes & News -------------- 0.4: - Patch from Pepper Lebeck-Jobe for handling ! style comments. 0.3: - Keys that are added which were not part of the original file are simply appended to the index. Shenanigans. 0.2: - Added an internal list (self._keyorder) to keep an ordered index of keys as they are encountered, so the file can we written-back out in the same order. 0.1: - Initial release/fork. - Added setup/packaging and doc - added in {foo} style references for previous properties, thanks to N B on ASPN. Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License Classifier: Topic :: Software Development :: Libraries Classifier: Topic :: Software Development :: Libraries :: Python Modules pyjavaproperties-0.6/README000066400000000000000000000060241166521526300156570ustar00rootroot00000000000000================ pyjavaproperties ================ * Project hosting: .. contents:: About ------------------ This is a "fork" of the "python replacement for java.util.Properties" recipe on ASPN: and uploaded by Anand Balachandran Pillai. The project is maintained by Jesse Noller , Anand Pilla . License ------------------ As with all ASPN recipes not otherwise licensed prior to July 15, 2008 on aspn.activestate.com, the original recipe is under PSF License. For more information, see the ASPN terms of service here: While the licensing under the PSF license is sub-optimal, it is what it is. See for more information about the PSF license. What this is ------------------ This module is designed to be a python equivalent to the `java.util.Properties `_ class. Currently, the basic input/output methods are supported, and there are plans to add the XML input/output methods found in J2SE 5.0. Fundamentally, this module is designed so that users can easily parse and manipulate Java Properties files - that's it. There's a fair number of us pythonistas who work in multi-language shops, and constantly writing your own parsing mechanism is just painful. Not to mention Java guys are notoriously unwilling to use anything which is cross-language for configuration, unless it's XML, which is a form of self-punishment. :) Plans ------------------ Here is a rough plan of features: - Keep/maintain blank lines and comments found in the original file - Make the module compatible with the new methods in J2SE 5.0 - Switch to/add python property access rather than direct dictionary get/set - Add unit tests - Add unicode support - When-Pigs-Fly: If running within Jython, switch to java.util.Properties under the hood - Coercion/conversion to python types for values Usage ------------------ This is the easy part:: from pyjavaproperties import Properties p = Properties() p.load(open('test2.properties')) p.list() print p print p.items() print p['name3'] p['name3'] = 'changed = value' print p['name3'] p['new key'] = 'new value' p.store(open('test2.properties','w')) See also the Properties.list() method, which will return an iterator over the property keys Changes & News -------------- 0.4: - Patch from Pepper Lebeck-Jobe for handling ! style comments. 0.3: - Keys that are added which were not part of the original file are simply appended to the index. Shenanigans. 0.2: - Added an internal list (self._keyorder) to keep an ordered index of keys as they are encountered, so the file can we written-back out in the same order. 0.1: - Initial release/fork. - Added setup/packaging and doc - added in {foo} style references for previous properties, thanks to N B on ASPN. pyjavaproperties-0.6/TODO000066400000000000000000000003201166521526300154600ustar00rootroot00000000000000* Add PEP 8 interface, python properties. * Add in unit tests - Have to find some really offensive .properties files * Switch to returning Unicode values * Possible coercion to python types (on ints/etc) pyjavaproperties-0.6/pyjavaproperties.egg-info/000077500000000000000000000000001166521526300220765ustar00rootroot00000000000000pyjavaproperties-0.6/pyjavaproperties.egg-info/PKG-INFO000066400000000000000000000102711166521526300231740ustar00rootroot00000000000000Metadata-Version: 1.0 Name: pyjavaproperties Version: 0.6 Summary: Python replacement for java.util.Properties. Home-page: http://pypi.python.org/pypi/pyjavaproperties Author: Jesse Noller Author-email: jnoller@gmail.com License: PSF License Description: ================ pyjavaproperties ================ * Project hosting: .. contents:: About ------------------ This is a "fork" of the "python replacement for java.util.Properties" recipe on ASPN: and uploaded by Anand Balachandran Pillai. The project is maintained by Jesse Noller , Anand Pilla . License ------------------ As with all ASPN recipes not otherwise licensed prior to July 15, 2008 on aspn.activestate.com, the original recipe is under PSF License. For more information, see the ASPN terms of service here: While the licensing under the PSF license is sub-optimal, it is what it is. See for more information about the PSF license. What this is ------------------ This module is designed to be a python equivalent to the `java.util.Properties `_ class. Currently, the basic input/output methods are supported, and there are plans to add the XML input/output methods found in J2SE 5.0. Fundamentally, this module is designed so that users can easily parse and manipulate Java Properties files - that's it. There's a fair number of us pythonistas who work in multi-language shops, and constantly writing your own parsing mechanism is just painful. Not to mention Java guys are notoriously unwilling to use anything which is cross-language for configuration, unless it's XML, which is a form of self-punishment. :) Plans ------------------ Here is a rough plan of features: - Keep/maintain blank lines and comments found in the original file - Make the module compatible with the new methods in J2SE 5.0 - Switch to/add python property access rather than direct dictionary get/set - Add unit tests - Add unicode support - When-Pigs-Fly: If running within Jython, switch to java.util.Properties under the hood - Coercion/conversion to python types for values Usage ------------------ This is the easy part:: from pyjavaproperties import Properties p = Properties() p.load(open('test2.properties')) p.list() print p print p.items() print p['name3'] p['name3'] = 'changed = value' print p['name3'] p['new key'] = 'new value' p.store(open('test2.properties','w')) See also the Properties.list() method, which will return an iterator over the property keys Changes & News -------------- 0.4: - Patch from Pepper Lebeck-Jobe for handling ! style comments. 0.3: - Keys that are added which were not part of the original file are simply appended to the index. Shenanigans. 0.2: - Added an internal list (self._keyorder) to keep an ordered index of keys as they are encountered, so the file can we written-back out in the same order. 0.1: - Initial release/fork. - Added setup/packaging and doc - added in {foo} style references for previous properties, thanks to N B on ASPN. Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License Classifier: Topic :: Software Development :: Libraries Classifier: Topic :: Software Development :: Libraries :: Python Modules pyjavaproperties-0.6/pyjavaproperties.egg-info/SOURCES.txt000066400000000000000000000004151166521526300237620ustar00rootroot00000000000000MANIFEST.in README TODO setup.py ./pyjavaproperties.py ./pyjavaproperties_test.py pyjavaproperties.egg-info/PKG-INFO pyjavaproperties.egg-info/SOURCES.txt pyjavaproperties.egg-info/dependency_links.txt pyjavaproperties.egg-info/top_level.txt testdata/complex.propertiespyjavaproperties-0.6/pyjavaproperties.egg-info/dependency_links.txt000066400000000000000000000000011166521526300261440ustar00rootroot00000000000000 pyjavaproperties-0.6/pyjavaproperties.egg-info/top_level.txt000066400000000000000000000000221166521526300246220ustar00rootroot00000000000000 pyjavaproperties pyjavaproperties-0.6/pyjavaproperties.py000066400000000000000000000244771166521526300207740ustar00rootroot00000000000000#! /usr/bin/env python """ A Python replacement for java.util.Properties class This is modelled as closely as possible to the Java original. Created - Anand B Pillai """ import sys,os import re import time class IllegalArgumentException(Exception): def __init__(self, lineno, msg): self.lineno = lineno self.msg = msg def __str__(self): s='Exception at line number %d => %s' % (self.lineno, self.msg) return s class Properties(object): """ A Python replacement for java.util.Properties """ def __init__(self, props=None): # Note: We don't take a default properties object # as argument yet # Dictionary of properties. self._props = {} # Dictionary of properties with 'pristine' keys # This is used for dumping the properties to a file # using the 'store' method self._origprops = {} self._keyorder = [] # Dictionary mapping keys from property # dictionary to pristine dictionary self._keymap = {} self.othercharre = re.compile(r'(?',line # Means we need to split by space. first, last = m2.span() sepidx = first elif m: # print 'Other match=>',line # No matching wspace char found, need # to split by either '=' or ':' first, last = m.span() sepidx = last - 1 # print line[sepidx] # If the last character is a backslash # it has to be preceded by a space in which # case the next line is read as part of the # same property while line[-1] == '\\': # Read next line nextline = i.next() nextline = nextline.strip() lineno += 1 # This line will become part of the value line = line[:-1] + nextline # Now split to key,value according to separation char if sepidx != -1: key, value = line[:sepidx], line[sepidx+1:] else: key,value = line,'' self._keyorder.append(key) self.processPair(key, value) def processPair(self, key, value): """ Process a (key, value) pair """ oldkey = key oldvalue = value # Create key intelligently keyparts = self.bspacere.split(key) # print keyparts strippable = False lastpart = keyparts[-1] if lastpart.find('\\ ') != -1: keyparts[-1] = lastpart.replace('\\','') # If no backspace is found at the end, but empty # space is found, strip it elif lastpart and lastpart[-1] == ' ': strippable = True key = ''.join(keyparts) if strippable: key = key.strip() oldkey = oldkey.strip() oldvalue = self.unescape(oldvalue) value = self.unescape(value) # Patch from N B @ ActiveState curlies = re.compile("{.+?}") found = curlies.findall(value) for f in found: srcKey = f[1:-1] if self._props.has_key(srcKey): value = value.replace(f, self._props[srcKey], 1) self._props[key] = value.strip() # Check if an entry exists in pristine keys if self._keymap.has_key(key): oldkey = self._keymap.get(key) self._origprops[oldkey] = oldvalue.strip() else: self._origprops[oldkey] = oldvalue.strip() # Store entry in keymap self._keymap[key] = oldkey if key not in self._keyorder: self._keyorder.append(key) def escape(self, value): # Java escapes the '=' and ':' in the value # string with backslashes in the store method. # So let us do the same. newvalue = value.replace(':','\:') newvalue = newvalue.replace('=','\=') return newvalue def unescape(self, value): # Reverse of escape newvalue = value.replace('\:',':') newvalue = newvalue.replace('\=','=') return newvalue def load(self, stream): """ Load properties from an open file stream """ # For the time being only accept file input streams if type(stream) is not file: raise TypeError,'Argument should be a file object!' # Check for the opened mode if stream.mode != 'r': raise ValueError,'Stream should be opened in read-only mode!' try: lines = stream.readlines() self.__parse(lines) except IOError, e: raise def getProperty(self, key): """ Return a property for the given key """ return self._props.get(key,'') def setProperty(self, key, value): """ Set the property for the given key """ if type(key) is str and type(value) is str: self.processPair(key, value) else: raise TypeError,'both key and value should be strings!' def propertyNames(self): """ Return an iterator over all the keys of the property dictionary, i.e the names of the properties """ return self._props.keys() def list(self, out=sys.stdout): """ Prints a listing of the properties to the stream 'out' which defaults to the standard output """ out.write('-- listing properties --\n') for key,value in self._props.items(): out.write(''.join((key,'=',value,'\n'))) def store(self, out, header=""): """ Write the properties list to the stream 'out' along with the optional 'header' """ if out.mode[0] != 'w': raise ValueError,'Steam should be opened in write mode!' try: out.write(''.join(('#',header,'\n'))) # Write timestamp tstamp = time.strftime('%a %b %d %H:%M:%S %Z %Y', time.localtime()) out.write(''.join(('#',tstamp,'\n'))) # Write properties from the pristine dictionary for prop in self._keyorder: if prop in self._origprops: val = self._origprops[prop] out.write(''.join((prop,'=',self.escape(val),'\n'))) out.close() except IOError, e: raise def getPropertyDict(self): return self._props def __getitem__(self, name): """ To support direct dictionary like access """ return self.getProperty(name) def __setitem__(self, name, value): """ To support direct dictionary like access """ self.setProperty(name, value) def __getattr__(self, name): """ For attributes not found in self, redirect to the properties dictionary """ try: return self.__dict__[name] except KeyError: if hasattr(self._props,name): return getattr(self._props, name) if __name__=="__main__": p = Properties() p.load(open('test2.properties')) p.list() print p print p.items() print p['name3'] p['name3'] = 'changed = value' print p['name3'] p['new key'] = 'new value' p.store(open('test2.properties','w')) pyjavaproperties-0.6/pyjavaproperties_test.py000066400000000000000000000043551166521526300220240ustar00rootroot00000000000000#! /usr/bin/env python """Basic tests to ensure pyjavaproperties behaves like java.util.Properties. Created - Pepper Lebeck-Jobe (eljobe@gmail.com) """ import os import unittest from pyjavaproperties import Properties class PyJavaPropertiesTest(unittest.TestCase): """Tests pyjavaproperties complies to java.util.Properties contract.""" def setUp(self): test_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testdata') self.properties_file = os.path.join(test_dir, 'complex.properties') def testParsePropertiesInput(self): properties = Properties() properties.load(open(self.properties_file)) self.assertEquals(23, len(properties.items())) self.assertEquals('Value00', properties['Key00']) self.assertEquals('Value01', properties['Key01']) self.assertEquals('Value02', properties['Key02']) self.assertEquals('Value03', properties['Key03']) self.assertEquals('Value04', properties['Key04']) self.assertEquals('Value05a, Value05b, Value05c', properties['Key05']) self.assertEquals('Value06a, Value06b, Value06c', properties['Key06']) self.assertEquals('Value07b', properties['Key07']) self.assertEquals( 'Value08a, Value08b, Value08c, Value08d, Value08e, Value08f', properties['Key08']) self.assertEquals( 'Value09a, Value09b, Value09c, Value09d, Value09e, Value09f', properties['Key09']) self.assertEquals('Value10', properties['Key10']) self.assertEquals('', properties['Key11']) self.assertEquals('Value12a, Value12b, Value12c', properties['Key12']) self.assertEquals('Value13 With Spaces', properties['Key13']) self.assertEquals('Value14 With Spaces', properties['Key14']) self.assertEquals('Value15 With Spaces', properties['Key15']) self.assertEquals('Value16', properties['Key16 With Spaces']) self.assertEquals('Value17', properties['Key17 With Spaces']) self.assertEquals('Value18 # Not a comment.', properties['Key18']) self.assertEquals('Value19 ! Not a comment.', properties['Key19']) self.assertEquals('Value20', properties['Key20=WithEquals']) self.assertEquals('Value21', properties['Key21:WithColon']) self.assertEquals('Value22', properties['Key22']) if __name__ == '__main__': unittest.main() pyjavaproperties-0.6/setup.cfg000066400000000000000000000000731166521526300166160ustar00rootroot00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 pyjavaproperties-0.6/setup.py000066400000000000000000000020631166521526300165100ustar00rootroot00000000000000import os import sys try: import ez_setup ez_setup.use_setuptools() except ImportError: pass from setuptools import setup # Use a cute trick to include the rest-style docs as the long_description # therefore having it self-doc'ed and hosted on pypi f = open(os.path.join(os.path.dirname(__file__), 'README')) long_description = f.read().strip() f.close() setup( name='pyjavaproperties', version='0.6', author='Jesse Noller', author_email = 'jnoller@gmail.com', description = 'Python replacement for java.util.Properties.', long_description = long_description, url='http://pypi.python.org/pypi/pyjavaproperties', license = 'PSF License', classifiers=[ 'Development Status :: 3 - Alpha', 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Topic :: Software Development :: Libraries', 'Topic :: Software Development :: Libraries :: Python Modules', ], py_modules=['pyjavaproperties'], packages=[''], package_dir={'': '.'}, ) pyjavaproperties-0.6/testdata/000077500000000000000000000000001166521526300166065ustar00rootroot00000000000000pyjavaproperties-0.6/testdata/complex.properties000066400000000000000000000020301166521526300223660ustar00rootroot00000000000000# notKey00:notValue00 This is a comment and ignored. ! notKey01:notValue01 This is a comment and ignored. # notKey02=notValue02 This is a comment and ignored. ! notKey03=notValue03 This is a comment and ignored. Key00:Value00 Key01=Value01 Key02:Value02 Key03 : Value03 Key04 = Value04 Key05: Value05a, Value05b, Value05c Key06 = Value06a, Value06b, Value06c Key07 = Value07a Key07 = Value07b Key08: Value08a, Value08b, \ Value08c, Value08d, \ Value08e, Value08f Key09 = Value09a, Value09b, \ Value09c, Value09d, \ Value09e, Value09f # notKey04=notValue04 This is a comment and ignored. Key10 Value10 ! notKey05=notValue05 This is a comment and ignored. Key11 Key12 Value12a, Value12b, Value12c Key13:Value13 With Spaces Key14=Value14 With Spaces Key15 Value15 With Spaces Key16\ With\ Spaces:Value16 Key17\ With\ Spaces=Value17 Key18 = Value18 # Not a comment. Key19 : Value19 ! Not a comment. Key20\=WithEquals = Value20 Key21\:WithColon : Value21 Key22 Value22