Exemple #1
0
def tokenize_json(content):
    assert isinstance(content, (str, bytes))

    if isinstance(content, bytes):
        content = content.decode('utf-8', 'ignore')

    if not content.strip():
        message = ErrorMessage(text='No content.',
                               code='parse_error',
                               position=Position(line_no=1,
                                                 column_no=1,
                                                 index=0))
        raise ParseError(messages=[message], summary='Invalid JSON.')

    try:
        decoder = _TokenizingDecoder(content=content)
        return decoder.decode(content)
    except json.decoder.JSONDecodeError as exc:
        message = ErrorMessage(
            text=_strip_endings(exc.msg, [" starting at", " at"]) + ".",
            code='parse_error',
            position=Position(line_no=exc.lineno,
                              column_no=exc.colno,
                              index=exc.pos))
        raise ParseError(messages=[message], summary='Invalid JSON.') from None
Exemple #2
0
def test_invalid_properties():
    with pytest.raises(ValidationError) as exc:
        apistar.parse('{"a": "abc", "b": 123}', encoding="json", validator=VALIDATOR)

    assert exc.value.messages == [
        ErrorMessage(
            text='Must be a number.',
            code='type',
            index=['a'],
            position=Position(line_no=1, column_no=7, index=6)
        ),
        ErrorMessage(
            text='Invalid property name.',
            code='invalid_property',
            index=['b'],
            position=Position(line_no=1, column_no=14, index=13)
        )
    ]
Exemple #3
0
def test_object_unterminated_after_value():
    with pytest.raises(ParseError) as exc:
        apistar.parse('{"abc": "def"', encoding='json')

    assert exc.value.messages == [
        ErrorMessage(
            text="Expecting ',' delimiter.",
            code='parse_error',
            position=Position(line_no=1, column_no=14, index=13)
        )
    ]
Exemple #4
0
def test_object_invalid_property_name():
    with pytest.raises(ParseError) as exc:
        apistar.parse('{"abc": "def", 1', encoding='json')

    assert exc.value.messages == [
        ErrorMessage(
            text="Expecting property name enclosed in double quotes.",
            code='parse_error',
            position=Position(line_no=1, column_no=16, index=15)
        )
    ]
Exemple #5
0
def test_object_missing_comma_delimiter():
    with pytest.raises(ParseError) as exc:
        apistar.parse('{"abc": "def" 1', encoding='json')

    assert exc.value.messages == [
        ErrorMessage(
            text="Expecting ',' delimiter.",
            code='parse_error',
            position=Position(line_no=1, column_no=15, index=14)
        )
    ]
Exemple #6
0
def test_object_missing_property_name():
    with pytest.raises(ParseError) as exc:
        apistar.parse('{', encoding='json')

    assert exc.value.messages == [
        ErrorMessage(
            text='Expecting property name enclosed in double quotes.',
            code='parse_error',
            position=Position(line_no=1, column_no=2, index=1)
        )
    ]
Exemple #7
0
def test_empty_string():
    with pytest.raises(ParseError) as exc:
        apistar.parse(b'', encoding='json')

    assert exc.value.messages == [
        ErrorMessage(
            text='No content.',
            code='parse_error',
            position=Position(line_no=1, column_no=1, index=0)
        )
    ]
Exemple #8
0
def test_missing_required_property():
    with pytest.raises(ValidationError) as exc:
        apistar.parse('{}', encoding="json", validator=VALIDATOR)

    assert exc.value.messages == [
        ErrorMessage(
            text='The "a" field is required.',
            code='required',
            index=['a'],
            position=Position(line_no=1, column_no=1, index=0))
    ]
Exemple #9
0
def test_unterminated_string():
    with pytest.raises(ParseError) as exc:
        apistar.parse('"ab', encoding='json')

    assert exc.value.messages == [
        ErrorMessage(
            text="Unterminated string.",
            code='parse_error',
            position=Position(line_no=1, column_no=1, index=0)
        )
    ]
Exemple #10
0
def test_invalid_token():
    with pytest.raises(ParseError) as exc:
        apistar.parse('-', encoding='json')

    assert exc.value.messages == [
        ErrorMessage(
            text="Expecting value.",
            code='parse_error',
            position=Position(line_no=1, column_no=1, index=0)
        )
    ]
Exemple #11
0
def test_invalid_top_level_item():
    with pytest.raises(ValidationError) as exc:
        apistar.parse('123', encoding="json", validator=VALIDATOR)

    assert exc.value.messages == [
        ErrorMessage(
            text='Must be an object.',
            code='type',
            index=None,
            position=Position(line_no=1, column_no=1, index=0)
        )
    ]
Exemple #12
0
def _get_position(content, index):
    return Position(line_no=content.count('\n', 0, index) + 1,
                    column_no=index - content.rfind('\n', 0, index),
                    index=index)
Exemple #13
0
def tokenize_yaml(content):
    class CustomLoader(SafeLoader):
        pass

    def construct_mapping(loader, node):
        start = node.start_mark.index
        end = node.end_mark.index
        mapping = loader.construct_mapping(node)
        return DictToken(mapping, start, end - 1, content=content)

    def construct_sequence(loader, node):
        start = node.start_mark.index
        end = node.end_mark.index
        value = loader.construct_sequence(node)
        return ListToken(value, start, end - 1, content=content)

    def construct_scalar(loader, node):
        start = node.start_mark.index
        end = node.end_mark.index
        value = loader.construct_scalar(node)
        return ScalarToken(value, start, end - 1, content=content)

    def construct_int(loader, node):
        start = node.start_mark.index
        end = node.end_mark.index
        value = loader.construct_yaml_int(node)
        return ScalarToken(value, start, end - 1, content=content)

    def construct_float(loader, node):
        start = node.start_mark.index
        end = node.end_mark.index
        value = loader.construct_yaml_float(node)
        return ScalarToken(value, start, end - 1, content=content)

    def construct_bool(loader, node):
        start = node.start_mark.index
        end = node.end_mark.index
        value = loader.construct_yaml_bool(node)
        return ScalarToken(value, start, end - 1, content=content)

    def construct_null(loader, node):
        start = node.start_mark.index
        end = node.end_mark.index
        value = loader.construct_yaml_null(node)
        return ScalarToken(value, start, end - 1, content=content)

    CustomLoader.add_constructor(
        yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_mapping)

    CustomLoader.add_constructor(
        yaml.resolver.BaseResolver.DEFAULT_SEQUENCE_TAG, construct_sequence)

    CustomLoader.add_constructor(yaml.resolver.BaseResolver.DEFAULT_SCALAR_TAG,
                                 construct_scalar)

    CustomLoader.add_constructor('tag:yaml.org,2002:int', construct_int)

    CustomLoader.add_constructor('tag:yaml.org,2002:float', construct_float)

    CustomLoader.add_constructor('tag:yaml.org,2002:bool', construct_bool)

    CustomLoader.add_constructor('tag:yaml.org,2002:null', construct_null)

    assert isinstance(content, (str, bytes))

    if isinstance(content, bytes):
        content = content.decode('utf-8', 'ignore')

    if not content.strip():
        message = ErrorMessage(text='No content.',
                               code='parse_error',
                               position=Position(line_no=1,
                                                 column_no=1,
                                                 index=0))
        raise ParseError(errors=[message], summary='Invalid YAML.')

    try:
        return yaml.load(content, CustomLoader)
    except (yaml.scanner.ScannerError, yaml.parser.ParserError) as exc:
        index = getattr(exc, 'index', 0)
        message = ErrorMessage(text=exc.problem + ".",
                               code='parse_error',
                               position=_get_position(content, index=index))
        raise ParseError(messages=[message], summary='Invalid YAML.') from None
Exemple #14
0
 def _get_position(self, index):
     content = self._content[:index + 1]
     lines = content.splitlines()
     line_no = max(len(lines), 1)
     column_no = 1 if not lines else max(len(lines[-1]), 1)
     return Position(line_no, column_no, index)