helpers.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import contextlib
  4. import inspect
  5. import logging
  6. import uuid
  7. from copy import deepcopy
  8. from functools import wraps, partial
  9. import simplejson as json
  10. from django.conf import settings
  11. from django.http import JsonResponse
  12. from django.utils.module_loading import import_string
  13. from mongoengine.base import BaseField
  14. from typing import Union, Tuple, TYPE_CHECKING, Optional, Mapping
  15. from apps import serviceCache
  16. from apps.web.constant import APP_TYPE, AppPlatformType
  17. from apps.web.core import ROLE
  18. from apps.web.core.auth.ali import AlipayAuthBridge
  19. from apps.web.core.auth.wechat import WechatAuthBridge
  20. from apps.web.core.bridge.wechat import WechatClientProxy
  21. from apps.web.core.datastructures import BaseVisitor
  22. from apps.web.core.models import SystemSettings, ManualPayApp, AliApp
  23. from apps.web.core.payment.ali import AliPayISVGateway
  24. from apps.web.models import MongoTempTable
  25. from apps.web.utils import is_user, is_dealer, is_agent, is_anonymous
  26. logger = logging.getLogger(__name__)
  27. if TYPE_CHECKING:
  28. from apps.web.device.models import DeviceDict
  29. from apps.web.core.models import WechatManagerApp, WechatAuthApp
  30. from apps.web.ad.models import Advertiser, Advertisement
  31. from apps.web.user.models import MyUser
  32. from apps.web.common.models import WithdrawRecord
  33. from apps.web.dealer.models import SubAccount
  34. from django.contrib.auth.models import AnonymousUser
  35. from apps.web.dealer.models import Dealer
  36. from apps.web.agent.models import Agent
  37. from apps.web.device.models import Device
  38. from apps.web.management.models import Manager
  39. SourceT = Union[Agent, Dealer, Device, Manager, DeviceDict, WithdrawRecord]
  40. from apps.web.core.models import WechatPayApp
  41. WechatAPP_T = Union[WechatPayApp, WechatManagerApp, WechatAuthApp]
  42. PayApp_T = Union[WechatPayApp, AliApp]
  43. AuthApp_T = Union[WechatManagerApp, WechatAuthApp]
  44. class DeviceTypeVisitor(BaseVisitor):
  45. def entry(self, node):
  46. return node.__class__.__name__
  47. def visit_Agent(self, node):
  48. # type:(Agent)->list
  49. """
  50. 主要的逻辑在于,如果该代理商有以自己为准的设备类型则显示,否则则向上查。因为在某些情况下,同一厂商下的代理商可能会与主代理商的部分起冲突
  51. :param node:
  52. :return:
  53. """
  54. from apps.web.device.models import DeviceType
  55. query_set = DeviceType.objects(agentId = str(node.id)).order_by("-popularity")
  56. if query_set.count() > 0:
  57. return query_set
  58. else:
  59. return DeviceType.objects(agentId = str(node.primary_agent.id)).order_by("-popularity")
  60. def visit_Dealer(self, node):
  61. # type:(Dealer)->list
  62. Agent = import_string('apps.web.agent.models.Agent')
  63. agent = Agent.objects(id = node.agentId).get()
  64. return self.visit_Agent(agent)
  65. def visit_SubAccount(self, node):
  66. # type:(SubAccount)->list
  67. Agent = import_string('apps.web.agent.models.Agent')
  68. agent = Agent.objects(id = node.agentId).get()
  69. return self.visit_Agent(agent)
  70. def visit_Manager(self, node):
  71. # type:(Manager)->list
  72. Agent = import_string('apps.web.agent.models.Agent')
  73. agent = Agent.objects(id = str(node.primeAgentId)).get()
  74. return self.visit_Agent(agent)
  75. def visit_Advertiser(self, node):
  76. # type:(Advertiser)->list
  77. from apps.web.management.models import Manager
  78. manager = Manager.objects(id = str(node.managerId)).first()
  79. return self.visit_Manager(manager)
  80. def visit_Advertisement(self, node):
  81. # type:(Advertisement)->list
  82. from apps.web.management.models import Manager
  83. manager = Manager.objects(id = str(node.managerId)).first()
  84. return self.visit_Manager(manager)
  85. class AgentCustomizedBrandVisitor(BaseVisitor):
  86. """
  87. 该访问者主要是为了帮助不同的资源利用者获得
  88. TODO: 减少请求,可以做缓存
  89. keygen := e.g. redis.set(<visitor-name>:<visitor-via(dealer|device|...)>:<hashed-id>, <id-to-retrieve-gateway|bridge>
  90. 目前自定义授权信息和收入流均为代理商所绑定。
  91. 在这里通过不同的对象分发生成相应的网关和桥。
  92. """
  93. def __init__(self, factory_type, **kwargs):
  94. self.model_cls = import_string('apps.web.agent.models.Agent')
  95. self.factory = self.model_cls.factory(factory_type = factory_type, **kwargs)
  96. def entry(self, node):
  97. return node.__class__.__name__
  98. def visit_Agent(self, node):
  99. return self.factory(node)
  100. def visit_Dealer(self, node):
  101. agent = self.model_cls.objects(id = str(node.agentId)).get()
  102. return self.visit_Agent(agent)
  103. def visit_Device(self, node):
  104. Dealer = import_string('apps.web.dealer.models.Dealer')
  105. Agent = import_string('apps.web.agent.models.Agent')
  106. dealer = Dealer.objects(id = node.ownerId).get()
  107. agent = Agent.objects(id = str(dealer.agentId)).get()
  108. return self.visit_Agent(agent)
  109. def visit_Manager(self, node):
  110. Agent = import_string('apps.web.agent.models.Agent')
  111. agent = Agent.objects(id = str(node.primeAgentId)).get()
  112. return self.visit_Agent(agent)
  113. def visit_DeviceDict(self, node):
  114. # type:(DeviceDict)->None
  115. """默认视为deviceDict"""
  116. Dealer = import_string('apps.web.dealer.models.Dealer')
  117. Agent = import_string('apps.web.agent.models.Agent')
  118. dealer = Dealer.objects(id = str(node['ownerId'])).get()
  119. agent = Agent.objects(id = str(dealer.agentId)).get()
  120. return self.visit_Agent(agent)
  121. def visit_WithdrawRecord(self, node):
  122. # type:(WithdrawRecord)->None
  123. Dealer = import_string('apps.web.dealer.models.Dealer')
  124. Agent = import_string('apps.web.agent.models.Agent')
  125. if node.role == ROLE.dealer:
  126. dealer = Dealer.objects(id = node.ownerId).get()
  127. agent = Agent.objects(id = str(dealer.agentId)).get()
  128. elif node.role == ROLE.agent:
  129. agent = Agent.objects(id = str(node.ownerId)).get()
  130. else:
  131. assert False, 'invalid withdraw record role'
  132. return self.visit_Agent(agent)
  133. def visit_dict(self, node):
  134. return self.visit_DeviceDict(node)
  135. class DealerCustomizedBrandVisitor(BaseVisitor):
  136. def __init__(self, factory_type, **kwargs):
  137. self.model_cls = import_string('apps.web.dealer.models.Dealer')
  138. self.factory = self.model_cls.factory(factory_type = factory_type, **kwargs)
  139. def entry(self, node):
  140. return node.__class__.__name__
  141. def visit_Dealer(self, node):
  142. return self.factory(node)
  143. def is_same_wechat_app(leftApp, rightApp):
  144. # type:(WechatAPP_T, WechatAPP_T)->bool
  145. if leftApp['appid'] == rightApp['appid']:
  146. return True
  147. else:
  148. return False
  149. def get_app(source, app_type, vistor = AgentCustomizedBrandVisitor, **kwargs):
  150. # type:(SourceT, str, Optional[AgentCustomizedBrandVisitor, DealerCustomizedBrandVisitor], Mapping[str, str])->WechatAPP_T
  151. logger.debug('get wechat app. source = {}; app type = {}; vistor = {}; kwargs = {}'.format(
  152. repr(source), app_type, vistor.__name__, str(kwargs)))
  153. return vistor(factory_type = 'app', app_type = app_type, **kwargs).visit(source)
  154. def get_user_manager_agent(source):
  155. # type:(SourceT)->Agent
  156. app = get_app(source = source, app_type = APP_TYPE.WECHAT_USER_MANAGER)
  157. return getattr(app, 'occupant')
  158. def get_ali_auth_bridge(source, app_type):
  159. # type:(SourceT)->AlipayAuthBridge
  160. app = get_app(source, app_type)
  161. return AlipayAuthBridge(app)
  162. def get_wechat_auth_bridge(source, app_type):
  163. # type:(SourceT, str)->WechatAuthBridge
  164. app = get_app(source, app_type)
  165. return WechatAuthBridge(app = app)
  166. def get_wechat_user_messager_app(source):
  167. return get_app(source, APP_TYPE.WECHAT_USER_MESSAGER)
  168. def get_wechat_user_manager_mp_proxy(source):
  169. app = get_app(source, APP_TYPE.WECHAT_USER_MANAGER)
  170. return WechatClientProxy(app)
  171. def get_wechat_user_sub_manager_mp_proxy(source):
  172. app = get_app(source, APP_TYPE.WECHAT_USER_SUBSCRIBE_MANAGER)
  173. return WechatClientProxy(app)
  174. def get_wechat_dealer_sub_manager_mp_proxy(source):
  175. app = get_app(source, APP_TYPE.WECHAT_DEALER_SUBSCRIBE_MANAGER)
  176. return WechatClientProxy(app)
  177. def get_wechat_manager_mp_proxy(source):
  178. app = get_app(source, APP_TYPE.WECHAT_MANAGER)
  179. return WechatClientProxy(app)
  180. def get_inhouse_wechat_manager_mp_proxy():
  181. Agent = import_string('apps.web.agent.models.Agent')
  182. app = Agent.get_platform_wechat_manager_app()
  183. return WechatClientProxy(app)
  184. def get_inhouse_wechat_user_manager_mp_proxy():
  185. Agent = import_string('apps.web.agent.models.Agent')
  186. app = Agent.get_inhouse_wechat_user_manager_app()
  187. return WechatClientProxy(app)
  188. def get_wechat_mini_env_pay_gateway(source, role = None, pay_app_type = None):
  189. # type:(SourceT, str, str)->WechatMiniPaymentGatewayT
  190. app = get_app(source = source,
  191. app_type = APP_TYPE.WECHAT_MINI_ENV_PAY,
  192. role = role,
  193. pay_app_type = pay_app_type) # type: WechatAPP_T
  194. return app.new_gateway(AppPlatformType.WECHAT_MINI)
  195. def get_wechat_env_pay_gateway(source, role = None, pay_app_type = None, vistor = AgentCustomizedBrandVisitor):
  196. app = get_app(source = source,
  197. app_type = APP_TYPE.WECHAT_ENV_PAY,
  198. role = role,
  199. vistor = vistor,
  200. pay_app_type = pay_app_type) # type: Optional[WechatPayApp]
  201. return app.new_gateway(AppPlatformType.WECHAT)
  202. def get_alipay_env_pay_gateway(source, role = None, pay_app_type = None, vistor = AgentCustomizedBrandVisitor):
  203. app = get_app(source = source,
  204. app_type = APP_TYPE.ALIPAY_ENV_PAY,
  205. role = role,
  206. vistor = vistor,
  207. pay_app_type = pay_app_type) # type: Optional[AliApp]
  208. return app.new_gateway(AppPlatformType.ALIPAY)
  209. def get_inhourse_wechat_env_pay_gateway(role = None, pay_app_type = None):
  210. """
  211. 使用平台商户进行支付. 例如SIM卡充值, API充值以及清静计划充值等
  212. 都在在微信环境在进行支付
  213. :param role:
  214. :param pay_app_type:
  215. :return:
  216. """
  217. Agent = import_string('apps.web.agent.models.Agent')
  218. inhouse_agent = Agent.get_inhouse_prime_agent() # type: Agent
  219. app = get_app(source = inhouse_agent,
  220. app_type = APP_TYPE.WECHAT_ENV_PAY,
  221. role = role,
  222. pay_app_type = pay_app_type) # type: Optional[WechatPayApp]
  223. return app.new_gateway(AppPlatformType.WECHAT)
  224. def get_platform_promotion_pay_gateway(pay_app_type):
  225. """
  226. 平台推广支付网关. 包括红包支付等, 提现广告记录在平台
  227. :param pay_app_type:
  228. :return:
  229. """
  230. from apps.web.core.models import PlatformPromotionApp
  231. return PlatformPromotionApp.get_app().new_gateway(pay_app_type)
  232. def get_platform_wallet_pay_gateway(pay_app_type):
  233. """
  234. 平台钱包支持. SIM卡自动充值, 代理商分成提现记录在平台
  235. :param pay_app_type:
  236. :return:
  237. """
  238. from apps.web.core.models import PlatformWalletApp
  239. return PlatformWalletApp.get_app().new_gateway(pay_app_type)
  240. def get_platform_reconcile_pay_gateway():
  241. """
  242. 平台对账支付网关. 用于账务错误给客户分账
  243. :return:
  244. """
  245. from apps.web.core.models import PlatformPromotionApp
  246. return PlatformPromotionApp.get_app().new_gateway(AppPlatformType.PLATFORM)
  247. def get_manual_pay_gateway(dealer):
  248. my_app = ManualPayApp.get_null_app()
  249. my_app.occupantId = str(dealer.id)
  250. my_app.occupant = dealer
  251. return my_app.new_gateway(AppPlatformType.PLATFORM)
  252. class PlatformPayGatewayUtil(object):
  253. @classmethod
  254. def get_ali_isv_pay_gateway(cls):
  255. app = AliApp.objects(appid = settings.ALI_ISV_APP_ID).first()
  256. return AliPayISVGateway(app)
  257. #############
  258. ### Misc ####
  259. #############
  260. def get_wx_config(user, url):
  261. # type:(Union[Dealer, Agent, MyUser, AnonymousUser], str)->Tuple[int, dict]
  262. try:
  263. if not user or is_anonymous(user):
  264. wechat_mp_proxy = get_inhouse_wechat_manager_mp_proxy()
  265. elif is_user(user):
  266. agent_id = str(user.agentId)
  267. Agent = import_string('apps.web.agent.models.Agent')
  268. agent = Agent.objects(id = agent_id).get()
  269. wechat_mp_proxy = get_wechat_user_manager_mp_proxy(agent)
  270. elif is_dealer(user) or is_agent(user):
  271. wechat_mp_proxy = get_wechat_manager_mp_proxy(user)
  272. else:
  273. wechat_mp_proxy = None
  274. if wechat_mp_proxy:
  275. value = wechat_mp_proxy.generate_js_auth_signature(url = url)
  276. logger.info('get wx config success. wxconfig = %s; proxy = %s' % (json.dumps(value), repr(wechat_mp_proxy)))
  277. else:
  278. value = {}
  279. logger.info('get wx config failure. auth bridge is null. user = %s' % repr(user))
  280. except Exception as e:
  281. value = {}
  282. logger.exception('get wx config failure. error = %s; user = %s' % (e, repr(user)))
  283. return value
  284. def current_platform(gateway_key, current):
  285. if gateway_key == current:
  286. return u'新平台'
  287. else:
  288. return u'老平台'
  289. DEVICE_LOCK_KEY = '{item}-operation-lock'
  290. def device_lock_key(item):
  291. # type:(str)->str
  292. return DEVICE_LOCK_KEY.format(item = item)
  293. START_DEVICE_LOCK_KEY = '{openId}-start-device-lock'
  294. def start_device_lock_key(openId):
  295. return START_DEVICE_LOCK_KEY.format(openId=openId)
  296. class ServerSwitch(object):
  297. # 拦截状态
  298. payment_blocking_status = ['pass', 'blocking', 'alipay', 'wechat']
  299. payment_Type = []
  300. white_list = ['o-VzzwAfpdglJY38Kj7yMvVWlIgw']
  301. @staticmethod
  302. def payment_switch(responseText):
  303. def warpper(func):
  304. @wraps(func)
  305. def inner(request, *args, **kwargs):
  306. status = ServerSwitch.check_payment_blocking_status(request)
  307. if status == True:
  308. logger.info('Blocking function:{}.{}()'.format(inner.__module__, inner.__name__))
  309. return JsonResponse({'result': 0, 'description': responseText, 'payload': {}})
  310. return func(request, *args, **kwargs)
  311. return inner
  312. return warpper
  313. @classmethod
  314. def check_payment_blocking_status(cls, request):
  315. result = False
  316. # 白名单获取
  317. white_list = serviceCache.get('adminWhiteList')
  318. if not white_list:
  319. white_list_obj = SystemSettings.objects.filter(key = 'adminWhiteList').first()
  320. if not white_list_obj:
  321. white_list = []
  322. serviceCache.set('adminWhiteList', white_list)
  323. else:
  324. white_list = white_list_obj.value
  325. serviceCache.set('adminWhiteList', white_list)
  326. if not serviceCache.get('paymentSwitch'):
  327. sys_setting = SystemSettings.objects.filter(key = 'paymentSwitch').first()
  328. if not sys_setting:
  329. logger.info('Can not get server settings,please touch mongodb')
  330. else:
  331. # 白名单(openid)
  332. if str(request.user.openId) in white_list:
  333. logger.info('user in white list user={}'.format(str(request.user.openId)))
  334. result = False
  335. # 全部拦截
  336. elif sys_setting.value == 'blocking':
  337. serviceCache.set('paymentSwitch', sys_setting.value)
  338. result = True
  339. # 拦截微信
  340. elif sys_setting.value == 'wechat':
  341. user_agent = request.META.get('HTTP_USER_AGENT')
  342. if 'MicroMessenger' in user_agent:
  343. serviceCache.set('paymentSwitch', sys_setting.value)
  344. result = True
  345. logger.info('Blocking wechat user request')
  346. # 拦截支付宝
  347. elif sys_setting.value == 'alipay':
  348. user_agent = request.META.get('HTTP_USER_AGENT')
  349. if 'Alipay' in user_agent:
  350. serviceCache.set('paymentSwitch', sys_setting.value)
  351. result = True
  352. logger.info('Blocking alipay user request')
  353. else:
  354. # 白名单(openid)
  355. if str(request.user.openId) in white_list:
  356. logger.info('user in white list user={}'.format(str(request.user.openId)))
  357. result = False
  358. elif serviceCache.get('paymentSwitch') == 'blocking':
  359. result = True
  360. elif serviceCache.get('paymentSwitch') == 'wechat':
  361. user_agent = request.META.get('HTTP_USER_AGENT')
  362. if 'MicroMessenger' in user_agent:
  363. result = True
  364. logger.info('Blocking wechat user request')
  365. elif serviceCache.get('paymentSwitch') == 'alipay':
  366. user_agent = request.META.get('HTTP_USER_AGENT')
  367. if 'Alipay' in user_agent:
  368. result = True
  369. logger.info('Blocking alipay user request')
  370. return result
  371. # 设置支付拦截状态
  372. @classmethod
  373. def set_payment_blocking_switch(cls, status = None):
  374. """
  375. status='pass':不拦截
  376. status='blocking':全部拦截
  377. status='wechat':拦截微信
  378. status='alipay':拦截支付宝
  379. """
  380. payment_blocking_status = ['pass', 'blocking', 'alipay', 'wechat']
  381. sys_setting = SystemSettings.objects.filter(key = 'paymentSwitch').first()
  382. if not sys_setting:
  383. logger.info('Can not get server settings,please touch mongodb')
  384. else:
  385. try:
  386. if not status:
  387. sys_setting.value = 'pass'
  388. sys_setting.save()
  389. serviceCache.delete('paymentSwitch')
  390. serviceCache.set('paymentSwitch', 'pass')
  391. logger.info('Set Payment blocking switch is fail ,status : pass')
  392. elif status not in payment_blocking_status:
  393. logger.info('That is not an option , status : ["pass", "blocking", "alipay", "wechat"]')
  394. else:
  395. sys_setting.value = status
  396. sys_setting.save()
  397. serviceCache.delete('paymentSwitch')
  398. serviceCache.set('paymentSwitch', status)
  399. logger.info('Payment blocking is running ,status : {}'.format(status))
  400. except Exception:
  401. logger.error('Set payment blocking switch is fail, try edit in mongodb')
  402. # 添加删除修改白名单
  403. @classmethod
  404. def edit_payment_while_list(cls, editType = 'add', openIds = []):
  405. white_list_obj = SystemSettings.objects.filter(key = 'adminWhiteList').first() or SystemSettings(
  406. key = 'adminWhiteList', value = [])
  407. white_list = white_list_obj.value
  408. if editType == 'add':
  409. white_list = white_list + openIds
  410. white_list_obj.value = list(set(white_list))
  411. white_list_obj.save()
  412. elif editType == 'update':
  413. white_list = openIds
  414. white_list_obj.value = list(set(white_list))
  415. white_list_obj.save()
  416. elif editType == 'delete':
  417. white_list = set(white_list) - set(openIds)
  418. white_list_obj.value = list(white_list)
  419. white_list_obj.save()
  420. if editType == 'clear':
  421. white_list_obj.delete()
  422. serviceCache.delete('adminWhiteList')
  423. serviceCache.set('adminWhiteList', white_list)
  424. def detect_browser(self, request, browser_name):
  425. user_agent = request.META.get('HTTP_USER_AGENT', 'unknown')
  426. return browser_name in user_agent
  427. detect_alipay_client = partial(detect_browser, browser_name = 'Alipay')
  428. detect_wechat_client = partial(detect_browser, browser_name = 'MicroMessenger')
  429. detect_union_client = partial(detect_browser, browser_name = 'Union')
  430. detect_jdpay_client = partial(detect_browser, browser_name = 'jdapp')
  431. detect_jdjr_client = partial(detect_browser, browser_name = 'JDJR')
  432. def remove_some_desc_for_consume(oldDesc, needRemove):
  433. vList = oldDesc.split(' ')
  434. try:
  435. sIndex = vList.index(needRemove)
  436. except Exception, e:
  437. return oldDesc
  438. vList[sIndex], vList[sIndex + 1], vList[sIndex + 2] = '', '', ''
  439. return ' '.join(vList)
  440. def copy_temp_document_classes(clazz, new_model_name):
  441. exclude = ['_fields', '_db_field_map', '_reverse_db_field_map', '_fields_ordered', '_is_document',
  442. 'MultipleObjectsReturned', '_superclasses', '_subclasses', '_types', '_class_name',
  443. '_meta', '__doc__', '__module__', '_collection', '_is_base_cls', '_auto_id_field', 'id',
  444. 'DoesNotExist', 'objects', '_cached_reference_fields']
  445. dicts = {'meta': deepcopy(clazz._origin_meta)}
  446. dicts['meta'].pop('indexes', None)
  447. dicts['meta']['index_background'] = True
  448. dicts['meta']['auto_create_index'] = False
  449. dicts['__module__'] = clazz.__module__
  450. new_cls = type(new_model_name, clazz.__bases__, dicts)
  451. for name, field in clazz.__dict__.iteritems():
  452. if name in exclude:
  453. continue
  454. else:
  455. field = getattr(clazz, name)
  456. if isinstance(field, BaseField):
  457. setattr(new_cls, name, field)
  458. else:
  459. if inspect.ismethod(field):
  460. if not field.im_self:
  461. setattr(new_cls, name, field.im_func)
  462. else:
  463. setattr(new_cls, name, classmethod(field.im_func))
  464. elif inspect.isfunction(field):
  465. setattr(new_cls, name, staticmethod(field))
  466. else:
  467. setattr(new_cls, name, field)
  468. return new_cls
  469. @contextlib.contextmanager
  470. def mongo_temp_table():
  471. tempModel = copy_temp_document_classes(
  472. MongoTempTable,
  473. '{}_{}'.format(MongoTempTable.__name__, str(uuid.uuid1())))
  474. yield tempModel
  475. try:
  476. tempModel.get_collection().drop()
  477. except Exception:
  478. pass