From ebaa3370b5aa8f378322a29b531a981fc8cc5e8d Mon Sep 17 00:00:00 2001 From: CACode Date: Thu, 6 May 2021 16:40:46 +0800 Subject: [PATCH 01/26] =?UTF-8?q?Revert=20"=E4=BF=AE=E6=94=B9=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=E6=B1=A0"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit bd2eb1ed41fb3e10e0c20cf10304cdbe00066fc9. On branch main --- .../MainWork/CACodeCustomizeAdapter.py | 18 ---- CACodeFramework/MainWork/CACodePureORM.py | 6 +- CACodeFramework/MainWork/CACodeRepository.py | 88 +++++-------------- CACodeFramework/cacode/Serialize.py | 24 ++--- CACodeFramework/exception/e_fields.py | 4 - CACodeFramework/opera/op_db.py | 7 +- CACodeFramework/pojoManager/Manage.py | 15 +--- CACodeFramework/util/Config.py | 4 +- CACodeFramework/util/DbUtil.py | 41 +-------- CACodeFramework/util/Log.py | 2 +- CACodeFramework/util/ParseUtil.py | 10 --- test/testFunc.py | 6 ++ 12 files changed, 55 insertions(+), 170 deletions(-) diff --git a/CACodeFramework/MainWork/CACodeCustomizeAdapter.py b/CACodeFramework/MainWork/CACodeCustomizeAdapter.py index 6fdced3..353ffca 100644 --- a/CACodeFramework/MainWork/CACodeCustomizeAdapter.py +++ b/CACodeFramework/MainWork/CACodeCustomizeAdapter.py @@ -3,27 +3,9 @@ from CACodeFramework.field.MySqlDefault import MySqlFields_Default class Adapter(object): - """ - 适配器,将sql方言适配到ORM框架中,实现sql自由 - - - 从配置表中开始配置sql方言,继承SqlLanguage类并实现抽象方法,开启 - - - - """ - def __init__(self, repositoryId, serializer=QuerySet, sqlFields=MySqlFields_Default): self.repositoryId = repositoryId self.serializer = serializer - self.sqlFields = sqlFields() - self.sql = [] def getFormId(self, obj_id): pass - - def setField(self, string): - """ - 设置一个字段 - """ - self.sql.append("{}{}{}".format(self.sqlFields.space, string, self.sqlFields.space)) diff --git a/CACodeFramework/MainWork/CACodePureORM.py b/CACodeFramework/MainWork/CACodePureORM.py index 4765b27..b2d3b3c 100644 --- a/CACodeFramework/MainWork/CACodePureORM.py +++ b/CACodeFramework/MainWork/CACodePureORM.py @@ -322,7 +322,7 @@ s """ ) _result_objs = [] for i in _result: - _obj = ParseUtil.parse_obj(data=i, instance=self.repository.instance) + _obj = ParseUtil.parse_obj(data=i, instance=self.repository.participants) _result_objs.append(_obj) _result = _result_objs else: @@ -337,9 +337,9 @@ s """ self.params.clear() if self.first_data: if type(_result) is list or type(_result) is tuple: - return self.serializer(instance=self.repository.instance, base_data=_result).first() + return self.serializer(instance=self.repository.participants, base_data=_result).first() else: - q = self.serializer(instance=self.repository.instance, base_data=_result) + q = self.serializer(instance=self.repository.participants, base_data=_result) return q def con_from(self): diff --git a/CACodeFramework/MainWork/CACodeRepository.py b/CACodeFramework/MainWork/CACodeRepository.py index e41c932..53a12fb 100644 --- a/CACodeFramework/MainWork/CACodeRepository.py +++ b/CACodeFramework/MainWork/CACodeRepository.py @@ -1,7 +1,6 @@ import copy from CACodeFramework.cacode.Serialize import QuerySet -from CACodeFramework.exception import e_fields from CACodeFramework.opera import op_db from CACodeFramework.util.Log import CACodeLog @@ -33,9 +32,10 @@ class Repository(object): - 需要配合:@Table(name, msg, **kwargs)使用 """ - def __init__(self, config_obj=None, instance=None, log_conf=None, close_log=False, serializer=QuerySet, - sqlFields=None, **kwargs): - """作者:CACode 最后编辑于2021/4/30 + def __init__(self, config_obj=None, participants=None, log_conf=None, close_log=False, serializer=QuerySet, + sql_field=None, + **kwargs): + """作者:CACode 最后编辑于2021/4/27 通过继承此类将数据表实体化 @@ -45,82 +45,40 @@ class Repository(object): 无需担心类型问题,无需担心datetime无法转换 使用方法: - #加入Table注解,并标注表名与描述,因考虑使用者后期优化问题,请务必填写MSG参数 + #加入Table注解,并标注表名与描述,因考虑后期优化问题,请务必填写MSG参数 @Table(name="demo_table", msg="demo message") #继承Repository并得到相对应的半自动ORM操做 class TestClass(Repository): # 初始化并super配置 - def __init__(self,**kwargs): - super(DemoTable, self).__init__(config_obj=ConF(), log_conf={ - 'path': "/log/", - 'save_flag': True - }, **kwargs) + def __init__(self): + super(TestClass, self).__init__(config_obj=ConF(), participants=Demo()) 初始化配置: 使用本类需要携带一个来自CACodeFramework.util.Config.config的配置类,详见:CACodeFramework.util.Config.config - Attributes: - 以下的字段均可覆盖重写 - - config_obj:数据源配置类 - - log_conf:日志配置工具 - - log_obj:日志对象 - - close_log:是否关闭日志 - - serializer:序列化使用的类,默认使用CACodeFramework.cacode.Serialize.QuerySet - - instance:实例 - - __table_name__:表名称 - - operation:操作类的实现 - - fields:操作的字段 - - sqlFields:sql方言 - :param config_obj:配置类 :param log_conf:日志配置类 :param close_log:是否关闭日志显示功能 :param serializer:自定义序列化器,默认使用CACodeFramework.cacode.Serialize.QuerySet """ # 以下使用ParseUtil将所有参数替换为可动态修改内哦不结构 - # 有没有关闭日志 ParseUtil.set_field_compulsory(self, key='close_log', data=kwargs, val=close_log) - if hasattr(self, 'close_log') and not self.close_log: + if not self.close_log: CACodeLog.warning(obj=self, msg='Being Initialize this object') - # 有没有表名 - ParseUtil.set_field_compulsory(self, key='__table_name__', data=kwargs, - val=self.__table_name__ if hasattr(self, '__table_name__') else - "`__table_name__` parsing failed") - # 操作类 + ParseUtil.set_field_compulsory(self, key='__table_name__', data=kwargs, val=self.__table_name__) ParseUtil.set_field_compulsory(self, key='operation', data=kwargs, val=op_db.DbOperation()) - # 参照对象 - ParseUtil.set_field_compulsory(self, key='instance', data=kwargs, val=instance) - # 取得字段的名称 - ParseUtil.set_field_compulsory(self, key='fields', data=kwargs, val=list(instance.getFields().keys())) - # 获取sql方言配置 - ParseUtil.set_field_compulsory(self, key='sqlFields', data=kwargs, val=sqlFields) - # 数据源配置 + ParseUtil.set_field_compulsory(self, key='participants', data=kwargs, val=participants) + ParseUtil.set_field_compulsory(self, key='fields', data=kwargs, val=list(participants.fields.keys())) ParseUtil.set_field_compulsory(self, key='config_obj', data=kwargs, val=config_obj) - # 连接池 - if hasattr(self, 'config_obj') and self.config_obj: - self.db_util = DbUtil.Db_opera(host=ParseUtil.fieldExit(self.config_obj, 'host'), - port=ParseUtil.fieldExit(self.config_obj, 'port'), - user=ParseUtil.fieldExit(self.config_obj, 'user'), - password=ParseUtil.fieldExit(self.config_obj, 'password'), - database=ParseUtil.fieldExit(self.config_obj, 'database'), - charset=ParseUtil.fieldExit(self.config_obj, 'charset'), - POOL=None if 'POOL' not in kwargs.keys() else kwargs['POOL']) - else: - CACodeLog.err(AttributeError, e_fields.Miss_Attr('`config_obj` is missing')) - + self.db_util = DbUtil.Db_opera(host=self.config_obj.host, + port=self.config_obj.port, + user=self.config_obj.user, + password=self.config_obj.password, + database=self.config_obj.database, + charset=self.config_obj.charset) ParseUtil.set_field_compulsory(self, key='result', data=kwargs, val=None) ParseUtil.set_field_compulsory(self, key='log_obj', data=kwargs, val=LogObj(**log_conf) if log_conf is not None else None) @@ -131,9 +89,9 @@ class Repository(object): # self.__table_name__ = self.__table_name__ # self.operation = op_db.DbOperation() # 模板类 - # self.instance = instance + # self.participants = participants # 该对象的所有字段 - # fds = instance.fields + # fds = participants.fields # self.fields = list(fds.keys()) # 配置类 # self.config_obj = config_obj @@ -188,7 +146,7 @@ class Repository(object): kwargs = {'func': self.operation.__find_all__, '__task_uuid__': name, 't_local': self} result = self.operation.start(*self.fields, **kwargs) - self.result = self.serializer(instance=self.instance, base_data=result) + self.result = self.serializer(instance=self.participants, base_data=result) return self.result @@ -214,7 +172,7 @@ class Repository(object): result = self.operation.start(*args, **kwargs) - self.result = self.serializer(instance=self.instance, base_data=result) + self.result = self.serializer(instance=self.participants, base_data=result) return self.result def find_one(self, **kwargs): @@ -279,7 +237,7 @@ class Repository(object): kwargs['t_local'] = self result = self.operation.start(**kwargs) - self.result = self.serializer(instance=self.instance, base_data=result) + self.result = self.serializer(instance=self.participants, base_data=result) return self.result def find_sql(self, **kwargs): @@ -305,7 +263,7 @@ class Repository(object): kwargs['t_local'] = self result = self.operation.start(**kwargs) - self.result = self.serializer(instance=self.instance, base_data=result) + self.result = self.serializer(instance=self.participants, base_data=result) return self.result def update(self, **kwargs): diff --git a/CACodeFramework/cacode/Serialize.py b/CACodeFramework/cacode/Serialize.py index 5f4d1e5..48c8e89 100644 --- a/CACodeFramework/cacode/Serialize.py +++ b/CACodeFramework/cacode/Serialize.py @@ -263,17 +263,17 @@ class QuerySet(list): list.__init__([]) self.__instance__ = instance - self.__using_fields__ = self.__instance__.__fields__ - self.__all_using_fields__ = JsonUtil.parse(obj=self.__instance__, end_load=True) + self.using_fields = self.__instance__.__fields__ + self.all_using_fields = JsonUtil.parse(obj=self.__instance__, end_load=True) - self.__ignore_field__ = {} - self.__append_field__ = {} + self.ignore_field = {} + self.append_field = {} for i in base_data: self.append( QueryItem(data_item=i, - ignore_field_id=id(self.__ignore_field__), - append_field_id=id(self.__append_field__), - using_fields=self.__using_fields__)) + ignore_field_id=id(self.ignore_field), + append_field_id=id(self.append_field), + using_fields=self.using_fields)) def size(self): return len(self) @@ -329,11 +329,11 @@ class QuerySet(list): """ 添加一个不会被解析忽略的字段 """ - if key not in self.__append_field__.keys() and \ - key not in self.__using_fields__.keys() and \ - key not in self.__all_using_fields__.keys(): + if key not in self.append_field.keys() and \ + key not in self.using_fields.keys() and \ + key not in self.all_using_fields.keys(): - self.__append_field__[key] = default_value + self.append_field[key] = default_value else: CACodeLog.log(obj=self, msg='`{}` already exists'.format(key)) @@ -341,7 +341,7 @@ class QuerySet(list): """ 添加一个会被解析忽略的字段 """ - self.__ignore_field__[key] = None + self.ignore_field[key] = None class QueryItem(JsonUtil): diff --git a/CACodeFramework/exception/e_fields.py b/CACodeFramework/exception/e_fields.py index d31400f..656cadf 100644 --- a/CACodeFramework/exception/e_fields.py +++ b/CACodeFramework/exception/e_fields.py @@ -26,10 +26,6 @@ def Log_Opera_Name(msg): return mat('CACode-DatabaseOperation', msg) -def Miss_Attr(msg): - return mat('CACode-Attribute', msg) - - def Error(): return 'ERROR' diff --git a/CACodeFramework/opera/op_db.py b/CACodeFramework/opera/op_db.py index cd46883..bedf968 100644 --- a/CACodeFramework/opera/op_db.py +++ b/CACodeFramework/opera/op_db.py @@ -58,7 +58,7 @@ class DbOperation(object): 任务方法 """ fields = ParseUtil(*args, is_field=True).parse_key() - sql_str = kwargs['sqlFields'].find_str + fields + kwargs['sqlFields'].from_str + kwargs['__table_name__'] + sql_str = find_str + fields + from_str + kwargs['__table_name__'] kwargs['sql'] = sql_str self.result = self.__find_many__(**kwargs) return self.result @@ -84,7 +84,7 @@ class DbOperation(object): self.result = [] for i in _rs: - self.result.append(ParseUtil.parse_obj(i, kwargs['instance'])) + self.result.append(ParseUtil.parse_obj(i, kwargs['participants'])) return self.result @@ -101,8 +101,7 @@ class DbOperation(object): raise SyntaxError('the key of `pojo` cannot be found in the parameters') filed_list = ParseUtil.parse_insert_pojo(kwargs['pojo'], __table_name__=kwargs['__table_name__'], - insert_str=kwargs['sqlFields'].insert_str, - values_str=kwargs['sqlFields'].values_str) + insert_str=insert_str, values_str=values_str) kwargs.update(filed_list) diff --git a/CACodeFramework/pojoManager/Manage.py b/CACodeFramework/pojoManager/Manage.py index 60d28b4..39287e5 100644 --- a/CACodeFramework/pojoManager/Manage.py +++ b/CACodeFramework/pojoManager/Manage.py @@ -23,14 +23,13 @@ class Pojo(CACodeRepository.Repository): self.__table_name__ = self.__table_name__ self.__table_msg__ = self.__table_msg__ - self.__fields__ = {} self.init_fields() for key, value in kwargs.items(): self.__setattr__(key, value) # 在这里将config_obj实例化 self.serializer = serializer super(Pojo, self).__init__(config_obj=config_obj, - instance=self, + participants=self, log_conf=log_conf, close_log=close_log, serializer=serializer, @@ -52,6 +51,7 @@ class Pojo(CACodeRepository.Repository): except SyntaxError: continue + self.fields = fds self.__fields__ = fds def to_json(self, bf=False): @@ -70,15 +70,6 @@ class Pojo(CACodeRepository.Repository): """ return JsonUtil.load(JsonUtil.parse(self)) - def getFields(self) -> dict: - return self.__fields__ - - def markTable(self): - """ - 将表生成至外部文件 - """ - pass - @property def orm(self): """ @@ -90,7 +81,7 @@ class Pojo(CACodeRepository.Repository): """ 为指定字段的值设置别名 """ - if 'ig' in self.getFields().keys(): + if 'ig' in self.__fields__.keys(): self.__fields__['ig'].append({ key: name }) diff --git a/CACodeFramework/util/Config.py b/CACodeFramework/util/Config.py index 1b35729..500c983 100644 --- a/CACodeFramework/util/Config.py +++ b/CACodeFramework/util/Config.py @@ -65,9 +65,9 @@ class config(object): """ return self.__dict__ - def get_json(self, bf=False): + def get_json(self): """ 将配置类转json :return: """ - return JsonUtil.parse(self.get_dict(), bf) + return JsonUtil.parse(self.get_dict()) diff --git a/CACodeFramework/util/DbUtil.py b/CACodeFramework/util/DbUtil.py index ec8cd06..5634b79 100644 --- a/CACodeFramework/util/DbUtil.py +++ b/CACodeFramework/util/DbUtil.py @@ -3,6 +3,7 @@ import threading from CACodeFramework.cacode.Modes import Singleton from CACodeFramework.util.Log import CACodeLog +from dbutils.pooled_db import PooledDB import pymysql @@ -38,6 +39,7 @@ def parse_kwa(db, **kwargs): class Db_opera(object): """ + 操作数据库类 """ @@ -47,44 +49,6 @@ class Db_opera(object): mincached=2, maxcached=5, maxshared=3, blocking=True, setsession=[], ping=0, POOL=None): """ - - 设置DB-API 2连接池。 - - creator:返回新的DB-API 2的任意函数 - 连接对象或符合DB-API 2的数据库模块 - mincached:池中空闲连接的初始数量 - (0表示启动时未建立连接) - maxcached:池中最大空闲连接数 - (0或无表示池大小不受限制) - maxshared:共享连接的最大数量 - (0或无表示所有连接都是专用的) - 当达到此最大数量时,连接为 - 如果被要求共享,则将它们共享。 - maxconnections:通常允许的最大连接数 - (0或无表示任意数量的连接) - blocking:确定超出最大值时的行为 - (如果将其设置为true,请阻止并等待,直到 - 连接减少,否则将报告错误) - maxusage:单个连接的最大重用次数 - (0或无表示无限重用) - 当达到连接的最大使用次数时, - 连接将自动重置(关闭并重新打开)。 - setsession:可用于准备的SQL命令的可选列表 - 会话,例如[“将日期样式设置为...”,“将时区设置为...”] - reset:返回到池后应如何重置连接 - (对于以begin()开始的回滚事务,为False或None, - 出于安全考虑,总是发出回滚是正确的) - failures:可选的异常类或异常类的元组 - 为此,应应用连接故障转移机制, - 如果默认值(OperationalError,InternalError)不足够 - ping:确定何时应使用ping()检查连接 - (0 =无=永不,1 =默认=每当从池中获取时, - 2 =创建游标时,4 =执行查询时, - 7 =始终,以及这些值的所有其他位组合) - args,kwargs:应传递给创建者的参数 - 函数或DB-API 2模块的连接构造函数 - - 初始化配置 以下参数与PooledDB一致 :param creator:默认即可 @@ -124,7 +88,6 @@ class Db_opera(object): """ 初始化数据库连接池 """ - from dbutils.pooled_db import PooledDB if self.POOL is None: self.POOL = PooledDB(creator=self.creator, maxconnections=self.maxconnections, mincached=self.mincached, maxcached=self.maxcached, diff --git a/CACodeFramework/util/Log.py b/CACodeFramework/util/Log.py index 8738e1f..e99fc51 100644 --- a/CACodeFramework/util/Log.py +++ b/CACodeFramework/util/Log.py @@ -206,7 +206,7 @@ class CACodeLog(object): hex_id = f"[{hex(id(obj))}]".ljust(FieldsLength.HEX_FORMAT) write_repr = f"[{write_repr}]".ljust(FieldsLength.CLASS_FORMAT) task_name = f"[{task_name}]".ljust(FieldsLength.TASK_FORMAT) - msg = f"\t\t:{msg}" + msg = f"\t\t:{msg}\n" info = "{}{}{}{}{}{}{}{}".format(t, field, line, operation_name, hex_id, write_repr, task_name, msg) diff --git a/CACodeFramework/util/ParseUtil.py b/CACodeFramework/util/ParseUtil.py index f8d1008..d42e2f1 100644 --- a/CACodeFramework/util/ParseUtil.py +++ b/CACodeFramework/util/ParseUtil.py @@ -261,13 +261,3 @@ class ParseUtil(object): setattr(obj, key, data[key]) else: setattr(obj, key, val) - - @staticmethod - def fieldExit(obj, field, el=None): - """ - 在对象中获取一个字段的值,如果这个字段不存在,则将值设置为`el` - """ - if hasattr(obj, field): - return getattr(obj, field) - else: - return el diff --git a/test/testFunc.py b/test/testFunc.py index c78e201..28f2f29 100644 --- a/test/testFunc.py +++ b/test/testFunc.py @@ -1,6 +1,7 @@ import time from CACodeFramework.cacode.Factory import Factory +from test.modules.Demo import DemoTable class MyFactory(Factory): @@ -10,6 +11,11 @@ class MyFactory(Factory): ] +def setData(): + for i in range(1000): + DemoTable(t_name=f'测试name{i}', t_pwd=f'测试pwd{i}', t_ms=f'测试msg{i}').save() + + if __name__ == '__main__': t1 = time.time() DemoTable = MyFactory.createInstance('Demo.DemoTable') -- Gitee From ce1c92e465bffc42897b91df7306c2ec13208703 Mon Sep 17 00:00:00 2001 From: CACode Date: Thu, 6 May 2021 16:42:11 +0800 Subject: [PATCH 02/26] =?UTF-8?q?Revert=20"=E4=BF=AE=E6=94=B9=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=E6=B1=A0"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit bd2eb1ed41fb3e10e0c20cf10304cdbe00066fc9. On branch main --- test/testFunc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testFunc.py b/test/testFunc.py index 28f2f29..ad2710f 100644 --- a/test/testFunc.py +++ b/test/testFunc.py @@ -22,4 +22,4 @@ if __name__ == '__main__': count = 0 result = DemoTable.orm.find().limit(10).end() print(result.to_json(True)) - print(time.time() - t1) + print(time.time() - t1) \ No newline at end of file -- Gitee From 007564708228349909180aa2002f8d219ce6b07e Mon Sep 17 00:00:00 2001 From: CACode Date: Thu, 6 May 2021 16:42:21 +0800 Subject: [PATCH 03/26] =?UTF-8?q?Revert=20"Revert=20"=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E6=B1=A0""?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit ebaa3370b5aa8f378322a29b531a981fc8cc5e8d. On branch main --- .../MainWork/CACodeCustomizeAdapter.py | 18 ++++ CACodeFramework/MainWork/CACodePureORM.py | 6 +- CACodeFramework/MainWork/CACodeRepository.py | 88 ++++++++++++++----- CACodeFramework/cacode/Serialize.py | 24 ++--- CACodeFramework/exception/e_fields.py | 4 + CACodeFramework/opera/op_db.py | 7 +- CACodeFramework/pojoManager/Manage.py | 15 +++- CACodeFramework/util/Config.py | 4 +- CACodeFramework/util/DbUtil.py | 41 ++++++++- CACodeFramework/util/Log.py | 2 +- CACodeFramework/util/ParseUtil.py | 10 +++ test/testFunc.py | 6 -- 12 files changed, 170 insertions(+), 55 deletions(-) diff --git a/CACodeFramework/MainWork/CACodeCustomizeAdapter.py b/CACodeFramework/MainWork/CACodeCustomizeAdapter.py index 353ffca..6fdced3 100644 --- a/CACodeFramework/MainWork/CACodeCustomizeAdapter.py +++ b/CACodeFramework/MainWork/CACodeCustomizeAdapter.py @@ -3,9 +3,27 @@ from CACodeFramework.field.MySqlDefault import MySqlFields_Default class Adapter(object): + """ + 适配器,将sql方言适配到ORM框架中,实现sql自由 + + + 从配置表中开始配置sql方言,继承SqlLanguage类并实现抽象方法,开启 + + + + """ + def __init__(self, repositoryId, serializer=QuerySet, sqlFields=MySqlFields_Default): self.repositoryId = repositoryId self.serializer = serializer + self.sqlFields = sqlFields() + self.sql = [] def getFormId(self, obj_id): pass + + def setField(self, string): + """ + 设置一个字段 + """ + self.sql.append("{}{}{}".format(self.sqlFields.space, string, self.sqlFields.space)) diff --git a/CACodeFramework/MainWork/CACodePureORM.py b/CACodeFramework/MainWork/CACodePureORM.py index b2d3b3c..4765b27 100644 --- a/CACodeFramework/MainWork/CACodePureORM.py +++ b/CACodeFramework/MainWork/CACodePureORM.py @@ -322,7 +322,7 @@ s """ ) _result_objs = [] for i in _result: - _obj = ParseUtil.parse_obj(data=i, instance=self.repository.participants) + _obj = ParseUtil.parse_obj(data=i, instance=self.repository.instance) _result_objs.append(_obj) _result = _result_objs else: @@ -337,9 +337,9 @@ s """ self.params.clear() if self.first_data: if type(_result) is list or type(_result) is tuple: - return self.serializer(instance=self.repository.participants, base_data=_result).first() + return self.serializer(instance=self.repository.instance, base_data=_result).first() else: - q = self.serializer(instance=self.repository.participants, base_data=_result) + q = self.serializer(instance=self.repository.instance, base_data=_result) return q def con_from(self): diff --git a/CACodeFramework/MainWork/CACodeRepository.py b/CACodeFramework/MainWork/CACodeRepository.py index 53a12fb..e41c932 100644 --- a/CACodeFramework/MainWork/CACodeRepository.py +++ b/CACodeFramework/MainWork/CACodeRepository.py @@ -1,6 +1,7 @@ import copy from CACodeFramework.cacode.Serialize import QuerySet +from CACodeFramework.exception import e_fields from CACodeFramework.opera import op_db from CACodeFramework.util.Log import CACodeLog @@ -32,10 +33,9 @@ class Repository(object): - 需要配合:@Table(name, msg, **kwargs)使用 """ - def __init__(self, config_obj=None, participants=None, log_conf=None, close_log=False, serializer=QuerySet, - sql_field=None, - **kwargs): - """作者:CACode 最后编辑于2021/4/27 + def __init__(self, config_obj=None, instance=None, log_conf=None, close_log=False, serializer=QuerySet, + sqlFields=None, **kwargs): + """作者:CACode 最后编辑于2021/4/30 通过继承此类将数据表实体化 @@ -45,40 +45,82 @@ class Repository(object): 无需担心类型问题,无需担心datetime无法转换 使用方法: - #加入Table注解,并标注表名与描述,因考虑后期优化问题,请务必填写MSG参数 + #加入Table注解,并标注表名与描述,因考虑使用者后期优化问题,请务必填写MSG参数 @Table(name="demo_table", msg="demo message") #继承Repository并得到相对应的半自动ORM操做 class TestClass(Repository): # 初始化并super配置 - def __init__(self): - super(TestClass, self).__init__(config_obj=ConF(), participants=Demo()) + def __init__(self,**kwargs): + super(DemoTable, self).__init__(config_obj=ConF(), log_conf={ + 'path': "/log/", + 'save_flag': True + }, **kwargs) 初始化配置: 使用本类需要携带一个来自CACodeFramework.util.Config.config的配置类,详见:CACodeFramework.util.Config.config + Attributes: + 以下的字段均可覆盖重写 + + config_obj:数据源配置类 + + log_conf:日志配置工具 + + log_obj:日志对象 + + close_log:是否关闭日志 + + serializer:序列化使用的类,默认使用CACodeFramework.cacode.Serialize.QuerySet + + instance:实例 + + __table_name__:表名称 + + operation:操作类的实现 + + fields:操作的字段 + + sqlFields:sql方言 + :param config_obj:配置类 :param log_conf:日志配置类 :param close_log:是否关闭日志显示功能 :param serializer:自定义序列化器,默认使用CACodeFramework.cacode.Serialize.QuerySet """ # 以下使用ParseUtil将所有参数替换为可动态修改内哦不结构 + # 有没有关闭日志 ParseUtil.set_field_compulsory(self, key='close_log', data=kwargs, val=close_log) - if not self.close_log: + if hasattr(self, 'close_log') and not self.close_log: CACodeLog.warning(obj=self, msg='Being Initialize this object') - ParseUtil.set_field_compulsory(self, key='__table_name__', data=kwargs, val=self.__table_name__) + # 有没有表名 + ParseUtil.set_field_compulsory(self, key='__table_name__', data=kwargs, + val=self.__table_name__ if hasattr(self, '__table_name__') else + "`__table_name__` parsing failed") + # 操作类 ParseUtil.set_field_compulsory(self, key='operation', data=kwargs, val=op_db.DbOperation()) - ParseUtil.set_field_compulsory(self, key='participants', data=kwargs, val=participants) - ParseUtil.set_field_compulsory(self, key='fields', data=kwargs, val=list(participants.fields.keys())) + # 参照对象 + ParseUtil.set_field_compulsory(self, key='instance', data=kwargs, val=instance) + # 取得字段的名称 + ParseUtil.set_field_compulsory(self, key='fields', data=kwargs, val=list(instance.getFields().keys())) + # 获取sql方言配置 + ParseUtil.set_field_compulsory(self, key='sqlFields', data=kwargs, val=sqlFields) + # 数据源配置 ParseUtil.set_field_compulsory(self, key='config_obj', data=kwargs, val=config_obj) - self.db_util = DbUtil.Db_opera(host=self.config_obj.host, - port=self.config_obj.port, - user=self.config_obj.user, - password=self.config_obj.password, - database=self.config_obj.database, - charset=self.config_obj.charset) + # 连接池 + if hasattr(self, 'config_obj') and self.config_obj: + self.db_util = DbUtil.Db_opera(host=ParseUtil.fieldExit(self.config_obj, 'host'), + port=ParseUtil.fieldExit(self.config_obj, 'port'), + user=ParseUtil.fieldExit(self.config_obj, 'user'), + password=ParseUtil.fieldExit(self.config_obj, 'password'), + database=ParseUtil.fieldExit(self.config_obj, 'database'), + charset=ParseUtil.fieldExit(self.config_obj, 'charset'), + POOL=None if 'POOL' not in kwargs.keys() else kwargs['POOL']) + else: + CACodeLog.err(AttributeError, e_fields.Miss_Attr('`config_obj` is missing')) + ParseUtil.set_field_compulsory(self, key='result', data=kwargs, val=None) ParseUtil.set_field_compulsory(self, key='log_obj', data=kwargs, val=LogObj(**log_conf) if log_conf is not None else None) @@ -89,9 +131,9 @@ class Repository(object): # self.__table_name__ = self.__table_name__ # self.operation = op_db.DbOperation() # 模板类 - # self.participants = participants + # self.instance = instance # 该对象的所有字段 - # fds = participants.fields + # fds = instance.fields # self.fields = list(fds.keys()) # 配置类 # self.config_obj = config_obj @@ -146,7 +188,7 @@ class Repository(object): kwargs = {'func': self.operation.__find_all__, '__task_uuid__': name, 't_local': self} result = self.operation.start(*self.fields, **kwargs) - self.result = self.serializer(instance=self.participants, base_data=result) + self.result = self.serializer(instance=self.instance, base_data=result) return self.result @@ -172,7 +214,7 @@ class Repository(object): result = self.operation.start(*args, **kwargs) - self.result = self.serializer(instance=self.participants, base_data=result) + self.result = self.serializer(instance=self.instance, base_data=result) return self.result def find_one(self, **kwargs): @@ -237,7 +279,7 @@ class Repository(object): kwargs['t_local'] = self result = self.operation.start(**kwargs) - self.result = self.serializer(instance=self.participants, base_data=result) + self.result = self.serializer(instance=self.instance, base_data=result) return self.result def find_sql(self, **kwargs): @@ -263,7 +305,7 @@ class Repository(object): kwargs['t_local'] = self result = self.operation.start(**kwargs) - self.result = self.serializer(instance=self.participants, base_data=result) + self.result = self.serializer(instance=self.instance, base_data=result) return self.result def update(self, **kwargs): diff --git a/CACodeFramework/cacode/Serialize.py b/CACodeFramework/cacode/Serialize.py index 48c8e89..5f4d1e5 100644 --- a/CACodeFramework/cacode/Serialize.py +++ b/CACodeFramework/cacode/Serialize.py @@ -263,17 +263,17 @@ class QuerySet(list): list.__init__([]) self.__instance__ = instance - self.using_fields = self.__instance__.__fields__ - self.all_using_fields = JsonUtil.parse(obj=self.__instance__, end_load=True) + self.__using_fields__ = self.__instance__.__fields__ + self.__all_using_fields__ = JsonUtil.parse(obj=self.__instance__, end_load=True) - self.ignore_field = {} - self.append_field = {} + self.__ignore_field__ = {} + self.__append_field__ = {} for i in base_data: self.append( QueryItem(data_item=i, - ignore_field_id=id(self.ignore_field), - append_field_id=id(self.append_field), - using_fields=self.using_fields)) + ignore_field_id=id(self.__ignore_field__), + append_field_id=id(self.__append_field__), + using_fields=self.__using_fields__)) def size(self): return len(self) @@ -329,11 +329,11 @@ class QuerySet(list): """ 添加一个不会被解析忽略的字段 """ - if key not in self.append_field.keys() and \ - key not in self.using_fields.keys() and \ - key not in self.all_using_fields.keys(): + if key not in self.__append_field__.keys() and \ + key not in self.__using_fields__.keys() and \ + key not in self.__all_using_fields__.keys(): - self.append_field[key] = default_value + self.__append_field__[key] = default_value else: CACodeLog.log(obj=self, msg='`{}` already exists'.format(key)) @@ -341,7 +341,7 @@ class QuerySet(list): """ 添加一个会被解析忽略的字段 """ - self.ignore_field[key] = None + self.__ignore_field__[key] = None class QueryItem(JsonUtil): diff --git a/CACodeFramework/exception/e_fields.py b/CACodeFramework/exception/e_fields.py index 656cadf..d31400f 100644 --- a/CACodeFramework/exception/e_fields.py +++ b/CACodeFramework/exception/e_fields.py @@ -26,6 +26,10 @@ def Log_Opera_Name(msg): return mat('CACode-DatabaseOperation', msg) +def Miss_Attr(msg): + return mat('CACode-Attribute', msg) + + def Error(): return 'ERROR' diff --git a/CACodeFramework/opera/op_db.py b/CACodeFramework/opera/op_db.py index bedf968..cd46883 100644 --- a/CACodeFramework/opera/op_db.py +++ b/CACodeFramework/opera/op_db.py @@ -58,7 +58,7 @@ class DbOperation(object): 任务方法 """ fields = ParseUtil(*args, is_field=True).parse_key() - sql_str = find_str + fields + from_str + kwargs['__table_name__'] + sql_str = kwargs['sqlFields'].find_str + fields + kwargs['sqlFields'].from_str + kwargs['__table_name__'] kwargs['sql'] = sql_str self.result = self.__find_many__(**kwargs) return self.result @@ -84,7 +84,7 @@ class DbOperation(object): self.result = [] for i in _rs: - self.result.append(ParseUtil.parse_obj(i, kwargs['participants'])) + self.result.append(ParseUtil.parse_obj(i, kwargs['instance'])) return self.result @@ -101,7 +101,8 @@ class DbOperation(object): raise SyntaxError('the key of `pojo` cannot be found in the parameters') filed_list = ParseUtil.parse_insert_pojo(kwargs['pojo'], __table_name__=kwargs['__table_name__'], - insert_str=insert_str, values_str=values_str) + insert_str=kwargs['sqlFields'].insert_str, + values_str=kwargs['sqlFields'].values_str) kwargs.update(filed_list) diff --git a/CACodeFramework/pojoManager/Manage.py b/CACodeFramework/pojoManager/Manage.py index 39287e5..60d28b4 100644 --- a/CACodeFramework/pojoManager/Manage.py +++ b/CACodeFramework/pojoManager/Manage.py @@ -23,13 +23,14 @@ class Pojo(CACodeRepository.Repository): self.__table_name__ = self.__table_name__ self.__table_msg__ = self.__table_msg__ + self.__fields__ = {} self.init_fields() for key, value in kwargs.items(): self.__setattr__(key, value) # 在这里将config_obj实例化 self.serializer = serializer super(Pojo, self).__init__(config_obj=config_obj, - participants=self, + instance=self, log_conf=log_conf, close_log=close_log, serializer=serializer, @@ -51,7 +52,6 @@ class Pojo(CACodeRepository.Repository): except SyntaxError: continue - self.fields = fds self.__fields__ = fds def to_json(self, bf=False): @@ -70,6 +70,15 @@ class Pojo(CACodeRepository.Repository): """ return JsonUtil.load(JsonUtil.parse(self)) + def getFields(self) -> dict: + return self.__fields__ + + def markTable(self): + """ + 将表生成至外部文件 + """ + pass + @property def orm(self): """ @@ -81,7 +90,7 @@ class Pojo(CACodeRepository.Repository): """ 为指定字段的值设置别名 """ - if 'ig' in self.__fields__.keys(): + if 'ig' in self.getFields().keys(): self.__fields__['ig'].append({ key: name }) diff --git a/CACodeFramework/util/Config.py b/CACodeFramework/util/Config.py index 500c983..1b35729 100644 --- a/CACodeFramework/util/Config.py +++ b/CACodeFramework/util/Config.py @@ -65,9 +65,9 @@ class config(object): """ return self.__dict__ - def get_json(self): + def get_json(self, bf=False): """ 将配置类转json :return: """ - return JsonUtil.parse(self.get_dict()) + return JsonUtil.parse(self.get_dict(), bf) diff --git a/CACodeFramework/util/DbUtil.py b/CACodeFramework/util/DbUtil.py index 5634b79..ec8cd06 100644 --- a/CACodeFramework/util/DbUtil.py +++ b/CACodeFramework/util/DbUtil.py @@ -3,7 +3,6 @@ import threading from CACodeFramework.cacode.Modes import Singleton from CACodeFramework.util.Log import CACodeLog -from dbutils.pooled_db import PooledDB import pymysql @@ -39,7 +38,6 @@ def parse_kwa(db, **kwargs): class Db_opera(object): """ - 操作数据库类 """ @@ -49,6 +47,44 @@ class Db_opera(object): mincached=2, maxcached=5, maxshared=3, blocking=True, setsession=[], ping=0, POOL=None): """ + + 设置DB-API 2连接池。 + + creator:返回新的DB-API 2的任意函数 + 连接对象或符合DB-API 2的数据库模块 + mincached:池中空闲连接的初始数量 + (0表示启动时未建立连接) + maxcached:池中最大空闲连接数 + (0或无表示池大小不受限制) + maxshared:共享连接的最大数量 + (0或无表示所有连接都是专用的) + 当达到此最大数量时,连接为 + 如果被要求共享,则将它们共享。 + maxconnections:通常允许的最大连接数 + (0或无表示任意数量的连接) + blocking:确定超出最大值时的行为 + (如果将其设置为true,请阻止并等待,直到 + 连接减少,否则将报告错误) + maxusage:单个连接的最大重用次数 + (0或无表示无限重用) + 当达到连接的最大使用次数时, + 连接将自动重置(关闭并重新打开)。 + setsession:可用于准备的SQL命令的可选列表 + 会话,例如[“将日期样式设置为...”,“将时区设置为...”] + reset:返回到池后应如何重置连接 + (对于以begin()开始的回滚事务,为False或None, + 出于安全考虑,总是发出回滚是正确的) + failures:可选的异常类或异常类的元组 + 为此,应应用连接故障转移机制, + 如果默认值(OperationalError,InternalError)不足够 + ping:确定何时应使用ping()检查连接 + (0 =无=永不,1 =默认=每当从池中获取时, + 2 =创建游标时,4 =执行查询时, + 7 =始终,以及这些值的所有其他位组合) + args,kwargs:应传递给创建者的参数 + 函数或DB-API 2模块的连接构造函数 + + 初始化配置 以下参数与PooledDB一致 :param creator:默认即可 @@ -88,6 +124,7 @@ class Db_opera(object): """ 初始化数据库连接池 """ + from dbutils.pooled_db import PooledDB if self.POOL is None: self.POOL = PooledDB(creator=self.creator, maxconnections=self.maxconnections, mincached=self.mincached, maxcached=self.maxcached, diff --git a/CACodeFramework/util/Log.py b/CACodeFramework/util/Log.py index e99fc51..8738e1f 100644 --- a/CACodeFramework/util/Log.py +++ b/CACodeFramework/util/Log.py @@ -206,7 +206,7 @@ class CACodeLog(object): hex_id = f"[{hex(id(obj))}]".ljust(FieldsLength.HEX_FORMAT) write_repr = f"[{write_repr}]".ljust(FieldsLength.CLASS_FORMAT) task_name = f"[{task_name}]".ljust(FieldsLength.TASK_FORMAT) - msg = f"\t\t:{msg}\n" + msg = f"\t\t:{msg}" info = "{}{}{}{}{}{}{}{}".format(t, field, line, operation_name, hex_id, write_repr, task_name, msg) diff --git a/CACodeFramework/util/ParseUtil.py b/CACodeFramework/util/ParseUtil.py index d42e2f1..f8d1008 100644 --- a/CACodeFramework/util/ParseUtil.py +++ b/CACodeFramework/util/ParseUtil.py @@ -261,3 +261,13 @@ class ParseUtil(object): setattr(obj, key, data[key]) else: setattr(obj, key, val) + + @staticmethod + def fieldExit(obj, field, el=None): + """ + 在对象中获取一个字段的值,如果这个字段不存在,则将值设置为`el` + """ + if hasattr(obj, field): + return getattr(obj, field) + else: + return el diff --git a/test/testFunc.py b/test/testFunc.py index ad2710f..6e9a84d 100644 --- a/test/testFunc.py +++ b/test/testFunc.py @@ -1,7 +1,6 @@ import time from CACodeFramework.cacode.Factory import Factory -from test.modules.Demo import DemoTable class MyFactory(Factory): @@ -11,11 +10,6 @@ class MyFactory(Factory): ] -def setData(): - for i in range(1000): - DemoTable(t_name=f'测试name{i}', t_pwd=f'测试pwd{i}', t_ms=f'测试msg{i}').save() - - if __name__ == '__main__': t1 = time.time() DemoTable = MyFactory.createInstance('Demo.DemoTable') -- Gitee From bfacfc5add255efa3d4e006d64d055ff6dd91bfe Mon Sep 17 00:00:00 2001 From: CACode Date: Thu, 6 May 2021 16:44:16 +0800 Subject: [PATCH 04/26] On branch main --- test/modules/DatabaseConf.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/modules/DatabaseConf.py b/test/modules/DatabaseConf.py index 951556c..27dbd03 100644 --- a/test/modules/DatabaseConf.py +++ b/test/modules/DatabaseConf.py @@ -12,10 +12,4 @@ class ConF(Config.config): self.set_field('print_sql', True) self.set_field('last_id', True) - host = "203.195.161.175" - port = 3306 - user = "root" - password = "Zyzs1234.." - database = "zh" - super(ConF, self).__init__(host, port, database, user, password, charset) -- Gitee From ed195eda95e51bd0409a540352358cefaa7a4e6c Mon Sep 17 00:00:00 2001 From: CACode Date: Thu, 6 May 2021 16:52:05 +0800 Subject: [PATCH 05/26] On branch main --- test/testFunc.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/testFunc.py b/test/testFunc.py index a71f88d..43f27cb 100644 --- a/test/testFunc.py +++ b/test/testFunc.py @@ -26,14 +26,8 @@ if __name__ == '__main__': t1 = time.time() demoTable = MyFactory.createInstance('DemoTable.DemoTable') count = 0 -<<<<<<< HEAD - result = DemoTable.orm.find().limit(10).end() - print(result.to_json(True)) - print(time.time() - t1) -======= # result = demoTable.find_all() result = demoTable.create(pojo=set_many(), many=True) info(f'time:{time.time() - t1}') info(f'count:{len(result)}') warn(result) ->>>>>>> cacode -- Gitee From 17a17fa62b99068f7c6957341eae2f5c333cebd6 Mon Sep 17 00:00:00 2001 From: CACode Date: Mon, 10 May 2021 07:00:54 +0800 Subject: [PATCH 06/26] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=80=82=E9=85=8D?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aop.py => MainWork/CACodeAopContainer.py} | 99 +---------- .../Config.py => MainWork/CACodeConfig.py} | 17 +- .../MainWork/CACodeCustomizeAdapter.py | 40 ++--- CACodeFramework/MainWork/CACodePureORM.py | 111 ++++++------ CACodeFramework/MainWork/CACodeRepository.py | 16 +- CACodeFramework/anno/annos.py | 13 +- CACodeFramework/field/FManage.py | 2 +- CACodeFramework/field/MySqlDefault.py | 160 ++++++++++++------ CACodeFramework/opera/CompulsoryRun.py | 2 + CACodeFramework/pojoManager/Manage.py | 2 +- CACodeFramework/util/ParseUtil.py | 50 ++---- test/modules/DatabaseConf.py | 23 ++- test/testFunc.py | 10 +- 13 files changed, 251 insertions(+), 294 deletions(-) rename CACodeFramework/{anno/aop.py => MainWork/CACodeAopContainer.py} (56%) rename CACodeFramework/{util/Config.py => MainWork/CACodeConfig.py} (77%) diff --git a/CACodeFramework/anno/aop.py b/CACodeFramework/MainWork/CACodeAopContainer.py similarity index 56% rename from CACodeFramework/anno/aop.py rename to CACodeFramework/MainWork/CACodeAopContainer.py index 4394c04..d420051 100644 --- a/CACodeFramework/anno/aop.py +++ b/CACodeFramework/MainWork/CACodeAopContainer.py @@ -1,6 +1,6 @@ import types -from CACodeFramework.opera.CompulsoryRun import Compulsory +from ..opera.CompulsoryRun import Compulsory class AopModelObject(object): @@ -11,8 +11,6 @@ class AopModelObject(object): def __init__(self, before=None, after=None, before_args=None, before_kwargs=None, after_args=None, after_kwargs=None): - # wraps(func)(self) - # self.func = func # 初始化所有字段 self.__before_func__ = before self.__before_args_data__ = before_args @@ -22,9 +20,6 @@ class AopModelObject(object): self.__after_args_data__ = after_args self.__after_kwargs_data__ = after_kwargs - def set_func(self, func): - self.func = func - def set_args(self, *args, **kwargs): self.args = args self.kwargs = kwargs @@ -33,7 +28,6 @@ class AopModelObject(object): """ 主操作 """ - # self.func = args[0] self.init_fields() # wraps(self.func)(self) @@ -44,7 +38,8 @@ class AopModelObject(object): # 执行before操作 self.before_run() # 执行原始数据 - result = self.original_func() + result = Compulsory.run_function( + func=self.func, args=self.args, kwargs=self.kwargs) # after解析 # self.after_parse(result) # after操作 @@ -130,39 +125,13 @@ class AopModelObject(object): v3=self.__after_kwargs_name__ ) - # def before_parse(self): - # """ - # 解析before参数的方法需要什么参数类型 - # """ - # __before_func__ = None - # __before_args_data__ = None - # __before_kwargs_data__ = None - # # 如果包含切入函数的字段 - # if hasattr(self, self.__before_name__): - # # 得到参数的名称 - # __before_func__ = getattr(self, self.__before_name__) - # if hasattr(self, self.__before_args_name__) and hasattr(self, self.__before_kwargs_name__): - # - # __before_args_data__ = getattr(self, self.__before_args_name__) - # __before_kwargs_data__ = getattr(self, self.__before_kwargs_name__) - # - # elif hasattr(self, self.__before_args_name__): - # __before_args_data__ = getattr(self, self.__before_args_name__) - # - # elif hasattr(self, self.__before_kwargs_name__): - # __before_kwargs_data__ = getattr(self, self.__before_kwargs_name__) - # - # # 批添加方法、参数和键值对 - # self.__before_func__ = __before_func__ - # self.__before_args_data__ = __before_args_data__ - # self.__before_kwargs_data__ = __before_kwargs_data__ - def before_run(self): """ 执行before方法 """ if self.__before_func__ and self.__before_args_data__ and self.__before_kwargs_data__: - self.__before_func__(*self.__before_args_data__, **self.__before_kwargs_data__) + self.__before_func__(*self.__before_args_data__, + **self.__before_kwargs_data__) elif self.__before_func__ and self.__before_args_data__: self.__before_func__(*self.__before_args_data__) elif self.__before_func__ and self.__before_kwargs_data__: @@ -172,35 +141,6 @@ class AopModelObject(object): else: pass - # def after_parse(self, result): - # """ - # 解析追加方法 - # :param result:原始方法返回的值 - # """ - # __after_func__ = None - # __after_args_data__ = None - # __after_kwargs_data__ = {} - # # 如果包含切入函数的字段 - # if hasattr(self, self.__after_name__): - # # 得到参数的名称 - # __after_func__ = getattr(self, self.__after_name__) - # if hasattr(self, self.__after_args_name__) and hasattr(self, self.__after_kwargs_name__): - # - # __after_args_data__ = getattr(self, self.__after_args_name__) - # __after_kwargs_data__ = getattr(self, self.__after_kwargs_name__) - # - # elif hasattr(self, self.__after_args_name__): - # __after_args_data__ = getattr(self, self.__after_args_name__) - # - # elif hasattr(self, self.__after_kwargs_name__): - # __after_kwargs_data__ = getattr(self, self.__after_kwargs_name__) - # - # # 批添加方法、参数和键值对 - # self.__after_func__ = __after_func__ - # self.__after_args_data__ = __after_args_data__ - # __after_kwargs_data__.update({'result': result}) - # self.__after_kwargs_data__ = __after_kwargs_data__ - def after_run(self, result): """ 执行after方法 @@ -210,7 +150,8 @@ class AopModelObject(object): self.__after_kwargs_data__.update({'result': result}) if self.__after_func__ and self.__after_args_data__ and self.__after_kwargs_data__: - self.__after_func__(*self.__after_args_data__, **self.__after_kwargs_data__) + self.__after_func__(*self.__after_args_data__, + **self.__after_kwargs_data__) elif self.__after_func__ and self.__after_args_data__: self.__after_func__(*self.__after_args_data__) elif self.__after_func__ and self.__after_kwargs_data__: @@ -219,29 +160,3 @@ class AopModelObject(object): self.__after_func__() else: pass - - def original_func(self): - """ - 最后使用强制法返回函数执行的结果 - 使用四个try逐一抛出 - """ - return Compulsory.run_function(func=self.func, args=self.args, kwargs=self.kwargs) - # try: - # return self.func(*self.args, **self.kwargs) - # except TypeError as e: - # pass - # - # try: - # return self.func(*self.args) - # except TypeError as e: - # pass - # - # try: - # return self.func(**self.kwargs) - # except TypeError as e: - # pass - # - # try: - # return self.func() - # except TypeError as e: - # pass diff --git a/CACodeFramework/util/Config.py b/CACodeFramework/MainWork/CACodeConfig.py similarity index 77% rename from CACodeFramework/util/Config.py rename to CACodeFramework/MainWork/CACodeConfig.py index 4c664a1..039a2d7 100644 --- a/CACodeFramework/util/Config.py +++ b/CACodeFramework/MainWork/CACodeConfig.py @@ -1,10 +1,10 @@ -from CACodeFramework.cacode.Serialize import JsonUtil -from CACodeFramework.exception.e_fields import FieldNotExist -from CACodeFramework.util.Log import CACodeLog -from CACodeFramework.util.ParseUtil import ParseUtil +from ..cacode.Serialize import JsonUtil +from ..exception.e_fields import FieldNotExist +from ..util.Log import CACodeLog +from ..util.ParseUtil import ParseUtil -class config(ParseUtil): +class Conf(ParseUtil): """ 配置类: 默认必须携带操作数据库所需的参数: @@ -17,7 +17,7 @@ class config(ParseUtil): - conf:其他配置 """ - def __init__(self, host, port, database, user, password, charset='utf8', creator=None): + def __init__(self, host, port, database, user, password, charset='utf8', creator=None, **kwargs): """ 必须要有的参数 :param host:数据库地址 @@ -30,7 +30,8 @@ class config(ParseUtil): """ if creator is None: - CACodeLog.log_error(msg="缺少数据库创建者,你是不是要设置`creator=pymysql`?", obj=FieldNotExist, raise_exception=True) + CACodeLog.log_error(msg="The creator is missing, do you want to set`creator=pymysql`?", + obj=FieldNotExist, raise_exception=True) self.creator = creator self.host = host self.port = port @@ -38,6 +39,8 @@ class config(ParseUtil): self.user = user self.password = password self.charset = charset + ParseUtil.insert_to_obj(self, kwargs) + super(Conf, self).__init__() def get(self): """ diff --git a/CACodeFramework/MainWork/CACodeCustomizeAdapter.py b/CACodeFramework/MainWork/CACodeCustomizeAdapter.py index 0f4bace..03ae76e 100644 --- a/CACodeFramework/MainWork/CACodeCustomizeAdapter.py +++ b/CACodeFramework/MainWork/CACodeCustomizeAdapter.py @@ -1,32 +1,22 @@ -from CACodeFramework.cacode.Serialize import QuerySet -from CACodeFramework.field.MySqlDefault import MySqlFields_Default - - -class Adapter(object): +class LanguageAdapter: """ 适配器,将sql方言适配到ORM框架中,实现sql自由 - 从配置表中开始配置sql方言,继承SqlLanguage类并实现抽象方法,开启 - - + 实现当前类,在orm操作中存在自定义字段时,保证所有的操作都能够按照你所希望的那样执行 """ - def __init__(self, repositoryId, serializer=QuerySet, sqlFields=MySqlFields_Default): - self.repositoryId = repositoryId - self.serializer = serializer - self.sqlFields = sqlFields() - self.sql = [] - - def getFormId(self, obj_id): - pass - - def setField(self, string): - """ - 设置一个字段 - """ - self.sql.append("{}{}{}".format(self.sqlFields.space, string, self.sqlFields.space)) - - class language: - pass + def __init__(self): + if hasattr(self, 'funcs'): + self.funcs['like'] = self.like + else: + self.funcs = { + 'like': self.like + } + + def like(self, instance, key, value): + instance.args.append('`' + key + '`') + instance.args.append(' LIKE ') + instance.args.append('%s') + instance.params.append(value) diff --git a/CACodeFramework/MainWork/CACodePureORM.py b/CACodeFramework/MainWork/CACodePureORM.py index bfea730..ebb032b 100644 --- a/CACodeFramework/MainWork/CACodePureORM.py +++ b/CACodeFramework/MainWork/CACodePureORM.py @@ -1,9 +1,9 @@ -from CACodeFramework.cacode.Serialize import QuerySet -from CACodeFramework.exception import e_fields -from CACodeFramework.util.Log import CACodeLog -from CACodeFramework.util.ParseUtil import ParseUtil +from ..cacode.Serialize import QuerySet +from ..exception import e_fields +from ..util.Log import CACodeLog +from ..util.ParseUtil import ParseUtil -from CACodeFramework.field.MySqlDefault import MySqlFields_Default +from ..field.MySqlDefault import MySqlFields_Default class CACodePureORM(object): @@ -17,7 +17,7 @@ class CACodePureORM(object): 上手快 """ - def __init__(self, repository, serializer=QuerySet, sqlFields=MySqlFields_Default()): + def __init__(self, repository, **kwargs): """ 初始化ORM @@ -29,15 +29,21 @@ class CACodePureORM(object): s """ self.args = [] self.params = [] - self.sqlFields = sqlFields + self.sqlFields = None + # self.sqlFields = sqlFields + ParseUtil.set_field_compulsory(self, key='serializer', data=kwargs, + val=QuerySet) + ParseUtil.set_field_compulsory(self, key='sqlFields', data=kwargs, + val=MySqlFields_Default()) + # 创建sql语法 if repository is None: - CACodeLog.err(AttributeError, 'Repository is null,Place use repository of ORM framework') + CACodeLog.err( + AttributeError, 'Repository is null,Place use repository of ORM framework') self.repository = repository - self.__table_name__ = '{}{}{}'.format(self.sqlFields.subscript, repository.__table_name__, - self.sqlFields.subscript) + self.__table_name__ = '{}{}{}'.format(self.sqlFields.left_subscript, repository.__table_name__, + self.sqlFields.right_subscript) self.first_data = False - self.serializer = serializer def top(self): return self.find().limit(1) @@ -62,7 +68,8 @@ s """ # 添加insert关键字 # self.args.append(insert_str) # self.args.append('{}{}'.format(self.__table_name__, left_par)) - sql = self.repository.config_obj.parse_insert_pojo(pojo, self.__table_name__.replace('`', '')) + sql = self.repository.config_obj.parse_insert_pojo( + pojo, self.__table_name__.replace('`', '')) self.args.append(sql['sql']) self.params = sql['params'] @@ -104,7 +111,8 @@ s """ example: update().set(key=value).where(key1=value1) """ - update_sql = '%s%s' % (self.sqlFields.update_str, str(self.__table_name__)) + update_sql = '%s%s' % (self.sqlFields.update_str, + str(self.__table_name__)) self.args.append(update_sql) return self @@ -121,7 +129,6 @@ s """ 如果args字段长度为0,默认为查找全部 """ self.args.append(self.sqlFields.find_str) - fields = '' # 如果有as字段 asses = None if 'asses' in kwargs.keys(): @@ -139,23 +146,25 @@ s """ if _all or 'all'.upper() == args[0].upper(): # 如果包含all关键字,则使用解析工具解析成字段参数 if not func_flag: - fields = ParseUtil(*self.repository.fields, is_field=True).parse_key() + fields = self.repository.config_obj.parse_key(*self.repository.fields, is_field=True) else: - fields = ParseUtil(*self.repository.fields, is_field=True).parse_key(is_field=False) + fields = self.repository.config_obj.parse_key(*self.repository.fields, is_field=False) else: if not func_flag: - fields = ParseUtil(*args, is_field=True).parse_key() + fields = self.repository.config_obj.parse_key(*args, is_field=True) else: - fields = ParseUtil(*args, is_field=True).parse_key(is_field=False) + fields = self.repository.config_obj.parse_key(*args) # 解决as问题 if asses is not None: fs = fields.split(',') if len(fs) != len(asses): # 匿名参数长度与字段长度不符合 - raise TypeError('The length of the anonymous parameter does not match the length of the field') + raise TypeError( + 'The length of the anonymous parameter does not match the length of the field') for i, v in enumerate(fs): if asses[i] is not None: - self.args.append('{}{}{}'.format(v, self.sqlFields.asses_str, asses[i])) + self.args.append('{}{}{}'.format( + v, self.sqlFields.asses_str, asses[i])) else: self.args.append(v) # 逗号 @@ -193,9 +202,9 @@ s """ """ self.args.append(field) for i in args_list: - self.args.append(self.sqlFields.subscript) + self.args.append(self.sqlFields.left_subscript) self.args.append(i) - self.args.append(self.sqlFields.subscript) + self.args.append(self.sqlFields.right_subscript) self.args.append(self.sqlFields.ander_str) self.rep_sym(self.sqlFields.ander_str, self.sqlFields.space) return self @@ -220,6 +229,7 @@ s """ self.args.append(self.sqlFields.where_str) for key, value in kwargs.items(): cp_key = key + customize = False sym = '=' if len(str(value)) > 2 and str(value)[0:2] in self.sqlFields.symbol: sym = value[0:2] @@ -234,15 +244,17 @@ s """ # 没有找到符号的话就从字段名开始 # 截取最后一段从两段下划线开始的末尾 sps = cp_key.split('__') - sym = sps[len(sps) - 1] - - cp_key = cp_key[:cp_key.rfind('__' + sym)] - - sym = ' ' + sym + ' ' - - self.args.append('`{}`{}%s'.format(cp_key, sym)) - self.args.append(self.sqlFields.ander_str) - self.params.append(value) + if not len(sps) == 1: + customize = True + sym = sps[len(sps) - 1] + ParseUtil.fieldExist(self.repository.config_obj, 'adapter', raise_exception=True) + cp_key = cp_key[:cp_key.rfind('__' + sym)] + self.repository.config_obj.adapter.funcs[sym](self, cp_key, value) + + if not customize: + self.args.append('`{}`{}%s'.format(cp_key, sym)) + self.args.append(self.sqlFields.ander_str) + self.params.append(value) self.rep_sym(self.sqlFields.ander_str) return self @@ -259,7 +271,8 @@ s """ self.args.append(self.sqlFields.limit_str) # 死亡空格 if end is None: - limit_param = '{}{}{}'.format(self.sqlFields.space, star, self.sqlFields.space) + limit_param = '{}{}{}'.format( + self.sqlFields.space, star, self.sqlFields.space) else: limit_param = '{}{}{}{}{}'.format(self.sqlFields.space, star, self.sqlFields.comma, end, self.sqlFields.space) @@ -276,9 +289,9 @@ s """ """ if self.sqlFields.order_by_str not in self.args: - raise CACodeLog.err(AttributeError, - e_fields.CACode_SqlError( - 'There is no `order by` field before calling `desc` field,You have an error in your SQL syntax')) + CACodeLog.err(AttributeError, + e_fields.CACode_SqlError('There is no `order by` field before calling `desc` field,' + 'You have an error in your SQL syntax')) self.args.append(self.sqlFields.desc_str) return self @@ -331,7 +344,8 @@ s """ ) _result_objs = [] for i in _result: - _obj = ParseUtil.parse_obj(data=i, instance=self.repository.instance) + _obj = ParseUtil.parse_obj( + data=i, instance=self.repository.instance) _result_objs.append(_obj) _result = _result_objs else: @@ -348,7 +362,8 @@ s """ if type(_result) is list or type(_result) is tuple: return self.serializer(instance=self.repository.instance, base_data=_result).first() else: - q = self.serializer(instance=self.repository.instance, base_data=_result) + q = self.serializer( + instance=self.repository.instance, base_data=_result) return q def con_from(self): @@ -371,27 +386,9 @@ s """ """ 将最后一个参数包含的指定字符替换为指定字符 """ - self.args[len(self.args) - 1] = str(self.args[len(self.args) - 1]).replace(sym, rep) + self.args[len(self.args) - + 1] = str(self.args[len(self.args) - 1]).replace(sym, rep) return self def end(self): return self.run() - - def adapter(self): - """ - 适配器: - 将当前ORM对象转换为可自定义sql方言的适配器并使用方法的__name__值作为方法名调用, - - 请注意,结尾使用的`_str`严格按照下划线加小写方式定义,大写不做识别处理,默认当成无效字符销毁在内存中 - - 名字格式: - 示例: - select_str:以关键字开头,_str结尾 - order_by_str:多个字段以下划线分割,_str结尾 - - 实际: - select_all_from_demo_where_id_str - - - """ - pass diff --git a/CACodeFramework/MainWork/CACodeRepository.py b/CACodeFramework/MainWork/CACodeRepository.py index e69481f..b70b269 100644 --- a/CACodeFramework/MainWork/CACodeRepository.py +++ b/CACodeFramework/MainWork/CACodeRepository.py @@ -1,13 +1,13 @@ import copy -from CACodeFramework.cacode.Serialize import QuerySet -from CACodeFramework.exception import e_fields -from CACodeFramework.field import MySqlDefault -from CACodeFramework.opera import op_db -from CACodeFramework.util.Log import CACodeLog +from ..cacode.Serialize import QuerySet +from ..exception import e_fields +from ..field import MySqlDefault +from ..opera import op_db +from ..util.Log import CACodeLog -from CACodeFramework.MainWork.CACodePureORM import CACodePureORM -from CACodeFramework.util import DbUtil +from ..MainWork.CACodePureORM import CACodePureORM +from ..util import DbUtil # 每个任务唯一ID import uuid @@ -158,7 +158,7 @@ class Repository: Return: ORM转换之后的实体对象 """ - return CACodePureORM(self, serializer=self.serializer) + return CACodePureORM(repository=self, serializer=self.serializer, sqlFields=self.sqlFields) def first(self): """ diff --git a/CACodeFramework/anno/annos.py b/CACodeFramework/anno/annos.py index 1401ae6..2107742 100644 --- a/CACodeFramework/anno/annos.py +++ b/CACodeFramework/anno/annos.py @@ -1,10 +1,3 @@ -import re -import inspect - -from CACodeFramework.anno.aop import AopModelObject -from CACodeFramework.cacode.Serialize import QuerySet - - def Table(name, msg, **kwargs): """ 标注该类为一个表 @@ -27,6 +20,7 @@ def parse_kwargs(params, kwargs): """ 通过${key}方式解析特殊字段 """ + import re new_args = [] for i in params: # 反选字符并替换 @@ -73,7 +67,7 @@ def Select(sql, params=None): new_args = parse_kwargs(params, kwargs) result = obj.find_sql(sql=sql, params=new_args) - + from CACodeFramework.cacode.Serialize import QuerySet return QuerySet(obj, result) return _wrapper_ @@ -176,12 +170,13 @@ def AopModel(before=None, after=None, """ # 得到对象组 + from CACodeFramework.MainWork.CACodeAopContainer import AopModelObject aop_obj = AopModelObject(before, after, before_args, before_kwargs, after_args, after_kwargs) def base_func(func): - aop_obj.set_func(func) + aop_obj.func = func def _wrapper_(*args, **kwargs): aop_obj.set_args(*args, **kwargs) diff --git a/CACodeFramework/field/FManage.py b/CACodeFramework/field/FManage.py index 99da282..7c117c4 100644 --- a/CACodeFramework/field/FManage.py +++ b/CACodeFramework/field/FManage.py @@ -28,7 +28,7 @@ class FieldControl: """ for k, v in data.items(): self.fields.append({ - str(k)[0:len(k) - 1].replace('_', ' '), v + str(k)[0:len(k) - 1].replace('_', ' '), }) def formatFromFile(self, path): diff --git a/CACodeFramework/field/MySqlDefault.py b/CACodeFramework/field/MySqlDefault.py index 8c0b19c..79b0674 100644 --- a/CACodeFramework/field/MySqlDefault.py +++ b/CACodeFramework/field/MySqlDefault.py @@ -2,13 +2,7 @@ # 空格符 import threading -from CACodeFramework.cacode.Modes import Singleton - -space = ' ' - - -def parse_field(key: str) -> str: - return space + key + space +from ..cacode.Modes import Singleton class MySqlFields_Default: @@ -18,48 +12,116 @@ class MySqlFields_Default: _instance_lock = threading.RLock() - def __init__(self): - # 角标 - self.subscript = '`' - # 插入 - self.insert_str = parse_field('INSERT INTO') - # 删除 - self.delete_str = parse_field('DELETE') - # 修改 - self.update_str = parse_field('UPDATE') - # 查找 - self.find_str = parse_field('SELECT') - # 当 - self.where_str = parse_field('WHERE') - # 根据 - self.by_str = parse_field('BY') - # 根据排序 - self.order_by_str = parse_field('ORDER BY') - # 根据 - self.group_by_str = parse_field('GROUP BY') - # 倒叙 - self.desc_str = parse_field('DESC') - # 设置 - self.set_str = parse_field('SET') - # 和 - self.ander_str = parse_field('AND') - # 分页 - self.limit_str = parse_field('LIMIT') - # 从 - self.from_str = parse_field('FROM') - # 值 - self.value_str = parse_field('VALUE') - # 多个值 - self.values_str = parse_field('VALUES') - # as - self.asses_str = parse_field('as') - # 运算符 - self.symbol = '>> << == <= >= != - + / * %'.split(' ') - self.left_par = parse_field('(') - self.right_par = parse_field(')') - self.comma = parse_field(',') - self.eq = parse_field('=') - self.space = " " + @staticmethod + def parse_field(key: str) -> str: + return f' {key} ' + + @property + def left_subscript(self): + """ + 左角标 + """ + return '`' + + @property + def right_subscript(self): + """ + 右角标 + """ + return '`' + + @property + def insert_str(self): + """ + 插入 + """ + return self.parse_field('INSERT INTO') + + @property + def delete_str(self): + """ + 删除 + """ + return self.parse_field('DELETE') + + @property + def update_str(self): + """ + 更新 + """ + return self.parse_field('UPDATE') + + @property + def find_str(self): + return self.parse_field('SELECT') + + @property + def where_str(self): + return self.parse_field('WHERE') + + @property + def by_str(self): + return self.parse_field('BY') + + @property + def order_by_str(self): + return self.parse_field('ORDER BY') + + @property + def group_by_str(self): + return self.parse_field('GROUP BY') + + @property + def desc_str(self): + return self.parse_field('DESC') + + @property + def set_str(self): + return self.parse_field('SET') + + @property + def ander_str(self): + return self.parse_field('AND') + + @property + def limit_str(self): + return self.parse_field('LIMIT') + + @property + def from_str(self): + return self.parse_field('FROM') + + @property + def value_str(self): + return self.parse_field('VALUE') + + @property + def values_str(self): + return self.parse_field('VALUES') + + @property + def asses_str(self): + return self.parse_field('AS') + + @property + def left_par(self): + return self.parse_field('(') + + @property + def right_par(self): + return self.parse_field(')') + + @property + def comma(self): + return self.parse_field(',') + + @property + def eq(self): + return self.parse_field('=') + + @property + def symbol(self): + return '>> << == <= >= != - + / * %'.split(' ') def parse_set(self, keys): """ diff --git a/CACodeFramework/opera/CompulsoryRun.py b/CACodeFramework/opera/CompulsoryRun.py index f3c0251..5e34abd 100644 --- a/CACodeFramework/opera/CompulsoryRun.py +++ b/CACodeFramework/opera/CompulsoryRun.py @@ -24,6 +24,8 @@ class Compulsory(object): except TypeError as e: pass + return None + @staticmethod def search_target(module, target_names): diff --git a/CACodeFramework/pojoManager/Manage.py b/CACodeFramework/pojoManager/Manage.py index 86bb618..5f433ab 100644 --- a/CACodeFramework/pojoManager/Manage.py +++ b/CACodeFramework/pojoManager/Manage.py @@ -116,7 +116,7 @@ class Pojo(CACodeRepository.Repository): """ 转ORM框架 """ - return CACodePureORM(self, self.serializer) + return CACodePureORM(repository=self, serializer=self.serializer, sqlFields=self.sqlFields) def format(self, key, name): """ diff --git a/CACodeFramework/util/ParseUtil.py b/CACodeFramework/util/ParseUtil.py index cb2e118..0b7248e 100644 --- a/CACodeFramework/util/ParseUtil.py +++ b/CACodeFramework/util/ParseUtil.py @@ -2,24 +2,13 @@ import copy from typing import List -from CACodeFramework.exception.e_fields import FieldNotExist -from CACodeFramework.pojoManager import tag -from CACodeFramework.util.Log import CACodeLog +from ..exception.e_fields import FieldNotExist +from ..pojoManager import tag +from ..util.Log import CACodeLog class ParseUtil(object): - def __init__(self, *args, to_str=False, is_field=False): - """ - 初始化解析参数工具 - :param args:需要解析的参数 - :param to_str:是否转成str格式 - :param is_field:是否为表字段格式 - """ - self.args = args - self.to_str = to_str - self.is_field = is_field - def parse_main(self, *args, to_str=False, is_field=False, symbol='%s'): """ 解析属性: @@ -38,7 +27,7 @@ class ParseUtil(object): else: fields.append(f'{symbol},' % (str(value))) else: - fields.append(value) + fields.append(value if not ParseUtil.is_default(value) else None) if len(fields) != 0: fields[len(fields) - 1] = fields[len(fields) - 1].replace(',', '') field_str = '' @@ -57,12 +46,7 @@ class ParseUtil(object): :param args: :return: """ - if args is not None and len(args) != 0: - self.args = args - if 'is_field' in kwargs.keys(): - self.is_field = kwargs['is_field'] - - fields = self.parse_main(*self.args, to_str=True, is_field=self.is_field) + fields = self.parse_main(*args, to_str=True, **kwargs) return fields def parse_value(self, *args, **kwargs): @@ -72,11 +56,7 @@ class ParseUtil(object): :param args: :return: """ - if args is not None and len(args) != 0: - self.args = args - if 'to_str' in kwargs.keys(): - self.to_str = kwargs['to_str'] - values = self.parse_main(*self.args, to_str=self.to_str) + values = self.parse_main(*args, **kwargs) return values def parse_insert(self, keys, values, __table_name__, insert_str, values_str, symbol='%s', @@ -91,9 +71,7 @@ class ParseUtil(object): values_str:values字符串 symbol:格式化方式,以`%s`作为匿名符号 """ - self.is_field = True fields = self.parse_key(*keys) - self.to_str = False values = self.parse_value(*values) # 分析需要几个隐藏值 hides_value = [f'{symbol},' for i in range(len(values))] @@ -252,9 +230,8 @@ class ParseUtil(object): 是否等于默认值 """ try: - t_v = __val.__class__.__bases__ - t_bf = tag.baseTag - return t_v[len(t_v) - 1] == t_bf + t_v = __val.__class__.__base__ + return t_v == tag.Template or t_v == tag.baseTag except SyntaxError: return False @@ -282,7 +259,7 @@ class ParseUtil(object): setattr(obj, key, val) @staticmethod - def fieldExist(obj: (object, dict), field: str, el=None, raise_exception=False) -> (object, Exception): + def fieldExist(obj: object, field: str, el=None, raise_exception=False) -> object: """ 在对象中获取一个字段的值,如果这个字段不存在,则将值设置为`el` """ @@ -292,7 +269,7 @@ class ParseUtil(object): else: if raise_exception: raise CACodeLog.log_error( - msg=f'the key of `pojo` cannot be found in the `{obj.__class__.__name__}`', + msg=f'the key of `{field}` cannot be found in the `{obj.__class__.__name__}`', obj=FieldNotExist, raise_exception=True) else: @@ -303,7 +280,7 @@ class ParseUtil(object): else: if raise_exception: raise CACodeLog.log_error( - msg=f'the key of `pojo` cannot be found in the `{obj.__class__.__name__}`', + msg=f'the key of `{field}` cannot be found in the `{obj.__class__.__name__}`', obj=FieldNotExist, raise_exception=True) else: @@ -319,3 +296,8 @@ class ParseUtil(object): cp_value.append(tuple(cp_v)) # 真实值 return cp_value + + @staticmethod + def insert_to_obj(obj, kwargs): + for key, value in kwargs.items(): + ParseUtil.set_field_compulsory(obj=obj, key=key, data=kwargs, val=value) diff --git a/test/modules/DatabaseConf.py b/test/modules/DatabaseConf.py index e7f6e81..e13ae5b 100644 --- a/test/modules/DatabaseConf.py +++ b/test/modules/DatabaseConf.py @@ -1,12 +1,22 @@ import pymssql import pymysql -from CACodeFramework.pojoManager import Manage -from CACodeFramework.util import Config -from CACodeFramework.util.Log import CACodeLog +from CACodeFramework.MainWork import CACodeConfig +from CACodeFramework.MainWork.CACodeCustomizeAdapter import LanguageAdapter -class MySqlConfig(Config.config): +class Adapter(LanguageAdapter): + def __init__(self): + self.funcs = { + 'fuck': self.__fuck + } + super(Adapter, self).__init__() + + def __fuck(self, instance, key, value): + self.like(instance, key, value) + + +class MySqlConfig(CACodeConfig.Conf): def __init__(self, host='localhost', port=3306, @@ -17,10 +27,11 @@ class MySqlConfig(Config.config): self.set_field('print_sql', True) self.set_field('last_id', True) - super(MySqlConfig, self).__init__(host, port, database, user, password, charset, creator=pymysql) + super(MySqlConfig, self).__init__(host, port, database, user, password, charset, creator=pymysql, + adapter=Adapter()) -class SqlServerConfig(Config.config): +class SqlServerConfig(CACodeConfig.Conf): def __init__(self, host='localhsot', port=1433, diff --git a/test/testFunc.py b/test/testFunc.py index 4ddba11..69fd38e 100644 --- a/test/testFunc.py +++ b/test/testFunc.py @@ -4,7 +4,6 @@ Date: 2021-04-26 11:46:16 LastEditTime: 2021-05-08 15:41:38 LastEditors: Please set LastEditors Description: Update Test -FilePath: \CACodeFramework-python-ORM\test\testFunc.py ''' import time @@ -22,7 +21,7 @@ class MyFactory(Factory): def set_many(): a = [] - for i in range(100000, 1000000): + for i in range(0, 1): a.append( MyFactory.createInstance('MySqlTest.DemoTable', t_msg=f'测试msg{i}', t_name=f'测试name{i}', t_pwd=f'测试pwd{i}', abs=True)) @@ -32,13 +31,14 @@ def set_many(): def TestMySql(): demoTable = MyFactory.createInstance('MySqlTest.DemoTable') # result = demoTable.find_all() - # test_data = set_many() + test_data = set_many() t = time.time() + result = demoTable.create(pojo=test_data, many=True) # result = demoTable.find_by_id(t_id=10) # page = result.page(7) # r = page.to_dict() - r = demoTable.orm.find().where(t_msg='测试msg1').end() - info(r) + # r = demoTable.orm.find().where(t_msg__fuck='1').end() + info(result) # info(f'count:{len(result)}') info(f'application run time:{time.time() - t}') # warn(result) -- Gitee From aff6b9e58b754933d65101196172204a928a9ec5 Mon Sep 17 00:00:00 2001 From: CACode <54068986+cctvadmin@users.noreply.github.com> Date: Mon, 10 May 2021 10:22:04 +0800 Subject: [PATCH 07/26] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=80=82=E9=85=8D?= =?UTF-8?q?=E5=99=A8=5Fin(self,instance,key,value)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...deCustomizeAdapter.py => CACodeAdapter.py} | 21 ++++++++---- CACodeFramework/MainWork/CACodePureORM.py | 32 ++++++++----------- CACodeFramework/MainWork/CACodeRepository.py | 5 +-- CACodeFramework/pojoManager/Manage.py | 4 +-- test/modules/DatabaseConf.py | 4 +-- test/testFunc.py | 17 +++++----- 6 files changed, 41 insertions(+), 42 deletions(-) rename CACodeFramework/MainWork/{CACodeCustomizeAdapter.py => CACodeAdapter.py} (49%) diff --git a/CACodeFramework/MainWork/CACodeCustomizeAdapter.py b/CACodeFramework/MainWork/CACodeAdapter.py similarity index 49% rename from CACodeFramework/MainWork/CACodeCustomizeAdapter.py rename to CACodeFramework/MainWork/CACodeAdapter.py index 03ae76e..0474b35 100644 --- a/CACodeFramework/MainWork/CACodeCustomizeAdapter.py +++ b/CACodeFramework/MainWork/CACodeAdapter.py @@ -6,17 +6,24 @@ class LanguageAdapter: 实现当前类,在orm操作中存在自定义字段时,保证所有的操作都能够按照你所希望的那样执行 """ + funcs = {} def __init__(self): - if hasattr(self, 'funcs'): - self.funcs['like'] = self.like - else: - self.funcs = { - 'like': self.like - } + self.funcs['like'] = self._like_opera + self.funcs['in'] = self._in_opera - def like(self, instance, key, value): + def _like_opera(self, instance, key, value): instance.args.append('`' + key + '`') instance.args.append(' LIKE ') instance.args.append('%s') instance.params.append(value) + + def _in_opera(self, instance, key, value): + if isinstance(value, list): + instance.args.append('`' + key + '`') + instance.args.append(' IN ') + value = [str(i) for i in value] + vals = ','.join(value) + instance.args.append(f'( {vals} )') + else: + raise AttributeError('value type is not list or QuerySet object') diff --git a/CACodeFramework/MainWork/CACodePureORM.py b/CACodeFramework/MainWork/CACodePureORM.py index ebb032b..12d9b83 100644 --- a/CACodeFramework/MainWork/CACodePureORM.py +++ b/CACodeFramework/MainWork/CACodePureORM.py @@ -1,9 +1,5 @@ -from ..cacode.Serialize import QuerySet from ..exception import e_fields from ..util.Log import CACodeLog -from ..util.ParseUtil import ParseUtil - -from ..field.MySqlDefault import MySqlFields_Default class CACodePureORM(object): @@ -17,7 +13,7 @@ class CACodePureORM(object): 上手快 """ - def __init__(self, repository, **kwargs): + def __init__(self, repository): """ 初始化ORM @@ -25,16 +21,14 @@ class CACodePureORM(object): 自定义方言除了可使用默认已存在的方法,还可以使用自定义sql方言拼接 :param repository:仓库 - :param sqlFields:sql方言的对象,默认使用MysqlFieldDefault设置 s """ self.args = [] self.params = [] self.sqlFields = None # self.sqlFields = sqlFields - ParseUtil.set_field_compulsory(self, key='serializer', data=kwargs, - val=QuerySet) - ParseUtil.set_field_compulsory(self, key='sqlFields', data=kwargs, - val=MySqlFields_Default()) + self.ParseUtil = repository.config_obj + self.serializer = repository.serializer + self.sqlFields = repository.sqlFields # 创建sql语法 if repository is None: CACodeLog.err( @@ -68,7 +62,7 @@ s """ # 添加insert关键字 # self.args.append(insert_str) # self.args.append('{}{}'.format(self.__table_name__, left_par)) - sql = self.repository.config_obj.parse_insert_pojo( + sql = self.ParseUtil.parse_insert_pojo( pojo, self.__table_name__.replace('`', '')) self.args.append(sql['sql']) self.params = sql['params'] @@ -146,14 +140,14 @@ s """ if _all or 'all'.upper() == args[0].upper(): # 如果包含all关键字,则使用解析工具解析成字段参数 if not func_flag: - fields = self.repository.config_obj.parse_key(*self.repository.fields, is_field=True) + fields = self.ParseUtil.parse_key(*self.repository.fields, is_field=True) else: - fields = self.repository.config_obj.parse_key(*self.repository.fields, is_field=False) + fields = self.ParseUtil.parse_key(*self.repository.fields, is_field=False) else: if not func_flag: - fields = self.repository.config_obj.parse_key(*args, is_field=True) + fields = self.ParseUtil.parse_key(*args, is_field=True) else: - fields = self.repository.config_obj.parse_key(*args) + fields = self.ParseUtil.parse_key(*args) # 解决as问题 if asses is not None: fs = fields.split(',') @@ -247,9 +241,9 @@ s """ if not len(sps) == 1: customize = True sym = sps[len(sps) - 1] - ParseUtil.fieldExist(self.repository.config_obj, 'adapter', raise_exception=True) + self.ParseUtil.fieldExist(self.ParseUtil, 'adapter', raise_exception=True) cp_key = cp_key[:cp_key.rfind('__' + sym)] - self.repository.config_obj.adapter.funcs[sym](self, cp_key, value) + self.ParseUtil.adapter.funcs[sym](self, cp_key, value) if not customize: self.args.append('`{}`{}%s'.format(cp_key, sym)) @@ -331,7 +325,7 @@ s """ 最终执行任务 """ sql = '' - conf = self.repository.config_obj.get_dict() + conf = self.ParseUtil.get_dict() print_sql = 'print_sql' in conf.keys() and conf['print_sql'] is True last_id = 'last_id' in conf.keys() and conf['last_id'] is True sql += ' '.join(self.args) @@ -344,7 +338,7 @@ s """ ) _result_objs = [] for i in _result: - _obj = ParseUtil.parse_obj( + _obj = self.ParseUtil.parse_obj( data=i, instance=self.repository.instance) _result_objs.append(_obj) _result = _result_objs diff --git a/CACodeFramework/MainWork/CACodeRepository.py b/CACodeFramework/MainWork/CACodeRepository.py index b70b269..a4829cd 100644 --- a/CACodeFramework/MainWork/CACodeRepository.py +++ b/CACodeFramework/MainWork/CACodeRepository.py @@ -13,9 +13,6 @@ from ..util import DbUtil import uuid -# from CACodeFramework.util.ParseUtil import ParseUtil - - class Repository: """ - POJO类 @@ -158,7 +155,7 @@ class Repository: Return: ORM转换之后的实体对象 """ - return CACodePureORM(repository=self, serializer=self.serializer, sqlFields=self.sqlFields) + return CACodePureORM(repository=self) def first(self): """ diff --git a/CACodeFramework/pojoManager/Manage.py b/CACodeFramework/pojoManager/Manage.py index 5f433ab..852faac 100644 --- a/CACodeFramework/pojoManager/Manage.py +++ b/CACodeFramework/pojoManager/Manage.py @@ -4,7 +4,6 @@ from CACodeFramework.pojoManager import tag from CACodeFramework.cacode.Serialize import JsonUtil from CACodeFramework.MainWork import CACodeRepository from CACodeFramework.util.Log import CACodeLog -from CACodeFramework.util.ParseUtil import ParseUtil class Pojo(CACodeRepository.Repository): @@ -116,7 +115,7 @@ class Pojo(CACodeRepository.Repository): """ 转ORM框架 """ - return CACodePureORM(repository=self, serializer=self.serializer, sqlFields=self.sqlFields) + return CACodePureORM(repository=self) def format(self, key, name): """ @@ -130,6 +129,7 @@ class Pojo(CACodeRepository.Repository): self.__fields__['ig'] = [] self.format(key, name) + @staticmethod def add_field(self, key, default_value=None): """ 添加一个不会被解析忽略的字段 diff --git a/test/modules/DatabaseConf.py b/test/modules/DatabaseConf.py index e13ae5b..036de55 100644 --- a/test/modules/DatabaseConf.py +++ b/test/modules/DatabaseConf.py @@ -2,7 +2,7 @@ import pymssql import pymysql from CACodeFramework.MainWork import CACodeConfig -from CACodeFramework.MainWork.CACodeCustomizeAdapter import LanguageAdapter +from CACodeFramework.MainWork.CACodeAdapter import LanguageAdapter class Adapter(LanguageAdapter): @@ -13,7 +13,7 @@ class Adapter(LanguageAdapter): super(Adapter, self).__init__() def __fuck(self, instance, key, value): - self.like(instance, key, value) + self._like_opera(instance, key, value) class MySqlConfig(CACodeConfig.Conf): diff --git a/test/testFunc.py b/test/testFunc.py index 69fd38e..e1a8cc8 100644 --- a/test/testFunc.py +++ b/test/testFunc.py @@ -23,7 +23,8 @@ def set_many(): a = [] for i in range(0, 1): a.append( - MyFactory.createInstance('MySqlTest.DemoTable', t_msg=f'测试msg{i}', t_name=f'测试name{i}', t_pwd=f'测试pwd{i}', + MyFactory.createInstance('SqlServerTest.DemoTable', t_msg=f'测试msg{i}', t_name=f'测试name{i}', + t_pwd=f'测试pwd{i}', abs=True)) return a @@ -31,14 +32,14 @@ def set_many(): def TestMySql(): demoTable = MyFactory.createInstance('MySqlTest.DemoTable') # result = demoTable.find_all() - test_data = set_many() + # test_data = set_many() t = time.time() - result = demoTable.create(pojo=test_data, many=True) + # result = demoTable.create(pojo=test_data, many=True) # result = demoTable.find_by_id(t_id=10) # page = result.page(7) - # r = page.to_dict() - # r = demoTable.orm.find().where(t_msg__fuck='1').end() - info(result) + # result = page.to_dict() + result = demoTable.orm.find().where(t_id__in=[1, 2, 3, 4, 5, 6, 7, 8, 9]).end() + info(result.to_json(True)) # info(f'count:{len(result)}') info(f'application run time:{time.time() - t}') # warn(result) @@ -54,6 +55,6 @@ if __name__ == '__main__': info = CACodeLog.log warn = CACodeLog.warning t1 = time.time() - # TestSqlServer() - TestMySql() + TestSqlServer() + # TestMySql() info(f'time:{time.time() - t1}') -- Gitee From f0a2f7a124270240034d48577830aec083df3226 Mon Sep 17 00:00:00 2001 From: CACode <54068986+cctvadmin@users.noreply.github.com> Date: Mon, 10 May 2021 12:41:09 +0800 Subject: [PATCH 08/26] 1 --- .gitignore | 1 - test/testFunc.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index fa85abc..9354750 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ __pycache__/ #delete.py #*.pyc #venv -setup.py .pypirc build CACodeFramework.egg-info diff --git a/test/testFunc.py b/test/testFunc.py index e1a8cc8..1ec8a7e 100644 --- a/test/testFunc.py +++ b/test/testFunc.py @@ -21,7 +21,7 @@ class MyFactory(Factory): def set_many(): a = [] - for i in range(0, 1): + for i in range(0, 100 * 10000): a.append( MyFactory.createInstance('SqlServerTest.DemoTable', t_msg=f'测试msg{i}', t_name=f'测试name{i}', t_pwd=f'测试pwd{i}', -- Gitee From 6407fb9aed24dafb84f887b1af7c18d698ff6287 Mon Sep 17 00:00:00 2001 From: CACode <54068986+cctvadmin@users.noreply.github.com> Date: Tue, 11 May 2021 18:06:31 +0800 Subject: [PATCH 09/26] On branch cacode --- setup.py | 2 +- test/README.md | 42 ++++++++++++++++++++++++++++ test/b.html | 27 ++++++++++++++++++ util/Generate POJOs.groovy | 56 -------------------------------------- util/__init__.py | 0 5 files changed, 70 insertions(+), 57 deletions(-) create mode 100644 test/README.md create mode 100644 test/b.html delete mode 100644 util/Generate POJOs.groovy delete mode 100644 util/__init__.py diff --git a/setup.py b/setup.py index 26c16b6..88d7fb5 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read() setuptools.setup( - name="CACodeFramework", + name="cacode_framework", version="1.3.1.2", author="CACode", author_email="cacode@163.com", diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000..3db0777 --- /dev/null +++ b/test/README.md @@ -0,0 +1,42 @@ + +# 快速开始 +``` +pip install cacode_framework +``` +## 版本要求 +``` +python>=3.6 +``` + +# 入门 +此框架适用于大部分数据库和web架构,入门门槛需要熟悉python语法即可 +## 定义一张表 + +创建一个名为`demo`数据库 +使用mysql命令行工具或者navicat执行以下sql语句,推荐使用navicat + +``` +CREATE DATABASE demo +``` + +然后创建一张名为`demo_table`的表 +``` +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; +DROP TABLE IF EXISTS `demo_table`; +CREATE TABLE `demo_table` ( + `t_id` int NOT NULL AUTO_INCREMENT, + `t_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, + `t_pwd` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, + `t_msg` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, + `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP, + `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`t_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1000000 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + +SET FOREIGN_KEY_CHECKS = 1; + +``` \ No newline at end of file diff --git a/test/b.html b/test/b.html new file mode 100644 index 0000000..ab68fa5 --- /dev/null +++ b/test/b.html @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + +
Please wait...
+ + + + + \ No newline at end of file diff --git a/util/Generate POJOs.groovy b/util/Generate POJOs.groovy deleted file mode 100644 index e13535a..0000000 --- a/util/Generate POJOs.groovy +++ /dev/null @@ -1,56 +0,0 @@ -import com.intellij.database.model.DasTable -import com.intellij.database.util.Case -import com.intellij.database.util.DasUtil - -/* - 你可以使用此脚本快捷生成POJO对象 - 最终效果为: - from CACodeFramework.MainWork.CACodePojo import POJO - - - class table(POJO): - def __init__(self): - self.shopId = None - self.title = None - self.icon = None - self.createTime = None - self.updateTime = None - - */ - -FILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { dir -> - SELECTION.filter { it instanceof DasTable }.each { generate(it, dir) } -} - -def generate(table, dir) { - def className = javaName(table.getName(), false) - def fields = calcFields(table) - new File(dir, className + ".py").withPrintWriter { out -> generate(out, className, fields) } -} - -def generate(out, className, fields) { - out.println "from CACodeFramework.MainWork.CACodePojo import POJO" - out.println "" - out.println "" - out.println "class table(POJO):" - out.println " def __init__(self):" - fields.each() { - out.println " self.${it.name} = None" - } -} - -def calcFields(table) { - DasUtil.getColumns(table).reduce([]) { fields, col -> - def spec = Case.LOWER.apply(col.getDataType().getSpecification()) - fields += [[ - name : javaName(col.getName(), false)]] - } -} - -def javaName(str, capitalize) { - def s = com.intellij.psi.codeStyle.NameUtil.splitNameIntoWords(str) - .collect { Case.LOWER.apply(it).capitalize() } - .join("") - .replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/, "_") - capitalize || s.length() == 1? s : Case.LOWER.apply(s[0]) + s[1..-1] -} diff --git a/util/__init__.py b/util/__init__.py deleted file mode 100644 index e69de29..0000000 -- Gitee From ae83f2e85cf9967777b72cf39c5c19055b0efd0f Mon Sep 17 00:00:00 2001 From: CACode Date: Sun, 16 May 2021 22:33:37 +0800 Subject: [PATCH 10/26] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BB=86=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- README.md | 7 +--- .../MainWork/CACodeAdapter.py | 10 ++++- .../MainWork/CACodeAopContainer.py | 0 .../MainWork/CACodeConfig.py | 3 ++ .../MainWork/CACodePureORM.py | 34 +++++++++++++-- .../MainWork/CACodeRepository.py | 4 +- .../MainWork/__init__.py | 0 .../__init__.py | 0 .../anno/__init__.py | 0 .../anno/annos.py | 4 +- .../cacode/Factory.py | 18 ++++---- .../cacode/Modes.py | 2 +- .../cacode/ReviewJson/JSON.py | 0 .../cacode/ReviewJson/__init__.py | 0 .../cacode/ReviewJson/_speedups.c | 0 .../cacode/ReviewJson/compat.py | 0 .../cacode/ReviewJson/decoder.py | 0 .../cacode/ReviewJson/encoder.py | 0 .../cacode/ReviewJson/errors.py | 0 .../cacode/ReviewJson/ordered_dict.py | 0 .../cacode/ReviewJson/raw_json.py | 0 .../cacode/ReviewJson/scanner.py | 0 .../cacode/ReviewJson/tool.py | 0 .../cacode/Serialize.py | 13 ++++-- .../cacode/__init__.py | 0 .../exception/__init__.py | 0 .../exception/e_fields.py | 0 .../field/FManage.py | 0 .../field/MySqlDefault.py | 7 ++++ .../field/__init__.py | 0 .../opera/CompulsoryRun.py | 4 +- .../opera/__init__.py | 0 .../opera/op_db.py | 18 ++++---- .../pojoManager/Manage.py | 42 ++++++------------- .../pojoManager/__init__.py | 0 .../pojoManager/tag.py | 6 ++- .../util/DBPool/__init__.py | 0 .../util/DBPool/persistent_db.py | 0 .../util/DBPool/persistent_pg.py | 0 .../util/DBPool/pooled_db.py | 0 .../util/DBPool/pooled_pg.py | 0 .../util/DBPool/simple_pooled_db.py | 0 .../util/DBPool/simple_pooled_pg.py | 0 .../util/DBPool/steady_db.py | 0 .../util/DBPool/steady_pg.py | 0 .../util/DbUtil.py | 13 ++++-- .../util/Log.py | 4 +- .../util/ParseUtil.py | 5 ++- .../util/__init__.py | 0 setup.py | 2 +- test/README.md | 42 ------------------- test/b.html | 27 ------------ test/modules/DatabaseConf.py | 4 +- test/modules/MySqlTest.py | 6 +-- test/modules/SqlServerTest.py | 6 +-- test/testFunc.py | 30 +++++++------ 57 files changed, 142 insertions(+), 171 deletions(-) rename {CACodeFramework => cacode_framework}/MainWork/CACodeAdapter.py (79%) rename {CACodeFramework => cacode_framework}/MainWork/CACodeAopContainer.py (100%) rename {CACodeFramework => cacode_framework}/MainWork/CACodeConfig.py (94%) rename {CACodeFramework => cacode_framework}/MainWork/CACodePureORM.py (93%) rename {CACodeFramework => cacode_framework}/MainWork/CACodeRepository.py (99%) rename {CACodeFramework => cacode_framework}/MainWork/__init__.py (100%) rename {CACodeFramework => cacode_framework}/__init__.py (100%) rename {CACodeFramework => cacode_framework}/anno/__init__.py (100%) rename {CACodeFramework => cacode_framework}/anno/annos.py (97%) rename {CACodeFramework => cacode_framework}/cacode/Factory.py (86%) rename {CACodeFramework => cacode_framework}/cacode/Modes.py (99%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/JSON.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/__init__.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/_speedups.c (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/compat.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/decoder.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/encoder.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/errors.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/ordered_dict.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/raw_json.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/scanner.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/tool.py (100%) rename {CACodeFramework => cacode_framework}/cacode/Serialize.py (98%) rename {CACodeFramework => cacode_framework}/cacode/__init__.py (100%) rename {CACodeFramework => cacode_framework}/exception/__init__.py (100%) rename {CACodeFramework => cacode_framework}/exception/e_fields.py (100%) rename {CACodeFramework => cacode_framework}/field/FManage.py (100%) rename {CACodeFramework => cacode_framework}/field/MySqlDefault.py (96%) rename {CACodeFramework => cacode_framework}/field/__init__.py (100%) rename {CACodeFramework => cacode_framework}/opera/CompulsoryRun.py (91%) rename {CACodeFramework => cacode_framework}/opera/__init__.py (100%) rename {CACodeFramework => cacode_framework}/opera/op_db.py (89%) rename {CACodeFramework => cacode_framework}/pojoManager/Manage.py (80%) rename {CACodeFramework => cacode_framework}/pojoManager/__init__.py (100%) rename {CACodeFramework => cacode_framework}/pojoManager/tag.py (95%) rename {CACodeFramework => cacode_framework}/util/DBPool/__init__.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/persistent_db.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/persistent_pg.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/pooled_db.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/pooled_pg.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/simple_pooled_db.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/simple_pooled_pg.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/steady_db.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/steady_pg.py (100%) rename {CACodeFramework => cacode_framework}/util/DbUtil.py (93%) rename {CACodeFramework => cacode_framework}/util/Log.py (98%) rename {CACodeFramework => cacode_framework}/util/ParseUtil.py (98%) rename {CACodeFramework => cacode_framework}/util/__init__.py (100%) delete mode 100644 test/README.md delete mode 100644 test/b.html diff --git a/.gitignore b/.gitignore index 9354750..a57e2e7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ __pycache__/ #venv .pypirc build -CACodeFramework.egg-info +cacode_framework.egg-info dist upload.bat pyproject.toml diff --git a/README.md b/README.md index d1f8c53..ec3f93d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@

Version - Documentation @@ -27,7 +26,7 @@ - python >=3.6 项目地址: https://gitee.com/cacode_cctvadmin/CACodeFramework-python-ORM -项目文档:https://frame.cacode.ren +项目文档:http://doc.cacode.ren > 统一市面上所有的数据库创建者,并分配连接池和缓存 @@ -35,8 +34,6 @@ 如果这个框架对你有帮助的话,请给个星点个star -# CACode开发团队 +# CACode !['CACode Development Team'](./imgs/icon_dev.png) -文档编辑于:2021/03/17 07:41 -作者:CACode diff --git a/CACodeFramework/MainWork/CACodeAdapter.py b/cacode_framework/MainWork/CACodeAdapter.py similarity index 79% rename from CACodeFramework/MainWork/CACodeAdapter.py rename to cacode_framework/MainWork/CACodeAdapter.py index 0474b35..46b7cd4 100644 --- a/CACodeFramework/MainWork/CACodeAdapter.py +++ b/cacode_framework/MainWork/CACodeAdapter.py @@ -9,8 +9,10 @@ class LanguageAdapter: funcs = {} def __init__(self): - self.funcs['like'] = self._like_opera - self.funcs['in'] = self._in_opera + if not hasattr(self, 'funcs'): + self.funcs = {} + self.sp('like', self._like_opera) + self.sp('in', self._in_opera) def _like_opera(self, instance, key, value): instance.args.append('`' + key + '`') @@ -27,3 +29,7 @@ class LanguageAdapter: instance.args.append(f'( {vals} )') else: raise AttributeError('value type is not list or QuerySet object') + + def sp(self, key, val): + if key not in self.funcs.keys(): + self.funcs[key] = val diff --git a/CACodeFramework/MainWork/CACodeAopContainer.py b/cacode_framework/MainWork/CACodeAopContainer.py similarity index 100% rename from CACodeFramework/MainWork/CACodeAopContainer.py rename to cacode_framework/MainWork/CACodeAopContainer.py diff --git a/CACodeFramework/MainWork/CACodeConfig.py b/cacode_framework/MainWork/CACodeConfig.py similarity index 94% rename from CACodeFramework/MainWork/CACodeConfig.py rename to cacode_framework/MainWork/CACodeConfig.py index 039a2d7..aeec07f 100644 --- a/CACodeFramework/MainWork/CACodeConfig.py +++ b/cacode_framework/MainWork/CACodeConfig.py @@ -1,3 +1,4 @@ +from .CACodeAdapter import LanguageAdapter from ..cacode.Serialize import JsonUtil from ..exception.e_fields import FieldNotExist from ..util.Log import CACodeLog @@ -40,6 +41,8 @@ class Conf(ParseUtil): self.password = password self.charset = charset ParseUtil.insert_to_obj(self, kwargs) + if 'adapter' not in kwargs.keys(): + self.adapter = LanguageAdapter() super(Conf, self).__init__() def get(self): diff --git a/CACodeFramework/MainWork/CACodePureORM.py b/cacode_framework/MainWork/CACodePureORM.py similarity index 93% rename from CACodeFramework/MainWork/CACodePureORM.py rename to cacode_framework/MainWork/CACodePureORM.py index 12d9b83..8b8daf4 100644 --- a/CACodeFramework/MainWork/CACodePureORM.py +++ b/cacode_framework/MainWork/CACodePureORM.py @@ -63,7 +63,8 @@ s """ # self.args.append(insert_str) # self.args.append('{}{}'.format(self.__table_name__, left_par)) sql = self.ParseUtil.parse_insert_pojo( - pojo, self.__table_name__.replace('`', '')) + pojo, self.__table_name__.replace('`', ''), insert_str=self.sqlFields.insert_str, + values_str=self.sqlFields.values_str) self.args.append(sql['sql']) self.params = sql['params'] @@ -169,7 +170,10 @@ s """ # 去掉末尾的逗号 self.rep_sym() # 加上from关键字 - self.con_from() + if 'poly' not in kwargs.keys(): + self.con_from() + else: + self.args += kwargs['poly'] return self def order_by(self, *args): @@ -320,7 +324,7 @@ s """ self.args.append(self.sqlFields.ander_str) return self - def run(self): + def run(self, need_sql=False): """ 最终执行任务 """ @@ -328,7 +332,9 @@ s """ conf = self.ParseUtil.get_dict() print_sql = 'print_sql' in conf.keys() and conf['print_sql'] is True last_id = 'last_id' in conf.keys() and conf['last_id'] is True - sql += ' '.join(self.args) + sql += ''.join(self.args) + if need_sql: + return sql if self.sqlFields.find_str in sql: _result = self.repository.db_util.select( sql=sql, @@ -386,3 +392,23 @@ s """ def end(self): return self.run() + + def __rshift__(self, other): + """ + 将左边orm迁移至右边 + """ + new_args = self.args.copy() + new_args.append(' ) ') + other.args.append(' ( ') + other.args += new_args + return other + + def __lshift__(self, other): + """ + 将右边迁移至左边 + """ + new_args = other.args.copy() + new_args.append(' ) ') + self.args.append(' ( ') + self.args = self.args + new_args + return self diff --git a/CACodeFramework/MainWork/CACodeRepository.py b/cacode_framework/MainWork/CACodeRepository.py similarity index 99% rename from CACodeFramework/MainWork/CACodeRepository.py rename to cacode_framework/MainWork/CACodeRepository.py index a4829cd..33628cc 100644 --- a/CACodeFramework/MainWork/CACodeRepository.py +++ b/cacode_framework/MainWork/CACodeRepository.py @@ -319,7 +319,7 @@ class Repository: :return: """ kwargs['config_obj'] = self.config_obj - kwargs = self.ParseUtil.print_sql(**kwargs) + kwargs = self.ParseUtil.find_print_sql(**kwargs) kwargs = self.ParseUtil.last_id(**kwargs) return self.db_util.update(**kwargs) @@ -333,7 +333,7 @@ class Repository: params:需要填充的字段 :return rowcount,last_id if last_id=True """ - kwargs = self.ParseUtil.print_sql(**kwargs) + kwargs = self.ParseUtil.find_print_sql(**kwargs) kwargs = self.ParseUtil.last_id(**kwargs) return self.db_util.insert(**kwargs) diff --git a/CACodeFramework/MainWork/__init__.py b/cacode_framework/MainWork/__init__.py similarity index 100% rename from CACodeFramework/MainWork/__init__.py rename to cacode_framework/MainWork/__init__.py diff --git a/CACodeFramework/__init__.py b/cacode_framework/__init__.py similarity index 100% rename from CACodeFramework/__init__.py rename to cacode_framework/__init__.py diff --git a/CACodeFramework/anno/__init__.py b/cacode_framework/anno/__init__.py similarity index 100% rename from CACodeFramework/anno/__init__.py rename to cacode_framework/anno/__init__.py diff --git a/CACodeFramework/anno/annos.py b/cacode_framework/anno/annos.py similarity index 97% rename from CACodeFramework/anno/annos.py rename to cacode_framework/anno/annos.py index 2107742..cf547dc 100644 --- a/CACodeFramework/anno/annos.py +++ b/cacode_framework/anno/annos.py @@ -67,7 +67,7 @@ def Select(sql, params=None): new_args = parse_kwargs(params, kwargs) result = obj.find_sql(sql=sql, params=new_args) - from CACodeFramework.cacode.Serialize import QuerySet + from cacode_framework.cacode.Serialize import QuerySet return QuerySet(obj, result) return _wrapper_ @@ -170,7 +170,7 @@ def AopModel(before=None, after=None, """ # 得到对象组 - from CACodeFramework.MainWork.CACodeAopContainer import AopModelObject + from cacode_framework.MainWork.CACodeAopContainer import AopModelObject aop_obj = AopModelObject(before, after, before_args, before_kwargs, after_args, after_kwargs) diff --git a/CACodeFramework/cacode/Factory.py b/cacode_framework/cacode/Factory.py similarity index 86% rename from CACodeFramework/cacode/Factory.py rename to cacode_framework/cacode/Factory.py index 58a1515..31c3b5e 100644 --- a/CACodeFramework/cacode/Factory.py +++ b/cacode_framework/cacode/Factory.py @@ -1,10 +1,10 @@ import threading -from CACodeFramework.cacode import Modes -from CACodeFramework.exception import e_fields -from CACodeFramework.exception.e_fields import ModuleCreateError -from CACodeFramework.opera.CompulsoryRun import Compulsory -from CACodeFramework.util.Log import CACodeLog +from cacode_framework.cacode import Modes +from cacode_framework.exception import e_fields +from cacode_framework.exception.e_fields import ModuleCreateError +from cacode_framework.opera.CompulsoryRun import Compulsory +from cacode_framework.util.Log import CACodeLog import importlib @@ -36,8 +36,8 @@ class Factory(object): CACodeLog.err(SyntaxError, e_fields.CACode_Factory_Error( 'Please import the Pojo module first,请先设置导入modules模块')) - self.module_names = {} - self.__base_init__() + self.module_names = self.modules + # self.__base_init__() def __base_init__(self): for package_name in self.modules: @@ -61,9 +61,7 @@ class Factory(object): 创建一个实例对象,并提供ORM操作 - name使用包名最后一位置作为起始值,如: - - Test.models.Demo + name 使用自定义的键 那么,当你调用Demo下的model时,你必须使用`Demo.DemoTable`这种 diff --git a/CACodeFramework/cacode/Modes.py b/cacode_framework/cacode/Modes.py similarity index 99% rename from CACodeFramework/cacode/Modes.py rename to cacode_framework/cacode/Modes.py index ce07bb8..699e2d9 100644 --- a/CACodeFramework/cacode/Modes.py +++ b/cacode_framework/cacode/Modes.py @@ -295,7 +295,7 @@ if __name__ == '__main__': "e": rep } result = Recursion.find_key_for_dict(data, "a") - from CACodeFramework.cacode.Serialize import JsonUtil + from cacode_framework.cacode.Serialize import JsonUtil print(JsonUtil.parse(result)) diff --git a/CACodeFramework/cacode/ReviewJson/JSON.py b/cacode_framework/cacode/ReviewJson/JSON.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/JSON.py rename to cacode_framework/cacode/ReviewJson/JSON.py diff --git a/CACodeFramework/cacode/ReviewJson/__init__.py b/cacode_framework/cacode/ReviewJson/__init__.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/__init__.py rename to cacode_framework/cacode/ReviewJson/__init__.py diff --git a/CACodeFramework/cacode/ReviewJson/_speedups.c b/cacode_framework/cacode/ReviewJson/_speedups.c similarity index 100% rename from CACodeFramework/cacode/ReviewJson/_speedups.c rename to cacode_framework/cacode/ReviewJson/_speedups.c diff --git a/CACodeFramework/cacode/ReviewJson/compat.py b/cacode_framework/cacode/ReviewJson/compat.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/compat.py rename to cacode_framework/cacode/ReviewJson/compat.py diff --git a/CACodeFramework/cacode/ReviewJson/decoder.py b/cacode_framework/cacode/ReviewJson/decoder.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/decoder.py rename to cacode_framework/cacode/ReviewJson/decoder.py diff --git a/CACodeFramework/cacode/ReviewJson/encoder.py b/cacode_framework/cacode/ReviewJson/encoder.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/encoder.py rename to cacode_framework/cacode/ReviewJson/encoder.py diff --git a/CACodeFramework/cacode/ReviewJson/errors.py b/cacode_framework/cacode/ReviewJson/errors.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/errors.py rename to cacode_framework/cacode/ReviewJson/errors.py diff --git a/CACodeFramework/cacode/ReviewJson/ordered_dict.py b/cacode_framework/cacode/ReviewJson/ordered_dict.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/ordered_dict.py rename to cacode_framework/cacode/ReviewJson/ordered_dict.py diff --git a/CACodeFramework/cacode/ReviewJson/raw_json.py b/cacode_framework/cacode/ReviewJson/raw_json.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/raw_json.py rename to cacode_framework/cacode/ReviewJson/raw_json.py diff --git a/CACodeFramework/cacode/ReviewJson/scanner.py b/cacode_framework/cacode/ReviewJson/scanner.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/scanner.py rename to cacode_framework/cacode/ReviewJson/scanner.py diff --git a/CACodeFramework/cacode/ReviewJson/tool.py b/cacode_framework/cacode/ReviewJson/tool.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/tool.py rename to cacode_framework/cacode/ReviewJson/tool.py diff --git a/CACodeFramework/cacode/Serialize.py b/cacode_framework/cacode/Serialize.py similarity index 98% rename from CACodeFramework/cacode/Serialize.py rename to cacode_framework/cacode/Serialize.py index f676361..cb2ee3e 100644 --- a/CACodeFramework/cacode/Serialize.py +++ b/cacode_framework/cacode/Serialize.py @@ -15,9 +15,9 @@ # CACode 1.2 2021/4/27 统一序列化器位置 # ------------------------------------------------------------------ -from CACodeFramework.cacode.ReviewJson.JSON import Json -from CACodeFramework.util.Log import CACodeLog -from CACodeFramework.cacode import ReviewJson +from cacode_framework.cacode.ReviewJson.JSON import Json +from cacode_framework.util.Log import CACodeLog +from cacode_framework.cacode import ReviewJson from datetime import date, datetime import functools @@ -265,7 +265,7 @@ class QuerySet(list): 初始化数据源 """ list.__init__([]) - if not query_items: + if query_items is None: self.__instance__ = instance self.__using_fields__ = self.__instance__.getFields() @@ -342,6 +342,11 @@ class QuerySet(list): """ return self[index] + def __str__(self): + return str(self.to_dict()) + + __repr__ = __str__ + # # class QueryItem(JsonUtil): diff --git a/CACodeFramework/cacode/__init__.py b/cacode_framework/cacode/__init__.py similarity index 100% rename from CACodeFramework/cacode/__init__.py rename to cacode_framework/cacode/__init__.py diff --git a/CACodeFramework/exception/__init__.py b/cacode_framework/exception/__init__.py similarity index 100% rename from CACodeFramework/exception/__init__.py rename to cacode_framework/exception/__init__.py diff --git a/CACodeFramework/exception/e_fields.py b/cacode_framework/exception/e_fields.py similarity index 100% rename from CACodeFramework/exception/e_fields.py rename to cacode_framework/exception/e_fields.py diff --git a/CACodeFramework/field/FManage.py b/cacode_framework/field/FManage.py similarity index 100% rename from CACodeFramework/field/FManage.py rename to cacode_framework/field/FManage.py diff --git a/CACodeFramework/field/MySqlDefault.py b/cacode_framework/field/MySqlDefault.py similarity index 96% rename from CACodeFramework/field/MySqlDefault.py rename to cacode_framework/field/MySqlDefault.py index 79b0674..e1b8a1b 100644 --- a/CACodeFramework/field/MySqlDefault.py +++ b/cacode_framework/field/MySqlDefault.py @@ -23,6 +23,13 @@ class MySqlFields_Default: """ return '`' + @property + def space(self): + """ + 空格 + """ + return ' ' + @property def right_subscript(self): """ diff --git a/CACodeFramework/field/__init__.py b/cacode_framework/field/__init__.py similarity index 100% rename from CACodeFramework/field/__init__.py rename to cacode_framework/field/__init__.py diff --git a/CACodeFramework/opera/CompulsoryRun.py b/cacode_framework/opera/CompulsoryRun.py similarity index 91% rename from CACodeFramework/opera/CompulsoryRun.py rename to cacode_framework/opera/CompulsoryRun.py index 5e34abd..49c4317 100644 --- a/CACodeFramework/opera/CompulsoryRun.py +++ b/cacode_framework/opera/CompulsoryRun.py @@ -33,8 +33,8 @@ class Compulsory(object): 深度搜素树 """ - from CACodeFramework.exception import e_fields - from CACodeFramework.util.Log import CACodeLog + from cacode_framework.exception import e_fields + from cacode_framework.util.Log import CACodeLog if len(target_names) == 0: return module diff --git a/CACodeFramework/opera/__init__.py b/cacode_framework/opera/__init__.py similarity index 100% rename from CACodeFramework/opera/__init__.py rename to cacode_framework/opera/__init__.py diff --git a/CACodeFramework/opera/op_db.py b/cacode_framework/opera/op_db.py similarity index 89% rename from CACodeFramework/opera/op_db.py rename to cacode_framework/opera/op_db.py index cb4e419..71602d7 100644 --- a/CACodeFramework/opera/op_db.py +++ b/cacode_framework/opera/op_db.py @@ -1,11 +1,11 @@ import threading -from CACodeFramework.cacode.Modes import Recursion -from CACodeFramework.cacode.Serialize import JsonUtil -from CACodeFramework.util.Log import CACodeLog +from cacode_framework.cacode.Modes import Recursion +from cacode_framework.cacode.Serialize import JsonUtil +from cacode_framework.util.Log import CACodeLog -from CACodeFramework.field.MySqlDefault import * -from CACodeFramework.util.ParseUtil import ParseUtil +from cacode_framework.field.MySqlDefault import * +from cacode_framework.util.ParseUtil import ParseUtil class DbOperation(object): @@ -57,7 +57,7 @@ class DbOperation(object): 任务方法 """ - fields = ParseUtil(*args, is_field=True).parse_key() + fields = ParseUtil().parse_key(*args, is_field=True) sql_str = kwargs['sqlFields'].find_str + fields + kwargs['sqlFields'].from_str + kwargs['__table_name__'] kwargs['sql'] = sql_str self.result = self.__find_many__(**kwargs) @@ -69,7 +69,7 @@ class DbOperation(object): 任务方法 """ # kwargs['conf_obj'] = config_obj - kwargs = ParseUtil.print_sql(**kwargs) + kwargs = ParseUtil.find_print_sql(**kwargs) self.result = self.__find_sql__(**kwargs) return self.result @@ -78,7 +78,7 @@ class DbOperation(object): 任务方法 """ - kwargs = ParseUtil.print_sql(**kwargs) + kwargs = ParseUtil.find_print_sql(**kwargs) _rs = kwargs['db_util'].select(**kwargs) self.result = [] @@ -93,7 +93,7 @@ class DbOperation(object): :param pojo: pojo对象 任务方法 """ - kwargs = ParseUtil.print_sql(**kwargs) + kwargs = ParseUtil.find_print_sql(**kwargs) kwargs = ParseUtil.last_id(**kwargs) ParseUtil.fieldExist(kwargs, 'pojo', raise_exception=True) diff --git a/CACodeFramework/pojoManager/Manage.py b/cacode_framework/pojoManager/Manage.py similarity index 80% rename from CACodeFramework/pojoManager/Manage.py rename to cacode_framework/pojoManager/Manage.py index 852faac..37e1b2a 100644 --- a/CACodeFramework/pojoManager/Manage.py +++ b/cacode_framework/pojoManager/Manage.py @@ -1,9 +1,9 @@ -from CACodeFramework.MainWork.CACodePureORM import CACodePureORM -from CACodeFramework.cacode.Serialize import QuerySet -from CACodeFramework.pojoManager import tag -from CACodeFramework.cacode.Serialize import JsonUtil -from CACodeFramework.MainWork import CACodeRepository -from CACodeFramework.util.Log import CACodeLog +from cacode_framework.MainWork.CACodePureORM import CACodePureORM +from cacode_framework.cacode.Serialize import QuerySet +from cacode_framework.pojoManager import tag +from cacode_framework.cacode.Serialize import JsonUtil +from cacode_framework.MainWork import CACodeRepository +from cacode_framework.util.Log import CACodeLog class Pojo(CACodeRepository.Repository): @@ -25,15 +25,15 @@ class Pojo(CACodeRepository.Repository): self.__table_name__ = self.__table_name__ self.__table_msg__ = self.__table_msg__ self.__fields__ = {} - self.init_fields() - for key, value in kwargs.items(): - self.__setattr__(key, value) # 在这里将config_obj实例化 self.serializer = serializer # 忽略的字段 self.__ignore_field__ = {} # 添加的字段 self.__append_field__ = {} + self.init_fields() + for key, value in kwargs.items(): + self.__setattr__(key, value) super(Pojo, self).__init__(config_obj=config_obj, instance=self, log_conf=log_conf, @@ -51,8 +51,10 @@ class Pojo(CACodeRepository.Repository): # 取出这个值引用对象的父类 try: t_v = value.__class__.__base__ - if t_v == tag.Template or t_v == tag.baseTag: - fds[key] = value + if t_v in [tag.Template, tag.baseTag]: + if not hasattr(self, key) or getattr(self, key) is None or t_v in [tag.Template, tag.baseTag]: + setattr(self, key, value.default) + fds[key] = value if value.default is None else value.default except SyntaxError as a: continue @@ -129,24 +131,6 @@ class Pojo(CACodeRepository.Repository): self.__fields__['ig'] = [] self.format(key, name) - @staticmethod - def add_field(self, key, default_value=None): - """ - 添加一个不会被解析忽略的字段 - """ - if key not in self.append_field.keys() and \ - key not in self.using_fields.keys(): - - self.append_field[key] = default_value - else: - CACodeLog.log(obj=self, msg='`{}` already exists'.format(key)) - - def remove_field(self, key): - """ - 添加一个会被解析忽略的字段 - """ - self.ignore_field[key] = None - def __str__(self): """ 默认显示表名称 diff --git a/CACodeFramework/pojoManager/__init__.py b/cacode_framework/pojoManager/__init__.py similarity index 100% rename from CACodeFramework/pojoManager/__init__.py rename to cacode_framework/pojoManager/__init__.py diff --git a/CACodeFramework/pojoManager/tag.py b/cacode_framework/pojoManager/tag.py similarity index 95% rename from CACodeFramework/pojoManager/tag.py rename to cacode_framework/pojoManager/tag.py index 34dfcc1..2daca82 100644 --- a/CACodeFramework/pojoManager/tag.py +++ b/cacode_framework/pojoManager/tag.py @@ -1,6 +1,6 @@ import datetime -from CACodeFramework.cacode.Serialize import JsonUtil +from cacode_framework.cacode.Serialize import JsonUtil """ 这个文件用来为pojo对象做标记,当对象为空或为以下任意类型时 @@ -36,8 +36,12 @@ class baseTag(object): """ # 是否为随着时间而更新 self.update_auto_time = update_auto_time + if update_auto_time: + self.default = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') # 是否自动设置为当前时间 self.auto_time = auto_time + if auto_time: + self.default = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') # 是否为自增 self.autoField = auto_field # 注释 diff --git a/CACodeFramework/util/DBPool/__init__.py b/cacode_framework/util/DBPool/__init__.py similarity index 100% rename from CACodeFramework/util/DBPool/__init__.py rename to cacode_framework/util/DBPool/__init__.py diff --git a/CACodeFramework/util/DBPool/persistent_db.py b/cacode_framework/util/DBPool/persistent_db.py similarity index 100% rename from CACodeFramework/util/DBPool/persistent_db.py rename to cacode_framework/util/DBPool/persistent_db.py diff --git a/CACodeFramework/util/DBPool/persistent_pg.py b/cacode_framework/util/DBPool/persistent_pg.py similarity index 100% rename from CACodeFramework/util/DBPool/persistent_pg.py rename to cacode_framework/util/DBPool/persistent_pg.py diff --git a/CACodeFramework/util/DBPool/pooled_db.py b/cacode_framework/util/DBPool/pooled_db.py similarity index 100% rename from CACodeFramework/util/DBPool/pooled_db.py rename to cacode_framework/util/DBPool/pooled_db.py diff --git a/CACodeFramework/util/DBPool/pooled_pg.py b/cacode_framework/util/DBPool/pooled_pg.py similarity index 100% rename from CACodeFramework/util/DBPool/pooled_pg.py rename to cacode_framework/util/DBPool/pooled_pg.py diff --git a/CACodeFramework/util/DBPool/simple_pooled_db.py b/cacode_framework/util/DBPool/simple_pooled_db.py similarity index 100% rename from CACodeFramework/util/DBPool/simple_pooled_db.py rename to cacode_framework/util/DBPool/simple_pooled_db.py diff --git a/CACodeFramework/util/DBPool/simple_pooled_pg.py b/cacode_framework/util/DBPool/simple_pooled_pg.py similarity index 100% rename from CACodeFramework/util/DBPool/simple_pooled_pg.py rename to cacode_framework/util/DBPool/simple_pooled_pg.py diff --git a/CACodeFramework/util/DBPool/steady_db.py b/cacode_framework/util/DBPool/steady_db.py similarity index 100% rename from CACodeFramework/util/DBPool/steady_db.py rename to cacode_framework/util/DBPool/steady_db.py diff --git a/CACodeFramework/util/DBPool/steady_pg.py b/cacode_framework/util/DBPool/steady_pg.py similarity index 100% rename from CACodeFramework/util/DBPool/steady_pg.py rename to cacode_framework/util/DBPool/steady_pg.py diff --git a/CACodeFramework/util/DbUtil.py b/cacode_framework/util/DbUtil.py similarity index 93% rename from CACodeFramework/util/DbUtil.py rename to cacode_framework/util/DbUtil.py index 5d2481f..ac12ecf 100644 --- a/CACodeFramework/util/DbUtil.py +++ b/cacode_framework/util/DbUtil.py @@ -1,9 +1,9 @@ import sys import threading -from CACodeFramework.cacode.Modes import Singleton -from CACodeFramework.util.DBPool.pooled_db import PooledDB -from CACodeFramework.util.Log import CACodeLog +from cacode_framework.cacode.Modes import Singleton +from cacode_framework.util.DBPool.pooled_db import PooledDB +from cacode_framework.util.Log import CACodeLog def parse_kwa(db, **kwargs): @@ -183,6 +183,9 @@ class Db_opera(object): return _result except Exception as e: db.rollback() + CACodeLog.log_error(obj=e.__class__, msg=e.__str__(), + LogObject=kwargs['logObject'] if 'logObject' in kwargs.keys() else None, + raise_exception=True) raise e finally: db.close() @@ -212,7 +215,9 @@ class Db_opera(object): return rowcount except Exception as e: db.rollback() - raise e + CACodeLog.log_error(obj=e.__class__, msg=e.__str__(), + LogObject=kwargs['logObject'] if 'logObject' in kwargs.keys() else None, + raise_exception=True) finally: db.close() diff --git a/CACodeFramework/util/Log.py b/cacode_framework/util/Log.py similarity index 98% rename from CACodeFramework/util/Log.py rename to cacode_framework/util/Log.py index 000a68e..eaa748c 100644 --- a/CACodeFramework/util/Log.py +++ b/cacode_framework/util/Log.py @@ -4,8 +4,8 @@ import re import sys import time import threading -from CACodeFramework.cacode.Modes import Singleton -from CACodeFramework.exception import e_fields +from cacode_framework.cacode.Modes import Singleton +from cacode_framework.exception import e_fields class FieldsLength: diff --git a/CACodeFramework/util/ParseUtil.py b/cacode_framework/util/ParseUtil.py similarity index 98% rename from CACodeFramework/util/ParseUtil.py rename to cacode_framework/util/ParseUtil.py index 0b7248e..169f8db 100644 --- a/CACodeFramework/util/ParseUtil.py +++ b/cacode_framework/util/ParseUtil.py @@ -181,7 +181,7 @@ class ParseUtil(object): return kwargs @staticmethod - def print_sql(**kwargs): + def find_print_sql(**kwargs): """ 遵循规则: 内部>配置文件 @@ -231,7 +231,8 @@ class ParseUtil(object): """ try: t_v = __val.__class__.__base__ - return t_v == tag.Template or t_v == tag.baseTag + if t_v in [tag.Template, tag.baseTag]: + return __val.default is None except SyntaxError: return False diff --git a/CACodeFramework/util/__init__.py b/cacode_framework/util/__init__.py similarity index 100% rename from CACodeFramework/util/__init__.py rename to cacode_framework/util/__init__.py diff --git a/setup.py b/setup.py index 88d7fb5..1361e63 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh: setuptools.setup( name="cacode_framework", - version="1.3.1.2", + version="1.0.0", author="CACode", author_email="cacode@163.com", description="CACode Framework For Python Flask,This framework corresponds to the ORM problem,You can see:https://gitee.com/cacode_cctvadmin/CACodeFramework-python-ORM", diff --git a/test/README.md b/test/README.md deleted file mode 100644 index 3db0777..0000000 --- a/test/README.md +++ /dev/null @@ -1,42 +0,0 @@ - -# 快速开始 -``` -pip install cacode_framework -``` -## 版本要求 -``` -python>=3.6 -``` - -# 入门 -此框架适用于大部分数据库和web架构,入门门槛需要熟悉python语法即可 -## 定义一张表 - -创建一个名为`demo`数据库 -使用mysql命令行工具或者navicat执行以下sql语句,推荐使用navicat - -``` -CREATE DATABASE demo -``` - -然后创建一张名为`demo_table`的表 -``` -SET NAMES utf8mb4; -SET FOREIGN_KEY_CHECKS = 0; -DROP TABLE IF EXISTS `demo_table`; -CREATE TABLE `demo_table` ( - `t_id` int NOT NULL AUTO_INCREMENT, - `t_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, - `t_pwd` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, - `t_msg` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, - `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP, - `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`t_id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1000000 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; - -SET FOREIGN_KEY_CHECKS = 1; - -``` \ No newline at end of file diff --git a/test/b.html b/test/b.html deleted file mode 100644 index ab68fa5..0000000 --- a/test/b.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - -

Please wait...
- - - - - \ No newline at end of file diff --git a/test/modules/DatabaseConf.py b/test/modules/DatabaseConf.py index 036de55..d437864 100644 --- a/test/modules/DatabaseConf.py +++ b/test/modules/DatabaseConf.py @@ -1,8 +1,8 @@ import pymssql import pymysql -from CACodeFramework.MainWork import CACodeConfig -from CACodeFramework.MainWork.CACodeAdapter import LanguageAdapter +from cacode_framework.MainWork import CACodeConfig +from cacode_framework.MainWork.CACodeAdapter import LanguageAdapter class Adapter(LanguageAdapter): diff --git a/test/modules/MySqlTest.py b/test/modules/MySqlTest.py index 5f281e3..a511ca7 100644 --- a/test/modules/MySqlTest.py +++ b/test/modules/MySqlTest.py @@ -1,8 +1,8 @@ import datetime -from CACodeFramework.anno.annos import Table, Select -from CACodeFramework.pojoManager import Manage -from CACodeFramework.pojoManager.Manage import Pojo +from cacode_framework.anno.annos import Table, Select +from cacode_framework.pojoManager import Manage +from cacode_framework.pojoManager.Manage import Pojo from test.modules.DatabaseConf import MySqlConfig diff --git a/test/modules/SqlServerTest.py b/test/modules/SqlServerTest.py index 3e0542c..d66ef14 100644 --- a/test/modules/SqlServerTest.py +++ b/test/modules/SqlServerTest.py @@ -3,9 +3,9 @@ # @Author: CACode # @File: SqlServerTest.py # @Software: PyCharm -from CACodeFramework.anno.annos import Table -from CACodeFramework.pojoManager import Manage -from CACodeFramework.pojoManager.Manage import Pojo +from cacode_framework.anno.annos import Table +from cacode_framework.pojoManager import Manage +from cacode_framework.pojoManager.Manage import Pojo from test.modules.DatabaseConf import SqlServerConfig diff --git a/test/testFunc.py b/test/testFunc.py index 1ec8a7e..259b4f3 100644 --- a/test/testFunc.py +++ b/test/testFunc.py @@ -7,30 +7,31 @@ Description: Update Test ''' import time -from CACodeFramework.cacode.Factory import Factory -from CACodeFramework.util.Log import CACodeLog +from cacode_framework.cacode.Factory import Factory +from cacode_framework.util.Log import CACodeLog class MyFactory(Factory): - modules = [ - 'test.modules.Demo', - 'test.modules.MySqlTest', - 'test.modules.SqlServerTest', - ] + modules = { + "demo": 'test.modules.Demo', + "mysql_test": 'test.modules.MySqlTest', + "sqlserver_test": 'test.modules.SqlServerTest', + } def set_many(): a = [] for i in range(0, 100 * 10000): a.append( - MyFactory.createInstance('SqlServerTest.DemoTable', t_msg=f'测试msg{i}', t_name=f'测试name{i}', + MyFactory.createInstance('sqlserver_test.DemoTable', t_msg=f'测试msg{i}', t_name=f'测试name{i}', t_pwd=f'测试pwd{i}', abs=True)) return a def TestMySql(): - demoTable = MyFactory.createInstance('MySqlTest.DemoTable') + demoTable = MyFactory.createInstance('mysql_test.DemoTable') + d_2 = MyFactory.createInstance('mysql_test.DemoTable') # result = demoTable.find_all() # test_data = set_many() t = time.time() @@ -38,8 +39,11 @@ def TestMySql(): # result = demoTable.find_by_id(t_id=10) # page = result.page(7) # result = page.to_dict() - result = demoTable.orm.find().where(t_id__in=[1, 2, 3, 4, 5, 6, 7, 8, 9]).end() - info(result.to_json(True)) + result = demoTable.orm.find().where(t_id__in=[1, 2, 3, 4, 5, 6, 7, 8, 9]) + r_2 = d_2.orm.find(poly=[' FROM ']) + var = r_2 << result + info(var.append(' a').end()) + # info(result.to_json(True)) # info(f'count:{len(result)}') info(f'application run time:{time.time() - t}') # warn(result) @@ -55,6 +59,6 @@ if __name__ == '__main__': info = CACodeLog.log warn = CACodeLog.warning t1 = time.time() - TestSqlServer() - # TestMySql() + # TestSqlServer() + TestMySql() info(f'time:{time.time() - t1}') -- Gitee From fc8d1755acf15a5ed823f1412cb9ad8d10ee3acb Mon Sep 17 00:00:00 2001 From: CACode <54068986+cctvadmin@users.noreply.github.com> Date: Mon, 17 May 2021 08:36:14 +0800 Subject: [PATCH 11/26] On branch cacode --- {CACodeFramework => cacode_framework}/MainWork/CACodeAdapter.py | 0 .../MainWork/CACodeAopContainer.py | 0 {CACodeFramework => cacode_framework}/MainWork/CACodeConfig.py | 0 {CACodeFramework => cacode_framework}/MainWork/CACodePureORM.py | 0 .../MainWork/CACodeRepository.py | 0 {CACodeFramework => cacode_framework}/MainWork/__init__.py | 0 {CACodeFramework => cacode_framework}/__init__.py | 0 {CACodeFramework => cacode_framework}/anno/__init__.py | 0 {CACodeFramework => cacode_framework}/anno/annos.py | 0 {CACodeFramework => cacode_framework}/cacode/Factory.py | 0 {CACodeFramework => cacode_framework}/cacode/Modes.py | 0 {CACodeFramework => cacode_framework}/cacode/ReviewJson/JSON.py | 0 .../cacode/ReviewJson/__init__.py | 0 .../cacode/ReviewJson/_speedups.c | 0 {CACodeFramework => cacode_framework}/cacode/ReviewJson/compat.py | 0 .../cacode/ReviewJson/decoder.py | 0 .../cacode/ReviewJson/encoder.py | 0 {CACodeFramework => cacode_framework}/cacode/ReviewJson/errors.py | 0 .../cacode/ReviewJson/ordered_dict.py | 0 .../cacode/ReviewJson/raw_json.py | 0 .../cacode/ReviewJson/scanner.py | 0 {CACodeFramework => cacode_framework}/cacode/ReviewJson/tool.py | 0 {CACodeFramework => cacode_framework}/cacode/Serialize.py | 0 {CACodeFramework => cacode_framework}/cacode/__init__.py | 0 {CACodeFramework => cacode_framework}/exception/__init__.py | 0 {CACodeFramework => cacode_framework}/exception/e_fields.py | 0 {CACodeFramework => cacode_framework}/field/FManage.py | 0 {CACodeFramework => cacode_framework}/field/MySqlDefault.py | 0 {CACodeFramework => cacode_framework}/field/__init__.py | 0 {CACodeFramework => cacode_framework}/opera/CompulsoryRun.py | 0 {CACodeFramework => cacode_framework}/opera/__init__.py | 0 {CACodeFramework => cacode_framework}/opera/op_db.py | 0 {CACodeFramework => cacode_framework}/pojoManager/Manage.py | 0 {CACodeFramework => cacode_framework}/pojoManager/__init__.py | 0 {CACodeFramework => cacode_framework}/pojoManager/tag.py | 0 {CACodeFramework => cacode_framework}/util/DBPool/__init__.py | 0 .../util/DBPool/persistent_db.py | 0 .../util/DBPool/persistent_pg.py | 0 {CACodeFramework => cacode_framework}/util/DBPool/pooled_db.py | 0 {CACodeFramework => cacode_framework}/util/DBPool/pooled_pg.py | 0 .../util/DBPool/simple_pooled_db.py | 0 .../util/DBPool/simple_pooled_pg.py | 0 {CACodeFramework => cacode_framework}/util/DBPool/steady_db.py | 0 {CACodeFramework => cacode_framework}/util/DBPool/steady_pg.py | 0 {CACodeFramework => cacode_framework}/util/DbUtil.py | 0 {CACodeFramework => cacode_framework}/util/Log.py | 0 {CACodeFramework => cacode_framework}/util/ParseUtil.py | 0 {CACodeFramework => cacode_framework}/util/__init__.py | 0 48 files changed, 0 insertions(+), 0 deletions(-) rename {CACodeFramework => cacode_framework}/MainWork/CACodeAdapter.py (100%) rename {CACodeFramework => cacode_framework}/MainWork/CACodeAopContainer.py (100%) rename {CACodeFramework => cacode_framework}/MainWork/CACodeConfig.py (100%) rename {CACodeFramework => cacode_framework}/MainWork/CACodePureORM.py (100%) rename {CACodeFramework => cacode_framework}/MainWork/CACodeRepository.py (100%) rename {CACodeFramework => cacode_framework}/MainWork/__init__.py (100%) rename {CACodeFramework => cacode_framework}/__init__.py (100%) rename {CACodeFramework => cacode_framework}/anno/__init__.py (100%) rename {CACodeFramework => cacode_framework}/anno/annos.py (100%) rename {CACodeFramework => cacode_framework}/cacode/Factory.py (100%) rename {CACodeFramework => cacode_framework}/cacode/Modes.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/JSON.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/__init__.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/_speedups.c (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/compat.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/decoder.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/encoder.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/errors.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/ordered_dict.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/raw_json.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/scanner.py (100%) rename {CACodeFramework => cacode_framework}/cacode/ReviewJson/tool.py (100%) rename {CACodeFramework => cacode_framework}/cacode/Serialize.py (100%) rename {CACodeFramework => cacode_framework}/cacode/__init__.py (100%) rename {CACodeFramework => cacode_framework}/exception/__init__.py (100%) rename {CACodeFramework => cacode_framework}/exception/e_fields.py (100%) rename {CACodeFramework => cacode_framework}/field/FManage.py (100%) rename {CACodeFramework => cacode_framework}/field/MySqlDefault.py (100%) rename {CACodeFramework => cacode_framework}/field/__init__.py (100%) rename {CACodeFramework => cacode_framework}/opera/CompulsoryRun.py (100%) rename {CACodeFramework => cacode_framework}/opera/__init__.py (100%) rename {CACodeFramework => cacode_framework}/opera/op_db.py (100%) rename {CACodeFramework => cacode_framework}/pojoManager/Manage.py (100%) rename {CACodeFramework => cacode_framework}/pojoManager/__init__.py (100%) rename {CACodeFramework => cacode_framework}/pojoManager/tag.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/__init__.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/persistent_db.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/persistent_pg.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/pooled_db.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/pooled_pg.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/simple_pooled_db.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/simple_pooled_pg.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/steady_db.py (100%) rename {CACodeFramework => cacode_framework}/util/DBPool/steady_pg.py (100%) rename {CACodeFramework => cacode_framework}/util/DbUtil.py (100%) rename {CACodeFramework => cacode_framework}/util/Log.py (100%) rename {CACodeFramework => cacode_framework}/util/ParseUtil.py (100%) rename {CACodeFramework => cacode_framework}/util/__init__.py (100%) diff --git a/CACodeFramework/MainWork/CACodeAdapter.py b/cacode_framework/MainWork/CACodeAdapter.py similarity index 100% rename from CACodeFramework/MainWork/CACodeAdapter.py rename to cacode_framework/MainWork/CACodeAdapter.py diff --git a/CACodeFramework/MainWork/CACodeAopContainer.py b/cacode_framework/MainWork/CACodeAopContainer.py similarity index 100% rename from CACodeFramework/MainWork/CACodeAopContainer.py rename to cacode_framework/MainWork/CACodeAopContainer.py diff --git a/CACodeFramework/MainWork/CACodeConfig.py b/cacode_framework/MainWork/CACodeConfig.py similarity index 100% rename from CACodeFramework/MainWork/CACodeConfig.py rename to cacode_framework/MainWork/CACodeConfig.py diff --git a/CACodeFramework/MainWork/CACodePureORM.py b/cacode_framework/MainWork/CACodePureORM.py similarity index 100% rename from CACodeFramework/MainWork/CACodePureORM.py rename to cacode_framework/MainWork/CACodePureORM.py diff --git a/CACodeFramework/MainWork/CACodeRepository.py b/cacode_framework/MainWork/CACodeRepository.py similarity index 100% rename from CACodeFramework/MainWork/CACodeRepository.py rename to cacode_framework/MainWork/CACodeRepository.py diff --git a/CACodeFramework/MainWork/__init__.py b/cacode_framework/MainWork/__init__.py similarity index 100% rename from CACodeFramework/MainWork/__init__.py rename to cacode_framework/MainWork/__init__.py diff --git a/CACodeFramework/__init__.py b/cacode_framework/__init__.py similarity index 100% rename from CACodeFramework/__init__.py rename to cacode_framework/__init__.py diff --git a/CACodeFramework/anno/__init__.py b/cacode_framework/anno/__init__.py similarity index 100% rename from CACodeFramework/anno/__init__.py rename to cacode_framework/anno/__init__.py diff --git a/CACodeFramework/anno/annos.py b/cacode_framework/anno/annos.py similarity index 100% rename from CACodeFramework/anno/annos.py rename to cacode_framework/anno/annos.py diff --git a/CACodeFramework/cacode/Factory.py b/cacode_framework/cacode/Factory.py similarity index 100% rename from CACodeFramework/cacode/Factory.py rename to cacode_framework/cacode/Factory.py diff --git a/CACodeFramework/cacode/Modes.py b/cacode_framework/cacode/Modes.py similarity index 100% rename from CACodeFramework/cacode/Modes.py rename to cacode_framework/cacode/Modes.py diff --git a/CACodeFramework/cacode/ReviewJson/JSON.py b/cacode_framework/cacode/ReviewJson/JSON.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/JSON.py rename to cacode_framework/cacode/ReviewJson/JSON.py diff --git a/CACodeFramework/cacode/ReviewJson/__init__.py b/cacode_framework/cacode/ReviewJson/__init__.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/__init__.py rename to cacode_framework/cacode/ReviewJson/__init__.py diff --git a/CACodeFramework/cacode/ReviewJson/_speedups.c b/cacode_framework/cacode/ReviewJson/_speedups.c similarity index 100% rename from CACodeFramework/cacode/ReviewJson/_speedups.c rename to cacode_framework/cacode/ReviewJson/_speedups.c diff --git a/CACodeFramework/cacode/ReviewJson/compat.py b/cacode_framework/cacode/ReviewJson/compat.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/compat.py rename to cacode_framework/cacode/ReviewJson/compat.py diff --git a/CACodeFramework/cacode/ReviewJson/decoder.py b/cacode_framework/cacode/ReviewJson/decoder.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/decoder.py rename to cacode_framework/cacode/ReviewJson/decoder.py diff --git a/CACodeFramework/cacode/ReviewJson/encoder.py b/cacode_framework/cacode/ReviewJson/encoder.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/encoder.py rename to cacode_framework/cacode/ReviewJson/encoder.py diff --git a/CACodeFramework/cacode/ReviewJson/errors.py b/cacode_framework/cacode/ReviewJson/errors.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/errors.py rename to cacode_framework/cacode/ReviewJson/errors.py diff --git a/CACodeFramework/cacode/ReviewJson/ordered_dict.py b/cacode_framework/cacode/ReviewJson/ordered_dict.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/ordered_dict.py rename to cacode_framework/cacode/ReviewJson/ordered_dict.py diff --git a/CACodeFramework/cacode/ReviewJson/raw_json.py b/cacode_framework/cacode/ReviewJson/raw_json.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/raw_json.py rename to cacode_framework/cacode/ReviewJson/raw_json.py diff --git a/CACodeFramework/cacode/ReviewJson/scanner.py b/cacode_framework/cacode/ReviewJson/scanner.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/scanner.py rename to cacode_framework/cacode/ReviewJson/scanner.py diff --git a/CACodeFramework/cacode/ReviewJson/tool.py b/cacode_framework/cacode/ReviewJson/tool.py similarity index 100% rename from CACodeFramework/cacode/ReviewJson/tool.py rename to cacode_framework/cacode/ReviewJson/tool.py diff --git a/CACodeFramework/cacode/Serialize.py b/cacode_framework/cacode/Serialize.py similarity index 100% rename from CACodeFramework/cacode/Serialize.py rename to cacode_framework/cacode/Serialize.py diff --git a/CACodeFramework/cacode/__init__.py b/cacode_framework/cacode/__init__.py similarity index 100% rename from CACodeFramework/cacode/__init__.py rename to cacode_framework/cacode/__init__.py diff --git a/CACodeFramework/exception/__init__.py b/cacode_framework/exception/__init__.py similarity index 100% rename from CACodeFramework/exception/__init__.py rename to cacode_framework/exception/__init__.py diff --git a/CACodeFramework/exception/e_fields.py b/cacode_framework/exception/e_fields.py similarity index 100% rename from CACodeFramework/exception/e_fields.py rename to cacode_framework/exception/e_fields.py diff --git a/CACodeFramework/field/FManage.py b/cacode_framework/field/FManage.py similarity index 100% rename from CACodeFramework/field/FManage.py rename to cacode_framework/field/FManage.py diff --git a/CACodeFramework/field/MySqlDefault.py b/cacode_framework/field/MySqlDefault.py similarity index 100% rename from CACodeFramework/field/MySqlDefault.py rename to cacode_framework/field/MySqlDefault.py diff --git a/CACodeFramework/field/__init__.py b/cacode_framework/field/__init__.py similarity index 100% rename from CACodeFramework/field/__init__.py rename to cacode_framework/field/__init__.py diff --git a/CACodeFramework/opera/CompulsoryRun.py b/cacode_framework/opera/CompulsoryRun.py similarity index 100% rename from CACodeFramework/opera/CompulsoryRun.py rename to cacode_framework/opera/CompulsoryRun.py diff --git a/CACodeFramework/opera/__init__.py b/cacode_framework/opera/__init__.py similarity index 100% rename from CACodeFramework/opera/__init__.py rename to cacode_framework/opera/__init__.py diff --git a/CACodeFramework/opera/op_db.py b/cacode_framework/opera/op_db.py similarity index 100% rename from CACodeFramework/opera/op_db.py rename to cacode_framework/opera/op_db.py diff --git a/CACodeFramework/pojoManager/Manage.py b/cacode_framework/pojoManager/Manage.py similarity index 100% rename from CACodeFramework/pojoManager/Manage.py rename to cacode_framework/pojoManager/Manage.py diff --git a/CACodeFramework/pojoManager/__init__.py b/cacode_framework/pojoManager/__init__.py similarity index 100% rename from CACodeFramework/pojoManager/__init__.py rename to cacode_framework/pojoManager/__init__.py diff --git a/CACodeFramework/pojoManager/tag.py b/cacode_framework/pojoManager/tag.py similarity index 100% rename from CACodeFramework/pojoManager/tag.py rename to cacode_framework/pojoManager/tag.py diff --git a/CACodeFramework/util/DBPool/__init__.py b/cacode_framework/util/DBPool/__init__.py similarity index 100% rename from CACodeFramework/util/DBPool/__init__.py rename to cacode_framework/util/DBPool/__init__.py diff --git a/CACodeFramework/util/DBPool/persistent_db.py b/cacode_framework/util/DBPool/persistent_db.py similarity index 100% rename from CACodeFramework/util/DBPool/persistent_db.py rename to cacode_framework/util/DBPool/persistent_db.py diff --git a/CACodeFramework/util/DBPool/persistent_pg.py b/cacode_framework/util/DBPool/persistent_pg.py similarity index 100% rename from CACodeFramework/util/DBPool/persistent_pg.py rename to cacode_framework/util/DBPool/persistent_pg.py diff --git a/CACodeFramework/util/DBPool/pooled_db.py b/cacode_framework/util/DBPool/pooled_db.py similarity index 100% rename from CACodeFramework/util/DBPool/pooled_db.py rename to cacode_framework/util/DBPool/pooled_db.py diff --git a/CACodeFramework/util/DBPool/pooled_pg.py b/cacode_framework/util/DBPool/pooled_pg.py similarity index 100% rename from CACodeFramework/util/DBPool/pooled_pg.py rename to cacode_framework/util/DBPool/pooled_pg.py diff --git a/CACodeFramework/util/DBPool/simple_pooled_db.py b/cacode_framework/util/DBPool/simple_pooled_db.py similarity index 100% rename from CACodeFramework/util/DBPool/simple_pooled_db.py rename to cacode_framework/util/DBPool/simple_pooled_db.py diff --git a/CACodeFramework/util/DBPool/simple_pooled_pg.py b/cacode_framework/util/DBPool/simple_pooled_pg.py similarity index 100% rename from CACodeFramework/util/DBPool/simple_pooled_pg.py rename to cacode_framework/util/DBPool/simple_pooled_pg.py diff --git a/CACodeFramework/util/DBPool/steady_db.py b/cacode_framework/util/DBPool/steady_db.py similarity index 100% rename from CACodeFramework/util/DBPool/steady_db.py rename to cacode_framework/util/DBPool/steady_db.py diff --git a/CACodeFramework/util/DBPool/steady_pg.py b/cacode_framework/util/DBPool/steady_pg.py similarity index 100% rename from CACodeFramework/util/DBPool/steady_pg.py rename to cacode_framework/util/DBPool/steady_pg.py diff --git a/CACodeFramework/util/DbUtil.py b/cacode_framework/util/DbUtil.py similarity index 100% rename from CACodeFramework/util/DbUtil.py rename to cacode_framework/util/DbUtil.py diff --git a/CACodeFramework/util/Log.py b/cacode_framework/util/Log.py similarity index 100% rename from CACodeFramework/util/Log.py rename to cacode_framework/util/Log.py diff --git a/CACodeFramework/util/ParseUtil.py b/cacode_framework/util/ParseUtil.py similarity index 100% rename from CACodeFramework/util/ParseUtil.py rename to cacode_framework/util/ParseUtil.py diff --git a/CACodeFramework/util/__init__.py b/cacode_framework/util/__init__.py similarity index 100% rename from CACodeFramework/util/__init__.py rename to cacode_framework/util/__init__.py -- Gitee From a71ff12d98f6cf59ffe062b539864def1b284453 Mon Sep 17 00:00:00 2001 From: CACode <54068986+cctvadmin@users.noreply.github.com> Date: Mon, 17 May 2021 18:12:27 +0800 Subject: [PATCH 12/26] 1 --- cacode_framework/MainWork/CACodePureORM.py | 31 +++++----------------- cacode_framework/exception/e_fields.py | 10 +++++++ cacode_framework/pojoManager/Manage.py | 4 +-- 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/cacode_framework/MainWork/CACodePureORM.py b/cacode_framework/MainWork/CACodePureORM.py index 8b8daf4..38d0876 100644 --- a/cacode_framework/MainWork/CACodePureORM.py +++ b/cacode_framework/MainWork/CACodePureORM.py @@ -67,28 +67,6 @@ s """ values_str=self.sqlFields.values_str) self.args.append(sql['sql']) self.params = sql['params'] - - # _dict = pojo.__dict__ - # keys = [] - # # 解析item - # for key, value in _dict.items(): - # # 去除为空的键 - # if value is None: - # continue - # keys.append('`{}`{}'.format(key, comma)) - # self.params.append(value) - # for i in keys: - # self.args.append(i) - # # 将最后一个字段的逗号改成空格 - # self.rep_sym(comma, space) - # # 加上右边括号 - # self.args.append(right_par) - # self.args.append('{}{}'.format(values_str, left_par)) - # for i in keys: - # self.args.append('%s{}'.format(comma)) - # # 将最后一个字段的逗号改成空格 - # self.rep_sym(comma, space) - # self.args.append(right_par) return self def delete(self): @@ -154,8 +132,9 @@ s """ fs = fields.split(',') if len(fs) != len(asses): # 匿名参数长度与字段长度不符合 - raise TypeError( - 'The length of the anonymous parameter does not match the length of the field') + CACodeLog.log_error(obj=TypeError, + msg='The length of the anonymous parameter does not match the length of the field', + raise_exception=True) for i, v in enumerate(fs): if asses[i] is not None: self.args.append('{}{}{}'.format( @@ -359,8 +338,10 @@ s """ self.args.clear() self.params.clear() if self.first_data: - if type(_result) is list or type(_result) is tuple: + if (isinstance(_result, list) or isinstance(_result, tuple)) and _result and len(_result) > 0: return self.serializer(instance=self.repository.instance, base_data=_result).first() + else: + return None else: q = self.serializer( instance=self.repository.instance, base_data=_result) diff --git a/cacode_framework/exception/e_fields.py b/cacode_framework/exception/e_fields.py index b1f33b1..e7cf7bc 100644 --- a/cacode_framework/exception/e_fields.py +++ b/cacode_framework/exception/e_fields.py @@ -1,3 +1,13 @@ +__all__ = [ + 'mat', 'CACode_SqlError', 'CACode_Factory_Error', + 'Json_Error', 'Syntax_Error', 'Attribute_Error', + 'Attribute_Error', 'Log_Opera_Name', 'Miss_Attr', + 'Error', 'Warn', 'Info', + 'Database_Operation', 'Parse_Error', 'FieldNotExist', + 'ModuleCreateError' +] + + def mat(prefix, suffix): return '%s:%s' % (prefix, suffix) diff --git a/cacode_framework/pojoManager/Manage.py b/cacode_framework/pojoManager/Manage.py index 37e1b2a..ab3ee20 100644 --- a/cacode_framework/pojoManager/Manage.py +++ b/cacode_framework/pojoManager/Manage.py @@ -22,8 +22,6 @@ class Pojo(CACodeRepository.Repository): if not hasattr(self, '__table_msg__'): self.__table_msg__ = 'The current object has no description' - self.__table_name__ = self.__table_name__ - self.__table_msg__ = self.__table_msg__ self.__fields__ = {} # 在这里将config_obj实例化 self.serializer = serializer @@ -55,7 +53,7 @@ class Pojo(CACodeRepository.Repository): if not hasattr(self, key) or getattr(self, key) is None or t_v in [tag.Template, tag.baseTag]: setattr(self, key, value.default) fds[key] = value if value.default is None else value.default - except SyntaxError as a: + except SyntaxError: continue self.__fields__ = fds -- Gitee From fff4cf0bd10dca36e97cbe296322f401f818d415 Mon Sep 17 00:00:00 2001 From: CACode Date: Wed, 19 May 2021 23:21:16 +0800 Subject: [PATCH 13/26] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AE=B8=E5=8F=AF?= =?UTF-8?q?=E8=AF=81=E7=B1=BB=E5=9E=8B=EF=BC=8C=E4=BF=AE=E6=94=B9=E6=A1=86?= =?UTF-8?q?=E6=9E=B6=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LICENSE | 875 ++++-------------- README.md | 20 +- cacode_framework/util/__init__.py | 0 setup.py | 8 +- {cacode_framework => summer}/__init__.py | 0 {cacode_framework => summer}/anno/__init__.py | 0 {cacode_framework => summer}/anno/annos.py | 6 +- .../cacode/Factory.py | 10 +- {cacode_framework => summer}/cacode/Modes.py | 2 +- .../cacode/ReviewJson/JSON.py | 15 +- .../cacode/ReviewJson/__init__.py | 0 .../cacode/ReviewJson/_speedups.c | 0 .../cacode/ReviewJson/compat.py | 0 .../cacode/ReviewJson/decoder.py | 0 .../cacode/ReviewJson/encoder.py | 0 .../cacode/ReviewJson/errors.py | 0 .../cacode/ReviewJson/ordered_dict.py | 9 +- .../cacode/ReviewJson/raw_json.py | 0 .../cacode/ReviewJson/scanner.py | 0 .../cacode/ReviewJson/tool.py | 0 .../cacode/Serialize.py | 6 +- .../cacode/__init__.py | 0 summer/exception/__init__.py | 16 + .../exception/e_fields.py | 8 - {cacode_framework => summer}/field/FManage.py | 0 .../field/MySqlDefault.py | 2 +- .../exception => summer/field}/__init__.py | 0 .../field => summer/opera}/__init__.py | 0 .../DbUtil.py => summer/opera/global_db.py | 18 +- {cacode_framework => summer}/opera/op_db.py | 10 +- .../pojoManager/Manage.py | 14 +- .../opera => summer/pojoManager}/__init__.py | 0 .../pojoManager/tag.py | 2 +- .../opera => summer/util}/CompulsoryRun.py | 4 +- .../util/DBPool/__init__.py | 0 .../util/DBPool/persistent_db.py | 0 .../util/DBPool/persistent_pg.py | 0 .../util/DBPool/pooled_db.py | 0 .../util/DBPool/pooled_pg.py | 0 .../util/DBPool/simple_pooled_db.py | 0 .../util/DBPool/simple_pooled_pg.py | 0 .../util/DBPool/steady_db.py | 0 .../util/DBPool/steady_pg.py | 0 {cacode_framework => summer}/util/Log.py | 4 +- .../util/ParseUtil.py | 6 +- .../pojoManager => summer/util}/__init__.py | 0 .../work/AopContainer.py | 2 +- .../CACodeConfig.py => summer/work/Config.py | 10 +- .../work/SummerAdapter.py | 0 .../MainWork => summer/work}/__init__.py | 0 .../CACodePureORM.py => summer/work/orm.py | 4 +- .../work/repository.py | 31 +- test/modules/DatabaseConf.py | 8 +- test/modules/MySqlTest.py | 6 +- test/modules/SqlServerTest.py | 6 +- test/testFunc.py | 10 +- 56 files changed, 310 insertions(+), 802 deletions(-) delete mode 100644 cacode_framework/util/__init__.py rename {cacode_framework => summer}/__init__.py (100%) rename {cacode_framework => summer}/anno/__init__.py (100%) rename {cacode_framework => summer}/anno/annos.py (97%) rename {cacode_framework => summer}/cacode/Factory.py (91%) rename {cacode_framework => summer}/cacode/Modes.py (99%) rename {cacode_framework => summer}/cacode/ReviewJson/JSON.py (88%) rename {cacode_framework => summer}/cacode/ReviewJson/__init__.py (100%) rename {cacode_framework => summer}/cacode/ReviewJson/_speedups.c (100%) rename {cacode_framework => summer}/cacode/ReviewJson/compat.py (100%) rename {cacode_framework => summer}/cacode/ReviewJson/decoder.py (100%) rename {cacode_framework => summer}/cacode/ReviewJson/encoder.py (100%) rename {cacode_framework => summer}/cacode/ReviewJson/errors.py (100%) rename {cacode_framework => summer}/cacode/ReviewJson/ordered_dict.py (90%) rename {cacode_framework => summer}/cacode/ReviewJson/raw_json.py (100%) rename {cacode_framework => summer}/cacode/ReviewJson/scanner.py (100%) rename {cacode_framework => summer}/cacode/ReviewJson/tool.py (100%) rename {cacode_framework => summer}/cacode/Serialize.py (98%) rename {cacode_framework => summer}/cacode/__init__.py (100%) create mode 100644 summer/exception/__init__.py rename {cacode_framework => summer}/exception/e_fields.py (87%) rename {cacode_framework => summer}/field/FManage.py (100%) rename {cacode_framework => summer}/field/MySqlDefault.py (98%) rename {cacode_framework/exception => summer/field}/__init__.py (100%) rename {cacode_framework/field => summer/opera}/__init__.py (100%) rename cacode_framework/util/DbUtil.py => summer/opera/global_db.py (92%) rename {cacode_framework => summer}/opera/op_db.py (93%) rename {cacode_framework => summer}/pojoManager/Manage.py (91%) rename {cacode_framework/opera => summer/pojoManager}/__init__.py (100%) rename {cacode_framework => summer}/pojoManager/tag.py (98%) rename {cacode_framework/opera => summer/util}/CompulsoryRun.py (91%) rename {cacode_framework => summer}/util/DBPool/__init__.py (100%) rename {cacode_framework => summer}/util/DBPool/persistent_db.py (100%) rename {cacode_framework => summer}/util/DBPool/persistent_pg.py (100%) rename {cacode_framework => summer}/util/DBPool/pooled_db.py (100%) rename {cacode_framework => summer}/util/DBPool/pooled_pg.py (100%) rename {cacode_framework => summer}/util/DBPool/simple_pooled_db.py (100%) rename {cacode_framework => summer}/util/DBPool/simple_pooled_pg.py (100%) rename {cacode_framework => summer}/util/DBPool/steady_db.py (100%) rename {cacode_framework => summer}/util/DBPool/steady_pg.py (100%) rename {cacode_framework => summer}/util/Log.py (98%) rename {cacode_framework => summer}/util/ParseUtil.py (98%) rename {cacode_framework/pojoManager => summer/util}/__init__.py (100%) rename cacode_framework/MainWork/CACodeAopContainer.py => summer/work/AopContainer.py (99%) rename cacode_framework/MainWork/CACodeConfig.py => summer/work/Config.py (90%) rename cacode_framework/MainWork/CACodeAdapter.py => summer/work/SummerAdapter.py (100%) rename {cacode_framework/MainWork => summer/work}/__init__.py (100%) rename cacode_framework/MainWork/CACodePureORM.py => summer/work/orm.py (99%) rename cacode_framework/MainWork/CACodeRepository.py => summer/work/repository.py (91%) diff --git a/LICENSE b/LICENSE index e72bfdd..f49a4e1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,674 +1,201 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md index ec3f93d..944c20a 100644 --- a/README.md +++ b/README.md @@ -10,29 +10,15 @@

-> pip命令:pip install CACodeFramework - -## Author +# 安装 -👤 **CACode** - -* Github: [@cctvadmin](https://github.com/cctvadmin) -* QQ: 2075383131 -* wechat: cacode -* email: cacode@163.com +> pip命令:pip install CACodeFramework ## 先决条件 - python >=3.6 -项目地址: https://gitee.com/cacode_cctvadmin/CACodeFramework-python-ORM -项目文档:http://doc.cacode.ren - -> 统一市面上所有的数据库创建者,并分配连接池和缓存 - -## 结语 - -如果这个框架对你有帮助的话,请给个星点个star +> 教程文档地址:http://doc.cacode.ren # CACode diff --git a/cacode_framework/util/__init__.py b/cacode_framework/util/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/setup.py b/setup.py index 1361e63..5ef218c 100644 --- a/setup.py +++ b/setup.py @@ -4,16 +4,16 @@ with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read() setuptools.setup( - name="cacode_framework", + name="summer_framework", version="1.0.0", author="CACode", author_email="cacode@163.com", - description="CACode Framework For Python Flask,This framework corresponds to the ORM problem,You can see:https://gitee.com/cacode_cctvadmin/CACodeFramework-python-ORM", + description="Summer framework for Python,You can see:https://gitee.com/cacode_cctvadmin/summer-python", long_description=long_description, long_description_content_type="text/markdown", - url="https://gitee.com/cacode_cctvadmin/CACodeFramework-python-ORM", + url="https://gitee.com/cacode_cctvadmin/summer-python", project_urls={ - "Bug Tracker": "https://gitee.com/cacode_cctvadmin/CACodeFramework-python-ORM/issues", + "Bug Tracker": "https://gitee.com/cacode_cctvadmin/summer-python/issues", }, license=' GPL-3.0', classifiers=[ diff --git a/cacode_framework/__init__.py b/summer/__init__.py similarity index 100% rename from cacode_framework/__init__.py rename to summer/__init__.py diff --git a/cacode_framework/anno/__init__.py b/summer/anno/__init__.py similarity index 100% rename from cacode_framework/anno/__init__.py rename to summer/anno/__init__.py diff --git a/cacode_framework/anno/annos.py b/summer/anno/annos.py similarity index 97% rename from cacode_framework/anno/annos.py rename to summer/anno/annos.py index cf547dc..459c52b 100644 --- a/cacode_framework/anno/annos.py +++ b/summer/anno/annos.py @@ -1,3 +1,6 @@ +from summer.work.AopContainer import AopModelObject + + def Table(name, msg, **kwargs): """ 标注该类为一个表 @@ -67,7 +70,7 @@ def Select(sql, params=None): new_args = parse_kwargs(params, kwargs) result = obj.find_sql(sql=sql, params=new_args) - from cacode_framework.cacode.Serialize import QuerySet + from summer.cacode.Serialize import QuerySet return QuerySet(obj, result) return _wrapper_ @@ -170,7 +173,6 @@ def AopModel(before=None, after=None, """ # 得到对象组 - from cacode_framework.MainWork.CACodeAopContainer import AopModelObject aop_obj = AopModelObject(before, after, before_args, before_kwargs, after_args, after_kwargs) diff --git a/cacode_framework/cacode/Factory.py b/summer/cacode/Factory.py similarity index 91% rename from cacode_framework/cacode/Factory.py rename to summer/cacode/Factory.py index 31c3b5e..b2af1c3 100644 --- a/cacode_framework/cacode/Factory.py +++ b/summer/cacode/Factory.py @@ -1,10 +1,10 @@ import threading -from cacode_framework.cacode import Modes -from cacode_framework.exception import e_fields -from cacode_framework.exception.e_fields import ModuleCreateError -from cacode_framework.opera.CompulsoryRun import Compulsory -from cacode_framework.util.Log import CACodeLog +from summer.cacode import Modes +from summer.exception import e_fields +from summer.exception import ModuleCreateError +from summer.util.CompulsoryRun import Compulsory +from summer.util.Log import CACodeLog import importlib diff --git a/cacode_framework/cacode/Modes.py b/summer/cacode/Modes.py similarity index 99% rename from cacode_framework/cacode/Modes.py rename to summer/cacode/Modes.py index 699e2d9..99907f0 100644 --- a/cacode_framework/cacode/Modes.py +++ b/summer/cacode/Modes.py @@ -295,7 +295,7 @@ if __name__ == '__main__': "e": rep } result = Recursion.find_key_for_dict(data, "a") - from cacode_framework.cacode.Serialize import JsonUtil + from summer.cacode.Serialize import JsonUtil print(JsonUtil.parse(result)) diff --git a/cacode_framework/cacode/ReviewJson/JSON.py b/summer/cacode/ReviewJson/JSON.py similarity index 88% rename from cacode_framework/cacode/ReviewJson/JSON.py rename to summer/cacode/ReviewJson/JSON.py index 159c447..f2319f0 100644 --- a/cacode_framework/cacode/ReviewJson/JSON.py +++ b/summer/cacode/ReviewJson/JSON.py @@ -5,6 +5,9 @@ __all__ = [ __author__ = 'CACode ' +from . import _default_encoder, JSONEncoder, _default_decoder, JSONDecoder +from decimal import Decimal + class Json: @@ -17,10 +20,8 @@ class Json: for_json=False, ignore_nan=False, int_as_string_bitcount=None, iterable_as_array=False, **kw): """ - - serializer `obj` to a json formatted `str` + 转json字符串 """ - # cached encoder if (not skipkeys and ensure_ascii and check_circular and allow_nan and cls is None and indent is None and separators is None and @@ -31,10 +32,8 @@ class Json: and not ignore_nan and int_as_string_bitcount is None and not kw ): - from . import _default_encoder return _default_encoder.encode(obj) if cls is None: - from . import JSONEncoder cls = JSONEncoder return cls( skipkeys=skipkeys, ensure_ascii=ensure_ascii, @@ -57,17 +56,14 @@ class Json: parse_int=None, parse_constant=None, object_pairs_hook=None, use_decimal=False, **kw): """ - Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON - document) to a Python object. + json转字典 """ if (cls is None and encoding is None and object_hook is None and parse_int is None and parse_float is None and parse_constant is None and object_pairs_hook is None and not use_decimal and not kw): - from . import _default_decoder return _default_decoder.decode(s) if cls is None: - from . import JSONDecoder cls = JSONDecoder if object_hook is not None: kw['object_hook'] = object_hook @@ -82,6 +78,5 @@ class Json: if use_decimal: if parse_float is not None: raise TypeError("use_decimal=True implies parse_float=Decimal") - from decimal import Decimal kw['parse_float'] = Decimal return cls(encoding=encoding, **kw).decode(s) diff --git a/cacode_framework/cacode/ReviewJson/__init__.py b/summer/cacode/ReviewJson/__init__.py similarity index 100% rename from cacode_framework/cacode/ReviewJson/__init__.py rename to summer/cacode/ReviewJson/__init__.py diff --git a/cacode_framework/cacode/ReviewJson/_speedups.c b/summer/cacode/ReviewJson/_speedups.c similarity index 100% rename from cacode_framework/cacode/ReviewJson/_speedups.c rename to summer/cacode/ReviewJson/_speedups.c diff --git a/cacode_framework/cacode/ReviewJson/compat.py b/summer/cacode/ReviewJson/compat.py similarity index 100% rename from cacode_framework/cacode/ReviewJson/compat.py rename to summer/cacode/ReviewJson/compat.py diff --git a/cacode_framework/cacode/ReviewJson/decoder.py b/summer/cacode/ReviewJson/decoder.py similarity index 100% rename from cacode_framework/cacode/ReviewJson/decoder.py rename to summer/cacode/ReviewJson/decoder.py diff --git a/cacode_framework/cacode/ReviewJson/encoder.py b/summer/cacode/ReviewJson/encoder.py similarity index 100% rename from cacode_framework/cacode/ReviewJson/encoder.py rename to summer/cacode/ReviewJson/encoder.py diff --git a/cacode_framework/cacode/ReviewJson/errors.py b/summer/cacode/ReviewJson/errors.py similarity index 100% rename from cacode_framework/cacode/ReviewJson/errors.py rename to summer/cacode/ReviewJson/errors.py diff --git a/cacode_framework/cacode/ReviewJson/ordered_dict.py b/summer/cacode/ReviewJson/ordered_dict.py similarity index 90% rename from cacode_framework/cacode/ReviewJson/ordered_dict.py rename to summer/cacode/ReviewJson/ordered_dict.py index d5a55eb..cafea6b 100644 --- a/cacode_framework/cacode/ReviewJson/ordered_dict.py +++ b/summer/cacode/ReviewJson/ordered_dict.py @@ -5,6 +5,7 @@ http://code.activestate.com/recipes/576693/ """ from UserDict import DictMixin + class OrderedDict(dict, DictMixin): def __init__(self, *args, **kwds): @@ -18,8 +19,8 @@ class OrderedDict(dict, DictMixin): def clear(self): self.__end = end = [] - end += [None, end, end] # sentinel node for doubly linked list - self.__map = {} # key --> [key, prev, next] + end += [None, end, end] # sentinel node for doubly linked list + self.__map = {} # key --> [key, prev, next] dict.clear(self) def __setitem__(self, key, value): @@ -95,8 +96,8 @@ class OrderedDict(dict, DictMixin): def __eq__(self, other): if isinstance(other, OrderedDict): - return len(self)==len(other) and \ - all(p==q for p, q in zip(self.items(), other.items())) + return len(self) == len(other) and \ + all(p == q for p, q in zip(self.items(), other.items())) return dict.__eq__(self, other) def __ne__(self, other): diff --git a/cacode_framework/cacode/ReviewJson/raw_json.py b/summer/cacode/ReviewJson/raw_json.py similarity index 100% rename from cacode_framework/cacode/ReviewJson/raw_json.py rename to summer/cacode/ReviewJson/raw_json.py diff --git a/cacode_framework/cacode/ReviewJson/scanner.py b/summer/cacode/ReviewJson/scanner.py similarity index 100% rename from cacode_framework/cacode/ReviewJson/scanner.py rename to summer/cacode/ReviewJson/scanner.py diff --git a/cacode_framework/cacode/ReviewJson/tool.py b/summer/cacode/ReviewJson/tool.py similarity index 100% rename from cacode_framework/cacode/ReviewJson/tool.py rename to summer/cacode/ReviewJson/tool.py diff --git a/cacode_framework/cacode/Serialize.py b/summer/cacode/Serialize.py similarity index 98% rename from cacode_framework/cacode/Serialize.py rename to summer/cacode/Serialize.py index cb2ee3e..49e188f 100644 --- a/cacode_framework/cacode/Serialize.py +++ b/summer/cacode/Serialize.py @@ -15,9 +15,9 @@ # CACode 1.2 2021/4/27 统一序列化器位置 # ------------------------------------------------------------------ -from cacode_framework.cacode.ReviewJson.JSON import Json -from cacode_framework.util.Log import CACodeLog -from cacode_framework.cacode import ReviewJson +from summer.cacode.ReviewJson.JSON import Json +from summer.util.Log import CACodeLog +from summer.cacode import ReviewJson from datetime import date, datetime import functools diff --git a/cacode_framework/cacode/__init__.py b/summer/cacode/__init__.py similarity index 100% rename from cacode_framework/cacode/__init__.py rename to summer/cacode/__init__.py diff --git a/summer/exception/__init__.py b/summer/exception/__init__.py new file mode 100644 index 0000000..ea200f4 --- /dev/null +++ b/summer/exception/__init__.py @@ -0,0 +1,16 @@ +class DBException(Exception): + def __init__(self, baseException): + self.baseException = baseException + self.baseName = self.baseException.__class__.__name__ + super(DBException, self).__init__() + + def __str__(self): + return f"({self.baseName}):{str(self.baseException)}" + + +class ModuleCreateError(ModuleNotFoundError): + pass + + +class FieldNotExist(AttributeError): + pass diff --git a/cacode_framework/exception/e_fields.py b/summer/exception/e_fields.py similarity index 87% rename from cacode_framework/exception/e_fields.py rename to summer/exception/e_fields.py index b1f33b1..d31400f 100644 --- a/cacode_framework/exception/e_fields.py +++ b/summer/exception/e_fields.py @@ -48,11 +48,3 @@ def Database_Operation(): def Parse_Error(msg): return mat('CACode-Parse', msg) - - -class FieldNotExist(AttributeError): - pass - - -class ModuleCreateError(ModuleNotFoundError): - pass diff --git a/cacode_framework/field/FManage.py b/summer/field/FManage.py similarity index 100% rename from cacode_framework/field/FManage.py rename to summer/field/FManage.py diff --git a/cacode_framework/field/MySqlDefault.py b/summer/field/MySqlDefault.py similarity index 98% rename from cacode_framework/field/MySqlDefault.py rename to summer/field/MySqlDefault.py index e1b8a1b..87ae5f3 100644 --- a/cacode_framework/field/MySqlDefault.py +++ b/summer/field/MySqlDefault.py @@ -2,7 +2,7 @@ # 空格符 import threading -from ..cacode.Modes import Singleton +from summer.cacode.Modes import Singleton class MySqlFields_Default: diff --git a/cacode_framework/exception/__init__.py b/summer/field/__init__.py similarity index 100% rename from cacode_framework/exception/__init__.py rename to summer/field/__init__.py diff --git a/cacode_framework/field/__init__.py b/summer/opera/__init__.py similarity index 100% rename from cacode_framework/field/__init__.py rename to summer/opera/__init__.py diff --git a/cacode_framework/util/DbUtil.py b/summer/opera/global_db.py similarity index 92% rename from cacode_framework/util/DbUtil.py rename to summer/opera/global_db.py index ac12ecf..d412ae2 100644 --- a/cacode_framework/util/DbUtil.py +++ b/summer/opera/global_db.py @@ -1,9 +1,10 @@ import sys import threading -from cacode_framework.cacode.Modes import Singleton -from cacode_framework.util.DBPool.pooled_db import PooledDB -from cacode_framework.util.Log import CACodeLog +from summer.cacode.Modes import Singleton +from summer.exception import DBException +from summer.util.DBPool.pooled_db import PooledDB +from summer.util.Log import CACodeLog def parse_kwa(db, **kwargs): @@ -161,7 +162,6 @@ class Db_opera(object): :return: """ db = self.get_conn() - cursor = None try: cursor = parse_kwa(db=db, **kwargs) # 列名 @@ -183,10 +183,7 @@ class Db_opera(object): return _result except Exception as e: db.rollback() - CACodeLog.log_error(obj=e.__class__, msg=e.__str__(), - LogObject=kwargs['logObject'] if 'logObject' in kwargs.keys() else None, - raise_exception=True) - raise e + raise DBException(e) finally: db.close() @@ -200,7 +197,6 @@ class Db_opera(object): :param many:是否为多行执行 """ db = self.get_conn() - cursor = None try: cursor = parse_kwa(db=db, many=many, **kwargs) db.commit() @@ -215,9 +211,7 @@ class Db_opera(object): return rowcount except Exception as e: db.rollback() - CACodeLog.log_error(obj=e.__class__, msg=e.__str__(), - LogObject=kwargs['logObject'] if 'logObject' in kwargs.keys() else None, - raise_exception=True) + raise DBException(e) finally: db.close() diff --git a/cacode_framework/opera/op_db.py b/summer/opera/op_db.py similarity index 93% rename from cacode_framework/opera/op_db.py rename to summer/opera/op_db.py index 71602d7..d624e38 100644 --- a/cacode_framework/opera/op_db.py +++ b/summer/opera/op_db.py @@ -1,11 +1,7 @@ -import threading +from summer.util.Log import CACodeLog -from cacode_framework.cacode.Modes import Recursion -from cacode_framework.cacode.Serialize import JsonUtil -from cacode_framework.util.Log import CACodeLog - -from cacode_framework.field.MySqlDefault import * -from cacode_framework.util.ParseUtil import ParseUtil +from summer.field.MySqlDefault import * +from summer.util.ParseUtil import ParseUtil class DbOperation(object): diff --git a/cacode_framework/pojoManager/Manage.py b/summer/pojoManager/Manage.py similarity index 91% rename from cacode_framework/pojoManager/Manage.py rename to summer/pojoManager/Manage.py index 37e1b2a..0d94b07 100644 --- a/cacode_framework/pojoManager/Manage.py +++ b/summer/pojoManager/Manage.py @@ -1,12 +1,12 @@ -from cacode_framework.MainWork.CACodePureORM import CACodePureORM -from cacode_framework.cacode.Serialize import QuerySet -from cacode_framework.pojoManager import tag -from cacode_framework.cacode.Serialize import JsonUtil -from cacode_framework.MainWork import CACodeRepository -from cacode_framework.util.Log import CACodeLog +from summer.work.orm import CACodePureORM +from summer.cacode.Serialize import QuerySet +from summer.pojoManager import tag +from summer.cacode.Serialize import JsonUtil +from summer.work import repository +from summer.util.Log import CACodeLog -class Pojo(CACodeRepository.Repository): +class Pojo(repository.Repository): def __init__(self, config_obj=None, log_conf=None, close_log=False, serializer=QuerySet, **kwargs): """ 初始化ORM框架 diff --git a/cacode_framework/opera/__init__.py b/summer/pojoManager/__init__.py similarity index 100% rename from cacode_framework/opera/__init__.py rename to summer/pojoManager/__init__.py diff --git a/cacode_framework/pojoManager/tag.py b/summer/pojoManager/tag.py similarity index 98% rename from cacode_framework/pojoManager/tag.py rename to summer/pojoManager/tag.py index 2daca82..c6ec889 100644 --- a/cacode_framework/pojoManager/tag.py +++ b/summer/pojoManager/tag.py @@ -1,6 +1,6 @@ import datetime -from cacode_framework.cacode.Serialize import JsonUtil +from summer.cacode.Serialize import JsonUtil """ 这个文件用来为pojo对象做标记,当对象为空或为以下任意类型时 diff --git a/cacode_framework/opera/CompulsoryRun.py b/summer/util/CompulsoryRun.py similarity index 91% rename from cacode_framework/opera/CompulsoryRun.py rename to summer/util/CompulsoryRun.py index 49c4317..0d67e56 100644 --- a/cacode_framework/opera/CompulsoryRun.py +++ b/summer/util/CompulsoryRun.py @@ -33,8 +33,8 @@ class Compulsory(object): 深度搜素树 """ - from cacode_framework.exception import e_fields - from cacode_framework.util.Log import CACodeLog + from summer.exception import e_fields + from summer.util.Log import CACodeLog if len(target_names) == 0: return module diff --git a/cacode_framework/util/DBPool/__init__.py b/summer/util/DBPool/__init__.py similarity index 100% rename from cacode_framework/util/DBPool/__init__.py rename to summer/util/DBPool/__init__.py diff --git a/cacode_framework/util/DBPool/persistent_db.py b/summer/util/DBPool/persistent_db.py similarity index 100% rename from cacode_framework/util/DBPool/persistent_db.py rename to summer/util/DBPool/persistent_db.py diff --git a/cacode_framework/util/DBPool/persistent_pg.py b/summer/util/DBPool/persistent_pg.py similarity index 100% rename from cacode_framework/util/DBPool/persistent_pg.py rename to summer/util/DBPool/persistent_pg.py diff --git a/cacode_framework/util/DBPool/pooled_db.py b/summer/util/DBPool/pooled_db.py similarity index 100% rename from cacode_framework/util/DBPool/pooled_db.py rename to summer/util/DBPool/pooled_db.py diff --git a/cacode_framework/util/DBPool/pooled_pg.py b/summer/util/DBPool/pooled_pg.py similarity index 100% rename from cacode_framework/util/DBPool/pooled_pg.py rename to summer/util/DBPool/pooled_pg.py diff --git a/cacode_framework/util/DBPool/simple_pooled_db.py b/summer/util/DBPool/simple_pooled_db.py similarity index 100% rename from cacode_framework/util/DBPool/simple_pooled_db.py rename to summer/util/DBPool/simple_pooled_db.py diff --git a/cacode_framework/util/DBPool/simple_pooled_pg.py b/summer/util/DBPool/simple_pooled_pg.py similarity index 100% rename from cacode_framework/util/DBPool/simple_pooled_pg.py rename to summer/util/DBPool/simple_pooled_pg.py diff --git a/cacode_framework/util/DBPool/steady_db.py b/summer/util/DBPool/steady_db.py similarity index 100% rename from cacode_framework/util/DBPool/steady_db.py rename to summer/util/DBPool/steady_db.py diff --git a/cacode_framework/util/DBPool/steady_pg.py b/summer/util/DBPool/steady_pg.py similarity index 100% rename from cacode_framework/util/DBPool/steady_pg.py rename to summer/util/DBPool/steady_pg.py diff --git a/cacode_framework/util/Log.py b/summer/util/Log.py similarity index 98% rename from cacode_framework/util/Log.py rename to summer/util/Log.py index eaa748c..ee6ae41 100644 --- a/cacode_framework/util/Log.py +++ b/summer/util/Log.py @@ -4,8 +4,8 @@ import re import sys import time import threading -from cacode_framework.cacode.Modes import Singleton -from cacode_framework.exception import e_fields +from summer.cacode.Modes import Singleton +from summer.exception import e_fields class FieldsLength: diff --git a/cacode_framework/util/ParseUtil.py b/summer/util/ParseUtil.py similarity index 98% rename from cacode_framework/util/ParseUtil.py rename to summer/util/ParseUtil.py index 169f8db..89442a1 100644 --- a/cacode_framework/util/ParseUtil.py +++ b/summer/util/ParseUtil.py @@ -2,9 +2,9 @@ import copy from typing import List -from ..exception.e_fields import FieldNotExist -from ..pojoManager import tag -from ..util.Log import CACodeLog +from summer.exception import FieldNotExist +from summer.pojoManager import tag +from summer.util.Log import CACodeLog class ParseUtil(object): diff --git a/cacode_framework/pojoManager/__init__.py b/summer/util/__init__.py similarity index 100% rename from cacode_framework/pojoManager/__init__.py rename to summer/util/__init__.py diff --git a/cacode_framework/MainWork/CACodeAopContainer.py b/summer/work/AopContainer.py similarity index 99% rename from cacode_framework/MainWork/CACodeAopContainer.py rename to summer/work/AopContainer.py index d420051..c5d6dcb 100644 --- a/cacode_framework/MainWork/CACodeAopContainer.py +++ b/summer/work/AopContainer.py @@ -1,6 +1,6 @@ import types -from ..opera.CompulsoryRun import Compulsory +from summer.util.CompulsoryRun import Compulsory class AopModelObject(object): diff --git a/cacode_framework/MainWork/CACodeConfig.py b/summer/work/Config.py similarity index 90% rename from cacode_framework/MainWork/CACodeConfig.py rename to summer/work/Config.py index aeec07f..9d3f9b0 100644 --- a/cacode_framework/MainWork/CACodeConfig.py +++ b/summer/work/Config.py @@ -1,8 +1,8 @@ -from .CACodeAdapter import LanguageAdapter -from ..cacode.Serialize import JsonUtil -from ..exception.e_fields import FieldNotExist -from ..util.Log import CACodeLog -from ..util.ParseUtil import ParseUtil +from SummerAdapter import LanguageAdapter +from summer.cacode.Serialize import JsonUtil +from summer.exception import FieldNotExist +from summer.util.Log import CACodeLog +from summer.util.ParseUtil import ParseUtil class Conf(ParseUtil): diff --git a/cacode_framework/MainWork/CACodeAdapter.py b/summer/work/SummerAdapter.py similarity index 100% rename from cacode_framework/MainWork/CACodeAdapter.py rename to summer/work/SummerAdapter.py diff --git a/cacode_framework/MainWork/__init__.py b/summer/work/__init__.py similarity index 100% rename from cacode_framework/MainWork/__init__.py rename to summer/work/__init__.py diff --git a/cacode_framework/MainWork/CACodePureORM.py b/summer/work/orm.py similarity index 99% rename from cacode_framework/MainWork/CACodePureORM.py rename to summer/work/orm.py index 8b8daf4..e5b5b77 100644 --- a/cacode_framework/MainWork/CACodePureORM.py +++ b/summer/work/orm.py @@ -1,5 +1,5 @@ -from ..exception import e_fields -from ..util.Log import CACodeLog +from summer.exception import e_fields +from summer.util.Log import CACodeLog class CACodePureORM(object): diff --git a/cacode_framework/MainWork/CACodeRepository.py b/summer/work/repository.py similarity index 91% rename from cacode_framework/MainWork/CACodeRepository.py rename to summer/work/repository.py index 33628cc..12c8186 100644 --- a/cacode_framework/MainWork/CACodeRepository.py +++ b/summer/work/repository.py @@ -1,13 +1,12 @@ import copy -from ..cacode.Serialize import QuerySet -from ..exception import e_fields -from ..field import MySqlDefault -from ..opera import op_db -from ..util.Log import CACodeLog +from summer.cacode.Serialize import QuerySet +from summer.exception import e_fields +from summer.field import MySqlDefault +from summer.opera import op_db, global_db +from summer.util.Log import CACodeLog -from ..MainWork.CACodePureORM import CACodePureORM -from ..util import DbUtil +from summer.work.orm import CACodePureORM # 每个任务唯一ID import uuid @@ -103,15 +102,15 @@ class Repository: ParseUtil.set_field_compulsory(self, key='sqlFields', data=kwargs, val=MySqlDefault.MySqlFields_Default()) # 连接池 if hasattr(self, 'config_obj') and self.config_obj: - self.db_util = DbUtil.Db_opera(host=ParseUtil.fieldExist(self.config_obj, 'host'), - port=ParseUtil.fieldExist(self.config_obj, 'port'), - user=ParseUtil.fieldExist(self.config_obj, 'user'), - password=ParseUtil.fieldExist(self.config_obj, 'password'), - database=ParseUtil.fieldExist(self.config_obj, 'database'), - charset=ParseUtil.fieldExist(self.config_obj, 'charset'), - creator=ParseUtil.fieldExist(self.config_obj, 'creator', - raise_exception=True), - POOL=None if 'POOL' not in kwargs.keys() else kwargs['POOL']) + self.db_util = global_db.Db_opera(host=ParseUtil.fieldExist(self.config_obj, 'host'), + port=ParseUtil.fieldExist(self.config_obj, 'port'), + user=ParseUtil.fieldExist(self.config_obj, 'user'), + password=ParseUtil.fieldExist(self.config_obj, 'password'), + database=ParseUtil.fieldExist(self.config_obj, 'database'), + charset=ParseUtil.fieldExist(self.config_obj, 'charset'), + creator=ParseUtil.fieldExist(self.config_obj, 'creator', + raise_exception=True), + POOL=None if 'POOL' not in kwargs.keys() else kwargs['POOL']) else: CACodeLog.err(AttributeError, e_fields.Miss_Attr('`config_obj` is missing')) diff --git a/test/modules/DatabaseConf.py b/test/modules/DatabaseConf.py index 4806b6b..ee6c1bb 100644 --- a/test/modules/DatabaseConf.py +++ b/test/modules/DatabaseConf.py @@ -1,8 +1,8 @@ import pymssql import pymysql -from cacode_framework.MainWork import CACodeConfig -from cacode_framework.MainWork.CACodeAdapter import LanguageAdapter +from summer.work import Config +from summer.work.SummerAdapter import LanguageAdapter class Adapter(LanguageAdapter): @@ -16,7 +16,7 @@ class Adapter(LanguageAdapter): self._like_opera(instance, key, value) -class MySqlConfig(CACodeConfig.Conf): +class MySqlConfig(Config.Conf): def __init__(self, host='localhost', port=3306, @@ -31,7 +31,7 @@ class MySqlConfig(CACodeConfig.Conf): adapter=Adapter()) -class SqlServerConfig(CACodeConfig.Conf): +class SqlServerConfig(Config.Conf): def __init__(self, host='localhsot', port=1433, diff --git a/test/modules/MySqlTest.py b/test/modules/MySqlTest.py index a511ca7..6d530c8 100644 --- a/test/modules/MySqlTest.py +++ b/test/modules/MySqlTest.py @@ -1,8 +1,8 @@ import datetime -from cacode_framework.anno.annos import Table, Select -from cacode_framework.pojoManager import Manage -from cacode_framework.pojoManager.Manage import Pojo +from summer.anno.annos import Table, Select +from summer.pojoManager import Manage +from summer.pojoManager.Manage import Pojo from test.modules.DatabaseConf import MySqlConfig diff --git a/test/modules/SqlServerTest.py b/test/modules/SqlServerTest.py index d66ef14..245d1cb 100644 --- a/test/modules/SqlServerTest.py +++ b/test/modules/SqlServerTest.py @@ -3,9 +3,9 @@ # @Author: CACode # @File: SqlServerTest.py # @Software: PyCharm -from cacode_framework.anno.annos import Table -from cacode_framework.pojoManager import Manage -from cacode_framework.pojoManager.Manage import Pojo +from summer.anno.annos import Table +from summer.pojoManager import Manage +from summer.pojoManager.Manage import Pojo from test.modules.DatabaseConf import SqlServerConfig diff --git a/test/testFunc.py b/test/testFunc.py index 259b4f3..844c433 100644 --- a/test/testFunc.py +++ b/test/testFunc.py @@ -7,8 +7,8 @@ Description: Update Test ''' import time -from cacode_framework.cacode.Factory import Factory -from cacode_framework.util.Log import CACodeLog +from summer.cacode.Factory import Factory +from summer.util.Log import CACodeLog class MyFactory(Factory): @@ -40,9 +40,9 @@ def TestMySql(): # page = result.page(7) # result = page.to_dict() result = demoTable.orm.find().where(t_id__in=[1, 2, 3, 4, 5, 6, 7, 8, 9]) - r_2 = d_2.orm.find(poly=[' FROM ']) - var = r_2 << result - info(var.append(' a').end()) + # r_2 = d_2.orm.find(poly=[' FROM ']) + # var = r_2 << result + info(result.append(' a').end()) # info(result.to_json(True)) # info(f'count:{len(result)}') info(f'application run time:{time.time() - t}') -- Gitee From 22652aaf866ae664b30664cb8d34a90d853ebafe Mon Sep 17 00:00:00 2001 From: CACode Date: Thu, 20 May 2021 00:13:52 +0800 Subject: [PATCH 14/26] updateRRADME.md --- .gitignore | 7 +++---- README.md | 41 ++++++++++++++++++++++++++++++++++------- imgs/lct.png | Bin 35815 -> 46275 bytes imgs/summer_tr.png | Bin 0 -> 844101 bytes 4 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 imgs/summer_tr.png diff --git a/.gitignore b/.gitignore index a57e2e7..e7d7c34 100644 --- a/.gitignore +++ b/.gitignore @@ -3,12 +3,11 @@ __pycache__/ #upload.bat #pyproject.toml #delete.py -#*.pyc -#venv +*.pyc +venv .pypirc build cacode_framework.egg-info dist upload.bat -pyproject.toml -.pypirc \ No newline at end of file +pyproject.toml \ No newline at end of file diff --git a/README.md b/README.md index 944c20a..33d2f78 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,52 @@ -

Welcome to CACodeFramework 👋

-

+

+ +

+

Welcome to Summer Framework 👋

+

Version Documentation - License: MIT + License: MIT

# 安装 -> pip命令:pip install CACodeFramework +> pip命令:pip install summer-framework ## 先决条件 -- python >=3.6 - +> python >=3.6 +> 基础的sql知识 > 教程文档地址:http://doc.cacode.ren -# CACode +# 它是如何运作的 + +![](./imgs/lct.png) + +# 适用场景 + +```text +经过测试,目前稳定运行于Django、Flask、FastApi、web2py。支持非任何架构的原生python, +可通过任何形式使用。不局限于已创建的对象,可动态加载数据库和数据表 +``` + +# 优点 + +```text +适配市面上所有基于DB-API2规范的数据库创建者,MySql承受100万次插入最快可达19秒。 +内部代码使用中文注释,阅读源码不费力 +``` + +# 内置 + +```text +内置json解析器和数据库连接池,带有缓存机制,能够在极大程度减少对数据库的压力 +``` + +# CACode Development Team !['CACode Development Team'](./imgs/icon_dev.png) diff --git a/imgs/lct.png b/imgs/lct.png index cbd6c8339351a6dced8eadc71b96c9d7ce962ef5..2e19c6c4d655a9cc6962055d7615420d5496fd44 100644 GIT binary patch literal 46275 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�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 diff --git a/imgs/summer_tr.png b/imgs/summer_tr.png new file mode 100644 index 0000000000000000000000000000000000000000..186eb045fe4c771404c024f74339c080e1c943b0 GIT binary patch literal 844101 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 Date: Thu, 20 May 2021 00:14:52 +0800 Subject: [PATCH 15/26] On branch main --- .gitignore | 1 - .pypirc | 7 ------- 2 files changed, 8 deletions(-) delete mode 100644 .pypirc diff --git a/.gitignore b/.gitignore index e7d7c34..c0a9c5e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ __pycache__/ #delete.py *.pyc venv -.pypirc build cacode_framework.egg-info dist diff --git a/.pypirc b/.pypirc deleted file mode 100644 index 9976367..0000000 --- a/.pypirc +++ /dev/null @@ -1,7 +0,0 @@ -[distutils] -index-servers = - pypi - -[pypi] -username:CACode -password:a18027503001 -- Gitee From a6db4f34c38e3552522b038814e904f76c90af01 Mon Sep 17 00:00:00 2001 From: CACode Date: Thu, 20 May 2021 00:40:32 +0800 Subject: [PATCH 16/26] On branch main --- .gitignore | 3 +- README.md | 6 +- pypi.md | 48 +++++++++++++ setup.py | 2 +- summer/work/Config.py | 2 +- summer_framework.egg-info/PKG-INFO | 68 +++++++++++++++++++ summer_framework.egg-info/SOURCES.txt | 60 ++++++++++++++++ .../dependency_links.txt | 1 + summer_framework.egg-info/top_level.txt | 2 + test/testFunc.py | 2 +- upload.bat | 3 +- 11 files changed, 188 insertions(+), 9 deletions(-) create mode 100644 pypi.md create mode 100644 summer_framework.egg-info/PKG-INFO create mode 100644 summer_framework.egg-info/SOURCES.txt create mode 100644 summer_framework.egg-info/dependency_links.txt create mode 100644 summer_framework.egg-info/top_level.txt diff --git a/.gitignore b/.gitignore index c0a9c5e..7a1f550 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ build cacode_framework.egg-info dist upload.bat -pyproject.toml \ No newline at end of file +pyproject.toml +*.pypirc \ No newline at end of file diff --git a/README.md b/README.md index 33d2f78..f98ea74 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,11 @@

Version - + Documentation - - License: MIT + + License: Apache

diff --git a/pypi.md b/pypi.md new file mode 100644 index 0000000..6b28188 --- /dev/null +++ b/pypi.md @@ -0,0 +1,48 @@ +

+ +

+

Welcome to Summer Framework 👋

+

+ Version + + + Documentation + + + License: Apache + +

+ +# 安装 + +> pip命令:pip install summer-framework + +## 先决条件 + +> python >=3.6 +> 基础的sql知识 +> 教程文档地址:http://doc.cacode.ren + +# 适用场景 + +```text +经过测试,目前稳定运行于Django、Flask、FastApi、web2py。支持非任何架构的原生python, +可通过任何形式使用。不局限于已创建的对象,可动态加载数据库和数据表 +``` + +# 优点 + +```text +适配市面上所有基于DB-API2规范的数据库创建者,MySql承受100万次插入最快可达19秒。 +内部代码使用中文注释,阅读源码不费力 +``` + +# 内置 + +```text +内置json解析器和数据库连接池,带有缓存机制,能够在极大程度减少对数据库的压力 +``` + +# CACode Development Team + +!['CACode Development Team'](./imgs/icon_dev.png) diff --git a/setup.py b/setup.py index 5ef218c..79d2232 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ setuptools.setup( project_urls={ "Bug Tracker": "https://gitee.com/cacode_cctvadmin/summer-python/issues", }, - license=' GPL-3.0', + license=' Apache License 2.0', classifiers=[ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", diff --git a/summer/work/Config.py b/summer/work/Config.py index 9d3f9b0..5113ca5 100644 --- a/summer/work/Config.py +++ b/summer/work/Config.py @@ -1,8 +1,8 @@ -from SummerAdapter import LanguageAdapter from summer.cacode.Serialize import JsonUtil from summer.exception import FieldNotExist from summer.util.Log import CACodeLog from summer.util.ParseUtil import ParseUtil +from summer.work.SummerAdapter import LanguageAdapter class Conf(ParseUtil): diff --git a/summer_framework.egg-info/PKG-INFO b/summer_framework.egg-info/PKG-INFO new file mode 100644 index 0000000..f8b5baf --- /dev/null +++ b/summer_framework.egg-info/PKG-INFO @@ -0,0 +1,68 @@ +Metadata-Version: 2.1 +Name: summer-framework +Version: 1.0.0 +Summary: Summer framework for Python,You can see:https://gitee.com/cacode_cctvadmin/summer-python +Home-page: https://gitee.com/cacode_cctvadmin/summer-python +Author: CACode +Author-email: cacode@163.com +License: Apache License 2.0 +Project-URL: Bug Tracker, https://gitee.com/cacode_cctvadmin/summer-python/issues +Description:

+ +

+

Welcome to Summer Framework 👋

+

+ Version + + + Documentation + + + License: Apache + +

+ + # 安装 + + > pip命令:pip install summer-framework + + ## 先决条件 + + > python >=3.6 + > 基础的sql知识 + > 教程文档地址:http://doc.cacode.ren + + # 它是如何运作的 + + ![](./imgs/lct.png) + + # 适用场景 + + ```text + 经过测试,目前稳定运行于Django、Flask、FastApi、web2py。支持非任何架构的原生python, + 可通过任何形式使用。不局限于已创建的对象,可动态加载数据库和数据表 + ``` + + # 优点 + + ```text + 适配市面上所有基于DB-API2规范的数据库创建者,MySql承受100万次插入最快可达19秒。 + 内部代码使用中文注释,阅读源码不费力 + ``` + + # 内置 + + ```text + 内置json解析器和数据库连接池,带有缓存机制,能够在极大程度减少对数据库的压力 + ``` + + # CACode Development Team + + !['CACode Development Team'](./imgs/icon_dev.png) + +Platform: UNKNOWN +Classifier: Programming Language :: Python :: 3 +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Requires-Python: >=3.6 +Description-Content-Type: text/markdown diff --git a/summer_framework.egg-info/SOURCES.txt b/summer_framework.egg-info/SOURCES.txt new file mode 100644 index 0000000..67d6c7d --- /dev/null +++ b/summer_framework.egg-info/SOURCES.txt @@ -0,0 +1,60 @@ +README.md +pyproject.toml +setup.py +summer/__init__.py +summer/anno/__init__.py +summer/anno/annos.py +summer/cacode/Factory.py +summer/cacode/Modes.py +summer/cacode/Serialize.py +summer/cacode/__init__.py +summer/cacode/ReviewJson/JSON.py +summer/cacode/ReviewJson/__init__.py +summer/cacode/ReviewJson/compat.py +summer/cacode/ReviewJson/decoder.py +summer/cacode/ReviewJson/encoder.py +summer/cacode/ReviewJson/errors.py +summer/cacode/ReviewJson/ordered_dict.py +summer/cacode/ReviewJson/raw_json.py +summer/cacode/ReviewJson/scanner.py +summer/cacode/ReviewJson/tool.py +summer/exception/__init__.py +summer/exception/e_fields.py +summer/field/FManage.py +summer/field/MySqlDefault.py +summer/field/__init__.py +summer/opera/__init__.py +summer/opera/global_db.py +summer/opera/op_db.py +summer/pojoManager/Manage.py +summer/pojoManager/__init__.py +summer/pojoManager/tag.py +summer/util/CompulsoryRun.py +summer/util/Log.py +summer/util/ParseUtil.py +summer/util/__init__.py +summer/util/DBPool/__init__.py +summer/util/DBPool/persistent_db.py +summer/util/DBPool/persistent_pg.py +summer/util/DBPool/pooled_db.py +summer/util/DBPool/pooled_pg.py +summer/util/DBPool/simple_pooled_db.py +summer/util/DBPool/simple_pooled_pg.py +summer/util/DBPool/steady_db.py +summer/util/DBPool/steady_pg.py +summer/work/AopContainer.py +summer/work/Config.py +summer/work/SummerAdapter.py +summer/work/__init__.py +summer/work/orm.py +summer/work/repository.py +summer_framework.egg-info/PKG-INFO +summer_framework.egg-info/SOURCES.txt +summer_framework.egg-info/dependency_links.txt +summer_framework.egg-info/top_level.txt +test/__init__.py +test/testFunc.py +test/modules/DatabaseConf.py +test/modules/MySqlTest.py +test/modules/SqlServerTest.py +test/modules/__init__.py \ No newline at end of file diff --git a/summer_framework.egg-info/dependency_links.txt b/summer_framework.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/summer_framework.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/summer_framework.egg-info/top_level.txt b/summer_framework.egg-info/top_level.txt new file mode 100644 index 0000000..b2e08ca --- /dev/null +++ b/summer_framework.egg-info/top_level.txt @@ -0,0 +1,2 @@ +summer +test diff --git a/test/testFunc.py b/test/testFunc.py index 844c433..efc07aa 100644 --- a/test/testFunc.py +++ b/test/testFunc.py @@ -42,7 +42,7 @@ def TestMySql(): result = demoTable.orm.find().where(t_id__in=[1, 2, 3, 4, 5, 6, 7, 8, 9]) # r_2 = d_2.orm.find(poly=[' FROM ']) # var = r_2 << result - info(result.append(' a').end()) + info(result.end()) # info(result.to_json(True)) # info(f'count:{len(result)}') info(f'application run time:{time.time() - t}') diff --git a/upload.bat b/upload.bat index 2afd370..befbad9 100644 --- a/upload.bat +++ b/upload.bat @@ -1,3 +1,2 @@ -python setup.py sdist -python setup.py bdist_wheel +python setup.py sdist bdist_wheel twine upload dist/* \ No newline at end of file -- Gitee From 86cd5efcaa35f864978d3b03768a8d4b02b5b0be Mon Sep 17 00:00:00 2001 From: CACode <54068986+cctvadmin@users.noreply.github.com> Date: Thu, 20 May 2021 18:14:51 +0800 Subject: [PATCH 17/26] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=8C=96=E5=99=A8=E6=97=A0=E6=B3=95=E5=BF=BD=E7=95=A5=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E5=A2=9E=E5=8A=A0=E5=AD=97=E6=AE=B5=EF=BC=8C=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E7=BA=BF=E7=A8=8B=E6=B1=A0=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- setup.py | 2 +- summer/cacode/Serialize.py | 21 +----- summer/{pojoManager => field}/tag.py | 0 summer/opera/op_db.py | 9 +-- summer/pojoManager/__init__.py | 0 summer/util/Log.py | 29 +++++--- summer/util/ParseUtil.py | 2 +- summer/{pojoManager => work}/Manage.py | 7 +- summer_framework.egg-info/PKG-INFO | 68 ------------------- summer_framework.egg-info/SOURCES.txt | 60 ---------------- .../dependency_links.txt | 1 - summer_framework.egg-info/top_level.txt | 2 - test/modules/MySqlTest.py | 5 +- test/modules/SqlServerTest.py | 9 ++- test/t_thread_pool/__init__.py | 23 +++++++ test/testFunc.py | 5 +- 17 files changed, 67 insertions(+), 178 deletions(-) rename summer/{pojoManager => field}/tag.py (100%) delete mode 100644 summer/pojoManager/__init__.py rename summer/{pojoManager => work}/Manage.py (98%) delete mode 100644 summer_framework.egg-info/PKG-INFO delete mode 100644 summer_framework.egg-info/SOURCES.txt delete mode 100644 summer_framework.egg-info/dependency_links.txt delete mode 100644 summer_framework.egg-info/top_level.txt create mode 100644 test/t_thread_pool/__init__.py diff --git a/.gitignore b/.gitignore index 7a1f550..f2b22cb 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ __pycache__/ *.pyc venv build -cacode_framework.egg-info +summer_framework.egg-info dist upload.bat pyproject.toml diff --git a/setup.py b/setup.py index 79d2232..9c07803 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh: setuptools.setup( name="summer_framework", - version="1.0.0", + version="1.0.0pre1", author="CACode", author_email="cacode@163.com", description="Summer framework for Python,You can see:https://gitee.com/cacode_cctvadmin/summer-python", diff --git a/summer/cacode/Serialize.py b/summer/cacode/Serialize.py index 49e188f..a837b1f 100644 --- a/summer/cacode/Serialize.py +++ b/summer/cacode/Serialize.py @@ -267,20 +267,8 @@ class QuerySet(list): list.__init__([]) if query_items is None: self.__instance__ = instance - - self.__using_fields__ = self.__instance__.getFields() - self.__all_using_fields__ = JsonUtil.parse( - obj=self.__instance__, end_load=True) - - self.__ignore_field__ = {} - self.__append_field__ = {} # 合并结果集对象 self.extend(base_data) - # for i in base_data: - # self.append(i) - # self.append( - # QueryItem(data_item=i, using_fields=self.__using_fields__, append_field=self.__append_field__, - # ignore_field=self.__ignore_field__)) else: self.extend(query_items) @@ -322,19 +310,14 @@ class QuerySet(list): """ 添加一个不会被解析忽略的字段 """ - if key not in self.__append_field__.keys() and \ - key not in self.__using_fields__.keys() and \ - key not in self.__all_using_fields__.keys(): - self.__append_field__[key] = default_value - else: - CACodeLog.log(obj=self, msg='`{}` already exists'.format(key)) + [self[i].add_field(key, default_value) for i in range(len(self))] def remove_field(self, key): """ 添加一个会被解析忽略的字段 """ - self.__ignore_field__[key] = None + [self[i].remove_field(key) for i in range(len(self))] def get(self, index): """ diff --git a/summer/pojoManager/tag.py b/summer/field/tag.py similarity index 100% rename from summer/pojoManager/tag.py rename to summer/field/tag.py diff --git a/summer/opera/op_db.py b/summer/opera/op_db.py index d624e38..38f5848 100644 --- a/summer/opera/op_db.py +++ b/summer/opera/op_db.py @@ -33,12 +33,13 @@ class DbOperation(object): # _kw = JsonUtil.load(JsonUtil.parse(_lock)) _kw = _lock.__dict__ kwargs.update(_kw) - _t = threading.Thread(target=func, args=args, kwargs=kwargs, name=name) - _t.start() + from concurrent.futures import ThreadPoolExecutor + pool = ThreadPoolExecutor() + _t = pool.submit(fn=func, *args, **kwargs) + # _t = threading.Thread(target=func, args=args, kwargs=kwargs, name=name) if not _lock.close_log: CACodeLog.log(obj=_t, msg='TASK-{} RUNNING'.format(name), task_name=name, LogObject=kwargs['log_obj']) - # 等待任务完成 - _t.join() + result = _t.result() # 返回结果 return self.result diff --git a/summer/pojoManager/__init__.py b/summer/pojoManager/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/summer/util/Log.py b/summer/util/Log.py index ee6ae41..f4d3713 100644 --- a/summer/util/Log.py +++ b/summer/util/Log.py @@ -81,12 +81,16 @@ class ConsoleColor: class ConsoleWrite: + def __init__(self): + self.fontColor = ConsoleColor.FontColor.WHITE + self.showType = ConsoleColor.ShowType.DEFAULT + self.backColor = None @staticmethod - def write(messages, fontColor=ConsoleColor.FontColor.WHITE, backColor=None, showType=ConsoleColor.ShowType.DEFAULT): - prefix = "{};".format(showType) if showType is not None else "" - center = ";".format(backColor) if backColor is not None else "" - suffix = "{}m{}".format(fontColor, messages) + def write(messages, consoleWriteObj): + prefix = "{};".format(consoleWriteObj.showType) if consoleWriteObj.showType is not None else "" + center = ";".format(consoleWriteObj.backColor) if consoleWriteObj.backColor is not None else "" + suffix = "{}m{}".format(consoleWriteObj.fontColor, messages) out = "\033[{}{}{}\033[0m".format(prefix, center, suffix) print(out) @@ -158,8 +162,7 @@ class CACodeLog(object): @staticmethod def log(msg, obj=None, line=sys._getframe().f_back.f_lineno, operation_name=e_fields.Log_Opera_Name("Task"), task_name='Task', LogObject=None, field=e_fields.Info(), func=None, - fontColor=ConsoleColor.FontColor.SUCCESS_COLOR, - showType=ConsoleColor.ShowType.HIGHLIGHT): + consoleWriteObj=ConsoleWrite()): """ 输出任务执行日志 @@ -210,7 +213,7 @@ class CACodeLog(object): info = "{}{}{}{}{}{}{}{}".format(t, field, line, operation_name, hex_id, write_repr, task_name, msg) - ConsoleWrite.write(messages=info, fontColor=fontColor, showType=showType) + ConsoleWrite.write(messages=info, consoleWriteObj=consoleWriteObj) # 输出日志信息 # file = sys.stdout # file.write(info) @@ -226,9 +229,13 @@ class CACodeLog(object): @staticmethod def warning(msg, obj=None, line=sys._getframe().f_back.f_lineno, task_name='Task', LogObject=None): + + consoleWrite = ConsoleWrite() + consoleWrite.fontColor = ConsoleColor.FontColor.WARNING_COLOR + CACodeLog.log(msg=msg, obj=obj, line=line, task_name=task_name, LogObject=LogObject, field=e_fields.Warn(), func=LogObject.warn if LogObject is not None else None, - fontColor=ConsoleColor.FontColor.WARNING_COLOR) + consoleWriteObj=consoleWrite) @staticmethod def log_error(msg, obj=None, line=sys._getframe().f_back.f_lineno, task_name='Task', LogObject=None, @@ -243,9 +250,13 @@ class CACodeLog(object): """ if raise_exception: raise obj(msg) + + consoleWrite = ConsoleWrite() + consoleWrite.fontColor = ConsoleColor.FontColor.ERROR_COLOR + CACodeLog.log(msg=msg, obj=obj, line=line, task_name=task_name, LogObject=LogObject, field=e_fields.Error(), func=LogObject.warn if LogObject is not None else None, - fontColor=ConsoleColor.FontColor.ERROR_COLOR) + consoleWriteObj=consoleWrite) @staticmethod def err(cls, msg, LogObject=None): diff --git a/summer/util/ParseUtil.py b/summer/util/ParseUtil.py index 89442a1..418a9f7 100644 --- a/summer/util/ParseUtil.py +++ b/summer/util/ParseUtil.py @@ -3,7 +3,7 @@ import copy from typing import List from summer.exception import FieldNotExist -from summer.pojoManager import tag +from summer.field import tag from summer.util.Log import CACodeLog diff --git a/summer/pojoManager/Manage.py b/summer/work/Manage.py similarity index 98% rename from summer/pojoManager/Manage.py rename to summer/work/Manage.py index 60ea2a2..0c505e5 100644 --- a/summer/pojoManager/Manage.py +++ b/summer/work/Manage.py @@ -1,6 +1,9 @@ -from summer.work.orm import CACodePureORM +__all__ = ['Pojo', 'tag'] +__version__ = '1.0.0pre1' + from summer.cacode.Serialize import QuerySet -from summer.pojoManager import tag +from summer.work.orm import CACodePureORM +from summer.field import tag from summer.cacode.Serialize import JsonUtil from summer.work import repository from summer.util.Log import CACodeLog diff --git a/summer_framework.egg-info/PKG-INFO b/summer_framework.egg-info/PKG-INFO deleted file mode 100644 index f8b5baf..0000000 --- a/summer_framework.egg-info/PKG-INFO +++ /dev/null @@ -1,68 +0,0 @@ -Metadata-Version: 2.1 -Name: summer-framework -Version: 1.0.0 -Summary: Summer framework for Python,You can see:https://gitee.com/cacode_cctvadmin/summer-python -Home-page: https://gitee.com/cacode_cctvadmin/summer-python -Author: CACode -Author-email: cacode@163.com -License: Apache License 2.0 -Project-URL: Bug Tracker, https://gitee.com/cacode_cctvadmin/summer-python/issues -Description:

- -

-

Welcome to Summer Framework 👋

-

- Version - - - Documentation - - - License: Apache - -

- - # 安装 - - > pip命令:pip install summer-framework - - ## 先决条件 - - > python >=3.6 - > 基础的sql知识 - > 教程文档地址:http://doc.cacode.ren - - # 它是如何运作的 - - ![](./imgs/lct.png) - - # 适用场景 - - ```text - 经过测试,目前稳定运行于Django、Flask、FastApi、web2py。支持非任何架构的原生python, - 可通过任何形式使用。不局限于已创建的对象,可动态加载数据库和数据表 - ``` - - # 优点 - - ```text - 适配市面上所有基于DB-API2规范的数据库创建者,MySql承受100万次插入最快可达19秒。 - 内部代码使用中文注释,阅读源码不费力 - ``` - - # 内置 - - ```text - 内置json解析器和数据库连接池,带有缓存机制,能够在极大程度减少对数据库的压力 - ``` - - # CACode Development Team - - !['CACode Development Team'](./imgs/icon_dev.png) - -Platform: UNKNOWN -Classifier: Programming Language :: Python :: 3 -Classifier: License :: OSI Approved :: MIT License -Classifier: Operating System :: OS Independent -Requires-Python: >=3.6 -Description-Content-Type: text/markdown diff --git a/summer_framework.egg-info/SOURCES.txt b/summer_framework.egg-info/SOURCES.txt deleted file mode 100644 index 67d6c7d..0000000 --- a/summer_framework.egg-info/SOURCES.txt +++ /dev/null @@ -1,60 +0,0 @@ -README.md -pyproject.toml -setup.py -summer/__init__.py -summer/anno/__init__.py -summer/anno/annos.py -summer/cacode/Factory.py -summer/cacode/Modes.py -summer/cacode/Serialize.py -summer/cacode/__init__.py -summer/cacode/ReviewJson/JSON.py -summer/cacode/ReviewJson/__init__.py -summer/cacode/ReviewJson/compat.py -summer/cacode/ReviewJson/decoder.py -summer/cacode/ReviewJson/encoder.py -summer/cacode/ReviewJson/errors.py -summer/cacode/ReviewJson/ordered_dict.py -summer/cacode/ReviewJson/raw_json.py -summer/cacode/ReviewJson/scanner.py -summer/cacode/ReviewJson/tool.py -summer/exception/__init__.py -summer/exception/e_fields.py -summer/field/FManage.py -summer/field/MySqlDefault.py -summer/field/__init__.py -summer/opera/__init__.py -summer/opera/global_db.py -summer/opera/op_db.py -summer/pojoManager/Manage.py -summer/pojoManager/__init__.py -summer/pojoManager/tag.py -summer/util/CompulsoryRun.py -summer/util/Log.py -summer/util/ParseUtil.py -summer/util/__init__.py -summer/util/DBPool/__init__.py -summer/util/DBPool/persistent_db.py -summer/util/DBPool/persistent_pg.py -summer/util/DBPool/pooled_db.py -summer/util/DBPool/pooled_pg.py -summer/util/DBPool/simple_pooled_db.py -summer/util/DBPool/simple_pooled_pg.py -summer/util/DBPool/steady_db.py -summer/util/DBPool/steady_pg.py -summer/work/AopContainer.py -summer/work/Config.py -summer/work/SummerAdapter.py -summer/work/__init__.py -summer/work/orm.py -summer/work/repository.py -summer_framework.egg-info/PKG-INFO -summer_framework.egg-info/SOURCES.txt -summer_framework.egg-info/dependency_links.txt -summer_framework.egg-info/top_level.txt -test/__init__.py -test/testFunc.py -test/modules/DatabaseConf.py -test/modules/MySqlTest.py -test/modules/SqlServerTest.py -test/modules/__init__.py \ No newline at end of file diff --git a/summer_framework.egg-info/dependency_links.txt b/summer_framework.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/summer_framework.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/summer_framework.egg-info/top_level.txt b/summer_framework.egg-info/top_level.txt deleted file mode 100644 index b2e08ca..0000000 --- a/summer_framework.egg-info/top_level.txt +++ /dev/null @@ -1,2 +0,0 @@ -summer -test diff --git a/test/modules/MySqlTest.py b/test/modules/MySqlTest.py index 6d530c8..731325e 100644 --- a/test/modules/MySqlTest.py +++ b/test/modules/MySqlTest.py @@ -1,13 +1,12 @@ import datetime from summer.anno.annos import Table, Select -from summer.pojoManager import Manage -from summer.pojoManager.Manage import Pojo +from summer.work import Manage from test.modules.DatabaseConf import MySqlConfig @Table(name='demo_table', msg='') -class DemoTable(Pojo): +class DemoTable(Manage.Pojo): def __init__(self, **kwargs): self.t_id = Manage.tag.intField(auto_field=True, primary_key=True) self.t_name = Manage.tag.varcharField(default='测试name') diff --git a/test/modules/SqlServerTest.py b/test/modules/SqlServerTest.py index 245d1cb..1c29d90 100644 --- a/test/modules/SqlServerTest.py +++ b/test/modules/SqlServerTest.py @@ -4,17 +4,16 @@ # @File: SqlServerTest.py # @Software: PyCharm from summer.anno.annos import Table -from summer.pojoManager import Manage -from summer.pojoManager.Manage import Pojo +from summer.work.Manage import Pojo from test.modules.DatabaseConf import SqlServerConfig @Table(name='testccfk', msg='') class DemoTable(Pojo): def __init__(self, **kwargs): - self.t_id = Manage.tag.intField() - self.t_msg = Manage.tag.intField() - self.create_time = Manage.tag.datetimeField() + self.t_id = summer.field.tag.intField() + self.t_msg = summer.field.tag.intField() + self.create_time = summer.field.tag.datetimeField() super(DemoTable, self).__init__(config_obj=SqlServerConfig(), log_conf={ 'path': "/log/", 'save_flag': True diff --git a/test/t_thread_pool/__init__.py b/test/t_thread_pool/__init__.py new file mode 100644 index 0000000..fd7026b --- /dev/null +++ b/test/t_thread_pool/__init__.py @@ -0,0 +1,23 @@ +import time +from concurrent.futures import ThreadPoolExecutor + + +def fetch_url(url): + print(url) + time.sleep(2) + return url + '-123456' + + +pool = ThreadPoolExecutor() +# Submit work to the pool +a = pool.submit(fetch_url, 'http://www.python.org') +b = pool.submit(fetch_url, 'http://www.pypy.org') + +if __name__ == '__main__': + # Get the results back + x = a.result() + y = b.result() + + print(x) + print(y) + print(1) diff --git a/test/testFunc.py b/test/testFunc.py index efc07aa..d8e29fc 100644 --- a/test/testFunc.py +++ b/test/testFunc.py @@ -39,10 +39,11 @@ def TestMySql(): # result = demoTable.find_by_id(t_id=10) # page = result.page(7) # result = page.to_dict() - result = demoTable.orm.find().where(t_id__in=[1, 2, 3, 4, 5, 6, 7, 8, 9]) + result = demoTable.orm.find().where(t_id__in=[1, 2, 3, 4, 5, 6, 7, 8, 9]).end() + result.remove_field('t_id') # r_2 = d_2.orm.find(poly=[' FROM ']) # var = r_2 << result - info(result.end()) + info(result) # info(result.to_json(True)) # info(f'count:{len(result)}') info(f'application run time:{time.time() - t}') -- Gitee From 198f8af58f2f9c1e627b4d7ca2f4a9b0d8f37620 Mon Sep 17 00:00:00 2001 From: CACode Date: Fri, 21 May 2021 00:24:15 +0800 Subject: [PATCH 18/26] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=8C=96=E5=99=A8=E5=BF=BD=E7=95=A5=E5=85=A8=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 +-- README.md | 2 +- pypi.md | 6 +-- setup.py | 6 +-- summer/{util => opera}/DBPool/__init__.py | 0 .../{util => opera}/DBPool/persistent_db.py | 0 .../{util => opera}/DBPool/persistent_pg.py | 0 summer/{util => opera}/DBPool/pooled_db.py | 0 summer/{util => opera}/DBPool/pooled_pg.py | 0 .../DBPool/simple_pooled_db.py | 0 .../DBPool/simple_pooled_pg.py | 0 summer/{util => opera}/DBPool/steady_db.py | 0 summer/{util => opera}/DBPool/steady_pg.py | 0 summer/opera/global_db.py | 2 +- summer/util/Log.py | 3 +- summer/work/Manage.py | 10 +++-- summer/work/SummerAdapter.py | 41 +++++++++++++++++-- summer/work/orm.py | 31 +++++++++----- summer/work/repository.py | 6 +-- test/testFunc.py | 6 +-- upload.bat | 3 +- 21 files changed, 81 insertions(+), 40 deletions(-) rename summer/{util => opera}/DBPool/__init__.py (100%) rename summer/{util => opera}/DBPool/persistent_db.py (100%) rename summer/{util => opera}/DBPool/persistent_pg.py (100%) rename summer/{util => opera}/DBPool/pooled_db.py (100%) rename summer/{util => opera}/DBPool/pooled_pg.py (100%) rename summer/{util => opera}/DBPool/simple_pooled_db.py (100%) rename summer/{util => opera}/DBPool/simple_pooled_pg.py (100%) rename summer/{util => opera}/DBPool/steady_db.py (100%) rename summer/{util => opera}/DBPool/steady_pg.py (100%) diff --git a/.gitignore b/.gitignore index f2b22cb..418bfe9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,9 @@ .idea __pycache__/ -#upload.bat -#pyproject.toml -#delete.py *.pyc venv build -summer_framework.egg-info +summer_python.egg-info dist upload.bat pyproject.toml diff --git a/README.md b/README.md index f98ea74..6111637 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ # 安装 -> pip命令:pip install summer-framework +> pip命令:pip install summer-python ## 先决条件 diff --git a/pypi.md b/pypi.md index 6b28188..4b09b47 100644 --- a/pypi.md +++ b/pypi.md @@ -15,7 +15,7 @@ # 安装 -> pip命令:pip install summer-framework +> pip命令:pip install summer-python ## 先决条件 @@ -42,7 +42,3 @@ ```text 内置json解析器和数据库连接池,带有缓存机制,能够在极大程度减少对数据库的压力 ``` - -# CACode Development Team - -!['CACode Development Team'](./imgs/icon_dev.png) diff --git a/setup.py b/setup.py index 9c07803..e0d3d80 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,11 @@ import setuptools -with open("README.md", "r", encoding="utf-8") as fh: +with open("pypi.md", "r", encoding="utf-8") as fh: long_description = fh.read() setuptools.setup( - name="summer_framework", - version="1.0.0pre1", + name="summer-python", + version="1.0.0b2", author="CACode", author_email="cacode@163.com", description="Summer framework for Python,You can see:https://gitee.com/cacode_cctvadmin/summer-python", diff --git a/summer/util/DBPool/__init__.py b/summer/opera/DBPool/__init__.py similarity index 100% rename from summer/util/DBPool/__init__.py rename to summer/opera/DBPool/__init__.py diff --git a/summer/util/DBPool/persistent_db.py b/summer/opera/DBPool/persistent_db.py similarity index 100% rename from summer/util/DBPool/persistent_db.py rename to summer/opera/DBPool/persistent_db.py diff --git a/summer/util/DBPool/persistent_pg.py b/summer/opera/DBPool/persistent_pg.py similarity index 100% rename from summer/util/DBPool/persistent_pg.py rename to summer/opera/DBPool/persistent_pg.py diff --git a/summer/util/DBPool/pooled_db.py b/summer/opera/DBPool/pooled_db.py similarity index 100% rename from summer/util/DBPool/pooled_db.py rename to summer/opera/DBPool/pooled_db.py diff --git a/summer/util/DBPool/pooled_pg.py b/summer/opera/DBPool/pooled_pg.py similarity index 100% rename from summer/util/DBPool/pooled_pg.py rename to summer/opera/DBPool/pooled_pg.py diff --git a/summer/util/DBPool/simple_pooled_db.py b/summer/opera/DBPool/simple_pooled_db.py similarity index 100% rename from summer/util/DBPool/simple_pooled_db.py rename to summer/opera/DBPool/simple_pooled_db.py diff --git a/summer/util/DBPool/simple_pooled_pg.py b/summer/opera/DBPool/simple_pooled_pg.py similarity index 100% rename from summer/util/DBPool/simple_pooled_pg.py rename to summer/opera/DBPool/simple_pooled_pg.py diff --git a/summer/util/DBPool/steady_db.py b/summer/opera/DBPool/steady_db.py similarity index 100% rename from summer/util/DBPool/steady_db.py rename to summer/opera/DBPool/steady_db.py diff --git a/summer/util/DBPool/steady_pg.py b/summer/opera/DBPool/steady_pg.py similarity index 100% rename from summer/util/DBPool/steady_pg.py rename to summer/opera/DBPool/steady_pg.py diff --git a/summer/opera/global_db.py b/summer/opera/global_db.py index d412ae2..1d4840e 100644 --- a/summer/opera/global_db.py +++ b/summer/opera/global_db.py @@ -3,7 +3,6 @@ import threading from summer.cacode.Modes import Singleton from summer.exception import DBException -from summer.util.DBPool.pooled_db import PooledDB from summer.util.Log import CACodeLog @@ -135,6 +134,7 @@ class Db_opera(object): 初始化数据库连接池 """ if self.POOL is None: + from summer.opera.DBPool.pooled_db import PooledDB self.POOL = PooledDB(creator=self.creator, maxconnections=self.maxconnections, mincached=self.mincached, maxcached=self.maxcached, maxshared=self.maxshared, diff --git a/summer/util/Log.py b/summer/util/Log.py index f4d3713..70930eb 100644 --- a/summer/util/Log.py +++ b/summer/util/Log.py @@ -82,7 +82,7 @@ class ConsoleColor: class ConsoleWrite: def __init__(self): - self.fontColor = ConsoleColor.FontColor.WHITE + self.fontColor = ConsoleColor.FontColor.GREEN self.showType = ConsoleColor.ShowType.DEFAULT self.backColor = None @@ -212,7 +212,6 @@ class CACodeLog(object): msg = f"\t\t:{msg}" info = "{}{}{}{}{}{}{}{}".format(t, field, line, operation_name, hex_id, write_repr, task_name, msg) - ConsoleWrite.write(messages=info, consoleWriteObj=consoleWriteObj) # 输出日志信息 # file = sys.stdout diff --git a/summer/work/Manage.py b/summer/work/Manage.py index 0c505e5..89db2d8 100644 --- a/summer/work/Manage.py +++ b/summer/work/Manage.py @@ -6,7 +6,6 @@ from summer.work.orm import CACodePureORM from summer.field import tag from summer.cacode.Serialize import JsonUtil from summer.work import repository -from summer.util.Log import CACodeLog class Pojo(repository.Repository): @@ -80,7 +79,8 @@ class Pojo(repository.Repository): new_dict = {} for key in all_fields.keys(): # 当字段为未填充状态时,默认定义为空 - new_dict[key] = getattr(self, key) if hasattr(self, key) else None + new_dict[key] = getattr(self, key) if hasattr(self, key) else all_fields[ + key] if key in all_fields.keys() else None return JsonUtil.parse(new_dict, bf=bf) def to_dict(self): @@ -90,11 +90,15 @@ class Pojo(repository.Repository): return JsonUtil.load(self.to_json()) def getFields(self) -> dict: + """ + 获取当前类所需要序列化的字段 + """ return self.__fields__ def markTable(self): """ 将表生成至外部文件 + TODO:没做,懒得做 """ pass @@ -104,8 +108,6 @@ class Pojo(repository.Repository): """ if key not in self.__append_field__.keys(): self.__append_field__[key] = default_value - else: - CACodeLog.log(obj=self, msg='`{}` already exists'.format(key)) def remove_field(self, key): """ diff --git a/summer/work/SummerAdapter.py b/summer/work/SummerAdapter.py index 46b7cd4..afd6a90 100644 --- a/summer/work/SummerAdapter.py +++ b/summer/work/SummerAdapter.py @@ -11,8 +11,13 @@ class LanguageAdapter: def __init__(self): if not hasattr(self, 'funcs'): self.funcs = {} - self.sp('like', self._like_opera) - self.sp('in', self._in_opera) + self.__sp('like', self._like_opera) + self.__sp('in', self._in_opera) + self.__sp('lt', self._lt_opera) + self.__sp('gt', self._gt_opera) + self.__sp('le', self._le_opera) + self.__sp('ge', self._ge_opera) + self.__sp('eq', self._eq_opera) def _like_opera(self, instance, key, value): instance.args.append('`' + key + '`') @@ -30,6 +35,36 @@ class LanguageAdapter: else: raise AttributeError('value type is not list or QuerySet object') - def sp(self, key, val): + def _lt_opera(self, instance, key, value): + instance.args.append('`' + key + '`') + instance.args.append(' < ') + instance.args.append('%s') + instance.params.append(value) + + def _gt_opera(self, instance, key, value): + instance.args.append('`' + key + '`') + instance.args.append(' > ') + instance.args.append('%s') + instance.params.append(value) + + def _le_opera(self, instance, key, value): + instance.args.append('`' + key + '`') + instance.args.append(' > ') + instance.args.append('%s') + instance.params.append(value) + + def _ge_opera(self, instance, key, value): + instance.args.append('`' + key + '`') + instance.args.append(' > ') + instance.args.append('%s') + instance.params.append(value) + + def _eq_opera(self, instance, key, value): + instance.args.append('`' + key + '`') + instance.args.append(' = ') + instance.args.append('%s') + instance.params.append(value) + + def __sp(self, key, val): if key not in self.funcs.keys(): self.funcs[key] = val diff --git a/summer/work/orm.py b/summer/work/orm.py index 9646ad3..70e0dcd 100644 --- a/summer/work/orm.py +++ b/summer/work/orm.py @@ -38,6 +38,7 @@ s """ self.sqlFields.right_subscript) self.first_data = False + self._result = [] def top(self): return self.find().limit(1) @@ -303,7 +304,7 @@ s """ self.args.append(self.sqlFields.ander_str) return self - def run(self, need_sql=False): + def run(self, need_sql=False, serializer=True, **kwargs): """ 最终执行任务 """ @@ -315,20 +316,20 @@ s """ if need_sql: return sql if self.sqlFields.find_str in sql: - _result = self.repository.db_util.select( + self._result = self.repository.db_util.select( sql=sql, params=self.params, print_sql=print_sql, last_id=last_id ) _result_objs = [] - for i in _result: + for i in self._result: _obj = self.ParseUtil.parse_obj( data=i, instance=self.repository.instance) _result_objs.append(_obj) - _result = _result_objs + self._result = _result_objs else: - _result = self.repository.db_util.update( + self._result = self.repository.db_util.update( sql=sql, params=self.params, print_sql=print_sql, @@ -338,13 +339,18 @@ s """ self.args.clear() self.params.clear() if self.first_data: - if (isinstance(_result, list) or isinstance(_result, tuple)) and _result and len(_result) > 0: - return self.serializer(instance=self.repository.instance, base_data=_result).first() + if (isinstance(self._result, list) or isinstance(self._result, tuple)) and self._result and len( + self._result) > 0: + if not serializer: + return self._result[0] + return self.serializer(instance=self.repository.instance, base_data=self._result).first() else: return None else: + if not serializer: + return self._result q = self.serializer( - instance=self.repository.instance, base_data=_result) + instance=self.repository.instance, base_data=self._result) return q def con_from(self): @@ -371,8 +377,8 @@ s """ 1] = str(self.args[len(self.args) - 1]).replace(sym, rep) return self - def end(self): - return self.run() + def end(self, **kwargs): + return self.run(**kwargs) def __rshift__(self, other): """ @@ -393,3 +399,8 @@ s """ self.args.append(' ( ') self.args = self.args + new_args return self + + def serializer(self): + q = self.serializer( + instance=self.repository.instance, base_data=self._result) + return q diff --git a/summer/work/repository.py b/summer/work/repository.py index 12c8186..b9d8056 100644 --- a/summer/work/repository.py +++ b/summer/work/repository.py @@ -81,10 +81,10 @@ class Repository: self.ParseUtil = config_obj ParseUtil = self.ParseUtil ParseUtil.set_field_compulsory(self, key='config_obj', data=kwargs, val=config_obj) - ParseUtil.set_field_compulsory(obj=self, data=kwargs, key='abs', val=False) + ParseUtil.set_field_compulsory(obj=self, data=kwargs, key='abst', val=False) # 当本类为抽象类时,仅设置所需要的值 ParseUtil.set_field_compulsory(self, key='close_log', data=kwargs, val=close_log) - if hasattr(self, 'close_log') and not self.close_log and not self.abs: + if hasattr(self, 'close_log') and not self.close_log and not self.abst: CACodeLog.warning(obj=self, msg='Being Initialize this object') # 有没有表名 ParseUtil.set_field_compulsory(self, key='__table_name__', data=kwargs, @@ -95,7 +95,7 @@ class Repository: # 取得字段的名称 ParseUtil.set_field_compulsory(self, key='fields', data=kwargs, val=list(self.instance.getFields().keys())) # 当当前类为抽象类时,为类取消初始化数据库配置 - if not self.abs: + if not self.abst: # 操作类 ParseUtil.set_field_compulsory(self, key='operation', data=kwargs, val=op_db.DbOperation()) # 获取sql方言配置 diff --git a/test/testFunc.py b/test/testFunc.py index d8e29fc..4b2e526 100644 --- a/test/testFunc.py +++ b/test/testFunc.py @@ -25,13 +25,12 @@ def set_many(): a.append( MyFactory.createInstance('sqlserver_test.DemoTable', t_msg=f'测试msg{i}', t_name=f'测试name{i}', t_pwd=f'测试pwd{i}', - abs=True)) + abst=True)) return a def TestMySql(): demoTable = MyFactory.createInstance('mysql_test.DemoTable') - d_2 = MyFactory.createInstance('mysql_test.DemoTable') # result = demoTable.find_all() # test_data = set_many() t = time.time() @@ -39,7 +38,8 @@ def TestMySql(): # result = demoTable.find_by_id(t_id=10) # page = result.page(7) # result = page.to_dict() - result = demoTable.orm.find().where(t_id__in=[1, 2, 3, 4, 5, 6, 7, 8, 9]).end() + result = demoTable.orm.find().where(t_id__eq=10).end() + result.add_field('aaaa', True) result.remove_field('t_id') # r_2 = d_2.orm.find(poly=[' FROM ']) # var = r_2 << result diff --git a/upload.bat b/upload.bat index befbad9..2afd370 100644 --- a/upload.bat +++ b/upload.bat @@ -1,2 +1,3 @@ -python setup.py sdist bdist_wheel +python setup.py sdist +python setup.py bdist_wheel twine upload dist/* \ No newline at end of file -- Gitee From edafffe668e93fd8b1c29c4ef049841929e457e0 Mon Sep 17 00:00:00 2001 From: CACode Date: Tue, 25 May 2021 00:44:05 +0800 Subject: [PATCH 19/26] =?UTF-8?q?=E5=A2=9E=E5=8A=A0readme=E5=AE=8C?= =?UTF-8?q?=E6=95=B4=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 228 ++++++++++++++++++++++++++++--- example/__init__.py | 3 + example/db_base.py | 74 ++++++++++ example/operas/__init__.py | 3 + example/operas/basis/__init__.py | 3 + example/operas/basis/find.py | 13 ++ example/tables/__init__.py | 3 + example/tables/demoModels.py | 22 +++ imgs/aestate_yuan.png | Bin 0 -> 141673 bytes imgs/lct.png | Bin 46275 -> 0 bytes imgs/summer_tr.png | Bin 844101 -> 0 bytes summer/cacode/Factory.py | 1 - test/modules/SqlServerTest.py | 10 +- test/tables/__init__.py | 3 + 14 files changed, 337 insertions(+), 26 deletions(-) create mode 100644 example/__init__.py create mode 100644 example/db_base.py create mode 100644 example/operas/__init__.py create mode 100644 example/operas/basis/__init__.py create mode 100644 example/operas/basis/find.py create mode 100644 example/tables/__init__.py create mode 100644 example/tables/demoModels.py create mode 100644 imgs/aestate_yuan.png delete mode 100644 imgs/lct.png delete mode 100644 imgs/summer_tr.png create mode 100644 test/tables/__init__.py diff --git a/README.md b/README.md index 6111637..e725e8c 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,238 @@

- +

-

Welcome to Summer Framework 👋

+

Aestate —— 创建仅属于你的sql语法

- Version + Version Documentation - License: Apache + License: Apache-2.0

+# 介绍 + +

+ Aestate Framework 是一款允许你自定义sql操作语法的orm (Object Relational Mapping)框架, 可以尽情发挥你的想象力,创造出属于你自己的sql操作方式。通过内置`DBUtils`来达到数据库操作和缓存,内置`simplejson`用于序列化和反序列化。 + 修改后的`simplejson`非常强大,通过`aestate.cacode.Serialize.JsonUtil`获得json工具类, 可达到将`object`类型的数据解析成json字符串或者反序列化为字典格式。 + 将最大限制的保留原始操作方式,允许工程师自定义一些特殊语法模板。支持分库分表多线程多进程执行,支持所有遵守DB-API2的数据库创建者 +

+ # 安装 -> pip命令:pip install summer-python +> pip 命令:pip install aestate +> anaconda 安装:conda install aestate -## 先决条件 +# 先决条件 > python >=3.6 -> 基础的sql知识 +> 基础的 sql 知识 > 教程文档地址:http://doc.cacode.ren -# 它是如何运作的 +# 更全面的教程和文档 + +- [文字教程 doc.cacode.ren](http://doc.cacode.ren) +- [视频教程 bilibili.com](https://www.bilibili.com/video/BV1gq4y1E7Fs/) + +# 开始学习 + +## 获得 demo 数据库 + +首先使用 mysql8.0 以上版本执行以下 sql 语句,创建我们的 demo 表 + +```sql +CREATE TABLE `demo` +( + `id` int NOT NULL AUTO_INCREMENT, + `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) USING BTREE +) +``` + +在我们的项目目录创建一个名为`db_base.py`文件,用于保存我们的全局配置和模板 +然后我们来 + +## 创建一个数据库配置 + +```python +# 位置在:example.db_base.py + +import pymysql + +from summer.work.Config import Conf + + +class db_conf(Conf): + def __init__(self): + # 设置全局打印sql语句 + self.set_field('print_sql', True) + # 设置全局插入语句返回最后一行id + self.set_field('last_id', True) + + super(db_conf, self).__init__( + # 数据库地址 + host='localhost', + # 数据库端口 + port=3306, + # 数据库名 + database='summer-demo', + # 数据库用户 + user='root', + # 数据库密码 + password='123456', + # 数据库创建者,如果你用的是mysql,那么这里就是pymysql,如果用的是sqlserver,那么这里就应该是pymssql + creator=pymysql) + +``` + +### 配置解释: + +```json +{ + "host": "数据库的路由 必填", + "port": "数据库端口 必填", + "database": "数据库名 必填", + "user": "登录使用的用户 必填", + "password": "用户的密码 必填", + "charset": "编码格式 默认utf8", + "creator": "数据库的创建者,如果你使用的是mysql,那么这里就需要import pymysql,然后将pymysql放入这个参数中 必填", + "print_sql": "是否在执行之前打印sql语句 默认False", + "last_id": "是否需要在insert插入操作结束后返回最后一行的行号,默认只返回受影响行数 默认False", + "adapter": "适配器,用于自定义语法和解决sql语句不同方言的问题,你可以自定义处理流程和自定义关键字,例如默认使用`__like`模糊查询,你可以将`__like`改为`__f**k`只要你愿意 默认None" +} +``` + +## 创建 Template 模板表 -![](./imgs/lct.png) +```python +# 位置在:example.db_base.py -# 适用场景 +from summer.work import Manage -```text -经过测试,目前稳定运行于Django、Flask、FastApi、web2py。支持非任何架构的原生python, -可通过任何形式使用。不局限于已创建的对象,可动态加载数据库和数据表 + +class table_template(Manage.Pojo): + def __init__(self, **kwargs): + """ + 模板类对象 + """ + # 创建一个自增的主键id,并且不允许为空 + self.id = Manage.tag.intField(primary_key=True, is_null=False, comment='主键自增') + # 创建一个创建时间,并设置`auto_time=True`,在第一次保存时可以为其设置默认为当前时间 + self.create_time = Manage.tag.datetimeField(auto_time=True, is_null=False, comment='创建时间') + # 创建一个更新时间,并设置`update_auto_time=True`,保证每次修改都会更新为当前时间 + self.update_time = Manage.tag.datetimeField(update_auto_time=True, is_null=False, comment='更新实际按') + # 如果子类包含`is_delete`字段,并且不为False时,为其添加一个是否删除的字段 + if 'is_delete' in kwargs.keys() and kwargs.get('is_delete'): + # 设置是否删除,推荐使用int(boolean) + self.is_delete = Manage.tag.tinyintField(default=int(False), is_null=False, comment='是否删除,0 未删除 1 删除') + # 设置config_obj未db_conf的对象, + super(table_template, self).__init__( + # 导入配置类 + config_obj=db_conf(), + # 设置日志配置 + log_conf={ + # 保存位置 + 'path': "/log/", + # 是否允许保存日志 + 'save_flag': True, + # 当日志到达多少MB时删除日志重新记录 + 'max_clean': 100 + }, + # 必备的字段,每一个Pojo对象都必须包含一个`**kwargs` + **kwargs) +``` + +### 配置解释: + +```json +{ + "config_obj": "配置类对象 必填", + "log_conf": "日志配置", + "close_log": "是否关闭日志 默认False", + "serializer": "序列化时使用的对象 默认QuerySet", + "more...": "更多字段请查看源代码:summer.work.repository.Repository类" +} ``` -# 优点 +## 为我们的 demo 表创建一个 Pojo + +在根目录下新建一个包,名为:`tables`,并在`tables`包下创建一个名为`demoModels.py`文件,在文件内编写以下代码: + +```python +# 位置在:example.tables.demoModels.py -```text -适配市面上所有基于DB-API2规范的数据库创建者,MySql承受100万次插入最快可达19秒。 -内部代码使用中文注释,阅读源码不费力 +from example.db_base import table_template +from summer.anno.annos import Table +from summer.work import Manage + + +# 使用装示器设置表的名称,name和msg是必填字段,name为表的名称,msg为表的注释 +# 如果你不喜欢使用装示器,你也可以在__init__()中使用self.__table_name__来设置表的名称 +# 如果你还是不喜欢,那就将这个类的名称写成表的名称,严格区分大小写 +# 为了规范起见,也为了你后面接手的人不骂你,请务必填写描述文本 +@Table(name='demo', msg='示例表') +# 使用表的全名为类名设置表的名称 +# class demo(table_template): +class Demo(table_template): + def __init__(self, **kwargs): + # 新建一个名为name的字段,长度为20,不允许为空 + self.name = Manage.tag.varcharField(length=20, is_null=False, comment='名称') + # 创建一个password字段 + self.password = Manage.tag.varcharField(length=20, is_null=False, comment='密码') + # 使用内部变量设置表的名称 + # self.__table_name__ = 'demo' + # 这里不设置`is_delete`字段 + super(Demo, self).__init__(**kwargs) ``` -# 内置 +在这个`demoModels.py`下你可以尝试写更多的表,企业开发请务必按照功能来分开写model,因为如果你写的全挤在一起,就会看起来就跟一个月没洗的袜子一样 + +## 创建一个工厂类 + +回到我们的`db_base.py`这个文件内,新建一个类并命名为:`MyFactory` + +```python +# 位置在:example.db_base.py + +from summer.cacode.Factory import Factory + + +class MyFactory(Factory): + # 这个是固定不变的,务必要死记下来 + modules = { + # 设置映射关系为 `别名`:`包的位置` + 'demo': 'example.tables.demoModels' + } + +``` + +## 基础实战 + +在你的逻辑文件下使用,例如我这边的在`example.operas.basis`下 +无论你在哪个文件下开始,都需要先使用刚才写的工厂来创建一个Pojo对象 + +```python +from example.db_base import MyFactory + +Demo = MyFactory.createInstance('demo.Demo') +``` + +### 查找操作 (find) + +用法: -```text -内置json解析器和数据库连接池,带有缓存机制,能够在极大程度减少对数据库的压力 +```python +result = Demo.find_all() +result = Demo.find_many(sql='SELECT * FROM demo') +result = Demo.find_one(sql='SELECT * FROM demo LIMIT 0,1') +result = Demo.find_field('id', 'name', 'password') +result = Demo.find_sql(sql='SELECT * FROM demo') ``` # CACode Development Team diff --git a/example/__init__.py b/example/__init__.py new file mode 100644 index 0000000..0a41789 --- /dev/null +++ b/example/__init__.py @@ -0,0 +1,3 @@ +# -*- utf-8 -*- +# @Time: 2021/5/25 0:04 +# @Author: CACode diff --git a/example/db_base.py b/example/db_base.py new file mode 100644 index 0000000..c7df4ba --- /dev/null +++ b/example/db_base.py @@ -0,0 +1,74 @@ +# -*- utf-8 -*- +# @Time: 2021/5/24 23:34 +# @Author: CACode +import pymysql + +from summer.work.Config import Conf + + +class db_conf(Conf): + def __init__(self): + # 设置全局打印sql语句 + self.set_field('print_sql', True) + # 设置全局插入语句返回最后一行id + self.set_field('last_id', True) + + super(db_conf, self).__init__( + # 数据库地址 + host='localhost', + # 数据库端口 + port=3306, + # 数据库名 + database='summer-demo', + # 数据库用户 + user='root', + # 数据库密码 + password='123456', + # 数据库创建者,如果你用的是mysql,那么这里就是pymysql,如果用的是sqlserver,那么这里就应该是pymssql + creator=pymysql) + + +from summer.work import Manage + + +class table_template(Manage.Pojo): + def __init__(self, **kwargs): + """ + 模板类对象 + """ + # 创建一个自增的主键id,并且不允许为空 + self.id = Manage.tag.intField(primary_key=True, is_null=False, comment='主键自增') + # 创建一个创建时间,并设置`auto_time=True`,在第一次保存时可以为其设置默认为当前时间 + self.create_time = Manage.tag.datetimeField(auto_time=True, is_null=False, comment='创建时间') + # 创建一个更新时间,并设置`update_auto_time=True`,保证每次修改都会更新为当前时间 + self.update_time = Manage.tag.datetimeField(update_auto_time=True, is_null=False, comment='更新实际按') + # 如果子类包含`is_delete`字段,并且不为False时,为其添加一个是否删除的字段 + if 'is_delete' in kwargs.keys() and kwargs.get('is_delete'): + # 设置是否删除,推荐使用int(boolean) + self.is_delete = Manage.tag.tinyintField(default=int(False), is_null=False, comment='是否删除,0 未删除 1 删除') + # 设置config_obj未db_conf的对象, + super(table_template, self).__init__( + # 导入配置类 + config_obj=db_conf(), + # 设置日志配置 + log_conf={ + # 保存位置 + 'path': "/log/", + # 是否允许保存日志 + 'save_flag': True, + # 当日志到达多少MB时删除日志重新记录 + 'max_clear': 100 + }, + # 必备的字段,每一个Pojo对象都必须包含一个`**kwargs` + **kwargs) + + +from summer.cacode.Factory import Factory + + +class MyFactory(Factory): + # 这个是固定不变的,务必要死记下来 + modules = { + # 设置映射关系为 `别名`:`包的位置` + 'demo': 'example.tables.demoModels' + } diff --git a/example/operas/__init__.py b/example/operas/__init__.py new file mode 100644 index 0000000..7b6193d --- /dev/null +++ b/example/operas/__init__.py @@ -0,0 +1,3 @@ +# -*- utf-8 -*- +# @Time: 2021/5/25 0:32 +# @Author: CACode diff --git a/example/operas/basis/__init__.py b/example/operas/basis/__init__.py new file mode 100644 index 0000000..7b6193d --- /dev/null +++ b/example/operas/basis/__init__.py @@ -0,0 +1,3 @@ +# -*- utf-8 -*- +# @Time: 2021/5/25 0:32 +# @Author: CACode diff --git a/example/operas/basis/find.py b/example/operas/basis/find.py new file mode 100644 index 0000000..fa67d13 --- /dev/null +++ b/example/operas/basis/find.py @@ -0,0 +1,13 @@ +# -*- utf-8 -*- +# @Time: 2021/5/25 0:33 +# @Author: CACode +from example.db_base import MyFactory + +# 使用自己创建的工厂来创建对象,创建的规则是: `别名`.`类名` +Demo = MyFactory.createInstance('demo.Demo') + +result_all = Demo.find_all() +result_many = Demo.find_many(sql='SELECT * FROM `demo`') +result_one = Demo.find_one(sql='SELECT * FROM `demo` LIMIT 0,1') +result_field = Demo.find_field('id', 'name', 'password') +result_sql = Demo.find_sql(sql='SELECT * FROM demo') diff --git a/example/tables/__init__.py b/example/tables/__init__.py new file mode 100644 index 0000000..0a41789 --- /dev/null +++ b/example/tables/__init__.py @@ -0,0 +1,3 @@ +# -*- utf-8 -*- +# @Time: 2021/5/25 0:04 +# @Author: CACode diff --git a/example/tables/demoModels.py b/example/tables/demoModels.py new file mode 100644 index 0000000..5e77d2f --- /dev/null +++ b/example/tables/demoModels.py @@ -0,0 +1,22 @@ +# -*- utf-8 -*- +# @Time: 2021/5/25 0:04 +# @Author: CACode +from example.db_base import table_template +from summer.anno.annos import Table +from summer.work import Manage + + +# 使用装示器设置表的名称,name和msg是必填字段,name为表的名称,msg为表的注释 +# 如果你不喜欢使用装示器,你也可以在__init__()中使用self.__table_name__来设置表的名称 +# 如果你还是不喜欢,那就将这个类的名称写成表的名称,严格区分大小写 +@Table(name='demo', msg='示例表') +class Demo(table_template): + def __init__(self, **kwargs): + # 新建一个名为name的字段,长度为20,不允许为空 + self.name = Manage.tag.varcharField(length=20, is_null=False, comment='名称') + # 创建一个password字段 + self.password = Manage.tag.varcharField(length=20, is_null=False, comment='密码') + # 这里不设置`is_delete`字段 + + self.__table_name__ = 'demo' + super(Demo, self).__init__(**kwargs) diff --git a/imgs/aestate_yuan.png b/imgs/aestate_yuan.png new file mode 100644 index 0000000000000000000000000000000000000000..d1fcaf7e30406bedbdc1449ef23a9d00b8a82ad9 GIT binary patch literal 141673 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 Date: Tue, 25 May 2021 00:45:52 +0800 Subject: [PATCH 20/26] =?UTF-8?q?=E4=BF=AE=E6=94=B9logo=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e725e8c..6c0dfa2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- +

Aestate —— 创建仅属于你的sql语法

-- Gitee From 75f3c5fa8c763ad11eebd8ffb22f7f42e21bd44c Mon Sep 17 00:00:00 2001 From: CACode Date: Tue, 25 May 2021 00:49:43 +0800 Subject: [PATCH 21/26] =?UTF-8?q?=E4=BF=AE=E6=94=B9logo=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6c0dfa2..071e8c6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- +

Aestate —— 创建仅属于你的sql语法

-- Gitee From 06016aab060f936c2f31b8a52e95154054f88b34 Mon Sep 17 00:00:00 2001 From: CACode Date: Wed, 26 May 2021 02:10:29 +0800 Subject: [PATCH 22/26] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E6=96=87=E6=A1=A3=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=8E=9F=E5=A7=8B?= =?UTF-8?q?=E4=BB=93=E5=BA=93=E6=93=8D=E4=BD=9C=E8=A1=A5=E4=B8=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 225 +++++++++++++++++++++++++++++++-- example/operas/basis/find.py | 14 +- example/operas/basis/insert.py | 42 ++++++ example/operas/basis/update.py | 3 + example/tables/demoModels.py | 7 +- imgs/aestate_yuan.png | Bin 141673 -> 0 bytes imgs/icon_dev.png | Bin 72659 -> 0 bytes pypi.md | 44 ------- setup.py | 12 +- summer/cacode/Factory.py | 6 +- summer/cacode/Serialize.py | 2 +- summer/opera/op_db.py | 12 +- summer/work/repository.py | 40 +++--- 13 files changed, 309 insertions(+), 98 deletions(-) create mode 100644 example/operas/basis/insert.py create mode 100644 example/operas/basis/update.py delete mode 100644 imgs/aestate_yuan.png delete mode 100644 imgs/icon_dev.png delete mode 100644 pypi.md diff --git a/README.md b/README.md index 071e8c6..682025a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- +

Aestate —— 创建仅属于你的sql语法

@@ -23,8 +23,9 @@ # 安装 -> pip 命令:pip install aestate -> anaconda 安装:conda install aestate +> pip 命令:pip install aestate 暂时无效,预计六月初开通 +> anaconda 安装:conda install aestate 暂时无效,预计六月初开通 +> 由于原名叫summer,所以你可以使用`pip install summer-python`安装 # 先决条件 @@ -175,7 +176,7 @@ from summer.work import Manage # 使用装示器设置表的名称,name和msg是必填字段,name为表的名称,msg为表的注释 # 如果你不喜欢使用装示器,你也可以在__init__()中使用self.__table_name__来设置表的名称 # 如果你还是不喜欢,那就将这个类的名称写成表的名称,严格区分大小写 -# 为了规范起见,也为了你后面接手的人不骂你,请务必填写描述文本 +# 为了规范起见,请务必填写描述文本 @Table(name='demo', msg='示例表') # 使用表的全名为类名设置表的名称 # class demo(table_template): @@ -191,7 +192,7 @@ class Demo(table_template): super(Demo, self).__init__(**kwargs) ``` -在这个`demoModels.py`下你可以尝试写更多的表,企业开发请务必按照功能来分开写model,因为如果你写的全挤在一起,就会看起来就跟一个月没洗的袜子一样 +在这个`demoModels.py`下你可以尝试写更多的表,企业开发请务必按照功能来分开写 model,因为如果你写的全挤在一起,就会看起来就跟一个月没洗的袜子一样 ## 创建一个工厂类 @@ -212,10 +213,14 @@ class MyFactory(Factory): ``` -## 基础实战 +## 基础实战(不建议使用) + +### 基础查找操作 (find) + +#### 必备 在你的逻辑文件下使用,例如我这边的在`example.operas.basis`下 -无论你在哪个文件下开始,都需要先使用刚才写的工厂来创建一个Pojo对象 +无论你在哪个文件下开始,都需要先使用刚才写的工厂来创建一个 Pojo 对象 ```python from example.db_base import MyFactory @@ -223,18 +228,210 @@ from example.db_base import MyFactory Demo = MyFactory.createInstance('demo.Demo') ``` -### 查找操作 (find) +或者也可以直接实例化这个类,看个人喜好,以后版本可能会移除这两个其中一个 + +```python +from example.tables.demoModels import Demo + +demo = Demo() +``` + +用法: + +#### find_all + +查找所有 返回的是集合形式的键值对 + +```python +result_all = Demo.find_all() +print('result_all', result_all) +``` + +```json +//这些是数据库的数据 +[ + { + "name": "a", + "password": "13", + "id": 1, + "create_time": "因为我们之前设置了模板类的auto_time,当没有的时候自动填充 2021-05-25 21:35:51", + "update_time": "同上 2021-05-25 21:35:51" + } + ...(表示更多数据) +] +``` + +#### find_many + +搜索多个 返回的是集合形式的键值对 + +```python +result_many = Demo.find_many(sql='SELECT * FROM `demo`') +print('result_many', result_many) +``` + +```json +//同上 +[ + { + "name": "a", + "password": "13", + "id": 1, + "create_time": "2021-05-25 21:35:51", + "update_time": "2021-05-25 21:35:51" + } + ... +] +``` + +#### find_one + +搜索一个返回的是表对象 + +```python +result_one = Demo.find_one(sql='SELECT * FROM `demo` WHERE `id`=1') +print('result_one', result_one.to_json()) +``` + +```json +//使用to_json()方法将对象转换为json字符串,也可以使用to_dict()转字典,默认就是这个表对象object +{ + "name": "a", + "password": "13", + "id": 1, + "create_time": "2021-05-25 21:35:51", + "update_time": "2021-05-25 21:35:51" +} + +``` + +#### find_field + +根据字段查找多个 返回的是集合形式的键值对 + +```python +result_field = Demo.find_field('id', 'name', 'password') +print('result_field', result_field) +``` + +```json +//同find_many() +[ + { + "name": "a", + "password": "13", + "id": 1, + "create_time": "2021-05-25 23:31:55", + "update_time": "2021-05-25 23:31:55" + } + ... +] +``` + +#### find_sql + +根据 sql 查找 返回的是集合形式的键值对 + +```python +result_sql = Demo.find_sql(sql='SELECT * FROM demo') +print('result_sql', result_sql) +``` + +```json +//find_field() +[ + { + "name": "a", + "password": "13", + "id": 1, + "create_time": "2021-05-25 23:31:55", + "update_time": "2021-05-25 23:31:55" + } + ... +] +``` + +### 基础插入操作 用法: +#### 必备 + +还是一样先创建一个表对象 + +```python +from example.db_base import MyFactory + +Demo = MyFactory.createInstance('demo.Demo') +``` + +或者也可以直接实例化这个类,看个人喜好,以后版本可能会移除这两个其中一个 + ```python -result = Demo.find_all() -result = Demo.find_many(sql='SELECT * FROM demo') -result = Demo.find_one(sql='SELECT * FROM demo LIMIT 0,1') -result = Demo.find_field('id', 'name', 'password') -result = Demo.find_sql(sql='SELECT * FROM demo') +from example.tables.demoModels import Demo + +demo = Demo() ``` +#### create() + +```python + + +def create(): + # 因为我们的模板表设置了`create_time`和`update_time`自动录入时间的`auto_time`和`update_auto_time` + # 所以这里不需要设置这两个的时间 + # abs参数设置为True时,表示这个对象仅作为数据使用,不参与数据操作过程 + data = MyFactory.createInstance('demo.Demo', name='test_name', password='123456', abs=True) + # 因为我们在全局配置,也就是db_base.py中的全局配置已经设置了允许返回最后一行的id + # 所以这里就可以拿到插入后最后一行的id + # 返回的结果是:受影响行数,最后一行id + line, last_id = Demo.create(data) + return line, last_id + + +if __name__ == '__main__': + create() +``` + +返回结果 + +```text +受影响行数,最后一行id +1,3 +``` + +#### save() + +```python +def save(): + # 为了全局变量的干净,我们得在内部重新创建一个 + Demo = MyFactory.createInstance('demo.Demo') + # 为对象设置值 + Demo.name = 'test_name' + Demo.password = '123456' + # 返回结果,具体参考上一个方法insert() + line, last_id = Demo.save() + print(line, last_id) + + +if __name__ == '__main__': + save() +``` + +返回结果 + +```text +受影响行数,最后一行id +1,4 +``` + +#### insert_sql() + +这个可以说是最鸡肋的方法也无妨 +> 1.0.0b3版本已废弃 + # CACode Development Team -!['CACode Development Team'](./imgs/icon_dev.png) +> Last edit time:2021/05/26 02:03 Asia/Shanghai +> [👉 Go to canotf`s homepage on Gitee 👈](https://gitee.com/canotf) diff --git a/example/operas/basis/find.py b/example/operas/basis/find.py index fa67d13..26dde32 100644 --- a/example/operas/basis/find.py +++ b/example/operas/basis/find.py @@ -5,9 +5,21 @@ from example.db_base import MyFactory # 使用自己创建的工厂来创建对象,创建的规则是: `别名`.`类名` Demo = MyFactory.createInstance('demo.Demo') +result = Demo.orm.find().order_by('id').end() +page = result.page(10).get(1) +# 查找所有 result_all = Demo.find_all() +print('result_all', result_all) +# 搜索多个 result_many = Demo.find_many(sql='SELECT * FROM `demo`') -result_one = Demo.find_one(sql='SELECT * FROM `demo` LIMIT 0,1') +print('result_many', result_many) +# 搜索一个 +result_one = Demo.find_one(sql='SELECT * FROM `demo` WHERE `id`=1') +print('result_one', result_one.to_json()) +# 根据字段查找多个 result_field = Demo.find_field('id', 'name', 'password') +print('result_field', result_field) +# 根据sql查找 result_sql = Demo.find_sql(sql='SELECT * FROM demo') +print('result_sql', result_sql) diff --git a/example/operas/basis/insert.py b/example/operas/basis/insert.py new file mode 100644 index 0000000..9f903ad --- /dev/null +++ b/example/operas/basis/insert.py @@ -0,0 +1,42 @@ +# -*- utf-8 -*- +# @Time: 2021/5/26 1:24 +# @Author: CACode +from example.db_base import MyFactory + +# 使用自己创建的工厂来创建对象,创建的规则是: `别名`.`类名` +Demo = MyFactory.createInstance('demo.Demo') + + +def create(): + # 因为我们的模板表设置了`create_time`和`update_time`自动录入时间的`auto_time`和`update_auto_time` + # 所以这里不需要设置这两个的时间 + # abs参数设置为True时,表示这个对象仅作为数据使用,不参与数据操作过程 + data = MyFactory.createInstance('demo.Demo', name='test_name', password='123456', abs=True) + # 因为我们在全局配置,也就是db_base.py中的全局配置已经设置了允许返回最后一行的id + # 所以这里就可以拿到插入后最后一行的id + # 返回的结果是:受影响行数,最后一行id + line, last_id = Demo.create(data) + print(line, last_id) + + +def save(): + # 为了全局变量的干净,我们得在内部重新创建一个 + Demo = MyFactory.createInstance('demo.Demo') + # 为对象设置值 + Demo.name = 'test_name' + Demo.password = '123456' + # 返回结果,具体参考上一个方法insert() + line, last_id = Demo.save() + print(line, last_id) + + +def insert_sql(): + # TODO: 1.0.0b3 已废弃 + from example.tables import demoModels + demo = demoModels.Demo() + line, last_id = demo.insert_sql(sql='INSERT INTO `demo` (`name`,`password`) VALUES ("test_name","test_password")') + print(line, last_id) + + +if __name__ == '__main__': + insert_sql() diff --git a/example/operas/basis/update.py b/example/operas/basis/update.py new file mode 100644 index 0000000..201a0c7 --- /dev/null +++ b/example/operas/basis/update.py @@ -0,0 +1,3 @@ +# -*- utf-8 -*- +# @Time: 2021/5/26 1:59 +# @Author: CACode diff --git a/example/tables/demoModels.py b/example/tables/demoModels.py index 5e77d2f..dbdd825 100644 --- a/example/tables/demoModels.py +++ b/example/tables/demoModels.py @@ -9,14 +9,17 @@ from summer.work import Manage # 使用装示器设置表的名称,name和msg是必填字段,name为表的名称,msg为表的注释 # 如果你不喜欢使用装示器,你也可以在__init__()中使用self.__table_name__来设置表的名称 # 如果你还是不喜欢,那就将这个类的名称写成表的名称,严格区分大小写 +# 为了规范起见,请务必填写描述文本 @Table(name='demo', msg='示例表') +# 使用表的全名为类名设置表的名称 +# class demo(table_template): class Demo(table_template): def __init__(self, **kwargs): # 新建一个名为name的字段,长度为20,不允许为空 self.name = Manage.tag.varcharField(length=20, is_null=False, comment='名称') # 创建一个password字段 self.password = Manage.tag.varcharField(length=20, is_null=False, comment='密码') + # 使用内部变量设置表的名称 + # self.__table_name__ = 'demo' # 这里不设置`is_delete`字段 - - self.__table_name__ = 'demo' super(Demo, self).__init__(**kwargs) diff --git a/imgs/aestate_yuan.png b/imgs/aestate_yuan.png deleted file mode 100644 index d1fcaf7e30406bedbdc1449ef23a9d00b8a82ad9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141673 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 - -

-

Welcome to Summer Framework 👋

-

- Version - - - Documentation - - - License: Apache - -

- -# 安装 - -> pip命令:pip install summer-python - -## 先决条件 - -> python >=3.6 -> 基础的sql知识 -> 教程文档地址:http://doc.cacode.ren - -# 适用场景 - -```text -经过测试,目前稳定运行于Django、Flask、FastApi、web2py。支持非任何架构的原生python, -可通过任何形式使用。不局限于已创建的对象,可动态加载数据库和数据表 -``` - -# 优点 - -```text -适配市面上所有基于DB-API2规范的数据库创建者,MySql承受100万次插入最快可达19秒。 -内部代码使用中文注释,阅读源码不费力 -``` - -# 内置 - -```text -内置json解析器和数据库连接池,带有缓存机制,能够在极大程度减少对数据库的压力 -``` diff --git a/setup.py b/setup.py index e0d3d80..52341dc 100644 --- a/setup.py +++ b/setup.py @@ -1,19 +1,19 @@ import setuptools -with open("pypi.md", "r", encoding="utf-8") as fh: +with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read() setuptools.setup( - name="summer-python", - version="1.0.0b2", + name="aestate", + version="1.0.0b3", author="CACode", author_email="cacode@163.com", - description="Summer framework for Python,You can see:https://gitee.com/cacode_cctvadmin/summer-python", + description="Aestate framework for Python,You can see:https://gitee.com/cacode_cctvadmin/aestate", long_description=long_description, long_description_content_type="text/markdown", - url="https://gitee.com/cacode_cctvadmin/summer-python", + url="https://gitee.com/cacode_cctvadmin/aestate", project_urls={ - "Bug Tracker": "https://gitee.com/cacode_cctvadmin/summer-python/issues", + "Bug Tracker": "https://gitee.com/cacode_cctvadmin/aestate/issues", }, license=' Apache License 2.0', classifiers=[ diff --git a/summer/cacode/Factory.py b/summer/cacode/Factory.py index 0e9783c..0c6589f 100644 --- a/summer/cacode/Factory.py +++ b/summer/cacode/Factory.py @@ -54,7 +54,7 @@ class Factory(object): self.module_names[last_name] = package_name @classmethod - def createInstance(cls, name: str, *args, **kwargs): + def createInstance(cls, _name: str, *args, **kwargs): """ 建造一个对象并将对象实例化 @@ -68,7 +68,7 @@ class Factory(object): - :param name:类的名称,从配置的instances开始获得 + :param _name:类的名称,从配置的instances开始获得 :param args:类的附属参数 :param kwargs:类的附属参数 """ @@ -76,7 +76,7 @@ class Factory(object): # 使用单例模式初始化仓库 this = Modes.Singleton.createFactory(cls) - module_names = str(name).split('.') + module_names = str(_name).split('.') # 断言这个module name不为空 if len(module_names) < 0: diff --git a/summer/cacode/Serialize.py b/summer/cacode/Serialize.py index a837b1f..a927445 100644 --- a/summer/cacode/Serialize.py +++ b/summer/cacode/Serialize.py @@ -326,7 +326,7 @@ class QuerySet(list): return self[index] def __str__(self): - return str(self.to_dict()) + return self.to_json() __repr__ = __str__ diff --git a/summer/opera/op_db.py b/summer/opera/op_db.py index 38f5848..8d219e6 100644 --- a/summer/opera/op_db.py +++ b/summer/opera/op_db.py @@ -1,7 +1,9 @@ from summer.util.Log import CACodeLog -from summer.field.MySqlDefault import * from summer.util.ParseUtil import ParseUtil +from concurrent.futures import ThreadPoolExecutor + +pool = ThreadPoolExecutor() class DbOperation(object): @@ -33,9 +35,7 @@ class DbOperation(object): # _kw = JsonUtil.load(JsonUtil.parse(_lock)) _kw = _lock.__dict__ kwargs.update(_kw) - from concurrent.futures import ThreadPoolExecutor - pool = ThreadPoolExecutor() - _t = pool.submit(fn=func, *args, **kwargs) + _t = pool.submit(lambda x, y: func(*x, **y), args, kwargs) # _t = threading.Thread(target=func, args=args, kwargs=kwargs, name=name) if not _lock.close_log: CACodeLog.log(obj=_t, msg='TASK-{} RUNNING'.format(name), task_name=name, LogObject=kwargs['log_obj']) @@ -60,7 +60,7 @@ class DbOperation(object): self.result = self.__find_many__(**kwargs) return self.result - def __find_many__(self, **kwargs): + def __find_many__(self, *args, **kwargs): """作者:CACode 最后编辑于2021/4/12 任务方法 @@ -70,7 +70,7 @@ class DbOperation(object): self.result = self.__find_sql__(**kwargs) return self.result - def __find_sql__(self, **kwargs): + def __find_sql__(self, *args, **kwargs): """作者:CACode 最后编辑于2021/4/12 任务方法 diff --git a/summer/work/repository.py b/summer/work/repository.py index b9d8056..ac98034 100644 --- a/summer/work/repository.py +++ b/summer/work/repository.py @@ -167,7 +167,7 @@ class Repository: 获取最后一个参数 """ - def find_all(self): + def find_all(self, **kwargs): """作者:CACode 最后编辑于2021/4/12 从当前数据表格中查找所有数据 @@ -175,21 +175,11 @@ class Repository: Returns: 将所有结果封装成POJO对象集合并返回数据 """ - # 设置名称 - name = str(uuid.uuid1()) # 开启任务 - kwargs = { - 'func': self.operation.__find_all__, - '__task_uuid__': name, - 't_local': self - } - result = self.operation.start(*self.fields, **kwargs) - - self.result = self.serializer(instance=self.instance, base_data=result) - + self.result = self.find_field(*self.__fields__, **kwargs) return self.result - def find_field(self, *args): + def find_field(self, *args, **kwargs): """作者:CACode 最后编辑于2021/4/12 只查询指定名称的字段,如: @@ -207,7 +197,7 @@ class Repository: # 设置名称 name = str(uuid.uuid1()) # 开启任务 - kwargs = {'func': self.operation.__find_by_field__, '__task_uuid__': name, 't_local': self} + kwargs.update({'func': self.operation.__find_by_field__, '__task_uuid__': name, 't_local': self}) result = self.operation.start(*args, **kwargs) @@ -245,9 +235,11 @@ class Repository: """ self.result = self.find_many(**kwargs) if self.result is None or len(self.result) == 0: + self.result = [] return None else: - return self.result[0] + self.result = self.result.first() + return self.result def find_many(self, **kwargs): """ @@ -332,18 +324,21 @@ class Repository: params:需要填充的字段 :return rowcount,last_id if last_id=True """ - kwargs = self.ParseUtil.find_print_sql(**kwargs) - kwargs = self.ParseUtil.last_id(**kwargs) - return self.db_util.insert(**kwargs) - - def save(self, **kwargs): + import warnings + warnings.warn("1.0.0b3版本开始已弃用,使用此方法并不能有任何作用", DeprecationWarning) + return 0, 0 + # kwargs = self.ParseUtil.find_print_sql(**kwargs) + # kwargs = self.ParseUtil.last_id(**kwargs) + # return self.db_util.insert(**kwargs) + + def save(self, *args, **kwargs): """ 将当前储存的值存入数据库 """ kwargs['pojo'] = self return self.create(**kwargs) - def create(self, **kwargs): + def create(self, *args, **kwargs): """ 插入属性: 返回受影响行数 @@ -353,6 +348,9 @@ class Repository: :return:rowcount,last_id if last_id=True """ # 设置名称 + if 'pojo' not in kwargs.keys(): + if args and len(args) > 0: + kwargs['pojo'] = args[0] name = str(uuid.uuid1()) # 开启任务 kwargs['func'] = self.operation.__insert__ -- Gitee From a679a798726b3af8b8d439a4afd58c440c0c17e9 Mon Sep 17 00:00:00 2001 From: CACode Date: Fri, 28 May 2021 10:42:54 +0800 Subject: [PATCH 23/26] =?UTF-8?q?[1.0.0b3]=E4=BF=AE=E5=A4=8Dwhere=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E7=AC=A6=E5=8F=B7=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- summer/work/orm.py | 36 ++++++++++++++++++++---------------- test/testFunc.py | 6 +++--- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 682025a..cf4aaaa 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ # 介绍

- Aestate Framework 是一款允许你自定义sql操作语法的orm (Object Relational Mapping)框架, 可以尽情发挥你的想象力,创造出属于你自己的sql操作方式。通过内置`DBUtils`来达到数据库操作和缓存,内置`simplejson`用于序列化和反序列化。 + Aestate Framework 是一款允许你自定义sql操作语法的ORM (Object Relational Mapping)框架, 可以尽情发挥你的想象力,创造出属于你自己的sql操作方式。通过内置`DBUtils`来达到数据库操作和缓存,内置`simplejson`用于序列化和反序列化。 修改后的`simplejson`非常强大,通过`aestate.cacode.Serialize.JsonUtil`获得json工具类, 可达到将`object`类型的数据解析成json字符串或者反序列化为字典格式。 将最大限制的保留原始操作方式,允许工程师自定义一些特殊语法模板。支持分库分表多线程多进程执行,支持所有遵守DB-API2的数据库创建者

diff --git a/summer/work/orm.py b/summer/work/orm.py index 70e0dcd..8a0ea5f 100644 --- a/summer/work/orm.py +++ b/summer/work/orm.py @@ -209,25 +209,29 @@ s """ cp_key = key customize = False sym = '=' + + # TODO:1.0.0b2 不能双选符号 BUG + # TODO: 1.0.0b2 只能跑一个 BUG + if len(str(value)) > 2 and str(value)[0:2] in self.sqlFields.symbol: sym = value[0:2] value = str(value)[2:len(str(value))] - elif sym == '==': - sym = '=' - elif sym == '>>': - sym = '>' - elif sym == '<<': - sym = '<' - else: - # 没有找到符号的话就从字段名开始 - # 截取最后一段从两段下划线开始的末尾 - sps = cp_key.split('__') - if not len(sps) == 1: - customize = True - sym = sps[len(sps) - 1] - self.ParseUtil.fieldExist(self.ParseUtil, 'adapter', raise_exception=True) - cp_key = cp_key[:cp_key.rfind('__' + sym)] - self.ParseUtil.adapter.funcs[sym](self, cp_key, value) + if sym == '==': + sym = '=' + elif sym == '>>': + sym = '>' + elif sym == '<<': + sym = '<' + else: + # 没有找到符号的话就从字段名开始 + # 截取最后一段从两段下划线开始的末尾 + sps = cp_key.split('__') + if not len(sps) == 1: + customize = True + sym = sps[len(sps) - 1] + self.ParseUtil.fieldExist(self.ParseUtil, 'adapter', raise_exception=True) + cp_key = cp_key[:cp_key.rfind('__' + sym)] + self.ParseUtil.adapter.funcs[sym](self, cp_key, value) if not customize: self.args.append('`{}`{}%s'.format(cp_key, sym)) diff --git a/test/testFunc.py b/test/testFunc.py index 4b2e526..eb03a03 100644 --- a/test/testFunc.py +++ b/test/testFunc.py @@ -38,9 +38,9 @@ def TestMySql(): # result = demoTable.find_by_id(t_id=10) # page = result.page(7) # result = page.to_dict() - result = demoTable.orm.find().where(t_id__eq=10).end() - result.add_field('aaaa', True) - result.remove_field('t_id') + result = demoTable.orm.find().where(t_id='<=10', t_name='测试name0').end() + # result.add_field('aaaa', True) + # result.remove_field('t_id') # r_2 = d_2.orm.find(poly=[' FROM ']) # var = r_2 << result info(result) -- Gitee From d5f3eff455aea35db6a369a5268031f0959ed78c Mon Sep 17 00:00:00 2001 From: CACode Date: Wed, 2 Jun 2021 05:49:43 +0800 Subject: [PATCH 24/26] =?UTF-8?q?1.0.1=E7=A8=B3=E5=AE=9A=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- {summer/anno => MyTest}/__init__.py | 0 {test => MyTest}/modules/DatabaseConf.py | 4 +- {test => MyTest}/modules/MySqlTest.py | 25 +- {test => MyTest}/modules/SqlServerTest.py | 6 +- {summer/cacode => MyTest/modules}/__init__.py | 0 {test => MyTest}/t_thread_pool/__init__.py | 0 {test => MyTest}/testFunc.py | 29 +- README.md | 19 +- {summer => aestate}/__init__.py | 6 +- {summer => aestate}/cacode/Factory.py | 36 +- {summer => aestate}/cacode/Modes.py | 2 +- {summer => aestate}/cacode/Serialize.py | 190 +- {summer/field => aestate/cacode}/__init__.py | 0 aestate/exception/__init__.py | 57 + {summer => aestate}/exception/e_fields.py | 0 {summer => aestate}/field/FManage.py | 0 {summer => aestate}/field/MySqlDefault.py | 2 +- {summer/opera => aestate/field}/__init__.py | 0 {summer => aestate}/field/tag.py | 2 +- {summer => aestate}/opera/DBPool/__init__.py | 0 .../opera/DBPool/persistent_db.py | 0 .../opera/DBPool/persistent_pg.py | 0 {summer => aestate}/opera/DBPool/pooled_db.py | 0 {summer => aestate}/opera/DBPool/pooled_pg.py | 0 .../opera/DBPool/simple_pooled_db.py | 0 .../opera/DBPool/simple_pooled_pg.py | 0 {summer => aestate}/opera/DBPool/steady_db.py | 0 {summer => aestate}/opera/DBPool/steady_pg.py | 0 {summer/util => aestate/opera}/__init__.py | 0 {summer => aestate}/opera/global_db.py | 18 +- {summer => aestate}/opera/op_db.py | 26 +- {summer => aestate}/util/CompulsoryRun.py | 4 +- {summer => aestate}/util/Log.py | 70 +- {summer => aestate}/util/ParseUtil.py | 38 +- {test => aestate/util}/__init__.py | 0 aestate/util/messy.py | 41 + aestate/util/others.py | 65 + aestate/work/Annotation.py | 189 + {summer => aestate}/work/AopContainer.py | 2 +- {summer => aestate}/work/Config.py | 10 +- {summer => aestate}/work/Manage.py | 10 +- {summer => aestate}/work/SummerAdapter.py | 0 {summer => aestate}/work/__init__.py | 0 {summer/anno => aestate/work}/annos.py | 4 +- {summer => aestate}/work/orm.py | 24 +- {summer => aestate}/work/repository.py | 14 +- example/db_base.py | 6 +- example/tables/demoModels.py | 4 +- setup.py | 10 +- summer/cacode/ReviewJson/JSON.py | 82 - summer/cacode/ReviewJson/__init__.py | 58 - summer/cacode/ReviewJson/_speedups.c | 3384 ----------------- summer/cacode/ReviewJson/compat.py | 44 - summer/cacode/ReviewJson/decoder.py | 400 -- summer/cacode/ReviewJson/encoder.py | 722 ---- summer/cacode/ReviewJson/errors.py | 54 - summer/cacode/ReviewJson/ordered_dict.py | 104 - summer/cacode/ReviewJson/raw_json.py | 9 - summer/cacode/ReviewJson/scanner.py | 85 - summer/cacode/ReviewJson/tool.py | 43 - summer/exception/__init__.py | 16 - test/modules/__init__.py | 0 test/tables/__init__.py | 3 - upload.py | 47 + 65 files changed, 620 insertions(+), 5346 deletions(-) rename {summer/anno => MyTest}/__init__.py (100%) rename {test => MyTest}/modules/DatabaseConf.py (96%) rename {test => MyTest}/modules/MySqlTest.py (47%) rename {test => MyTest}/modules/SqlServerTest.py (80%) rename {summer/cacode => MyTest/modules}/__init__.py (100%) rename {test => MyTest}/t_thread_pool/__init__.py (100%) rename {test => MyTest}/testFunc.py (62%) rename {summer => aestate}/__init__.py (64%) rename {summer => aestate}/cacode/Factory.py (75%) rename {summer => aestate}/cacode/Modes.py (99%) rename {summer => aestate}/cacode/Serialize.py (53%) rename {summer/field => aestate/cacode}/__init__.py (100%) create mode 100644 aestate/exception/__init__.py rename {summer => aestate}/exception/e_fields.py (100%) rename {summer => aestate}/field/FManage.py (100%) rename {summer => aestate}/field/MySqlDefault.py (98%) rename {summer/opera => aestate/field}/__init__.py (100%) rename {summer => aestate}/field/tag.py (99%) rename {summer => aestate}/opera/DBPool/__init__.py (100%) rename {summer => aestate}/opera/DBPool/persistent_db.py (100%) rename {summer => aestate}/opera/DBPool/persistent_pg.py (100%) rename {summer => aestate}/opera/DBPool/pooled_db.py (100%) rename {summer => aestate}/opera/DBPool/pooled_pg.py (100%) rename {summer => aestate}/opera/DBPool/simple_pooled_db.py (100%) rename {summer => aestate}/opera/DBPool/simple_pooled_pg.py (100%) rename {summer => aestate}/opera/DBPool/steady_db.py (100%) rename {summer => aestate}/opera/DBPool/steady_pg.py (100%) rename {summer/util => aestate/opera}/__init__.py (100%) rename {summer => aestate}/opera/global_db.py (95%) rename {summer => aestate}/opera/op_db.py (81%) rename {summer => aestate}/util/CompulsoryRun.py (93%) rename {summer => aestate}/util/Log.py (85%) rename {summer => aestate}/util/ParseUtil.py (91%) rename {test => aestate/util}/__init__.py (100%) create mode 100644 aestate/util/messy.py create mode 100644 aestate/util/others.py create mode 100644 aestate/work/Annotation.py rename {summer => aestate}/work/AopContainer.py (99%) rename {summer => aestate}/work/Config.py (90%) rename {summer => aestate}/work/Manage.py (95%) rename {summer => aestate}/work/SummerAdapter.py (100%) rename {summer => aestate}/work/__init__.py (100%) rename {summer/anno => aestate/work}/annos.py (98%) rename {summer => aestate}/work/orm.py (96%) rename {summer => aestate}/work/repository.py (97%) delete mode 100644 summer/cacode/ReviewJson/JSON.py delete mode 100644 summer/cacode/ReviewJson/__init__.py delete mode 100644 summer/cacode/ReviewJson/_speedups.c delete mode 100644 summer/cacode/ReviewJson/compat.py delete mode 100644 summer/cacode/ReviewJson/decoder.py delete mode 100644 summer/cacode/ReviewJson/encoder.py delete mode 100644 summer/cacode/ReviewJson/errors.py delete mode 100644 summer/cacode/ReviewJson/ordered_dict.py delete mode 100644 summer/cacode/ReviewJson/raw_json.py delete mode 100644 summer/cacode/ReviewJson/scanner.py delete mode 100644 summer/cacode/ReviewJson/tool.py delete mode 100644 summer/exception/__init__.py delete mode 100644 test/modules/__init__.py delete mode 100644 test/tables/__init__.py create mode 100644 upload.py diff --git a/.gitignore b/.gitignore index 418bfe9..e83d1c2 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ __pycache__/ *.pyc venv build -summer_python.egg-info +aestate.egg-info dist upload.bat pyproject.toml diff --git a/summer/anno/__init__.py b/MyTest/__init__.py similarity index 100% rename from summer/anno/__init__.py rename to MyTest/__init__.py diff --git a/test/modules/DatabaseConf.py b/MyTest/modules/DatabaseConf.py similarity index 96% rename from test/modules/DatabaseConf.py rename to MyTest/modules/DatabaseConf.py index ee6c1bb..a75bf75 100644 --- a/test/modules/DatabaseConf.py +++ b/MyTest/modules/DatabaseConf.py @@ -1,8 +1,8 @@ import pymssql import pymysql -from summer.work import Config -from summer.work.SummerAdapter import LanguageAdapter +from aestate.work import Config +from aestate.work.SummerAdapter import LanguageAdapter class Adapter(LanguageAdapter): diff --git a/test/modules/MySqlTest.py b/MyTest/modules/MySqlTest.py similarity index 47% rename from test/modules/MySqlTest.py rename to MyTest/modules/MySqlTest.py index 731325e..931a6a0 100644 --- a/test/modules/MySqlTest.py +++ b/MyTest/modules/MySqlTest.py @@ -1,8 +1,8 @@ import datetime -from summer.anno.annos import Table, Select -from summer.work import Manage -from test.modules.DatabaseConf import MySqlConfig +from aestate.work.annos import Table, Select +from aestate.work import Manage +from MyTest.modules.DatabaseConf import MySqlConfig @Table(name='demo_table', msg='') @@ -22,3 +22,22 @@ class DemoTable(Manage.Pojo): @Select(sql='SELECT * FROM demo_table WHERE t_id<=%s', params=['${t_id}']) def find_by_id(self, t_id): pass + + +@Table(name='demo_table', msg='') +class De(Manage.Pojo): + def __init__(self, **kwargs): + self.t_id = Manage.tag.intField(auto_field=True, primary_key=True) + self.t_name = Manage.tag.varcharField(default='测试name') + self.t_msg = Manage.tag.varcharField(default='测试msg') + self.t_pwd = Manage.tag.varcharField(default='测试pwd') + self.create_time = Manage.tag.datetimeField(default=datetime.datetime.utcnow(), auto_time=True) + self.update_time = Manage.tag.datetimeField(default=datetime.datetime.utcnow(), update_auto_time=True) + super(De, self).__init__(config_obj=MySqlConfig(), log_conf={ + 'path': "/log/", + 'save_flag': True + }, **kwargs) + + @Select(sql='SELECT * FROM demo_table WHERE t_id<=%s', params=['${t_id}']) + def find_by_id(self, t_id): + pass diff --git a/test/modules/SqlServerTest.py b/MyTest/modules/SqlServerTest.py similarity index 80% rename from test/modules/SqlServerTest.py rename to MyTest/modules/SqlServerTest.py index 512caf1..176faec 100644 --- a/test/modules/SqlServerTest.py +++ b/MyTest/modules/SqlServerTest.py @@ -3,9 +3,9 @@ # @Author: CACode # @File: SqlServerTest.py # @Software: PyCharm -from summer.anno.annos import Table -from summer.work import Manage -from test.modules.DatabaseConf import SqlServerConfig +from aestate.work.annos import Table +from aestate.work import Manage +from MyTest.modules.DatabaseConf import SqlServerConfig @Table(name='testccfk', msg='') diff --git a/summer/cacode/__init__.py b/MyTest/modules/__init__.py similarity index 100% rename from summer/cacode/__init__.py rename to MyTest/modules/__init__.py diff --git a/test/t_thread_pool/__init__.py b/MyTest/t_thread_pool/__init__.py similarity index 100% rename from test/t_thread_pool/__init__.py rename to MyTest/t_thread_pool/__init__.py diff --git a/test/testFunc.py b/MyTest/testFunc.py similarity index 62% rename from test/testFunc.py rename to MyTest/testFunc.py index 4b2e526..5fed7a3 100644 --- a/test/testFunc.py +++ b/MyTest/testFunc.py @@ -6,9 +6,10 @@ LastEditors: Please set LastEditors Description: Update Test ''' import time +from datetime import datetime -from summer.cacode.Factory import Factory -from summer.util.Log import CACodeLog +from aestate.cacode.Factory import Factory +from aestate.util.Log import CACodeLog class MyFactory(Factory): @@ -21,26 +22,31 @@ class MyFactory(Factory): def set_many(): a = [] - for i in range(0, 100 * 10000): + for i in range(0, 1): a.append( MyFactory.createInstance('sqlserver_test.DemoTable', t_msg=f'测试msg{i}', t_name=f'测试name{i}', - t_pwd=f'测试pwd{i}', + t_pwd=f'测试pwd{i}', create_time=datetime.utcnow(), abst=True)) return a def TestMySql(): demoTable = MyFactory.createInstance('mysql_test.DemoTable') + demoTable = MyFactory.createInstance('mysql_test.De') # result = demoTable.find_all() - # test_data = set_many() + test_data = set_many() t = time.time() + # result = demoTable.find_field('t_id') # result = demoTable.create(pojo=test_data, many=True) - # result = demoTable.find_by_id(t_id=10) + # result = demoTable.orm.find().where(t_id=10).end() # page = result.page(7) # result = page.to_dict() - result = demoTable.orm.find().where(t_id__eq=10).end() - result.add_field('aaaa', True) - result.remove_field('t_id') + # result = demoTable.orm.find().where(t_id__eq=10).end() + # result = demoTable.orm.find().where(t_id=1, t_name='测试name0').end() + # result = demoTable.orm.find().where(t_id='<<10', t_name='测试name0').end() + result = demoTable.orm.find().where(t_id='>>10', t_name='测试name10').end() + # result.add_field('aaaa', True) + # result.remove_field('t_id') # r_2 = d_2.orm.find(poly=[' FROM ']) # var = r_2 << result info(result) @@ -56,6 +62,10 @@ def TestSqlServer(): info(result) +def me(): + print(time.time()) + + if __name__ == '__main__': info = CACodeLog.log warn = CACodeLog.warning @@ -63,3 +73,4 @@ if __name__ == '__main__': # TestSqlServer() TestMySql() info(f'time:{time.time() - t1}') + # me() diff --git a/README.md b/README.md index 682025a..2e49289 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,12 @@ # 安装 -> pip 命令:pip install aestate 暂时无效,预计六月初开通 -> anaconda 安装:conda install aestate 暂时无效,预计六月初开通 -> 由于原名叫summer,所以你可以使用`pip install summer-python`安装 +> pip 命令:pip install aestate +> anaconda 安装:conda install aestate + +# 依赖包 + +> pip install aestate-json # 先决条件 @@ -66,7 +69,7 @@ CREATE TABLE `demo` import pymysql -from summer.work.Config import Conf +from aestate.work.Config import Conf class db_conf(Conf): @@ -114,7 +117,7 @@ class db_conf(Conf): ```python # 位置在:example.db_base.py -from summer.work import Manage +from aestate.work import Manage class table_template(Manage.Pojo): @@ -169,8 +172,8 @@ class table_template(Manage.Pojo): # 位置在:example.tables.demoModels.py from example.db_base import table_template -from summer.anno.annos import Table -from summer.work import Manage +from aestate.work.annos import Table +from aestate.work import Manage # 使用装示器设置表的名称,name和msg是必填字段,name为表的名称,msg为表的注释 @@ -201,7 +204,7 @@ class Demo(table_template): ```python # 位置在:example.db_base.py -from summer.cacode.Factory import Factory +from aestate.cacode.Factory import Factory class MyFactory(Factory): diff --git a/summer/__init__.py b/aestate/__init__.py similarity index 64% rename from summer/__init__.py rename to aestate/__init__.py index d34dd77..b772b50 100644 --- a/summer/__init__.py +++ b/aestate/__init__.py @@ -1,5 +1,9 @@ -__version__ = "Test-1.3.1.2" +__version__ = "1.0.1b1" __description__ = "CACode Framework For Python Flask,This framework corresponds to the ORM problem" __author__ = "CACode" __author_email__ = "cacode@163.com" __url__ = "https://gitee.com/cacode_cctvadmin/CACodeFramework-python-ORM" +__aestate__ = __version__, {'aestate-json': '1.0.0'} + +if __name__ == '__main__': + print(__aestate__) diff --git a/summer/cacode/Factory.py b/aestate/cacode/Factory.py similarity index 75% rename from summer/cacode/Factory.py rename to aestate/cacode/Factory.py index 0c6589f..8ca7d2f 100644 --- a/summer/cacode/Factory.py +++ b/aestate/cacode/Factory.py @@ -1,11 +1,23 @@ import threading -from summer.cacode import Modes -from summer.exception import e_fields -from summer.exception import ModuleCreateError -from summer.util.CompulsoryRun import Compulsory -from summer.util.Log import CACodeLog +from aestate.cacode import Modes +from aestate.exception import e_fields +from aestate.exception import ModuleCreateError +from aestate.util.CompulsoryRun import Compulsory +from aestate.util.Log import CACodeLog import importlib +__logo__ = """ + __ _ _ __ + / / /\ | | | | \ \ + / / / \ ___ ___| |_ __ _| |_ ___ \ \ + < < / /\ \ / _ \/ __| __/ _` | __/ _ \ > > + \ \ / ____ \ __/\__ \ || (_| | || __/ / / + \_\ /_/ \_\___||___/\__\__,_|\__\___| /_/ + + :: Aestate Framework :: (version:1.0.1) + +""" + class Factory(object): """ @@ -14,12 +26,10 @@ class Factory(object): 使用方法: class MyFactory(Factory): - def __init__(self): - self.instances = [ - 'test.modules.Demo', - 'test.modules.BaseData', - ] - super().__init__() + modules = { + 'test.modules.Demo', + 'test.modules.BaseData', + } if __name__ == '__main__': @@ -28,7 +38,7 @@ class Factory(object): """ _instance_lock = threading.Lock() - def __init__(self, modules): + def __init__(self, modules, banner=__logo__, **kwargs): try: self.modules = modules except AttributeError: @@ -36,7 +46,7 @@ class Factory(object): 'Please import the Pojo module first,请先设置导入modules模块')) self.module_names = self.modules - # self.__base_init__() + print('%s' % banner) def __base_init__(self): for package_name in self.modules: diff --git a/summer/cacode/Modes.py b/aestate/cacode/Modes.py similarity index 99% rename from summer/cacode/Modes.py rename to aestate/cacode/Modes.py index 99907f0..d264d02 100644 --- a/summer/cacode/Modes.py +++ b/aestate/cacode/Modes.py @@ -295,7 +295,7 @@ if __name__ == '__main__': "e": rep } result = Recursion.find_key_for_dict(data, "a") - from summer.cacode.Serialize import JsonUtil + from aestate.cacode.Serialize import JsonUtil print(JsonUtil.parse(result)) diff --git a/summer/cacode/Serialize.py b/aestate/cacode/Serialize.py similarity index 53% rename from summer/cacode/Serialize.py rename to aestate/cacode/Serialize.py index a927445..62f36c9 100644 --- a/summer/cacode/Serialize.py +++ b/aestate/cacode/Serialize.py @@ -15,14 +15,11 @@ # CACode 1.2 2021/4/27 统一序列化器位置 # ------------------------------------------------------------------ -from summer.cacode.ReviewJson.JSON import Json -from summer.util.Log import CACodeLog -from summer.cacode import ReviewJson -from datetime import date, datetime -import functools - -__version__ = ('Test', 1, 0, 0) +__version__ = ('Test', 1, 0, 1, 'b1') __author__ = 'CACode' + +from ajson import aj + """ 此文件内包含有序列化器所有需要用到的参数 JsonUtil可使用原simplejson部分功能,内嵌simplejson,升级功能包含 @@ -31,184 +28,7 @@ JsonUtil可使用原simplejson部分功能,内嵌simplejson,升级功能包 """ __all__ = ['JsonUtil', 'QuerySet', 'PageHelp'] - - -class JsonUtil(Json): - """作者:CACode 最后编辑于2021/4/27 - Json工具 - JsonUtil.parse(**kwargs):将任意对象解析成json字符串 - JsonUtil.load(**kwargs):将字符串解析成字典 - """ - - @staticmethod - def date_encoder(obj): - if isinstance(obj, datetime): - return obj.strftime('%Y-%m-%d %H:%M:%S') - elif isinstance(obj, date): - return obj.strftime('%Y-%m-%d') - else: - return None - - class JsonDateEncoder(ReviewJson.JSONEncoder): - def default(self, obj): - return JsonUtil.date_encoder(obj) - - class SimplejsonDateEncoder(ReviewJson.JSONEncoder): - def default(self, obj): - return JsonUtil.date_encoder(obj) - - @staticmethod - def parse(obj, bf=False, end_load=False): - """作者:CACode 最后编辑于2021/4/27 - - 将对象转换成字典格式: - 支持: - dict - list - object - list[object] - object[list] - object[list[object]] - ....... - - 注意事项: - - bf和end_load同时只能使用一个 - - 当两者同时存在时,默认使用end_load功能 - - - :param obj:需要解析的对象 - :param bf:是否需要美化json - :param end_load:是否需要在最后转成字典格式 - """ - - def json_to_str(_obj): - """ - json转字符串 - """ - json_f = functools.partial( - JsonUtil.dumps, cls=JsonUtil.JsonDateEncoder) - json_str = json_f(_obj) - return json_str - - def parse_list(list_obj): - """ - 解析list数据的json - 放置了递归函数,所以不必担心解析报错或者解析不到位 - """ - obj_dicts = [] - for item in list_obj: - # 循环集合 - if isinstance(item, list): - # 如果是集合则递归 - obj_dicts.append(parse_list(item)) - elif isinstance(item, tuple): - # 如果是tuple元组则转成集合后递归 - return obj_dicts.append(parse_list(list(item))) - elif isinstance(item, dict) or isinstance(item, str): - # 如果是字典或者字符串,则直接交给obj_dicts填充 - obj_dicts.append(item) - elif isinstance(item, object): - # 如果是object则交给parse_obj()解析 - obj_dicts.append(parse_obj(item)) - else: - obj_dicts.append(item) - return obj_dicts - - def parse_obj(_obj) -> str: - """ - 夺命循环递递归 - """ - obj_dicts = [] - if isinstance(_obj, dict): - _dict = _obj.__dict__ - # 如果是list,则交给parse_list(解决) - for key, item in _dict.items(): - obj_dicts.append({ - key: parse_list(item) - }) - elif isinstance(_obj, list): - # 如果是字典或者字符串,则直接交给obj_dicts填充 - obj_dicts.append(parse_list(_obj)) - # 由于parse_list()中有对于tuple累心的解析,所以不必担心tuple - elif isinstance(_obj, str): - # 如果是字典或者字符串,则直接交给obj_dicts填充 - obj_dicts = _obj - else: - # 如果不是list类型,则直接解析成字典 - try: - obj_dicts = _obj.__dict__ - except AttributeError as e: - obj_dicts = _obj - # 异常警告,抛出 - return obj_dicts - - def parse_dict(_obj): - """作者:CACode 最后编辑于2021/4/27 - 解析字典格式 - """ - obj_dicts = {} - if isinstance(_obj, dict): - for key, value in _obj.items(): - if isinstance(value, list): - obj_dicts[key] = parse_list(value) - elif isinstance(value, dict): - obj_dicts[key] = parse_dict(value) - else: - v = parse_obj(value) - obj_dicts[key] = v - return obj_dicts - - # 如果他是集合并且里面包含的非字典而是object,则将对象转成字典 - if isinstance(obj, list): - obj = parse_list(obj) - elif isinstance(obj, dict): - obj = parse_dict(obj) - elif isinstance(obj, object): - obj = parse_obj(obj) - # 最后的解析结果 - result = json_to_str(obj) - if end_load: - return JsonUtil.load(result) - elif bf: - return JsonUtil.beautiful(JsonUtil.load(result)) - return result - - @staticmethod - def load(item): - """作者:CACode 最后编辑于2021/4/27 - 将json字符串解析成字典 - """ - if isinstance(item, list): - _dats = [] - for i in item: - _dats.append(JsonUtil.load(i)) - return _dats - elif isinstance(item, tuple): - # 如果是tuple元组则转成集合后递归 - _dats = [] - for i in list(item): - _dats.append(JsonUtil.load(i)) - return _dats - elif isinstance(item, dict): - # 如果是字典,则直接返回 - return item - elif isinstance(item, str): - # 如果是字符串则解析为字典 - return JsonUtil.loads(item) - elif isinstance(item, object): - # 如果是object则交给parse_obj()解析 - return item.__dict__ - else: - return JsonUtil.loads(item) - - @staticmethod - def beautiful(_data): - """作者:CACode 最后编辑于2021/4/27 - 美化json - """ - return JsonUtil.dumps(_data, sort_keys=True, indent=4, separators=(',', ':')) +JsonUtil = aj class QuerySet(list): diff --git a/summer/field/__init__.py b/aestate/cacode/__init__.py similarity index 100% rename from summer/field/__init__.py rename to aestate/cacode/__init__.py diff --git a/aestate/exception/__init__.py b/aestate/exception/__init__.py new file mode 100644 index 0000000..c275d95 --- /dev/null +++ b/aestate/exception/__init__.py @@ -0,0 +1,57 @@ +import re + + +class DBException(Exception): + def __init__(self, baseException): + self.baseException = baseException + self.baseName = self.baseException.__class__.__name__ + super(DBException, self).__init__() + + def __str__(self): + return f"({self.baseName}):{str(self.baseException)}" + + +class ModuleCreateError(ModuleNotFoundError): + pass + + +class FieldNotExist(AttributeError): + pass + + +class BaseMySqlError: + def __init__(self, exception): + self.exception = exception + self.text = str(exception) + + def ver(self): + return self.text + + def raise_exception(self): + ar = self.exception.args + ar_array = list(ar) + ar_array[len(ar_array) - 1] = self.text + self.exception.args = ar_array + raise DBException(self.exception) + + +class MySqlErrorRegular: + def __init__(self, text): + self.text = text + self.err_text = text + + def syntax_error(self): + flag = re.compile("You have an error in your SQL syntax[\w\W].*use near([\w\W].*)") + err_content = flag.findall(self.text) + if err_content: + self.err_text = "sql语句拼写错误,错误内容:(%s)" % err_content[0] + return self.err_text + + +class MySqlErrorTest(BaseMySqlError): + + def ver(self): + mer = MySqlErrorRegular(self.text) + err_text = mer.syntax_error() + self.text = err_text + return err_text diff --git a/summer/exception/e_fields.py b/aestate/exception/e_fields.py similarity index 100% rename from summer/exception/e_fields.py rename to aestate/exception/e_fields.py diff --git a/summer/field/FManage.py b/aestate/field/FManage.py similarity index 100% rename from summer/field/FManage.py rename to aestate/field/FManage.py diff --git a/summer/field/MySqlDefault.py b/aestate/field/MySqlDefault.py similarity index 98% rename from summer/field/MySqlDefault.py rename to aestate/field/MySqlDefault.py index 87ae5f3..6d96d0c 100644 --- a/summer/field/MySqlDefault.py +++ b/aestate/field/MySqlDefault.py @@ -2,7 +2,7 @@ # 空格符 import threading -from summer.cacode.Modes import Singleton +from aestate.cacode.Modes import Singleton class MySqlFields_Default: diff --git a/summer/opera/__init__.py b/aestate/field/__init__.py similarity index 100% rename from summer/opera/__init__.py rename to aestate/field/__init__.py diff --git a/summer/field/tag.py b/aestate/field/tag.py similarity index 99% rename from summer/field/tag.py rename to aestate/field/tag.py index c6ec889..a18a656 100644 --- a/summer/field/tag.py +++ b/aestate/field/tag.py @@ -1,6 +1,6 @@ import datetime -from summer.cacode.Serialize import JsonUtil +from aestate.cacode.Serialize import JsonUtil """ 这个文件用来为pojo对象做标记,当对象为空或为以下任意类型时 diff --git a/summer/opera/DBPool/__init__.py b/aestate/opera/DBPool/__init__.py similarity index 100% rename from summer/opera/DBPool/__init__.py rename to aestate/opera/DBPool/__init__.py diff --git a/summer/opera/DBPool/persistent_db.py b/aestate/opera/DBPool/persistent_db.py similarity index 100% rename from summer/opera/DBPool/persistent_db.py rename to aestate/opera/DBPool/persistent_db.py diff --git a/summer/opera/DBPool/persistent_pg.py b/aestate/opera/DBPool/persistent_pg.py similarity index 100% rename from summer/opera/DBPool/persistent_pg.py rename to aestate/opera/DBPool/persistent_pg.py diff --git a/summer/opera/DBPool/pooled_db.py b/aestate/opera/DBPool/pooled_db.py similarity index 100% rename from summer/opera/DBPool/pooled_db.py rename to aestate/opera/DBPool/pooled_db.py diff --git a/summer/opera/DBPool/pooled_pg.py b/aestate/opera/DBPool/pooled_pg.py similarity index 100% rename from summer/opera/DBPool/pooled_pg.py rename to aestate/opera/DBPool/pooled_pg.py diff --git a/summer/opera/DBPool/simple_pooled_db.py b/aestate/opera/DBPool/simple_pooled_db.py similarity index 100% rename from summer/opera/DBPool/simple_pooled_db.py rename to aestate/opera/DBPool/simple_pooled_db.py diff --git a/summer/opera/DBPool/simple_pooled_pg.py b/aestate/opera/DBPool/simple_pooled_pg.py similarity index 100% rename from summer/opera/DBPool/simple_pooled_pg.py rename to aestate/opera/DBPool/simple_pooled_pg.py diff --git a/summer/opera/DBPool/steady_db.py b/aestate/opera/DBPool/steady_db.py similarity index 100% rename from summer/opera/DBPool/steady_db.py rename to aestate/opera/DBPool/steady_db.py diff --git a/summer/opera/DBPool/steady_pg.py b/aestate/opera/DBPool/steady_pg.py similarity index 100% rename from summer/opera/DBPool/steady_pg.py rename to aestate/opera/DBPool/steady_pg.py diff --git a/summer/util/__init__.py b/aestate/opera/__init__.py similarity index 100% rename from summer/util/__init__.py rename to aestate/opera/__init__.py diff --git a/summer/opera/global_db.py b/aestate/opera/global_db.py similarity index 95% rename from summer/opera/global_db.py rename to aestate/opera/global_db.py index 1d4840e..2cb6bc9 100644 --- a/summer/opera/global_db.py +++ b/aestate/opera/global_db.py @@ -1,9 +1,9 @@ import sys import threading -from summer.cacode.Modes import Singleton -from summer.exception import DBException -from summer.util.Log import CACodeLog +from aestate.cacode.Modes import Singleton +from aestate.exception import MySqlErrorTest +from aestate.util.Log import CACodeLog def parse_kwa(db, **kwargs): @@ -32,7 +32,7 @@ def parse_kwa(db, **kwargs): CACodeLog.log(obj=db, line=_l, task_name='Print Sql', msg=msg) if many_flay: - cursor.executemany(kwargs['sql'], kwargs['pojo_data']) + cursor.executemany(kwargs['sql'], kwargs['params']) else: if 'params' in kwargs and kwargs['params']: cursor.execute(kwargs['sql'], tuple(kwargs['params'])) @@ -41,7 +41,9 @@ def parse_kwa(db, **kwargs): return cursor except Exception as e: db.rollback() - raise e + mysql_err = MySqlErrorTest(e) + mysql_err.ver() + mysql_err.raise_exception() class Db_opera(object): @@ -134,7 +136,7 @@ class Db_opera(object): 初始化数据库连接池 """ if self.POOL is None: - from summer.opera.DBPool.pooled_db import PooledDB + from aestate.opera.DBPool.pooled_db import PooledDB self.POOL = PooledDB(creator=self.creator, maxconnections=self.maxconnections, mincached=self.mincached, maxcached=self.maxcached, maxshared=self.maxshared, @@ -183,7 +185,7 @@ class Db_opera(object): return _result except Exception as e: db.rollback() - raise DBException(e) + raise e finally: db.close() @@ -211,7 +213,7 @@ class Db_opera(object): return rowcount except Exception as e: db.rollback() - raise DBException(e) + raise e finally: db.close() diff --git a/summer/opera/op_db.py b/aestate/opera/op_db.py similarity index 81% rename from summer/opera/op_db.py rename to aestate/opera/op_db.py index 8d219e6..cd5b509 100644 --- a/summer/opera/op_db.py +++ b/aestate/opera/op_db.py @@ -1,6 +1,6 @@ -from summer.util.Log import CACodeLog +from aestate.util.Log import CACodeLog -from summer.util.ParseUtil import ParseUtil +from aestate.util.ParseUtil import ParseUtil from concurrent.futures import ThreadPoolExecutor pool = ThreadPoolExecutor() @@ -54,7 +54,8 @@ class DbOperation(object): 任务方法 """ - fields = ParseUtil().parse_key(*args, is_field=True) + fields = kwargs['config_obj'].parse_key(*args, is_field=True, left=kwargs['sqlFields'].left_subscript, + right=kwargs['sqlFields'].right_subscript) sql_str = kwargs['sqlFields'].find_str + fields + kwargs['sqlFields'].from_str + kwargs['__table_name__'] kwargs['sql'] = sql_str self.result = self.__find_many__(**kwargs) @@ -96,14 +97,17 @@ class DbOperation(object): ParseUtil.fieldExist(kwargs, 'pojo', raise_exception=True) if 'many' in kwargs and kwargs['many']: - # 多行插入 - filed_list = kwargs['config_obj'].parse_insert_pojo(kwargs['pojo'][0], - __table_name__=kwargs['__table_name__'], - insert_str=kwargs['sqlFields'].insert_str, - values_str=kwargs['sqlFields'].values_str) - - kwargs['pojo_data'] = ParseUtil.parse_pojo_many(pojo_many=kwargs['pojo']) - kwargs.update(filed_list) + # 多行插入 这个先取出sql语句,params无作用 + for item in kwargs['pojo']: + filed_list = kwargs['config_obj'].parse_insert_pojo(item, + __table_name__=kwargs['__table_name__'], + insert_str=kwargs['sqlFields'].insert_str, + values_str=kwargs['sqlFields'].values_str) + + if 'params' not in kwargs.keys() or not isinstance(kwargs['params'], list): + kwargs['params'] = [] + kwargs['sql'] = filed_list['sql'] + kwargs['params'].append(filed_list['params']) self.result = kwargs['db_util'].insert(**kwargs) return self.result else: diff --git a/summer/util/CompulsoryRun.py b/aestate/util/CompulsoryRun.py similarity index 93% rename from summer/util/CompulsoryRun.py rename to aestate/util/CompulsoryRun.py index 0d67e56..2757883 100644 --- a/summer/util/CompulsoryRun.py +++ b/aestate/util/CompulsoryRun.py @@ -33,8 +33,8 @@ class Compulsory(object): 深度搜素树 """ - from summer.exception import e_fields - from summer.util.Log import CACodeLog + from aestate.exception import e_fields + from aestate.util.Log import CACodeLog if len(target_names) == 0: return module diff --git a/summer/util/Log.py b/aestate/util/Log.py similarity index 85% rename from summer/util/Log.py rename to aestate/util/Log.py index 70930eb..1787d5e 100644 --- a/summer/util/Log.py +++ b/aestate/util/Log.py @@ -1,21 +1,20 @@ import datetime import os -import re import sys -import time import threading -from summer.cacode.Modes import Singleton -from summer.exception import e_fields +from aestate.cacode.Modes import Singleton +from aestate.exception import e_fields +from aestate.util import messy class FieldsLength: DATETIME_FORMAT = 27 INFO_FORMAT = 10 - LINE_FORMAT = 10 + LINE_FORMAT = 13 OPERATION_FORMAT = 32 HEX_FORMAT = 17 - CLASS_FORMAT = 80 - TASK_FORMAT = 10 + CLASS_FORMAT = 70 + TASK_FORMAT = 15 class ConsoleColor: @@ -95,18 +94,6 @@ class ConsoleWrite: print(out) -def date_format(time_obj=time, fmt='%Y-%m-%d %H:%M:%S'): - """ - 时间转字符串 - :param time_obj: - :param fmt: - :return: - """ - _tm = time_obj.time() - _t = time.localtime(_tm) - return time.strftime(fmt, _t) - - def write(path, content, max_size): """ 写出文件 @@ -160,7 +147,7 @@ class CACodeLog(object): self.save_flag = save_flag @staticmethod - def log(msg, obj=None, line=sys._getframe().f_back.f_lineno, operation_name=e_fields.Log_Opera_Name("Task"), + def log(msg, obj=None, line=sys._getframe().f_back.f_lineno, task_name='Task', LogObject=None, field=e_fields.Info(), func=None, consoleWriteObj=ConsoleWrite()): """ @@ -174,29 +161,31 @@ class CACodeLog(object): """ + def fullname(o): + + module = o.__class__.__module__ + if module is None or module == str.__class__.__module__: + return o.__class__.__name__ # Avoid reporting __builtin__ + else: + return module + '.' + o.__class__.__name__ + # 格式:时间 类型 日志名称 对象地址 被调用行号 执行类型 信息 t = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3] - # format(t, - # e_fields.Info(), - # e_fields.Log_Opera_Name(task_name), - # hex(id(obj)), - # obj.__str__(), - # task_name, - # msg) try: if obj is not None: - repr = re.findall(r'<.*>', obj.__repr__()) - repr = repr[0] if repr else None - cc = repr[1:len(repr) - 1] - repr_c = re.findall(r'<.*>', cc) - if repr and not repr_c: - write_repr = repr - elif repr_c: - write_repr = repr_c[0] - else: - write_repr = type(obj) + write_repr = fullname(obj) + # repr = re.findall(r'<.*>', obj.__repr__()) + # repr = repr[0] if repr else None + # cc = repr[1:len(repr) - 1] + # repr_c = re.findall(r'<.*>', cc) + # if repr and not repr_c: + # write_repr = repr + # elif repr_c: + # write_repr = repr_c[0] + # else: + # write_repr = type(obj) else: write_repr = 'OBJECT IS NULL' except TypeError as err: @@ -205,13 +194,12 @@ class CACodeLog(object): t = f"[{t}]".ljust(FieldsLength.DATETIME_FORMAT) field = f"[{field}]".ljust(FieldsLength.INFO_FORMAT) line = f"[line:{line}]".ljust(FieldsLength.LINE_FORMAT) - operation_name = f"[{operation_name}]".ljust(FieldsLength.OPERATION_FORMAT) hex_id = f"[{hex(id(obj))}]".ljust(FieldsLength.HEX_FORMAT) write_repr = f"[{write_repr}]".ljust(FieldsLength.CLASS_FORMAT) task_name = f"[{task_name}]".ljust(FieldsLength.TASK_FORMAT) - msg = f"\t\t:{msg}" + msg = f":{msg}" - info = "{}{}{}{}{}{}{}{}".format(t, field, line, operation_name, hex_id, write_repr, task_name, msg) + info = "{}{}{}{}{}{}{}".format(t, field, line, hex_id, write_repr, task_name, msg) ConsoleWrite.write(messages=info, consoleWriteObj=consoleWriteObj) # 输出日志信息 # file = sys.stdout @@ -298,7 +286,7 @@ class CACodeLog(object): :return: """ path = self.get_path(path_str) - _date = date_format() + _date = messy.date_format() # _log = '[%s]\t[%s] - %s\r\n' % (_date, 'content', str(content)) if self.print_flag: self.log(content) diff --git a/summer/util/ParseUtil.py b/aestate/util/ParseUtil.py similarity index 91% rename from summer/util/ParseUtil.py rename to aestate/util/ParseUtil.py index 418a9f7..b47cac0 100644 --- a/summer/util/ParseUtil.py +++ b/aestate/util/ParseUtil.py @@ -2,14 +2,15 @@ import copy from typing import List -from summer.exception import FieldNotExist -from summer.field import tag -from summer.util.Log import CACodeLog +from aestate.exception import FieldNotExist +from aestate.field import tag +from aestate.util import messy +from aestate.util.Log import CACodeLog -class ParseUtil(object): +class ParseUtil: - def parse_main(self, *args, to_str=False, is_field=False, symbol='%s'): + def parse_main(self, *args, to_str=False, symbol='%s', left='`', right='`', **kwargs): """ 解析属性: 将属性格式设置为:['`a`,','`b`,','`c`'] @@ -17,13 +18,19 @@ class ParseUtil(object): :param args:参数 :param is_field:是否为表字段格式 :param symbol:分隔符语法 + :param left:分隔符语法 + :param right:分隔符语法 :return: """ + + is_field = kwargs['is_field'] if 'is_field' in kwargs.keys() else False + fields = [] for value in args: + value = messy.conversion_types(value) if to_str: if is_field: - fields.append(f'`{symbol}`,' % (str(value))) + fields.append(f'{left}{symbol}{right},' % (str(value))) else: fields.append(f'{symbol},' % (str(value))) else: @@ -46,6 +53,8 @@ class ParseUtil(object): :param args: :return: """ + if 'is_field' not in kwargs.keys(): + kwargs['is_field'] = True fields = self.parse_main(*args, to_str=True, **kwargs) return fields @@ -87,8 +96,7 @@ class ParseUtil(object): kes = {'sql': sql} args = [] - for i in values: - args.append(i) + [args.append(i) for i in values] kes['params'] = args return kes @@ -136,13 +144,13 @@ class ParseUtil(object): @staticmethod def parse_obj(data: dict, instance: object) -> object: """ - 将数据解析成对象 - 注意事项: - 数据来源必须是DbUtil下查询出来的 - :param data:单行数据 - :param instance:参与解析的对象 - :return:POJO对象 - """ + 将数据解析成对象 + 注意事项: + 数据来源必须是DbUtil下查询出来的 + :param data:单行数据 + :param instance:参与解析的对象 + :return:POJO对象 + """ # 深度复制对象 part_obj = copy.copy(instance) for key, value in data.items(): diff --git a/test/__init__.py b/aestate/util/__init__.py similarity index 100% rename from test/__init__.py rename to aestate/util/__init__.py diff --git a/aestate/util/messy.py b/aestate/util/messy.py new file mode 100644 index 0000000..b5614c0 --- /dev/null +++ b/aestate/util/messy.py @@ -0,0 +1,41 @@ +# -*- utf-8 -*- +# @Time: 2021/5/30 10:17 +# @Author: CACode +import time +from datetime import datetime + + +def conversion_types(val): + """ + 将val的类型转换为字符串并插入array + """ + if isinstance(val, datetime): + val = val.strftime('%Y-%m-%d %H:%M:%S') + return val + + +def date_format(time_obj=time, fmt='%Y-%m-%d %H:%M:%S'): + """ + 时间转字符串 + :param time_obj: + :param fmt: + :return: + """ + _tm = time_obj.time() + _t = time.localtime(_tm) + return time.strftime(fmt, _t) + + +def datetime_to_time(d_time): + pass + + +def time_to_datetime(t_time): + """ + 时间戳转datetime + """ + try: + d_time = datetime.fromtimestamp(t_time) + except OSError as ose: + return None + return d_time diff --git a/aestate/util/others.py b/aestate/util/others.py new file mode 100644 index 0000000..856ebb2 --- /dev/null +++ b/aestate/util/others.py @@ -0,0 +1,65 @@ +# 社会因懒人而得到进步 +class DictTemplate(object): + """ + 字典对象模板 + """ + + def __init__(self, init_data): + self.init_data = init_data + + def add(self, key, obj): + setattr(self, key, obj) + + +class DictToObject(object): + """ + 将字典转成对象,解决懒得写中括号 + """ + + def __init__(self, dict_data): + baseClass = DictTemplate(dict_data) + self.dict_data = dict_data + self.baseNode = baseClass + self.verification(self.baseNode, self.dict_data) + + @staticmethod + def conversion(dict_data: dict): + node = DictToObject(dict_data) + return node.baseNode + + def verification(self, node: DictTemplate, value): + """ + 验证模块 + """ + node.init_data = value + if isinstance(value, dict): + for key, val in value.items(): + if isinstance(val, (dict, list, tuple)): + val = self.verification(DictTemplate(val), val) + node.add(key, val) + + elif isinstance(value, list): + list_temp = [] + for val in value: + if isinstance(val, (dict, list, tuple)): + val = self.verification(DictTemplate(val), val) + list_temp.append(val) + node.add('', list_temp) + + return node + + +if __name__ == '__main__': + dict_data = { + 'a': 1, + 'b': { + 'a': [1] + }, + 'c': [ + { + 'a': 1 + } + ] + } + d = DictToObject.conversion(dict_data) + print(d.c) diff --git a/aestate/work/Annotation.py b/aestate/work/Annotation.py new file mode 100644 index 0000000..9198846 --- /dev/null +++ b/aestate/work/Annotation.py @@ -0,0 +1,189 @@ +from aestate.work.AopContainer import AopModelObject + + +def Table(name, msg, **kwargs): + """ + 标注该类为一个表 + :param name:表的名称 + :param msg:表的描述 + :return: + """ + + def set_to_field(cls): + setattr(cls, '__table_name__', name) + setattr(cls, '__table_msg__', msg) + for key, value in kwargs.items(): + setattr(cls, key, value) + return cls + + return set_to_field + + +def parse_kwargs(params, kwargs): + """ + 通过${key}方式解析特殊字段 + """ + import re + new_args = [] + for i in params: + # 反选字符并替换 + sub = re.sub(r'\${(.*?)}', '{}', str(i)) + context = re.findall(r'\${(.*?)}', str(i)) + if context: + mk = [] + for con in context: + mk.append(kwargs[con]) + # 将字符格式化进sub + sfm = sub.format(*mk) + new_args.append(sfm) + + else: + new_args.append(i) + + return new_args + + +def Select(sql, params=None): + """ + 快捷的查询装饰器 + + 使用此装饰器,可以将大量重复代码继承到此装饰器内部实现 + + 使用方法: + @Select(sql="SELECT * FROM demo_table WHERE t_id<=%s AND t_msg like %s", params=['${t_id}', '%${t_msg}%']) + + sql:执行的sql语句,需要加密的参数使用`%s`表示 + + params:加密参数的内容,标记使用传参请使用`${字段名}`表示 + + + + """ + + def base_func(cls): + def _wrapper_(*args, **kwargs): + lines = list(args) + obj = lines[0] + del lines[0] + # cls_obj = cls(*lines, **kwargs) + + new_args = parse_kwargs(params, kwargs) + + result = obj.find_sql(sql=sql, params=new_args) + from aestate.cacode.Serialize import QuerySet + return QuerySet(obj, result) + + return _wrapper_ + + return base_func + + +def AopModel(before=None, after=None, + before_args=None, before_kwargs=None, + after_args=None, after_kwargs=None): + """ + + AOP切面模式: + 依赖AopModel装饰器,再在方法上加入@AopModel即可切入编程 + + + 优点: + + 当使用@AopModel时,内部函数将会逐级调用回调函数,执行循序是: + - func(*self.args, **self.kwargs) + - func(*self.args) + - func(**self.kwargs) + - func() + 这将意味着,如果你的参数传入错误时,AopModel依旧会遵循原始方法所使用的规则,最令人大跌眼镜的使用方法就是: + + def Before(**kwargs): + print('Before:', kwargs) + # 此处的Before方法未存在args参数,而使用@AopModel时却传入了args + @AopModel(before=Before,before_args=(0,1,2), before_kwargs={'1': '1'}) + def find_title_and_selects(self, **kwargs): + + print('function task', kwargs['uid']) + + _r = self.orm.find().where(index="<<100").end() + + print(_r) + + return _r + + 其中包含参数有: + before:切入时需要执行的函数 + + before_args:切入的参数 + 传入的列表或元组类型数据 + 如果是需要使用当前pojo中的内容时,传参格式为:(pojo.字段名) + 可扩展格式,例如需要传入字典 + + before_kwargs:切入的参数 -- 传入的字典数据 + + after:切出前需要执行的参数 + + after_args:切出的参数 + 传入的列表或元组类型数据 + 如果是需要使用当前pojo中的内容时,传参格式为:('self.字段名') + 可扩展格式,例如需要传入字典:('self.dict.key') + + after_kwargs:切出的参数 -- 传入的字典数据 + + + 执行流程: + + Before->original->After + + Before注意事项: + + 使用该参数时,方法具有返回值概不做处理,需要返回值内容可使用`global`定义一个全局字段用于保存数值 + + 当无法解析或者解析失败时m将使用pass关键字忽略操作 + + After注意事项: + + 使用该参数时,必须搭配至少一个result=None的kwargs存在于方法的形参中, + + 当original方法执行完成将把返回值固定使用result键值对注入到该函数中 + + 当无法解析或者解析失败时m将使用pass关键字忽略操作 + + + + Attributes: + + before:切入时需要执行的函数 + + after:切出前需要执行的参数 + + before_args:切入的参数 + 传入的列表或元组类型数据 + 如果是需要使用当前pojo中的内容时,传参格式为:(pojo.字段名) + 可扩展格式,例如需要传入字典 + + before_kwargs:切入的参数 -- 传入的字典数据 + + after_args:切出的参数 + 传入的列表或元组类型数据 + 如果是需要使用当前pojo中的内容时,传参格式为:('self.字段名') + 可扩展格式,例如需要传入字典:('self.dict.key') + + after_kwargs:切出的参数 -- 传入的字典数据 + + + """ + # 得到对象组 + aop_obj = AopModelObject(before, after, + before_args, before_kwargs, + after_args, after_kwargs) + + def base_func(func): + aop_obj.func = func + + def _wrapper_(*args, **kwargs): + aop_obj.set_args(*args, **kwargs) + return aop_obj.start() + + return _wrapper_ + + return base_func diff --git a/summer/work/AopContainer.py b/aestate/work/AopContainer.py similarity index 99% rename from summer/work/AopContainer.py rename to aestate/work/AopContainer.py index c5d6dcb..a89224a 100644 --- a/summer/work/AopContainer.py +++ b/aestate/work/AopContainer.py @@ -1,6 +1,6 @@ import types -from summer.util.CompulsoryRun import Compulsory +from aestate.util.CompulsoryRun import Compulsory class AopModelObject(object): diff --git a/summer/work/Config.py b/aestate/work/Config.py similarity index 90% rename from summer/work/Config.py rename to aestate/work/Config.py index 5113ca5..bb8fb5e 100644 --- a/summer/work/Config.py +++ b/aestate/work/Config.py @@ -1,8 +1,8 @@ -from summer.cacode.Serialize import JsonUtil -from summer.exception import FieldNotExist -from summer.util.Log import CACodeLog -from summer.util.ParseUtil import ParseUtil -from summer.work.SummerAdapter import LanguageAdapter +from aestate.cacode.Serialize import JsonUtil +from aestate.exception import FieldNotExist +from aestate.util.Log import CACodeLog +from aestate.util.ParseUtil import ParseUtil +from aestate.work.SummerAdapter import LanguageAdapter class Conf(ParseUtil): diff --git a/summer/work/Manage.py b/aestate/work/Manage.py similarity index 95% rename from summer/work/Manage.py rename to aestate/work/Manage.py index 89db2d8..b8bd786 100644 --- a/summer/work/Manage.py +++ b/aestate/work/Manage.py @@ -1,11 +1,11 @@ __all__ = ['Pojo', 'tag'] __version__ = '1.0.0pre1' -from summer.cacode.Serialize import QuerySet -from summer.work.orm import CACodePureORM -from summer.field import tag -from summer.cacode.Serialize import JsonUtil -from summer.work import repository +from aestate.cacode.Serialize import QuerySet +from aestate.work.orm import CACodePureORM +from aestate.field import tag +from aestate.cacode.Serialize import JsonUtil +from aestate.work import repository class Pojo(repository.Repository): diff --git a/summer/work/SummerAdapter.py b/aestate/work/SummerAdapter.py similarity index 100% rename from summer/work/SummerAdapter.py rename to aestate/work/SummerAdapter.py diff --git a/summer/work/__init__.py b/aestate/work/__init__.py similarity index 100% rename from summer/work/__init__.py rename to aestate/work/__init__.py diff --git a/summer/anno/annos.py b/aestate/work/annos.py similarity index 98% rename from summer/anno/annos.py rename to aestate/work/annos.py index 459c52b..bda66fc 100644 --- a/summer/anno/annos.py +++ b/aestate/work/annos.py @@ -1,4 +1,4 @@ -from summer.work.AopContainer import AopModelObject +from .AopContainer import AopModelObject def Table(name, msg, **kwargs): @@ -70,7 +70,7 @@ def Select(sql, params=None): new_args = parse_kwargs(params, kwargs) result = obj.find_sql(sql=sql, params=new_args) - from summer.cacode.Serialize import QuerySet + from aestate.cacode.Serialize import QuerySet return QuerySet(obj, result) return _wrapper_ diff --git a/summer/work/orm.py b/aestate/work/orm.py similarity index 96% rename from summer/work/orm.py rename to aestate/work/orm.py index 70e0dcd..0fce59f 100644 --- a/summer/work/orm.py +++ b/aestate/work/orm.py @@ -1,5 +1,5 @@ -from summer.exception import e_fields -from summer.util.Log import CACodeLog +from aestate.exception import e_fields +from aestate.util.Log import CACodeLog class CACodePureORM(object): @@ -212,15 +212,15 @@ s """ if len(str(value)) > 2 and str(value)[0:2] in self.sqlFields.symbol: sym = value[0:2] value = str(value)[2:len(str(value))] - elif sym == '==': - sym = '=' - elif sym == '>>': - sym = '>' - elif sym == '<<': - sym = '<' + if sym == '==': + sym = '=' + elif sym == '>>': + sym = '>' + elif sym == '<<': + sym = '<' + # 没有找到符号的话就从字段名开始 + # 截取最后一段从两段下划线开始的末尾 else: - # 没有找到符号的话就从字段名开始 - # 截取最后一段从两段下划线开始的末尾 sps = cp_key.split('__') if not len(sps) == 1: customize = True @@ -404,3 +404,7 @@ s """ q = self.serializer( instance=self.repository.instance, base_data=self._result) return q + + def __str__(self): + sql = ''.join(self.args) + return sql diff --git a/summer/work/repository.py b/aestate/work/repository.py similarity index 97% rename from summer/work/repository.py rename to aestate/work/repository.py index ac98034..9e892d5 100644 --- a/summer/work/repository.py +++ b/aestate/work/repository.py @@ -1,12 +1,12 @@ import copy -from summer.cacode.Serialize import QuerySet -from summer.exception import e_fields -from summer.field import MySqlDefault -from summer.opera import op_db, global_db -from summer.util.Log import CACodeLog +from aestate.cacode.Serialize import QuerySet +from aestate.exception import e_fields +from aestate.field import MySqlDefault +from aestate.opera import op_db, global_db +from aestate.util.Log import CACodeLog -from summer.work.orm import CACodePureORM +from aestate.work.orm import CACodePureORM # 每个任务唯一ID import uuid @@ -89,7 +89,7 @@ class Repository: # 有没有表名 ParseUtil.set_field_compulsory(self, key='__table_name__', data=kwargs, val=self.__table_name__ if hasattr(self, '__table_name__') else - "`__table_name__` parsing failed") + '"__table_name__" parsing failed') # 参照对象 ParseUtil.set_field_compulsory(self, key='instance', data=kwargs, val=instance) # 取得字段的名称 diff --git a/example/db_base.py b/example/db_base.py index c7df4ba..6c6b398 100644 --- a/example/db_base.py +++ b/example/db_base.py @@ -3,7 +3,7 @@ # @Author: CACode import pymysql -from summer.work.Config import Conf +from aestate.work.Config import Conf class db_conf(Conf): @@ -28,7 +28,7 @@ class db_conf(Conf): creator=pymysql) -from summer.work import Manage +from aestate.work import Manage class table_template(Manage.Pojo): @@ -63,7 +63,7 @@ class table_template(Manage.Pojo): **kwargs) -from summer.cacode.Factory import Factory +from aestate.cacode.Factory import Factory class MyFactory(Factory): diff --git a/example/tables/demoModels.py b/example/tables/demoModels.py index dbdd825..ec2f8ca 100644 --- a/example/tables/demoModels.py +++ b/example/tables/demoModels.py @@ -2,8 +2,8 @@ # @Time: 2021/5/25 0:04 # @Author: CACode from example.db_base import table_template -from summer.anno.annos import Table -from summer.work import Manage +from aestate.work.annos import Table +from aestate.work import Manage # 使用装示器设置表的名称,name和msg是必填字段,name为表的名称,msg为表的注释 diff --git a/setup.py b/setup.py index 52341dc..84e59a0 100644 --- a/setup.py +++ b/setup.py @@ -3,9 +3,14 @@ import setuptools with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read() +pa = setuptools.find_packages() +print(pa) +pa = ['aestate', 'aestate.cacode', 'aestate.exception', 'aestate.field', 'aestate.opera', + 'aestate.util', 'aestate.work', 'aestate.opera.DBPool'] + setuptools.setup( name="aestate", - version="1.0.0b3", + version="1.0.1", author="CACode", author_email="cacode@163.com", description="Aestate framework for Python,You can see:https://gitee.com/cacode_cctvadmin/aestate", @@ -21,6 +26,7 @@ setuptools.setup( "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", ], - packages=setuptools.find_packages(), + packages=pa, python_requires=">=3.6", + setup_requires=['aestate-json'] ) diff --git a/summer/cacode/ReviewJson/JSON.py b/summer/cacode/ReviewJson/JSON.py deleted file mode 100644 index f2319f0..0000000 --- a/summer/cacode/ReviewJson/JSON.py +++ /dev/null @@ -1,82 +0,0 @@ -__version__ = '1.0.0' -__all__ = [ - 'Json' -] - -__author__ = 'CACode ' - -from . import _default_encoder, JSONEncoder, _default_decoder, JSONDecoder -from decimal import Decimal - - -class Json: - - @staticmethod - def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, - allow_nan=True, cls=None, indent=None, separators=None, - encoding='utf-8', default=None, use_decimal=True, - namedtuple_as_object=True, tuple_as_array=True, - bigint_as_string=False, sort_keys=False, item_sort_key=None, - for_json=False, ignore_nan=False, int_as_string_bitcount=None, - iterable_as_array=False, **kw): - """ - 转json字符串 - """ - if (not skipkeys and ensure_ascii and - check_circular and allow_nan and - cls is None and indent is None and separators is None and - encoding == 'utf-8' and default is None and use_decimal - and namedtuple_as_object and tuple_as_array and not iterable_as_array - and not bigint_as_string and not sort_keys - and not item_sort_key and not for_json - and not ignore_nan and int_as_string_bitcount is None - and not kw - ): - return _default_encoder.encode(obj) - if cls is None: - cls = JSONEncoder - return cls( - skipkeys=skipkeys, ensure_ascii=ensure_ascii, - check_circular=check_circular, allow_nan=allow_nan, indent=indent, - separators=separators, encoding=encoding, default=default, - use_decimal=use_decimal, - namedtuple_as_object=namedtuple_as_object, - tuple_as_array=tuple_as_array, - iterable_as_array=iterable_as_array, - bigint_as_string=bigint_as_string, - sort_keys=sort_keys, - item_sort_key=item_sort_key, - for_json=for_json, - ignore_nan=ignore_nan, - int_as_string_bitcount=int_as_string_bitcount, - **kw).encode(obj) - - @staticmethod - def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, - parse_int=None, parse_constant=None, object_pairs_hook=None, - use_decimal=False, **kw): - """ - json转字典 - """ - if (cls is None and encoding is None and object_hook is None and - parse_int is None and parse_float is None and - parse_constant is None and object_pairs_hook is None - and not use_decimal and not kw): - return _default_decoder.decode(s) - if cls is None: - cls = JSONDecoder - if object_hook is not None: - kw['object_hook'] = object_hook - if object_pairs_hook is not None: - kw['object_pairs_hook'] = object_pairs_hook - if parse_float is not None: - kw['parse_float'] = parse_float - if parse_int is not None: - kw['parse_int'] = parse_int - if parse_constant is not None: - kw['parse_constant'] = parse_constant - if use_decimal: - if parse_float is not None: - raise TypeError("use_decimal=True implies parse_float=Decimal") - kw['parse_float'] = Decimal - return cls(encoding=encoding, **kw).decode(s) diff --git a/summer/cacode/ReviewJson/__init__.py b/summer/cacode/ReviewJson/__init__.py deleted file mode 100644 index bf96527..0000000 --- a/summer/cacode/ReviewJson/__init__.py +++ /dev/null @@ -1,58 +0,0 @@ -from __future__ import absolute_import - -__version__ = '1.0.0' -__all__ = [ - 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder', - 'OrderedDict', 'RawJSON' -] - -__author__ = 'CACode ' - -from .errors import JSONDecodeError -from .raw_json import RawJSON -from .decoder import JSONDecoder -from .encoder import JSONEncoder, JSONEncoderForHTML - - -def _import_OrderedDict(): - import collections - try: - return collections.OrderedDict - except AttributeError: - from . import ordered_dict - return ordered_dict.OrderedDict - - -OrderedDict = _import_OrderedDict() - - -def _import_c_make_encoder(): - try: - from ._speedups import make_encoder - return make_encoder - except ImportError: - return None - - -_default_encoder = JSONEncoder( - skipkeys=False, - ensure_ascii=True, - check_circular=True, - allow_nan=True, - indent=None, - separators=None, - encoding='utf-8', - default=None, - use_decimal=True, - namedtuple_as_object=True, - tuple_as_array=True, - iterable_as_array=False, - bigint_as_string=False, - item_sort_key=None, - for_json=False, - ignore_nan=False, - int_as_string_bitcount=None, -) - -_default_decoder = JSONDecoder(encoding=None, object_hook=None, - object_pairs_hook=None) diff --git a/summer/cacode/ReviewJson/_speedups.c b/summer/cacode/ReviewJson/_speedups.c deleted file mode 100644 index e710128..0000000 --- a/summer/cacode/ReviewJson/_speedups.c +++ /dev/null @@ -1,3384 +0,0 @@ -/* -*- mode: C; c-file-style: "python"; c-basic-offset: 4 -*- */ -#include "Python.h" -#include "structmember.h" - -#if PY_MAJOR_VERSION >= 3 -#define PyInt_FromSsize_t PyLong_FromSsize_t -#define PyInt_AsSsize_t PyLong_AsSsize_t -#define PyInt_Check(obj) 0 -#define PyInt_CheckExact(obj) 0 -#define JSON_UNICHR Py_UCS4 -#define JSON_InternFromString PyUnicode_InternFromString -#define PyString_GET_SIZE PyUnicode_GET_LENGTH -#define PY2_UNUSED -#define PY3_UNUSED UNUSED -#else /* PY_MAJOR_VERSION >= 3 */ -#define PY2_UNUSED UNUSED -#define PY3_UNUSED -#define PyBytes_Check PyString_Check -#define PyUnicode_READY(obj) 0 -#define PyUnicode_KIND(obj) (sizeof(Py_UNICODE)) -#define PyUnicode_DATA(obj) ((void *)(PyUnicode_AS_UNICODE(obj))) -#define PyUnicode_READ(kind, data, index) ((JSON_UNICHR)((const Py_UNICODE *)(data))[(index)]) -#define PyUnicode_GET_LENGTH PyUnicode_GET_SIZE -#define JSON_UNICHR Py_UNICODE -#define JSON_InternFromString PyString_InternFromString -#endif /* PY_MAJOR_VERSION < 3 */ - -#if PY_VERSION_HEX < 0x02070000 -#if !defined(PyOS_string_to_double) -#define PyOS_string_to_double json_PyOS_string_to_double -static double -json_PyOS_string_to_double(const char *s, char **endptr, PyObject *overflow_exception); -static double -json_PyOS_string_to_double(const char *s, char **endptr, PyObject *overflow_exception) -{ - double x; - assert(endptr == NULL); - assert(overflow_exception == NULL); - PyFPE_START_PROTECT("json_PyOS_string_to_double", return -1.0;) - x = PyOS_ascii_atof(s); - PyFPE_END_PROTECT(x) - return x; -} -#endif -#endif /* PY_VERSION_HEX < 0x02070000 */ - -#if PY_VERSION_HEX < 0x02060000 -#if !defined(Py_TYPE) -#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) -#endif -#if !defined(Py_SIZE) -#define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size) -#endif -#if !defined(PyVarObject_HEAD_INIT) -#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, -#endif -#endif /* PY_VERSION_HEX < 0x02060000 */ - -#ifdef __GNUC__ -#define UNUSED __attribute__((__unused__)) -#else -#define UNUSED -#endif - -#define DEFAULT_ENCODING "utf-8" - -#define PyScanner_Check(op) PyObject_TypeCheck(op, &PyScannerType) -#define PyScanner_CheckExact(op) (Py_TYPE(op) == &PyScannerType) -#define PyEncoder_Check(op) PyObject_TypeCheck(op, &PyEncoderType) -#define PyEncoder_CheckExact(op) (Py_TYPE(op) == &PyEncoderType) - -#define JSON_ALLOW_NAN 1 -#define JSON_IGNORE_NAN 2 - -static PyObject *JSON_Infinity = NULL; -static PyObject *JSON_NegInfinity = NULL; -static PyObject *JSON_NaN = NULL; -static PyObject *JSON_EmptyUnicode = NULL; -#if PY_MAJOR_VERSION < 3 -static PyObject *JSON_EmptyStr = NULL; -#endif - -static PyTypeObject PyScannerType; -static PyTypeObject PyEncoderType; - -typedef struct { - PyObject *large_strings; /* A list of previously accumulated large strings */ - PyObject *small_strings; /* Pending small strings */ -} JSON_Accu; - -static int -JSON_Accu_Init(JSON_Accu *acc); -static int -JSON_Accu_Accumulate(JSON_Accu *acc, PyObject *unicode); -static PyObject * -JSON_Accu_FinishAsList(JSON_Accu *acc); -static void -JSON_Accu_Destroy(JSON_Accu *acc); - -#define ERR_EXPECTING_VALUE "Expecting value" -#define ERR_ARRAY_DELIMITER "Expecting ',' delimiter or ']'" -#define ERR_ARRAY_VALUE_FIRST "Expecting value or ']'" -#define ERR_OBJECT_DELIMITER "Expecting ',' delimiter or '}'" -#define ERR_OBJECT_PROPERTY "Expecting property name enclosed in double quotes" -#define ERR_OBJECT_PROPERTY_FIRST "Expecting property name enclosed in double quotes or '}'" -#define ERR_OBJECT_PROPERTY_DELIMITER "Expecting ':' delimiter" -#define ERR_STRING_UNTERMINATED "Unterminated string starting at" -#define ERR_STRING_CONTROL "Invalid control character %r at" -#define ERR_STRING_ESC1 "Invalid \\X escape sequence %r" -#define ERR_STRING_ESC4 "Invalid \\uXXXX escape sequence" - -typedef struct _PyScannerObject { - PyObject_HEAD - PyObject *encoding; - PyObject *strict_bool; - int strict; - PyObject *object_hook; - PyObject *pairs_hook; - PyObject *parse_float; - PyObject *parse_int; - PyObject *parse_constant; - PyObject *memo; -} PyScannerObject; - -static PyMemberDef scanner_members[] = { - {"encoding", T_OBJECT, offsetof(PyScannerObject, encoding), READONLY, "encoding"}, - {"strict", T_OBJECT, offsetof(PyScannerObject, strict_bool), READONLY, "strict"}, - {"object_hook", T_OBJECT, offsetof(PyScannerObject, object_hook), READONLY, "object_hook"}, - {"object_pairs_hook", T_OBJECT, offsetof(PyScannerObject, pairs_hook), READONLY, "object_pairs_hook"}, - {"parse_float", T_OBJECT, offsetof(PyScannerObject, parse_float), READONLY, "parse_float"}, - {"parse_int", T_OBJECT, offsetof(PyScannerObject, parse_int), READONLY, "parse_int"}, - {"parse_constant", T_OBJECT, offsetof(PyScannerObject, parse_constant), READONLY, "parse_constant"}, - {NULL} -}; - -typedef struct _PyEncoderObject { - PyObject_HEAD - PyObject *markers; - PyObject *defaultfn; - PyObject *encoder; - PyObject *indent; - PyObject *key_separator; - PyObject *item_separator; - PyObject *sort_keys; - PyObject *key_memo; - PyObject *encoding; - PyObject *Decimal; - PyObject *skipkeys_bool; - int skipkeys; - int fast_encode; - /* 0, JSON_ALLOW_NAN, JSON_IGNORE_NAN */ - int allow_or_ignore_nan; - int use_decimal; - int namedtuple_as_object; - int tuple_as_array; - int iterable_as_array; - PyObject *max_long_size; - PyObject *min_long_size; - PyObject *item_sort_key; - PyObject *item_sort_kw; - int for_json; -} PyEncoderObject; - -static PyMemberDef encoder_members[] = { - {"markers", T_OBJECT, offsetof(PyEncoderObject, markers), READONLY, "markers"}, - {"default", T_OBJECT, offsetof(PyEncoderObject, defaultfn), READONLY, "default"}, - {"encoder", T_OBJECT, offsetof(PyEncoderObject, encoder), READONLY, "encoder"}, - {"encoding", T_OBJECT, offsetof(PyEncoderObject, encoder), READONLY, "encoding"}, - {"indent", T_OBJECT, offsetof(PyEncoderObject, indent), READONLY, "indent"}, - {"key_separator", T_OBJECT, offsetof(PyEncoderObject, key_separator), READONLY, "key_separator"}, - {"item_separator", T_OBJECT, offsetof(PyEncoderObject, item_separator), READONLY, "item_separator"}, - {"sort_keys", T_OBJECT, offsetof(PyEncoderObject, sort_keys), READONLY, "sort_keys"}, - /* Python 2.5 does not support T_BOOl */ - {"skipkeys", T_OBJECT, offsetof(PyEncoderObject, skipkeys_bool), READONLY, "skipkeys"}, - {"key_memo", T_OBJECT, offsetof(PyEncoderObject, key_memo), READONLY, "key_memo"}, - {"item_sort_key", T_OBJECT, offsetof(PyEncoderObject, item_sort_key), READONLY, "item_sort_key"}, - {"max_long_size", T_OBJECT, offsetof(PyEncoderObject, max_long_size), READONLY, "max_long_size"}, - {"min_long_size", T_OBJECT, offsetof(PyEncoderObject, min_long_size), READONLY, "min_long_size"}, - {NULL} -}; - -static PyObject * -join_list_unicode(PyObject *lst); -static PyObject * -JSON_ParseEncoding(PyObject *encoding); -static PyObject * -maybe_quote_bigint(PyEncoderObject* s, PyObject *encoded, PyObject *obj); -static Py_ssize_t -ascii_char_size(JSON_UNICHR c); -static Py_ssize_t -ascii_escape_char(JSON_UNICHR c, char *output, Py_ssize_t chars); -static PyObject * -ascii_escape_unicode(PyObject *pystr); -static PyObject * -ascii_escape_str(PyObject *pystr); -static PyObject * -py_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr); -#if PY_MAJOR_VERSION < 3 -static PyObject * -join_list_string(PyObject *lst); -static PyObject * -scan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr); -static PyObject * -scanstring_str(PyObject *pystr, Py_ssize_t end, char *encoding, int strict, Py_ssize_t *next_end_ptr); -static PyObject * -_parse_object_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr); -#endif -static PyObject * -scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next_end_ptr); -static PyObject * -scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr); -static PyObject * -_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx); -static PyObject * -scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds); -static void -scanner_dealloc(PyObject *self); -static int -scanner_clear(PyObject *self); -static PyObject * -encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds); -static void -encoder_dealloc(PyObject *self); -static int -encoder_clear(PyObject *self); -static int -is_raw_json(PyObject *obj); -static PyObject * -encoder_stringify_key(PyEncoderObject *s, PyObject *key); -static int -encoder_listencode_list(PyEncoderObject *s, JSON_Accu *rval, PyObject *seq, Py_ssize_t indent_level); -static int -encoder_listencode_obj(PyEncoderObject *s, JSON_Accu *rval, PyObject *obj, Py_ssize_t indent_level); -static int -encoder_listencode_dict(PyEncoderObject *s, JSON_Accu *rval, PyObject *dct, Py_ssize_t indent_level); -static PyObject * -_encoded_const(PyObject *obj); -static void -raise_errmsg(char *msg, PyObject *s, Py_ssize_t end); -static PyObject * -encoder_encode_string(PyEncoderObject *s, PyObject *obj); -static int -_convertPyInt_AsSsize_t(PyObject *o, Py_ssize_t *size_ptr); -static PyObject * -_convertPyInt_FromSsize_t(Py_ssize_t *size_ptr); -static PyObject * -encoder_encode_float(PyEncoderObject *s, PyObject *obj); -static int -_is_namedtuple(PyObject *obj); -static int -_has_for_json_hook(PyObject *obj); -static PyObject * -moduleinit(void); - -#define S_CHAR(c) (c >= ' ' && c <= '~' && c != '\\' && c != '"') -#define IS_WHITESPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r')) - -#define MIN_EXPANSION 6 - -static PyObject* RawJSONType = NULL; -static int -is_raw_json(PyObject *obj) -{ - return PyObject_IsInstance(obj, RawJSONType) ? 1 : 0; -} - -static int -JSON_Accu_Init(JSON_Accu *acc) -{ - /* Lazily allocated */ - acc->large_strings = NULL; - acc->small_strings = PyList_New(0); - if (acc->small_strings == NULL) - return -1; - return 0; -} - -static int -flush_accumulator(JSON_Accu *acc) -{ - Py_ssize_t nsmall = PyList_GET_SIZE(acc->small_strings); - if (nsmall) { - int ret; - PyObject *joined; - if (acc->large_strings == NULL) { - acc->large_strings = PyList_New(0); - if (acc->large_strings == NULL) - return -1; - } -#if PY_MAJOR_VERSION >= 3 - joined = join_list_unicode(acc->small_strings); -#else /* PY_MAJOR_VERSION >= 3 */ - joined = join_list_string(acc->small_strings); -#endif /* PY_MAJOR_VERSION < 3 */ - if (joined == NULL) - return -1; - if (PyList_SetSlice(acc->small_strings, 0, nsmall, NULL)) { - Py_DECREF(joined); - return -1; - } - ret = PyList_Append(acc->large_strings, joined); - Py_DECREF(joined); - return ret; - } - return 0; -} - -static int -JSON_Accu_Accumulate(JSON_Accu *acc, PyObject *unicode) -{ - Py_ssize_t nsmall; -#if PY_MAJOR_VERSION >= 3 - assert(PyUnicode_Check(unicode)); -#else /* PY_MAJOR_VERSION >= 3 */ - assert(PyString_Check(unicode) || PyUnicode_Check(unicode)); -#endif /* PY_MAJOR_VERSION < 3 */ - - if (PyList_Append(acc->small_strings, unicode)) - return -1; - nsmall = PyList_GET_SIZE(acc->small_strings); - /* Each item in a list of unicode objects has an overhead (in 64-bit - * builds) of: - * - 8 bytes for the list slot - * - 56 bytes for the header of the unicode object - * that is, 64 bytes. 100000 such objects waste more than 6MB - * compared to a single concatenated string. - */ - if (nsmall < 100000) - return 0; - return flush_accumulator(acc); -} - -static PyObject * -JSON_Accu_FinishAsList(JSON_Accu *acc) -{ - int ret; - PyObject *res; - - ret = flush_accumulator(acc); - Py_CLEAR(acc->small_strings); - if (ret) { - Py_CLEAR(acc->large_strings); - return NULL; - } - res = acc->large_strings; - acc->large_strings = NULL; - if (res == NULL) - return PyList_New(0); - return res; -} - -static void -JSON_Accu_Destroy(JSON_Accu *acc) -{ - Py_CLEAR(acc->small_strings); - Py_CLEAR(acc->large_strings); -} - -static int -IS_DIGIT(JSON_UNICHR c) -{ - return c >= '0' && c <= '9'; -} - -static PyObject * -maybe_quote_bigint(PyEncoderObject* s, PyObject *encoded, PyObject *obj) -{ - if (s->max_long_size != Py_None && s->min_long_size != Py_None) { - if (PyObject_RichCompareBool(obj, s->max_long_size, Py_GE) || - PyObject_RichCompareBool(obj, s->min_long_size, Py_LE)) { -#if PY_MAJOR_VERSION >= 3 - PyObject* quoted = PyUnicode_FromFormat("\"%U\"", encoded); -#else - PyObject* quoted = PyString_FromFormat("\"%s\"", - PyString_AsString(encoded)); -#endif - Py_DECREF(encoded); - encoded = quoted; - } - } - - return encoded; -} - -static int -_is_namedtuple(PyObject *obj) -{ - int rval = 0; - PyObject *_asdict = PyObject_GetAttrString(obj, "_asdict"); - if (_asdict == NULL) { - PyErr_Clear(); - return 0; - } - rval = PyCallable_Check(_asdict); - Py_DECREF(_asdict); - return rval; -} - -static int -_has_for_json_hook(PyObject *obj) -{ - int rval = 0; - PyObject *for_json = PyObject_GetAttrString(obj, "for_json"); - if (for_json == NULL) { - PyErr_Clear(); - return 0; - } - rval = PyCallable_Check(for_json); - Py_DECREF(for_json); - return rval; -} - -static int -_convertPyInt_AsSsize_t(PyObject *o, Py_ssize_t *size_ptr) -{ - /* PyObject to Py_ssize_t converter */ - *size_ptr = PyInt_AsSsize_t(o); - if (*size_ptr == -1 && PyErr_Occurred()) - return 0; - return 1; -} - -static PyObject * -_convertPyInt_FromSsize_t(Py_ssize_t *size_ptr) -{ - /* Py_ssize_t to PyObject converter */ - return PyInt_FromSsize_t(*size_ptr); -} - -static Py_ssize_t -ascii_escape_char(JSON_UNICHR c, char *output, Py_ssize_t chars) -{ - /* Escape unicode code point c to ASCII escape sequences - in char *output. output must have at least 12 bytes unused to - accommodate an escaped surrogate pair "\uXXXX\uXXXX" */ - if (S_CHAR(c)) { - output[chars++] = (char)c; - } - else { - output[chars++] = '\\'; - switch (c) { - case '\\': output[chars++] = (char)c; break; - case '"': output[chars++] = (char)c; break; - case '\b': output[chars++] = 'b'; break; - case '\f': output[chars++] = 'f'; break; - case '\n': output[chars++] = 'n'; break; - case '\r': output[chars++] = 'r'; break; - case '\t': output[chars++] = 't'; break; - default: -#if PY_MAJOR_VERSION >= 3 || defined(Py_UNICODE_WIDE) - if (c >= 0x10000) { - /* UTF-16 surrogate pair */ - JSON_UNICHR v = c - 0x10000; - c = 0xd800 | ((v >> 10) & 0x3ff); - output[chars++] = 'u'; - output[chars++] = "0123456789abcdef"[(c >> 12) & 0xf]; - output[chars++] = "0123456789abcdef"[(c >> 8) & 0xf]; - output[chars++] = "0123456789abcdef"[(c >> 4) & 0xf]; - output[chars++] = "0123456789abcdef"[(c ) & 0xf]; - c = 0xdc00 | (v & 0x3ff); - output[chars++] = '\\'; - } -#endif - output[chars++] = 'u'; - output[chars++] = "0123456789abcdef"[(c >> 12) & 0xf]; - output[chars++] = "0123456789abcdef"[(c >> 8) & 0xf]; - output[chars++] = "0123456789abcdef"[(c >> 4) & 0xf]; - output[chars++] = "0123456789abcdef"[(c ) & 0xf]; - } - } - return chars; -} - -static Py_ssize_t -ascii_char_size(JSON_UNICHR c) -{ - if (S_CHAR(c)) { - return 1; - } - else if (c == '\\' || - c == '"' || - c == '\b' || - c == '\f' || - c == '\n' || - c == '\r' || - c == '\t') { - return 2; - } -#if PY_MAJOR_VERSION >= 3 || defined(Py_UNICODE_WIDE) - else if (c >= 0x10000U) { - return 2 * MIN_EXPANSION; - } -#endif - else { - return MIN_EXPANSION; - } -} - -static PyObject * -ascii_escape_unicode(PyObject *pystr) -{ - /* Take a PyUnicode pystr and return a new ASCII-only escaped PyString */ - Py_ssize_t i; - Py_ssize_t input_chars = PyUnicode_GET_LENGTH(pystr); - Py_ssize_t output_size = 2; - Py_ssize_t chars; - PY2_UNUSED int kind = PyUnicode_KIND(pystr); - void *data = PyUnicode_DATA(pystr); - PyObject *rval; - char *output; - - output_size = 2; - for (i = 0; i < input_chars; i++) { - output_size += ascii_char_size(PyUnicode_READ(kind, data, i)); - } -#if PY_MAJOR_VERSION >= 3 - rval = PyUnicode_New(output_size, 127); - if (rval == NULL) { - return NULL; - } - assert(PyUnicode_KIND(rval) == PyUnicode_1BYTE_KIND); - output = (char *)PyUnicode_DATA(rval); -#else - rval = PyString_FromStringAndSize(NULL, output_size); - if (rval == NULL) { - return NULL; - } - output = PyString_AS_STRING(rval); -#endif - chars = 0; - output[chars++] = '"'; - for (i = 0; i < input_chars; i++) { - chars = ascii_escape_char(PyUnicode_READ(kind, data, i), output, chars); - } - output[chars++] = '"'; - assert(chars == output_size); - return rval; -} - -#if PY_MAJOR_VERSION >= 3 - -static PyObject * -ascii_escape_str(PyObject *pystr) -{ - PyObject *rval; - PyObject *input = PyUnicode_DecodeUTF8(PyBytes_AS_STRING(pystr), PyBytes_GET_SIZE(pystr), NULL); - if (input == NULL) - return NULL; - rval = ascii_escape_unicode(input); - Py_DECREF(input); - return rval; -} - -#else /* PY_MAJOR_VERSION >= 3 */ - -static PyObject * -ascii_escape_str(PyObject *pystr) -{ - /* Take a PyString pystr and return a new ASCII-only escaped PyString */ - Py_ssize_t i; - Py_ssize_t input_chars; - Py_ssize_t output_size; - Py_ssize_t chars; - PyObject *rval; - char *output; - char *input_str; - - input_chars = PyString_GET_SIZE(pystr); - input_str = PyString_AS_STRING(pystr); - output_size = 2; - - /* Fast path for a string that's already ASCII */ - for (i = 0; i < input_chars; i++) { - JSON_UNICHR c = (JSON_UNICHR)input_str[i]; - if (c > 0x7f) { - /* We hit a non-ASCII character, bail to unicode mode */ - PyObject *uni; - uni = PyUnicode_DecodeUTF8(input_str, input_chars, "strict"); - if (uni == NULL) { - return NULL; - } - rval = ascii_escape_unicode(uni); - Py_DECREF(uni); - return rval; - } - output_size += ascii_char_size(c); - } - - rval = PyString_FromStringAndSize(NULL, output_size); - if (rval == NULL) { - return NULL; - } - chars = 0; - output = PyString_AS_STRING(rval); - output[chars++] = '"'; - for (i = 0; i < input_chars; i++) { - chars = ascii_escape_char((JSON_UNICHR)input_str[i], output, chars); - } - output[chars++] = '"'; - assert(chars == output_size); - return rval; -} -#endif /* PY_MAJOR_VERSION < 3 */ - -static PyObject * -encoder_stringify_key(PyEncoderObject *s, PyObject *key) -{ - if (PyUnicode_Check(key)) { - Py_INCREF(key); - return key; - } -#if PY_MAJOR_VERSION >= 3 - else if (PyBytes_Check(key) && s->encoding != NULL) { - const char *encoding = PyUnicode_AsUTF8(s->encoding); - if (encoding == NULL) - return NULL; - return PyUnicode_Decode( - PyBytes_AS_STRING(key), - PyBytes_GET_SIZE(key), - encoding, - NULL); - } -#else /* PY_MAJOR_VERSION >= 3 */ - else if (PyString_Check(key)) { - Py_INCREF(key); - return key; - } -#endif /* PY_MAJOR_VERSION < 3 */ - else if (PyFloat_Check(key)) { - return encoder_encode_float(s, key); - } - else if (key == Py_True || key == Py_False || key == Py_None) { - /* This must come before the PyInt_Check because - True and False are also 1 and 0.*/ - return _encoded_const(key); - } - else if (PyInt_Check(key) || PyLong_Check(key)) { - if (!(PyInt_CheckExact(key) || PyLong_CheckExact(key))) { - /* See #118, do not trust custom str/repr */ - PyObject *res; - PyObject *tmp = PyObject_CallFunctionObjArgs((PyObject *)&PyLong_Type, key, NULL); - if (tmp == NULL) { - return NULL; - } - res = PyObject_Str(tmp); - Py_DECREF(tmp); - return res; - } - else { - return PyObject_Str(key); - } - } - else if (s->use_decimal && PyObject_TypeCheck(key, (PyTypeObject *)s->Decimal)) { - return PyObject_Str(key); - } - if (s->skipkeys) { - Py_INCREF(Py_None); - return Py_None; - } - PyErr_Format(PyExc_TypeError, - "keys must be str, int, float, bool or None, " - "not %.100s", key->ob_type->tp_name); - return NULL; -} - -static PyObject * -encoder_dict_iteritems(PyEncoderObject *s, PyObject *dct) -{ - PyObject *items; - PyObject *iter = NULL; - PyObject *lst = NULL; - PyObject *item = NULL; - PyObject *kstr = NULL; - PyObject *sortfun = NULL; - PyObject *sortres; - static PyObject *sortargs = NULL; - - if (sortargs == NULL) { - sortargs = PyTuple_New(0); - if (sortargs == NULL) - return NULL; - } - - if (PyDict_CheckExact(dct)) - items = PyDict_Items(dct); - else - items = PyMapping_Items(dct); - if (items == NULL) - return NULL; - iter = PyObject_GetIter(items); - Py_DECREF(items); - if (iter == NULL) - return NULL; - if (s->item_sort_kw == Py_None) - return iter; - lst = PyList_New(0); - if (lst == NULL) - goto bail; - while ((item = PyIter_Next(iter))) { - PyObject *key, *value; - if (!PyTuple_Check(item) || Py_SIZE(item) != 2) { - PyErr_SetString(PyExc_ValueError, "items must return 2-tuples"); - goto bail; - } - key = PyTuple_GET_ITEM(item, 0); - if (key == NULL) - goto bail; -#if PY_MAJOR_VERSION < 3 - else if (PyString_Check(key)) { - /* item can be added as-is */ - } -#endif /* PY_MAJOR_VERSION < 3 */ - else if (PyUnicode_Check(key)) { - /* item can be added as-is */ - } - else { - PyObject *tpl; - kstr = encoder_stringify_key(s, key); - if (kstr == NULL) - goto bail; - else if (kstr == Py_None) { - /* skipkeys */ - Py_DECREF(kstr); - continue; - } - value = PyTuple_GET_ITEM(item, 1); - if (value == NULL) - goto bail; - tpl = PyTuple_Pack(2, kstr, value); - if (tpl == NULL) - goto bail; - Py_CLEAR(kstr); - Py_DECREF(item); - item = tpl; - } - if (PyList_Append(lst, item)) - goto bail; - Py_DECREF(item); - } - Py_CLEAR(iter); - if (PyErr_Occurred()) - goto bail; - sortfun = PyObject_GetAttrString(lst, "sort"); - if (sortfun == NULL) - goto bail; - sortres = PyObject_Call(sortfun, sortargs, s->item_sort_kw); - if (!sortres) - goto bail; - Py_DECREF(sortres); - Py_CLEAR(sortfun); - iter = PyObject_GetIter(lst); - Py_CLEAR(lst); - return iter; -bail: - Py_XDECREF(sortfun); - Py_XDECREF(kstr); - Py_XDECREF(item); - Py_XDECREF(lst); - Py_XDECREF(iter); - return NULL; -} - -/* Use JSONDecodeError exception to raise a nice looking ValueError subclass */ -static PyObject *JSONDecodeError = NULL; -static void -raise_errmsg(char *msg, PyObject *s, Py_ssize_t end) -{ - PyObject *exc = PyObject_CallFunction(JSONDecodeError, "(zOO&)", msg, s, _convertPyInt_FromSsize_t, &end); - if (exc) { - PyErr_SetObject(JSONDecodeError, exc); - Py_DECREF(exc); - } -} - -static PyObject * -join_list_unicode(PyObject *lst) -{ - /* return u''.join(lst) */ - return PyUnicode_Join(JSON_EmptyUnicode, lst); -} - -#if PY_MAJOR_VERSION >= 3 -#define join_list_string join_list_unicode -#else /* PY_MAJOR_VERSION >= 3 */ -static PyObject * -join_list_string(PyObject *lst) -{ - /* return ''.join(lst) */ - static PyObject *joinfn = NULL; - if (joinfn == NULL) { - joinfn = PyObject_GetAttrString(JSON_EmptyStr, "join"); - if (joinfn == NULL) - return NULL; - } - return PyObject_CallFunctionObjArgs(joinfn, lst, NULL); -} -#endif /* PY_MAJOR_VERSION < 3 */ - -static PyObject * -_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx) -{ - /* return (rval, idx) tuple, stealing reference to rval */ - PyObject *tpl; - PyObject *pyidx; - /* - steal a reference to rval, returns (rval, idx) - */ - if (rval == NULL) { - assert(PyErr_Occurred()); - return NULL; - } - pyidx = PyInt_FromSsize_t(idx); - if (pyidx == NULL) { - Py_DECREF(rval); - return NULL; - } - tpl = PyTuple_New(2); - if (tpl == NULL) { - Py_DECREF(pyidx); - Py_DECREF(rval); - return NULL; - } - PyTuple_SET_ITEM(tpl, 0, rval); - PyTuple_SET_ITEM(tpl, 1, pyidx); - return tpl; -} - -#define APPEND_OLD_CHUNK \ - if (chunk != NULL) { \ - if (chunks == NULL) { \ - chunks = PyList_New(0); \ - if (chunks == NULL) { \ - goto bail; \ - } \ - } \ - if (PyList_Append(chunks, chunk)) { \ - goto bail; \ - } \ - Py_CLEAR(chunk); \ - } - -#if PY_MAJOR_VERSION < 3 -static PyObject * -scanstring_str(PyObject *pystr, Py_ssize_t end, char *encoding, int strict, Py_ssize_t *next_end_ptr) -{ - /* Read the JSON string from PyString pystr. - end is the index of the first character after the quote. - encoding is the encoding of pystr (must be an ASCII superset) - if strict is zero then literal control characters are allowed - *next_end_ptr is a return-by-reference index of the character - after the end quote - - Return value is a new PyString (if ASCII-only) or PyUnicode - */ - PyObject *rval; - Py_ssize_t len = PyString_GET_SIZE(pystr); - Py_ssize_t begin = end - 1; - Py_ssize_t next = begin; - int has_unicode = 0; - char *buf = PyString_AS_STRING(pystr); - PyObject *chunks = NULL; - PyObject *chunk = NULL; - PyObject *strchunk = NULL; - - if (len == end) { - raise_errmsg(ERR_STRING_UNTERMINATED, pystr, begin); - goto bail; - } - else if (end < 0 || len < end) { - PyErr_SetString(PyExc_ValueError, "end is out of bounds"); - goto bail; - } - while (1) { - /* Find the end of the string or the next escape */ - Py_UNICODE c = 0; - for (next = end; next < len; next++) { - c = (unsigned char)buf[next]; - if (c == '"' || c == '\\') { - break; - } - else if (strict && c <= 0x1f) { - raise_errmsg(ERR_STRING_CONTROL, pystr, next); - goto bail; - } - else if (c > 0x7f) { - has_unicode = 1; - } - } - if (!(c == '"' || c == '\\')) { - raise_errmsg(ERR_STRING_UNTERMINATED, pystr, begin); - goto bail; - } - /* Pick up this chunk if it's not zero length */ - if (next != end) { - APPEND_OLD_CHUNK - strchunk = PyString_FromStringAndSize(&buf[end], next - end); - if (strchunk == NULL) { - goto bail; - } - if (has_unicode) { - chunk = PyUnicode_FromEncodedObject(strchunk, encoding, NULL); - Py_DECREF(strchunk); - if (chunk == NULL) { - goto bail; - } - } - else { - chunk = strchunk; - } - } - next++; - if (c == '"') { - end = next; - break; - } - if (next == len) { - raise_errmsg(ERR_STRING_UNTERMINATED, pystr, begin); - goto bail; - } - c = buf[next]; - if (c != 'u') { - /* Non-unicode backslash escapes */ - end = next + 1; - switch (c) { - case '"': break; - case '\\': break; - case '/': break; - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - default: c = 0; - } - if (c == 0) { - raise_errmsg(ERR_STRING_ESC1, pystr, end - 2); - goto bail; - } - } - else { - c = 0; - next++; - end = next + 4; - if (end >= len) { - raise_errmsg(ERR_STRING_ESC4, pystr, next - 1); - goto bail; - } - /* Decode 4 hex digits */ - for (; next < end; next++) { - JSON_UNICHR digit = (JSON_UNICHR)buf[next]; - c <<= 4; - switch (digit) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - c |= (digit - '0'); break; - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': - c |= (digit - 'a' + 10); break; - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': - c |= (digit - 'A' + 10); break; - default: - raise_errmsg(ERR_STRING_ESC4, pystr, end - 5); - goto bail; - } - } -#if defined(Py_UNICODE_WIDE) - /* Surrogate pair */ - if ((c & 0xfc00) == 0xd800) { - if (end + 6 < len && buf[next] == '\\' && buf[next+1] == 'u') { - JSON_UNICHR c2 = 0; - end += 6; - /* Decode 4 hex digits */ - for (next += 2; next < end; next++) { - c2 <<= 4; - JSON_UNICHR digit = buf[next]; - switch (digit) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - c2 |= (digit - '0'); break; - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': - c2 |= (digit - 'a' + 10); break; - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': - c2 |= (digit - 'A' + 10); break; - default: - raise_errmsg(ERR_STRING_ESC4, pystr, end - 5); - goto bail; - } - } - if ((c2 & 0xfc00) != 0xdc00) { - /* not a low surrogate, rewind */ - end -= 6; - next = end; - } - else { - c = 0x10000 + (((c - 0xd800) << 10) | (c2 - 0xdc00)); - } - } - } -#endif /* Py_UNICODE_WIDE */ - } - if (c > 0x7f) { - has_unicode = 1; - } - APPEND_OLD_CHUNK - if (has_unicode) { - chunk = PyUnicode_FromOrdinal(c); - if (chunk == NULL) { - goto bail; - } - } - else { - char c_char = Py_CHARMASK(c); - chunk = PyString_FromStringAndSize(&c_char, 1); - if (chunk == NULL) { - goto bail; - } - } - } - - if (chunks == NULL) { - if (chunk != NULL) - rval = chunk; - else { - rval = JSON_EmptyStr; - Py_INCREF(rval); - } - } - else { - APPEND_OLD_CHUNK - rval = join_list_string(chunks); - if (rval == NULL) { - goto bail; - } - Py_CLEAR(chunks); - } - - *next_end_ptr = end; - return rval; -bail: - *next_end_ptr = -1; - Py_XDECREF(chunk); - Py_XDECREF(chunks); - return NULL; -} -#endif /* PY_MAJOR_VERSION < 3 */ - -static PyObject * -scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next_end_ptr) -{ - /* Read the JSON string from PyUnicode pystr. - end is the index of the first character after the quote. - if strict is zero then literal control characters are allowed - *next_end_ptr is a return-by-reference index of the character - after the end quote - - Return value is a new PyUnicode - */ - PyObject *rval; - Py_ssize_t begin = end - 1; - Py_ssize_t next = begin; - PY2_UNUSED int kind = PyUnicode_KIND(pystr); - Py_ssize_t len = PyUnicode_GET_LENGTH(pystr); - void *buf = PyUnicode_DATA(pystr); - PyObject *chunks = NULL; - PyObject *chunk = NULL; - - if (len == end) { - raise_errmsg(ERR_STRING_UNTERMINATED, pystr, begin); - goto bail; - } - else if (end < 0 || len < end) { - PyErr_SetString(PyExc_ValueError, "end is out of bounds"); - goto bail; - } - while (1) { - /* Find the end of the string or the next escape */ - JSON_UNICHR c = 0; - for (next = end; next < len; next++) { - c = PyUnicode_READ(kind, buf, next); - if (c == '"' || c == '\\') { - break; - } - else if (strict && c <= 0x1f) { - raise_errmsg(ERR_STRING_CONTROL, pystr, next); - goto bail; - } - } - if (!(c == '"' || c == '\\')) { - raise_errmsg(ERR_STRING_UNTERMINATED, pystr, begin); - goto bail; - } - /* Pick up this chunk if it's not zero length */ - if (next != end) { - APPEND_OLD_CHUNK -#if PY_MAJOR_VERSION < 3 - chunk = PyUnicode_FromUnicode(&((const Py_UNICODE *)buf)[end], next - end); -#else - chunk = PyUnicode_Substring(pystr, end, next); -#endif - if (chunk == NULL) { - goto bail; - } - } - next++; - if (c == '"') { - end = next; - break; - } - if (next == len) { - raise_errmsg(ERR_STRING_UNTERMINATED, pystr, begin); - goto bail; - } - c = PyUnicode_READ(kind, buf, next); - if (c != 'u') { - /* Non-unicode backslash escapes */ - end = next + 1; - switch (c) { - case '"': break; - case '\\': break; - case '/': break; - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - default: c = 0; - } - if (c == 0) { - raise_errmsg(ERR_STRING_ESC1, pystr, end - 2); - goto bail; - } - } - else { - c = 0; - next++; - end = next + 4; - if (end >= len) { - raise_errmsg(ERR_STRING_ESC4, pystr, next - 1); - goto bail; - } - /* Decode 4 hex digits */ - for (; next < end; next++) { - JSON_UNICHR digit = PyUnicode_READ(kind, buf, next); - c <<= 4; - switch (digit) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - c |= (digit - '0'); break; - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': - c |= (digit - 'a' + 10); break; - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': - c |= (digit - 'A' + 10); break; - default: - raise_errmsg(ERR_STRING_ESC4, pystr, end - 5); - goto bail; - } - } -#if PY_MAJOR_VERSION >= 3 || defined(Py_UNICODE_WIDE) - /* Surrogate pair */ - if ((c & 0xfc00) == 0xd800) { - JSON_UNICHR c2 = 0; - if (end + 6 < len && - PyUnicode_READ(kind, buf, next) == '\\' && - PyUnicode_READ(kind, buf, next + 1) == 'u') { - end += 6; - /* Decode 4 hex digits */ - for (next += 2; next < end; next++) { - JSON_UNICHR digit = PyUnicode_READ(kind, buf, next); - c2 <<= 4; - switch (digit) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - c2 |= (digit - '0'); break; - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': - c2 |= (digit - 'a' + 10); break; - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': - c2 |= (digit - 'A' + 10); break; - default: - raise_errmsg(ERR_STRING_ESC4, pystr, end - 5); - goto bail; - } - } - if ((c2 & 0xfc00) != 0xdc00) { - /* not a low surrogate, rewind */ - end -= 6; - next = end; - } - else { - c = 0x10000 + (((c - 0xd800) << 10) | (c2 - 0xdc00)); - } - } - } -#endif - } - APPEND_OLD_CHUNK - chunk = PyUnicode_FromOrdinal(c); - if (chunk == NULL) { - goto bail; - } - } - - if (chunks == NULL) { - if (chunk != NULL) - rval = chunk; - else { - rval = JSON_EmptyUnicode; - Py_INCREF(rval); - } - } - else { - APPEND_OLD_CHUNK - rval = join_list_unicode(chunks); - if (rval == NULL) { - goto bail; - } - Py_CLEAR(chunks); - } - *next_end_ptr = end; - return rval; -bail: - *next_end_ptr = -1; - Py_XDECREF(chunk); - Py_XDECREF(chunks); - return NULL; -} - -PyDoc_STRVAR(pydoc_scanstring, - "scanstring(basestring, end, encoding, strict=True) -> (str, end)\n" - "\n" - "Scan the string s for a JSON string. End is the index of the\n" - "character in s after the quote that started the JSON string.\n" - "Unescapes all valid JSON string escape sequences and raises ValueError\n" - "on attempt to decode an invalid string. If strict is False then literal\n" - "control characters are allowed in the string.\n" - "\n" - "Returns a tuple of the decoded string and the index of the character in s\n" - "after the end quote." -); - -static PyObject * -py_scanstring(PyObject* self UNUSED, PyObject *args) -{ - PyObject *pystr; - PyObject *rval; - Py_ssize_t end; - Py_ssize_t next_end = -1; - char *encoding = NULL; - int strict = 1; - if (!PyArg_ParseTuple(args, "OO&|zi:scanstring", &pystr, _convertPyInt_AsSsize_t, &end, &encoding, &strict)) { - return NULL; - } - if (encoding == NULL) { - encoding = DEFAULT_ENCODING; - } - if (PyUnicode_Check(pystr)) { - if (PyUnicode_READY(pystr)) - return NULL; - rval = scanstring_unicode(pystr, end, strict, &next_end); - } -#if PY_MAJOR_VERSION < 3 - /* Using a bytes input is unsupported for scanning in Python 3. - It is coerced to str in the decoder before it gets here. */ - else if (PyString_Check(pystr)) { - rval = scanstring_str(pystr, end, encoding, strict, &next_end); - } -#endif - else { - PyErr_Format(PyExc_TypeError, - "first argument must be a string, not %.80s", - Py_TYPE(pystr)->tp_name); - return NULL; - } - return _build_rval_index_tuple(rval, next_end); -} - -PyDoc_STRVAR(pydoc_encode_basestring_ascii, - "encode_basestring_ascii(basestring) -> str\n" - "\n" - "Return an ASCII-only JSON representation of a Python string" -); - -static PyObject * -py_encode_basestring_ascii(PyObject* self UNUSED, PyObject *pystr) -{ - /* Return an ASCII-only JSON representation of a Python string */ - /* METH_O */ - if (PyBytes_Check(pystr)) { - return ascii_escape_str(pystr); - } - else if (PyUnicode_Check(pystr)) { - if (PyUnicode_READY(pystr)) - return NULL; - return ascii_escape_unicode(pystr); - } - else { - PyErr_Format(PyExc_TypeError, - "first argument must be a string, not %.80s", - Py_TYPE(pystr)->tp_name); - return NULL; - } -} - -static void -scanner_dealloc(PyObject *self) -{ - /* bpo-31095: UnTrack is needed before calling any callbacks */ - PyObject_GC_UnTrack(self); - scanner_clear(self); - Py_TYPE(self)->tp_free(self); -} - -static int -scanner_traverse(PyObject *self, visitproc visit, void *arg) -{ - PyScannerObject *s; - assert(PyScanner_Check(self)); - s = (PyScannerObject *)self; - Py_VISIT(s->encoding); - Py_VISIT(s->strict_bool); - Py_VISIT(s->object_hook); - Py_VISIT(s->pairs_hook); - Py_VISIT(s->parse_float); - Py_VISIT(s->parse_int); - Py_VISIT(s->parse_constant); - Py_VISIT(s->memo); - return 0; -} - -static int -scanner_clear(PyObject *self) -{ - PyScannerObject *s; - assert(PyScanner_Check(self)); - s = (PyScannerObject *)self; - Py_CLEAR(s->encoding); - Py_CLEAR(s->strict_bool); - Py_CLEAR(s->object_hook); - Py_CLEAR(s->pairs_hook); - Py_CLEAR(s->parse_float); - Py_CLEAR(s->parse_int); - Py_CLEAR(s->parse_constant); - Py_CLEAR(s->memo); - return 0; -} - -#if PY_MAJOR_VERSION < 3 -static PyObject * -_parse_object_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) -{ - /* Read a JSON object from PyString pystr. - idx is the index of the first character after the opening curly brace. - *next_idx_ptr is a return-by-reference index to the first character after - the closing curly brace. - - Returns a new PyObject (usually a dict, but object_hook or - object_pairs_hook can change that) - */ - char *str = PyString_AS_STRING(pystr); - Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1; - PyObject *rval = NULL; - PyObject *pairs = NULL; - PyObject *item; - PyObject *key = NULL; - PyObject *val = NULL; - char *encoding = PyString_AS_STRING(s->encoding); - int has_pairs_hook = (s->pairs_hook != Py_None); - int did_parse = 0; - Py_ssize_t next_idx; - if (has_pairs_hook) { - pairs = PyList_New(0); - if (pairs == NULL) - return NULL; - } - else { - rval = PyDict_New(); - if (rval == NULL) - return NULL; - } - - /* skip whitespace after { */ - while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; - - /* only loop if the object is non-empty */ - if (idx <= end_idx && str[idx] != '}') { - int trailing_delimiter = 0; - while (idx <= end_idx) { - PyObject *memokey; - trailing_delimiter = 0; - - /* read key */ - if (str[idx] != '"') { - raise_errmsg(ERR_OBJECT_PROPERTY, pystr, idx); - goto bail; - } - key = scanstring_str(pystr, idx + 1, encoding, s->strict, &next_idx); - if (key == NULL) - goto bail; - memokey = PyDict_GetItem(s->memo, key); - if (memokey != NULL) { - Py_INCREF(memokey); - Py_DECREF(key); - key = memokey; - } - else { - if (PyDict_SetItem(s->memo, key, key) < 0) - goto bail; - } - idx = next_idx; - - /* skip whitespace between key and : delimiter, read :, skip whitespace */ - while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; - if (idx > end_idx || str[idx] != ':') { - raise_errmsg(ERR_OBJECT_PROPERTY_DELIMITER, pystr, idx); - goto bail; - } - idx++; - while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; - - /* read any JSON data type */ - val = scan_once_str(s, pystr, idx, &next_idx); - if (val == NULL) - goto bail; - - if (has_pairs_hook) { - item = PyTuple_Pack(2, key, val); - if (item == NULL) - goto bail; - Py_CLEAR(key); - Py_CLEAR(val); - if (PyList_Append(pairs, item) == -1) { - Py_DECREF(item); - goto bail; - } - Py_DECREF(item); - } - else { - if (PyDict_SetItem(rval, key, val) < 0) - goto bail; - Py_CLEAR(key); - Py_CLEAR(val); - } - idx = next_idx; - - /* skip whitespace before } or , */ - while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; - - /* bail if the object is closed or we didn't get the , delimiter */ - did_parse = 1; - if (idx > end_idx) break; - if (str[idx] == '}') { - break; - } - else if (str[idx] != ',') { - raise_errmsg(ERR_OBJECT_DELIMITER, pystr, idx); - goto bail; - } - idx++; - - /* skip whitespace after , delimiter */ - while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; - trailing_delimiter = 1; - } - if (trailing_delimiter) { - raise_errmsg(ERR_OBJECT_PROPERTY, pystr, idx); - goto bail; - } - } - /* verify that idx < end_idx, str[idx] should be '}' */ - if (idx > end_idx || str[idx] != '}') { - if (did_parse) { - raise_errmsg(ERR_OBJECT_DELIMITER, pystr, idx); - } else { - raise_errmsg(ERR_OBJECT_PROPERTY_FIRST, pystr, idx); - } - goto bail; - } - - /* if pairs_hook is not None: rval = object_pairs_hook(pairs) */ - if (s->pairs_hook != Py_None) { - val = PyObject_CallFunctionObjArgs(s->pairs_hook, pairs, NULL); - if (val == NULL) - goto bail; - Py_DECREF(pairs); - *next_idx_ptr = idx + 1; - return val; - } - - /* if object_hook is not None: rval = object_hook(rval) */ - if (s->object_hook != Py_None) { - val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL); - if (val == NULL) - goto bail; - Py_DECREF(rval); - rval = val; - val = NULL; - } - *next_idx_ptr = idx + 1; - return rval; -bail: - Py_XDECREF(rval); - Py_XDECREF(key); - Py_XDECREF(val); - Py_XDECREF(pairs); - return NULL; -} -#endif /* PY_MAJOR_VERSION < 3 */ - -static PyObject * -_parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) -{ - /* Read a JSON object from PyUnicode pystr. - idx is the index of the first character after the opening curly brace. - *next_idx_ptr is a return-by-reference index to the first character after - the closing curly brace. - - Returns a new PyObject (usually a dict, but object_hook can change that) - */ - void *str = PyUnicode_DATA(pystr); - Py_ssize_t end_idx = PyUnicode_GET_LENGTH(pystr) - 1; - PY2_UNUSED int kind = PyUnicode_KIND(pystr); - PyObject *rval = NULL; - PyObject *pairs = NULL; - PyObject *item; - PyObject *key = NULL; - PyObject *val = NULL; - int has_pairs_hook = (s->pairs_hook != Py_None); - int did_parse = 0; - Py_ssize_t next_idx; - - if (has_pairs_hook) { - pairs = PyList_New(0); - if (pairs == NULL) - return NULL; - } - else { - rval = PyDict_New(); - if (rval == NULL) - return NULL; - } - - /* skip whitespace after { */ - while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; - - /* only loop if the object is non-empty */ - if (idx <= end_idx && PyUnicode_READ(kind, str, idx) != '}') { - int trailing_delimiter = 0; - while (idx <= end_idx) { - PyObject *memokey; - trailing_delimiter = 0; - - /* read key */ - if (PyUnicode_READ(kind, str, idx) != '"') { - raise_errmsg(ERR_OBJECT_PROPERTY, pystr, idx); - goto bail; - } - key = scanstring_unicode(pystr, idx + 1, s->strict, &next_idx); - if (key == NULL) - goto bail; - memokey = PyDict_GetItem(s->memo, key); - if (memokey != NULL) { - Py_INCREF(memokey); - Py_DECREF(key); - key = memokey; - } - else { - if (PyDict_SetItem(s->memo, key, key) < 0) - goto bail; - } - idx = next_idx; - - /* skip whitespace between key and : delimiter, read :, skip - whitespace */ - while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; - if (idx > end_idx || PyUnicode_READ(kind, str, idx) != ':') { - raise_errmsg(ERR_OBJECT_PROPERTY_DELIMITER, pystr, idx); - goto bail; - } - idx++; - while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; - - /* read any JSON term */ - val = scan_once_unicode(s, pystr, idx, &next_idx); - if (val == NULL) - goto bail; - - if (has_pairs_hook) { - item = PyTuple_Pack(2, key, val); - if (item == NULL) - goto bail; - Py_CLEAR(key); - Py_CLEAR(val); - if (PyList_Append(pairs, item) == -1) { - Py_DECREF(item); - goto bail; - } - Py_DECREF(item); - } - else { - if (PyDict_SetItem(rval, key, val) < 0) - goto bail; - Py_CLEAR(key); - Py_CLEAR(val); - } - idx = next_idx; - - /* skip whitespace before } or , */ - while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; - - /* bail if the object is closed or we didn't get the , - delimiter */ - did_parse = 1; - if (idx > end_idx) break; - if (PyUnicode_READ(kind, str, idx) == '}') { - break; - } - else if (PyUnicode_READ(kind, str, idx) != ',') { - raise_errmsg(ERR_OBJECT_DELIMITER, pystr, idx); - goto bail; - } - idx++; - - /* skip whitespace after , delimiter */ - while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; - trailing_delimiter = 1; - } - if (trailing_delimiter) { - raise_errmsg(ERR_OBJECT_PROPERTY, pystr, idx); - goto bail; - } - } - - /* verify that idx < end_idx, str[idx] should be '}' */ - if (idx > end_idx || PyUnicode_READ(kind, str, idx) != '}') { - if (did_parse) { - raise_errmsg(ERR_OBJECT_DELIMITER, pystr, idx); - } else { - raise_errmsg(ERR_OBJECT_PROPERTY_FIRST, pystr, idx); - } - goto bail; - } - - /* if pairs_hook is not None: rval = object_pairs_hook(pairs) */ - if (s->pairs_hook != Py_None) { - val = PyObject_CallFunctionObjArgs(s->pairs_hook, pairs, NULL); - if (val == NULL) - goto bail; - Py_DECREF(pairs); - *next_idx_ptr = idx + 1; - return val; - } - - /* if object_hook is not None: rval = object_hook(rval) */ - if (s->object_hook != Py_None) { - val = PyObject_CallFunctionObjArgs(s->object_hook, rval, NULL); - if (val == NULL) - goto bail; - Py_DECREF(rval); - rval = val; - val = NULL; - } - *next_idx_ptr = idx + 1; - return rval; -bail: - Py_XDECREF(rval); - Py_XDECREF(key); - Py_XDECREF(val); - Py_XDECREF(pairs); - return NULL; -} - -#if PY_MAJOR_VERSION < 3 -static PyObject * -_parse_array_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) -{ - /* Read a JSON array from PyString pystr. - idx is the index of the first character after the opening brace. - *next_idx_ptr is a return-by-reference index to the first character after - the closing brace. - - Returns a new PyList - */ - char *str = PyString_AS_STRING(pystr); - Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1; - PyObject *val = NULL; - PyObject *rval = PyList_New(0); - Py_ssize_t next_idx; - if (rval == NULL) - return NULL; - - /* skip whitespace after [ */ - while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; - - /* only loop if the array is non-empty */ - if (idx <= end_idx && str[idx] != ']') { - int trailing_delimiter = 0; - while (idx <= end_idx) { - trailing_delimiter = 0; - /* read any JSON term and de-tuplefy the (rval, idx) */ - val = scan_once_str(s, pystr, idx, &next_idx); - if (val == NULL) { - goto bail; - } - - if (PyList_Append(rval, val) == -1) - goto bail; - - Py_CLEAR(val); - idx = next_idx; - - /* skip whitespace between term and , */ - while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; - - /* bail if the array is closed or we didn't get the , delimiter */ - if (idx > end_idx) break; - if (str[idx] == ']') { - break; - } - else if (str[idx] != ',') { - raise_errmsg(ERR_ARRAY_DELIMITER, pystr, idx); - goto bail; - } - idx++; - - /* skip whitespace after , */ - while (idx <= end_idx && IS_WHITESPACE(str[idx])) idx++; - trailing_delimiter = 1; - } - if (trailing_delimiter) { - raise_errmsg(ERR_EXPECTING_VALUE, pystr, idx); - goto bail; - } - } - - /* verify that idx < end_idx, str[idx] should be ']' */ - if (idx > end_idx || str[idx] != ']') { - if (PyList_GET_SIZE(rval)) { - raise_errmsg(ERR_ARRAY_DELIMITER, pystr, idx); - } else { - raise_errmsg(ERR_ARRAY_VALUE_FIRST, pystr, idx); - } - goto bail; - } - *next_idx_ptr = idx + 1; - return rval; -bail: - Py_XDECREF(val); - Py_DECREF(rval); - return NULL; -} -#endif /* PY_MAJOR_VERSION < 3 */ - -static PyObject * -_parse_array_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) -{ - /* Read a JSON array from PyString pystr. - idx is the index of the first character after the opening brace. - *next_idx_ptr is a return-by-reference index to the first character after - the closing brace. - - Returns a new PyList - */ - PY2_UNUSED int kind = PyUnicode_KIND(pystr); - void *str = PyUnicode_DATA(pystr); - Py_ssize_t end_idx = PyUnicode_GET_LENGTH(pystr) - 1; - PyObject *val = NULL; - PyObject *rval = PyList_New(0); - Py_ssize_t next_idx; - if (rval == NULL) - return NULL; - - /* skip whitespace after [ */ - while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; - - /* only loop if the array is non-empty */ - if (idx <= end_idx && PyUnicode_READ(kind, str, idx) != ']') { - int trailing_delimiter = 0; - while (idx <= end_idx) { - trailing_delimiter = 0; - /* read any JSON term */ - val = scan_once_unicode(s, pystr, idx, &next_idx); - if (val == NULL) { - goto bail; - } - - if (PyList_Append(rval, val) == -1) - goto bail; - - Py_CLEAR(val); - idx = next_idx; - - /* skip whitespace between term and , */ - while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; - - /* bail if the array is closed or we didn't get the , delimiter */ - if (idx > end_idx) break; - if (PyUnicode_READ(kind, str, idx) == ']') { - break; - } - else if (PyUnicode_READ(kind, str, idx) != ',') { - raise_errmsg(ERR_ARRAY_DELIMITER, pystr, idx); - goto bail; - } - idx++; - - /* skip whitespace after , */ - while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; - trailing_delimiter = 1; - } - if (trailing_delimiter) { - raise_errmsg(ERR_EXPECTING_VALUE, pystr, idx); - goto bail; - } - } - - /* verify that idx < end_idx, str[idx] should be ']' */ - if (idx > end_idx || PyUnicode_READ(kind, str, idx) != ']') { - if (PyList_GET_SIZE(rval)) { - raise_errmsg(ERR_ARRAY_DELIMITER, pystr, idx); - } else { - raise_errmsg(ERR_ARRAY_VALUE_FIRST, pystr, idx); - } - goto bail; - } - *next_idx_ptr = idx + 1; - return rval; -bail: - Py_XDECREF(val); - Py_DECREF(rval); - return NULL; -} - -static PyObject * -_parse_constant(PyScannerObject *s, PyObject *constant, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) -{ - /* Read a JSON constant from PyString pystr. - constant is the Python string that was found - ("NaN", "Infinity", "-Infinity"). - idx is the index of the first character of the constant - *next_idx_ptr is a return-by-reference index to the first character after - the constant. - - Returns the result of parse_constant - */ - PyObject *rval; - - /* rval = parse_constant(constant) */ - rval = PyObject_CallFunctionObjArgs(s->parse_constant, constant, NULL); - idx += PyString_GET_SIZE(constant); - *next_idx_ptr = idx; - return rval; -} - -#if PY_MAJOR_VERSION < 3 -static PyObject * -_match_number_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ssize_t *next_idx_ptr) -{ - /* Read a JSON number from PyString pystr. - idx is the index of the first character of the number - *next_idx_ptr is a return-by-reference index to the first character after - the number. - - Returns a new PyObject representation of that number: - PyInt, PyLong, or PyFloat. - May return other types if parse_int or parse_float are set - */ - char *str = PyString_AS_STRING(pystr); - Py_ssize_t end_idx = PyString_GET_SIZE(pystr) - 1; - Py_ssize_t idx = start; - int is_float = 0; - PyObject *rval; - PyObject *numstr; - - /* read a sign if it's there, make sure it's not the end of the string */ - if (str[idx] == '-') { - if (idx >= end_idx) { - raise_errmsg(ERR_EXPECTING_VALUE, pystr, idx); - return NULL; - } - idx++; - } - - /* read as many integer digits as we find as long as it doesn't start with 0 */ - if (str[idx] >= '1' && str[idx] <= '9') { - idx++; - while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++; - } - /* if it starts with 0 we only expect one integer digit */ - else if (str[idx] == '0') { - idx++; - } - /* no integer digits, error */ - else { - raise_errmsg(ERR_EXPECTING_VALUE, pystr, idx); - return NULL; - } - - /* if the next char is '.' followed by a digit then read all float digits */ - if (idx < end_idx && str[idx] == '.' && str[idx + 1] >= '0' && str[idx + 1] <= '9') { - is_float = 1; - idx += 2; - while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++; - } - - /* if the next char is 'e' or 'E' then maybe read the exponent (or backtrack) */ - if (idx < end_idx && (str[idx] == 'e' || str[idx] == 'E')) { - - /* save the index of the 'e' or 'E' just in case we need to backtrack */ - Py_ssize_t e_start = idx; - idx++; - - /* read an exponent sign if present */ - if (idx < end_idx && (str[idx] == '-' || str[idx] == '+')) idx++; - - /* read all digits */ - while (idx <= end_idx && str[idx] >= '0' && str[idx] <= '9') idx++; - - /* if we got a digit, then parse as float. if not, backtrack */ - if (str[idx - 1] >= '0' && str[idx - 1] <= '9') { - is_float = 1; - } - else { - idx = e_start; - } - } - - /* copy the section we determined to be a number */ - numstr = PyString_FromStringAndSize(&str[start], idx - start); - if (numstr == NULL) - return NULL; - if (is_float) { - /* parse as a float using a fast path if available, otherwise call user defined method */ - if (s->parse_float != (PyObject *)&PyFloat_Type) { - rval = PyObject_CallFunctionObjArgs(s->parse_float, numstr, NULL); - } - else { - /* rval = PyFloat_FromDouble(PyOS_ascii_atof(PyString_AS_STRING(numstr))); */ - double d = PyOS_string_to_double(PyString_AS_STRING(numstr), - NULL, NULL); - if (d == -1.0 && PyErr_Occurred()) - return NULL; - rval = PyFloat_FromDouble(d); - } - } - else { - /* parse as an int using a fast path if available, otherwise call user defined method */ - if (s->parse_int != (PyObject *)&PyInt_Type) { - rval = PyObject_CallFunctionObjArgs(s->parse_int, numstr, NULL); - } - else { - rval = PyInt_FromString(PyString_AS_STRING(numstr), NULL, 10); - } - } - Py_DECREF(numstr); - *next_idx_ptr = idx; - return rval; -} -#endif /* PY_MAJOR_VERSION < 3 */ - -static PyObject * -_match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_ssize_t *next_idx_ptr) -{ - /* Read a JSON number from PyUnicode pystr. - idx is the index of the first character of the number - *next_idx_ptr is a return-by-reference index to the first character after - the number. - - Returns a new PyObject representation of that number: - PyInt, PyLong, or PyFloat. - May return other types if parse_int or parse_float are set - */ - PY2_UNUSED int kind = PyUnicode_KIND(pystr); - void *str = PyUnicode_DATA(pystr); - Py_ssize_t end_idx = PyUnicode_GET_LENGTH(pystr) - 1; - Py_ssize_t idx = start; - int is_float = 0; - JSON_UNICHR c; - PyObject *rval; - PyObject *numstr; - - /* read a sign if it's there, make sure it's not the end of the string */ - if (PyUnicode_READ(kind, str, idx) == '-') { - if (idx >= end_idx) { - raise_errmsg(ERR_EXPECTING_VALUE, pystr, idx); - return NULL; - } - idx++; - } - - /* read as many integer digits as we find as long as it doesn't start with 0 */ - c = PyUnicode_READ(kind, str, idx); - if (c == '0') { - /* if it starts with 0 we only expect one integer digit */ - idx++; - } - else if (IS_DIGIT(c)) { - idx++; - while (idx <= end_idx && IS_DIGIT(PyUnicode_READ(kind, str, idx))) { - idx++; - } - } - else { - /* no integer digits, error */ - raise_errmsg(ERR_EXPECTING_VALUE, pystr, idx); - return NULL; - } - - /* if the next char is '.' followed by a digit then read all float digits */ - if (idx < end_idx && - PyUnicode_READ(kind, str, idx) == '.' && - IS_DIGIT(PyUnicode_READ(kind, str, idx + 1))) { - is_float = 1; - idx += 2; - while (idx <= end_idx && IS_DIGIT(PyUnicode_READ(kind, str, idx))) idx++; - } - - /* if the next char is 'e' or 'E' then maybe read the exponent (or backtrack) */ - if (idx < end_idx && - (PyUnicode_READ(kind, str, idx) == 'e' || - PyUnicode_READ(kind, str, idx) == 'E')) { - Py_ssize_t e_start = idx; - idx++; - - /* read an exponent sign if present */ - if (idx < end_idx && - (PyUnicode_READ(kind, str, idx) == '-' || - PyUnicode_READ(kind, str, idx) == '+')) idx++; - - /* read all digits */ - while (idx <= end_idx && IS_DIGIT(PyUnicode_READ(kind, str, idx))) idx++; - - /* if we got a digit, then parse as float. if not, backtrack */ - if (IS_DIGIT(PyUnicode_READ(kind, str, idx - 1))) { - is_float = 1; - } - else { - idx = e_start; - } - } - - /* copy the section we determined to be a number */ -#if PY_MAJOR_VERSION >= 3 - numstr = PyUnicode_Substring(pystr, start, idx); -#else - numstr = PyUnicode_FromUnicode(&((Py_UNICODE *)str)[start], idx - start); -#endif - if (numstr == NULL) - return NULL; - if (is_float) { - /* parse as a float using a fast path if available, otherwise call user defined method */ - if (s->parse_float != (PyObject *)&PyFloat_Type) { - rval = PyObject_CallFunctionObjArgs(s->parse_float, numstr, NULL); - } - else { -#if PY_MAJOR_VERSION >= 3 - rval = PyFloat_FromString(numstr); -#else - rval = PyFloat_FromString(numstr, NULL); -#endif - } - } - else { - /* no fast path for unicode -> int, just call */ - rval = PyObject_CallFunctionObjArgs(s->parse_int, numstr, NULL); - } - Py_DECREF(numstr); - *next_idx_ptr = idx; - return rval; -} - -#if PY_MAJOR_VERSION < 3 -static PyObject * -scan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) -{ - /* Read one JSON term (of any kind) from PyString pystr. - idx is the index of the first character of the term - *next_idx_ptr is a return-by-reference index to the first character after - the number. - - Returns a new PyObject representation of the term. - */ - char *str = PyString_AS_STRING(pystr); - Py_ssize_t length = PyString_GET_SIZE(pystr); - PyObject *rval = NULL; - int fallthrough = 0; - if (idx < 0 || idx >= length) { - raise_errmsg(ERR_EXPECTING_VALUE, pystr, idx); - return NULL; - } - switch (str[idx]) { - case '"': - /* string */ - rval = scanstring_str(pystr, idx + 1, - PyString_AS_STRING(s->encoding), - s->strict, - next_idx_ptr); - break; - case '{': - /* object */ - if (Py_EnterRecursiveCall(" while decoding a JSON object " - "from a string")) - return NULL; - rval = _parse_object_str(s, pystr, idx + 1, next_idx_ptr); - Py_LeaveRecursiveCall(); - break; - case '[': - /* array */ - if (Py_EnterRecursiveCall(" while decoding a JSON array " - "from a string")) - return NULL; - rval = _parse_array_str(s, pystr, idx + 1, next_idx_ptr); - Py_LeaveRecursiveCall(); - break; - case 'n': - /* null */ - if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') { - Py_INCREF(Py_None); - *next_idx_ptr = idx + 4; - rval = Py_None; - } - else - fallthrough = 1; - break; - case 't': - /* true */ - if ((idx + 3 < length) && str[idx + 1] == 'r' && str[idx + 2] == 'u' && str[idx + 3] == 'e') { - Py_INCREF(Py_True); - *next_idx_ptr = idx + 4; - rval = Py_True; - } - else - fallthrough = 1; - break; - case 'f': - /* false */ - if ((idx + 4 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'l' && str[idx + 3] == 's' && str[idx + 4] == 'e') { - Py_INCREF(Py_False); - *next_idx_ptr = idx + 5; - rval = Py_False; - } - else - fallthrough = 1; - break; - case 'N': - /* NaN */ - if ((idx + 2 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'N') { - rval = _parse_constant(s, JSON_NaN, idx, next_idx_ptr); - } - else - fallthrough = 1; - break; - case 'I': - /* Infinity */ - if ((idx + 7 < length) && str[idx + 1] == 'n' && str[idx + 2] == 'f' && str[idx + 3] == 'i' && str[idx + 4] == 'n' && str[idx + 5] == 'i' && str[idx + 6] == 't' && str[idx + 7] == 'y') { - rval = _parse_constant(s, JSON_Infinity, idx, next_idx_ptr); - } - else - fallthrough = 1; - break; - case '-': - /* -Infinity */ - if ((idx + 8 < length) && str[idx + 1] == 'I' && str[idx + 2] == 'n' && str[idx + 3] == 'f' && str[idx + 4] == 'i' && str[idx + 5] == 'n' && str[idx + 6] == 'i' && str[idx + 7] == 't' && str[idx + 8] == 'y') { - rval = _parse_constant(s, JSON_NegInfinity, idx, next_idx_ptr); - } - else - fallthrough = 1; - break; - default: - fallthrough = 1; - } - /* Didn't find a string, object, array, or named constant. Look for a number. */ - if (fallthrough) - rval = _match_number_str(s, pystr, idx, next_idx_ptr); - return rval; -} -#endif /* PY_MAJOR_VERSION < 3 */ - - -static PyObject * -scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) -{ - /* Read one JSON term (of any kind) from PyUnicode pystr. - idx is the index of the first character of the term - *next_idx_ptr is a return-by-reference index to the first character after - the number. - - Returns a new PyObject representation of the term. - */ - PY2_UNUSED int kind = PyUnicode_KIND(pystr); - void *str = PyUnicode_DATA(pystr); - Py_ssize_t length = PyUnicode_GET_LENGTH(pystr); - PyObject *rval = NULL; - int fallthrough = 0; - if (idx < 0 || idx >= length) { - raise_errmsg(ERR_EXPECTING_VALUE, pystr, idx); - return NULL; - } - switch (PyUnicode_READ(kind, str, idx)) { - case '"': - /* string */ - rval = scanstring_unicode(pystr, idx + 1, - s->strict, - next_idx_ptr); - break; - case '{': - /* object */ - if (Py_EnterRecursiveCall(" while decoding a JSON object " - "from a unicode string")) - return NULL; - rval = _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr); - Py_LeaveRecursiveCall(); - break; - case '[': - /* array */ - if (Py_EnterRecursiveCall(" while decoding a JSON array " - "from a unicode string")) - return NULL; - rval = _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr); - Py_LeaveRecursiveCall(); - break; - case 'n': - /* null */ - if ((idx + 3 < length) && - PyUnicode_READ(kind, str, idx + 1) == 'u' && - PyUnicode_READ(kind, str, idx + 2) == 'l' && - PyUnicode_READ(kind, str, idx + 3) == 'l') { - Py_INCREF(Py_None); - *next_idx_ptr = idx + 4; - rval = Py_None; - } - else - fallthrough = 1; - break; - case 't': - /* true */ - if ((idx + 3 < length) && - PyUnicode_READ(kind, str, idx + 1) == 'r' && - PyUnicode_READ(kind, str, idx + 2) == 'u' && - PyUnicode_READ(kind, str, idx + 3) == 'e') { - Py_INCREF(Py_True); - *next_idx_ptr = idx + 4; - rval = Py_True; - } - else - fallthrough = 1; - break; - case 'f': - /* false */ - if ((idx + 4 < length) && - PyUnicode_READ(kind, str, idx + 1) == 'a' && - PyUnicode_READ(kind, str, idx + 2) == 'l' && - PyUnicode_READ(kind, str, idx + 3) == 's' && - PyUnicode_READ(kind, str, idx + 4) == 'e') { - Py_INCREF(Py_False); - *next_idx_ptr = idx + 5; - rval = Py_False; - } - else - fallthrough = 1; - break; - case 'N': - /* NaN */ - if ((idx + 2 < length) && - PyUnicode_READ(kind, str, idx + 1) == 'a' && - PyUnicode_READ(kind, str, idx + 2) == 'N') { - rval = _parse_constant(s, JSON_NaN, idx, next_idx_ptr); - } - else - fallthrough = 1; - break; - case 'I': - /* Infinity */ - if ((idx + 7 < length) && - PyUnicode_READ(kind, str, idx + 1) == 'n' && - PyUnicode_READ(kind, str, idx + 2) == 'f' && - PyUnicode_READ(kind, str, idx + 3) == 'i' && - PyUnicode_READ(kind, str, idx + 4) == 'n' && - PyUnicode_READ(kind, str, idx + 5) == 'i' && - PyUnicode_READ(kind, str, idx + 6) == 't' && - PyUnicode_READ(kind, str, idx + 7) == 'y') { - rval = _parse_constant(s, JSON_Infinity, idx, next_idx_ptr); - } - else - fallthrough = 1; - break; - case '-': - /* -Infinity */ - if ((idx + 8 < length) && - PyUnicode_READ(kind, str, idx + 1) == 'I' && - PyUnicode_READ(kind, str, idx + 2) == 'n' && - PyUnicode_READ(kind, str, idx + 3) == 'f' && - PyUnicode_READ(kind, str, idx + 4) == 'i' && - PyUnicode_READ(kind, str, idx + 5) == 'n' && - PyUnicode_READ(kind, str, idx + 6) == 'i' && - PyUnicode_READ(kind, str, idx + 7) == 't' && - PyUnicode_READ(kind, str, idx + 8) == 'y') { - rval = _parse_constant(s, JSON_NegInfinity, idx, next_idx_ptr); - } - else - fallthrough = 1; - break; - default: - fallthrough = 1; - } - /* Didn't find a string, object, array, or named constant. Look for a number. */ - if (fallthrough) - rval = _match_number_unicode(s, pystr, idx, next_idx_ptr); - return rval; -} - -static PyObject * -scanner_call(PyObject *self, PyObject *args, PyObject *kwds) -{ - /* Python callable interface to scan_once_{str,unicode} */ - PyObject *pystr; - PyObject *rval; - Py_ssize_t idx; - Py_ssize_t next_idx = -1; - static char *kwlist[] = {"string", "idx", NULL}; - PyScannerObject *s; - assert(PyScanner_Check(self)); - s = (PyScannerObject *)self; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:scan_once", kwlist, &pystr, _convertPyInt_AsSsize_t, &idx)) - return NULL; - - if (PyUnicode_Check(pystr)) { - if (PyUnicode_READY(pystr)) - return NULL; - rval = scan_once_unicode(s, pystr, idx, &next_idx); - } -#if PY_MAJOR_VERSION < 3 - else if (PyString_Check(pystr)) { - rval = scan_once_str(s, pystr, idx, &next_idx); - } -#endif /* PY_MAJOR_VERSION < 3 */ - else { - PyErr_Format(PyExc_TypeError, - "first argument must be a string, not %.80s", - Py_TYPE(pystr)->tp_name); - return NULL; - } - PyDict_Clear(s->memo); - return _build_rval_index_tuple(rval, next_idx); -} - -static PyObject * -JSON_ParseEncoding(PyObject *encoding) -{ - if (encoding == Py_None) - return JSON_InternFromString(DEFAULT_ENCODING); -#if PY_MAJOR_VERSION >= 3 - if (PyUnicode_Check(encoding)) { - if (PyUnicode_AsUTF8(encoding) == NULL) { - return NULL; - } - Py_INCREF(encoding); - return encoding; - } -#else /* PY_MAJOR_VERSION >= 3 */ - if (PyString_Check(encoding)) { - Py_INCREF(encoding); - return encoding; - } - if (PyUnicode_Check(encoding)) - return PyUnicode_AsEncodedString(encoding, NULL, NULL); -#endif /* PY_MAJOR_VERSION >= 3 */ - PyErr_SetString(PyExc_TypeError, "encoding must be a string"); - return NULL; -} - -static PyObject * -scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - /* Initialize Scanner object */ - PyObject *ctx; - static char *kwlist[] = {"context", NULL}; - PyScannerObject *s; - PyObject *encoding; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx)) - return NULL; - - s = (PyScannerObject *)type->tp_alloc(type, 0); - if (s == NULL) - return NULL; - - if (s->memo == NULL) { - s->memo = PyDict_New(); - if (s->memo == NULL) - goto bail; - } - - encoding = PyObject_GetAttrString(ctx, "encoding"); - if (encoding == NULL) - goto bail; - s->encoding = JSON_ParseEncoding(encoding); - Py_XDECREF(encoding); - if (s->encoding == NULL) - goto bail; - - /* All of these will fail "gracefully" so we don't need to verify them */ - s->strict_bool = PyObject_GetAttrString(ctx, "strict"); - if (s->strict_bool == NULL) - goto bail; - s->strict = PyObject_IsTrue(s->strict_bool); - if (s->strict < 0) - goto bail; - s->object_hook = PyObject_GetAttrString(ctx, "object_hook"); - if (s->object_hook == NULL) - goto bail; - s->pairs_hook = PyObject_GetAttrString(ctx, "object_pairs_hook"); - if (s->pairs_hook == NULL) - goto bail; - s->parse_float = PyObject_GetAttrString(ctx, "parse_float"); - if (s->parse_float == NULL) - goto bail; - s->parse_int = PyObject_GetAttrString(ctx, "parse_int"); - if (s->parse_int == NULL) - goto bail; - s->parse_constant = PyObject_GetAttrString(ctx, "parse_constant"); - if (s->parse_constant == NULL) - goto bail; - - return (PyObject *)s; - -bail: - Py_DECREF(s); - return NULL; -} - -PyDoc_STRVAR(scanner_doc, "JSON scanner object"); - -static -PyTypeObject PyScannerType = { - PyVarObject_HEAD_INIT(NULL, 0) - "simplejson._speedups.Scanner", /* tp_name */ - sizeof(PyScannerObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - scanner_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - scanner_call, /* tp_call */ - 0, /* tp_str */ - 0,/* PyObject_GenericGetAttr, */ /* tp_getattro */ - 0,/* PyObject_GenericSetAttr, */ /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - scanner_doc, /* tp_doc */ - scanner_traverse, /* tp_traverse */ - scanner_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - scanner_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0,/* PyType_GenericAlloc, */ /* tp_alloc */ - scanner_new, /* tp_new */ - 0,/* PyObject_GC_Del, */ /* tp_free */ -}; - -static PyObject * -encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = { - "markers", - "default", - "encoder", - "indent", - "key_separator", - "item_separator", - "sort_keys", - "skipkeys", - "allow_nan", - "key_memo", - "use_decimal", - "namedtuple_as_object", - "tuple_as_array", - "int_as_string_bitcount", - "item_sort_key", - "encoding", - "for_json", - "ignore_nan", - "Decimal", - "iterable_as_array", - NULL}; - - PyEncoderObject *s; - PyObject *markers, *defaultfn, *encoder, *indent, *key_separator; - PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan, *key_memo; - PyObject *use_decimal, *namedtuple_as_object, *tuple_as_array, *iterable_as_array; - PyObject *int_as_string_bitcount, *item_sort_key, *encoding, *for_json; - PyObject *ignore_nan, *Decimal; - int is_true; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOOOOOOOOOOOOO:make_encoder", kwlist, - &markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator, - &sort_keys, &skipkeys, &allow_nan, &key_memo, &use_decimal, - &namedtuple_as_object, &tuple_as_array, - &int_as_string_bitcount, &item_sort_key, &encoding, &for_json, - &ignore_nan, &Decimal, &iterable_as_array)) - return NULL; - - s = (PyEncoderObject *)type->tp_alloc(type, 0); - if (s == NULL) - return NULL; - - Py_INCREF(markers); - s->markers = markers; - Py_INCREF(defaultfn); - s->defaultfn = defaultfn; - Py_INCREF(encoder); - s->encoder = encoder; -#if PY_MAJOR_VERSION >= 3 - if (encoding == Py_None) { - s->encoding = NULL; - } - else -#endif /* PY_MAJOR_VERSION >= 3 */ - { - s->encoding = JSON_ParseEncoding(encoding); - if (s->encoding == NULL) - goto bail; - } - Py_INCREF(indent); - s->indent = indent; - Py_INCREF(key_separator); - s->key_separator = key_separator; - Py_INCREF(item_separator); - s->item_separator = item_separator; - Py_INCREF(skipkeys); - s->skipkeys_bool = skipkeys; - s->skipkeys = PyObject_IsTrue(skipkeys); - if (s->skipkeys < 0) - goto bail; - Py_INCREF(key_memo); - s->key_memo = key_memo; - s->fast_encode = (PyCFunction_Check(s->encoder) && PyCFunction_GetFunction(s->encoder) == (PyCFunction)py_encode_basestring_ascii); - is_true = PyObject_IsTrue(ignore_nan); - if (is_true < 0) - goto bail; - s->allow_or_ignore_nan = is_true ? JSON_IGNORE_NAN : 0; - is_true = PyObject_IsTrue(allow_nan); - if (is_true < 0) - goto bail; - s->allow_or_ignore_nan |= is_true ? JSON_ALLOW_NAN : 0; - s->use_decimal = PyObject_IsTrue(use_decimal); - if (s->use_decimal < 0) - goto bail; - s->namedtuple_as_object = PyObject_IsTrue(namedtuple_as_object); - if (s->namedtuple_as_object < 0) - goto bail; - s->tuple_as_array = PyObject_IsTrue(tuple_as_array); - if (s->tuple_as_array < 0) - goto bail; - s->iterable_as_array = PyObject_IsTrue(iterable_as_array); - if (s->iterable_as_array < 0) - goto bail; - if (PyInt_Check(int_as_string_bitcount) || PyLong_Check(int_as_string_bitcount)) { - static const unsigned long long_long_bitsize = SIZEOF_LONG_LONG * 8; - long int_as_string_bitcount_val = PyLong_AsLong(int_as_string_bitcount); - if (int_as_string_bitcount_val > 0 && int_as_string_bitcount_val < (long)long_long_bitsize) { - s->max_long_size = PyLong_FromUnsignedLongLong(1ULL << (int)int_as_string_bitcount_val); - s->min_long_size = PyLong_FromLongLong(-1LL << (int)int_as_string_bitcount_val); - if (s->min_long_size == NULL || s->max_long_size == NULL) { - goto bail; - } - } - else { - PyErr_Format(PyExc_TypeError, - "int_as_string_bitcount (%ld) must be greater than 0 and less than the number of bits of a `long long` type (%lu bits)", - int_as_string_bitcount_val, long_long_bitsize); - goto bail; - } - } - else if (int_as_string_bitcount == Py_None) { - Py_INCREF(Py_None); - s->max_long_size = Py_None; - Py_INCREF(Py_None); - s->min_long_size = Py_None; - } - else { - PyErr_SetString(PyExc_TypeError, "int_as_string_bitcount must be None or an integer"); - goto bail; - } - if (item_sort_key != Py_None) { - if (!PyCallable_Check(item_sort_key)) { - PyErr_SetString(PyExc_TypeError, "item_sort_key must be None or callable"); - goto bail; - } - } - else { - is_true = PyObject_IsTrue(sort_keys); - if (is_true < 0) - goto bail; - if (is_true) { - static PyObject *itemgetter0 = NULL; - if (!itemgetter0) { - PyObject *operator = PyImport_ImportModule("operator"); - if (!operator) - goto bail; - itemgetter0 = PyObject_CallMethod(operator, "itemgetter", "i", 0); - Py_DECREF(operator); - } - item_sort_key = itemgetter0; - if (!item_sort_key) - goto bail; - } - } - if (item_sort_key == Py_None) { - Py_INCREF(Py_None); - s->item_sort_kw = Py_None; - } - else { - s->item_sort_kw = PyDict_New(); - if (s->item_sort_kw == NULL) - goto bail; - if (PyDict_SetItemString(s->item_sort_kw, "key", item_sort_key)) - goto bail; - } - Py_INCREF(sort_keys); - s->sort_keys = sort_keys; - Py_INCREF(item_sort_key); - s->item_sort_key = item_sort_key; - Py_INCREF(Decimal); - s->Decimal = Decimal; - s->for_json = PyObject_IsTrue(for_json); - if (s->for_json < 0) - goto bail; - - return (PyObject *)s; - -bail: - Py_DECREF(s); - return NULL; -} - -static PyObject * -encoder_call(PyObject *self, PyObject *args, PyObject *kwds) -{ - /* Python callable interface to encode_listencode_obj */ - static char *kwlist[] = {"obj", "_current_indent_level", NULL}; - PyObject *obj; - Py_ssize_t indent_level; - PyEncoderObject *s; - JSON_Accu rval; - assert(PyEncoder_Check(self)); - s = (PyEncoderObject *)self; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&:_iterencode", kwlist, - &obj, _convertPyInt_AsSsize_t, &indent_level)) - return NULL; - if (JSON_Accu_Init(&rval)) - return NULL; - if (encoder_listencode_obj(s, &rval, obj, indent_level)) { - JSON_Accu_Destroy(&rval); - return NULL; - } - return JSON_Accu_FinishAsList(&rval); -} - -static PyObject * -_encoded_const(PyObject *obj) -{ - /* Return the JSON string representation of None, True, False */ - if (obj == Py_None) { - static PyObject *s_null = NULL; - if (s_null == NULL) { - s_null = JSON_InternFromString("null"); - } - Py_INCREF(s_null); - return s_null; - } - else if (obj == Py_True) { - static PyObject *s_true = NULL; - if (s_true == NULL) { - s_true = JSON_InternFromString("true"); - } - Py_INCREF(s_true); - return s_true; - } - else if (obj == Py_False) { - static PyObject *s_false = NULL; - if (s_false == NULL) { - s_false = JSON_InternFromString("false"); - } - Py_INCREF(s_false); - return s_false; - } - else { - PyErr_SetString(PyExc_ValueError, "not a const"); - return NULL; - } -} - -static PyObject * -encoder_encode_float(PyEncoderObject *s, PyObject *obj) -{ - /* Return the JSON representation of a PyFloat */ - double i = PyFloat_AS_DOUBLE(obj); - if (!Py_IS_FINITE(i)) { - if (!s->allow_or_ignore_nan) { - PyErr_SetString(PyExc_ValueError, "Out of range float values are not JSON compliant"); - return NULL; - } - if (s->allow_or_ignore_nan & JSON_IGNORE_NAN) { - return _encoded_const(Py_None); - } - /* JSON_ALLOW_NAN is set */ - else if (i > 0) { - Py_INCREF(JSON_Infinity); - return JSON_Infinity; - } - else if (i < 0) { - Py_INCREF(JSON_NegInfinity); - return JSON_NegInfinity; - } - else { - Py_INCREF(JSON_NaN); - return JSON_NaN; - } - } - /* Use a better float format here? */ - if (PyFloat_CheckExact(obj)) { - return PyObject_Repr(obj); - } - else { - /* See #118, do not trust custom str/repr */ - PyObject *res; - PyObject *tmp = PyObject_CallFunctionObjArgs((PyObject *)&PyFloat_Type, obj, NULL); - if (tmp == NULL) { - return NULL; - } - res = PyObject_Repr(tmp); - Py_DECREF(tmp); - return res; - } -} - -static PyObject * -encoder_encode_string(PyEncoderObject *s, PyObject *obj) -{ - /* Return the JSON representation of a string */ - PyObject *encoded; - - if (s->fast_encode) { - return py_encode_basestring_ascii(NULL, obj); - } - encoded = PyObject_CallFunctionObjArgs(s->encoder, obj, NULL); - if (encoded != NULL && -#if PY_MAJOR_VERSION < 3 - !PyString_Check(encoded) && -#endif /* PY_MAJOR_VERSION < 3 */ - !PyUnicode_Check(encoded)) - { - PyErr_Format(PyExc_TypeError, - "encoder() must return a string, not %.80s", - Py_TYPE(encoded)->tp_name); - Py_DECREF(encoded); - return NULL; - } - return encoded; -} - -static int -_steal_accumulate(JSON_Accu *accu, PyObject *stolen) -{ - /* Append stolen and then decrement its reference count */ - int rval = JSON_Accu_Accumulate(accu, stolen); - Py_DECREF(stolen); - return rval; -} - -static int -encoder_listencode_obj(PyEncoderObject *s, JSON_Accu *rval, PyObject *obj, Py_ssize_t indent_level) -{ - /* Encode Python object obj to a JSON term, rval is a PyList */ - int rv = -1; - do { - if (obj == Py_None || obj == Py_True || obj == Py_False) { - PyObject *cstr = _encoded_const(obj); - if (cstr != NULL) - rv = _steal_accumulate(rval, cstr); - } - else if ((PyBytes_Check(obj) && s->encoding != NULL) || - PyUnicode_Check(obj)) - { - PyObject *encoded = encoder_encode_string(s, obj); - if (encoded != NULL) - rv = _steal_accumulate(rval, encoded); - } - else if (PyInt_Check(obj) || PyLong_Check(obj)) { - PyObject *encoded; - if (PyInt_CheckExact(obj) || PyLong_CheckExact(obj)) { - encoded = PyObject_Str(obj); - } - else { - /* See #118, do not trust custom str/repr */ - PyObject *tmp = PyObject_CallFunctionObjArgs((PyObject *)&PyLong_Type, obj, NULL); - if (tmp == NULL) { - encoded = NULL; - } - else { - encoded = PyObject_Str(tmp); - Py_DECREF(tmp); - } - } - if (encoded != NULL) { - encoded = maybe_quote_bigint(s, encoded, obj); - if (encoded == NULL) - break; - rv = _steal_accumulate(rval, encoded); - } - } - else if (PyFloat_Check(obj)) { - PyObject *encoded = encoder_encode_float(s, obj); - if (encoded != NULL) - rv = _steal_accumulate(rval, encoded); - } - else if (s->for_json && _has_for_json_hook(obj)) { - PyObject *newobj; - if (Py_EnterRecursiveCall(" while encoding a JSON object")) - return rv; - newobj = PyObject_CallMethod(obj, "for_json", NULL); - if (newobj != NULL) { - rv = encoder_listencode_obj(s, rval, newobj, indent_level); - Py_DECREF(newobj); - } - Py_LeaveRecursiveCall(); - } - else if (s->namedtuple_as_object && _is_namedtuple(obj)) { - PyObject *newobj; - if (Py_EnterRecursiveCall(" while encoding a JSON object")) - return rv; - newobj = PyObject_CallMethod(obj, "_asdict", NULL); - if (newobj != NULL) { - rv = encoder_listencode_dict(s, rval, newobj, indent_level); - Py_DECREF(newobj); - } - Py_LeaveRecursiveCall(); - } - else if (PyList_Check(obj) || (s->tuple_as_array && PyTuple_Check(obj))) { - if (Py_EnterRecursiveCall(" while encoding a JSON object")) - return rv; - rv = encoder_listencode_list(s, rval, obj, indent_level); - Py_LeaveRecursiveCall(); - } - else if (PyDict_Check(obj)) { - if (Py_EnterRecursiveCall(" while encoding a JSON object")) - return rv; - rv = encoder_listencode_dict(s, rval, obj, indent_level); - Py_LeaveRecursiveCall(); - } - else if (s->use_decimal && PyObject_TypeCheck(obj, (PyTypeObject *)s->Decimal)) { - PyObject *encoded = PyObject_Str(obj); - if (encoded != NULL) - rv = _steal_accumulate(rval, encoded); - } - else if (is_raw_json(obj)) - { - PyObject *encoded = PyObject_GetAttrString(obj, "encoded_json"); - if (encoded != NULL) - rv = _steal_accumulate(rval, encoded); - } - else { - PyObject *ident = NULL; - PyObject *newobj; - if (s->iterable_as_array) { - newobj = PyObject_GetIter(obj); - if (newobj == NULL) - PyErr_Clear(); - else { - rv = encoder_listencode_list(s, rval, newobj, indent_level); - Py_DECREF(newobj); - break; - } - } - if (s->markers != Py_None) { - int has_key; - ident = PyLong_FromVoidPtr(obj); - if (ident == NULL) - break; - has_key = PyDict_Contains(s->markers, ident); - if (has_key) { - if (has_key != -1) - PyErr_SetString(PyExc_ValueError, "Circular reference detected"); - Py_DECREF(ident); - break; - } - if (PyDict_SetItem(s->markers, ident, obj)) { - Py_DECREF(ident); - break; - } - } - if (Py_EnterRecursiveCall(" while encoding a JSON object")) - return rv; - newobj = PyObject_CallFunctionObjArgs(s->defaultfn, obj, NULL); - if (newobj == NULL) { - Py_XDECREF(ident); - Py_LeaveRecursiveCall(); - break; - } - rv = encoder_listencode_obj(s, rval, newobj, indent_level); - Py_LeaveRecursiveCall(); - Py_DECREF(newobj); - if (rv) { - Py_XDECREF(ident); - rv = -1; - } - else if (ident != NULL) { - if (PyDict_DelItem(s->markers, ident)) { - Py_XDECREF(ident); - rv = -1; - } - Py_XDECREF(ident); - } - } - } while (0); - return rv; -} - -static int -encoder_listencode_dict(PyEncoderObject *s, JSON_Accu *rval, PyObject *dct, Py_ssize_t indent_level) -{ - /* Encode Python dict dct a JSON term */ - static PyObject *open_dict = NULL; - static PyObject *close_dict = NULL; - static PyObject *empty_dict = NULL; - PyObject *kstr = NULL; - PyObject *ident = NULL; - PyObject *iter = NULL; - PyObject *item = NULL; - PyObject *items = NULL; - PyObject *encoded = NULL; - Py_ssize_t idx; - - if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) { - open_dict = JSON_InternFromString("{"); - close_dict = JSON_InternFromString("}"); - empty_dict = JSON_InternFromString("{}"); - if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) - return -1; - } - if (PyDict_Size(dct) == 0) - return JSON_Accu_Accumulate(rval, empty_dict); - - if (s->markers != Py_None) { - int has_key; - ident = PyLong_FromVoidPtr(dct); - if (ident == NULL) - goto bail; - has_key = PyDict_Contains(s->markers, ident); - if (has_key) { - if (has_key != -1) - PyErr_SetString(PyExc_ValueError, "Circular reference detected"); - goto bail; - } - if (PyDict_SetItem(s->markers, ident, dct)) { - goto bail; - } - } - - if (JSON_Accu_Accumulate(rval, open_dict)) - goto bail; - - if (s->indent != Py_None) { - /* TODO: DOES NOT RUN */ - indent_level += 1; - /* - newline_indent = '\n' + (_indent * _current_indent_level) - separator = _item_separator + newline_indent - buf += newline_indent - */ - } - - iter = encoder_dict_iteritems(s, dct); - if (iter == NULL) - goto bail; - - idx = 0; - while ((item = PyIter_Next(iter))) { - PyObject *encoded, *key, *value; - if (!PyTuple_Check(item) || Py_SIZE(item) != 2) { - PyErr_SetString(PyExc_ValueError, "items must return 2-tuples"); - goto bail; - } - key = PyTuple_GET_ITEM(item, 0); - if (key == NULL) - goto bail; - value = PyTuple_GET_ITEM(item, 1); - if (value == NULL) - goto bail; - - encoded = PyDict_GetItem(s->key_memo, key); - if (encoded != NULL) { - Py_INCREF(encoded); - } else { - kstr = encoder_stringify_key(s, key); - if (kstr == NULL) - goto bail; - else if (kstr == Py_None) { - /* skipkeys */ - Py_DECREF(item); - Py_DECREF(kstr); - continue; - } - } - if (idx) { - if (JSON_Accu_Accumulate(rval, s->item_separator)) - goto bail; - } - if (encoded == NULL) { - encoded = encoder_encode_string(s, kstr); - Py_CLEAR(kstr); - if (encoded == NULL) - goto bail; - if (PyDict_SetItem(s->key_memo, key, encoded)) - goto bail; - } - if (JSON_Accu_Accumulate(rval, encoded)) { - goto bail; - } - Py_CLEAR(encoded); - if (JSON_Accu_Accumulate(rval, s->key_separator)) - goto bail; - if (encoder_listencode_obj(s, rval, value, indent_level)) - goto bail; - Py_CLEAR(item); - idx += 1; - } - Py_CLEAR(iter); - if (PyErr_Occurred()) - goto bail; - if (ident != NULL) { - if (PyDict_DelItem(s->markers, ident)) - goto bail; - Py_CLEAR(ident); - } - if (s->indent != Py_None) { - /* TODO: DOES NOT RUN */ - indent_level -= 1; - /* - yield '\n' + (_indent * _current_indent_level) - */ - } - if (JSON_Accu_Accumulate(rval, close_dict)) - goto bail; - return 0; - -bail: - Py_XDECREF(encoded); - Py_XDECREF(items); - Py_XDECREF(item); - Py_XDECREF(iter); - Py_XDECREF(kstr); - Py_XDECREF(ident); - return -1; -} - - -static int -encoder_listencode_list(PyEncoderObject *s, JSON_Accu *rval, PyObject *seq, Py_ssize_t indent_level) -{ - /* Encode Python list seq to a JSON term */ - static PyObject *open_array = NULL; - static PyObject *close_array = NULL; - static PyObject *empty_array = NULL; - PyObject *ident = NULL; - PyObject *iter = NULL; - PyObject *obj = NULL; - int is_true; - int i = 0; - - if (open_array == NULL || close_array == NULL || empty_array == NULL) { - open_array = JSON_InternFromString("["); - close_array = JSON_InternFromString("]"); - empty_array = JSON_InternFromString("[]"); - if (open_array == NULL || close_array == NULL || empty_array == NULL) - return -1; - } - ident = NULL; - is_true = PyObject_IsTrue(seq); - if (is_true == -1) - return -1; - else if (is_true == 0) - return JSON_Accu_Accumulate(rval, empty_array); - - if (s->markers != Py_None) { - int has_key; - ident = PyLong_FromVoidPtr(seq); - if (ident == NULL) - goto bail; - has_key = PyDict_Contains(s->markers, ident); - if (has_key) { - if (has_key != -1) - PyErr_SetString(PyExc_ValueError, "Circular reference detected"); - goto bail; - } - if (PyDict_SetItem(s->markers, ident, seq)) { - goto bail; - } - } - - iter = PyObject_GetIter(seq); - if (iter == NULL) - goto bail; - - if (JSON_Accu_Accumulate(rval, open_array)) - goto bail; - if (s->indent != Py_None) { - /* TODO: DOES NOT RUN */ - indent_level += 1; - /* - newline_indent = '\n' + (_indent * _current_indent_level) - separator = _item_separator + newline_indent - buf += newline_indent - */ - } - while ((obj = PyIter_Next(iter))) { - if (i) { - if (JSON_Accu_Accumulate(rval, s->item_separator)) - goto bail; - } - if (encoder_listencode_obj(s, rval, obj, indent_level)) - goto bail; - i++; - Py_CLEAR(obj); - } - Py_CLEAR(iter); - if (PyErr_Occurred()) - goto bail; - if (ident != NULL) { - if (PyDict_DelItem(s->markers, ident)) - goto bail; - Py_CLEAR(ident); - } - if (s->indent != Py_None) { - /* TODO: DOES NOT RUN */ - indent_level -= 1; - /* - yield '\n' + (_indent * _current_indent_level) - */ - } - if (JSON_Accu_Accumulate(rval, close_array)) - goto bail; - return 0; - -bail: - Py_XDECREF(obj); - Py_XDECREF(iter); - Py_XDECREF(ident); - return -1; -} - -static void -encoder_dealloc(PyObject *self) -{ - /* bpo-31095: UnTrack is needed before calling any callbacks */ - PyObject_GC_UnTrack(self); - encoder_clear(self); - Py_TYPE(self)->tp_free(self); -} - -static int -encoder_traverse(PyObject *self, visitproc visit, void *arg) -{ - PyEncoderObject *s; - assert(PyEncoder_Check(self)); - s = (PyEncoderObject *)self; - Py_VISIT(s->markers); - Py_VISIT(s->defaultfn); - Py_VISIT(s->encoder); - Py_VISIT(s->encoding); - Py_VISIT(s->indent); - Py_VISIT(s->key_separator); - Py_VISIT(s->item_separator); - Py_VISIT(s->key_memo); - Py_VISIT(s->sort_keys); - Py_VISIT(s->item_sort_kw); - Py_VISIT(s->item_sort_key); - Py_VISIT(s->max_long_size); - Py_VISIT(s->min_long_size); - Py_VISIT(s->Decimal); - return 0; -} - -static int -encoder_clear(PyObject *self) -{ - /* Deallocate Encoder */ - PyEncoderObject *s; - assert(PyEncoder_Check(self)); - s = (PyEncoderObject *)self; - Py_CLEAR(s->markers); - Py_CLEAR(s->defaultfn); - Py_CLEAR(s->encoder); - Py_CLEAR(s->encoding); - Py_CLEAR(s->indent); - Py_CLEAR(s->key_separator); - Py_CLEAR(s->item_separator); - Py_CLEAR(s->key_memo); - Py_CLEAR(s->skipkeys_bool); - Py_CLEAR(s->sort_keys); - Py_CLEAR(s->item_sort_kw); - Py_CLEAR(s->item_sort_key); - Py_CLEAR(s->max_long_size); - Py_CLEAR(s->min_long_size); - Py_CLEAR(s->Decimal); - return 0; -} - -PyDoc_STRVAR(encoder_doc, "_iterencode(obj, _current_indent_level) -> iterable"); - -static -PyTypeObject PyEncoderType = { - PyVarObject_HEAD_INIT(NULL, 0) - "simplejson._speedups.Encoder", /* tp_name */ - sizeof(PyEncoderObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - encoder_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - encoder_call, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - encoder_doc, /* tp_doc */ - encoder_traverse, /* tp_traverse */ - encoder_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - encoder_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - encoder_new, /* tp_new */ - 0, /* tp_free */ -}; - -static PyMethodDef speedups_methods[] = { - {"encode_basestring_ascii", - (PyCFunction)py_encode_basestring_ascii, - METH_O, - pydoc_encode_basestring_ascii}, - {"scanstring", - (PyCFunction)py_scanstring, - METH_VARARGS, - pydoc_scanstring}, - {NULL, NULL, 0, NULL} -}; - -PyDoc_STRVAR(module_doc, -"simplejson speedups\n"); - -#if PY_MAJOR_VERSION >= 3 -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "_speedups", /* m_name */ - module_doc, /* m_doc */ - -1, /* m_size */ - speedups_methods, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear*/ - NULL, /* m_free */ -}; -#endif - -PyObject * -import_dependency(char *module_name, char *attr_name) -{ - PyObject *rval; - PyObject *module = PyImport_ImportModule(module_name); - if (module == NULL) - return NULL; - rval = PyObject_GetAttrString(module, attr_name); - Py_DECREF(module); - return rval; -} - -static int -init_constants(void) -{ - JSON_NaN = JSON_InternFromString("NaN"); - if (JSON_NaN == NULL) - return 0; - JSON_Infinity = JSON_InternFromString("Infinity"); - if (JSON_Infinity == NULL) - return 0; - JSON_NegInfinity = JSON_InternFromString("-Infinity"); - if (JSON_NegInfinity == NULL) - return 0; -#if PY_MAJOR_VERSION >= 3 - JSON_EmptyUnicode = PyUnicode_New(0, 127); -#else /* PY_MAJOR_VERSION >= 3 */ - JSON_EmptyStr = PyString_FromString(""); - if (JSON_EmptyStr == NULL) - return 0; - JSON_EmptyUnicode = PyUnicode_FromUnicode(NULL, 0); -#endif /* PY_MAJOR_VERSION >= 3 */ - if (JSON_EmptyUnicode == NULL) - return 0; - - return 1; -} - -static PyObject * -moduleinit(void) -{ - PyObject *m; - if (PyType_Ready(&PyScannerType) < 0) - return NULL; - if (PyType_Ready(&PyEncoderType) < 0) - return NULL; - if (!init_constants()) - return NULL; - -#if PY_MAJOR_VERSION >= 3 - m = PyModule_Create(&moduledef); -#else - m = Py_InitModule3("_speedups", speedups_methods, module_doc); -#endif - Py_INCREF((PyObject*)&PyScannerType); - PyModule_AddObject(m, "make_scanner", (PyObject*)&PyScannerType); - Py_INCREF((PyObject*)&PyEncoderType); - PyModule_AddObject(m, "make_encoder", (PyObject*)&PyEncoderType); - RawJSONType = import_dependency("simplejson.raw_json", "RawJSON"); - if (RawJSONType == NULL) - return NULL; - JSONDecodeError = import_dependency("simplejson.errors", "JSONDecodeError"); - if (JSONDecodeError == NULL) - return NULL; - return m; -} - -#if PY_MAJOR_VERSION >= 3 -PyMODINIT_FUNC -PyInit__speedups(void) -{ - return moduleinit(); -} -#else -void -init_speedups(void) -{ - moduleinit(); -} -#endif diff --git a/summer/cacode/ReviewJson/compat.py b/summer/cacode/ReviewJson/compat.py deleted file mode 100644 index d18f7bc..0000000 --- a/summer/cacode/ReviewJson/compat.py +++ /dev/null @@ -1,44 +0,0 @@ -"""Python 3 compatibility shims -""" -import sys - -if sys.version_info[0] < 3: - PY3 = False - - - def b(s): - return s - - - try: - from cStringIO import StringIO - except ImportError: - from StringIO import StringIO - BytesIO = StringIO - text_type = unicode - binary_type = str - string_types = (basestring,) - integer_types = (int, long) - unichr = unichr - reload_module = reload -else: - PY3 = True - if sys.version_info[:2] >= (3, 4): - from importlib import reload as reload_module - else: - from imp import reload as reload_module - - - def b(s): - return bytes(s, 'latin1') - - - from io import StringIO, BytesIO - - text_type = str - binary_type = bytes - string_types = (str,) - integer_types = (int,) - unichr = chr - -long_type = integer_types[-1] diff --git a/summer/cacode/ReviewJson/decoder.py b/summer/cacode/ReviewJson/decoder.py deleted file mode 100644 index 7f0b056..0000000 --- a/summer/cacode/ReviewJson/decoder.py +++ /dev/null @@ -1,400 +0,0 @@ -"""Implementation of JSONDecoder -""" -from __future__ import absolute_import -import re -import sys -import struct -from .compat import PY3, unichr -from .scanner import make_scanner, JSONDecodeError - -def _import_c_scanstring(): - try: - from ._speedups import scanstring - return scanstring - except ImportError: - return None -c_scanstring = _import_c_scanstring() - -# NOTE (3.1.0): JSONDecodeError may still be imported from this module for -# compatibility, but it was never in the __all__ -__all__ = ['JSONDecoder'] - -FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL - -def _floatconstants(): - if sys.version_info < (2, 6): - _BYTES = '7FF80000000000007FF0000000000000'.decode('hex') - nan, inf = struct.unpack('>dd', _BYTES) - else: - nan = float('nan') - inf = float('inf') - return nan, inf, -inf - -NaN, PosInf, NegInf = _floatconstants() - -_CONSTANTS = { - '-Infinity': NegInf, - 'Infinity': PosInf, - 'NaN': NaN, -} - -STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS) -BACKSLASH = { - '"': u'"', '\\': u'\\', '/': u'/', - 'b': u'\b', 'f': u'\f', 'n': u'\n', 'r': u'\r', 't': u'\t', -} - -DEFAULT_ENCODING = "utf-8" - -def py_scanstring(s, end, encoding=None, strict=True, - _b=BACKSLASH, _m=STRINGCHUNK.match, _join=u''.join, - _PY3=PY3, _maxunicode=sys.maxunicode): - """Scan the string s for a JSON string. End is the index of the - character in s after the quote that started the JSON string. - Unescapes all valid JSON string escape sequences and raises ValueError - on attempt to decode an invalid string. If strict is False then literal - control characters are allowed in the string. - - Returns a tuple of the decoded string and the index of the character in s - after the end quote.""" - if encoding is None: - encoding = DEFAULT_ENCODING - chunks = [] - _append = chunks.append - begin = end - 1 - while 1: - chunk = _m(s, end) - if chunk is None: - raise JSONDecodeError( - "Unterminated string starting at", s, begin) - end = chunk.end() - content, terminator = chunk.groups() - # Content is contains zero or more unescaped string characters - if content: - if not _PY3 and not isinstance(content, unicode): - content = unicode(content, encoding) - _append(content) - # Terminator is the end of string, a literal control character, - # or a backslash denoting that an escape sequence follows - if terminator == '"': - break - elif terminator != '\\': - if strict: - msg = "Invalid control character %r at" - raise JSONDecodeError(msg, s, end) - else: - _append(terminator) - continue - try: - esc = s[end] - except IndexError: - raise JSONDecodeError( - "Unterminated string starting at", s, begin) - # If not a unicode escape sequence, must be in the lookup table - if esc != 'u': - try: - char = _b[esc] - except KeyError: - msg = "Invalid \\X escape sequence %r" - raise JSONDecodeError(msg, s, end) - end += 1 - else: - # Unicode escape sequence - msg = "Invalid \\uXXXX escape sequence" - esc = s[end + 1:end + 5] - escX = esc[1:2] - if len(esc) != 4 or escX == 'x' or escX == 'X': - raise JSONDecodeError(msg, s, end - 1) - try: - uni = int(esc, 16) - except ValueError: - raise JSONDecodeError(msg, s, end - 1) - end += 5 - # Check for surrogate pair on UCS-4 systems - # Note that this will join high/low surrogate pairs - # but will also pass unpaired surrogates through - if (_maxunicode > 65535 and - uni & 0xfc00 == 0xd800 and - s[end:end + 2] == '\\u'): - esc2 = s[end + 2:end + 6] - escX = esc2[1:2] - if len(esc2) == 4 and not (escX == 'x' or escX == 'X'): - try: - uni2 = int(esc2, 16) - except ValueError: - raise JSONDecodeError(msg, s, end) - if uni2 & 0xfc00 == 0xdc00: - uni = 0x10000 + (((uni - 0xd800) << 10) | - (uni2 - 0xdc00)) - end += 6 - char = unichr(uni) - # Append the unescaped character - _append(char) - return _join(chunks), end - - -# Use speedup if available -scanstring = c_scanstring or py_scanstring - -WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS) -WHITESPACE_STR = ' \t\n\r' - -def JSONObject(state, encoding, strict, scan_once, object_hook, - object_pairs_hook, memo=None, - _w=WHITESPACE.match, _ws=WHITESPACE_STR): - (s, end) = state - # Backwards compatibility - if memo is None: - memo = {} - memo_get = memo.setdefault - pairs = [] - # Use a slice to prevent IndexError from being raised, the following - # check will raise a more specific ValueError if the string is empty - nextchar = s[end:end + 1] - # Normally we expect nextchar == '"' - if nextchar != '"': - if nextchar in _ws: - end = _w(s, end).end() - nextchar = s[end:end + 1] - # Trivial empty object - if nextchar == '}': - if object_pairs_hook is not None: - result = object_pairs_hook(pairs) - return result, end + 1 - pairs = {} - if object_hook is not None: - pairs = object_hook(pairs) - return pairs, end + 1 - elif nextchar != '"': - raise JSONDecodeError( - "Expecting property name enclosed in double quotes", - s, end) - end += 1 - while True: - key, end = scanstring(s, end, encoding, strict) - key = memo_get(key, key) - - # To skip some function call overhead we optimize the fast paths where - # the JSON key separator is ": " or just ":". - if s[end:end + 1] != ':': - end = _w(s, end).end() - if s[end:end + 1] != ':': - raise JSONDecodeError("Expecting ':' delimiter", s, end) - - end += 1 - - try: - if s[end] in _ws: - end += 1 - if s[end] in _ws: - end = _w(s, end + 1).end() - except IndexError: - pass - - value, end = scan_once(s, end) - pairs.append((key, value)) - - try: - nextchar = s[end] - if nextchar in _ws: - end = _w(s, end + 1).end() - nextchar = s[end] - except IndexError: - nextchar = '' - end += 1 - - if nextchar == '}': - break - elif nextchar != ',': - raise JSONDecodeError("Expecting ',' delimiter or '}'", s, end - 1) - - try: - nextchar = s[end] - if nextchar in _ws: - end += 1 - nextchar = s[end] - if nextchar in _ws: - end = _w(s, end + 1).end() - nextchar = s[end] - except IndexError: - nextchar = '' - - end += 1 - if nextchar != '"': - raise JSONDecodeError( - "Expecting property name enclosed in double quotes", - s, end - 1) - - if object_pairs_hook is not None: - result = object_pairs_hook(pairs) - return result, end - pairs = dict(pairs) - if object_hook is not None: - pairs = object_hook(pairs) - return pairs, end - -def JSONArray(state, scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR): - (s, end) = state - values = [] - nextchar = s[end:end + 1] - if nextchar in _ws: - end = _w(s, end + 1).end() - nextchar = s[end:end + 1] - # Look-ahead for trivial empty array - if nextchar == ']': - return values, end + 1 - elif nextchar == '': - raise JSONDecodeError("Expecting value or ']'", s, end) - _append = values.append - while True: - value, end = scan_once(s, end) - _append(value) - nextchar = s[end:end + 1] - if nextchar in _ws: - end = _w(s, end + 1).end() - nextchar = s[end:end + 1] - end += 1 - if nextchar == ']': - break - elif nextchar != ',': - raise JSONDecodeError("Expecting ',' delimiter or ']'", s, end - 1) - - try: - if s[end] in _ws: - end += 1 - if s[end] in _ws: - end = _w(s, end + 1).end() - except IndexError: - pass - - return values, end - -class JSONDecoder(object): - """Simple JSON decoder - - Performs the following translations in decoding by default: - - +---------------+-------------------+ - | JSON | Python | - +===============+===================+ - | object | dict | - +---------------+-------------------+ - | array | list | - +---------------+-------------------+ - | string | str, unicode | - +---------------+-------------------+ - | number (int) | int, long | - +---------------+-------------------+ - | number (real) | float | - +---------------+-------------------+ - | true | True | - +---------------+-------------------+ - | false | False | - +---------------+-------------------+ - | null | None | - +---------------+-------------------+ - - It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as - their corresponding ``float`` values, which is outside the JSON spec. - - """ - - def __init__(self, encoding=None, object_hook=None, parse_float=None, - parse_int=None, parse_constant=None, strict=True, - object_pairs_hook=None): - """ - *encoding* determines the encoding used to interpret any - :class:`str` objects decoded by this instance (``'utf-8'`` by - default). It has no effect when decoding :class:`unicode` objects. - - Note that currently only encodings that are a superset of ASCII work, - strings of other encodings should be passed in as :class:`unicode`. - - *object_hook*, if specified, will be called with the result of every - JSON object decoded and its return value will be used in place of the - given :class:`dict`. This can be used to provide custom - deserializations (e.g. to support JSON-RPC class hinting). - - *object_pairs_hook* is an optional function that will be called with - the result of any object literal decode with an ordered list of pairs. - The return value of *object_pairs_hook* will be used instead of the - :class:`dict`. This feature can be used to implement custom decoders - that rely on the order that the key and value pairs are decoded (for - example, :func:`collections.OrderedDict` will remember the order of - insertion). If *object_hook* is also defined, the *object_pairs_hook* - takes priority. - - *parse_float*, if specified, will be called with the string of every - JSON float to be decoded. By default, this is equivalent to - ``float(num_str)``. This can be used to use another datatype or parser - for JSON floats (e.g. :class:`decimal.Decimal`). - - *parse_int*, if specified, will be called with the string of every - JSON int to be decoded. By default, this is equivalent to - ``int(num_str)``. This can be used to use another datatype or parser - for JSON integers (e.g. :class:`float`). - - *parse_constant*, if specified, will be called with one of the - following strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``. This - can be used to raise an exception if invalid JSON numbers are - encountered. - - *strict* controls the parser's behavior when it encounters an - invalid control character in a string. The default setting of - ``True`` means that unescaped control characters are parse errors, if - ``False`` then control characters will be allowed in strings. - - """ - if encoding is None: - encoding = DEFAULT_ENCODING - self.encoding = encoding - self.object_hook = object_hook - self.object_pairs_hook = object_pairs_hook - self.parse_float = parse_float or float - self.parse_int = parse_int or int - self.parse_constant = parse_constant or _CONSTANTS.__getitem__ - self.strict = strict - self.parse_object = JSONObject - self.parse_array = JSONArray - self.parse_string = scanstring - self.memo = {} - self.scan_once = make_scanner(self) - - def decode(self, s, _w=WHITESPACE.match, _PY3=PY3): - """Return the Python representation of ``s`` (a ``str`` or ``unicode`` - instance containing a JSON document) - - """ - if _PY3 and isinstance(s, bytes): - s = str(s, self.encoding) - obj, end = self.raw_decode(s) - end = _w(s, end).end() - if end != len(s): - raise JSONDecodeError("Extra data", s, end, len(s)) - return obj - - def raw_decode(self, s, idx=0, _w=WHITESPACE.match, _PY3=PY3): - """Decode a JSON document from ``s`` (a ``str`` or ``unicode`` - beginning with a JSON document) and return a 2-tuple of the Python - representation and the index in ``s`` where the document ended. - Optionally, ``idx`` can be used to specify an offset in ``s`` where - the JSON document begins. - - This can be used to decode a JSON document from a string that may - have extraneous data at the end. - - """ - if idx < 0: - # Ensure that raw_decode bails on negative indexes, the regex - # would otherwise mask this behavior. #98 - raise JSONDecodeError('Expecting value', s, idx) - if _PY3 and not isinstance(s, str): - raise TypeError("Input string must be text, not bytes") - # strip UTF-8 bom - if len(s) > idx: - ord0 = ord(s[idx]) - if ord0 == 0xfeff: - idx += 1 - elif ord0 == 0xef and s[idx:idx + 3] == '\xef\xbb\xbf': - idx += 3 - return self.scan_once(s, idx=_w(s, idx).end()) diff --git a/summer/cacode/ReviewJson/encoder.py b/summer/cacode/ReviewJson/encoder.py deleted file mode 100644 index 7ea172e..0000000 --- a/summer/cacode/ReviewJson/encoder.py +++ /dev/null @@ -1,722 +0,0 @@ -"""Implementation of JSONEncoder -""" -from __future__ import absolute_import -import re -from operator import itemgetter -# Do not import Decimal directly to avoid reload issues -import decimal -from .compat import unichr, binary_type, text_type, string_types, integer_types, PY3 -def _import_speedups(): - try: - from . import _speedups - return _speedups.encode_basestring_ascii, _speedups.make_encoder - except ImportError: - return None, None -c_encode_basestring_ascii, c_make_encoder = _import_speedups() - -from .decoder import PosInf -from .raw_json import RawJSON - -ESCAPE = re.compile(r'[\x00-\x1f\\"]') -ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])') -HAS_UTF8 = re.compile(r'[\x80-\xff]') -ESCAPE_DCT = { - '\\': '\\\\', - '"': '\\"', - '\b': '\\b', - '\f': '\\f', - '\n': '\\n', - '\r': '\\r', - '\t': '\\t', -} -for i in range(0x20): - #ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i)) - ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,)) - -FLOAT_REPR = repr - -def encode_basestring(s, _PY3=PY3, _q=u'"'): - """Return a JSON representation of a Python string - - """ - if _PY3: - if isinstance(s, bytes): - s = str(s, 'utf-8') - elif type(s) is not str: - # convert an str subclass instance to exact str - # raise a TypeError otherwise - s = str.__str__(s) - else: - if isinstance(s, str) and HAS_UTF8.search(s) is not None: - s = unicode(s, 'utf-8') - elif type(s) not in (str, unicode): - # convert an str subclass instance to exact str - # convert a unicode subclass instance to exact unicode - # raise a TypeError otherwise - if isinstance(s, str): - s = str.__str__(s) - else: - s = unicode.__getnewargs__(s)[0] - def replace(match): - return ESCAPE_DCT[match.group(0)] - return _q + ESCAPE.sub(replace, s) + _q - - -def py_encode_basestring_ascii(s, _PY3=PY3): - """Return an ASCII-only JSON representation of a Python string - - """ - if _PY3: - if isinstance(s, bytes): - s = str(s, 'utf-8') - elif type(s) is not str: - # convert an str subclass instance to exact str - # raise a TypeError otherwise - s = str.__str__(s) - else: - if isinstance(s, str) and HAS_UTF8.search(s) is not None: - s = unicode(s, 'utf-8') - elif type(s) not in (str, unicode): - # convert an str subclass instance to exact str - # convert a unicode subclass instance to exact unicode - # raise a TypeError otherwise - if isinstance(s, str): - s = str.__str__(s) - else: - s = unicode.__getnewargs__(s)[0] - def replace(match): - s = match.group(0) - try: - return ESCAPE_DCT[s] - except KeyError: - n = ord(s) - if n < 0x10000: - #return '\\u{0:04x}'.format(n) - return '\\u%04x' % (n,) - else: - # surrogate pair - n -= 0x10000 - s1 = 0xd800 | ((n >> 10) & 0x3ff) - s2 = 0xdc00 | (n & 0x3ff) - #return '\\u{0:04x}\\u{1:04x}'.format(s1, s2) - return '\\u%04x\\u%04x' % (s1, s2) - return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"' - - -encode_basestring_ascii = ( - c_encode_basestring_ascii or py_encode_basestring_ascii) - -class JSONEncoder(object): - """Extensible JSON encoder for Python data structures. - - Supports the following objects and types by default: - - +-------------------+---------------+ - | Python | JSON | - +===================+===============+ - | dict, namedtuple | object | - +-------------------+---------------+ - | list, tuple | array | - +-------------------+---------------+ - | str, unicode | string | - +-------------------+---------------+ - | int, long, float | number | - +-------------------+---------------+ - | True | true | - +-------------------+---------------+ - | False | false | - +-------------------+---------------+ - | None | null | - +-------------------+---------------+ - - To extend this to recognize other objects, subclass and implement a - ``.default()`` method with another method that returns a serializable - object for ``o`` if possible, otherwise it should call the superclass - implementation (to raise ``TypeError``). - - """ - item_separator = ', ' - key_separator = ': ' - - def __init__(self, skipkeys=False, ensure_ascii=True, - check_circular=True, allow_nan=True, sort_keys=False, - indent=None, separators=None, encoding='utf-8', default=None, - use_decimal=True, namedtuple_as_object=True, - tuple_as_array=True, bigint_as_string=False, - item_sort_key=None, for_json=False, ignore_nan=False, - int_as_string_bitcount=None, iterable_as_array=False): - """Constructor for JSONEncoder, with sensible defaults. - - If skipkeys is false, then it is a TypeError to attempt - encoding of keys that are not str, int, long, float or None. If - skipkeys is True, such items are simply skipped. - - If ensure_ascii is true, the output is guaranteed to be str - objects with all incoming unicode characters escaped. If - ensure_ascii is false, the output will be unicode object. - - If check_circular is true, then lists, dicts, and custom encoded - objects will be checked for circular references during encoding to - prevent an infinite recursion (which would cause an OverflowError). - Otherwise, no such check takes place. - - If allow_nan is true, then NaN, Infinity, and -Infinity will be - encoded as such. This behavior is not JSON specification compliant, - but is consistent with most JavaScript based encoders and decoders. - Otherwise, it will be a ValueError to encode such floats. - - If sort_keys is true, then the output of dictionaries will be - sorted by key; this is useful for regression tests to ensure - that JSON serializations can be compared on a day-to-day basis. - - If indent is a string, then JSON array elements and object members - will be pretty-printed with a newline followed by that string repeated - for each level of nesting. ``None`` (the default) selects the most compact - representation without any newlines. For backwards compatibility with - versions of simplejson earlier than 2.1.0, an integer is also accepted - and is converted to a string with that many spaces. - - If specified, separators should be an (item_separator, key_separator) - tuple. The default is (', ', ': ') if *indent* is ``None`` and - (',', ': ') otherwise. To get the most compact JSON representation, - you should specify (',', ':') to eliminate whitespace. - - If specified, default is a function that gets called for objects - that can't otherwise be serialized. It should return a JSON encodable - version of the object or raise a ``TypeError``. - - If encoding is not None, then all input strings will be - transformed into unicode using that encoding prior to JSON-encoding. - The default is UTF-8. - - If use_decimal is true (default: ``True``), ``decimal.Decimal`` will - be supported directly by the encoder. For the inverse, decode JSON - with ``parse_float=decimal.Decimal``. - - If namedtuple_as_object is true (the default), objects with - ``_asdict()`` methods will be encoded as JSON objects. - - If tuple_as_array is true (the default), tuple (and subclasses) will - be encoded as JSON arrays. - - If *iterable_as_array* is true (default: ``False``), - any object not in the above table that implements ``__iter__()`` - will be encoded as a JSON array. - - If bigint_as_string is true (not the default), ints 2**53 and higher - or lower than -2**53 will be encoded as strings. This is to avoid the - rounding that happens in Javascript otherwise. - - If int_as_string_bitcount is a positive number (n), then int of size - greater than or equal to 2**n or lower than or equal to -2**n will be - encoded as strings. - - If specified, item_sort_key is a callable used to sort the items in - each dictionary. This is useful if you want to sort items other than - in alphabetical order by key. - - If for_json is true (not the default), objects with a ``for_json()`` - method will use the return value of that method for encoding as JSON - instead of the object. - - If *ignore_nan* is true (default: ``False``), then out of range - :class:`float` values (``nan``, ``inf``, ``-inf``) will be serialized - as ``null`` in compliance with the ECMA-262 specification. If true, - this will override *allow_nan*. - - """ - - self.skipkeys = skipkeys - self.ensure_ascii = ensure_ascii - self.check_circular = check_circular - self.allow_nan = allow_nan - self.sort_keys = sort_keys - self.use_decimal = use_decimal - self.namedtuple_as_object = namedtuple_as_object - self.tuple_as_array = tuple_as_array - self.iterable_as_array = iterable_as_array - self.bigint_as_string = bigint_as_string - self.item_sort_key = item_sort_key - self.for_json = for_json - self.ignore_nan = ignore_nan - self.int_as_string_bitcount = int_as_string_bitcount - if indent is not None and not isinstance(indent, string_types): - indent = indent * ' ' - self.indent = indent - if separators is not None: - self.item_separator, self.key_separator = separators - elif indent is not None: - self.item_separator = ',' - if default is not None: - self.default = default - self.encoding = encoding - - def default(self, o): - """Implement this method in a subclass such that it returns - a serializable object for ``o``, or calls the base implementation - (to raise a ``TypeError``). - - For example, to support arbitrary iterators, you could - implement default like this:: - - def default(self, o): - try: - iterable = iter(o) - except TypeError: - pass - else: - return list(iterable) - return JSONEncoder.default(self, o) - - """ - raise TypeError('Object of type %s is not JSON serializable' % - o.__class__.__name__) - - def encode(self, o): - """Return a JSON string representation of a Python data structure. - - >>> from simplejson import JSONEncoder - >>> JSONEncoder().encode({"foo": ["bar", "baz"]}) - '{"foo": ["bar", "baz"]}' - - """ - # This is for extremely simple cases and benchmarks. - if isinstance(o, binary_type): - _encoding = self.encoding - if (_encoding is not None and not (_encoding == 'utf-8')): - o = text_type(o, _encoding) - if isinstance(o, string_types): - if self.ensure_ascii: - return encode_basestring_ascii(o) - else: - return encode_basestring(o) - # This doesn't pass the iterator directly to ''.join() because the - # exceptions aren't as detailed. The list call should be roughly - # equivalent to the PySequence_Fast that ''.join() would do. - chunks = self.iterencode(o, _one_shot=True) - if not isinstance(chunks, (list, tuple)): - chunks = list(chunks) - if self.ensure_ascii: - return ''.join(chunks) - else: - return u''.join(chunks) - - def iterencode(self, o, _one_shot=False): - """Encode the given object and yield each string - representation as available. - - For example:: - - for chunk in JSONEncoder().iterencode(bigobject): - mysocket.write(chunk) - - """ - if self.check_circular: - markers = {} - else: - markers = None - if self.ensure_ascii: - _encoder = encode_basestring_ascii - else: - _encoder = encode_basestring - if self.encoding != 'utf-8' and self.encoding is not None: - def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding): - if isinstance(o, binary_type): - o = text_type(o, _encoding) - return _orig_encoder(o) - - def floatstr(o, allow_nan=self.allow_nan, ignore_nan=self.ignore_nan, - _repr=FLOAT_REPR, _inf=PosInf, _neginf=-PosInf): - # Check for specials. Note that this type of test is processor - # and/or platform-specific, so do tests which don't depend on - # the internals. - - if o != o: - text = 'NaN' - elif o == _inf: - text = 'Infinity' - elif o == _neginf: - text = '-Infinity' - else: - if type(o) != float: - # See #118, do not trust custom str/repr - o = float(o) - return _repr(o) - - if ignore_nan: - text = 'null' - elif not allow_nan: - raise ValueError( - "Out of range float values are not JSON compliant: " + - repr(o)) - - return text - - key_memo = {} - int_as_string_bitcount = ( - 53 if self.bigint_as_string else self.int_as_string_bitcount) - if (_one_shot and c_make_encoder is not None - and self.indent is None): - _iterencode = c_make_encoder( - markers, self.default, _encoder, self.indent, - self.key_separator, self.item_separator, self.sort_keys, - self.skipkeys, self.allow_nan, key_memo, self.use_decimal, - self.namedtuple_as_object, self.tuple_as_array, - int_as_string_bitcount, - self.item_sort_key, self.encoding, self.for_json, - self.ignore_nan, decimal.Decimal, self.iterable_as_array) - else: - _iterencode = _make_iterencode( - markers, self.default, _encoder, self.indent, floatstr, - self.key_separator, self.item_separator, self.sort_keys, - self.skipkeys, _one_shot, self.use_decimal, - self.namedtuple_as_object, self.tuple_as_array, - int_as_string_bitcount, - self.item_sort_key, self.encoding, self.for_json, - self.iterable_as_array, Decimal=decimal.Decimal) - try: - return _iterencode(o, 0) - finally: - key_memo.clear() - - -class JSONEncoderForHTML(JSONEncoder): - """An encoder that produces JSON safe to embed in HTML. - - To embed JSON content in, say, a script tag on a web page, the - characters &, < and > should be escaped. They cannot be escaped - with the usual entities (e.g. &) because they are not expanded - within