Skip to content

Commit 5f6ab74

Browse files
committed
Align FluentBundle API with Fluent, add FluentResource, remove add_messages.
1 parent 159ad1a commit 5f6ab74

15 files changed

+154
-137
lines changed

fluent.runtime/CHANGELOG.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Changelog
22
=========
33

4+
fluent.runtime next
5+
-------------------
6+
7+
* Added ``fluent.runtime.FluentResource`` and
8+
``fluent.runtime.FluentBundle.add_resource``.
9+
* Removed ``fluent.runtime.FluentBundle.add_messages``.
10+
411
fluent.runtime 0.2 (September 10, 2019)
512
---------------------------------------
613

fluent.runtime/docs/usage.rst

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Once you have some FTL files, you can generate translations using the
2727

2828
.. code-block:: python
2929
30-
>>> from fluent.runtime import FluentBundle
30+
>>> from fluent.runtime import FluentBundle, FluentResource
3131
3232
You pass a list of locales to the constructor - the first being the
3333
desired locale, with fallbacks after that:
@@ -41,10 +41,11 @@ file stored on disk, here we will just add them directly:
4141

4242
.. code-block:: python
4343
44-
>>> bundle.add_messages("""
44+
>>> resource = FluentResource("""
4545
... welcome = Welcome to this great app!
4646
... greet-by-name = Hello, { $name }!
4747
... """)
48+
>>> bundle.add_resource(resource
4849
4950
To generate translations, use the ``format`` method, passing a message
5051
ID and an optional dictionary of substitution parameters. If the the
@@ -101,7 +102,9 @@ When rendering translations, Fluent passes any numeric arguments (``int``,
101102
102103
.. code-block:: python
103104
104-
>>> bundle.add_messages("show-total-points = You have { $points } points.")
105+
>>> bundle.add_resource(FluentResource(
106+
... "show-total-points = You have { $points } points."
107+
... ))
105108
>>> val, errs = bundle.format("show-total-points", {'points': 1234567})
106109
>>> val
107110
'You have 1,234,567 points.'
@@ -118,7 +121,9 @@ by wrapping your numeric arguments with
118121
'You have 1234567 points.'
119122
120123
>>> amount = fluent_number(1234.56, style="currency", currency="USD")
121-
>>> bundle.add_messages("your-balance = Your balance is { $amount }")
124+
>>> bundle.add_resource(FluentResource(
125+
... "your-balance = Your balance is { $amount }"
126+
... ))
122127
>>> bundle.format("your-balance", {'amount': amount})[0]
123128
'Your balance is $1,234.56'
124129
@@ -136,7 +141,7 @@ passed through locale aware functions:
136141
.. code-block:: python
137142
138143
>>> from datetime import date
139-
>>> bundle.add_messages("today-is = Today is { $today }")
144+
>>> bundle.add_resource(FluentResource("today-is = Today is { $today }"))
140145
>>> val, errs = bundle.format("today-is", {"today": date.today() })
141146
>>> val
142147
'Today is Jun 16, 2018'
@@ -145,7 +150,9 @@ You can explicitly call the ``DATETIME`` builtin to specify options:
145150
146151
.. code-block:: python
147152
148-
>>> bundle.add_messages('today-is = Today is { DATETIME($today, dateStyle: "short") }')
153+
>>> bundle.add_resource(FluentResource(
154+
... 'today-is = Today is { DATETIME($today, dateStyle: "short") }'
155+
... ))
149156
150157
See the `DATETIME
151158
docs <https://projectfluent.org/fluent/guide/functions.html#datetime>`_.
@@ -193,7 +200,7 @@ ways:
193200
>>> utcnow
194201
datetime.datetime(2018, 6, 17, 12, 15, 5, 677597)
195202
196-
>>> bundle.add_messages("now-is = Now is { $now }")
203+
>>> bundle.add_resource(FluentResource("now-is = Now is { $now }"))
197204
>>> val, errs = bundle.format("now-is",
198205
... {"now": fluent_date(utcnow,
199206
... timeZone="Europe/Moscow",
@@ -218,14 +225,14 @@ You can add functions to the ones available to FTL authors by passing a
218225
... 'Windows': 'windows'}.get(platform.system(), 'other')
219226
220227
>>> bundle = FluentBundle(['en-US'], functions={'OS': os_name})
221-
>>> bundle.add_messages("""
228+
>>> bundle.add_resource(FluentResource("""
222229
... welcome = { OS() ->
223230
... [linux] Welcome to Linux
224231
... [mac] Welcome to Mac
225232
... [windows] Welcome to Windows
226233
... *[other] Welcome
227234
... }
228-
... """)
235+
... """))
229236
>>> print(bundle.format('welcome')[0]
230237
Welcome to Linux
231238

fluent.runtime/fluent/runtime/__init__.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
from .utils import ATTRIBUTE_SEPARATOR, TERM_SIGIL, ast_to_id, native_to_fluent
1414

1515

16+
def FluentResource(source):
17+
parser = FluentParser()
18+
return parser.parse(source)
19+
20+
1621
class FluentBundle(object):
1722
"""
1823
Message contexts are single-language stores of translations. They are
@@ -39,14 +44,12 @@ def __init__(self, locales, functions=None, use_isolating=True):
3944
self._babel_locale = self._get_babel_locale()
4045
self._plural_form = babel.plural.to_python(self._babel_locale.plural_form)
4146

42-
def add_messages(self, source):
43-
parser = FluentParser()
44-
resource = parser.parse(source)
47+
def add_resource(self, resource, allow_overrides=False):
4548
# TODO - warn/error about duplicates
4649
for item in resource.body:
4750
if isinstance(item, (Message, Term)):
4851
full_id = ast_to_id(item)
49-
if full_id not in self._messages_and_terms:
52+
if full_id not in self._messages_and_terms or allow_overrides:
5053
self._messages_and_terms[full_id] = item
5154

5255
def has_message(self, message_id):

fluent.runtime/tests/format/test_arguments.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,23 @@
22

33
import unittest
44

5-
from fluent.runtime import FluentBundle
5+
from fluent.runtime import FluentBundle, FluentResource
66

77
from ..utils import dedent_ftl
88

99

1010
class TestNumbersInValues(unittest.TestCase):
1111
def setUp(self):
1212
self.ctx = FluentBundle(['en-US'], use_isolating=False)
13-
self.ctx.add_messages(dedent_ftl("""
13+
self.ctx.add_resource(FluentResource(dedent_ftl("""
1414
foo = Foo { $num }
1515
bar = { foo }
1616
baz =
1717
.attr = Baz Attribute { $num }
1818
qux = { "a" ->
1919
*[a] Baz Variant A { $num }
2020
}
21-
"""))
21+
""")))
2222

2323
def test_can_be_used_in_the_message_value(self):
2424
val, errs = self.ctx.format('foo', {'num': 3})
@@ -44,9 +44,9 @@ def test_can_be_used_in_a_variant(self):
4444
class TestStrings(unittest.TestCase):
4545
def setUp(self):
4646
self.ctx = FluentBundle(['en-US'], use_isolating=False)
47-
self.ctx.add_messages(dedent_ftl("""
47+
self.ctx.add_resource(FluentResource(dedent_ftl("""
4848
foo = { $arg }
49-
"""))
49+
""")))
5050

5151
def test_can_be_a_string(self):
5252
val, errs = self.ctx.format('foo', {'arg': 'Argument'})

fluent.runtime/tests/format/test_attributes.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import unittest
44

5-
from fluent.runtime import FluentBundle
5+
from fluent.runtime import FluentBundle, FluentResource
66
from fluent.runtime.errors import FluentReferenceError
77

88
from ..utils import dedent_ftl
@@ -12,14 +12,14 @@ class TestAttributesWithStringValues(unittest.TestCase):
1212

1313
def setUp(self):
1414
self.ctx = FluentBundle(['en-US'], use_isolating=False)
15-
self.ctx.add_messages(dedent_ftl("""
15+
self.ctx.add_resource(FluentResource(dedent_ftl("""
1616
foo = Foo
1717
.attr = Foo Attribute
1818
bar = { foo } Bar
1919
.attr = Bar Attribute
2020
ref-foo = { foo.attr }
2121
ref-bar = { bar.attr }
22-
"""))
22+
""")))
2323

2424
def test_can_be_referenced_for_entities_with_string_values(self):
2525
val, errs = self.ctx.format('ref-foo', {})
@@ -46,7 +46,7 @@ class TestAttributesWithSimplePatternValues(unittest.TestCase):
4646

4747
def setUp(self):
4848
self.ctx = FluentBundle(['en-US'], use_isolating=False)
49-
self.ctx.add_messages(dedent_ftl("""
49+
self.ctx.add_resource(FluentResource(dedent_ftl("""
5050
foo = Foo
5151
bar = Bar
5252
.attr = { foo } Attribute
@@ -57,7 +57,7 @@ def setUp(self):
5757
ref-bar = { bar.attr }
5858
ref-baz = { baz.attr }
5959
ref-qux = { qux.attr }
60-
"""))
60+
""")))
6161

6262
def test_can_be_referenced_for_entities_with_string_values(self):
6363
val, errs = self.ctx.format('ref-bar', {})
@@ -93,7 +93,7 @@ def test_works_with_self_references_direct(self):
9393
class TestMissing(unittest.TestCase):
9494
def setUp(self):
9595
self.ctx = FluentBundle(['en-US'], use_isolating=False)
96-
self.ctx.add_messages(dedent_ftl("""
96+
self.ctx.add_resource(FluentResource(dedent_ftl("""
9797
foo = Foo
9898
bar = Bar
9999
.attr = Bar Attribute
@@ -107,7 +107,7 @@ def setUp(self):
107107
attr-only =
108108
.attr = Attr Only Attribute
109109
ref-double-missing = { missing.attr }
110-
"""))
110+
""")))
111111

112112
def test_falls_back_for_msg_with_string_value_and_no_attributes(self):
113113
val, errs = self.ctx.format('ref-foo', {})

fluent.runtime/tests/format/test_builtins.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from datetime import date, datetime
55
from decimal import Decimal
66

7-
from fluent.runtime import FluentBundle
7+
from fluent.runtime import FluentBundle, FluentResource
88
from fluent.runtime.errors import FluentReferenceError
99
from fluent.runtime.types import fluent_date, fluent_number
1010

@@ -15,15 +15,15 @@ class TestNumberBuiltin(unittest.TestCase):
1515

1616
def setUp(self):
1717
self.ctx = FluentBundle(['en-US'], use_isolating=False)
18-
self.ctx.add_messages(dedent_ftl("""
18+
self.ctx.add_resource(FluentResource(dedent_ftl("""
1919
implicit-call = { 123456 }
2020
implicit-call2 = { $arg }
2121
defaults = { NUMBER(123456) }
2222
percent-style = { NUMBER(1.234, style: "percent") }
2323
currency-style = { NUMBER(123456, style: "currency", currency: "USD") }
2424
from-arg = { NUMBER($arg) }
2525
merge-params = { NUMBER($arg, useGrouping: 0) }
26-
"""))
26+
""")))
2727

2828
def test_implicit_call(self):
2929
val, errs = self.ctx.format('implicit-call', {})
@@ -100,11 +100,11 @@ class TestDatetimeBuiltin(unittest.TestCase):
100100

101101
def setUp(self):
102102
self.ctx = FluentBundle(['en-US'], use_isolating=False)
103-
self.ctx.add_messages(dedent_ftl("""
103+
self.ctx.add_resource(FluentResource(dedent_ftl("""
104104
implicit-call = { $date }
105105
explicit-call = { DATETIME($date) }
106106
call-with-arg = { DATETIME($date, dateStyle: "long") }
107-
"""))
107+
""")))
108108

109109
def test_implicit_call_date(self):
110110
val, errs = self.ctx.format('implicit-call', {'date': date(2018, 2, 1)})

fluent.runtime/tests/format/test_functions.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import unittest
44

5-
from fluent.runtime import FluentBundle
5+
from fluent.runtime import FluentBundle, FluentResource
66
from fluent.runtime.errors import FluentReferenceError
77
from fluent.runtime.types import FluentNone
88

@@ -14,7 +14,7 @@ class TestFunctionCalls(unittest.TestCase):
1414
def setUp(self):
1515
self.ctx = FluentBundle(['en-US'], use_isolating=False,
1616
functions={'IDENTITY': lambda x: x})
17-
self.ctx.add_messages(dedent_ftl("""
17+
self.ctx.add_resource(FluentResource(dedent_ftl("""
1818
foo = Foo
1919
.attr = Attribute
2020
pass-nothing = { IDENTITY() }
@@ -24,7 +24,7 @@ def setUp(self):
2424
pass-attr = { IDENTITY(foo.attr) }
2525
pass-external = { IDENTITY($ext) }
2626
pass-function-call = { IDENTITY(IDENTITY(1)) }
27-
"""))
27+
""")))
2828

2929
def test_accepts_strings(self):
3030
val, errs = self.ctx.format('pass-string', {})
@@ -67,9 +67,9 @@ class TestMissing(unittest.TestCase):
6767

6868
def setUp(self):
6969
self.ctx = FluentBundle(['en-US'], use_isolating=False)
70-
self.ctx.add_messages(dedent_ftl("""
70+
self.ctx.add_resource(FluentResource(dedent_ftl("""
7171
missing = { MISSING(1) }
72-
"""))
72+
""")))
7373

7474
def test_falls_back_to_name_of_function(self):
7575
val, errs = self.ctx.format("missing", {})
@@ -91,10 +91,10 @@ def number_processor(number):
9191
functions={'NUMBER_PROCESSOR':
9292
number_processor})
9393

94-
self.ctx.add_messages(dedent_ftl("""
94+
self.ctx.add_resource(FluentResource(dedent_ftl("""
9595
pass-number = { NUMBER_PROCESSOR(1) }
9696
pass-arg = { NUMBER_PROCESSOR($arg) }
97-
"""))
97+
""")))
9898

9999
def test_args_passed_as_numbers(self):
100100
val, errs = self.ctx.format('pass-arg', {'arg': 1})
@@ -120,13 +120,13 @@ def my_function(arg, kwarg1=None, kwarg2="default"):
120120

121121
self.ctx = FluentBundle(['en-US'], use_isolating=False,
122122
functions={'MYFUNC': my_function})
123-
self.ctx.add_messages(dedent_ftl("""
123+
self.ctx.add_resource(FluentResource(dedent_ftl("""
124124
pass-arg = { MYFUNC("a") }
125125
pass-kwarg1 = { MYFUNC("a", kwarg1: 1) }
126126
pass-kwarg2 = { MYFUNC("a", kwarg2: "other") }
127127
pass-kwargs = { MYFUNC("a", kwarg1: 1, kwarg2: "other") }
128128
pass-user-arg = { MYFUNC($arg) }
129-
"""))
129+
""")))
130130

131131
def test_defaults(self):
132132
val, errs = self.ctx.format('pass-arg', {})

fluent.runtime/tests/format/test_isolating.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import unittest
44

5-
from fluent.runtime import FluentBundle
5+
from fluent.runtime import FluentBundle, FluentResource
66

77
from ..utils import dedent_ftl
88

@@ -15,12 +15,12 @@ class TestUseIsolating(unittest.TestCase):
1515

1616
def setUp(self):
1717
self.ctx = FluentBundle(['en-US'])
18-
self.ctx.add_messages(dedent_ftl("""
18+
self.ctx.add_resource(FluentResource(dedent_ftl("""
1919
foo = Foo
2020
bar = { foo } Bar
2121
baz = { $arg } Baz
2222
qux = { bar } { baz }
23-
"""))
23+
""")))
2424

2525
def test_isolates_interpolated_message_references(self):
2626
val, errs = self.ctx.format('bar', {})
@@ -49,11 +49,11 @@ class TestSkipIsolating(unittest.TestCase):
4949

5050
def setUp(self):
5151
self.ctx = FluentBundle(['en-US'])
52-
self.ctx.add_messages(dedent_ftl("""
52+
self.ctx.add_resource(FluentResource(dedent_ftl("""
5353
-brand-short-name = Amaya
5454
foo = { -brand-short-name }
5555
with-arg = { $arg }
56-
"""))
56+
""")))
5757

5858
def test_skip_isolating_chars_if_just_one_message_ref(self):
5959
val, errs = self.ctx.format('foo', {})

0 commit comments

Comments
 (0)