How to use parsed method in fMBT

Best Python code snippet using fMBT_python

test_parsers.py

Source:test_parsers.py Github

copy

Full Screen

1# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.2#3# Licensed under the Apache License, Version 2.0 (the "License"). You4# may not use this file except in compliance with the License. A copy of5# the License is located at6#7# http://aws.amazon.com/apache2.0/8#9# or in the "license" file accompanying this file. This file is10# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF11# ANY KIND, either express or implied. See the License for the specific12# language governing permissions and limitations under the License.13import datetime14import itertools15import pytest16from dateutil.tz import tzutc17from botocore import model, parsers18from botocore.compat import MutableMapping, json19from tests import RawResponse, unittest20# HTTP responses will typically return a custom HTTP21# dict. We want to ensure we're able to work with any22# kind of mutable mapping implementation.23class CustomHeaderDict(MutableMapping):24 def __init__(self, original_dict):25 self._d = original_dict26 def __getitem__(self, item):27 return self._d[item]28 def __setitem__(self, item, value):29 self._d[item] = value30 def __delitem__(self, item):31 del self._d[item]32 def __iter__(self):33 return iter(self._d)34 def __len__(self):35 return len(self._d)36# These tests contain botocore specific tests that either37# don't make sense in the protocol tests or haven't been added38# yet.39class TestResponseMetadataParsed(unittest.TestCase):40 def test_response_metadata_parsed_for_query_service(self):41 parser = parsers.QueryParser()42 response = (43 b'<OperationNameResponse>'44 b' <OperationNameResult><Str>myname</Str></OperationNameResult>'45 b' <ResponseMetadata>'46 b' <RequestId>request-id</RequestId>'47 b' </ResponseMetadata>'48 b'</OperationNameResponse>'49 )50 output_shape = model.StructureShape(51 'OutputShape',52 {53 'type': 'structure',54 'resultWrapper': 'OperationNameResult',55 'members': {56 'Str': {57 'shape': 'StringType',58 },59 'Num': {60 'shape': 'IntegerType',61 },62 },63 },64 model.ShapeResolver(65 {66 'StringType': {67 'type': 'string',68 },69 'IntegerType': {70 'type': 'integer',71 },72 }73 ),74 )75 parsed = parser.parse(76 {'body': response, 'headers': {}, 'status_code': 200}, output_shape77 )78 self.assertEqual(79 parsed,80 {81 'Str': 'myname',82 'ResponseMetadata': {83 'RequestId': 'request-id',84 'HTTPStatusCode': 200,85 'HTTPHeaders': {},86 },87 },88 )89 def test_metadata_always_exists_for_query(self):90 # ResponseMetadata is used for more than just the request id. It91 # should always get populated, even if the request doesn't seem to92 # have an id.93 parser = parsers.QueryParser()94 response = (95 b'<OperationNameResponse>'96 b' <OperationNameResult><Str>myname</Str></OperationNameResult>'97 b'</OperationNameResponse>'98 )99 output_shape = model.StructureShape(100 'OutputShape',101 {102 'type': 'structure',103 'resultWrapper': 'OperationNameResult',104 'members': {105 'Str': {106 'shape': 'StringType',107 },108 'Num': {109 'shape': 'IntegerType',110 },111 },112 },113 model.ShapeResolver(114 {115 'StringType': {116 'type': 'string',117 },118 'IntegerType': {119 'type': 'integer',120 },121 }122 ),123 )124 parsed = parser.parse(125 {'body': response, 'headers': {}, 'status_code': 200}, output_shape126 )127 expected = {128 'Str': 'myname',129 'ResponseMetadata': {'HTTPStatusCode': 200, 'HTTPHeaders': {}},130 }131 self.assertEqual(parsed, expected)132 def test_response_metadata_parsed_for_ec2(self):133 parser = parsers.EC2QueryParser()134 response = (135 b'<OperationNameResponse>'136 b' <Str>myname</Str>'137 b' <requestId>request-id</requestId>'138 b'</OperationNameResponse>'139 )140 output_shape = model.StructureShape(141 'OutputShape',142 {143 'type': 'structure',144 'members': {145 'Str': {146 'shape': 'StringType',147 }148 },149 },150 model.ShapeResolver({'StringType': {'type': 'string'}}),151 )152 parsed = parser.parse(153 {'headers': {}, 'body': response, 'status_code': 200}, output_shape154 )155 # Note that the response metadata is normalized to match the query156 # protocol, even though this is not how it appears in the output.157 self.assertEqual(158 parsed,159 {160 'Str': 'myname',161 'ResponseMetadata': {162 'RequestId': 'request-id',163 'HTTPStatusCode': 200,164 'HTTPHeaders': {},165 },166 },167 )168 def test_metadata_always_exists_for_ec2(self):169 # ResponseMetadata is used for more than just the request id. It170 # should always get populated, even if the request doesn't seem to171 # have an id.172 parser = parsers.EC2QueryParser()173 response = (174 b'<OperationNameResponse>'175 b' <Str>myname</Str>'176 b'</OperationNameResponse>'177 )178 output_shape = model.StructureShape(179 'OutputShape',180 {181 'type': 'structure',182 'members': {183 'Str': {184 'shape': 'StringType',185 }186 },187 },188 model.ShapeResolver({'StringType': {'type': 'string'}}),189 )190 parsed = parser.parse(191 {'headers': {}, 'body': response, 'status_code': 200}, output_shape192 )193 expected = {194 'Str': 'myname',195 'ResponseMetadata': {'HTTPStatusCode': 200, 'HTTPHeaders': {}},196 }197 self.assertEqual(parsed, expected)198 def test_response_metadata_on_json_request(self):199 parser = parsers.JSONParser()200 response = b'{"Str": "mystring"}'201 headers = {'x-amzn-requestid': 'request-id'}202 output_shape = model.StructureShape(203 'OutputShape',204 {205 'type': 'structure',206 'members': {207 'Str': {208 'shape': 'StringType',209 }210 },211 },212 model.ShapeResolver({'StringType': {'type': 'string'}}),213 )214 parsed = parser.parse(215 {'body': response, 'headers': headers, 'status_code': 200},216 output_shape,217 )218 # Note that the response metadata is normalized to match the query219 # protocol, even though this is not how it appears in the output.220 self.assertEqual(221 parsed,222 {223 'Str': 'mystring',224 'ResponseMetadata': {225 'RequestId': 'request-id',226 'HTTPStatusCode': 200,227 'HTTPHeaders': headers,228 },229 },230 )231 def test_response_no_initial_event_stream(self):232 parser = parsers.JSONParser()233 output_shape = model.StructureShape(234 'OutputShape',235 {236 'type': 'structure',237 'members': {'Payload': {'shape': 'Payload'}},238 },239 model.ShapeResolver(240 {241 'Payload': {242 'type': 'structure',243 'members': [],244 'eventstream': True,245 }246 }247 ),248 )249 with self.assertRaises(parsers.ResponseParserError):250 response_dict = {251 'status_code': 200,252 'headers': {},253 'body': RawResponse(b''),254 'context': {'operation_name': 'TestOperation'},255 }256 parser.parse(response_dict, output_shape)257 def test_metadata_always_exists_for_json(self):258 # ResponseMetadata is used for more than just the request id. It259 # should always get populated, even if the request doesn't seem to260 # have an id.261 parser = parsers.JSONParser()262 response = b'{"Str": "mystring"}'263 headers = {}264 output_shape = model.StructureShape(265 'OutputShape',266 {267 'type': 'structure',268 'members': {269 'Str': {270 'shape': 'StringType',271 }272 },273 },274 model.ShapeResolver({'StringType': {'type': 'string'}}),275 )276 parsed = parser.parse(277 {'body': response, 'headers': headers, 'status_code': 200},278 output_shape,279 )280 expected = {281 'Str': 'mystring',282 'ResponseMetadata': {283 'HTTPStatusCode': 200,284 'HTTPHeaders': headers,285 },286 }287 self.assertEqual(parsed, expected)288 def test_response_metadata_on_rest_json_response(self):289 parser = parsers.RestJSONParser()290 response = b'{"Str": "mystring"}'291 headers = {'x-amzn-requestid': 'request-id'}292 output_shape = model.StructureShape(293 'OutputShape',294 {295 'type': 'structure',296 'members': {297 'Str': {298 'shape': 'StringType',299 }300 },301 },302 model.ShapeResolver({'StringType': {'type': 'string'}}),303 )304 parsed = parser.parse(305 {'body': response, 'headers': headers, 'status_code': 200},306 output_shape,307 )308 # Note that the response metadata is normalized to match the query309 # protocol, even though this is not how it appears in the output.310 self.assertEqual(311 parsed,312 {313 'Str': 'mystring',314 'ResponseMetadata': {315 'RequestId': 'request-id',316 'HTTPStatusCode': 200,317 'HTTPHeaders': headers,318 },319 },320 )321 def test_metadata_always_exists_on_rest_json_response(self):322 # ResponseMetadata is used for more than just the request id. It323 # should always get populated, even if the request doesn't seem to324 # have an id.325 parser = parsers.RestJSONParser()326 response = b'{"Str": "mystring"}'327 headers = {}328 output_shape = model.StructureShape(329 'OutputShape',330 {331 'type': 'structure',332 'members': {333 'Str': {334 'shape': 'StringType',335 }336 },337 },338 model.ShapeResolver({'StringType': {'type': 'string'}}),339 )340 parsed = parser.parse(341 {'body': response, 'headers': headers, 'status_code': 200},342 output_shape,343 )344 expected = {345 'Str': 'mystring',346 'ResponseMetadata': {347 'HTTPStatusCode': 200,348 'HTTPHeaders': headers,349 },350 }351 self.assertEqual(parsed, expected)352 def test_response_metadata_from_s3_response(self):353 # Even though s3 is a rest-xml service, it's response metadata354 # is slightly different. It has two request ids, both come from355 # the response headers, are both are named differently from other356 # rest-xml responses.357 headers = {'x-amz-id-2': 'second-id', 'x-amz-request-id': 'request-id'}358 parser = parsers.RestXMLParser()359 parsed = parser.parse(360 {'body': '', 'headers': headers, 'status_code': 200}, None361 )362 self.assertEqual(363 parsed,364 {365 'ResponseMetadata': {366 'RequestId': 'request-id',367 'HostId': 'second-id',368 'HTTPStatusCode': 200,369 'HTTPHeaders': headers,370 }371 },372 )373 def test_metadata_always_exists_on_rest_xml_response(self):374 # ResponseMetadata is used for more than just the request id. It375 # should always get populated, even if the request doesn't seem to376 # have an id.377 headers = {}378 parser = parsers.RestXMLParser()379 parsed = parser.parse(380 {'body': '', 'headers': headers, 'status_code': 200}, None381 )382 expected = {383 'ResponseMetadata': {'HTTPStatusCode': 200, 'HTTPHeaders': headers}384 }385 self.assertEqual(parsed, expected)386 def test_checksum_metadata_parsed_from_response_context(self):387 headers = {}388 response_dict = {389 'status_code': 200,390 'headers': headers,391 'body': b'',392 'context': {'checksum': {'response_algorithm': 'crc32'}},393 }394 parser = parsers.RestXMLParser()395 parsed = parser.parse(response_dict, None)396 expected_algorithm = 'crc32'397 actual_algorithm = parsed['ResponseMetadata']['ChecksumAlgorithm']398 self.assertEqual(actual_algorithm, expected_algorithm)399class TestTaggedUnions(unittest.TestCase):400 def assert_tagged_union_response_with_unknown_member(401 self,402 parser,403 response,404 output_shape,405 expected_parsed_response,406 expected_log,407 ):408 with self.assertLogs() as captured_log:409 parsed = parser.parse(response, output_shape)410 self.assertEqual(parsed, expected_parsed_response)411 self.assertEqual(len(captured_log.records), 1)412 self.assertIn(413 (414 'Received a tagged union response with member '415 'unknown to client'416 ),417 captured_log.records[0].getMessage(),418 )419 def test_base_json_parser_handles_unknown_member(self):420 parser = parsers.JSONParser()421 response = b'{"Foo": "mystring"}'422 headers = {'x-amzn-requestid': 'request-id'}423 output_shape = model.StructureShape(424 'OutputShape',425 {426 'type': 'structure',427 'union': True,428 'members': {429 'Str': {430 'shape': 'StringType',431 }432 },433 },434 model.ShapeResolver({'StringType': {'type': 'string'}}),435 )436 response = {'body': response, 'headers': headers, 'status_code': 200}437 # Parsed response omits data from service since it is not438 # modeled in the client439 expected_parsed_response = {440 'SDK_UNKNOWN_MEMBER': {'name': 'Foo'},441 'ResponseMetadata': {442 'RequestId': 'request-id',443 'HTTPStatusCode': 200,444 'HTTPHeaders': {'x-amzn-requestid': 'request-id'},445 },446 }447 expected_log = "Received a response with an unknown member Foo set"448 self.assert_tagged_union_response_with_unknown_member(449 parser,450 response,451 output_shape,452 expected_parsed_response,453 expected_log,454 )455 def test_base_xml_parser_handles_unknown_member(self):456 parser = parsers.QueryParser()457 response = (458 b'<OperationNameResponse>'459 b' <OperationNameResult><Foo>mystring</Foo></OperationNameResult>'460 b' <ResponseMetadata>'461 b' <RequestId>request-id</RequestId>'462 b' </ResponseMetadata>'463 b'</OperationNameResponse>'464 )465 output_shape = model.StructureShape(466 'OutputShape',467 {468 'type': 'structure',469 'union': True,470 'resultWrapper': 'OperationNameResult',471 'members': {472 'Str': {473 'shape': 'StringType',474 },475 },476 },477 model.ShapeResolver(478 {479 'StringType': {480 'type': 'string',481 },482 }483 ),484 )485 response = {'body': response, 'headers': {}, 'status_code': 200}486 # Parsed response omits data from service since it is not487 # modeled in the client488 expected_parsed_response = {489 'SDK_UNKNOWN_MEMBER': {'name': 'Foo'},490 'ResponseMetadata': {491 'RequestId': 'request-id',492 'HTTPStatusCode': 200,493 'HTTPHeaders': {},494 },495 }496 expected_log = "Received a response with an unknown member Foo set"497 self.assert_tagged_union_response_with_unknown_member(498 parser,499 response,500 output_shape,501 expected_parsed_response,502 expected_log,503 )504 def test_parser_errors_out_when_multiple_members_set(self):505 parser = parsers.JSONParser()506 response = b'{"Foo": "mystring", "Bar": "mystring2"}'507 headers = {'x-amzn-requestid': 'request-id'}508 output_shape = model.StructureShape(509 'OutputShape',510 {511 'type': 'structure',512 'union': True,513 'members': {514 'Foo': {515 'shape': 'StringType',516 },517 'Bar': {518 'shape': 'StringType',519 },520 },521 },522 model.ShapeResolver({'StringType': {'type': 'string'}}),523 )524 response = {'body': response, 'headers': headers, 'status_code': 200}525 with self.assertRaises(parsers.ResponseParserError):526 parser.parse(response, output_shape)527class TestHeaderResponseInclusion(unittest.TestCase):528 def create_parser(self):529 return parsers.JSONParser()530 def create_arbitary_output_shape(self):531 output_shape = model.StructureShape(532 'OutputShape',533 {534 'type': 'structure',535 'members': {536 'Str': {537 'shape': 'StringType',538 }539 },540 },541 model.ShapeResolver({'StringType': {'type': 'string'}}),542 )543 return output_shape544 def test_can_add_errors_into_response(self):545 parser = self.create_parser()546 headers = {547 'x-amzn-requestid': 'request-id',548 'Header1': 'foo',549 'Header2': 'bar',550 }551 output_shape = self.create_arbitary_output_shape()552 parsed = parser.parse(553 {'body': b'{}', 'headers': headers, 'status_code': 200},554 output_shape,555 )556 # The mapped header's keys should all be lower cased557 parsed_headers = {558 'x-amzn-requestid': 'request-id',559 'header1': 'foo',560 'header2': 'bar',561 }562 # Response headers should be mapped as HTTPHeaders.563 self.assertEqual(564 parsed['ResponseMetadata']['HTTPHeaders'], parsed_headers565 )566 def test_can_always_json_serialize_headers(self):567 parser = self.create_parser()568 original_headers = {569 'x-amzn-requestid': 'request-id',570 'Header1': 'foo',571 }572 headers = CustomHeaderDict(original_headers)573 output_shape = self.create_arbitary_output_shape()574 parsed = parser.parse(575 {'body': b'{}', 'headers': headers, 'status_code': 200},576 output_shape,577 )578 metadata = parsed['ResponseMetadata']579 # We've had the contract that you can json serialize a580 # response. So we want to ensure that despite using a CustomHeaderDict581 # we can always JSON dumps the response metadata.582 self.assertEqual(583 json.loads(json.dumps(metadata))['HTTPHeaders']['header1'], 'foo'584 )585class TestResponseParsingDatetimes(unittest.TestCase):586 def test_can_parse_float_timestamps(self):587 # The type "timestamp" can come back as both an integer or as a float.588 # We need to make sure we handle the case where the timestamp comes589 # back as a float. It might make sense to move this to protocol tests.590 output_shape = model.Shape(591 shape_name='datetime', shape_model={'type': 'timestamp'}592 )593 parser = parsers.JSONParser()594 timestamp_as_float = b'1407538750.49'595 expected_parsed = datetime.datetime(596 2014, 8, 8, 22, 59, 10, 490000, tzinfo=tzutc()597 )598 parsed = parser.parse(599 {'body': timestamp_as_float, 'headers': [], 'status_code': 200},600 output_shape,601 )602 self.assertEqual(parsed, expected_parsed)603class TestResponseParserFactory(unittest.TestCase):604 def setUp(self):605 self.factory = parsers.ResponseParserFactory()606 def test_rest_parser(self):607 parser = self.factory.create_parser('rest-xml')608 self.assertTrue(isinstance(parser, parsers.BaseRestParser))609 self.assertTrue(isinstance(parser, parsers.BaseXMLResponseParser))610 def test_json_parser(self):611 parser = self.factory.create_parser('json')612 self.assertTrue(isinstance(parser, parsers.BaseJSONParser))613class TestCanDecorateResponseParsing(unittest.TestCase):614 def setUp(self):615 self.factory = parsers.ResponseParserFactory()616 def create_request_dict(self, with_body):617 return {'body': with_body, 'headers': [], 'status_code': 200}618 def test_normal_blob_parsing(self):619 output_shape = model.Shape(620 shape_name='BlobType', shape_model={'type': 'blob'}621 )622 parser = self.factory.create_parser('json')623 hello_world_b64 = b'"aGVsbG8gd29ybGQ="'624 expected_parsed = b'hello world'625 parsed = parser.parse(626 self.create_request_dict(with_body=hello_world_b64), output_shape627 )628 self.assertEqual(parsed, expected_parsed)629 def test_can_decorate_scalar_parsing(self):630 output_shape = model.Shape(631 shape_name='BlobType', shape_model={'type': 'blob'}632 )633 # Here we're overriding the blob parser so that634 # we can change it to a noop parser.635 self.factory.set_parser_defaults(blob_parser=lambda x: x)636 parser = self.factory.create_parser('json')637 hello_world_b64 = b'"aGVsbG8gd29ybGQ="'638 expected_parsed = "aGVsbG8gd29ybGQ="639 parsed = parser.parse(640 self.create_request_dict(with_body=hello_world_b64), output_shape641 )642 self.assertEqual(parsed, expected_parsed)643 def test_can_decorate_timestamp_parser(self):644 output_shape = model.Shape(645 shape_name='datetime', shape_model={'type': 'timestamp'}646 )647 # Here we're overriding the timestamp parser so that648 # we can change it to just convert a string to an integer649 # instead of converting to a datetime.650 self.factory.set_parser_defaults(timestamp_parser=lambda x: int(x))651 parser = self.factory.create_parser('json')652 timestamp_as_int = b'1407538750'653 expected_parsed = int(timestamp_as_int)654 parsed = parser.parse(655 self.create_request_dict(with_body=timestamp_as_int), output_shape656 )657 self.assertEqual(parsed, expected_parsed)658class TestHandlesNoOutputShape(unittest.TestCase):659 """Verify that each protocol handles no output shape properly."""660 def test_empty_rest_json_response(self):661 headers = {'x-amzn-requestid': 'request-id'}662 parser = parsers.RestJSONParser()663 output_shape = None664 parsed = parser.parse(665 {'body': b'', 'headers': headers, 'status_code': 200}, output_shape666 )667 self.assertEqual(668 parsed,669 {670 'ResponseMetadata': {671 'RequestId': 'request-id',672 'HTTPStatusCode': 200,673 'HTTPHeaders': headers,674 }675 },676 )677 def test_empty_rest_xml_response(self):678 # This is the format used by cloudfront, route53.679 headers = {'x-amzn-requestid': 'request-id'}680 parser = parsers.RestXMLParser()681 output_shape = None682 parsed = parser.parse(683 {'body': b'', 'headers': headers, 'status_code': 200}, output_shape684 )685 self.assertEqual(686 parsed,687 {688 'ResponseMetadata': {689 'RequestId': 'request-id',690 'HTTPStatusCode': 200,691 'HTTPHeaders': headers,692 }693 },694 )695 def test_empty_query_response(self):696 body = (697 b'<DeleteTagsResponse xmlns="http://autoscaling.amazonaws.com/">'698 b' <ResponseMetadata>'699 b' <RequestId>request-id</RequestId>'700 b' </ResponseMetadata>'701 b'</DeleteTagsResponse>'702 )703 parser = parsers.QueryParser()704 output_shape = None705 parsed = parser.parse(706 {'body': body, 'headers': {}, 'status_code': 200}, output_shape707 )708 self.assertEqual(709 parsed,710 {711 'ResponseMetadata': {712 'RequestId': 'request-id',713 'HTTPStatusCode': 200,714 'HTTPHeaders': {},715 }716 },717 )718 def test_empty_json_response(self):719 headers = {'x-amzn-requestid': 'request-id'}720 # Output shape of None represents no output shape in the model.721 output_shape = None722 parser = parsers.JSONParser()723 parsed = parser.parse(724 {'body': b'', 'headers': headers, 'status_code': 200}, output_shape725 )726 self.assertEqual(727 parsed,728 {729 'ResponseMetadata': {730 'RequestId': 'request-id',731 'HTTPStatusCode': 200,732 'HTTPHeaders': headers,733 }734 },735 )736class TestHandlesInvalidXMLResponses(unittest.TestCase):737 def test_invalid_xml_shown_in_error_message(self):738 # Missing the closing XML tags.739 invalid_xml = (740 b'<DeleteTagsResponse xmlns="http://autoscaling.amazonaws.com/">'741 b' <ResponseMetadata>'742 )743 parser = parsers.QueryParser()744 output_shape = None745 # The XML body should be in the error message.746 with self.assertRaisesRegex(747 parsers.ResponseParserError, '<DeleteTagsResponse'748 ):749 parser.parse(750 {'body': invalid_xml, 'headers': {}, 'status_code': 200},751 output_shape,752 )753class TestRESTXMLResponses(unittest.TestCase):754 def test_multiple_structures_list_returns_struture(self):755 # This is to handle the scenario when something is modeled756 # as a structure and instead a list of structures is returned.757 # For this case, a single element from the list should be parsed758 # For botocore, this will be the first element.759 # Currently, this logic may happen in s3's GetBucketLifecycle760 # operation.761 headers = {}762 parser = parsers.RestXMLParser()763 body = (764 '<?xml version="1.0" ?>'765 '<OperationName xmlns="http://s3.amazonaws.com/doc/2006-03-01/">'766 ' <Foo><Bar>first_value</Bar></Foo>'767 ' <Foo><Bar>middle_value</Bar></Foo>'768 ' <Foo><Bar>last_value</Bar></Foo>'769 '</OperationName>'770 )771 builder = model.DenormalizedStructureBuilder()772 output_shape = builder.with_members(773 {774 'Foo': {775 'type': 'structure',776 'members': {777 'Bar': {778 'type': 'string',779 }780 },781 }782 }783 ).build_model()784 parsed = parser.parse(785 {'body': body, 'headers': headers, 'status_code': 200},786 output_shape,787 )788 # Ensure the first element is used out of the list.789 self.assertEqual(parsed['Foo'], {'Bar': 'first_value'})790class TestEventStreamParsers(unittest.TestCase):791 def setUp(self):792 self.parser = parsers.EventStreamXMLParser()793 self.output_shape = model.StructureShape(794 'EventStream',795 {796 'eventstream': True,797 'type': 'structure',798 'members': {799 'EventA': {'shape': 'EventAStructure'},800 'EventB': {'shape': 'EventBStructure'},801 'EventC': {'shape': 'EventCStructure'},802 'EventD': {'shape': 'EventDStructure'},803 'EventException': {'shape': 'ExceptionShape'},804 },805 },806 model.ShapeResolver(807 {808 'EventAStructure': {809 'event': True,810 'type': 'structure',811 'members': {812 'Stats': {813 'shape': 'StatsStructure',814 'eventpayload': True,815 },816 'Header': {817 'shape': 'IntShape',818 'eventheader': True,819 },820 },821 },822 'EventBStructure': {823 'event': True,824 'type': 'structure',825 'members': {826 'Body': {827 'shape': 'BlobShape',828 'eventpayload': True,829 }830 },831 },832 'EventCStructure': {833 'event': True,834 'type': 'structure',835 'members': {836 'Body': {837 'shape': 'StringShape',838 'eventpayload': True,839 }840 },841 },842 'EventDStructure': {843 'event': True,844 'type': 'structure',845 'members': {846 'StringField': {'shape': 'StringShape'},847 'IntField': {'shape': 'IntShape'},848 'Header': {849 'shape': 'IntShape',850 'eventheader': True,851 },852 },853 },854 'StatsStructure': {855 'type': 'structure',856 'members': {857 'StringField': {'shape': 'StringShape'},858 'IntField': {'shape': 'IntShape'},859 },860 },861 'BlobShape': {'type': 'blob'},862 'StringShape': {'type': 'string'},863 'IntShape': {'type': 'integer'},864 'ExceptionShape': {865 'exception': True,866 'type': 'structure',867 'members': {'message': {'shape': 'StringShape'}},868 },869 }870 ),871 )872 def parse_event(self, headers=None, body=None, status_code=200):873 response_dict = {874 'body': body,875 'headers': headers,876 'status_code': status_code,877 }878 return self.parser.parse(response_dict, self.output_shape)879 def test_parses_event_xml(self):880 headers = {'Header': 123, ':event-type': 'EventA'}881 body = (882 b'<Stats xmlns="">'883 b' <StringField>abcde</StringField>'884 b' <IntField>1234</IntField>'885 b'</Stats>'886 )887 parsed = self.parse_event(headers, body)888 expected = {889 'EventA': {890 'Header': 123,891 'Stats': {'StringField': 'abcde', 'IntField': 1234},892 }893 }894 self.assertEqual(parsed, expected)895 def test_parses_event_bad_xml(self):896 headers = {'Header': 123, ':event-type': 'EventA'}897 parsed = self.parse_event(headers, b'')898 expected = {'EventA': {'Header': 123, 'Stats': {}}}899 self.assertEqual(parsed, expected)900 def test_parses_event_blob(self):901 headers = {':event-type': 'EventB'}902 parsed = self.parse_event(headers, b'blob')903 expected = {'EventB': {'Body': b'blob'}}904 self.assertEqual(parsed, expected)905 def test_parses_event_string(self):906 headers = {':event-type': 'EventC'}907 parsed = self.parse_event(headers, b'blob')908 expected = {'EventC': {'Body': 'blob'}}909 self.assertEqual(parsed, expected)910 def test_parses_payload_implicit(self):911 headers = {'Header': 123, ':event-type': 'EventD'}912 body = (913 b'<EventD xmlns="">'914 b' <StringField>abcde</StringField>'915 b' <IntField>1234</IntField>'916 b'</EventD>'917 )918 parsed = self.parse_event(headers, body)919 expected = {920 'EventD': {'Header': 123, 'StringField': 'abcde', 'IntField': 1234}921 }922 self.assertEqual(parsed, expected)923 def test_parses_error_event(self):924 error_code = 'client/SomeError'925 error_message = 'You did something wrong'926 headers = {927 ':message-type': 'error',928 ':error-code': error_code,929 ':error-message': error_message,930 }931 body = b''932 parsed = self.parse_event(headers, body, status_code=400)933 expected = {'Error': {'Code': error_code, 'Message': error_message}}934 self.assertEqual(parsed, expected)935 def test_parses_exception_event(self):936 self.parser = parsers.EventStreamJSONParser()937 error_code = 'EventException'938 headers = {939 ':message-type': 'exception',940 ':exception-type': error_code,941 }942 body = b'{"message": "You did something wrong"}'943 parsed = self.parse_event(headers, body, status_code=400)944 expected = {945 'Error': {'Code': error_code, 'Message': 'You did something wrong'}946 }947 self.assertEqual(parsed, expected)948 def test_parses_event_json(self):949 self.parser = parsers.EventStreamJSONParser()950 headers = {':event-type': 'EventD'}951 body = b'{' b' "StringField": "abcde",' b' "IntField": 1234' b'}'952 parsed = self.parse_event(headers, body)953 expected = {'EventD': {'StringField': 'abcde', 'IntField': 1234}}954 self.assertEqual(parsed, expected)955class TestParseErrorResponses(unittest.TestCase):956 # This class consolidates all the error parsing tests957 # across all the protocols. We may potentially pull958 # this into the shared protocol tests in the future,959 # so consolidating them into a single class will make960 # this easier.961 def setUp(self):962 self.error_shape = model.StructureShape(963 'ErrorShape',964 {965 'type': 'structure',966 'exception': True,967 'members': {968 'ModeledField': {969 'shape': 'StringType',970 }971 },972 },973 model.ShapeResolver({'StringType': {'type': 'string'}}),974 )975 def test_response_metadata_errors_for_json_protocol(self):976 parser = parsers.JSONParser()977 response = {978 "body": b"""979 {"__type":"amazon.foo.validate#ValidationException",980 "message":"this is a message"}981 """,982 "status_code": 400,983 "headers": {"x-amzn-requestid": "request-id"},984 }985 parsed = parser.parse(response, None)986 # Even (especially) on an error condition, the987 # ResponseMetadata should be populated.988 self.assertIn('ResponseMetadata', parsed)989 self.assertEqual(parsed['ResponseMetadata']['RequestId'], 'request-id')990 self.assertIn('Error', parsed)991 self.assertEqual(parsed['Error']['Message'], 'this is a message')992 self.assertEqual(parsed['Error']['Code'], 'ValidationException')993 def test_response_metadata_errors_alternate_form_json_protocol(self):994 # Sometimes there is no '#' in the __type. We need to be995 # able to parse this error message as well.996 parser = parsers.JSONParser()997 response = {998 "body": b"""999 {"__type":"ValidationException",1000 "message":"this is a message"}1001 """,1002 "status_code": 400,1003 "headers": {"x-amzn-requestid": "request-id"},1004 }1005 parsed = parser.parse(response, None)1006 self.assertIn('Error', parsed)1007 self.assertEqual(parsed['Error']['Message'], 'this is a message')1008 self.assertEqual(parsed['Error']['Code'], 'ValidationException')1009 def test_parse_error_response_for_query_protocol(self):1010 body = (1011 b'<ErrorResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">'1012 b' <Error>'1013 b' <Type>Sender</Type>'1014 b' <Code>InvalidInput</Code>'1015 b' <Message>ARN asdf is not valid.</Message>'1016 b' </Error>'1017 b' <RequestId>request-id</RequestId>'1018 b'</ErrorResponse>'1019 )1020 parser = parsers.QueryParser()1021 parsed = parser.parse(1022 {'body': body, 'headers': {}, 'status_code': 400}, None1023 )1024 self.assertIn('Error', parsed)1025 self.assertEqual(1026 parsed['Error'],1027 {1028 'Code': 'InvalidInput',1029 'Message': 'ARN asdf is not valid.',1030 'Type': 'Sender',1031 },1032 )1033 def test_can_parse_sdb_error_response_query_protocol(self):1034 body = (1035 b'<OperationNameResponse>'1036 b' <Errors>'1037 b' <Error>'1038 b' <Code>1</Code>'1039 b' <Message>msg</Message>'1040 b' </Error>'1041 b' </Errors>'1042 b' <RequestId>abc-123</RequestId>'1043 b'</OperationNameResponse>'1044 )1045 parser = parsers.QueryParser()1046 parsed = parser.parse(1047 {'body': body, 'headers': {}, 'status_code': 500}, None1048 )1049 self.assertIn('Error', parsed)1050 self.assertEqual(parsed['Error'], {'Code': '1', 'Message': 'msg'})1051 self.assertEqual(1052 parsed['ResponseMetadata'],1053 {'RequestId': 'abc-123', 'HTTPStatusCode': 500, 'HTTPHeaders': {}},1054 )1055 def test_can_parser_ec2_errors(self):1056 body = (1057 b'<Response>'1058 b' <Errors>'1059 b' <Error>'1060 b' <Code>InvalidInstanceID.NotFound</Code>'1061 b' <Message>The instance ID i-12345 does not exist</Message>'1062 b' </Error>'1063 b' </Errors>'1064 b' <RequestID>06f382b0-d521-4bb6-988c-ca49d5ae6070</RequestID>'1065 b'</Response>'1066 )1067 parser = parsers.EC2QueryParser()1068 parsed = parser.parse(1069 {'body': body, 'headers': {}, 'status_code': 400}, None1070 )1071 self.assertIn('Error', parsed)1072 self.assertEqual(1073 parsed['Error'],1074 {1075 'Code': 'InvalidInstanceID.NotFound',1076 'Message': 'The instance ID i-12345 does not exist',1077 },1078 )1079 def test_can_parse_rest_xml_errors(self):1080 body = (1081 b'<ErrorResponse xmlns="https://route53.amazonaws.com/doc/2013-04-01/">'1082 b' <Error>'1083 b' <Type>Sender</Type>'1084 b' <Code>NoSuchHostedZone</Code>'1085 b' <Message>No hosted zone found with ID: foobar</Message>'1086 b' </Error>'1087 b' <RequestId>bc269cf3-d44f-11e5-8779-2d21c30eb3f1</RequestId>'1088 b'</ErrorResponse>'1089 )1090 parser = parsers.RestXMLParser()1091 parsed = parser.parse(1092 {'body': body, 'headers': {}, 'status_code': 400}, None1093 )1094 self.assertIn('Error', parsed)1095 self.assertEqual(1096 parsed['Error'],1097 {1098 'Code': 'NoSuchHostedZone',1099 'Message': 'No hosted zone found with ID: foobar',1100 'Type': 'Sender',1101 },1102 )1103 def test_can_parse_rest_json_errors(self):1104 body = b'{"Message":"Function not found: foo","Type":"User"}'1105 headers = {1106 'x-amzn-requestid': 'request-id',1107 'x-amzn-errortype': 'ResourceNotFoundException:http://url/',1108 }1109 parser = parsers.RestJSONParser()1110 parsed = parser.parse(1111 {'body': body, 'headers': headers, 'status_code': 400}, None1112 )1113 self.assertIn('Error', parsed)1114 self.assertEqual(1115 parsed['Error'],1116 {1117 'Code': 'ResourceNotFoundException',1118 'Message': 'Function not found: foo',1119 },1120 )1121 def test_error_response_with_no_body_rest_json(self):1122 parser = parsers.RestJSONParser()1123 response = b''1124 headers = {'content-length': '0', 'connection': 'keep-alive'}1125 output_shape = None1126 parsed = parser.parse(1127 {'body': response, 'headers': headers, 'status_code': 504},1128 output_shape,1129 )1130 self.assertIn('Error', parsed)1131 self.assertEqual(1132 parsed['Error'], {'Code': '504', 'Message': 'Gateway Timeout'}1133 )1134 self.assertEqual(1135 parsed['ResponseMetadata'],1136 {'HTTPStatusCode': 504, 'HTTPHeaders': headers},1137 )1138 def test_error_response_with_string_body_rest_json(self):1139 parser = parsers.RestJSONParser()1140 response = b'HTTP content length exceeded 1049600 bytes.'1141 headers = {'content-length': '0', 'connection': 'keep-alive'}1142 output_shape = None1143 parsed = parser.parse(1144 {'body': response, 'headers': headers, 'status_code': 413},1145 output_shape,1146 )1147 self.assertIn('Error', parsed)1148 self.assertEqual(1149 parsed['Error'],1150 {'Code': '413', 'Message': response.decode('utf-8')},1151 )1152 self.assertEqual(1153 parsed['ResponseMetadata'],1154 {'HTTPStatusCode': 413, 'HTTPHeaders': headers},1155 )1156 def test_error_response_with_xml_body_rest_json(self):1157 parser = parsers.RestJSONParser()1158 response = (1159 b'<AccessDeniedException>'1160 b' <Message>Unable to determine service/operation name to be authorized</Message>'1161 b'</AccessDeniedException>'1162 )1163 headers = {'content-length': '0', 'connection': 'keep-alive'}1164 output_shape = None1165 parsed = parser.parse(1166 {'body': response, 'headers': headers, 'status_code': 403},1167 output_shape,1168 )1169 self.assertIn('Error', parsed)1170 self.assertEqual(1171 parsed['Error'],1172 {'Code': '403', 'Message': response.decode('utf-8')},1173 )1174 self.assertEqual(1175 parsed['ResponseMetadata'],1176 {'HTTPStatusCode': 403, 'HTTPHeaders': headers},1177 )1178 def test_s3_error_response(self):1179 body = (1180 b'<Error>'1181 b' <Code>NoSuchBucket</Code>'1182 b' <Message>error message</Message>'1183 b' <BucketName>asdf</BucketName>'1184 b' <RequestId>EF1EF43A74415102</RequestId>'1185 b' <HostId>hostid</HostId>'1186 b'</Error>'1187 )1188 headers = {'x-amz-id-2': 'second-id', 'x-amz-request-id': 'request-id'}1189 parser = parsers.RestXMLParser()1190 parsed = parser.parse(1191 {'body': body, 'headers': headers, 'status_code': 400}, None1192 )1193 self.assertIn('Error', parsed)1194 self.assertEqual(1195 parsed['Error'],1196 {1197 'Code': 'NoSuchBucket',1198 'Message': 'error message',1199 'BucketName': 'asdf',1200 # We don't want the RequestId/HostId because they're already1201 # present in the ResponseMetadata key.1202 },1203 )1204 self.assertEqual(1205 parsed['ResponseMetadata'],1206 {1207 'RequestId': 'request-id',1208 'HostId': 'second-id',1209 'HTTPStatusCode': 400,1210 'HTTPHeaders': headers,1211 },1212 )1213 def test_s3_error_response_with_no_body(self):1214 # If you try to HeadObject a key that does not exist,1215 # you will get an empty body. When this happens1216 # we expect that we will use Code/Message from the1217 # HTTP status code.1218 body = ''1219 headers = {'x-amz-id-2': 'second-id', 'x-amz-request-id': 'request-id'}1220 parser = parsers.RestXMLParser()1221 parsed = parser.parse(1222 {'body': body, 'headers': headers, 'status_code': 404}, None1223 )1224 self.assertIn('Error', parsed)1225 self.assertEqual(1226 parsed['Error'],1227 {1228 'Code': '404',1229 'Message': 'Not Found',1230 },1231 )1232 self.assertEqual(1233 parsed['ResponseMetadata'],1234 {1235 'RequestId': 'request-id',1236 'HostId': 'second-id',1237 'HTTPStatusCode': 404,1238 'HTTPHeaders': headers,1239 },1240 )1241 def test_can_parse_glacier_error_response(self):1242 body = (1243 b'{"code":"AccessDeniedException","type":"Client","message":'1244 b'"Access denied"}'1245 )1246 headers = {'x-amzn-requestid': 'request-id'}1247 parser = parsers.RestJSONParser()1248 parsed = parser.parse(1249 {'body': body, 'headers': headers, 'status_code': 400}, None1250 )1251 self.assertEqual(1252 parsed['Error'],1253 {'Message': 'Access denied', 'Code': 'AccessDeniedException'},1254 )1255 def test_can_parse_restjson_error_code(self):1256 body = b'''{1257 "status": "error",1258 "errors": [{"message": "[*Deprecated*: blah"}],1259 "adds": 0,1260 "__type": "#WasUnableToParseThis",1261 "message": "blah",1262 "deletes": 0}'''1263 headers = {'x-amzn-requestid': 'request-id'}1264 parser = parsers.RestJSONParser()1265 parsed = parser.parse(1266 {'body': body, 'headers': headers, 'status_code': 400}, None1267 )1268 self.assertEqual(1269 parsed['Error'],1270 {'Message': 'blah', 'Code': 'WasUnableToParseThis'},1271 )1272 def test_can_parse_with_case_insensitive_keys(self):1273 body = (1274 b'{"Code":"AccessDeniedException","type":"Client","Message":'1275 b'"Access denied"}'1276 )1277 headers = {'x-amzn-requestid': 'request-id'}1278 parser = parsers.RestJSONParser()1279 parsed = parser.parse(1280 {'body': body, 'headers': headers, 'status_code': 400}, None1281 )1282 self.assertEqual(1283 parsed['Error'],1284 {'Message': 'Access denied', 'Code': 'AccessDeniedException'},1285 )1286 def test_can_parse_rest_json_modeled_fields(self):1287 body = (1288 b'{"ModeledField":"Some modeled field",'1289 b'"Message":"Some message"}'1290 )1291 parser = parsers.RestJSONParser()1292 response_dict = {1293 'status_code': 400,1294 'headers': {},1295 'body': body,1296 }1297 parsed = parser.parse(response_dict, self.error_shape)1298 expected_parsed = {1299 'ModeledField': 'Some modeled field',1300 }1301 self.assertEqual(parsed, expected_parsed)1302 def test_can_parse_rest_xml_modeled_fields(self):1303 parser = parsers.RestXMLParser()1304 body = (1305 b'<?xml version="1.0"?>\n<ErrorResponse xmlns="http://foo.bar">'1306 b'<Error><Type>Sender</Type><Code>NoSuchDistribution</Code>'1307 b'<Message>The specified distribution does not exist.</Message>'1308 b'<ModeledField>Some modeled field</ModeledField>'1309 b'</Error>'1310 b'</ErrorResponse>'1311 )1312 response_dict = {1313 'status_code': 400,1314 'headers': {},1315 'body': body,1316 }1317 parsed = parser.parse(response_dict, self.error_shape)1318 expected_parsed = {1319 'ModeledField': 'Some modeled field',1320 }1321 self.assertEqual(parsed, expected_parsed)1322 def test_can_parse_ec2_modeled_fields(self):1323 body = (1324 b'<Response><Errors><Error>'1325 b'<Code>ExceptionShape</Code>'1326 b'<Message>Foo message</Message>'1327 b'<ModeledField>Some modeled field</ModeledField>'1328 b'</Error></Errors></Response>'1329 )1330 parser = parsers.EC2QueryParser()1331 response_dict = {1332 'status_code': 400,1333 'headers': {},1334 'body': body,1335 }1336 parsed = parser.parse(response_dict, self.error_shape)1337 expected_parsed = {1338 'ModeledField': 'Some modeled field',1339 }1340 self.assertEqual(parsed, expected_parsed)1341 def test_can_parse_query_modeled_fields(self):1342 parser = parsers.QueryParser()1343 body = (1344 b'<?xml version="1.0"?>\n<ErrorResponse xmlns="http://foo.bar">'1345 b'<Error><Type>Sender</Type><Code>SomeCode</Code>'1346 b'<Message>A message</Message>'1347 b'<ModeledField>Some modeled field</ModeledField>'1348 b'</Error>'1349 b'</ErrorResponse>'1350 )1351 response_dict = {1352 'status_code': 400,1353 'headers': {},1354 'body': body,1355 }1356 parsed = parser.parse(response_dict, self.error_shape)1357 expected_parsed = {1358 'ModeledField': 'Some modeled field',1359 }1360 self.assertEqual(parsed, expected_parsed)1361 def test_can_parse_json_modeled_fields(self):1362 body = (1363 b'{"ModeledField":"Some modeled field",'1364 b'"Message":"Some message",'1365 b'"__type": "Prefix#SomeError"}'1366 )1367 parser = parsers.JSONParser()1368 response_dict = {1369 'status_code': 400,1370 'headers': {},1371 'body': body,1372 }1373 parsed = parser.parse(response_dict, self.error_shape)1374 expected_parsed = {1375 'ModeledField': 'Some modeled field',1376 }1377 self.assertEqual(parsed, expected_parsed)1378 def test_can_parse_route53_with_missing_message(self):1379 # The message isn't always in the XML response (or even the headers).1380 # We should be able to handle this gracefully and still at least1381 # populate a "Message" key so that consumers don't have to1382 # conditionally check for this.1383 body = (1384 b'<ErrorResponse>'1385 b' <Error>'1386 b' <Type>Sender</Type>'1387 b' <Code>InvalidInput</Code>'1388 b' </Error>'1389 b' <RequestId>id</RequestId>'1390 b'</ErrorResponse>'1391 )1392 parser = parsers.RestXMLParser()1393 parsed = parser.parse(1394 {'body': body, 'headers': {}, 'status_code': 400}, None1395 )1396 error = parsed['Error']1397 self.assertEqual(error['Code'], 'InvalidInput')1398 # Even though there's no <Message /> we should1399 # still populate an empty string.1400 self.assertEqual(error['Message'], '')1401def _generic_test_bodies():1402 generic_html_body = (1403 b'<html><body><b>Http/1.1 Service Unavailable</b></body></html>'1404 )1405 empty_body = b''1406 none_body = None1407 return [generic_html_body, empty_body, none_body]1408@pytest.mark.parametrize(1409 "parser, body",1410 itertools.product(1411 parsers.PROTOCOL_PARSERS.values(), _generic_test_bodies()1412 ),1413)1414def test_can_handle_generic_error_message(parser, body):1415 # There are times when you can get a service to respond with a generic1416 # html error page. We should be able to handle this case.1417 parsed = parser().parse(1418 {'body': body, 'headers': {}, 'status_code': 503}, None1419 )1420 assert parsed['Error'] == {'Code': '503', 'Message': 'Service Unavailable'}...

Full Screen

Full Screen

options.js

Source:options.js Github

copy

Full Screen

1/* Every input option is tested and parsed. This'll prevent2 endless validation in internal methods. These tests are3 structured with an item for every option available. An4 option can be marked as required by setting the 'r' flag.5 The testing function is provided with three arguments:6 - The provided value for the option;7 - A reference to the options object;8 - The name for the option;9 The testing function returns false when an error is detected,10 or true when everything is OK. It can also modify the option11 object, to make sure all values can be correctly looped elsewhere. */12 var defaultFormatter = { 'to': function( value ){13 return value !== undefined && value.toFixed(2);14 }, 'from': Number };15 function validateFormat ( entry ) {16 // Any object with a to and from method is supported.17 if ( isValidFormatter(entry) ) {18 return true;19 }20 throw new Error("noUiSlider (" + VERSION + "): 'format' requires 'to' and 'from' methods.");21 }22 function testStep ( parsed, entry ) {23 if ( !isNumeric( entry ) ) {24 throw new Error("noUiSlider (" + VERSION + "): 'step' is not numeric.");25 }26 // The step option can still be used to set stepping27 // for linear sliders. Overwritten if set in 'range'.28 parsed.singleStep = entry;29 }30 function testRange ( parsed, entry ) {31 // Filter incorrect input.32 if ( typeof entry !== 'object' || Array.isArray(entry) ) {33 throw new Error("noUiSlider (" + VERSION + "): 'range' is not an object.");34 }35 // Catch missing start or end.36 if ( entry.min === undefined || entry.max === undefined ) {37 throw new Error("noUiSlider (" + VERSION + "): Missing 'min' or 'max' in 'range'.");38 }39 // Catch equal start or end.40 if ( entry.min === entry.max ) {41 throw new Error("noUiSlider (" + VERSION + "): 'range' 'min' and 'max' cannot be equal.");42 }43 parsed.spectrum = new Spectrum(entry, parsed.snap, parsed.singleStep);44 }45 function testStart ( parsed, entry ) {46 entry = asArray(entry);47 // Validate input. Values aren't tested, as the public .val method48 // will always provide a valid location.49 if ( !Array.isArray( entry ) || !entry.length ) {50 throw new Error("noUiSlider (" + VERSION + "): 'start' option is incorrect.");51 }52 // Store the number of handles.53 parsed.handles = entry.length;54 // When the slider is initialized, the .val method will55 // be called with the start options.56 parsed.start = entry;57 }58 function testSnap ( parsed, entry ) {59 // Enforce 100% stepping within subranges.60 parsed.snap = entry;61 if ( typeof entry !== 'boolean' ){62 throw new Error("noUiSlider (" + VERSION + "): 'snap' option must be a boolean.");63 }64 }65 function testAnimate ( parsed, entry ) {66 // Enforce 100% stepping within subranges.67 parsed.animate = entry;68 if ( typeof entry !== 'boolean' ){69 throw new Error("noUiSlider (" + VERSION + "): 'animate' option must be a boolean.");70 }71 }72 function testAnimationDuration ( parsed, entry ) {73 parsed.animationDuration = entry;74 if ( typeof entry !== 'number' ){75 throw new Error("noUiSlider (" + VERSION + "): 'animationDuration' option must be a number.");76 }77 }78 function testConnect ( parsed, entry ) {79 var connect = [false];80 var i;81 // Map legacy options82 if ( entry === 'lower' ) {83 entry = [true, false];84 }85 else if ( entry === 'upper' ) {86 entry = [false, true];87 }88 // Handle boolean options89 if ( entry === true || entry === false ) {90 for ( i = 1; i < parsed.handles; i++ ) {91 connect.push(entry);92 }93 connect.push(false);94 }95 // Reject invalid input96 else if ( !Array.isArray( entry ) || !entry.length || entry.length !== parsed.handles + 1 ) {97 throw new Error("noUiSlider (" + VERSION + "): 'connect' option doesn't match handle count.");98 }99 else {100 connect = entry;101 }102 parsed.connect = connect;103 }104 function testOrientation ( parsed, entry ) {105 // Set orientation to an a numerical value for easy106 // array selection.107 switch ( entry ){108 case 'horizontal':109 parsed.ort = 0;110 break;111 case 'vertical':112 parsed.ort = 1;113 break;114 default:115 throw new Error("noUiSlider (" + VERSION + "): 'orientation' option is invalid.");116 }117 }118 function testMargin ( parsed, entry ) {119 if ( !isNumeric(entry) ){120 throw new Error("noUiSlider (" + VERSION + "): 'margin' option must be numeric.");121 }122 // Issue #582123 if ( entry === 0 ) {124 return;125 }126 parsed.margin = parsed.spectrum.getMargin(entry);127 if ( !parsed.margin ) {128 throw new Error("noUiSlider (" + VERSION + "): 'margin' option is only supported on linear sliders.");129 }130 }131 function testLimit ( parsed, entry ) {132 if ( !isNumeric(entry) ){133 throw new Error("noUiSlider (" + VERSION + "): 'limit' option must be numeric.");134 }135 parsed.limit = parsed.spectrum.getMargin(entry);136 if ( !parsed.limit || parsed.handles < 2 ) {137 throw new Error("noUiSlider (" + VERSION + "): 'limit' option is only supported on linear sliders with 2 or more handles.");138 }139 }140 function testPadding ( parsed, entry ) {141 if ( !isNumeric(entry) ){142 throw new Error("noUiSlider (" + VERSION + "): 'padding' option must be numeric.");143 }144 if ( entry === 0 ) {145 return;146 }147 parsed.padding = parsed.spectrum.getMargin(entry);148 if ( !parsed.padding ) {149 throw new Error("noUiSlider (" + VERSION + "): 'padding' option is only supported on linear sliders.");150 }151 if ( parsed.padding < 0 ) {152 throw new Error("noUiSlider (" + VERSION + "): 'padding' option must be a positive number.");153 }154 if ( parsed.padding >= 50 ) {155 throw new Error("noUiSlider (" + VERSION + "): 'padding' option must be less than half the range.");156 }157 }158 function testDirection ( parsed, entry ) {159 // Set direction as a numerical value for easy parsing.160 // Invert connection for RTL sliders, so that the proper161 // handles get the connect/background classes.162 switch ( entry ) {163 case 'ltr':164 parsed.dir = 0;165 break;166 case 'rtl':167 parsed.dir = 1;168 break;169 default:170 throw new Error("noUiSlider (" + VERSION + "): 'direction' option was not recognized.");171 }172 }173 function testBehaviour ( parsed, entry ) {174 // Make sure the input is a string.175 if ( typeof entry !== 'string' ) {176 throw new Error("noUiSlider (" + VERSION + "): 'behaviour' must be a string containing options.");177 }178 // Check if the string contains any keywords.179 // None are required.180 var tap = entry.indexOf('tap') >= 0;181 var drag = entry.indexOf('drag') >= 0;182 var fixed = entry.indexOf('fixed') >= 0;183 var snap = entry.indexOf('snap') >= 0;184 var hover = entry.indexOf('hover') >= 0;185 if ( fixed ) {186 if ( parsed.handles !== 2 ) {187 throw new Error("noUiSlider (" + VERSION + "): 'fixed' behaviour must be used with 2 handles");188 }189 // Use margin to enforce fixed state190 testMargin(parsed, parsed.start[1] - parsed.start[0]);191 }192 parsed.events = {193 tap: tap || snap,194 drag: drag,195 fixed: fixed,196 snap: snap,197 hover: hover198 };199 }200 function testMultitouch ( parsed, entry ) {201 parsed.multitouch = entry;202 if ( typeof entry !== 'boolean' ){203 throw new Error("noUiSlider (" + VERSION + "): 'multitouch' option must be a boolean.");204 }205 }206 function testTooltips ( parsed, entry ) {207 if ( entry === false ) {208 return;209 }210 else if ( entry === true ) {211 parsed.tooltips = [];212 for ( var i = 0; i < parsed.handles; i++ ) {213 parsed.tooltips.push(true);214 }215 }216 else {217 parsed.tooltips = asArray(entry);218 if ( parsed.tooltips.length !== parsed.handles ) {219 throw new Error("noUiSlider (" + VERSION + "): must pass a formatter for all handles.");220 }221 parsed.tooltips.forEach(function(formatter){222 if ( typeof formatter !== 'boolean' && (typeof formatter !== 'object' || typeof formatter.to !== 'function') ) {223 throw new Error("noUiSlider (" + VERSION + "): 'tooltips' must be passed a formatter or 'false'.");224 }225 });226 }227 }228 function testAriaFormat ( parsed, entry ) {229 parsed.ariaFormat = entry;230 validateFormat(entry);231 }232 function testFormat ( parsed, entry ) {233 parsed.format = entry;234 validateFormat(entry);235 }236 function testCssPrefix ( parsed, entry ) {237 if ( entry !== undefined && typeof entry !== 'string' && entry !== false ) {238 throw new Error("noUiSlider (" + VERSION + "): 'cssPrefix' must be a string or `false`.");239 }240 parsed.cssPrefix = entry;241 }242 function testCssClasses ( parsed, entry ) {243 if ( entry !== undefined && typeof entry !== 'object' ) {244 throw new Error("noUiSlider (" + VERSION + "): 'cssClasses' must be an object.");245 }246 if ( typeof parsed.cssPrefix === 'string' ) {247 parsed.cssClasses = {};248 for ( var key in entry ) {249 if ( !entry.hasOwnProperty(key) ) { continue; }250 parsed.cssClasses[key] = parsed.cssPrefix + entry[key];251 }252 } else {253 parsed.cssClasses = entry;254 }255 }256 function testUseRaf ( parsed, entry ) {257 if ( entry === true || entry === false ) {258 parsed.useRequestAnimationFrame = entry;259 } else {260 throw new Error("noUiSlider (" + VERSION + "): 'useRequestAnimationFrame' option should be true (default) or false.");261 }262 }263 // Test all developer settings and parse to assumption-safe values.264 function testOptions ( options ) {265 // To prove a fix for #537, freeze options here.266 // If the object is modified, an error will be thrown.267 // Object.freeze(options);268 var parsed = {269 margin: 0,270 limit: 0,271 padding: 0,272 animate: true,273 animationDuration: 300,274 ariaFormat: defaultFormatter,275 format: defaultFormatter276 };277 // Tests are executed in the order they are presented here.278 var tests = {279 'step': { r: false, t: testStep },280 'start': { r: true, t: testStart },281 'connect': { r: true, t: testConnect },282 'direction': { r: true, t: testDirection },283 'snap': { r: false, t: testSnap },284 'animate': { r: false, t: testAnimate },285 'animationDuration': { r: false, t: testAnimationDuration },286 'range': { r: true, t: testRange },287 'orientation': { r: false, t: testOrientation },288 'margin': { r: false, t: testMargin },289 'limit': { r: false, t: testLimit },290 'padding': { r: false, t: testPadding },291 'behaviour': { r: true, t: testBehaviour },292 'multitouch': { r: true, t: testMultitouch },293 'ariaFormat': { r: false, t: testAriaFormat },294 'format': { r: false, t: testFormat },295 'tooltips': { r: false, t: testTooltips },296 'cssPrefix': { r: false, t: testCssPrefix },297 'cssClasses': { r: false, t: testCssClasses },298 'useRequestAnimationFrame': { r: false, t: testUseRaf }299 };300 var defaults = {301 'connect': false,302 'direction': 'ltr',303 'behaviour': 'tap',304 'multitouch': false,305 'orientation': 'horizontal',306 'cssPrefix' : 'noUi-',307 'cssClasses': {308 target: 'target',309 base: 'base',310 origin: 'origin',311 handle: 'handle',312 handleLower: 'handle-lower',313 handleUpper: 'handle-upper',314 horizontal: 'horizontal',315 vertical: 'vertical',316 background: 'background',317 connect: 'connect',318 ltr: 'ltr',319 rtl: 'rtl',320 draggable: 'draggable',321 drag: 'state-drag',322 tap: 'state-tap',323 active: 'active',324 tooltip: 'tooltip',325 pips: 'pips',326 pipsHorizontal: 'pips-horizontal',327 pipsVertical: 'pips-vertical',328 marker: 'marker',329 markerHorizontal: 'marker-horizontal',330 markerVertical: 'marker-vertical',331 markerNormal: 'marker-normal',332 markerLarge: 'marker-large',333 markerSub: 'marker-sub',334 value: 'value',335 valueHorizontal: 'value-horizontal',336 valueVertical: 'value-vertical',337 valueNormal: 'value-normal',338 valueLarge: 'value-large',339 valueSub: 'value-sub'340 },341 'useRequestAnimationFrame': true342 };343 // AriaFormat defaults to regular format, if any.344 if ( options.format && !options.ariaFormat ) {345 options.ariaFormat = options.format;346 }347 // Run all options through a testing mechanism to ensure correct348 // input. It should be noted that options might get modified to349 // be handled properly. E.g. wrapping integers in arrays.350 Object.keys(tests).forEach(function( name ){351 // If the option isn't set, but it is required, throw an error.352 if ( options[name] === undefined && defaults[name] === undefined ) {353 if ( tests[name].r ) {354 throw new Error("noUiSlider (" + VERSION + "): '" + name + "' is required.");355 }356 return true;357 }358 tests[name].t( parsed, options[name] === undefined ? defaults[name] : options[name] );359 });360 // Forward pips options361 parsed.pips = options.pips;362 var styles = [['left', 'top'], ['right', 'bottom']];363 // Pre-define the styles.364 parsed.style = styles[parsed.dir][parsed.ort];365 parsed.styleOposite = styles[parsed.dir?0:1][parsed.ort];366 return parsed;...

Full Screen

Full Screen

grammar.py

Source:grammar.py Github

copy

Full Screen

1import sys2from pyparsing import Word, alphas, Combine, nums, Regex, ParseException, string, Optional3class LogGrammar(object):4 """A class to define the format (grammar) of a log file. We heavily rely on pyparsing in this case.5 """6 def __init__(self, log_type=None):7 """The constructor of LogGrammar.8 """9 self.log_type = log_type10 if self.log_type == 'blue-gene':11 self.bluegene_grammar = self.__get_bluegene_grammar()12 elif self.log_type == 'spark':13 self.spark_grammar = self.__get_spark_grammar()14 elif self.log_type == 'windows':15 self.windows_grammar = self.__get_windows_grammar()16 @staticmethod17 def loading(number):18 if number % 1000 == 0:19 s = str(number) + ' ...'20 print(s, end='')21 print('\r', end='')22 @staticmethod23 def __get_bluegene_grammar():24 """The definition of BlueGene/L grammar.25 The BlueGene/L logs can be downloaded from [Useninx2006a]_ and26 this data was used in [Stearley2008]_.27 Returns28 -------29 bluegene_grammar :30 Grammar for BlueGene/L supercomputer logs.31 References32 ----------33 .. [Usenix2006a] The HPC4 data. URL: https://www.usenix.org/cfdr-data#hpc434 .. [Stearley2008] Stearley, J., & Oliner, A. J. Bad words: Finding faults in Spirit's syslogs.35 In 8th IEEE International Symposium on Cluster Computing and the Grid, pp. 765-770.36 """37 ints = Word(nums)38 sock = Word(alphas + '-' + '_')39 number = ints40 date = Combine(ints + '.' + ints + '.' + ints)41 core1 = Word(alphas + nums + '-' + ':' + '_')42 datetime = Combine(ints + '-' + ints + '-' + ints + '-' + ints + '.' + ints + '.' + ints + '.' + ints)43 core2 = Word(alphas + nums + '-' + ':' + '_')44 source = Word(alphas + '(' + ')')45 service = Word(alphas + '_')46 info_type = Word(alphas)47 message = Regex('.*')48 # blue gene log grammar49 bluegene_grammar = sock + number + date + core1 + datetime + core2 + source + service + info_type + message50 return bluegene_grammar51 def parse_bluegenelog(self, log_line):52 """Parse the BlueGene/L logs based on defined grammar.53 Parameters54 ----------55 log_line : str56 A log line to be parsed57 Returns58 -------59 parsed : dict[str, str]60 A parsed BlueGene/L log.61 """62 parsed = dict()63 try:64 parsed_bluegenelog = self.bluegene_grammar.parseString(log_line)65 parsed['sock'] = parsed_bluegenelog[0]66 parsed['number'] = parsed_bluegenelog[1]67 parsed['date'] = parsed_bluegenelog[2]68 parsed['core1'] = parsed_bluegenelog[3]69 parsed['timestamp'] = parsed_bluegenelog[4]70 parsed['core2'] = parsed_bluegenelog[5]71 parsed['source'] = parsed_bluegenelog[6]72 parsed['service'] = parsed_bluegenelog[7]73 parsed['info_type'] = parsed_bluegenelog[8]74 parsed['message'] = parsed_bluegenelog[9]75 except ParseException as e:76 print(repr(e))77 print(log_line)78 return parsed 79 @staticmethod80 def __get_spark_grammar():81 ints = Word(nums)82 date = Optional(Combine(ints + '/' + ints + '/' + ints))83 time = Optional(Combine(ints + ":" + ints + ":" + ints))84 status = Optional(Word(string.ascii_uppercase))85 service = Optional(Word(alphas + nums + '/' + '-' + '_' + '.' + '[' + ']' + ':' + '$'))86 message = Regex('.*')87 spark_grammar = date.setResultsName('date') + time.setResultsName('time') + status.setResultsName('status') + \88 service.setResultsName('service') + message.setResultsName('message')89 return spark_grammar90 def parse_spark(self, log_line):91 parsed = dict()92 try:93 parsed_spark = self.spark_grammar.parseString(log_line)94 parsed['date'] = parsed_spark.date95 parsed['time'] = parsed_spark.time96 parsed['status'] = parsed_spark.status97 parsed['service'] = parsed_spark.service98 parsed['message'] = parsed_spark.message99 except ParseException as e:100 print(repr(e))101 print(log_line)102 return parsed103 @staticmethod104 def __get_windows_grammar():105 ints = Word(nums)106 date = Optional(Combine(ints + '-' + ints + '-' + ints))107 time = Optional(Combine(ints + ":" + ints + ":" + ints + ','))108 status = Optional(Word(string.ascii_uppercase + string.ascii_lowercase))109 service = Optional(Word(string.ascii_uppercase))110 message = Regex('.*')111 windows_grammar = date.setResultsName('date') + time.setResultsName('time') + \112 status.setResultsName('status') + service.setResultsName('service') + message.setResultsName('message')113 return windows_grammar114 def parse_windows(self, log_line):115 parsed = dict()116 try:117 parsed_windows = self.windows_grammar.parseString(log_line)118 parsed['date'] = parsed_windows.date119 parsed['time'] = parsed_windows.time120 parsed['status'] = parsed_windows.status121 parsed['service'] = parsed_windows.service122 parsed['message'] = parsed_windows.message123 except ParseException as e:124 print(repr(e))125 print(log_line)126 return parsed127if __name__ == '__main__':128 logtype = sys.argv[1]129 filename = '/home/hudan/Git/pylogsentiment/datasets/' + logtype + '/logs/' + logtype + '.log'130 lg = LogGrammar(logtype)131 index = 0132 with open(filename, 'r', encoding='utf-8-sig', errors='ignore') as f:133 for line in f:134 # get parsed line and print135 parsed_line = None 136 if logtype == 'bgl':137 parsed_line = lg.parse_bluegenelog(line)138 elif logtype == 'spark':139 parsed_line = lg.parse_spark(line)140 elif logtype == 'windows':141 parsed_line = lg.parse_windows(line)142 lg.loading(index)143 index += 1...

Full Screen

Full Screen

utils_parser.py

Source:utils_parser.py Github

copy

Full Screen

...27 if self.short_tables:28 self.on_short_tables_parse(self.short_tables)29 for short_table in self.short_tables:30 self.on_short_table_parse(short_table)31 self.on_short_table_parsed(short_table)32 self.on_short_tables_parsed(self.short_tables)33 self.on_root_parsed(self.root)34 def _parse_topic(self, topic):35 """Parses a topic.36 """37 self._parse_topic_properties(topic.properties)38 for ps in topic.property_sets:39 self.on_property_set_parse(ps)40 self._parse_topic_properties(ps.properties)41 self.on_property_set_parsed(ps)42 for sp in topic[TYPE_KEY_SUBPROCESS]:43 self.on_subprocess_parse(sp)44 self._parse_topic(sp)45 self.on_subprocess_parsed(sp)46 def _parse_topic_properties(self, properties):47 """Parses a collection of properties associated with either a topic or a property-set.48 """49 for p in properties:50 self.on_property_parse(p)51 if p.enum:52 self.on_enum_parse(p.enum)53 for ec in p.enum.choices:54 self.on_enum_choice_parse(ec)55 self.on_enum_choice_parsed(ec)56 self.on_enum_parsed(p.enum)57 self.on_property_parsed(p)58 def on_root_parse(self, root):59 """On root parse event handler.60 """61 pass62 def on_root_parsed(self, root):63 """On root parsed event handler.64 """65 pass66 def on_grid_parse(self, grid):67 """On grid parse event handler.68 """69 pass70 def on_grid_parsed(self, grid):71 """On grid parsed event handler.72 """73 pass74 def on_keyprops_parse(self, key_props):75 """On key-properties parse event handler.76 """77 pass78 def on_keyprops_parsed(self, key_props):79 """On key-properties parsed event handler.80 """81 pass82 def on_process_parse(self, process):83 """On process parse event handler.84 """85 pass86 def on_process_parsed(self, process):87 """On process parsed event handler.88 """89 pass90 def on_subprocess_parse(self, subprocess):91 """On sub-process parse event handler.92 """93 pass94 def on_subprocess_parsed(self, subprocess):95 """On sub-process parsed event handler.96 """97 pass98 def on_property_set_parse(self, prop_set):99 """On property set parse event handler.100 """101 pass102 def on_property_set_parsed(self, prop_set):103 """On property set parsed event handler.104 """105 pass106 def on_property_parse(self, prop):107 """On property parse event handler.108 """109 pass110 def on_property_parsed(self, prop):111 """On property parsed event handler.112 """113 pass114 def on_enum_parse(self, enum):115 """On enum parse event handler.116 """117 pass118 def on_enum_parsed(self, enum):119 """On enum parsed event handler.120 """121 pass122 def on_enum_choice_parse(self, choice):123 """On enum choice parse event handler.124 """125 pass126 def on_enum_choice_parsed(self, choice):127 """On enum choice parsed event handler.128 """129 pass130 def on_short_tables_parse(self, short_tables):131 """On short tables parse event handler.132 """133 pass134 def on_short_tables_parsed(self, short_tables):135 """On short tables parsed event handler.136 """137 pass138 def on_short_table_parse(self, short_table):139 """On short table parse event handler.140 """141 pass142 def on_short_table_parsed(self, short_table):143 """On short table parsed event handler.144 """...

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run fMBT automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful