import DB
import DBTables
import pyio

True = 1
False = 0

# Misc
def DisplayTypesStats(*args):
  for i in apply(pyio.GetTypesStats, args): # Requested types
  #for i in pyio.GetTypesStats('TTable', 'TField'): # Only the types TTable and TField
    print "--------------------------------------------------------------------------------"
    print "TYPE ", i[0]
    print "    Instance count :", i[1]
    print "    Create Hits :", i[2]
    print "    Delete Hits :", i[3]
  print "--------------------------------------------------------------------------------"

# Event functions

def AfterScroll(Dataset):
  print "---------> Scrolled to rec #"+str(Dataset.RecNo)+" <--------------"

# Event methods

# WARNING :
# ---------
# if you store the TTable in your C instance, and if you use events,
# you must be aware of the reference counting mechanism, and its
# failure on circular references:
# c = C(): c refcount = 1
# c.T = CreateTTable(): c.T refcount = 1
# c.T.OnAfterOpen = c.OnAfterOpen: c refcount = 2
# del c: c refcount = 1 and you loose any reference on your c instance
# which still contains a TTable.
# so if you want to avoid the leaking, then you must clear the events
# before you delete the instance:
# c.T.OnAfterOpen = None: c refcount = 1
# del c: c refcount = 0 -> c is deleted
#
# Try to use try..finally constructs, in order to avoid
# the leaking if an exception is raised before you can free the
# resources.
#
# Don't forget to close the TTable, if you want to get the Before/After
# close events, because when destroying a TTable, we first clear all
# events. But that's the case with the Delphi behaviour too.

class C:
  def __init__(Self):
    # Create and open the table
    Self.T = DBTables.CreateTTable()
    Self.T.DatabaseName   = "DBDemos"
    Self.T.TableName      = "customer.db"
    Self.T.AfterScroll    = AfterScroll         # a global function
    Self.T.BeforeOpen     = Self.BeforeOpen     # a method of the c instance of class C
    Self.T.AfterOpen      = Self.AfterOpen      # a method of the c instance of class C
    Self.T.BeforeClose    = Self.BeforeClose    # a method of the c instance of class C
    Self.T.AfterClose     = Self.AfterClose     # a method of the c instance of class C
    Self.T.OnFilterRecord = Self.OnFilterRecord # a method of the c instance of class C
    Self.T.Filtered = True
    Self.T.Open()

  def __del__(Self):
    print "c instance deleted"

  def Free(Self):
    Self.T.Close()
    del Self.T

  def BeforeOpen(Self, Dataset):
    Self.Name = Dataset.DatabaseName + ":" + Dataset.TableName
    print "Before Open of ", Self.Name

  def AfterOpen(Self, Dataset):
    print "After Open of ", Self.Name

  def BeforeClose(Self, Dataset):
    print "Before close of ", Self.Name

  def AfterClose(Self, Dataset):
    print "After Close of ", Self.Name

  def OnFilterRecord(Self, Dataset, Accept):
    # Accept is var argument in Delphi, but in Python you can't
    # change a function's argument. So we use a special object
    # TVarArg which contains a single property : Value
    Accept.Value = Dataset.FieldByName("Company").AsString > "E"
    if not Accept.Value:
      print "$$$$$ Rejected record:", Dataset.FieldsAsTuple()

DisplayTypesStats()
c = C()
DisplayTypesStats()

# don't use a "for i in c.T" expression with a filtered table,
# because the BDE will filter the whole table for each movement,
# in order to get the RecordCount.

try:
  c.T.First()
  while not c.T.EOF:
    print c.T.FieldsAsTuple()
    c.T.Next()

finally:
  c.Free()
  del c

DisplayTypesStats()
#DisplayTypesStats('TField', 'TTable')


