def act_context(context): """Action routine for CONTEXT directive.""" if len(context.line.split()) != 1: raise ExtraToken('CONTEXT', line=context.line_num) if context.context: raise DuplicateName('CONTEXT', context.line_num) context.context = import_by_path(context.line)
def act_exception(context): """Action routine for EXCEPTION directive.""" if len(context.line.split()) != 1: raise ExtraToken('EXCEPTION', line=context.line_num) if context.exception is not None: raise DuplicateDirective('EXCEPTION', context.line_num) context.exception = import_by_path(context.line)
def _coerce_type(type, enum, enums): def validate_int(value): try: return int(value) except Exception: raise ValueError('must be an int') def validate_count(value): try: value = int(value) if value > 0: return value except Exception: pass raise ValueError('must be a postive int') if enum: if enum not in enums: raise Exception("enum '%s' not defined" % enum) type = enums[enum] elif type == 'int': type = validate_int elif type == 'count': type = validate_count elif type == 'bool': type = config_file.validate_bool else: try: type = import_by_path(type) except Exception: raise Exception( "unable to import validation function '{}'".format(type)) return type
def _normalize(self, table, table2): if table2: if table2 in self._tables: # lookup by alias table2 = self._tables[table2] else: # lookup by class table2 = import_by_path(table2) match = [t for t in self._tables if t.cls == table2] if not match: raise TypeError("'{}' does not match any tables".format( table2.__name__)) elif len(match) > 1: raise TypeError("'{}' matches multiple tables".format( table2.__name__)) table2 = match[0] ref = self._find_foreign_key_reference(table, table2) if ref: t, field = ref return table, field.field_name, t, t.cls._fields.pk ref = self._find_primary_key_reference(table, table2) if ref: t, field = ref return table, table._fields.pk, t, field raise TypeError( "no primary or foreign key matches found for '{}'".format( table.__name__))
def act_handler(context): """Action routine for HANDLER directive.""" args = context.line.split() if len(args) == 1: raise TooFewTokens('HANDLER', line=context.line_num) if len(args) > 2: raise ExtraToken('HANDLER', line=context.line_num) name, path = args name = name.strip() if name in context.handlers: raise DuplicateName('HANDLER', context.line_num) handler = import_by_path(path) context.handlers[name] = handler
def cls(self): self._cls = import_by_path(self._cls) return self._cls
def join(self, table, table2=None, alias=None, outer=None): """Add a table to the query The table will be joined to another table in the query using foreign or primary key matches. Parameters: table - DAO of the table to add to the query (1)(4) table2 - name, alias or DAO of table to join (2) alias - name of joined table (3) outer - OUTER join indicator LEFT or RIGHT Notes: 1. The table can be specified as a DAO or as a dot separated path to a DAO for import. First, foreign keys in 'table' will be checked for a single matching primary key in one of the tables that is already part of the query. If no match is found, the primary key of 'table' will be matched in the same way. 2. If multiple matches occur when trying to join 'table', the ambiguity can be removed by specifying which existing table to match. Foreign keys from 'table' will be checked first, followed by the primary key. 3. The 'alias' parameter can be used to prevent collision with an existing DAO attribute, or to allow the same DAO to be joined more than once. 4. Any joined DAO is accesible as an attribute of the DAO used to create the Query object. The default attribute name is the lower case classname of the DAO. Specifying 'alias' will override this default. Example of join result structure: This query: Root.query().join(Node).execute(...) will result in a set of Root instances, each joined to a Node instance. Each Node instance is added as an attribute of a Root instance. Therefore: root = result[0] node = root.node In the case of multiple join clauses, each joined instance will be added to the DAO used to create the Query object. """ try: table = import_by_path(table) except ValueError: raise TypeError("invalid path to table: '{}'".format(table)) except ModuleNotFoundError: raise TypeError("unable to load '{}'".format(table)) if alias is None: alias = table.__name__.lower() if alias in [t.alias for t in self._tables]: raise ValueError("duplicate table '{}'".format(alias)) table, field, table2, field2 = self._normalize(table, table2) self._tables.append(QueryTable(table, alias)) if outer is None: join = ' JOIN ' elif outer.lower() == 'right': join = ' RIGHT OUTER JOIN ' elif outer.lower() == 'left': join = ' LEFT OUTER JOIN ' else: raise ValueError("invalid outer join value: '{}'".format(outer)) self._join += '{} `{}` AS `{}` ON `{}`.`{}` = `{}`.`{}`'.format( join, table.TABLENAME, alias, alias, table._fields[field].name, table2.alias, table2.cls._fields[field2].name, ) return self