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

Feeds #16

Merged
merged 29 commits into from
Jan 4, 2018
Merged

Feeds #16

merged 29 commits into from
Jan 4, 2018

Conversation

danpalmer
Copy link
Contributor

@danpalmer danpalmer commented Dec 27, 2017

@coveralls
Copy link

Coverage Status

Coverage decreased (-1.3%) to 98.439% when pulling a3352a0 on feeds into 9c9786c on master.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.3%) to 99.391% when pulling 8881e33 on feeds into 9c9786c on master.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.2%) to 99.533% when pulling f366c6c on feeds into 9c9786c on master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) to 99.733% when pulling fd73449 on feeds into 9c9786c on master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) to 99.734% when pulling 0446c06 on feeds into 9c9786c on master.

Copy link
Contributor

@PeterJCLaw PeterJCLaw left a comment

Choose a reason for hiding this comment

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

Mostly fine; I think we need to work out how (and test) we're going to handle failures getting data from feeds.



def test_multiple_feeds_same_name_invalid():
with assert_config_error(f"Feeds must have unique names at state_machines.example.feeds"):
Copy link
Contributor

Choose a reason for hiding this comment

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

This string doesn't have any format placeholders in -- consider dropping the f prefix.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if len(set(x.name for x in feeds)) < len(feeds):
raise ConfigError(
f"Feeds must have unique names at {'.'.join(path + ['feeds'])}",
)
Copy link
Contributor

Choose a reason for hiding this comment

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

For even nicer errors, we could use a collections.Counter to detect exactly which feeds had non-unique names. (I'm not sure how many feeds we're expecting to exist in each config file).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd expect it will be typically 1, sometimes 1<n<5. I don't think this is necessary for now.

from routemaster.exit_conditions import Context, ExitConditionProgram
from routemaster.exit_conditions import ExitConditionProgram

if False: # typing
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the rationale behind this being a fake import -- is it circular?

I'm ok with using the if False idiom if there are conflicts on the import or it's a major performance hit, but would rather just import things directly for simpler cases as it's a bit ugly (and also makes the type annotations a bit ugly too).

(future occurrences not commented)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What's the rationale behind this being a fake import -- is it circular?

Yes

This is only to support typing, and in Python 3.7 we can switch to 'if TYPING'.

Copy link
Contributor

Choose a reason for hiding this comment

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

ok, could we have a comment about these being circular? (possibly as well as the need for it only being for typing).


def __init__(
self,
label: str,
Copy link
Contributor

Choose a reason for hiding this comment

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

Elsewhere (in the API at least) we call this a label_name (with label meaning a fully qualified name plus state machine), should we use that terminology here too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm, I'm not sure about this. A label should be just the string, I think we should probably change the Label in state_machine to something like LabelRef. Won't do this in this PR though.

@@ -45,15 +45,15 @@ jobs:
# Run tox, caching the .tox directory
- restore_cache:
name: Restore .tox cache
key: deps-tox-{{ .Branch }}-{{ checksum "scripts/linting/requirements.txt" }}-{{ checksum "scripts/testing/requirements.txt" }}-{{ checksum "setup.py" }}
key: deps-tox-{{ .Branch }}-{{ checksum "scripts/linting/requirements.txt" }}-{{ checksum "scripts/typechecking/requirements.txt" }}-{{ checksum "scripts/testing/requirements.txt" }}-{{ checksum "setup.py" }}
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 to adding a typechecking requirements.txt; this change (and the similar one below) should probably be cherry-picked to master though.

from routemaster.utils import get_path


def feeds_for_state_machine(state_machine) -> Dict[str, 'Feed']:
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor: should the argument by type-annotated? (I'm not sure how much typing coverage we're aiming for)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We actually can't here due to python/mypy#4049 – there's detail in the commit message that removed the type.

self.data = None
self.state_machine = state_machine

def fetch(self, label: str):
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor: given that this is lazy and without return value, perhaps it should be named preload or ensure_fetched?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

606b673 - prefetch

self.state_machine,
)

response = requests.get(url)
Copy link
Contributor

Choose a reason for hiding this comment

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

What behaviour do we want if this errors? (Should this raise_for_status?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, this should fail for now. We might want to allow for more in the future, maybe 404 should be allowed for example. 473539d



@httpretty.activate
def test_fetch_only_once():
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this test is a duplicate of test_only_loads_feed_once

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ish. This tests it directly on the feed, the other through a context. Given it's the context's responsibility to pre-warm I think it's worth having this test on both.



@httpretty.activate
def test_lookup():
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this test is a duplicate of test_accesses_variable_in_feed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not quite, test_accesses_variable_in_feed goes through a layer of dynamic dispatch (in a way) in the context, which is worth testing I think.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) to 99.734% when pulling 473539d on feeds into 9c9786c on master.

Copy link
Contributor

@PeterJCLaw PeterJCLaw left a comment

Choose a reason for hiding this comment

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

Would be great if we could have explicit comments about the typing imports which are circular, fine otherwise.

@danpalmer
Copy link
Contributor Author

Would be great if we could have explicit comments about the typing imports which are circular, fine otherwise.

Do you think this is necessary? I thought the if False pattern was enough to document that.

@danpalmer
Copy link
Contributor Author

Merging now, will address if needed on master.

@danpalmer danpalmer merged commit 8059262 into master Jan 4, 2018
@danpalmer danpalmer deleted the feeds branch January 4, 2018 18:02
@PeterJCLaw
Copy link
Contributor

PeterJCLaw commented Jan 4, 2018

I thought the if False pattern was enough to document [that an import is circular and for typing only].

I've seen some projects put all their typing-only imports under this sort of guard, which I'm not sure I see the point of. Given that we only use it for that reason here we maybe don't, but I was then surprised to see that you'd commented them as # typing which is similarly implied.

If we're aiming to generally put typing imports unguarded (which is the style I've used elsewhere and would encourage; from what I've seen it's what we're doing here anyway), then the cases where we're not doing that are interesting for the reason we're not doing that rather than for the fact that they're typing imports. Thus a comment about them being circular is most useful. I'm open to having a comment which says something like "circular typing-only imports" if you feel we need to call out that they're typing imports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

None yet

3 participants