""" Define an Abstract Base Class (ABC) for models """ from datetime import datetime from decimal import Decimal from sqlalchemy import inspect from sqlalchemy.sql.expression import and_ from sqlalchemy.orm.collections import InstrumentedList from pyjeeves import logging from . import db logger = logging.getLogger("PyJeeves." + __name__) class RawBaseModel(): """ Generalize __init__, __repr__ and to_json Based on the models columns , ForetagKod=1""" print_only = () # First filter print_filter = () # Second filter to_json_filter = () # Only json filter column_map = {} __table_args__ = { 'extend_existing': True } @classmethod def _base_filters(self, obj, filters=and_()): # This method provides base filtering, additional filtering can be done in subclasses # Add this method to your model if you want more filtering, otherwise leave it out # import and_ from sqlalchemy package # this is a base filter for ALL queries return and_( obj.ForetagKod == 1, filters ) def __repr__(self): """ Define a base way to print models Columns inside `print_filter` are excluded """ return '%s(%s)' % (self.__class__.__name__, { column: value for column, value in self._to_dict().items() if column not in self.print_filter }) @staticmethod def _to_json_types(value): if isinstance(value, datetime): return value.strftime('%Y-%m-%d') if isinstance(value, Decimal): return "%.2f" % value try: if isinstance(value, InstrumentedList): return [x.json for x in value] if type(value).__module__ != 'builtins': # Perhaps == builtin? return value.json except AttributeError: logger.debug(str(type(value)) + " was not converted to jsonifyable type") return None return value @property def json(self): """ Define a base way to jsonify models Columns inside `to_json_filter` are excluded Columns inside `to_json_only_filter` are only included """ return { column: RawBaseModel._to_json_types(value) # if not isinstance(value, datetime) else value.strftime('%Y-%m-%d') # if type(value).__module__ != self.__module__ # Perhaps == builtin? # else value.json # Convert instances to json if same module for column, value in self._to_dict().items() if column not in self.to_json_filter } def _to_dict(self): """ This would more or less be the same as a `to_json` But putting it in a "private" function Allows to_json to be overriden without impacting __repr__ Or the other way around And to add filter lists """ return { self._map_columns(column.key): getattr(self, column.key) for column in inspect(self.__class__).attrs if not self.print_only or column.key in self.print_only } def _map_columns(self, key): if key in self.column_map: return self.column_map[key] return key def merge(self): db.raw_session.merge(self) return self def commit(self): db.raw_session.commit() def save(self): db.raw_session.add(self) db.raw_session.commit() return self def delete(self): db.raw_session.delete(self) db.raw_session.commit()