def __init__(self): self.application_title = get_avishan_config().OPENAPI_APPLICATION_TITLE self.application_description = get_avishan_config().OPENAPI_APPLICATION_DESCRIPTION self.application_version = get_avishan_config().OPENAPI_APPLICATION_VERSION self.application_servers = get_avishan_config().OPENAPI_APPLICATION_SERVERS self.project: Project = get_avishan_config().PROJECT self.models: List[DjangoAvishanModel] = sorted(self.project.models_pool(), key=lambda x: x.name)
def __init__(self, get_response): from avishan.configure import get_avishan_config self.get_response = get_response get_avishan_config().on_startup() """Run Descriptor to find any error in startup and store project""" from avishan.descriptor import Project self.project = Project(name=get_avishan_config().PROJECT_NAME) get_avishan_config().PROJECT = self.project
def load_apps(self) -> List['DjangoApplication']: from avishan.configure import get_avishan_config return [ DjangoApplication(project=self, name=app_name) for app_name in settings.INSTALLED_APPS if app_name not in get_avishan_config().descriptor_ignored_installed_apps() ]
def export(self) -> dict: if self.name: return { "$ref": f"#/components/schemas/{self.name}" } data = { 'type': self.type, 'description': "" } if self.type == 'integer': data['minimum'] = 1 data['maximum'] = 9223372036854775807 if self.format: data['format'] = self.format if self.default is not Attribute.NO_DEFAULT: data['default'] = self.default if self.description: data['description'] = self.description if self.items: data['items'] = self.items.export() if self.enum: enum = 'Enum: ' for item in self.enum: enum += f"`{item}`, " data['description'] = enum[:-2] + "." + data['description'] if len(data['description']) == 0: del data['description'] if len(self.properties) > 0: data['properties'] = {} data['required'] = [] for item in self.properties: if item.required: data['required'].append(item.name) data['properties'][item.name] = item.export() if not item.required: data['properties'][item.name]['nullable'] = True if len(data['required']) == 0: del data['required'] if self.type == 'string' and self.format == 'date-time': data['example'] = timezone.now().strftime(get_avishan_config().DATETIME_STRING_FORMAT) if self.type == 'string' and self.format == 'date': data['example'] = timezone.now().strftime(get_avishan_config().DATE_STRING_FORMAT) return data
def setup(self, request, *args, **kwargs): super().setup(request, *args, **kwargs) self.context = { **self.context, **{ 'CURRENT_REQUEST': request, 'AVISHAN_CONFIG': get_avishan_config(), 'self': self } }
def __init__(self, request: WSGIRequest): from avishan.views.class_based import AvishanView, AvishanTemplateView from avishan.models import BaseUser, UserGroup, UserUserGroup, EmailKeyValueAuthentication, \ PhoneKeyValueAuthentication, EmailOtpAuthentication, PhoneOtpAuthentication, VisitorKeyAuthentication, \ RequestTrack from avishan.descriptor import Project from avishan.configure import get_avishan_config from avishan.exceptions import AvishanException self.project: Optional[Project] = None self.request: WSGIRequest = request self.response: dict = {} self.parsed_data: Optional[dict] = None self.language: str = request.GET.get('language') or request.GET.get( 'lng') or get_avishan_config().LANGUAGE self.can_touch_response: bool = True self.is_tracked: bool = True self.add_token: bool = False self.is_api: Optional[bool] = None self.view_class: Optional[AvishanView] = None self.on_error_view_class: Optional[AvishanTemplateView] = None self.json_unsafe: bool = False self.token: Optional[str] = None self.decoded_token: Optional[dict] = None self.status_code: int = 200 self.context: dict = {} self.messages: dict = { 'debug': [], 'info': [], 'success': [], 'warning': [], 'error': [] } self.start_time: datetime.datetime = timezone.now() self.end_time: Optional[datetime.datetime] = None self.view_start_time: Optional[datetime.datetime] = None self.view_end_time: Optional[datetime.datetime] = None self.base_user: Optional[BaseUser] = None self.user_group: Optional[UserGroup] = None self.user_user_group: Optional[UserUserGroup] = None self.authentication_object: Optional[ Union[EmailKeyValueAuthentication, PhoneKeyValueAuthentication, EmailOtpAuthentication, PhoneOtpAuthentication, VisitorKeyAuthentication]] = None self.request_track_object: RequestTrack = RequestTrack() self.exception: Optional[AvishanException] = None self.traceback: Optional[str] = None self.debug: bool = False
def __init__(self, model: type, target_name: str, response_json_key: str, url: str = None, method: ApiMethod.METHOD = ApiMethod.METHOD.GET, authenticate: bool = True, hide_in_redoc: bool = False, is_class_method: bool = None, documentation: 'ApiDocumentation' = None): from avishan.configure import get_avishan_config from avishan.models import AvishanModel model: AvishanModel if url is None: auto_set_url = True url = f'/{target_name}' else: auto_set_url = False super().__init__(target=getattr(model, target_name), url='/' + get_avishan_config().AVISHAN_URLS_START + f'/{model.class_plural_snake_case_name()}' + url, method=method) self.model = model self.authenticate = authenticate self.hide_in_redoc = hide_in_redoc self.response_json_key = response_json_key if is_class_method is not None: self.is_class_method = is_class_method if not self.is_class_method and auto_set_url: self.url = '/' + get_avishan_config().AVISHAN_URLS_START + f'/{model.class_plural_snake_case_name()}/' \ + '{id}' + url self.documentation = documentation
def __str__(self): try: if get_current_request().avishan.language is None: lang = get_avishan_config().LANGUAGE else: lang = get_current_request().avishan.language if lang.upper() in self.__dict__.keys() and self.__dict__[ lang.upper()] is not None: return self.__dict__[lang.upper()] except: pass try: return list(self.__dict__.values())[0] except IndexError: return 'NOT_TRANSLATED_STRING'
def send_template_sms( phone: Phone, template_name: str, token: str, token2: str = None, token3: str = None, api_key: Optional[str] = get_avishan_config().KAVENEGAR_API_TOKEN): data = {'receptor': phone.key, 'template': template_name, 'token': token} if token2 is not None: data['token2'] = token2 if token3 is not None: data['token3'] = token3 response = requests.post( url=f"https://api.kavenegar.com/v1/{api_key}/verify/lookup.json", data=data) if response.status_code != 200: print(response.text)
def __init__(self): self.packs = [] for item in get_avishan_config().CHAYI_PROJECT_PACKAGE: self.packs.append([ item[0], f'package {item[1]}.models;\n\n' f'import {item[1]}.constants.Constants;\n' ]) self.files = {} self.tab_size = 0 for model in AvishanModel.get_models(): if model._meta.abstract or model.export_ignore: continue self.files[model.class_name() + ".java"] = self.model_file_creator(model) self.model_file_predefined_models(self.files) self.compress_files(self.packs, self.files)
def send_raw_sms( phone: Union[Phone, List[Phone]], text: str, api_key: Optional[str] = get_avishan_config().KAVENEGAR_API_TOKEN): receptor = "" if isinstance(phone, Phone): receptor = phone.key else: for item in phone: receptor += item.key + "," if len(phone) > 0: receptor = receptor[:-1] if len(receptor) == 0: raise ErrorMessageException(message=AvishanTranslatable( EN='Empty receptor numbers', FA='لیست دریافت کنندهها خالی است')) data = {'receptor': receptor, 'message': text} response = requests.post( url=f"https://api.kavenegar.com/v1/{api_key}/sms/send.json", data=data) if response.status_code != 200: print(response.text)
def _export_paths(self) -> dict: data = {} for model in self.models: if model.name in get_avishan_config().get_openapi_ignored_path_models(): continue for direct_callable in model.direct_callables: direct_callable: DirectCallable if direct_callable.hide_in_redoc or direct_callable.documentation is None: continue if direct_callable.url not in data.keys(): data[direct_callable.url] = Path(url=direct_callable.url) setattr(data[direct_callable.url], direct_callable.method.name.lower(), Operation( summary=direct_callable.documentation.title, description=direct_callable.documentation.description, request_body=Operation.extract_request_body_from_direct_callable(direct_callable), responses=Operation.extract_responses_from_direct_callable(direct_callable), tags=[stringcase.titlecase(model.name)] )) for key, value in data.items(): data[key] = value.export() return data
def distance_matrix(origins: List[Tuple[float, float]], destinations: List[Tuple[float, float]]) -> \ List[List[Tuple[float, float]]]: if len(origins) == 0 or len(destinations) == 0: raise ValueError('length of entered lists can\'t be 0') origins_text = '' for item in origins: origins_text += f'%7C{item[0]},{item[1]}' destinations_text = '' for item in destinations: destinations_text += f'%7C{item[0]},{item[1]}' url = f'https://api.neshan.org/v1/distance-matrix?' \ f'origins={origins_text[3:]}&destinations={destinations_text[3:]}' response = requests.get(url=url, headers={ 'Api-Key': get_avishan_config().NESHAN_API_KEY }).json() data = [] for row in response['rows']: data.append([(element['distance']['value'], element['duration']['value']) for element in row['elements']]) return data
def _remove_authenticate(cls) -> bool: from avishan.configure import get_avishan_config return get_avishan_config().CRUD_AUTHENTICATE.get(cls.class_name(), cls.DEFAULT_CRUD_DICT).get('remove', True)
def save_request_track(request: WSGIRequest): from avishan.configure import get_avishan_config # noinspection PyTypeHints request.avishan: AvishanRequestStorage from avishan.models import RequestTrackException for ignore in get_avishan_config().IGNORE_TRACKING_STARTS: if request.get_full_path().startswith(ignore) and \ request.avishan.request_track_object: request.avishan.request_track_object.delete() return request.avishan.end_time = timezone.now() authentication_type_class_title = "NOT_AVAILABLE" authentication_type_object_id = 0 if request.avishan.authentication_object: authentication_type_class_title = request.avishan.authentication_object.__class__.__name__ authentication_type_object_id = request.avishan.authentication_object.id request_data = "NOT_AVAILABLE" request_data_size = -1 if request.method in ['POST', 'PUT']: try: request_data = json.dumps(request.data, indent=2) request_data_size = sys.getsizeof(json.dumps(request.data)) except: print("*DEBUG* request parse error") request_headers = "" for key, value in request.META.items(): if key.startswith('HTTP_'): request_headers += f'{key[5:]}={value}\n' for key in request.FILES.keys(): request_headers += f'FILE({key})\n' from avishan.views.class_based import AvishanView if request.avishan.view_class: view_name = request.avishan.view_class.__class__.__name__ \ if isinstance(request.avishan.view_class, AvishanView) \ else request.avishan.view_class.__name__ else: view_name = None try: response_data = json.dumps(request.avishan.response, indent=2) except: print("*DEBUG* response parse error:", request.avishan.response) response_data = 'NOT_AVAILABLE' from avishan.models import UserUserGroup if request.avishan.user_user_group: try: uug = UserUserGroup.objects.get( id=request.avishan.user_user_group.id) except UserUserGroup.DoesNotExist: uug = None else: uug = None try: created = request.avishan.request_track_object.update( view_name=view_name, url=request.get_full_path(), status_code=request.avishan.status_code, method=request.method, json_unsafe=request.avishan.json_unsafe, is_api=request.avishan.is_api, add_token=request.avishan.add_token, user_user_group=uug, request_data=request_data, request_data_size=request_data_size, request_headers=request_headers, response_data=response_data, response_data_size=sys.getsizeof(response_data), start_time=request.avishan.start_time, end_time=request.avishan.end_time, total_execution_milliseconds=int( (request.avishan.end_time - request.avishan.start_time).total_seconds() * 1000), view_execution_milliseconds=int( (request.avishan.view_end_time - request.avishan.view_start_time).total_seconds() * 1000) if request.avishan.view_end_time else 0, authentication_type_class_title=authentication_type_class_title, authentication_type_object_id=authentication_type_object_id) if request.avishan.exception is not None: RequestTrackException.objects.create( request_track=created, class_title=request.avishan.exception.__class__.__name__, args=request.avishan.exception.args, traceback=request.avishan.traceback) except Exception as e: print('save_request_track_error:'.upper(), e)
def model_file_head_imports() -> str: return get_avishan_config().CHAYI_MODEL_FILE_IMPORTS
class AvishanFaker: _faker = Faker(locale=get_avishan_config().FAKER_LOCALE) Faker.seed(get_avishan_config().FAKER_SEED) @classmethod def fake_it(cls, **overriding): data = {} for key, value in cls.faker_get_create_params_dict().items(): if callable(getattr(cls, f'_{key}_fake', None)): data[key] = getattr(cls, f'_{key}_fake')() else: if key in overriding.keys(): if callable(overriding[key]): faking_method = overriding[key] else: faking_method = None else: faking_method = cls.faker_assign_faking_method(key, value) if not faking_method: data[key] = overriding[key] else: data[key] = faking_method() created = cls.faker_get_create_method()(**data) if not hasattr(cls, 'fakes'): cls.fakes = [] cls.fakes.append(created) return created @classmethod def fake_list(cls, count: int = 5, **overriding): return [cls.fake_it(**overriding) for _ in range(count)] @classmethod def faker_generate(cls, count: int = 5): if not hasattr(cls, 'fakes'): cls.fakes = [] cls.fake_list(count=count - len(cls.fakes)) return cls.fakes @classmethod def faker_get_create_params_dict(cls) -> Dict[str, Parameter]: return dict( inspect.signature( cls.faker_get_create_method()).parameters.items()) @classmethod def faker_get_create_method(cls) -> Callable: from avishan.models import AvishanModel cls: Union[AvishanFaker, AvishanModel] return cls.create @classmethod def faker_assign_faking_method(cls, key: str, value: Parameter) -> Callable: from avishan.models import AvishanModel if not isinstance(value, Parameter): raise ValueError( f'parameter {key} in class {cls.__name__} should have type hint to fake it.' ) if key == 'kwargs': raise ValueError(f'kwargs in class {cls.__name__} is not valid') if value.default is None: return lambda: None if isinstance(value.annotation, models.base.ModelBase): if issubclass(value.annotation, AvishanModel): return lambda: value.annotation.fake_it() raise NotImplementedError() try: return { bool: cls._bool_fake, str: cls._str_fake, int: cls._int_fake, float: cls._float_fake, datetime: cls._datetime_fake, date: cls._date_fake, time: cls._time_fake }[value.annotation] except KeyError: pass if isinstance(value.annotation.__args__[0], ForwardRef): list_of = AvishanModel.get_model_with_class_name( value.annotation.__args__[0].__forward_arg__) else: list_of = value.annotation.__args__[0] return lambda: list_of.fake_list() @classmethod def _bool_fake(cls) -> bool: return cls._faker.pybool() @classmethod def _str_fake(cls) -> str: return " ".join(cls._faker.words(8)) @classmethod def _int_fake(cls) -> int: return cls._faker.pyint(min_value=0, max_value=100000) @classmethod def _float_fake(cls, left_digits: Optional[int] = 2, right_digits: Optional[int] = 2, positive: Optional[bool] = True, min_value: Optional[float] = 0, max_value: Optional[float] = None) -> float: return cls._faker.pyfloat(left_digits=left_digits, right_digits=right_digits, positive=positive, min_value=min_value, max_value=max_value) @classmethod def _datetime_fake(cls) -> datetime: return cls._faker.date_time() @classmethod def _date_fake(cls) -> date: return cls._faker.date_object() @classmethod def _time_fake(cls) -> time: return cls._faker.time_object()
from requests import post, Response from avishan.configure import get_avishan_config FIREBASE_SERVER_TOKEN = get_avishan_config().FIREBASE_SERVER_TOKEN def send_firebase_data_message( data: dict, to_key: str, server_key: str = FIREBASE_SERVER_TOKEN) -> Response: return post(url='https://fcm.googleapis.com/fcm/send', json={ "data": data, 'to': to_key, "android": { "priority": "high" }, }, headers={'Authorization': f'key={server_key}'}) def send_firebase_notification(title: str, body: str, to_key: str, server_key: str = FIREBASE_SERVER_TOKEN): return post(url='https://fcm.googleapis.com/fcm/send', json={ "notification": { "title": title, "body": body },
def get_app_names() -> List[str]: from django.apps import apps from avishan.configure import get_avishan_config return [key.name for key in apps.get_app_configs() if key.name in get_avishan_config().MONITORED_APPS_NAMES]
def __call__(self, request: WSGIRequest): from avishan.utils import discard_monitor, find_token, decode_token, add_token_to_response, find_and_check_user from avishan.exceptions import AvishanException from avishan.exceptions import save_traceback from avishan.configure import get_avishan_config request.avishan = AvishanRequestStorage(request) request.avishan.project = self.project """Checks for avoid-touch requests""" if discard_monitor(request.get_full_path()): print(f"NOT_MONITORED: {request.get_full_path()}") response = self.get_response(request) if 'token' in request.COOKIES.keys(): response.set_cookie('token', request.COOKIES['token']) del request.avishan return response """Find token and parse it""" """ Bara inke yadam nare. tooye sathe middleware vaghti error midim, chon nemidoonim api e ya template, error ro zakhire mikonim mirim decorator, baad oonja k set shod in meghdar, check mikonim chon error hast, barmigarde inja """ try: if find_token(): decode_token() find_and_check_user() except AvishanException: pass except Exception as e: save_traceback() AvishanException(e) get_avishan_config().on_request(request) # todo 0.2.2 check for 'avishan_' in request bodies """Send request object to the next layer and wait for response""" try: response = self.get_response(request) if not request.avishan.can_touch_response: del request.avishan return response except AvishanException: pass except Exception as e: save_traceback() AvishanException(e) remove_from_crum = False if get_current_request() is None: remove_from_crum = True set_current_request(request) """messages""" if request.avishan.have_message(): # todo 0.2.3: check for debug=True if request.avishan.is_api: request.avishan.response['messages'] = request.avishan.messages else: # noinspection PyTypeChecker self.fill_messages_framework(request) if request.avishan.on_error_view_class and response.status_code == 500: response = request.avishan.on_error_view_class.render() # todo fix problem on template: not showing thrown exception message add_token_to_response(response) status_code = request.avishan.status_code is_api = request.avishan.is_api json_safe = not request.avishan.json_unsafe if is_api: response = request.avishan.response.copy() if request.avishan.is_tracked or request.avishan.exception is not None: self.save_request_track(request) del request.avishan if remove_from_crum: set_current_request(None) if is_api: return JsonResponse(response, status=status_code, safe=json_safe) """Do not change redirection status codes""" if response.status_code // 100 != 3: response.status_code = status_code return response