def test_entity_decoration(self): # Default label based on name. user = db.execute(db.User.t.create(name='foo')) assert label.label(user) == 'foo' # Custom label. realm = db.execute(db.Realm.t.create(name='bar')) avatar = db.execute(db.Avatar.t.create( name='baz', user=user, realm=realm)) assert label.label(avatar) == u'baz (foo in bar)'
def test_transaction_method_decoration(self): # Extents for entity classes that are not customized only have # a transaction method for the canonical Create transaction. t = db.Realm.t assert sorted(t) == ['create'] assert label.label(t.create) == 'New' # Entity instances for entity classes that are not customized # only have transaction methods for canonical Delete and # Update transactions. realm = db.execute(t.create(name='foo')) t = realm.t L = sorted(t) assert L == ['clone', 'delete', 'update'] assert label.label(t.delete) == 'Delete' assert label.label(t.update) == 'Edit' assert label.label( db.Realm.EntityClass.t.delete_selected) == 'Delete Selected' # Transaction methods that aren't labeled are automatically # labeled. Test for labels of custom extent transaction # methods. t = db.Batch_Job.t assert 'multiple_keys_create' in list(t) assert label.label(t.multiple_keys_create) == 'Multiple Keys Create' # Test for labels of custom entity transaction methods. t = db.Account[1].t assert 'suspend' in list(t) assert 'transfer' in list(t) assert label.label(t.suspend) == 'Suspend' assert label.label(t.transfer) == 'Transfer Funds From This Account' # Test for labels of database-level transaction functions. t = db.t assert list(t) == ['subtransactions'] assert label.label(t.subtransactions) == 'Subtransactions'
def get_default_tx_dialog(parent, db, tx, get_value_handlers, set_field_handlers): extent_name = tx.s.extent_name if extent_name is None: title = u'%s' % label(tx) text = u'%s' % label(tx) else: extent_label = label(db.extent(extent_name)) title = u'%s :: %s' % (label(tx), extent_label) text = u'%s :: %s' % (label(tx), extent_label) field_map = tx.s.field_map() fields = field_map.values() dialog = get_dialog(title, parent, text, db, tx, fields, get_value_handlers, set_field_handlers) return dialog
def test_database_decoration(self): # This label is assigned automatically. assert label.label(db) == u'Schevo Database' # It can be easily overridden. label.relabel(db, 'Custom Label') assert label.label(db) == u'Custom Label' # When reopening the database, the label persists. self.reopen() assert label.label(db) == u'Custom Label' # Cannot change the label during a transaction. def fn(db): label.relabel(db, u'Custom Label 2') tx = transaction.CallableWrapper(fn) raises(error.DatabaseExecutingTransaction, db.execute, tx)
def _get_columns_for_field_spec(self, field_spec): columns = [] if '_oid' not in self._hidden: column = grid.Column(self, '_oid', 'OID', data_type=int) columns.append(column) if '_rev' not in self._hidden: column = grid.Column(self, '_rev', 'Rev', data_type=int) columns.append(column) for field_name, FieldClass in field_spec.iteritems(): if field_name in self._hidden: # Don't create a column for this field. continue if self._related and field_name == self._related.field_name: # Don't create a column for the related field. continue if not FieldClass.expensive and not FieldClass.hidden: data_type = FieldClass.data_type title = label(FieldClass) if issubclass(FieldClass, field.Entity): column = EntityColumn(self, field_name, title, data_type) elif issubclass(FieldClass, field.Image): column = grid.Column(self, field_name, title, data_type, type='pixbuf') else: column = FieldColumn(self, field_name, title, data_type) columns.append(column) return columns
def __init__(self, db, field): gtk.EventBox.__init__(self) self.set_visible_window(False) self.db = db self.field = field if os.name == 'nt' and not field.directory_only: if field.file_only: stock_id = gtk.STOCK_FILE self._hbox = hbox = gtk.HBox() hbox.show() self._entry = entry = gtk.Entry() entry.show() entry.props.editable = False entry.props.can_focus = False entry.props.has_focus = False self._button = button = gtk.Button() button.show() image = gtk.Image() image.show() image.set_from_stock(stock_id, gtk.ICON_SIZE_MENU) button.add(image) hbox.pack_start(entry) hbox.pack_start(button, expand=False) button.connect('clicked', self._on_clicked) self.add(hbox) else: title = 'Choose %r file' % label(self.field) self._filechooser = chooser = gtk.FileChooserButton(title) if self.field.directory_only: chooser.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) chooser.show() chooser.connect('selection-changed', self._on_changed) self.add(chooser)
def update_title(self): """Add or remove the database label from the end of the title.""" separator = u' :: ' text = self.get_title() # Get only the text in front of the separator. text = text.split(separator, 1)[0] if self._db: text = text + separator + label(self._db) self.set_title(text)
def main(self, arg0, args): print print parser = _parser() options, args = parser.parse_args(list(args)) if len(args) != 1: parser.error('Please specify URL.') url = args[0] # Open the database. print 'Opening database...' db = schevo.database.open(url) print print 'Label:', label(db) print 'Version:', db.version print 'Format:', db.format print print 'Checking for needed repairs...' print repairs = schevo.repair.repairs_needed(db, url) db.close() if len(repairs) == 0: print 'No repairs needed.' return print 'Repairs needed:' for repair in repairs: print '-', repair.description if repair.is_needed_certainty == False: print ( ' (Could not detect if needed; ' 'assuming so for safety.)' ) print if not options.repair: print 'Use -r or --repair option to perform repairs.' return print 'Repairing database...' for repair in repairs: repair.perform() print 'Done:', repair.description print print 'Re-checking for needed repairs...' print db = schevo.database.open(url) repairs_with_certainty = [ r for r in schevo.repair.repairs_needed(db, url) if r.is_needed_certainty == True ] db.close() if len(repairs_with_certainty) > 0: print 'WARNING! Repairs needed despite actions taken above:' for repair in repairs: print '-', repair.description print return 1 else: print 'No repairs needed.'
def main(self, arg0, args): print print parser = _parser() options, args = parser.parse_args(list(args)) if len(args) != 1: parser.error("Please specify DBFILE.") db_filename = args[0] # Open the database. if not os.path.isfile(db_filename): parser.error("DBFILE must be an existing database.") print "Opening database..." db = schevo.database.open( filename=db_filename, backend_name=options.backend_name, backend_args=options.backend_args ) print print "Label:", label(db) print "Version:", db.version print "Format:", db.format print print "Checking for needed repairs..." print repairs = schevo.repair.repairs_needed(db, db_filename) db.close() if len(repairs) == 0: print "No repairs needed." return print "Repairs needed:" for repair in repairs: print "-", repair.description if repair.is_needed_certainty == False: print (" (Could not detect if needed; " "assuming so for safety.)") print if not options.repair: print "Use -r or --repair option to perform repairs." return print "Repairing database..." for repair in repairs: repair.perform() print "Done:", repair.description print print "Re-checking for needed repairs..." print db = schevo.database.open(db_filename) repairs_with_certainty = [ r for r in schevo.repair.repairs_needed(db, db_filename) if r.is_needed_certainty == True ] db.close() if len(repairs_with_certainty) > 0: print "WARNING! Repairs needed despite actions taken above:" for repair in repairs: print "-", repair.description print return 1 else: print "No repairs needed."
def test_many_pluralization(self): assert label(db.Goauld) == u"Goa\u2032uld" assert plural(db.Goauld) == u"Goa\u2032ulds" ex = db.execute something = ex(db.Something.t.create()) goauld1 = ex(db.Goauld.t.create(something=something)) goauld2 = ex(db.Goauld.t.create(something=something)) goaulds = something.m.goaulds() assert len(goaulds) == 2 assert goauld1 in goaulds assert goauld2 in goaulds
def test_extent_decoration(self): # These labels were assigned automatically. assert label.label(db.Avatar) == 'Avatar' assert label.label(db.Batch_Job) == 'Batch Job' assert label.label(db.Realm) == 'Realm' assert label.label(db.User) == 'User' assert label.label(db.Person) == 'Person' assert label.plural(db.Avatar) == 'Avatars' assert label.plural(db.Batch_Job) == 'Batch Jobs' assert label.plural(db.Realm) == 'Realms' assert label.plural(db.User) == 'Users' # These labels were assigned manually. assert label.plural(db.Person) == 'People' # The docstring for an extent is set to the docstring for the # entity. assert db.Person.__doc__ == 'Bank account owner.' # An extent may optionally be hidden from typical user # interfaces. assert db.AlphaAlpha.hidden assert not db.AlphaBravo.hidden
def __init__(self, ResultClass, results): columns = [] sorted = True for field_name, FieldClass in ResultClass._field_spec.iteritems(): if not FieldClass.expensive: title = label(FieldClass) column = Column(field_name, title, data_type=str, sorted=sorted) columns.append(column) sorted = False ObjectList.__init__(self, columns, results)
def __init__(self, db, extent, method_name): gtk.VBox.__init__(self) self._db = db self._extent = extent method = extent.q[method_name] query = self._query = method() # Criteria form. expander_label = gtk.HBox() image_label = icon.small_image(self, db, 'q.%s' % method_name) text_label = gtk.Label(label(method)) expander_label.pack_start(image_label, expand=False, padding=6) expander_label.pack_start(text_label, expand=False) image_label = icon.small_image(self, extent) text_label = gtk.Label(u'<b>%s</b>' % label(extent)) text_label.props.use_markup = True expander_label.pack_start(image_label, expand=False, padding=6) expander_label.pack_start(text_label, expand=False) expander = gtk.Expander() expander.props.label_widget = expander_label self.pack_start(expander, expand=False) vbox = gtk.VBox() expander.add(vbox) criteria = self._criteria = query_widget(db, query) vbox.pack_start(criteria, expand=False) # Update button. box = gtk.HBox() vbox.pack_start(box, expand=False) refresh = gtk.Button(stock=gtk.STOCK_REFRESH) refresh.connect('clicked', self.on_refresh_clicked) box.pack_end(refresh, expand=False) # Results table. scroller = gtk.ScrolledWindow() scroller.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) self.pack_start(scroller, expand=True) results = self._results = Results(db, query) scroller.add_with_viewport(results) self.show_all() criteria.update_ui() results.rerun()
def get_method_action(db, instance, namespace_id, method_name, related=None): """Return action for method name.""" namespace = getattr(instance, namespace_id) method = namespace[method_name] method_label = label(method) action = Action() action.db = db action.instance = instance # Default label. action.label = u'%s...' % method_label if namespace_id == 't' and method_name in DEFAULT_T_METHODS: # Determine if there are any custom methods whose labels start # with the same string. t = action.instance.t other_found = False for other_name in t: if other_name not in DEFAULT_T_METHODS: other_label = label(t[other_name]) if other_label.startswith(method_label): other_found = True if other_found: # Custom labels, since there are custom methods that share # prefixes. if isinstance(instance, Entity): action.label = u'%s %s...' % ( method_label, label(instance.s.extent)) elif isinstance(instance, Extent): action.label = u'%s %s...' % (method_label, label(instance)) elif isinstance(instance, View): action.label = u'%s %s...' % ( method_label, label(instance.s.entity.s.extent)) action.method = method action.name = method_name action.related = related if namespace_id == 'q': action.type = 'query' elif namespace_id == 't': action.type = 'transaction' return action
def __unicode__(self): FieldClass = self.FieldClass field = FieldClass(self, self.field_name) operator = self.operator on = self.on if isinstance(on, base.Extent): on_label = plural(on) else: on_label = unicode(on) s = u'%s where %s %s' % ( on_label, label(field), label(self.operator), ) if operator is not o_any: value = self.value if isinstance(value, Query): s += u' %s' % value else: field.set(value) s += u' %s' % field return s
def test_clone_simple(self): # Create a user that we will then clone. tx = db.User.t.create(name='User 1', age=123) user1 = db.execute(tx) # Make sure the label for the 'clone' transaction method is # correct. assert label(user1.t.clone) == 'Clone' # Create a 'clone' transaction based on the user. tx = user1.t.clone() # Make sure the label for the actual transaction is correct. assert label(tx) == 'Clone' # The values of the cloned transaction should match the entity # being cloned. assert tx.name == user1.name assert tx.age == user1.age # Executing the transaction without modification will result # in a key collision, since a user with the name 'User 1' # already exists. try: db.execute(tx) except error.KeyCollision, e: assert e.extent_name == 'User' assert e.key_spec == ('name',) assert e.field_values == (u'User 1',)
def __init__(self, query): model = gtk.ListStore(gobject.TYPE_STRING) gtk.ComboBox.__init__(self, model) cell = gtk.CellRendererText() self.pack_start(cell, True) self.add_attribute(cell, 'text', 0) # Add operators. operators = self._operators = query.valid_operators current_operator = query.operator index = -1 for operator in operators: index += 1 self.append_text(label(operator)) if operator is current_operator: self.set_active(index)
def __init__(self, allowed_extents): gtk.VButtonBox.__init__(self) group = None self.selected_extent = None for extent in allowed_extents: button = gtk.RadioButton(group, label(extent), use_underline=False) if group is None: # First in the list, so make it the group and the # selected extent. group = button self.selected_extent = extent button.props.active = True button.connect('toggled', self.on_radio_button__toggled, extent) button.show() self.add(button)
def print_entity_information(db, entity): if db.format != 2: raise RuntimeError('Unsupported DB format') print '=' * 70 print 'Entity information for %r' % entity print 'Label: %r' % label(entity) extent = entity.s.extent print 'Extent: %r (id %r)' % ( extent.name, db._extent_name_id[extent.name], ) print 'Fields:' extent_map = db._extent_map(extent.name) field_id_name = extent_map['field_id_name'] entity_map = db._entity_map(extent.name, entity.s.oid) for field_id, stored_value in sorted(entity_map['fields'].iteritems()): print ' %r (name %r): %r' % ( field_id, field_id_name[field_id], stored_value, ) print 'Related Entities:' related_entities = sorted(entity_map['related_entities'].iteritems()) for field_id, related_entity_set in related_entities: print ' %r (name %r): %r' % ( field_id, field_id_name[field_id], related_entity_set, ) print 'Link Count: %r' % entity_map['link_count'] print 'Links:' links = sorted(entity_map['links'].iteritems()) for (ref_extent_id, ref_field_id), links_tree in links: ref_extent_name = db._extent_id_name.get(ref_extent_id, '<Not Found>') if ref_extent_id in db._extent_id_name: ref_extent_map = db._extent_map(ref_extent_name) ref_field_name = ref_extent_map['field_id_name'][ref_field_id] else: ref_field_name = '<Unknown>' oids = ' '.join(str(oid) for oid in sorted(links_tree)) print ' From extent %r (name %r) field %r (name %r): %r' % ( ref_extent_id, ref_extent_name, ref_field_id, ref_field_name, oids, )
def get_default_view_dialog(parent, db, entity, action, get_value_handlers, set_field_handlers): extent_text = label(entity.s.extent) title = u'View :: %s' % (extent_text, ) text = u'View :: %s :: %s' % (extent_text, entity) def include(field): if action.include_expensive: return True elif field.expensive: return False else: return True f_map = entity.s.field_map(include) fields = f_map.values() dialog = get_dialog(title, parent, text, db, entity, fields, get_value_handlers, set_field_handlers) return dialog
def __unicode__(self): extent = self._on criteria = self._criteria if criteria: field_spec = self._on.field_spec criteria = [ # (field label, value label) (label(field_spec[name]), unicode(self.f[name])) for name in criteria ] criteria = ', '.join( '%s == %s' % (field_label, value_label) for field_label, value_label in criteria ) return u'%s where (%s)' % (plural(extent), criteria) else: return u'all %s' % plural(extent)
def __init__(self, db, query): gtk.HBox.__init__(self) self._db = db self._query = query FieldClass = query.FieldClass # Field for value-based operators. field = self._field = FieldClass(query, query.field_name, query.value) # Label for the query's field. field_label = widget.FieldLabel(label(field)) self.pack_start(field_label, expand=False) # Menu list for operator selection. opcombo = OperatorComboBox(query) self.pack_start(opcombo, expand=False) opcombo.connect('changed', self.on_opcombo_changed) # Field widget. controller = self._controller = gtk_field.Controller(db, field) field_widget = self._field_widget = controller.widget self.pack_start(field_widget, expand=True) field_widget.props.visible = query.operator not in FIELDLESS_OPERATORS
def rerun(self): """Re-run the query and update results.""" db = self._db # Destroy existing results. class_expander = self._class_expander while class_expander: class_, expander = class_expander.pop() expander.destroy() # Re-run query. results = self._query() class_results = {} for result in results: L = class_results.setdefault(result.__class__, []) L.append(result) # Create expanders and listviews. if not class_results: no_results = gtk.Label('No results found.') self.pack_start(no_results, expand=False) class_expander.append((None, no_results)) for class_, results in class_results.iteritems(): extent = class_._extent expander_label = gtk.HBox() # Label for extent. extent_image = icon.small_image(self, extent) count = len(results) if count != 1: extent_label = gtk.Label( u'%i %s found:' % (count, plural(extent))) else: extent_label = gtk.Label( u'%i %s found:' % (count, label(extent))) expander_label.pack_start(extent_image, expand=False, padding=6) expander_label.pack_start(extent_label, expand=False, padding=6) expander = gtk.Expander() expander.props.label_widget = expander_label expander.props.expanded = True self.pack_start(expander, expand=True) listview = ResultsListView(class_, results) expander.add(listview) class_expander.append((class_, expander)) self.show_all()
def test_field_decoration(self): # Fields on transactions have labels. tx = db.Avatar.t.create() # These labels were assigned automatically. assert label.label(tx.f.realm) == 'Realm' assert label.label(tx.f.user) == 'User' assert label.label(tx.f.name) == 'Name' # Batch_Job.priority has a custom label. tx = db.Batch_Job.t.create() assert label.label(tx.f.priority) == 'Pri.' # Resulting entity instances' fields have labels. tx.name = 'foo' tx.priority = 1 batch_job = db.execute(tx) assert label.label(batch_job.f.name) == 'Name' assert label.label(batch_job.f.priority) == 'Pri.'
def setup_transactions(cls, class_name, class_dict, t_spec): """Create standard transaction classes.""" # Fields in a transaction class defined in the schema appear # below the fields that come from the entity field spec. for name in dir(cls): # Skip namespace names so we do not access them. if len(name) == 1 or name == 'sys': continue OldClass = getattr(cls, name) if not isinstance(OldClass, type): continue if not issubclass(OldClass, (transaction.Create, transaction.Delete, transaction.Update)): continue NewClass = type(name, (OldClass,), {}) NewClass._EntityClass = cls NewClass._extent_name = class_name NewClass._fget_fields = cls._fget_fields field_spec = NewClass._field_spec = t_spec.copy() field_spec.update(OldClass._field_spec, reorder=True) field_spec.reorder_all() # Perform any class-level initialization. if hasattr(NewClass, '_init_class'): NewClass._init_class() setattr(cls, name, NewClass) # Special case for DeleteSelected. It needs to be subclassed # so that its ._db is set properly, but it does not need the # field copying performed above. if (isinstance(cls._DeleteSelected, type) and issubclass(cls._DeleteSelected, transaction.DeleteSelected) ): NewClass = type(name, (cls._DeleteSelected,), {}) NewClass._EntityClass = cls NewClass._extent_name = class_name if hasattr(NewClass, '_init_class'): NewClass._init_class() relabel(NewClass, label(cls._DeleteSelected)) cls._DeleteSelected = NewClass
def test_transaction_decoration(self): # Canonical transactions have default labels. tx = db.Realm.t.create(name='foo') assert label.label(tx) == 'New' realm = db.execute(tx) assert label.label(realm.t.delete()) == 'Delete' assert label.label(realm.t.update()) == 'Edit' assert label.label( db.Realm.EntityClass.t.delete_selected([])) == 'Delete Selected' # Custom transactions have default labels generated from their # class name. tx = db.User.t.create_foo_and_bar() assert label.label(tx) == 'Create Foo And Bar' # Transaction instances can have custom labels assigned upon # creation by transaction methods, among other means. tx = db.Account[1].t.transfer() text = 'Transfer Funds From Fred Flintstone :: Personal' assert label.label(tx) == text
def test_q_labels(self): assert label(db.DeltaAlpha.q.by_example) == u'By Example' assert label(db.DeltaAlpha.q.exact) == u'Exact Matches'
def test_builtin_decoration(self): assert label.label('some string') == 'some string'
def test_UNASSIGNED(self): assert label(UNASSIGNED) == '<UNASSIGNED>' assert len(UNASSIGNED) == 0 assert str(UNASSIGNED) == '' assert raises(TypeError, UNASSIGNED)
def test_view_labels(self): assert label(db.EchoAlpha[1].v.default) == u'View' assert label(db.EchoCharlie[1].v.custom) == u'Custom View' assert label(db.EchoAlpha[1].v.default()) == u'View' assert label(db.EchoCharlie[1].v.custom()) == u'Custom View'