1616# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1717# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1818#
19- # $Id: admin.py,v 1.22 2002-08-16 04:26:42 richard Exp $
19+ # $Id: admin.py,v 1.23 2002-08-19 02:53:27 richard Exp $
2020
2121import sys , os , getpass , getopt , re , UserDict , shlex , shutil
2222try :
@@ -808,13 +808,19 @@ def do_retire(self, args):
808808 return 0
809809
810810 def do_export (self , args ):
811- '''Usage: export [class[,class]] destination_dir
811+ '''Usage: export [class[,class]] export_dir
812812 Export the database to tab-separated-value files.
813813
814814 This action exports the current data from the database into
815815 tab-separated-value files that are placed in the nominated destination
816816 directory. The journals are not exported.
817817 '''
818+ # we need the CSV module
819+ if csv is None :
820+ raise UsageError , \
821+ _ ('Sorry, you need the csv module to use this function.\n '
822+ 'Get it from: http://www.object-craft.com.au/projects/csv/' )
823+
818824 # grab the directory to export to
819825 if len (args ) < 1 :
820826 raise UsageError , _ ('Not enough arguments supplied' )
@@ -827,56 +833,38 @@ def do_export(self, args):
827833 classes = self .db .classes .keys ()
828834
829835 # use the csv parser if we can - it's faster
830- if csv is not None :
831- p = csv .parser (field_sep = ':' )
836+ p = csv .parser (field_sep = ':' )
832837
833838 # do all the classes specified
834839 for classname in classes :
835840 cl = self .get_class (classname )
836841 f = open (os .path .join (dir , classname + '.csv' ), 'w' )
837- f .write (':' .join (cl .properties .keys ()) + '\n ' )
842+ properties = cl .getprops ()
843+ propnames = properties .keys ()
844+ propnames .sort ()
845+ print >> f , p .join (propnames )
838846
839847 # all nodes for this class
840- properties = cl .getprops ()
841848 for nodeid in cl .list ():
842- l = []
843- for prop , proptype in properties :
844- value = cl .get (nodeid , prop )
845- # convert data where needed
846- if isinstance (proptype , hyperdb .Date ):
847- value = value .get_tuple ()
848- elif isinstance (proptype , hyperdb .Interval ):
849- value = value .get_tuple ()
850- elif isinstance (proptype , hyperdb .Password ):
851- value = str (value )
852- l .append (repr (value ))
853-
854- # now write
855- if csv is not None :
856- f .write (p .join (l ) + '\n ' )
857- else :
858- # escape the individual entries to they're valid CSV
859- m = []
860- for entry in l :
861- if '"' in entry :
862- entry = '""' .join (entry .split ('"' ))
863- if ':' in entry :
864- entry = '"%s"' % entry
865- m .append (entry )
866- f .write (':' .join (m ) + '\n ' )
849+ print >> f , p .join (cl .export_list (propnames , nodeid ))
867850 return 0
868851
869852 def do_import (self , args ):
870- '''Usage: import class file
871- Import the contents of the tab-separated-value file.
872-
873- The file must define the same properties as the class (including having
874- a "header" line with those property names.) The new nodes are added to
875- the existing database - if you want to create a new database using the
876- imported data, then create a new database (or, tediously, retire all
877- the old data.)
853+ '''Usage: import import_dir
854+ Import a database from the directory containing CSV files, one per
855+ class to import.
856+
857+ The files must define the same properties as the class (including having
858+ a "header" line with those property names.)
859+
860+ The imported nodes will have the same nodeid as defined in the
861+ import file, thus replacing any existing content.
862+
863+ XXX The new nodes are added to the existing database - if you want to
864+ XXX create a new database using the imported data, then create a new
865+ XXX database (or, tediously, retire all the old data.)
878866 '''
879- if len (args ) < 2 :
867+ if len (args ) < 1 :
880868 raise UsageError , _ ('Not enough arguments supplied' )
881869 if csv is None :
882870 raise UsageError , \
@@ -885,56 +873,44 @@ def do_import(self, args):
885873
886874 from roundup import hyperdb
887875
888- # ensure that the properties and the CSV file headings match
889- classname = args [0 ]
890- cl = self .get_class (classname )
891- f = open (args [1 ])
892- p = csv .parser (field_sep = ':' )
893- file_props = p .parse (f .readline ())
894- props = cl .properties .keys ()
895- m = file_props [:]
896- m .sort ()
897- props .sort ()
898- if m != props :
899- raise UsageError , _ ('Import file doesn\' t define the same '
900- 'properties as "%(arg0)s".' )% {'arg0' : args [0 ]}
901-
902- # loop through the file and create a node for each entry
903- n = range (len (props ))
904- while 1 :
905- line = f .readline ()
906- if not line : break
876+ for file in os .listdir (args [0 ]):
877+ f = open (os .path .join (args [0 ], file ))
907878
908- # parse lines until we get a complete entry
879+ # get the classname
880+ classname = os .path .splitext (file )[0 ]
881+
882+ # ensure that the properties and the CSV file headings match
883+ cl = self .get_class (classname )
884+ p = csv .parser (field_sep = ':' )
885+ file_props = p .parse (f .readline ())
886+ properties = cl .getprops ()
887+ propnames = properties .keys ()
888+ propnames .sort ()
889+ m = file_props [:]
890+ m .sort ()
891+ if m != propnames :
892+ raise UsageError , _ ('Import file doesn\' t define the same '
893+ 'properties as "%(arg0)s".' )% {'arg0' : args [0 ]}
894+
895+ # loop through the file and create a node for each entry
896+ maxid = 1
909897 while 1 :
910- l = p .parse (line )
911- if l : break
912898 line = f .readline ()
913- if not line :
914- raise ValueError , "Unexpected EOF during CSV parse"
915-
916- # make the new node's property map
917- d = {}
918- for i in n :
919- # Use eval to reverse the repr() used to output the CSV
920- value = eval (l [i ])
921- # Figure the property for this column
922- key = file_props [i ]
923- proptype = cl .properties [key ]
924- # Convert for property type
925- if isinstance (proptype , hyperdb .Date ):
926- value = date .Date (value )
927- elif isinstance (proptype , hyperdb .Interval ):
928- value = date .Interval (value )
929- elif isinstance (proptype , hyperdb .Password ):
930- pwd = password .Password ()
931- pwd .unpack (value )
932- value = pwd
933- if value is not None :
934- d [key ] = value
935-
936- # and create the new node
937- apply (cl .create , (), d )
899+ if not line : break
900+
901+ # parse lines until we get a complete entry
902+ while 1 :
903+ l = p .parse (line )
904+ if l : break
905+ line = f .readline ()
906+ if not line :
907+ raise ValueError , "Unexpected EOF during CSV parse"
908+
909+ # do the import and figure the current highest nodeid
910+ maxid = max (maxid , int (cl .import_list (propnames , l )))
911+
912+ print 'setting' , classname , maxid
913+ self .db .setid (classname , str (maxid ))
938914 return 0
939915
940916 def do_pack (self , args ):
@@ -1170,6 +1146,9 @@ def main(self):
11701146
11711147#
11721148# $Log: not supported by cvs2svn $
1149+ # Revision 1.22 2002/08/16 04:26:42 richard
1150+ # moving towards full database export
1151+ #
11731152# Revision 1.21 2002/08/01 01:07:37 richard
11741153# include info about new user roles
11751154#
0 commit comments