-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update fluent.runtime for fluent.syntax 0.10 #88
Update fluent.runtime for fluent.syntax 0.10 #88
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gave this a bit of a read, but I'd prefer stas to make the actual review.
Some notes: I did check for some performance problems that I spotted on the compiler branch (the args check in resolve
), that's not here, so that's good :-)
I prefer no else after return. Sometimes the code does it, sometimes not, let's be consistent about that.
I'd prefer the context manager and the sub-state to be explicit about "Variables in TermReferences". Make it non-generic? Took me a while to understand that that is what it's doing, and that it's doing only that.
I'm not fond of the serialize-to-rich-ID-and-parse-it-right-after for Term/Message/Attribute references.
I have to admit that I didn't look at the tests at all. Also something I defer to someone that wrote a resolver ;-)
Yep, one of the issues here was that I was backporting some code and some ways of doing things from later branches where they make more sense. With regard to the first point you made, the 'current environment' concept does come in useful for other features, so it does seem more generic than for just term args. Perhaps it would help if there were comments on each element describing why if is needed? It seems like a waste to change it if I've got a good idea I'm going to change it back again later. With the second point, I'll backport the rest of the changes which make the 'rich ID' more useful in several ways, which should clean up that ugly parsing of the rich ID you pointed out. |
This has the result of performance optimization in a number of places, because we don't need to traverse attributes each time (with probably a very small startup cost), and simplifying quite a bit of logic. Also, tests for the corner cases found by looking at code coverage for the changes, and cleanups of places that were handling message IDs
bc1eaf6
to
59292d6
Compare
@Pike - hopefully I've addressed most of the things you highlighted with my latest changes. There are more things in In addition there is now b8aa39d which is both an optimization and a code cleanup. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great, thanks @spookylukey. The code looks good to land, but I'd like to ask for two more test suites and I'd like to take a look at them before merging.
The first test suite should test that terms referenced within other terms always start with fresh args
.
-foo = Foo is {$arg}
-bar = {-foo(arg: $arg)}
-baz = {-foo}
ref-bar = {-bar(arg: 1)}
ref-baz = {-bar(arg: 1)}
In the example above, ref-bar
should format to 1
without erros while ref-baz
should format to Foo is arg
because arg
hasn't been explicitly passed to -foo
. This raises an interesting question about whether that should be an error or not. I think the current behavior of not reporting the error is OK to land, but I've take note of this and I'll try to come up with a solution in the spec.
In the second test suite, we should verify that messages referenced from within terms don't have access to external args.
msg = Msg is {$arg}
-foo = {msg}
ref-foo = {-foo(arg: 1)}
In this snippet, ref-foo
should format to Msg is 1
even if format
received external args of {'arg': 2}
. This might be surprising, and perhaps we should forbid referencing messages from within terms in the future completely. For now however, this behavior adheres to the rule of creating fresh args
for each TermReference
and using it throughout its resolution.
fluent.runtime/setup.py
Outdated
@@ -26,7 +26,7 @@ | |||
], | |||
packages=['fluent', 'fluent.runtime'], | |||
install_requires=[ | |||
'fluent>=0.9,<0.10', | |||
'fluent.syntax>=0.10', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be a good idea to add an upper bound here as well. Syntax 0.9 will make a few changes to the AST (nothing extreme) which will likely break the resolver written against Syntax 0.8 (implemented by fluent.syntax
0.10).
if isinstance(ref, AttributeExpression): | ||
return _make_attr_id(reference_to_id(ref.ref), | ||
ref.name.name) | ||
return (TERM_SIGIL if isinstance(ref, TermReference) else '') + ref.id.name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit (not blocking): Perhaps start with the if
here, similar to how you check for AttributeExpression
? And the same in ast_to_id
. unknown_reference_error_obj
already does this.
fluent.runtime/tox.ini
Outdated
@@ -6,7 +6,7 @@ skipsdist=True | |||
setenv = | |||
PYTHONPATH = {toxinidir} | |||
deps = | |||
fluent>=0.9,<0.10 | |||
fluent>=0.10 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this read fluent.syntax
? And again, it might be a good idea to specify the upper bound.
# The '-thing' term should not get passed article="indefinite" | ||
val, errs = self.ctx.format('thing-no-arg', {'article': 'indefinite'}) | ||
self.assertEqual(val, 'the thing') | ||
self.assertEqual(errs, []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a third variant to -thing
for when no article is needed, [none] thing
, and add a test similar to this one? Something like:
def test_no_implicit_access_to_external_args_but_term_args_still_passed(self):
val, errs = self.ctx.format('thing-with-arg', {'article': 'other'})
self.assertEqual(val, 'a thing')
def test_inner_arg(self): | ||
val, errs = self.ctx.format('inner-arg', {}) | ||
self.assertEqual(val, 'The thing.') | ||
self.assertEqual(errs, []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a test similar to TestParameterizedTerms.test_no_implicit_access_to_external_args
which verifies that the args passed to the term replace external args fully, rather than be merged with them.
def test_inner_arg_with_external_args(self):
val, errs = self.ctx.format('inner-arg', {'article': 'indefinite'})
self.assertEqual(val, 'The thing.')
I have two extra comments about the rich-id logic. They don't block this PR. A consequence of the rich-id approach is that by storing the attributes separately from the messages they belong to, it forces any formatting API to be a pull API. What I mean by that is that the consumer of the library needs to know exactly the names of the attributes they request. I think this is fine for That said, I expect the rich-id logic to go away when we implement Syntax 0.9. If I understand correctly, it's currently used as way to simplify the handling of Thanks again! |
Is the definition of
This also appears to be following the spec correctly - named arguments can be only number or string literals: |
Ah, my bad, you're right of course. That's projectfluent/fluent#230 (which I just filed because the original issue, 188, used outdated syntax and nomenclature). We'll consider extending the syntax to allow How about this test? -foo = {$a} {$b}
-bar = {-foo(b: 2)}
-baz = {-foo}
ref-bar = {-bar(a: 1)}
ref-baz = {-baz(a: 1)}
|
I think that's address everything you mentioned now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, LGTM.
Fixes #86