-
Notifications
You must be signed in to change notification settings - Fork 2
Add a mock_all_slots option to create_thing_without_server
#199
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
base: docs-tidy-after-dropping-dependencies
Are you sure you want to change the base?
Add a mock_all_slots option to create_thing_without_server
#199
Conversation
:deco: now correctly formats cross-references as `@whatever` in the docs.
There was a bad indent in the properties module level docstring, and a few imports that confused Sphinx when making cross-references. I've moved an exception and tweaked the way Thing._thing_server_interface is declared to improve the docs: this should not change any code.
ThingServerInterface is used as a type hint for `Thing._thing_server_interface`. It was previously imported with an `if TYPE_CHECKING` guard, but as I've now explicitly type hinted and documented that attribute, any time `get_type_hints` is called on a `Thing` subclass (which is every time one is defined) it will cause an error. I've now imported it unconditionally, which fixes the problem. This does not cause any interdependency issues, as `thing_server_interface` has few onward dependencies.
This shouldn't be duplicated in `conf.py`.
I've converted quite a few links to other pages in the docs, now that they exist. I think redirecting people to the WoT page all the time is causing confusion.
386cc5b to
48b1aaa
Compare
|
Great :) Glad this works, and it seems like it wasn't too much code to implement it. I am thinking that it is probably a sensible idea to create a submodule called |
48b1aaa to
2709890
Compare
Barecheck - Code coverage reportTotal: 94.52%Your code coverage diff: 0.13% ▴ ✅ All code changes are covered |
|
I understand I think moving it to a testing module is probably a good idea. I like the idea of:
I think it makes it very clear that this not intended for actual use. |
rwb27
left a comment
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. I've made a couple of suggestions that might be nice, but don't change the way it works meaningfully.
It would be good to move this to a testing module as we discussed, I'm happy for you to do that now, or we can do it later.
| # Note that this causes mypy to throw an `attr-defined` error as _mock | ||
| # only exists in the MockThingServerInterface | ||
| thing._thing_server_interface._mocks.append(mock) # type: ignore[attr-defined] |
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.
What I've done in situations like this is use type narrowing:
| # Note that this causes mypy to throw an `attr-defined` error as _mock | |
| # only exists in the MockThingServerInterface | |
| thing._thing_server_interface._mocks.append(mock) # type: ignore[attr-defined] | |
| interface = thing._thing_server_interface | |
| if isinstance(interface, MockThingServerInterface): | |
| interface._mocks.append(mock) | |
| else: | |
| raise TypeError("Slots may not be mocked when a Thing is attached to a real server." |
It's a bit more verbose, but it's probably a helpful check to have, as well as eliminating a type ignore.
| # only exists in the MockThingServerInterface | ||
| thing._thing_server_interface._mocks.append(mock) # type: ignore[attr-defined] | ||
|
|
||
| attr.connect(thing, mocks, ...) |
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.
Might it make sense to do this in a separate loop? Your code above does an impressively thorough job of constructing a collection of mock Things that you can pass to attr.connect without having to mess with the ThingSlot code (which I really like). However, the first slot will not see mocked Things that are added to satisfy later slots.
Splitting the loop means all the slots see all the mocked Things, which makes it function just a little bit more like the real thing, and might catch odd edge cases where there are interactions between multiple slots. I realise that is very edge-casey, but it's a pretty minor tweak so why not...
| attr.connect(thing, mocks, ...) | |
| for attr_name, attr in class_attributes(thing): | |
| if isinstance(attr, ThingSlot): | |
| attr.connect(thing, mocks, ...) |
|
Yeah this is only targeted to #195 so it has a sensible diff. I think aiming it at main once those are merged makes sense |
0cf53bb to
ed2e66f
Compare
Adds a
mock_all_slotsoption tocreate_thing_without_server. This will follow the default specified bything_slot, so if the default isNoneno mock is created.If it is a mapping with no default
I thinkone instance is created, thisneeds checking in a testis tested.I have targeted it at #195 so the diff is clear.
Closes #198