def activate(session: session, activator: callable): """ load rules - executed on commit raises exception if cycles detected :param session: SQLAlchemy session :param activator: function that declares rules (e.g., Rule.sum...) :return: """ engine = session.bind.engine setup(session, engine) activator() validate(session, engine)
def activate(session: session, activator: callable, constraint_event: callable = None): """ Call after opening database to activate logic: - register SQLAlchemy listeners - create RuleBank, load rules - later executed on commit - raises exception if cycles detected Use constraint_event to log / change class of constraints, for example def constraint_handler(message: str, constraint: Constraint, logic_row: LogicRow): error_attrs = "" if constraint: if constraint.error_attributes: for each_error_attribute in constraint.error_attributes: error_attrs = error_attrs + each_error_attribute.name + " " exception_message = "Custom constraint_handler for: " + message +\ ", error_attributes: " + error_attrs logic_row.log(exception_message) raise MyConstraintException(exception_message) Arguments: session: SQLAlchemy session activator: user function that declares rules (e.g., Rule.sum...) constraint_event: optional user function called on constraint exceptions """ rule_bank = rule_bank_setup.setup(session) if constraint_event is not None: rule_bank.constraint_event = constraint_event activator() rule_bank_setup.compute_formula_execution_order()
+ required_path_python_rules) sys.path.append(required_path_python_rules) else: pass print("NOT Fixing path (default PyCharm, set in VSC Launch Config): " + required_path_python_rules) from logic_bank.rule_bank import rule_bank_withdraw # required to avoid circular imports from logic_bank.rule_bank import rule_bank_setup from banking.logic.rules_bank import activate_basic_rules """ Logging configuration """ logging.basicConfig(format="%(asctime)s:%(levelname)s:%(name)s:%(message)s") logging.getLogger().setLevel(logging.DEBUG) app = Flask(__name__) app.config.from_object("config") db = SQLA(app) appbuilder = AppBuilder(app, db.session) if use_rules: rule_bank_setup.setup(db.session, db.engine) activate_basic_rules() rule_bank_setup.validate(db.session, db.engine) # checks for cycles, etc from . import views
basedir = os.path.dirname(basedir) print("\n****************\n" " IMPORTANT - create database.db from database-gold.db in " + basedir + "/nw/db/" + "\n****************") nw_loc = os.path.join(basedir, "db/database.db") nw_source = os.path.join(basedir, "db/database-gold.db") copyfile(src=nw_source, dst=nw_loc) conn_string = "sqlite:///" + nw_loc engine = sqlalchemy.create_engine(conn_string, echo=False) # sqlalchemy sqls... session_maker = sqlalchemy.orm.sessionmaker() session_maker.configure(bind=engine) session = session_maker() by_rules = True # True => use rules, False => use hand code (for comparison) rule_list = None db = None if by_rules: rule_bank_setup.setup(session, engine) activate_basic_check_credit_rules() rule_bank_setup.validate(session, engine) # checks for cycles, etc else: # setup to illustrate hand-coding alternative - target, modifier, function event.listen(session, "before_commit", nw_before_commit) event.listen(session, "before_flush", nw_before_flush) print("\n" + prt("nw/logic/__init__.py END - connected, session created, listeners registered\n"))