# -*- coding: utf-8 -*-"""Pretty Table support. Allow you quickly print query result in ascii table.:func:`from_everything`**中文文档**因为 PrettyTable 只能通过 from_db_cursor 来创建, 也就是说要求返回ResultProxy, 而不是 ORM 对象的列表. 所以在 :func:`from_object`, :func:`from_query`这些使用 ``session.query(Entity)`` 的函数中, 我们需要用特殊技巧, 让 session.query最终返回 ResultProxy."""fromtypingimportUnion,Tuple,Listfromsqlalchemyimportselect,Table,textfromsqlalchemy.engineimportEnginefromsqlalchemy.ormimportSessionfromsqlalchemy.ormimportDeclarativeMetafromsqlalchemy.sql.selectableimportSelectfromsqlalchemy.sql.elementsimportTextClausefromsqlalchemy.engine.resultimportResult,ScalarResult,RowfromprettytableimportPrettyTablefrom.utilsimportensure_session,clean_sessiondefget_keys_values(item)->Tuple[Union[list,tuple],Union[list,tuple]]:ifisinstance(item.__class__,DeclarativeMeta):keys,values=list(),list()forcolumninitem.__class__.__table__.columns:keys.append(column.name)values.append(getattr(item,column.name))returnkeys,valueselifisinstance(item,Row):returnlist(item._fields),list(item)else:# pragma: no coverraiseTypeErrordeffrom_result(result:Union[Result,ScalarResult]):pt=PrettyTable()try:first_item=next(result)keys,values=get_keys_values(first_item)pt.field_names=keyspt.add_row(values)exceptStopIteration:returnptifisinstance(result,ScalarResult):forobjinresult:pt.add_row([getattr(obj,key)forkeyinkeys])elifisinstance(result,Result):forrowinresult:pt.add_row(list(row))else:raiseExceptionreturnpt
[docs]deffrom_text_clause(t:TextClause,engine:Engine,**kwargs)->PrettyTable:""" Execute a query in form of texture clause, return the result in form of :class:`PrettyTable`. """withengine.connect()asconnection:result=connection.execute(t,**kwargs)returnfrom_result(result)
[docs]deffrom_stmt(stmt:Select,engine:Engine,**kwargs)->PrettyTable:""" Create a :class:`prettytable.PrettyTable` from :class:`sqlalchemy.select`. :param sql: a ``sqlalchemy.sql.selectable.Select`` object. :param engine: an ``sqlalchemy.engine.base.Engine`` object. **中文文档** 将 sqlalchemy 的 sql expression query 结果放入 prettytable 中. """withengine.connect()asconnection:result=connection.execute(stmt,**kwargs)returnfrom_result(result)
[docs]deffrom_table(table:Table,engine:Engine,limit:int=None,**kwargs)->PrettyTable:""" Select data in a database table and put into prettytable. Create a :class:`prettytable.PrettyTable` from :class:`sqlalchemy.Table`. :param table: a ``sqlalchemy.sql.schema.Table`` object :param engine: the engine or session used to execute the query. :param limit: int, limit rows to return. **中文文档** 将数据表中的数据放入 PrettyTable 中. """stmt=select([table])iflimitisnotNone:stmt=stmt.limit(limit)withengine.connect()asconnection:result=connection.execute(stmt,**kwargs)returnfrom_result(result)
[docs]deffrom_model(orm_class,engine_or_session:Union[Engine,Session],limit:int=None,**kwargs):""" Select data from the table defined by a ORM class, and put into prettytable :param orm_class: an orm class inherit from ``sqlalchemy.ext.declarative.declarative_base()`` :param engine_or_session: the engine or session used to execute the query. :param limit: int, limit rows to return. **中文文档** 将数据对象的数据放入 PrettyTable 中. 常用于快速预览某个对象背后的数据. """ses,auto_close=ensure_session(engine_or_session)stmt=select(orm_class.__table__)iflimitisnotNone:stmt=stmt.limit(limit)result=ses.execute(stmt,**kwargs)tb=from_result(result)clean_session(ses,auto_close)returntb
[docs]deffrom_dict_list(data:List[dict])->PrettyTable:""" Construct a Prettytable from list of dictionary. """tb=PrettyTable()iflen(data)==0:# pragma: no coverreturntbelse:tb.field_names=list(data[0].keys())forrowindata:tb.add_row(list(row.values()))returntb
[docs]deffrom_everything(everything:Union[TextClause,Select,Table,List[dict],DeclarativeMeta],engine_or_session:Union[Engine,Session]=None,limit:int=None,**kwargs):""" Construct a Prettytable from any kinds of sqlalchemy query. :type engine_or_session: Union[Engine, Session] :rtype: PrettyTable Usage:: from sqlalchemy import select sql = select([t_user]) print(from_everything(sql, engine)) query = session.query(User) print(from_everything(query, session)) session.query(User) """ifisinstance(everything,TextClause):returnfrom_text_clause(everything,engine_or_session,**kwargs)ifisinstance(everything,str):returnfrom_text_clause(text(everything),engine_or_session,**kwargs)ifisinstance(everything,Select):returnfrom_stmt(everything,engine_or_session,**kwargs)ifisinstance(everything,Table):returnfrom_table(everything,engine_or_session,limit=limit,**kwargs)ifisinstance(everything,DeclarativeMeta):returnfrom_model(everything,engine_or_session,limit=limit,**kwargs)ifisinstance(everything,Result):returnfrom_result(everything)ifisinstance(everything,list):returnfrom_dict_list(everything)raiseException