-
Notifications
You must be signed in to change notification settings - Fork 233
Refactoring: split up core.py #575
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
Conversation
This makes importing from tinytuya.core continue to work.
Looks like I no longer depend on a lot of the new files directly.
|
Thanks @tringenbach ! I definitely welcome the help , code cleanup and prep for async support. @uzlonewolf if you have time, would love your review (added). |
tinytuya/core/XenonDevice.py
Outdated
| # FIXME: The place where this is used looks like it might have meant `self.version`, but I'm not really sure yet | ||
| # this is copy/pasted instead of moved because it feels like a bug to me | ||
| version_tuple = (1, 15, 1) | ||
| version = __version__ = "%d.%d.%d" % version_tuple |
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 global should not be in this file. It refers to the library version and exists in core.py. The 'self.version' or local version parameters in the functions refer to the Tuya device versions.
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.
So later in that file (321 in my PR, 948 of core.py in master), there is:
# FIXME: check if we really meant the global `version` here or not
self.version_str = "v" + str(version)
self.version_bytes = str(version).encode('latin1')
self.version_header = self.version_bytes + PROTOCOL_3x_HEADER
self.payload_dict = NoneWhich I assume meant to say new_version or self.version (which are the same at that point), but accidentally uses the global version instead.
Actually, it might have been copied from set_version, where version is an argument.
|
While there should be no functional difference, due to the significant code changes, I propose we set this as v0.16.0.
|
Also use the `as H` / `as DT` aliases in more places.
I went ahead and changed And I am now using the |
That works!
Ugh, it just occurs to me that there there are examples that take advantage of these constants and are likley used by others who use this library. We will need to still support these: import tinytuya
d = tinytuya.OutletDevice('DEVICEID', 'Auto', 'DEVICEKEY', persist=True)
payload = d.generate_payload(tinytuya.UPDATEDPS)
d.send(payload)So it probalby makes more sense to just use something like from .command_types import *and use these constants as we have been. Also, on line 30, the |
Device Auto-IP ( |
Perfect! I see that it does indeed work for the possible existing use case if we address those imports (once I make the scanner import change): import tinytuya
d = tinytuya.OutletDevice(device_id, 'Auto', key, persist=True)
d.status()
payload = d.generate_payload(tinytuya.UPDATEDPS)
d.send(payload)
d.status()
I think we can stay with your approach (CT and H). I don't see any pylint warnings with that.
As @uzlonewolf says, the 'Auto' part initiates
That's usually what I do as well, but it does not test all the module functions. The github workflow for pylint and test is also very basic and in need of improvement too. |
Since I moved core.py into a subdirectory, it needs to import scanner from `..`. Since I added a subdirectory, pylint needs to be recursive. That also lints contrib, so I fixed a typo and disabled use-before-assign a logging line.
I pushed up your suggested fix to the import scanner issue. I also noticed that the pylint command in the pipeline wasn't linting my new subdirectory, so I added the recursive option. That also made it lint contrib, so I fixed a typo in one file, and disabled a rule on a single line in another, so that it passes. I couldn't get the tests to work locally though.
I also tried running |
The pylint test?
That's about right. We don't have good tests. This only verifies that the module can be imported. I don' t know if UDP packets would be allowed, but it would be ideal to have a Tuya device simulator and have the test run a scan, at the minimum, if not have a slate of critical function tests (e.g. get status, set values). |
I meant that Since then, as you've already seen, I got |
| """ | ||
| status = self.status() | ||
| if "Error" in status: | ||
| return satus |
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.
Good fix.
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 for the great work on this @tringenbach . My tests look good and based on summary ❤️ feedback from @uzlonewolf, I'm comfortable merging this and releasing as 1.16.0.
|
Merge and released as https://pypi.org/project/tinytuya/1.16.0/ # upgrade library
pip install tinytuya --upgrade
# upgrade CLI
pipx upgrade tinytuyaDocker for server: jasonacox/tinytuya:1.16.0p13 Please report any bugs/issues. Thank @tringenbach ! 🙏 |
Yet something else I intended to do but never found the time to implement T_T I did add the start of a simulator that currently only does v3.5 and status() a while back though https://github.com/jasonacox/tinytuya/blob/master/tools/fake-v35-device.py |
This PR refactors core.py by splitting it up into about a dozen smaller files. It puts it in a
core/directory, so existing code that imports fromtinytuya.coreshould hopefully be unaffected.I've been a software engineer for a while now. I'm less experienced in Python though compared to some other ecosystems, and I've never messed with this project before.
You didn't ask me to do this refactor, and I didn't even reach out first, so no hard feelings if you reject this outright. I understand that my idea of better organized code might not be yours.
My motivation is that I was looking into what it would take to add an asyncio mode. Splitting the code up into separate files allowed me to look at the resulting
importlines to understand which pieces of the code directly do IO. (Though of course, making anything async has a viral affect.) If nothing else, this exercise helped me learn, or begin to learn, the codebase.I used a combination of VSCode's "move to file" feature, manual copy/pasting, and cleaning up of the imports.
I ended up duplicating
IS_PY2andversioninto two files, but nothing else should be duplicated. I suspectversionbeing used in XenonDevice is unintentional on your part.If nothing else, please take a look at my comment
# FIXME: check if we really meant the globalversionhere or notinXenonDevice.py. I think that may be a real bug. I did not attempt to fix it, as I wanted this PR to have no functional or API changes.In
header.py, I used the syntaxfrom . import command_types as CT, because I liked having theCT.prefix to group the constants. I was tempted to use that in the other placescommand_typesandheaderwere imported, but I couldn't find a way to get VSCode to do that for me, and didn't want to make a lot of manual changes. Besides, I don't know if you would like that or not.Thanks!