Skip to content
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

Make Funsor compatible with Python 3.5 #329

Merged
merged 19 commits into from
Jul 12, 2020
Merged

Make Funsor compatible with Python 3.5 #329

merged 19 commits into from
Jul 12, 2020

Conversation

eb8680
Copy link
Member

@eb8680 eb8680 commented May 12, 2020

Necessary for use with Pyro, which supports Python 3.5 and uses it in Travis.

As far as I can tell, this PR contains all of the changes necessary to support Python 3.5 - I couldn't find any lurking order dependence in the obvious places, especially the distribution wrappers. The only substantive issue I found and fixed was caused by a mysterious nondeterministic edge case in multipledispatch, perhaps related to #243. Otherwise, most of the changes are either removals of f-strings or replacements of dictionaries with OrderedDicts in test case lists to make pytest test collection deterministic.

@eb8680 eb8680 added bug Something isn't working WIP testing labels May 12, 2020
@fritzo
Copy link
Member

fritzo commented May 12, 2020

bye bye f-strings 😢

@fritzo
Copy link
Member

fritzo commented May 12, 2020

This is going to be a significant review effort because we have started using the ordered dictionary assumption, but Python 3.5 doesn't follow ordered dictionary semantics. I think we'll need to replace dict with OrderedDict in many places.

@eb8680
Copy link
Member Author

eb8680 commented May 12, 2020

we have started using the ordered dictionary assumption

I think it's mostly confined to the tests and perhaps to funsor.distributions, hopefully we can fix the obvious cases here and deal with others as they come up.

@eb8680 eb8680 reopened this Jul 11, 2020
@eb8680 eb8680 requested a review from fritzo July 11, 2020 23:48
Copy link
Member

@fritzo fritzo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. Only minor comments.

Could we spend an hour or so poking around code and discussing issues to convince each other that all determinism issues are resolved? We can do that after this PR merges. The goal of this PR is unusual in that it is difficult to verify by reviewing a diff on github; rather I'd like to search the full Funsor codebase for possible sources of nondeterminism.

setup.py Show resolved Hide resolved
Comment on lines +210 to +220
OrderedDict(),
OrderedDict([('i', bint(2))]),
OrderedDict([('i', bint(2)), ('j', bint(3))]),
], ids=id_from_inputs)
@pytest.mark.parametrize('real_inputs', [
{'x': reals()},
{'x': reals(4)},
{'x': reals(2, 3)},
{'x': reals(), 'y': reals()},
{'x': reals(2), 'y': reals(3)},
{'x': reals(4), 'y': reals(2, 3), 'z': reals()},
OrderedDict([('x', reals())]),
OrderedDict([('x', reals(4))]),
OrderedDict([('x', reals(2, 3))]),
OrderedDict([('x', reals()), ('y', reals())]),
OrderedDict([('x', reals(2)), ('y', reals(3))]),
OrderedDict([('x', reals(4)), ('y', reals(2, 3)), ('z', reals())]),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think we can revert these changes. I had set this test up so that we could write concise {}-dicts in the param statements, then convert them to OrderedDict via OrderedDict(list(sorted(xxx.items()))) below. I think this is still nice to do for readability.

Please let me know if I've misunderstand some issue with pytest collection and the OrderedDict change is required.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OrderedDict changes to test parameters in this PR are required for using pytest-xdist. Otherwise, test collection will fail with multiple workers.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining! I'll avoid this pattern in the future.

test/test_gaussian.py Show resolved Hide resolved
@@ -45,6 +45,11 @@
np.seterr(all='ignore')


# have to make this deterministic for pytest collection to work
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain the type of error you saw, so I can keep an eye out for similar errors in the future?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pytest-xdist seems to require all workers to have identical test cases that appear in the same order. Some test cases in this file are generated by looping over the keys of REDUCE_OP_TO_NUMERIC, which is a dictionary. If you revert this change and attempt to run the tests in Python 3.5 with multiple workers (pytest -n auto), test collection will nondeterministically fail because workers may not agree.

if objects != types and supercedes(types, objects):
register(*objects)(self.default)
except TypeError:
pass # mysterious source of ambiguity in Python 3.5 breaks this
Copy link
Member Author

@eb8680 eb8680 Jul 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only significant change in this PR. It places stricter constraints on method resolution order in multiple dispatch in cases that could be ambiguous, and otherwise has no effect. If this is reverted, attempting to run the test suite in Python 3.5 will lead to a bunch of strange, nondeterministic and difficult-to-diagnose test failures ultimately caused by patterns not firing when they ought to.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird. Do you know whether the Type error occurs in !=, supercedes(), and, or register()()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding supercedes here fixes the test failures, but introduces occasional TypeErrors which can be disregarded.

Copy link
Member

@fritzo fritzo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing these issues!

if objects != types and supercedes(types, objects):
register(*objects)(self.default)
except TypeError:
pass # mysterious source of ambiguity in Python 3.5 breaks this
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird. Do you know whether the Type error occurs in !=, supercedes(), and, or register()()?

Comment on lines +210 to +220
OrderedDict(),
OrderedDict([('i', bint(2))]),
OrderedDict([('i', bint(2)), ('j', bint(3))]),
], ids=id_from_inputs)
@pytest.mark.parametrize('real_inputs', [
{'x': reals()},
{'x': reals(4)},
{'x': reals(2, 3)},
{'x': reals(), 'y': reals()},
{'x': reals(2), 'y': reals(3)},
{'x': reals(4), 'y': reals(2, 3), 'z': reals()},
OrderedDict([('x', reals())]),
OrderedDict([('x', reals(4))]),
OrderedDict([('x', reals(2, 3))]),
OrderedDict([('x', reals()), ('y', reals())]),
OrderedDict([('x', reals(2)), ('y', reals(3))]),
OrderedDict([('x', reals(4)), ('y', reals(2, 3)), ('z', reals())]),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining! I'll avoid this pattern in the future.

@fritzo fritzo merged commit b571be1 into master Jul 12, 2020
@fritzo fritzo deleted the lint-py3.5 branch July 12, 2020 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting review bug Something isn't working testing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants