def parse(self, stream, media_type=None, parser_context=None): """ Parses the incoming bytestream as a multipart encoded form, and returns a DataAndFiles object. `.data` will be a `QueryDict` containing all the form parameters. `.files` will be a `QueryDict` containing all the form files. """ parser_context = parser_context or {} request = parser_context["request"] encoding = parser_context.get("encoding", settings.DEFAULT_CHARSET) meta = request.META.copy() meta["CONTENT_TYPE"] = media_type upload_handlers = request.upload_handlers try: parser = DjangoMultiPartParser(meta, stream, upload_handlers, encoding) data, files = parser.parse() return DataAndFiles( underscoreize(data, **api_settings.JSON_UNDERSCOREIZE), underscoreize(files, **api_settings.JSON_UNDERSCOREIZE), ) except MultiPartParserError as exc: raise ParseError("Multipart form parse error - %s" % str(exc))
def test_under_to_camel_input_untouched_for_sequence(self): data = [ {'first_input': 1}, {'second_input': 2}, ] reference_input = deepcopy(data) underscoreize(data) self.assertEqual(data, reference_input)
def get_body_in_request(request): if not request.body: raise HttpException(detail=Errors.BAD_REQUEST.name, status_code=Errors.BAD_REQUEST) try: data = json.loads(request.body.decode('utf-8')) return underscoreize(data) except JSONDecodeError: data = request.POST return underscoreize(data)
def parse(self, stream, media_type=None, parser_context=None): data_and_files = super(CamelCaseMultiPartParser, self).parse(stream, media_type=media_type, parser_context=parser_context) data_and_files.data = underscoreize(data_and_files.data) data_and_files.files = underscoreize(data_and_files.files) return data_and_files
def test_participant_details(self): """ Participant details are public. """ participants_count = randint(1, 10) ParticipantFactory.create_batch(participants_count) participant = ParticipantFactory() # Actions actions_count = randint(1, 10) ParticipantActionFactory.create_batch(actions_count, participant=participant) # Profile Entries profile_entries_count = randint(1, 10) profile_entries = ProfileEntryFactory.create_batch( profile_entries_count) participant.profile.add(*profile_entries) participant.save() url = reverse('api:participant-detail', args=[participant.id]) response = self.admin_client.get(url) serialized = ParticipantSerializer( Participant.objects.get(pk=participant.id)) self.assertEqual(status.HTTP_200_OK, response.status_code) self.assertEqual(serialized.data, underscoreize(response.data)) self.assertEqual(actions_count, len(response.data.get('actions'))) self.assertEqual(profile_entries_count, len(response.data.get('profile')))
def test_camel_to_under_keys(self): data = { "twoWord": 1, "longKeyWithManyUnderscores": 2, "only1Key": 3, "onlyOneLetterA": 4, "bOnlyOneLetter": 5, "onlyCLetter": 6, "mix123123aAndLetters": 7, "mix123123aaAndLettersComplex": 8, "wordWITHCaps": 9, "key10": 10, "anotherKey1": 11, "anotherKey10": 12, "optionS1": 13, "optionS10": 14, } output = { "two_word": 1, "long_key_with_many_underscores": 2, "only_1_key": 3, "only_one_letter_a": 4, "b_only_one_letter": 5, "only_c_letter": 6, "mix_123123a_and_letters": 7, "mix_123123aa_and_letters_complex": 8, "word_with_caps": 9, "key_10": 10, "another_key_1": 11, "another_key_10": 12, "option_s_1": 13, "option_s_10": 14, } self.assertEqual(underscoreize(data), output)
def test_get_thread_details(self): """ Thread details are public. """ email_1 = EmailFactory() email_1.replies.add(EmailReplyFactory()) email_1.replies.add(EmailReplyFactory()) email_1.attachments.add(ExerciseFileFactory()) # This is how the email becomes a thread (for now...) email_1.belongs_to = email_1 email_1.save() # add some emails to email_1 to make it a thread email_count = randint(1, 15) emails = EmailFactory.create_batch(email_count) for email in emails: email.belongs_to = email_1 email.save() url = reverse('api:thread-detail', args=[email_1.id]) response = self.client.get(url) serialized = ThreadSerializer(ExerciseEmail.objects.get(pk=email_1.id)) self.assertEqual(status.HTTP_200_OK, response.status_code) self.assertEqual(serialized.data, underscoreize(response.data)) # +1 because itself will be listed in emails too self.assertEqual(email_count + 1, len(response.data.get('emails'))) self.assertEqual(2, len(response.data.get('replies'))) self.assertEqual(1, len(response.data.get('attachments')))
def parse(self, stream, media_type=None, parser_context=None): data = super(CamelCaseJSONParser, self).parse(stream, media_type=media_type, parser_context=parser_context) return underscoreize(data)
def test_recursive_with_ignored_keys(self): ignore_fields = ("ignore_me", "newKey") data = { "ignoreMe": { "noChangeRecursive": 1 }, "changeMe": { "changeRecursive": 2 }, "newKey": { "alsoNoChange": 3 }, } output = { "ignore_me": { "noChangeRecursive": 1 }, "change_me": { "change_recursive": 2 }, "new_key": { "alsoNoChange": 3 }, } self.assertEqual(underscoreize(data, ignore_fields=ignore_fields), output)
def test_compatibility(self): input = { "title_display": 1, "a_list": [1, "two_three", {"three_four": 5}], "a_tuple": ("one_two", 3) } self.assertEqual(underscoreize(camelize(input)), input)
def test_thread_list_allow_admin(self): """ Admin users should be able to retrieve thread list. """ url = reverse('api:thread-list') email_count = randint(3, 50) emails = EmailFactory.create_batch(email_count) self.threadify(emails[0]) self.threadify(emails[1]) email_1 = emails[2] email_1.replies.add(EmailReplyFactory()) email_1.attachments.add(ExerciseFileFactory()) email_1.belongs_to = emails[0] email_1.save() response = self.admin_client.get(url) serialized = ThreadSerializer( ExerciseEmail.objects.filter(pk=F('belongs_to')), many=True) self.assertEqual(status.HTTP_200_OK, response.status_code) # There should be only 2 threads self.assertEqual(2, len(response.data)) self.assertEqual(serialized.data, underscoreize(response.data))
def test_get_exercise_details(self): """ Exercise details are public. """ ExerciseFactory.create_batch(5) exercise_1 = ExerciseFactory() # add emails email_count = randint(2, 15) emails = EmailFactory.create_batch(email_count) self.threadify(emails[0]) self.threadify(emails[1]) exercise_1.emails.add(*emails) # add files file_count = randint(1, 10) files = ExerciseFileFactory.create_batch(file_count) exercise_1.files.add(*files) exercise_1.save() url = reverse('api:exercise-detail', args=[exercise_1.id]) response = self.client.get(url) serialized = ExerciseSerializer(Exercise.objects.get(pk=exercise_1.id)) self.assertEqual(status.HTTP_200_OK, response.status_code) self.assertEqual(2, len(response.data.get('threads'))) self.assertEqual(file_count, len(response.data.get('files'))) self.assertEqual(serialized.data, underscoreize(response.data))
def test_underscoreize_iterates_over_generator(self): data = self._camel_generator() output = [ {'simple_is_better': 'than complex'}, {'that_is': 'correct'}, ] self.assertEqual(underscoreize(data), output)
def fetch_object(url: str, do_underscoreize=True) -> dict: from vng_api_common.models import APICredential client_auth = APICredential.get_auth(url) headers = client_auth.credentials() if client_auth else {} try: response = requests.get(url, headers=headers) except requests.exceptions.RequestException as exc: raise FetchError(exc.args[0]) from exc try: response.raise_for_status() except requests.HTTPError as exc: raise FetchError(exc.args[0]) from exc try: data = response.json() except json.JSONDecodeError as exc: raise FetchJsonError(exc.args[0]) from exc if not do_underscoreize: return data return underscoreize(data)
def fetch_object(url: str, do_underscoreize=True) -> dict: from zgw_consumers.models import Service # TODO should we replace it with Service.get_client() and use it instead of requests? # but in this case we couldn't catch separate FetchJsonError client_auth_header = Service.get_auth_header(url) headers = client_auth_header or {} try: response = requests.get(url, headers=headers) except requests.exceptions.RequestException as exc: raise FetchError(exc.args[0]) from exc try: response.raise_for_status() except requests.HTTPError as exc: raise FetchError(exc.args[0]) from exc try: data = response.json() except json.JSONDecodeError as exc: raise FetchJsonError(exc.args[0]) from exc if not do_underscoreize: return data return underscoreize(data)
def test_camel_to_under_keys(self): query_dict = QueryDict("testList=1&testList=2", mutable=True) data = { "twoWord": 1, "longKeyWithManyUnderscores": 2, "only1Key": 3, "onlyOneLetterA": 4, "bOnlyOneLetter": 5, "onlyCLetter": 6, "mix123123aAndLetters": 7, } query_dict.update(data) output_query = QueryDict("test_list=1&test_list=2", mutable=True) output = { "two_word": 1, "long_key_with_many_underscores": 2, "only_1_key": 3, "only_one_letter_a": 4, "b_only_one_letter": 5, "only_c_letter": 6, "mix_123123a_and_letters": 7, } output_query.update(output) self.assertEqual(underscoreize(query_dict), output_query)
def test_get(self): """Test GET request to 'character' api'""" game1 = Game.objects.create(**create_game_mock(name='Game 1')) game2 = Game.objects.create(**create_game_mock(name='Game 2')) games = [game1, game2] for count in range(0, 4): def assertions_cb(character, data): self._assert_character_props(character, data) self._assert_created_character_nested_props(character, data) self._test_post( assertions_cb, name='test_' + str(count), count=count, game= games[count % 2].id, ) grouped_collection = underscoreize(self._get().data) self.assertEqual(grouped_collection[0]['game_name'], 'Game 1') self.assertEqual(grouped_collection[0]['game_id'], game1.id) self.assertEqual(grouped_collection[0]['characters'][0]['name'], 'test_0') self.assertEqual(grouped_collection[0]['characters'][1]['name'], 'test_2') self.assertEqual(grouped_collection[1]['game_name'], 'Game 2') self.assertEqual(grouped_collection[1]['game_id'], game2.id) self.assertEqual(grouped_collection[1]['characters'][0]['name'], 'test_1') self.assertEqual(grouped_collection[1]['characters'][1]['name'], 'test_3')
def test_under_to_camel(self): input = { "titleDisplay": 1 } output = { "title_display": 1 } self.assertEqual(underscoreize(input), output)
def __call__(self, request): request.GET = underscoreize( request.GET, **api_settings.JSON_UNDERSCOREIZE ) response = self.get_response(request) return response
def parse(self, stream, media_type=None, parser_context=None): parser_context = parser_context or {} encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) try: data = stream.read().decode(encoding) return underscoreize(json.loads(data)) except ValueError as exc: raise ParseError('JSON parse error - %s' % six.text_type(exc))
def test_compatibility(self): input = { "title_display": 1, "a_list": [1, "two_three", { "three_four": 5 }], "a_tuple": ("one_two", 3) } self.assertEqual(underscoreize(camelize(input)), input)
def parse(self, stream, media_type=None, parser_context=None): parser_context = parser_context or {} encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) try: data = stream.read().decode(encoding) return underscoreize(json.loads(data)) except ValueError as exc: raise ParseError('JSON parse error - %s' % six.text_type(exc))
def load_from_disk(cls, job_id: str) -> Job: jobdir = os.path.join(django.conf.settings.DESIGN_OUTPUT_FOLDER, job_id) with open(os.path.join(jobdir, 'summary.json')) as f: data = underscoreize(json.load(f), ignore_fields=('pegRNAs', 'cloning_options', 'nuclease_options')) data['organism'] = Organism.objects.get(pk=data['organism']['id']) for s in data['summary']: s['pegRNAs'] = s.pop('peg_rn_as') job = cls(**data, output_folder=django.conf.settings.DESIGN_OUTPUT_FOLDER) return job
def test_camel_to_under_dict(self): input = { "titleDisplay": 1 } output = { "title_display": 1 } result = underscoreize(input) self.assertEqual(result, output) self.assertIsNot(result, input, "should not change original dict")
def test_camel_to_under_tuple(self): input = [ {"titleDisplay": 1} ] output = [ {"title_display": 1} ] result = underscoreize(input) self.assertEqual(result, output) self.assertIsNot(result, input, "should not change original tuple")
def _request_auth(self) -> list: client = AuthorizationsConfig.get_client() try: response = client.list('applicatie', query_params={'client_ids': self.client_id}) except ClientError: logger.warn("Authorization component can't be accessed") return [] return underscoreize(response['results'])
def parse(self, stream, media_type=None, parser_context=None): parser_context = parser_context or {} encoding = parser_context.get("encoding", settings.DEFAULT_CHARSET) try: data = stream.read().decode(encoding) return underscoreize(json.loads(data), **api_settings.JSON_UNDERSCOREIZE) except ValueError as exc: raise ParseError("JSON parse error - %s" % str(exc))
def results(self): for i, edit in enumerate(self.edits): try: with open(os.path.join(self.jobdir, f'edit{i}.json')) as f: data = json.load(f) primers = data.pop('primers') data = underscoreize(data) data['pegRNAs'] = data.pop('peg_rn_as') data['primers'] = primers yield data except FileNotFoundError: break
def parse(cls, request): from django.http.request import QueryDict tmp = QueryDict('', mutable=True) data = underscoreize(dict(request.GET)) for k, v in data.items(): if k in cls.parsing_values: if isinstance(v, str): v = camel_to_underscore(v) elif isinstance(v, list): v = [(camel_to_underscore(v_) if isinstance(v_, str) else v_) for v_ in v] tmp.setlistdefault(k, v) return tmp
def test_camel_to_under_nested(self): input = { "titleDisplay": 1, "aList": [1, "two_three", {"threeFour": 5}], "aTuple": ("one_two", 3) } output = { "title_display": 1, "a_list": [1, "two_three", {"three_four": 5}], "a_tuple": ("one_two", 3) } self.assertEqual(underscoreize(input), output)
def _transform_query_params(self, view, query_params: QueryDict) -> QueryDict: if not self._is_camel_case(view): return query_params # data can be a regular dict if it's coming from a serializer if hasattr(query_params, "lists"): data = dict(query_params.lists()) else: data = query_params transformed = underscoreize(data) return QueryDict(urlencode(transformed, doseq=True))
def input_validation( loader_class, # noqa: TYP001 serializer, # noqa: TYP001 method: str, route: str, camel_case_parser: bool, **kwargs, ) -> None: """ Verifies that an OpenAPI schema request body definition is valid, according to the API view's input serializer. :param loader_class: Class containing a `get_request_body` method :param serializer: Serializer class used for input validation in your API view :param method: HTTP method ('get', 'put', 'post', ...) :param route: Relative path of the endpoint being tested :param camel_case_parser: True if request body should be camel cased - this is usually required when you're using djangorestframework-camel-case parses for your APIs. :raises: django_swagger_tester.exceptions.SwaggerDocumentationError or django_swagger_tester.exceptions.CaseError """ loader = loader_class(route=route, method=method, **kwargs) endpoint_schema = loader.get_request_body() request_body_schema = get_request_body_schema(endpoint_schema) if 'example' in request_body_schema: # Find a ready dict object # This happens when you use your Serializer as the request body parameter in drf_yasg auto schemas example = request_body_schema['example'] else: # Parses schema bit by bit # This happens if you use static schemas or document your request body using Schema objects in drf_yasg example = serialize_schema(request_body_schema) # Make camelCased input snake_cased so the serializer can read it if camel_case_parser: from djangorestframework_camel_case.util import underscoreize example = underscoreize(example) logger.debug('Validating example: %s', example) serializer = serializer(data=example) # type: ignore if not serializer.is_valid(): logger.info('Example was invalid') raise SwaggerDocumentationError( f'Request body is not valid according to the passed serializer.' f'\n\nSwagger example request body: \n\n\t{json.dumps(example)}' f'\n\nSerializer error:\n\n\t{json.dumps(serializer.errors)}\n\n' f'Note: If all your parameters are correct, you might need to change `camel_case_parser` to True or False.' ) # Check the example's case for inconsistencies SchemaCaseTester(request_body_schema, **kwargs)
def get_request(access_token, url, client_id, client_secret, wait_for_retry=False): """ To make an API call Handles if the token is expired. :param access_token: :param url: :param client_id: :param client_secret: :param wait_for_retry: :return: """ r = requests.get(url, headers=APICall.get_headers(access_token)) if r.status_code == 200: # Camel to snake case converter response_data = underscoreize(r.json()) return access_token, response_data, 0 elif r.status_code == 401: # Token is expired # Get a new access_token and try again new_access_token = APICall.get_access_token( client_id, client_secret) return APICall.get_request(new_access_token, url, client_id, client_secret) elif r.status_code == 429: if wait_for_retry: # sleep if wait_for_retry is explicitly specified time.sleep(int(r.headers['retry-after'])) return APICall.get_request(access_token, url, client_id, client_secret) return access_token, None, int(r.headers['retry-after']) else: # unknown status_code, raise exception print(r.status_code) raise Exception
def test_exercise_list_allow_admin(self): """ Admin users should be able to retrieve the exercise list. """ url = reverse('api:exercise-list') exercises_count = randint(1, 50) ExerciseFactory.create_batch(exercises_count) response = self.admin_client.get(url) serialized = ExerciseSerializer(Exercise.objects.all(), many=True) self.assertEqual(status.HTTP_200_OK, response.status_code) self.assertEqual(exercises_count, len(response.data)) self.assertEqual(serialized.data, underscoreize(response.data))
def test_participant_list_allow_admin(self): """ Admin users should be able to retrieve thread list. """ url = reverse('api:participant-list') participant_count = randint(1, 50) ParticipantFactory.create_batch(participant_count) response = self.admin_client.get(url) serialized = ParticipantSerializer(Participant.objects.all(), many=True) self.assertEqual(status.HTTP_200_OK, response.status_code) self.assertEqual(participant_count, len(response.data)) self.assertEqual(serialized.data, underscoreize(response.data))
def test_email_list_allow_admin(self): """ Admin users should be able to retrieve the email list. """ url = reverse("api:email-list") email_count = 3 EmailFactory.create_batch(email_count) response = self.admin_client.get(url) serialized = ExerciseEmailSerializer(ExerciseEmail.objects.all(), many=True) self.assertEqual(status.HTTP_200_OK, response.status_code) self.assertEqual(email_count, len(response.data)) self.assertEqual(serialized.data, underscoreize(response.data))
def test_compatibility(self): input = { "title_245a_display": 1 } self.assertEqual(underscoreize(camelize(input)), input)