Documentation#685
Conversation
|
Ooooo! Love this! I see only conflict is version. Are you updating that? |
|
Yeah, I had bumped the version which in hindsight wasn't needed as there aren't really any code changes, only comment changes. I also reworked how it sets the version string while I was in there to match what was wanted in #588 but I'll probably pull it out and save that for a different PR. Or you can do it the next time the version needs to be bumped. I noticed this merge conflict yesterday but didn't fix it as I ran into a different issue that needs some discussion before moving forward: Sphinx gets confused and cannot generate links when a class has the same name as the module (filename) it is in. Initially I had solved this by moving Cloud and BulbDevice et al to new files with different names, however I later realized this will break imports if someone is doing i.e. I just discovered a different workaround that would allow leaving all the files as they are now at the expense of linking functions as |
Thanks yes, I agree. It breaks my automation (which I just need to fix).
To be honest, that sounds like a weakness (bug?) in Sphinx that needs to be addressed there, not by rewriting our structure. I'll start walking through the commits. Let me know when you think this is ready. |
|
|
||
| for clib in ('pyca/cryptography', 'PyCryptodomex', 'PyCrypto', 'pyaes'): | ||
| Crypto = Crypto_modes = AES = CRYPTOLIB = None | ||
| CRYPTOLIB = _AES = _Crypto = _Crypto_modes = None |
I agree. Unfortunately they can't/won't fix it. I found one issue where someone (I have no idea if they are involved with the project or are just some rando) was basically bragging about how "over 100 people have opened issues due to this problem and all those people are wrong!" I'm still working on it though and have been digging through the Sphinx source code looking for a way to monkey-patch around it or something. Fixing it for the *Device classes was rather easy, it's the constants/direct attributes which are kicking my butt. |
|
It's a kludge, but it appears to work. Fortunately it only messes with Sphinx so even if it breaks it's not a big deal. |
|
Thanks @uzlonewolf - I'll run the Copilot peer review. Let me know if you think this ready to go otherwise. |
There was a problem hiding this comment.
Pull request overview
This PR introduces an initial Sphinx + ReadTheDocs documentation setup for TinyTuya and updates existing modules with docstrings/metadata to improve autodoc output.
Changes:
- Add Sphinx project scaffolding, custom templates, and ReadTheDocs build configuration.
- Improve/normalize docstrings across core modules for autodoc/autosummary.
- Minor refactors to support documentation generation (e.g., centralizing
UDPKEY, exporting crypto symbols).
Reviewed changes
Copilot reviewed 41 out of 43 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| tinytuya/core/udp_helper.py | Uses shared UDPKEY constant for UDP decrypt/HMAC. |
| tinytuya/core/message_helper.py | Adds richer docstrings for packing/unpacking protocol messages. |
| tinytuya/core/error_helper.py | Adds module/docs scaffolding around error codes and JSON error helper. |
| tinytuya/core/document.py | Adds documentation metadata for Sphinx generation. |
| tinytuya/core/crypto_helper.py | Exposes documented crypto globals and renames internal imports for clarity. |
| tinytuya/core/core.py | Adds package metadata and docstrings to utility functions. |
| tinytuya/core/const.py | Documents constants and adds UDPKEY constant. |
| tinytuya/core/command_types.py | Adds Sphinx-style inline docs for command constants. |
| tinytuya/core/init.py | Adjusts imports and exposes document module for Sphinx context. |
| tinytuya/core/XenonDevice.py | Adds class docstring and docstring tweaks aimed at Sphinx output. |
| tinytuya/core/Device.py | Adds module-level name override aimed at Sphinx output. |
| tinytuya/init.py | Simplifies top-level docstring and exports additional metadata. |
| tinytuya/OutletDevice.py | Removes large header comment block (docs now come from Sphinx). |
| tinytuya/CoverDevice.py | Removes large header comment block (docs now come from Sphinx). |
| tinytuya/Cloud.py | Adds a class docstring placeholder for Cloud. |
| tinytuya/BulbDevice.py | Adds __init__ docstring and docstring concatenation for Sphinx. |
| setup.py | Changes crypto dependency detection to avoid pkg_resources usage. |
| docs/sphinx/tt_gen_local_api.rst | Adds autosummary entrypoint for local API docs. |
| docs/sphinx/start/*.rst | Adds “Getting Started” placeholder pages. |
| docs/sphinx/start.rst | Adds getting-started toctree. |
| docs/sphinx/index.rst | Adds Sphinx root index and toctree. |
| docs/sphinx/contrib.rst | Adds placeholder contrib page. |
| docs/sphinx/conf.py | Adds Sphinx configuration + custom directives/monkeypatches for nicer output. |
| docs/sphinx/cloud_api.rst | Adds autosummary entrypoint for Cloud API docs. |
| docs/sphinx/_templates/*.rst | Adds custom autosummary/autodoc templates for module/class layout. |
| docs/sphinx/_static/.gitkeep | Keeps static dir in git. |
| docs/rtd-requirements.txt | Adds RTD requirements for Sphinx/theme. |
| docs/make.bat | Adds Windows Sphinx build helper. |
| docs/Makefile | Adds Unix Sphinx build helper. |
| .readthedocs.yaml | Configures RTD build (Python version, deps install, fail on warnings). |
| .gitignore | Ignores Sphinx generated output directory. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -0,0 +1,13 @@ | |||
| :orphan: | |||
There was a problem hiding this comment.
This file appears to start with a UTF-8 BOM/zero-width character (an invisible character before :orphan:). That can cause odd rendering/diffs; consider removing the BOM so the first character is :.
| :orphan: | |
| :orphan: |
| @@ -0,0 +1,12 @@ | |||
| TinyTuya Cloud API | |||
There was a problem hiding this comment.
This file appears to start with a UTF-8 BOM/zero-width character (an invisible character before TinyTuya Cloud API). That can cause odd rendering/diffs; consider removing the BOM.
| TinyTuya Cloud API | |
| TinyTuya Cloud API |
| kwargs['version'] = None | ||
| super(BulbDevice, self).__init__(*args, **kwargs) | ||
|
|
||
| # Monkey-patch the docstring so Sphinx gets a contatenation of parent+ours |
There was a problem hiding this comment.
Comment typo: "contatenation" → "concatenation".
| # Monkey-patch the docstring so Sphinx gets a contatenation of parent+ours | |
| # Monkey-patch the docstring so Sphinx gets a concatenation of parent+ours |
| """ | ||
| Error messages and formattring | ||
| """ |
There was a problem hiding this comment.
Module docstring has a typo: "formattring" should be "formatting".
| @@ -0,0 +1,14 @@ | |||
| TinyTuya Local API | |||
There was a problem hiding this comment.
This template appears to start with a UTF-8 BOM/zero-width character (an invisible character before TinyTuya Local API). That can leak into generated pages; consider removing the BOM from the template file.
| TinyTuya Local API | |
| TinyTuya Local API |
|
|
||
| class Cloud(object): | ||
| """ | ||
| placeholder |
There was a problem hiding this comment.
The Cloud class docstring is currently just "placeholder", which will surface prominently in the generated docs. Consider removing it (so the existing, detailed __init__ docstring is used) or replacing it with a short summary of what Cloud represents.
| placeholder | |
| Interface to the Tuya Cloud IoT Platform for managing and controlling devices via cloud APIs. |
| # Fix the name so it's not tinytuya.core.XenonDevice | ||
| __name__ = 'tinytuya.XenonDevice' | ||
|
|
||
| log = logging.getLogger(__name__) |
There was a problem hiding this comment.
__name__ is a special module attribute; overriding it at runtime can confuse logging, introspection, stack traces, and tooling (and it doesn't change the class' fully-qualified name in a safe way). For documentation purposes, prefer setting XenonDevice.__module__ = "tinytuya" (or configuring Sphinx autodoc/currentmodule) instead of mutating the module __name__.
| node_id (str, optional): alias for cid | ||
| parent (XenonDevice, optional): gateway device this device is a child of) | ||
|
|
There was a problem hiding this comment.
Docstring has an unmatched trailing parenthesis in the parent argument description ("child of)"). This will render oddly in generated docs; please remove the extra ).
| # Fix the name so it's not tinytuya.core.Device | ||
| __name__ = 'tinytuya.Device' | ||
|
|
||
| log = logging.getLogger(__name__) |
There was a problem hiding this comment.
__name__ is a special module attribute; overriding it can confuse logging and introspection and may have unintended side effects at import time. For documentation purposes, prefer setting Device.__module__ or adjusting Sphinx autodoc configuration rather than mutating the module __name__.
|
Some noise here (reviews), but some signal we should act on. I can help with these. |
|
I'm working through them and am hoping to get it wrapped up in the morning. Most of those warnings are easy fixes, it's finishing the documenting everywhere else which is taking a while 😆 |
|
While working on the Cloud documentation I ended up rewriting the Region stuff. Known region codes are now in |
…device_helper.py file
|
@jasonacox-sam Tests are failing here. See if you can figure out why. |
|
@uzlonewolf — traced the CI failure. Quick update on my earlier comment: The Pylint error is: This is happening because your PR branch ( Good news: master has since refactored The fix: rebase this PR branch onto current master. The conflict should resolve the Pylint error automatically since the udp_helper.py changes on master supersede the old version your branch is targeting. No separate fix PR needed from our side. |
|
No, I already fixed it, it's just that this is nowhere near ready to merge even with that failure fixed so I didn't bother pushing it. This turned out to be like 100x more effort than I was expecting and I ended up spending the time I had intended to use on documenting the code on making Sphinx do what I wanted. I haven't had time the last few weeks to finish it and was hoping to get it done this weekend, however I suddenly had a work project dropped on me Friday afternoon that's needed for Monday, so... |
|
No worries and no rush @uzlonewolf - Thanks for the update. |
|
On a (similar? unrelated?) note, this is like the umpteenth time I've made a stupid mistake like this when committing, so I ended up adding a git hook to .git/hooks/pre-commit that calls pylint on every commit, so hopefully this will be the last time it happens ^_^ My #!/bin/bash
echo "Running pylint..."
pylint --recursive y --reports y -E tinytuya || {
echo "pylint failed, aborting commit!"
exit 2
}
echo "done."
exit $?Sadly you can't commit anything in .git/ or I'd submit a PR for it :( |
Oh! That's good. Adding myself. :) @jasonacox-sam Make sure you add this to your local clone too! |
One thing that's always annoyed me about TinyTuya is the lack of documentation. One day I'd be using the good documentation for something like pySerial and the next I'd be digging through TinyTuya source code files 🤣 So, I got the Sphinx code-to-documentation generator set up along with Read The Docs for web display. It's still very, very rough as I spent the last 2 days fighting with Sphinx to get it to link everything correctly, but the TinyTuya function definitions imported surprisingly well as-is without me needing to rewrite anything.
PoC: https://tinytuya-lw.readthedocs.io/
It's still really rough, but it's a start. I think the next thing I'm going to work on is adding type hinting to all the functions (which is going to require Python 3.5+).