Coverage for model/utils/request.py: 100%

50 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2024-11-05 04:22 +0000

1import time 

2import json 

3from functools import wraps 

4from flask import request, current_app 

5from mongo import engine 

6from mongo.utils import doc_required 

7from .response import * 

8 

9__all__ = ( 

10 'Request', 

11 'get_ip', 

12) 

13 

14type_map = { 

15 'int': int, 

16 'list': list, 

17 'str': str, 

18 'dict': dict, 

19 'bool': bool, 

20 'None': type(None) 

21} 

22 

23 

24class _Request(type): 

25 

26 def __getattr__(self, content_type): 

27 

28 def get(*keys, vars_dict={}): 

29 

30 def data_func(func): 

31 

32 @wraps(func) 

33 def wrapper(*args, **kwargs): 

34 data = getattr(request, content_type) 

35 if data == None: 

36 # FIXME: This exception doesn't mean the content type is wrong 

37 return HTTPError( 

38 f'Unaccepted Content-Type {content_type}', 415) 

39 try: 

40 # Magic 

41 # yapf: disable 

42 kwargs.update({ 

43 k: (lambda v: v 

44 if t is None or type(v) is t else int(''))( 

45 data.get((lambda s, *t: s + ''.join( 

46 map(str.capitalize, t)) 

47 )(*filter(bool, k.split('_'))))) 

48 for k, t in map( 

49 lambda x: 

50 (x[0], (x[1:] or None) and type_map.get(x[1].strip())), 

51 map(lambda q: q.split(':', 1), keys)) 

52 }) 

53 # yapf: enable 

54 except ValueError as ve: 

55 return HTTPError('Requested Value With Wrong Type', 

56 400) 

57 kwargs.update( 

58 {v: data.get(vars_dict[v]) 

59 for v in vars_dict}) 

60 return func(*args, **kwargs) 

61 

62 return wrapper 

63 

64 return data_func 

65 

66 return get 

67 

68 

69class Request(metaclass=_Request): 

70 

71 @staticmethod 

72 def doc(src, des, cls=None, src_none_allowed=False): 

73 ''' 

74 a warpper to `doc_required` for flask route 

75 ''' 

76 

77 def deco(func): 

78 

79 @doc_required(src, des, cls, src_none_allowed) 

80 def inner_wrapper(*args, **ks): 

81 return func(*args, **ks) 

82 

83 @wraps(func) 

84 def real_wrapper(*args, **ks): 

85 try: 

86 return inner_wrapper(*args, **ks) 

87 # if document not exists in db 

88 except engine.DoesNotExist as e: 

89 return HTTPError(str(e), 404) 

90 # if args missing 

91 except TypeError as e: 

92 return HTTPError(str(e), 500) 

93 except engine.ValidationError as e: 

94 current_app.logger.info( 

95 f'Validation error [err={e.to_dict()}]') 

96 return HTTPError('Invalid parameter', 400) 

97 

98 return real_wrapper 

99 

100 return deco 

101 

102 

103def get_ip() -> str: 

104 ip = request.headers.get('X-Forwarded-For', '').split(',')[-1].strip() 

105 return ip