--- /dev/null
+include MANIFEST.in
+include m_lib/flad/test/test.cfg m_lib/flad/test/test.txt m_lib/flad/test/comment.txt
--- /dev/null
+
+ Flat ASCII Database and config files modules
+
+ FLAD is family of modules for manipulating Flat ASCII Databases.
+Flat ASCII Database is just a text file with strucrured information. For
+example, flad/fladm modules operates on the following files:
+
+ # Global comment/header for the entire file
+ # It is possible to insert empty line after header
+
+ Name: Orion
+ Type: URL
+ URL: http://www.orion.web/
+
+ Name: NRSC
+ Type: Med domain
+ Domain type: N/A
+
+ Well, I hope you get the idea. The database is just a list of records;
+records are key/value pairs separated by key_sep (flad/fladm/fladc default is
+": ", fladw default is "=", but this can be easyly changed); records are
+usually separated by empty line (fladw use different syntax).
+
+COPYRIGHT and LEGAL ISSUES
+ The software is copyrighted and free. All programs copyrighted by
+PhiloSoft Design. Programs are provided "as-is", without any kind of
+warranty.
+ #include "disclaimer.h"
+
+-------------------------------- flad --------------------------------
+
+ flad.py defines the base object, Flad. The object is real FLADatabase,
+and it serves as parent for most FLAD objects. This object provides
+framework for checking (during append/insert operations) every record. The
+module itself is not using it, but fladm (see below) make use of the
+feature.
+ The database is a list (UserList, actually) of records, where every
+record is just a dictionary mapping keys to values. Keys and values are
+just strings (this is not enforced; loading from file create a dictionaries
+of string, after loading user can add/change values; but storing to file
+routines are expecting string values again).
+
+-------------------------------- fladm -------------------------------
+
+ fladm.py defines the object Flad_WithMustKeys. This is inherently FLAD
+with restriction. User should define two set of keys - keys that must be in
+every record, and keys that can be. If there are no "must" keys - "other"
+keys don't matter. If there are "must" keys, but not "other" keys - every
+"must" key must be in every record, but any record can contain any key. If
+there are both "must" keys and "other" keys - every record must contain all
+"must" keys and some or all of "other" keys, but not other. To create
+database with only "must" keys, make "other" keys empty list - []!
+
+-------------------------------- fladc -------------------------------
+
+ fladc.py defines the object Flad_Conf. This is FLAD object to manipulate
+config files. Config file is just a FLAD file with EXACTLY one record - one
+dictionary of properties, that can be used to query and store properties.
+The resulting dictionary can be saved as FLAD file.
+
+-------------------------------- fladw -------------------------------
+
+ fladw.py defines object Flad_WIni to retrieve, manipulate and store
+WIN.INI-like files.
+ General rules for the object is the same - there are routines to load it
+from file and store back, but algorithms are quite different. Records are
+sections; sections are separated by section names - [section_name], e.g.
+ Every record in Flad_WIni is tuple
+(section_name_string, [list_of_comments_and_keys], {dict_of_key-to-value_mapping}).
+ There are procedures to add/remove sections, add/del/change/query key values.
--- /dev/null
+"Broytman Flat ASCII Database for Python, Copyright (C) 1996-2001 PhiloSoft Design"
--- /dev/null
+"""
+ Flat ASCII Database.
+ This module implements a very simple database on the flat ASCII files.
+
+ Written by Broytman. Copyright (C) 1997-2005 PhiloSoft Design
+"""
+
+
+import string
+from UserList import UserList
+
+
+# Flad restriction error
+checking_error = "flad.checking_error"
+
+# Default key/value separator
+def_keysep = ": "
+
+
+class Flad(UserList):
+ """
+ Class to represent memory database.
+ FLAD database is a list of records,
+ where every record is a dictionary.
+ """
+
+ # Field and record separators are ALWAYS newline. It cannot be changed
+ # without extensive rewriting of this module
+ # field_sep = rec_sep = '\n'
+
+ def __init__(self, check_record_func = None, key_sep = def_keysep):
+ UserList.__init__(self)
+ self.check_record_func = check_record_func
+ self.key_sep = key_sep
+
+ self.comment = ''
+ self.wait_comment = 1
+
+
+ def check_record(self, record): # Method can be overriden in subclasses
+ if self.check_record_func:
+ if callable(self.check_record_func):
+ return self.check_record_func(self, record)
+ else:
+ raise TypeError, "non-callable restriction function"
+ else:
+ return 1
+
+
+ def checking_error(self): # Method can be overriden in subclasses
+ raise checking_error
+
+
+ def __setitem__(self, i, item):
+ if not self.check_record(item):
+ self.checking_error()
+ else:
+ UserList.__setitem__(self, i, item)
+
+
+ def __setslice__(self, i, j, list):
+ if list:
+ copy_list = list[:]
+ for item in list:
+ if not self.check_record(item):
+ self.checking_error()
+ del copy_list[copy_list.index(item)]
+ UserList.__setslice__(self, i, j, copy_list)
+
+
+ def append(self, item):
+ if not self.check_record(item):
+ self.checking_error()
+ else:
+ UserList.append(self, item)
+
+
+ def insert(self, i, item):
+ if not self.check_record(item):
+ self.checking_error()
+ else:
+ UserList.insert(self, i, item)
+
+
+ def split_key(self, line):
+ """
+ Split input line to key/value pair and add the pair to dictionary
+ """
+ ###line = string.lstrip(line) # Do not rstrip - if empty value, this will remove space from key
+ if line[-1] == '\n':
+ line = line[:-1] # Chop
+
+ l = string.split(line, self.key_sep, 1) # Just split to key and reminder
+ return tuple(l)
+
+
+ def __parse_line(self, record, line): # Internal function
+ if line == '\n': # Empty line is record separator (but there cannot be more than 1 empty lines)
+ if record: # This helps to skip all empty lines
+ self.append(record) # Check and add the record to list
+ return 1 # Signal to stop filling the record and start a new one
+
+ else:
+ key, value = self.split_key(line)
+ if key in record.keys(): # This have to be done with check_record
+ # but the record is not complete now,
+ # so it is not ready to be checked :(
+ # And, of course, two keys with the same name
+ # cannot be added to dictionary
+ raise KeyError, "field key \"" + key + "\" already in record"
+
+ record[key] = value
+
+ return 0
+
+
+ def create_new_record(self): # Method can be overriden in subclasses
+ return {}
+
+
+ def feed(self, record, line): # Method can be overriden in subclasses
+ if line:
+ if self.wait_comment:
+ if string.strip(line) == '':
+ self.comment = self.comment + '\n'
+ self.wait_string = 0
+ return 0
+
+ elif string.lstrip(line)[0] == '#':
+ self.comment = self.comment + line
+ return 0
+
+ else:
+ self.wait_comment = 0
+ # Fallback to parsing
+
+ return self.__parse_line(record, line)
+
+ else:
+ self.append(record)
+
+ return 0
+
+
+ def load_file(self, f):
+ """
+ Load a database from file as a list of records.
+ Every record is a dictionary of key/value pairs.
+ The file is reading as whole - this is much faster, but require
+ more memory.
+ """
+
+ if type(f) == type(''): # If f is string - use it as file's name
+ infile = open(f, 'r')
+ else:
+ infile = f # else assume it is opened file (fileobject) or
+ # "compatible" object (must has readline() methods)
+
+ try:
+ lines = infile.readlines()
+
+ finally:
+ if type(f) == type(''): # If f was opened - close it
+ infile.close()
+
+ record = self.create_new_record()
+
+ for line in lines:
+ if self.feed(record, line):
+ record = self.create_new_record()
+
+ # Close record on EOF without empty line
+ if record:
+ self.feed(record, None)
+
+
+ def load_from_file(self, f):
+ """
+ Load a database from file as a list of records.
+ Every record is a dictionary of key/value pairs.
+ The file is reading line by line - this is much slower, but do not
+ require so much memory. (On systems with limited virtual memory,
+ like DOS, it is even faster - for big files)
+ """
+
+ if type(f) == type(''): # If f is string - use it as file's name
+ infile = open(f, 'r')
+ else:
+ infile = f # else assume it is opened file (fileobject) or
+ # "compatible" object (must has readline() method)
+
+ record = self.create_new_record()
+
+ try:
+ line = infile.readline()
+
+ while line:
+ if self.feed(record, line):
+ record = self.create_new_record()
+
+ line = infile.readline()
+
+ finally:
+ if type(f) == type(''): # If f was opened - close it
+ infile.close()
+
+ # Close record on EOF without empty line
+ if record:
+ self.feed(record, None)
+
+
+ def store_to_file(self, f):
+ if type(f) == type(''): # If f is string - use it as file's name
+ outfile = open(f, 'w')
+ else:
+ outfile = f # else assume it is opened file (fileobject) or
+ # "compatible" object (must has write() method)
+
+ flush_record = 0 # Do not close record on 1st loop
+
+ if self.comment <> '':
+ outfile.write(self.comment)
+
+ for record in self:
+ copy_rec = record.copy() # Make a copy to delete keys
+
+ if flush_record:
+ outfile.write('\n') # Close record
+ else:
+ flush_record = 1 # Set flag for all but 1st record
+
+ if copy_rec:
+ for key in copy_rec.keys():
+ outfile.write(key + self.key_sep + copy_rec[key] + '\n')
+ del copy_rec[key]
+
+ if type(f) == type(''): # If f was opened - close it
+ outfile.close()
+
+
+def load_file(f, check_record_func = None):
+ """
+ Create a database object and load it from file
+ """
+
+ db = Flad(check_record_func)
+ db.load_file(f)
+
+ return db
+
+
+def load_from_file(f, check_record_func = None):
+ """
+ Create a database object and load it from file
+ """
+
+ db = Flad(check_record_func)
+ db.load_from_file(f)
+
+ return db
--- /dev/null
+"""
+ Flat ASCII Database to implement VERY simple config files.
+
+ Written by Broytman. Copyright (C) 1997-2005 PhiloSoft Design
+"""
+
+
+import flad, fladm
+
+
+error = "fladc.error" # Too many records
+
+
+class Flad_Conf(dict):
+ """
+ FLAD config is just FLAD Database with exactly ONE record.
+ Flad_Conf objects are just UserDicts.
+ """
+ def __init__(self, must_keys = None, other_keys = None):
+ dict.__init__(self)
+
+ self.must_keys = must_keys
+ self.other_keys = other_keys
+
+
+ def __make_db(self):
+ if self.must_keys:
+ db = fladm.Flad_WithMustKeys(check_record, self.must_keys, self.other_keys)
+ else:
+ db = flad.Flad()
+
+ return db
+
+
+ def load_file(self, f):
+ db = self.__make_db()
+ db.load_file(f)
+
+ if len(db) <> 1:
+ raise error, "incorrect number of records in config file `%s'; expected 1, got %d" % (str(f), len(db))
+
+ self.data = db[0]
+
+
+ def load_from_file(self, f):
+ db = self.__make_db()
+ db.load_from_file(f)
+
+ if len(db) <> 1:
+ raise error, "incorrect number of records in config file `%s'; expected 1, got %d" % (str(f), len(db))
+
+ self.data = db[0]
+
+
+ def store_to_file(self, f):
+ db = self.__make_db()
+ db.append(self.data)
+ db.store_to_file(f)
+
+
+def check_record(data, record): # Only allow append 1 record
+ return len(data) == 0
+
+
+def load_file(f, must_keys = None, other_keys = None):
+ """
+ Create a database object and load it from file
+ """
+
+ db = Flad_Conf(must_keys, other_keys)
+ db.load_file(f)
+
+ return db
+
+
+def load_from_file(f, must_keys = None, other_keys = None):
+ """
+ Create a database object and load it from file
+ """
+
+ db = Flad_Conf(must_keys, other_keys)
+ db.load_from_file(f)
+
+ return db
--- /dev/null
+"""
+ Flat ASCII Database with "must" keys
+
+ Written by Broytman. Copyright (C) 1997-2005 PhiloSoft Design
+"""
+
+
+from flad import Flad, def_keysep
+
+
+class Flad_WithMustKeys(Flad):
+ """
+ Database with two lists of keys - keys that must be in every record,
+ and keys that allowed to be in some records.
+ """
+
+ def __init__(self, check_record_func = None, must_keys = None, other_keys = None):
+ Flad.__init__(self, check_record_func)
+ self.must_keys = must_keys # Save keys lists to store...
+ self.other_keys = other_keys #... desired sequence of keys
+
+
+ def store_to_file(self, f):
+ if type(f) == type(''): # If f is string - use it as file's name
+ outfile = open(f, 'w')
+ else:
+ outfile = f # else assume it is opened file (fileobject) or
+ # "compatible" object (must has write() method)
+
+ flush_record = 0 # Do not close record on 1st loop
+
+ for record in self:
+ copy_rec = record.copy() # Make a copy to delete keys
+
+ if flush_record:
+ outfile.write('\n') # Close record
+ else:
+ flush_record = 1 # Set flag for all but 1st record
+
+ if self.must_keys:
+ for key in self.must_keys:
+ outfile.write(key + def_keysep + copy_rec[key] + '\n')
+ del copy_rec[key]
+
+ if self.other_keys:
+ for key in self.other_keys:
+ if copy_rec.has_key(key):
+ outfile.write(key + def_keysep + copy_rec[key] + '\n')
+ del copy_rec[key]
+
+ if copy_rec:
+ for key in copy_rec.keys():
+ outfile.write(key + def_keysep + copy_rec[key] + '\n')
+ del copy_rec[key]
+
+ if type(f) == type(''): # If f was open - close it
+ outfile.close()
+
+
+def check_record(data, record):
+ """
+ Check record for consistency and append it to list of records
+ """
+ must_keys = data.must_keys
+ other_keys = data.other_keys
+
+ if must_keys:
+ copy_must = must_keys[:] # Make a copy
+ else:
+ copy_must = None
+
+ for key in record.keys(): # Check every key
+ if must_keys and (key in must_keys):
+ del copy_must[copy_must.index(key)] # Remove the key from copied list
+ elif (must_keys and (key not in must_keys) and (other_keys and (key not in other_keys))) or (other_keys and (key not in other_keys)):
+ raise KeyError, "field key \"" + key + "\" is not in list of allowed keys"
+
+ if copy_must: # If there is at least one key - it is an error:
+ # not all "must" keys are in record
+ raise KeyError, "not all \"must\" keys are in record; keys: " + str(copy_must)
+
+ return 1
+
+
+def load_file(f, check_record_func = None, must_keys = None, other_keys = None):
+ """
+ Create a database object and load it from file
+ """
+
+ db = Flad_WithMustKeys(check_record_func, must_keys, other_keys)
+ db.load_file(f)
+
+ return db
+
+
+def load_from_file(f, check_record_func = None, must_keys = None, other_keys = None):
+ """
+ Create a database object and load it from file
+ """
+
+ db = Flad_WithMustKeys(check_record_func, must_keys, other_keys)
+ db.load_from_file(f)
+
+ return db
--- /dev/null
+"""
+ Flat ASCII Database to load WIN.INI-like files.
+
+ Written by Broytman. Copyright (C) 1997-2005 PhiloSoft Design
+"""
+
+
+import string, re
+import flad
+
+
+error = "fladw.error"
+section_error = "fladw.section_error"
+
+
+re_section = re.compile("^ *\[(.+)\] *$")
+
+
+class Flad_WIni(flad.Flad):
+ """
+ FLAD database is a list of records, where every record is
+ a tuple (section_name, keys, section_dictionary).
+ Sounds similary to Flad? But it is Flad! The only difference is that
+ Flad_WIni has section names and keys (i.e. list of keys and comments
+ in every section to preserve comments and desired order of keys).
+ """
+ def __init__(self):
+ flad.Flad.__init__(self, key_sep = '=')
+ self.first_section = 1
+
+
+ def __parse_line(self, record, line): # Internal function
+ match = re_section.match(line) # Record separator is section name
+ if match:
+ return match.group(1) # Signal to stop filling the record (section) and start a new one
+
+ if self.first_section:
+ if string.strip(line) <> '':
+ raise error, "non-empty line before 1st section"
+
+ elif (string.strip(line) == '') or (string.lstrip(line)[0] == ';') : # Empty line or comment
+ record[0].append(line)
+
+ else:
+ key, value = self.split_key(line)
+ if key in record[1].keys(): # This have to be done with check_record
+ # but the record is not complete now,
+ # so it is not ready to be checked :(
+ # And, of course, two keys with the same name
+ # cannot be added to dictionary
+ raise KeyError, "field key \"" + key + "\" already in record"
+
+ record[0].append(key)
+ record[1][key] = value
+
+ return 0
+
+
+ def create_new_record(self):
+ return ([], {})
+
+
+ def feed(self, record, line):
+ if line:
+ section = self.__parse_line(record, line)
+ if section:
+ if not self.first_section:
+ self.append((self.section, record[0], record[1]))
+ self.section = section
+
+ return 1 # Section filled - create new section
+ else:
+ self.first_section = 0
+ self.section = section
+
+ else:
+ if self.first_section and (string.strip(line) <> ''):
+ raise error, "non-empty line before 1st section"
+ # else: line had been appended to section in __parse_line()
+
+ else: # This called after last line of the source file
+ self.append((self.section, record[0], record[1]))
+ del self.section, self.first_section
+
+ # Now remove last empty line in every section
+ for record in self:
+ klist = record[1]
+ if klist:
+ l = len(klist) - 1
+ if string.strip(klist[l]) == '':
+ del klist[l]
+
+ return 0
+
+
+ def store_to_file(self, f):
+ if type(f) == type(''): # If f is string - use it as file's name
+ outfile = open(f, 'w')
+ else:
+ outfile = f # else assume it is opened file (fileobject) or
+ # "compatible" object (must has write() method)
+
+ flush_section = 0 # Do not close 1st section
+
+ for record in self:
+ if flush_section:
+ outfile.write('\n') # Close section
+ else:
+ flush_section = 1 # Set flag for all but 1st section
+
+ outfile.write('[' + record[0] + ']\n') # Section
+
+ if record[1]:
+ for key in record[1]:
+ if string.strip(key) == '' or string.lstrip(key)[0] == ';' :
+ outfile.write(key)
+ else:
+ outfile.write(key + self.key_sep + record[2][key] + '\n')
+
+ if type(f) == type(''): # If f was opened - close it
+ outfile.close()
+
+
+ def find_section(self, section):
+ for i in range(0, len(self)):
+ record = self[i]
+ if record[0] == section:
+ return i
+
+ return -1
+
+
+ def add_section(self, section):
+ rec_no = self.find_section(section)
+ if rec_no >= 0:
+ raise section_error, "section [%s] already exists" % section
+
+ self.append((section, [], {}))
+
+
+ def del_section(self, section):
+ rec_no = self.find_section(section)
+ if rec_no < 0:
+ raise section_error, "section [%s] does not exists" % section
+
+ del self[rec_no]
+
+
+ def set_keyvalue(self, section, key, value):
+ rec_no = self.find_section(section)
+ if rec_no < 0:
+ record = (section, [key], {key: value})
+ self.append(record)
+
+ else:
+ record = self[rec_no]
+ if key not in record[1]:
+ record[1].append(key)
+ record[2][key] = value
+
+
+ def get_keyvalue(self, section, key):
+ rec_no = self.find_section(section)
+ if rec_no < 0:
+ raise section_error, "section [%s] does not exists" % section
+
+ record = self[rec_no]
+ if key not in record[1]:
+ raise KeyError, "section [%s] does not has `%s' key" % (section, key)
+
+ return record[2][key]
+
+
+ def get_keydefault(self, section, key, default):
+ rec_no = self.find_section(section)
+ if rec_no < 0:
+ return default
+
+ record = self[rec_no]
+ if key not in record[1]:
+ return default
+
+ return record[2][key]
+
+
+ def del_key(self, section, key):
+ rec_no = self.find_section(section)
+ if rec_no < 0:
+ raise section_error, "section [%s] does not exists" % section
+
+ record = self[rec_no]
+ if key not in record[1]:
+ raise KeyError, "section [%s] does not has `%s' key" % (section, key)
+
+ klist = record[1]
+ del klist[klist.index(key)]
+ del record[2][key]
+
+
+def load_file(f):
+ db = Flad_WIni()
+ db.load_file(f)
+
+ return db
+
+
+def load_from_file(f):
+ db = Flad_WIni()
+ db.load_from_file(f)
+
+ return db
--- /dev/null
+"Broytman Flat ASCII Database for Python - Test, Copyright (C) 1996-2001 PhiloSoft Design"
--- /dev/null
+# This is test FLAD (Flat ASCII Database)
+
+Type: Public URL
+Name: Test 1
+
+Type: Public Dir
+Name: Test 2
+
+Type: Private Dir
+Name: Test 3
--- /dev/null
+Type: Public URL
+Name: Test 1
\ No newline at end of file
--- /dev/null
+Type: Public URL
+Name: Test 1
+
+Type: Public Dir
+Name: Test 2
+
+Type: Private Dir
+Name: Test 3
--- /dev/null
+#! /usr/bin/env python
+
+
+from m_lib.flad import fladm
+
+
+def test():
+ print
+ print "Test 1:",
+ fladm.load_from_file("test.txt", fladm.check_record, None, None)
+ print "Ok"
+
+ print "Test 2:",
+ fladm.load_from_file("test.txt", fladm.check_record, ["Type"], None)
+ print "Ok"
+
+ print "Test 3:",
+ fladm.load_from_file("test.txt", fladm.check_record, ["Type", "Name"], None)
+ print "Ok"
+
+ print "Test 4:",
+ fladm.load_from_file("test.txt", fladm.check_record, ["Type"], ["Name"])
+ print "Ok"
+
+ print "Test 5:",
+ try: # Note! This must raise KeyError - "Name" key is not listed
+ fladm.load_from_file("test.txt", fladm.check_record, ["Type"], [""])
+ except KeyError:
+ print "Ok"
+ else:
+ print "Error!"
+
+ print "Test 6:",
+ fladm.load_from_file("test.txt", fladm.check_record, None, ["Type", "Name"])
+ print "Ok"
+
+ print "Test 7:",
+ try: # Note! This must raise KeyError - "Error" key is listed in must field
+ fladm.load_from_file("test.txt", fladm.check_record, ["Error"], ["Type"])
+ except KeyError:
+ print "Ok"
+ else:
+ print "Error!"
+
+ print "Test 8:",
+ datalist = fladm.load_from_file("test.txt", fladm.check_record, None, ["Type", "Name", "Error"])
+ print "Ok"
+
+ print "\nLast but not test: just printing loaded list"
+ print datalist
+ print
+
+
+if __name__ == "__main__":
+ test()
--- /dev/null
+#! /usr/bin/env python
+
+
+from m_lib.flad import flad
+
+
+def test():
+ print "Test 1:",
+ datalist = flad.load_from_file("test.txt")
+ datalist.store_to_file("test2.o1")
+ print "Ok"
+
+ print "Test 2:",
+ datalist = flad.load_from_file("comment.txt")
+ datalist.store_to_file("test2.o2")
+ print "Ok"
+
+
+if __name__ == "__main__":
+ test()
--- /dev/null
+#! /usr/bin/env python
+
+
+from m_lib.flad import fladm
+
+
+def test():
+ print "Test:",
+ datalist = fladm.load_file("test.txt", fladm.check_record, ["Type"], ["Name"])
+ datalist.store_to_file("test3.out")
+ print "Ok"
+
+
+if __name__ == "__main__":
+ test()
--- /dev/null
+#! /usr/bin/env python
+
+
+from m_lib.flad import fladc
+
+
+def test():
+ print "Test:",
+ conf = fladc.load_file("test.cfg")
+ print "Ok"
+
+ print "Property 'Type' is", conf["Type"]
+
+
+if __name__ == "__main__":
+ test()
--- /dev/null
+#! /usr/bin/env python
+
+
+from m_lib.flad import fladc
+
+
+def test():
+ print "Test:",
+
+ try: # Note! This must raise fladc.error - too many records in the file
+ conf = fladc.load_file("test.txt")
+ except fladc.error:
+ print "Ok"
+ else:
+ print "Error!"
+
+
+if __name__ == "__main__":
+ test()
--- /dev/null
+#! /usr/bin/env python
+
+
+from m_lib.flad import fladc
+
+
+def test():
+ print "Test:",
+ conf = fladc.load_file("test.cfg", ["Type", "Name"])
+ conf.store_to_file("test6.out")
+ print "Ok"
+
+
+if __name__ == "__main__":
+ test()
--- /dev/null
+#! /usr/bin/env python
+
+
+from m_lib.flad import fladw
+
+
+def test():
+ print "Test:",
+ ini = fladw.load_file("C:\\WINDOWS\\WIN.INI")
+ ini.store_to_file("test7.out")
+ print "Ok"
+
+ print "windows/BorderWidth =", ini.get_keyvalue("windows", "BorderWidth")
+
+
+if __name__ == "__main__":
+ test()
from distutils.core import setup
setup(name = "m_lib",
- version = "2.0",
- description = "Broytman Library for Python",
- long_description = "Broytman Library for Python, Copyright (C) 1996-2013 PhiloSoft Design",
- author = "Oleg Broytman",
- author_email = "phd@phdru.name",
- url = "http://phdru.name/Software/Python/#m_lib",
- license = "GPL",
- platforms = "All",
- packages = ["m_lib", "m_lib.clock", "m_lib.lazy",
- "m_lib.net", "m_lib.net.ftp", "m_lib.net.www", "m_lib.rus"]
+ version = "2.0",
+ description = "Broytman Library for Python",
+ long_description = "Broytman Library for Python, Copyright (C) 1996-2013 PhiloSoft Design",
+ author = "Oleg Broytman",
+ author_email = "phd@phdru.name",
+ url = "http://phdru.name/Software/Python/#m_lib",
+ license = "GPL",
+ platforms = "All",
+ packages = ["m_lib", "m_lib.clock",
+ "m_lib.flad", "m_lib.flad.test", "m_lib.lazy",
+ "m_lib.net", "m_lib.net.ftp", "m_lib.net.www", "m_lib.rus",
+ ],
+ data_files = [("%s/m_lib/flad/test" % python_lib, [
+ "m_lib/flad/test/test.cfg",
+ "m_lib/flad/test/test.txt",
+ "m_lib/flad/test/comment.txt",
+ ])]
)