Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
Next Release (TBD)
==================

* No changes yet.
* Fix ``end`` position offset for quoted identifier, literal, and raw string
literal tokens
(`issue #380 <https://github.com/jmespath/jmespath.py/issues/380>`__)


1.1.0
Expand Down
6 changes: 3 additions & 3 deletions jmespath/lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,15 @@ def _consume_literal(self):
message="Bad token %s" % lexeme)
token_len = self._position - start
return {'type': 'literal', 'value': parsed_json,
'start': start, 'end': token_len}
'start': start, 'end': start + token_len}

def _consume_quoted_identifier(self):
start = self._position
lexeme = '"' + self._consume_until('"') + '"'
try:
token_len = self._position - start
return {'type': 'quoted_identifier', 'value': loads(lexeme),
'start': start, 'end': token_len}
'start': start, 'end': start + token_len}
except ValueError as e:
error_message = str(e).split(':')[0]
raise LexerError(lexer_position=start,
Expand All @@ -194,7 +194,7 @@ def _consume_raw_string_literal(self):
lexeme = self._consume_until("'").replace("\\'", "'")
token_len = self._position - start
return {'type': 'literal', 'value': lexeme,
'start': start, 'end': token_len}
'start': start, 'end': start + token_len}

def _match_or_else(self, expected, match_type, else_type):
start = self._position
Expand Down
21 changes: 21 additions & 0 deletions tests/test_lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,27 @@ def test_position_multiple_tokens(self):
]
)

def test_position_quoted_identifier(self):
tokens = list(self.lexer.tokenize('foo."q"'))
quoted = [t for t in tokens if t['type'] == 'quoted_identifier'][0]
self.assertEqual(quoted['start'], 4)
self.assertEqual(quoted['end'], 6)
self.assertGreaterEqual(quoted['end'], quoted['start'])

def test_position_literal_not_at_start(self):
tokens = list(self.lexer.tokenize('foo.`123`'))
literal = [t for t in tokens if t['type'] == 'literal'][0]
self.assertEqual(literal['start'], 4)
self.assertEqual(literal['end'], 8)
self.assertGreaterEqual(literal['end'], literal['start'])

def test_position_raw_string_not_at_start(self):
tokens = list(self.lexer.tokenize("foo.'bar'"))
literal = [t for t in tokens if t['type'] == 'literal'][0]
self.assertEqual(literal['start'], 4)
self.assertEqual(literal['end'], 8)
self.assertGreaterEqual(literal['end'], literal['start'])

def test_adds_quotes_when_invalid_json(self):
tokens = list(self.lexer.tokenize('`{{}`'))
self.assertEqual(
Expand Down