Skip to content

Commit e2cfea0

Browse files
authored
Merge pull request #116 from django-ftl/fluent_1_syntax
Updated for fluent.syntax 0.14+ / Fluent spec 1.0
2 parents db28684 + 3475416 commit e2cfea0

File tree

8 files changed

+45
-137
lines changed

8 files changed

+45
-137
lines changed

.travis.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,23 @@ python:
1010
- "nightly"
1111
env:
1212
global:
13-
- FLUENT_RUNTIME_DEFAULT_DEPS="fluent.syntax==0.13.0 attrs==19.1.0 babel==2.6.0 pytz==2018.9 six==1.12.0"
13+
- FLUENT_RUNTIME_DEFAULT_DEPS="fluent.syntax==0.15 attrs==19.1.0 babel==2.6.0 pytz==2018.9 six==1.12.0"
1414
- FLUENT_SYNTAX_DEFAULT_DEPS="six"
1515
matrix:
1616
- PACKAGE=fluent.syntax
1717
- PACKAGE=fluent.runtime
1818
matrix:
1919
include:
20-
- name: "fluent.runtime w/ fluent.syntax==0.10"
20+
- name: "fluent.runtime w/ fluent.syntax==0.14"
2121
python: "3.6"
22-
env: PACKAGE=fluent.runtime TEST_DEPS="fluent.syntax==0.10.0 attrs==19.1.0 babel==2.6.0 pytz==2018.9 six==1.12.0"
22+
env: PACKAGE=fluent.runtime TEST_DEPS="fluent.syntax==0.14 attrs==19.1.0 babel==2.6.0 pytz==2018.9 six==1.12.0"
2323
- name: "fluent.runtime with latest everything"
2424
python: "3.6"
2525
# These are copy-pasted from setup.py
26-
env: PACKAGE=fluent.runtime TEST_DEPS="fluent.syntax>=0.10,<=0.13 attrs babel pytz six"
26+
env: PACKAGE=fluent.runtime TEST_DEPS="fluent.syntax>=0.14,<=0.16 attrs babel pytz six"
2727
allow_failures:
2828
- python: "3.6"
29-
env: PACKAGE=fluent.runtime TEST_DEPS="fluent.syntax>=0.10,<=0.13 attrs babel pytz six"
29+
env: PACKAGE=fluent.runtime TEST_DEPS="fluent.syntax>=0.14,<=0.16 attrs babel pytz six"
3030

3131
install:
3232
- if [ "$PACKAGE" = "fluent.runtime" ]; then TEST_DEPS=${TEST_DEPS:-$FLUENT_RUNTIME_DEFAULT_DEPS}; else TEST_DEPS=${TEST_DEPS:-$FLUENT_SYNTAX_DEFAULT_DEPS}; fi

fluent.runtime/fluent/runtime/resolver.py

Lines changed: 17 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ def __call__(self, env):
158158

159159
class StringLiteral(FTL.StringLiteral, Literal):
160160
def __call__(self, env):
161-
return self.value
161+
return self.parse()['value']
162162

163163

164164
class NumberLiteral(FTL.NumberLiteral, BaseResolver):
@@ -180,7 +180,14 @@ def __call__(self, env):
180180

181181
class TermReference(FTL.TermReference, BaseResolver):
182182
def __call__(self, env):
183-
with env.modified_for_term_reference():
183+
if self.arguments:
184+
if self.arguments.positional:
185+
env.errors.append(FluentFormatError("Ignored positional arguments passed to term '{0}'"
186+
.format(reference_to_id(self))))
187+
kwargs = {kwarg.name.name: kwarg.value(env) for kwarg in self.arguments.named}
188+
else:
189+
kwargs = None
190+
with env.modified_for_term_reference(args=kwargs):
184191
return lookup_reference(self, env)(env)
185192

186193

@@ -200,9 +207,9 @@ def lookup_reference(ref, env):
200207
except LookupError:
201208
env.errors.append(unknown_reference_error_obj(ref_id))
202209

203-
if isinstance(ref, AttributeExpression):
210+
if ref.attribute:
204211
# Fallback
205-
parent_id = reference_to_id(ref.ref)
212+
parent_id = reference_to_id(ref, ignore_attributes=True)
206213
try:
207214
return env.context.lookup(parent_id)
208215
except LookupError:
@@ -231,40 +238,10 @@ def __call__(self, env):
231238
return FluentNone(name)
232239

233240

234-
class AttributeExpression(FTL.AttributeExpression, BaseResolver):
235-
def __call__(self, env):
236-
return lookup_reference(self, env)(env)
237-
238-
239241
class Attribute(FTL.Attribute, BaseResolver):
240242
pass
241243

242244

243-
class VariantList(FTL.VariantList, BaseResolver):
244-
def __call__(self, env, key=None):
245-
found = None
246-
for variant in self.variants:
247-
if variant.default:
248-
default = variant
249-
if key is None:
250-
# We only want the default
251-
break
252-
253-
compare_value = variant.key(env)
254-
if match(key, compare_value, env):
255-
found = variant
256-
break
257-
258-
if found is None:
259-
if (key is not None and not isinstance(key, FluentNone)):
260-
env.errors.append(FluentReferenceError("Unknown variant: {0}"
261-
.format(key)))
262-
found = default
263-
assert found, "Not having a default variant is a parse error"
264-
265-
return found.value(env)
266-
267-
268245
class SelectExpression(FTL.SelectExpression, BaseResolver):
269246
def __call__(self, env):
270247
key = self.selector(env)
@@ -314,33 +291,15 @@ def __call__(self, env):
314291
return self.name
315292

316293

317-
class VariantExpression(FTL.VariantExpression, BaseResolver):
318-
def __call__(self, env):
319-
message = lookup_reference(self.ref, env)
320-
321-
# TODO What to do if message is not a VariantList?
322-
# Need test at least.
323-
assert isinstance(message, VariantList)
324-
325-
variant_name = self.key.name
326-
return message(env, variant_name)
294+
class CallArguments(FTL.CallArguments, BaseResolver):
295+
pass
327296

328297

329-
class CallExpression(FTL.CallExpression, BaseResolver):
298+
class FunctionReference(FTL.FunctionReference, BaseResolver):
330299
def __call__(self, env):
331-
args = [arg(env) for arg in self.positional]
332-
kwargs = {kwarg.name.name: kwarg.value(env) for kwarg in self.named}
333-
334-
if isinstance(self.callee, (TermReference, AttributeExpression)):
335-
term = lookup_reference(self.callee, env)
336-
if args:
337-
env.errors.append(FluentFormatError("Ignored positional arguments passed to term '{0}'"
338-
.format(reference_to_id(self.callee))))
339-
with env.modified_for_term_reference(args=kwargs):
340-
return term(env)
341-
342-
# builtin or custom function call
343-
function_name = self.callee.id.name
300+
args = [arg(env) for arg in self.arguments.positional]
301+
kwargs = {kwarg.name.name: kwarg.value(env) for kwarg in self.arguments.named}
302+
function_name = self.id.name
344303
try:
345304
function = env.context._functions[function_name]
346305
except LookupError:

fluent.runtime/fluent/runtime/utils.py

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from datetime import date, datetime
44
from decimal import Decimal
55

6-
from fluent.syntax.ast import AttributeExpression, Term, TermReference
6+
from fluent.syntax.ast import Term, TermReference
77

88
from .types import FluentInt, FluentFloat, FluentDecimal, FluentDate, FluentDateTime
99
from .errors import FluentReferenceError
@@ -39,9 +39,9 @@ def native_to_fluent(val):
3939
return val
4040

4141

42-
def reference_to_id(ref):
42+
def reference_to_id(ref, ignore_attributes=False):
4343
"""
44-
Returns a string reference for a MessageReference, TermReference or AttributeExpression
44+
Returns a string reference for a MessageReference or TermReference
4545
AST node.
4646
4747
e.g.
@@ -50,12 +50,14 @@ def reference_to_id(ref):
5050
-term
5151
-term.attr
5252
"""
53-
if isinstance(ref, AttributeExpression):
54-
return _make_attr_id(reference_to_id(ref.ref),
55-
ref.name.name)
5653
if isinstance(ref, TermReference):
57-
return TERM_SIGIL + ref.id.name
58-
return ref.id.name
54+
start = TERM_SIGIL + ref.id.name
55+
else:
56+
start = ref.id.name
57+
58+
if not ignore_attributes and ref.attribute:
59+
return ''.join([start, ATTRIBUTE_SEPARATOR, ref.attribute.name])
60+
return start
5961

6062

6163
def unknown_reference_error_obj(ref_id):
@@ -64,10 +66,3 @@ def unknown_reference_error_obj(ref_id):
6466
if ref_id.startswith(TERM_SIGIL):
6567
return FluentReferenceError("Unknown term: {0}".format(ref_id))
6668
return FluentReferenceError("Unknown message: {0}".format(ref_id))
67-
68-
69-
def _make_attr_id(parent_ref_id, attr_name):
70-
"""
71-
Given a parent id and the attribute name, return the attribute id
72-
"""
73-
return ''.join([parent_ref_id, ATTRIBUTE_SEPARATOR, attr_name])

fluent.runtime/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
packages=['fluent', 'fluent.runtime'],
2222
# These should also be duplicated in tox.ini and ../.travis.yml
2323
install_requires=[
24-
'fluent.syntax>=0.10,<=0.13',
24+
'fluent.syntax>=0.14,<=0.16',
2525
'attrs',
2626
'babel',
2727
'pytz',

fluent.runtime/tests/format/test_placeables.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ def setUp(self):
2424
uses-message = { message }
2525
uses-message-attr = { message.attr }
2626
uses-term = { -term }
27-
uses-term-variant = { -term2[variant2] }
2827
2928
bad-message-ref = Text { not-a-message }
3029
bad-message-attr-ref = Text { message.not-an-attr }
@@ -57,11 +56,6 @@ def test_placeable_term(self):
5756
self.assertEqual(val, 'Term')
5857
self.assertEqual(len(errs), 0)
5958

60-
def test_placeable_term_variant(self):
61-
val, errs = self.ctx.format('uses-term-variant', {})
62-
self.assertEqual(val, 'Term Variant 2')
63-
self.assertEqual(len(errs), 0)
64-
6559
def test_placeable_bad_message(self):
6660
val, errs = self.ctx.format('bad-message-ref', {})
6761
self.assertEqual(val, 'Text not-a-message')

fluent.runtime/tests/format/test_primitives.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: utf-8 -*-
12
from __future__ import absolute_import, unicode_literals
23

34
import unittest
@@ -10,7 +11,7 @@
1011
class TestSimpleStringValue(unittest.TestCase):
1112
def setUp(self):
1213
self.ctx = FluentBundle(['en-US'], use_isolating=False)
13-
self.ctx.add_messages(dedent_ftl("""
14+
self.ctx.add_messages(dedent_ftl(r"""
1415
foo = Foo
1516
placeable-literal = { "Foo" } Bar
1617
placeable-message = { foo } Bar
@@ -27,6 +28,7 @@ def setUp(self):
2728
[BazAttribute] Member 3
2829
*[other] Member 4
2930
}
31+
escapes = {" "}stuff{"\u0258}\"\\end"}
3032
"""))
3133

3234
def test_can_be_used_as_a_value(self):
@@ -64,6 +66,11 @@ def test_can_be_a_value_of_an_attribute_used_as_a_selector(self):
6466
self.assertEqual(val, 'Member 3')
6567
self.assertEqual(len(errs), 0)
6668

69+
def test_escapes(self):
70+
val, errs = self.ctx.format('escapes', {})
71+
self.assertEqual(val, r' stuffɘ}"\end')
72+
self.assertEqual(len(errs), 0)
73+
6774

6875
class TestComplexStringValue(unittest.TestCase):
6976
def setUp(self):

fluent.runtime/tests/format/test_variants.py

Lines changed: 0 additions & 47 deletions
This file was deleted.

fluent.runtime/tox.ini

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# This config is for local testing. It should be duplicated into .travis.yml
22
[tox]
3-
envlist = {py27,py35,py36,py37,pypy,pypy3}-syntax0.13, py36-syntax0.10, latest
3+
envlist = {py27,py35,py36,py37,pypy,pypy3}-syntax0.15, py36-syntax0.14, latest
44
skipsdist=True
55

66
[testenv]
77
setenv =
88
PYTHONPATH = {toxinidir}
99
deps =
10-
syntax0.10: fluent.syntax==0.10.0
11-
syntax0.13: fluent.syntax==0.13.0
10+
syntax0.15: fluent.syntax==0.15
11+
syntax0.14: fluent.syntax==0.14
1212
attrs==19.1.0
1313
babel==2.6.0
1414
pytz==2018.9
@@ -22,7 +22,7 @@ deps =
2222
# It's tempting to use '.' here to get 'pip install .'
2323
# Unfortunately it is super slow: https://github.com/pypa/pip/issues/2195
2424
# Instead we copy-paste from setup.py
25-
fluent.syntax>=0.10,<=0.13
25+
fluent.syntax>=0.14,<=0.16
2626
attrs
2727
babel
2828
pytz

0 commit comments

Comments
 (0)