When re-exporting entities from a package-level
__init__.py, always use the form
import ... as ... even if the name is not changed, to signal static analysis tools that the name is intended to be re-exported (unless the aliased name starts with an underscore). This is enforceable with MyPy.
Excepting the above described case of package-level API re-export, do not import specific entities; instead, import only the module itself and then use verbose references, as shown below. If you really need to import a specific entity, consider prefixing it with an underscore to prevent scope leakage. Exception applies to well-encapsulated submodules which are not part of the package API (i.e., prefixed with an underscore) – you can import whatever you want provided that the visibility scope of the module is sufficiently narrow. Example:
from pyuavcan.transport import Transport # Don't do this. import pyuavcan.transport # Good. Use like: pyuavcan.transport.Transport
Semantic and behavioral conventions
def write(self, data: typing.Union[bytes, str], timeout: typing.Optional[float] = None) -> int: """ This method can be invoked concurrently from multiple threads, even if there are other threads blocked on any of the reading methods. :param data: Data to transmit. :param timeout: Timeout in seconds, None for infinity. :return: Number of bytes written -- always either len(data) or 0 on timeout. """ if isinstance(data, str): data = data.encode() if not isinstance(data, bytes): raise ValueError('Invalid data type: %r' % type(data)) try: if len(data) > 0: self._txq.put(data, timeout=timeout) except queue.Full: return 0 else: return len(data)
Keep simple test cases as close to the tested code as possible: either in doctest or in test functions; in the latter case, use the function name pattern
_unittest_*. Move all complex test code outside of the main codebase into a dedicated package (usually named
Write all new code in Python 3.7.
The recommended IDE for Python development is JetBrains PyCharm.