Skip to content

Commit

Permalink
Initial MVP
Browse files Browse the repository at this point in the history
  • Loading branch information
puddly committed Oct 21, 2022
0 parents commit 7473015
Show file tree
Hide file tree
Showing 12 changed files with 1,130 additions and 0 deletions.
77 changes: 77 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
coverage.xml
*,cover
.pytest_cache/

# Translations
*.mo
*.pot

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# pyenv
.python-version

# dotenv
.env

# virtualenv
.venv/
.venv*/
venv/
ENV/

# Editor temp files
.*.swp

# Visual Studio Code
.vscode

.DS_Store
.mypy_cache/
44 changes: 44 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
hooks:
- id: debug-statements

- repo: https://github.com/psf/black
rev: 22.3.0
hooks:
- id: black

- repo: https://github.com/PyCQA/flake8
rev: 4.0.1
hooks:
- id: flake8
entry: pflake8
additional_dependencies:
- pyproject-flake8==0.0.1a3
- flake8-bugbear==22.1.11
- flake8-comprehensions==3.8.0
- flake8_2020==1.6.1
- mccabe==0.6.1
- pycodestyle==2.8.0
- pyflakes==2.4.0

- repo: https://github.com/PyCQA/isort
rev: 5.10.1
hooks:
- id: isort

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.942
hooks:
- id: mypy

- repo: https://github.com/asottile/pyupgrade
rev: v2.31.0
hooks:
- id: pyupgrade

- repo: https://github.com/fsouza/autoflake8
rev: v0.3.1
hooks:
- id: autoflake8
Empty file added README.md
Empty file.
50 changes: 50 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
[build-system]
requires = ["setuptools>=34.4.0", "wheel"]
build-backend = "setuptools.build_meta"

[tool.black]
safe = true
quiet = true

[tool.isort]
multi_line_output = 3
length_sort = true
balanced_wrapping = true
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true
line_length = 88
indent = " "
sections = ["FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
default_section = "THIRDPARTY"
known_first_party = ["universal_silabs_flasher", "tests"]
forced_separate = "tests"
combine_as_imports = true

[tool.pytest.ini_options]
addopts = "--showlocals --verbose"
testpaths = ["tests"]
timeout = 20
log_format = "%(asctime)s.%(msecs)03d %(levelname)s %(message)s"
log_date_format = "%Y-%m-%d %H:%M:%S"
asyncio_mode = "auto"

[tool.flake8]
exclude = ".venv,.git,.tox,docs,venv,bin,lib,deps,build"
# To work with Black
max-line-length = 88
# W503: Line break occurred before a binary operator
# E203: Whitespace before ':'
# D202 No blank lines allowed after function docstring
ignore = "W503,E203,D202"

[tool.mypy]
check_untyped_defs = true
show_error_codes = true
show_error_context = true

[tool.coverage.run]
source = ["universal_silabs_flasher"]

[tool.pyupgrade]
py37plus = true
32 changes: 32 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[metadata]
name = universal-silabs-flasher
description = Tool to flash firmware onto any Silicon Labs radio running EmberZNet, CPC multi-PAN, or just a bare Gecko Bootloader
version = attr: universal_silabs_flasher.__version__
long_description = file: README.md
long_description_content_type = text/markdown; charset=UTF-8
url = https://github.com/zigpy/zigpy-znp
author = Puddly
author_email = [email protected]
license = GPL-3.0

[options]
packages = find:
python_requires = >=3.7
install_requires =
zigpy
bellows
async_timeout
coloredlogs

[options.packages.find]
exclude =
tests
tests.*

[options.extras_require]
testing =
pytest>=7.1.2
pytest-asyncio>=0.19.0
pytest-timeout>=2.1.0
pytest-mock>=3.8.2
pytest-cov>=3.0.0
4 changes: 4 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import setuptools

if __name__ == "__main__":
setuptools.setup()
6 changes: 6 additions & 0 deletions universal_silabs_flasher/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
MAJOR_VERSION = 0
MINOR_VERSION = 0
PATCH_VERSION = 1

__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__ = f"{__short_version__}.{PATCH_VERSION}"
60 changes: 60 additions & 0 deletions universal_silabs_flasher/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from __future__ import annotations

import asyncio
import logging
import collections

_LOGGER = logging.getLogger(__name__)


class StateMachine:
def __init__(self, states: list[str], initial: str) -> None:
assert initial in states

self.states = states
self.state = initial

self.futures_for_state = collections.defaultdict(list)

async def wait_for_state(self, state: str) -> None:
assert state in self.states

future = asyncio.get_running_loop().create_future()
self.futures_for_state[state].append(future)

try:
return await future
finally:
self.futures_for_state[state].remove(future)

def set_state(self, state: str) -> None:
assert state in self.states
self.state = state

for future in self.futures_for_state[state]:
future.set_result(None)


class SerialProtocol(asyncio.Protocol):
def __init__(self) -> None:
self._buffer = bytearray()
self._transport = None
self._connected_event = asyncio.Event()

async def wait_until_connected(self):
await self._connected_event.wait()

def connection_made(self, transport: asyncio.BaseTransport) -> None:
_LOGGER.debug("Connection made: %s", transport)

self._transport = transport
self._connected_event.set()

def send_data(self, data: bytes) -> None:
data = bytes(data)
_LOGGER.debug("Sending data %s", data)
self._transport.write(data)

def data_received(self, data: bytes) -> None:
_LOGGER.debug("Received data %s", data)
self._buffer += data
Loading

0 comments on commit 7473015

Please sign in to comment.