def run(self, gui): """Given a fresh empty master database in self.dbm, fill it from the open backup database file (self.dbs). """ try: # Create tables t = u"config" gui.report(_("Creating table '%s'") % t) self.makeTable(t) self.restoreTable(t) gui.report(_("Creating table 'data'")) self.dbm.createDataTable() self.restoreDataTable() self.dbm.createInterfaceTable() gui.report(_("Created interface table")) # Copy reports gui.report(_("Creating teacher report tables ...")) t = u"reports" # Get list of teachers from configuration data for tch in self.dbs.listAllFiles(u"teachers/"): self.makeTable(teacher2user(tch[9:])) # Parse all class configuration data, to determine # ownership of reports reports = makeReportsDict(self.dbs) for id, value in self.dbs.read(u"SELECT * FROM %s" % t): table = teacher2user(reports[id]) sqlins = u"INSERT INTO %s VALUES(?, ?)" % table self.dbm.send(sqlins, (id, value)) #********* This was just an idea, but it may never be used. # # Copy comments # gui.report(_("Copying comments ...")) # t = "comments" # self.makeTable(t) # self.restoreTable(t) gui.report(_("DONE!")) except: print_exc() message(_("Couldn't restore database")) self.dbm = None self.close()
def init(self, gui, filepath, forceDialog=False): self.gui = gui self.filepath = filepath # Get the path to the user database file self.dbs = None dbDir = None dbPath = self.settings.getSetting("dbFile") while True: if not self.filepath: if dbPath: dbd = os.path.dirname(dbPath) if os.path.isdir(dbd): dbDir = dbd if os.path.isfile(dbPath): self.filepath = dbPath dbPath = None if forceDialog or not self.filepath: self.filepath = getFile(_("User Database File"), startDir=dbDir, defaultSuffix=u".zga", filter=(_("Database Files"), (u"*.zga",))) if not self.filepath: return self.dbs = DBs(self.filepath) if self.dbs.isOpen(): break dbDir = os.path.dirname(self.filepath) self.filepath = None self.settings.setSetting("dbFile", self.filepath) # Set window title self.gui.setTitle(_("Synchronize %s") % self.filepath) self.dbm = None # Get the default host name from the 'base' data self.dbhost = self.dbs.baseDict[u"masterHost"] # Get information from the 'config' table self.dbname = self.dbs.getConfig(u"dbname") teacher = self.dbs.getConfig(u"me") if not teacher: error(_("'%s' is not a teacher's database file") % self.filepath) self.dbuser = teacher2user(teacher) # Close user database file self.closeFile() # set gui lineEdits self.gui.setDBinfo(self.dbhost, self.dbname, self.dbuser, self.filepath)
def makeReports(self): """Update the teachers' report tables, adding and removing tables and records where demanded by the configuration changes. """ # Get a list of existing teacher tables ttables = self.db.getTeacherTables() # Get an updated list of teachers from the config data teachers = self.source.listFiles("teachers") # Create any new tables needed, and check for reports which # must be added or deleted allReports = makeReportsDict(self.source) for teacher in teachers: tbname = teacher2user(teacher) if tbname in ttables: ttables.remove(tbname) for rep in self.db.listIds(tbname): if allReports.has_key(rep): # Mark this report as already existing allReports[rep] = None else: self.report(_("Deleting report %1"), (rep, )) sqldel = u"DELETE FROM %s WHERE id = ?" % tbname self.db.send(sqldel, (rep, )) else: self.db.createIVTable(tbname) self.report(_("... made %1"), (tbname, )) self.report(_("Creating initial reports")) for key, t in allReports.items(): if t: sqlins = u"INSERT INTO %s VALUES(?, ?)" % teacher2user(t) self.db.send(sqlins, (key, makeReportValue(u"", u""))) # Remove unneeded tables for tbname in ttables: self.report(_("... removing %1"), (tbname, )) self.db.send(u"DROP TABLE %s" % tbname)
def makeReports(self): """Update the teachers' report tables, adding and removing tables and records where demanded by the configuration changes. """ # Get a list of existing teacher tables ttables = self.db.getTeacherTables() # Get an updated list of teachers from the config data teachers = self.source.listFiles("teachers") # Create any new tables needed, and check for reports which # must be added or deleted allReports = makeReportsDict(self.source) for teacher in teachers: tbname = teacher2user(teacher) if tbname in ttables: ttables.remove(tbname) for rep in self.db.listIds(tbname): if allReports.has_key(rep): # Mark this report as already existing allReports[rep] = None else: self.report(_("Deleting report %1"), (rep,)) sqldel = u"DELETE FROM %s WHERE id = ?" % tbname self.db.send(sqldel, (rep,)) else: self.db.createIVTable(tbname) self.report(_("... made %1"), (tbname,)) self.report(_("Creating initial reports")) for key, t in allReports.items(): if t: sqlins = u"INSERT INTO %s VALUES(?, ?)" % teacher2user(t) self.db.send(sqlins, (key, makeReportValue(u"", u""))) # Remove unneeded tables for tbname in ttables: self.report(_("... removing %1"), (tbname,)) self.db.send(u"DROP TABLE %s" % tbname)
def run(self, gui): """Copy the master database to the slave. """ try: # Create tables table = u"config" gui.report(_("Creating table '%s'") % table) self.makeTable(table) self.dumpTable(table) gui.report(_("Creating table 'data'")) self.dbs.createDataTable() if self.teacher: # Don't dump the image files, just that for the current teacher self.dumpDataTable( r"(?!imagefiles/)|imagefiles/teachers/%s\." % self.teacher) else: self.dumpDataTable() # Copy reports gui.report(_("Copying reports ...")) table = u"reports" self.makeTable(table) if self.teacher: # Database user for self.teacher (also report table name) user = teacher2user(self.teacher) # Only copy the owner's reports self.dumpTable(user, table) else: for tm in self.dbm.getTeacherTables(): self.dumpTable(tm, table) #********* This was just an idea, but it may never be used. # # Copy comments # gui.report(_("Copying comments ...")) # table = u"comments" # self.makeTable(table) # if self.teacher: # # Only copy comments pertaining to the owner's reports # okIds = self.dbm.listIds(user) # for c in self.dbm.listIds(table): # if c in okIds: # for v in self.dbm.read(u"""SELECT value FROM comments # WHERE id = ?""", (c,)): # self.dbs.send(u"""INSERT INTO comments # VALUES(?, ?)""", (c, v[0])) # # else: # self.dumpTable(table) if self.teacher: # Set creation time self.dbs.send( u"""INSERT INTO config VALUES('createtime', ?)""", (self.ctime, )) # Set db-file 'owner' self.dbs.send( u"""UPDATE config SET value = ? WHERE id = 'me'""", (self.teacher, )) else: # Set the last backup time self.dbs.send( u"""UPDATE config SET value = ? WHERE id = 'backuptime'""", (self.ctime, )) self.dbm.send( u"""UPDATE config SET value = ? WHERE id = 'backuptime'""", (self.ctime, )) self.dbs.close() self.dbs = None gui.report(_("DONE!")) except: print_exc() message( _("Couldn't create database file." " Removing incomplete file (%1)"), (self.filepath, )) if self.dbs.isOpen(): self.dbs.close() os.remove(self.filepath) self.dbs = None self.filepath = None
def run(self, gui): """Copy the master database to the slave. """ try: # Create tables table = u"config" gui.report(_("Creating table '%s'") % table) self.makeTable(table) self.dumpTable(table) gui.report(_("Creating table 'data'")) self.dbs.createDataTable() if self.teacher: # Don't dump the image files, just that for the current teacher self.dumpDataTable(r"(?!imagefiles/)|imagefiles/teachers/%s\." % self.teacher) else: self.dumpDataTable() # Copy reports gui.report(_("Copying reports ...")) table = u"reports" self.makeTable(table) if self.teacher: # Database user for self.teacher (also report table name) user = teacher2user(self.teacher) # Only copy the owner's reports self.dumpTable(user, table) else: for tm in self.dbm.getTeacherTables(): self.dumpTable(tm, table) #********* This was just an idea, but it may never be used. # # Copy comments # gui.report(_("Copying comments ...")) # table = u"comments" # self.makeTable(table) # if self.teacher: # # Only copy comments pertaining to the owner's reports # okIds = self.dbm.listIds(user) # for c in self.dbm.listIds(table): # if c in okIds: # for v in self.dbm.read(u"""SELECT value FROM comments # WHERE id = ?""", (c,)): # self.dbs.send(u"""INSERT INTO comments # VALUES(?, ?)""", (c, v[0])) # # else: # self.dumpTable(table) if self.teacher: # Set creation time self.dbs.send(u"""INSERT INTO config VALUES('createtime', ?)""", (self.ctime,)) # Set db-file 'owner' self.dbs.send(u"""UPDATE config SET value = ? WHERE id = 'me'""", (self.teacher,)) else: # Set the last backup time self.dbs.send(u"""UPDATE config SET value = ? WHERE id = 'backuptime'""", (self.ctime,)) self.dbm.send(u"""UPDATE config SET value = ? WHERE id = 'backuptime'""", (self.ctime,)) self.dbs.close() self.dbs = None gui.report(_("DONE!")) except: print_exc() message(_("Couldn't create database file." " Removing incomplete file (%1)"), (self.filepath,)) if self.dbs.isOpen(): self.dbs.close() os.remove(self.filepath) self.dbs = None self.filepath = None
def synchronize(dbm, filepath, gui): """Synchronize the given file with the given (open) master database. """ # Current master time mtime = dbm.getTime() # Move the user database file to backup location dir = os.path.dirname(filepath) bfile = re.sub(".zga$", "_%s.zga" % mtime, filepath) if (os.name == 'posix'): try: if Popen(["lsof", filepath], stdout=PIPE).communicate()[0]: warning(_("The database file (%1) is being used" " by another application"), (filepath,)) return except: warning(_("You should install 'lsof' so that usage" " of the file can be tested")) try: os.rename(filepath, bfile) except: # This trap only works on Windows. Linux will happily # allow you to delete a file while another program is # working on it! 'lsof filename' (see above) should be # a way to avoid that. warning(_("Couldn't rename the database file (%1).\n" "Is it being used by another application?"), (filepath,)) return gui.report(_("Database file renamed to %s") % bfile) dbs = DBs(bfile) if not dbs.isOpen(): os.rename(bfile, filepath) return # Teacher's report table teacher = dbs.getConfig(u"me") mtb = teacher2user(teacher) if mtb not in dbm.getTeacherTables(): warning(_("%1: Owning teacher (%2) not known to master database"), (filepath, teacher)) return gui.report(_("Copying reports from user database to master")) # Counter for transferred reports rcount = 0 # Creation time of slave db, i.e. last sync time ctime = dbs.getConfig(u"createtime") # Get all updated reports for id, data in dbs.read(u"SELECT * FROM reports"): # Split off the version data dver, drep = data.split(u"\n", 1) # Get the master version data try: mver = dbm.readValue(mtb, id).split(u"\n", 1)[0] except: gui.report(_("Invalid report, not updated : %s") % id) if (mver > ctime): if confirmationDialog(_("Report update problem"), _("Master version of report has been updated" " since this client was last synchronized.\n" " Replace that version of '%s'?") % id, False): gui.report(_("Revised master version of report '%s'" " will be overwritten") % id) else: gui.report(_("Revised master version of report '%s'" " not overwritten") % id) continue elif (dver <= mver): # Only do anything if the local version is newer than the # the master version continue if (dver > mtime): # The new version has a time stamp later than the # current time on the master, adjust it if dver.endswith(u"$"): dver = mtime + u"$" else: dver = mtime try: sqlupd = u"UPDATE %s SET value = ? WHERE id = ?" % mtb dbm.send(sqlupd, (dver + u"\n" + drep, id)) rcount += 1 except: gui.report(_("Couldn't update report '%s'") % id) gui.report(_("Transferred %d reports") % rcount) # Close the user database dbs.close() # Remember the latest sync time if rcount: dbm.send(u"""UPDATE interface SET value = ? WHERE id = 'lastsynctime'""", (mtime,)) # Recreate the user database gui.report(_("Recreating the user database")) recreate(dbm, filepath, teacher, gui)