mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 1428889: upgrade json-e from 2.3.2 to 2.5.0; r=bstack
MozReview-Commit-ID: FlucI8bQq4h --HG-- extra : rebase_source : 4cff4a912e33487b9f4133dae200eef051af39fd
This commit is contained in:
parent
82c77e224c
commit
a94444c14e
47
third_party/python/json-e/jsone/interpreter.py
vendored
47
third_party/python/json-e/jsone/interpreter.py
vendored
@ -1,7 +1,7 @@
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
from .prattparser import PrattParser, infix, prefix
|
||||
from .shared import TemplateError, string
|
||||
from .shared import TemplateError, InterpreterError, string
|
||||
import operator
|
||||
import json
|
||||
|
||||
@ -21,8 +21,9 @@ OPERATORS = {
|
||||
}
|
||||
|
||||
|
||||
def expectationError(operator, expected):
|
||||
return TemplateError('{} expected {}'.format(operator, expected))
|
||||
def infixExpectationError(operator, expected):
|
||||
return InterpreterError('infix: {} expects {} {} {}'.
|
||||
format(operator, expected, operator, expected))
|
||||
|
||||
|
||||
class ExpressionEvaluator(PrattParser):
|
||||
@ -44,9 +45,9 @@ class ExpressionEvaluator(PrattParser):
|
||||
'null', 'number', 'identifier', 'string',
|
||||
]
|
||||
precedence = [
|
||||
['in'],
|
||||
['||'],
|
||||
['&&'],
|
||||
['in'],
|
||||
['==', '!='],
|
||||
['>=', '<=', '<', '>'],
|
||||
['+', '-'],
|
||||
@ -80,14 +81,14 @@ class ExpressionEvaluator(PrattParser):
|
||||
def uminus(self, token, pc):
|
||||
v = pc.parse('unary')
|
||||
if not isNumber(v):
|
||||
raise expectationError('unary -', 'number')
|
||||
raise InterpreterError('{} expects {}'.format('unary -', 'number'))
|
||||
return -v
|
||||
|
||||
@prefix("+")
|
||||
def uplus(self, token, pc):
|
||||
v = pc.parse('unary')
|
||||
if not isNumber(v):
|
||||
raise expectationError('unary +', 'number')
|
||||
raise InterpreterError('{} expects {}'.format('unary +', 'number'))
|
||||
return v
|
||||
|
||||
@prefix("identifier")
|
||||
@ -95,8 +96,8 @@ class ExpressionEvaluator(PrattParser):
|
||||
try:
|
||||
return self.context[token.value]
|
||||
except KeyError:
|
||||
raise TemplateError(
|
||||
'no context value named "{}"'.format(token.value))
|
||||
raise InterpreterError(
|
||||
'unknown context value {}'.format(token.value))
|
||||
|
||||
@prefix("null")
|
||||
def null(self, token, pc):
|
||||
@ -131,23 +132,23 @@ class ExpressionEvaluator(PrattParser):
|
||||
@infix("+")
|
||||
def plus(self, left, token, pc):
|
||||
if not isinstance(left, (string, int, float)) or isinstance(left, bool):
|
||||
raise expectationError('+', 'number or string')
|
||||
raise infixExpectationError('+', 'number/string')
|
||||
right = pc.parse(token.kind)
|
||||
if not isinstance(right, (string, int, float)) or isinstance(right, bool):
|
||||
raise expectationError('+', 'number or string')
|
||||
raise infixExpectationError('+', 'number/string')
|
||||
if type(right) != type(left) and \
|
||||
(isinstance(left, string) or isinstance(right, string)):
|
||||
raise expectationError('+', 'matching types')
|
||||
raise infixExpectationError('+', 'numbers/strings')
|
||||
return left + right
|
||||
|
||||
@infix('-', '*', '/', '**')
|
||||
def arith(self, left, token, pc):
|
||||
op = token.kind
|
||||
if not isNumber(left):
|
||||
raise expectationError(op, 'number')
|
||||
raise infixExpectationError(op, 'number')
|
||||
right = pc.parse({'**': '**-right-associative'}.get(op))
|
||||
if not isNumber(right):
|
||||
raise expectationError(op, 'number')
|
||||
raise infixExpectationError(op, 'number')
|
||||
return OPERATORS[op](left, right)
|
||||
|
||||
@infix("[")
|
||||
@ -175,7 +176,7 @@ class ExpressionEvaluator(PrattParser):
|
||||
@infix(".")
|
||||
def property_dot(self, left, token, pc):
|
||||
if not isinstance(left, dict):
|
||||
raise expectationError('.', 'object')
|
||||
raise infixExpectationError('.', 'object')
|
||||
k = pc.require('identifier').value
|
||||
try:
|
||||
return left[k]
|
||||
@ -202,7 +203,7 @@ class ExpressionEvaluator(PrattParser):
|
||||
right = pc.parse(op)
|
||||
if type(left) != type(right) or \
|
||||
not (isinstance(left, (int, float, string)) and not isinstance(left, bool)):
|
||||
raise expectationError(op, 'matching types')
|
||||
raise infixExpectationError(op, 'numbers/strings')
|
||||
return OPERATORS[op](left, right)
|
||||
|
||||
@infix("in")
|
||||
@ -210,17 +211,17 @@ class ExpressionEvaluator(PrattParser):
|
||||
right = pc.parse(token.kind)
|
||||
if isinstance(right, dict):
|
||||
if not isinstance(left, string):
|
||||
raise expectationError('in-object', 'string on left side')
|
||||
raise infixExpectationError('in-object', 'string on left side')
|
||||
elif isinstance(right, string):
|
||||
if not isinstance(left, string):
|
||||
raise expectationError('in-string', 'string on left side')
|
||||
raise infixExpectationError('in-string', 'string on left side')
|
||||
elif not isinstance(right, list):
|
||||
raise expectationError(
|
||||
raise infixExpectationError(
|
||||
'in', 'Array, string, or object on right side')
|
||||
try:
|
||||
return left in right
|
||||
except TypeError:
|
||||
raise expectationError('in', 'scalar value, collection')
|
||||
raise infixExpectationError('in', 'scalar value, collection')
|
||||
|
||||
|
||||
def isNumber(v):
|
||||
@ -268,19 +269,19 @@ def accessProperty(value, a, b, is_interval):
|
||||
try:
|
||||
return value[a:b]
|
||||
except TypeError:
|
||||
raise expectationError('[..]', 'integer')
|
||||
raise infixExpectationError('[..]', 'integer')
|
||||
else:
|
||||
try:
|
||||
return value[a]
|
||||
except IndexError:
|
||||
raise TemplateError('index out of bounds')
|
||||
except TypeError:
|
||||
raise expectationError('[..]', 'integer')
|
||||
raise infixExpectationError('[..]', 'integer')
|
||||
|
||||
if not isinstance(value, dict):
|
||||
raise expectationError('[..]', 'object, array, or string')
|
||||
raise infixExpectationError('[..]', 'object, array, or string')
|
||||
if not isinstance(a, string):
|
||||
raise expectationError('[..]', 'string index')
|
||||
raise infixExpectationError('[..]', 'string index')
|
||||
|
||||
try:
|
||||
return value[a]
|
||||
|
10
third_party/python/json-e/jsone/prattparser.py
vendored
10
third_party/python/json-e/jsone/prattparser.py
vendored
@ -11,7 +11,7 @@ class SyntaxError(TemplateError):
|
||||
@classmethod
|
||||
def unexpected(cls, got, exp):
|
||||
exp = ', '.join(sorted(exp))
|
||||
return cls('Found {}, expected {}'.format(got, exp))
|
||||
return cls('Found {}, expected {}'.format(got.value, exp))
|
||||
|
||||
|
||||
Token = namedtuple('Token', ['kind', 'value', 'start', 'end'])
|
||||
@ -92,7 +92,7 @@ class PrattParser(with_metaclass(PrattParserMeta, object)):
|
||||
# if there are any tokens remaining, that's an error..
|
||||
token = pc.attempt()
|
||||
if token:
|
||||
raise SyntaxError.unexpected(token.kind, self.infix_rules)
|
||||
raise SyntaxError.unexpected(token, self.infix_rules)
|
||||
return result
|
||||
|
||||
def parseUntilTerminator(self, source, terminator):
|
||||
@ -100,7 +100,7 @@ class PrattParser(with_metaclass(PrattParserMeta, object)):
|
||||
result = pc.parse()
|
||||
token = pc.attempt()
|
||||
if token.kind != terminator:
|
||||
raise SyntaxError.unexpected(token.kind, [terminator])
|
||||
raise SyntaxError.unexpected(token, [terminator])
|
||||
return (result, token.start)
|
||||
|
||||
def _generate_tokens(self, source):
|
||||
@ -169,7 +169,7 @@ class ParseContext(object):
|
||||
if not token:
|
||||
raise SyntaxError('Unexpected end of input')
|
||||
if kinds and token.kind not in kinds:
|
||||
raise SyntaxError.unexpected(token.kind, kinds)
|
||||
raise SyntaxError.unexpected(token, kinds)
|
||||
return token
|
||||
|
||||
def parse(self, precedence=None):
|
||||
@ -178,7 +178,7 @@ class ParseContext(object):
|
||||
token = self.require()
|
||||
prefix_rule = parser.prefix_rules.get(token.kind)
|
||||
if not prefix_rule:
|
||||
raise SyntaxError.unexpected(token.kind, parser.prefix_rules)
|
||||
raise SyntaxError.unexpected(token, parser.prefix_rules)
|
||||
left = prefix_rule(parser, token, self)
|
||||
while self.next_token:
|
||||
kind = self.next_token.kind
|
||||
|
29
third_party/python/json-e/jsone/render.py
vendored
29
third_party/python/json-e/jsone/render.py
vendored
@ -72,7 +72,10 @@ def checkUndefinedProperties(template, allowed):
|
||||
|
||||
@operator('$eval')
|
||||
def eval(template, context):
|
||||
return evaluateExpression(renderValue(template['$eval'], context), context)
|
||||
checkUndefinedProperties(template, ['\$eval'])
|
||||
if not isinstance(template['$eval'], string):
|
||||
raise TemplateError("$eval must be given a string expression")
|
||||
return evaluateExpression(template['$eval'], context)
|
||||
|
||||
|
||||
@operator('$flatten')
|
||||
@ -140,21 +143,21 @@ def ifConstruct(template, context):
|
||||
def jsonConstruct(template, context):
|
||||
checkUndefinedProperties(template, ['\$json'])
|
||||
value = renderValue(template['$json'], context)
|
||||
return json.dumps(value, separators=(',', ':'))
|
||||
return json.dumps(value, separators=(',', ':'), sort_keys=True)
|
||||
|
||||
|
||||
@operator('$let')
|
||||
def let(template, context):
|
||||
checkUndefinedProperties(template, ['\$let', 'in'])
|
||||
variables = renderValue(template['$let'], context)
|
||||
if not isinstance(variables, dict):
|
||||
raise TemplateError("$let value must evaluate to an object")
|
||||
else:
|
||||
if not all(IDENTIFIER_RE.match(variableNames) for variableNames in variables.keys()):
|
||||
raise TemplateError('top level keys of $let must follow /[a-zA-Z_][a-zA-Z0-9_]*/')
|
||||
if not isinstance(template['$let'], dict):
|
||||
raise TemplateError("$let value must be an object")
|
||||
|
||||
subcontext = context.copy()
|
||||
subcontext.update(variables)
|
||||
for k, v in template['$let'].items():
|
||||
if not IDENTIFIER_RE.match(k):
|
||||
raise TemplateError('top level keys of $let must follow /[a-zA-Z_][a-zA-Z0-9_]*/')
|
||||
subcontext[k] = renderValue(v, context)
|
||||
|
||||
try:
|
||||
in_expression = template['in']
|
||||
except KeyError:
|
||||
@ -243,7 +246,7 @@ def reverse(template, context):
|
||||
checkUndefinedProperties(template, ['\$reverse'])
|
||||
value = renderValue(template['$reverse'], context)
|
||||
if not isinstance(value, list):
|
||||
raise TemplateError("$reverse value must evaluate to an array")
|
||||
raise TemplateError("$reverse value must evaluate to an array of objects")
|
||||
return list(reversed(value))
|
||||
|
||||
|
||||
@ -253,7 +256,7 @@ def sort(template, context):
|
||||
checkUndefinedProperties(template, ['\$sort', BY_RE])
|
||||
value = renderValue(template['$sort'], context)
|
||||
if not isinstance(value, list):
|
||||
raise TemplateError("$sort value must evaluate to an array")
|
||||
raise TemplateError('$sorted values to be sorted must have the same type')
|
||||
|
||||
# handle by(..) if given, applying the schwartzian transform
|
||||
by_keys = [k for k in template if k.startswith('by(')]
|
||||
@ -279,9 +282,9 @@ def sort(template, context):
|
||||
except IndexError:
|
||||
return []
|
||||
if eltype in (list, dict, bool, type(None)):
|
||||
raise TemplateError('$sort values must be sortable')
|
||||
raise TemplateError('$sorted values to be sorted must have the same type')
|
||||
if not all(isinstance(e[0], eltype) for e in to_sort):
|
||||
raise TemplateError('$sorted values must all have the same type')
|
||||
raise TemplateError('$sorted values to be sorted must have the same type')
|
||||
|
||||
# unzip the schwartzian transform
|
||||
return list(e[1] for e in sorted(to_sort))
|
||||
|
12
third_party/python/json-e/jsone/shared.py
vendored
12
third_party/python/json-e/jsone/shared.py
vendored
@ -28,6 +28,10 @@ class TemplateError(JSONTemplateError):
|
||||
pass
|
||||
|
||||
|
||||
class InterpreterError(JSONTemplateError):
|
||||
pass
|
||||
|
||||
|
||||
# Regular expression matching: X days Y hours Z minutes
|
||||
# todo: support hr, wk, yr
|
||||
FROMNOW_RE = re.compile(''.join([
|
||||
@ -109,7 +113,13 @@ def to_str(v):
|
||||
|
||||
def stringDate(date):
|
||||
# Convert to isoFormat
|
||||
string = date.isoformat()
|
||||
try:
|
||||
string = date.isoformat(timespec='microseconds')
|
||||
# py2.7 to py3.5 does not have timespec
|
||||
except TypeError as e:
|
||||
string = date.isoformat()
|
||||
if string.find('.') == -1:
|
||||
string += '.000'
|
||||
string = datefmt_re.sub(r'\1Z', string)
|
||||
return string
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user