feat(packaging): nest protocol/ + ocf/ under smartthings_local, add PyPI packaging

Nest the two library packages under a single import namespace so they
can ship as one distribution:

  protocol/ -> smartthings_local/protocol/
  ocf/      -> smartthings_local/ocf/   (git mv, history preserved)

- Rewrite all imports protocol.* -> smartthings_local.protocol.*,
  ocf.* -> smartthings_local.ocf.* across the ocf modules, mqtt_demo/
  (bridge, descriptor, samples), and tests.
- Add pyproject.toml: dist name `smartthings-local`, hatch-vcs versioning
  from v* tags, wheel ships only smartthings_local/.
- Add .github/workflows/publish.yml: build + PyPI Trusted Publishing on
  v* tags (OIDC, no stored token).
- Force-include protocol/ocf_root_ca.pem via [tool.hatch.build] artifacts:
  it is tracked but matches .gitignore's *.pem, so hatchling's VCS file
  selection would drop it — and dtls_session.py loads it at runtime.
- Update mqtt_demo Dockerfile COPY and deploy.sh tar allowlist to the
  single smartthings_local/ package.
- .gitignore: build artifacts (_version.py, dist/, *.egg-info/).

Validated: pytest tests/ (11 passed), python -m build produces sdist +
wheel with the pem bundled, fresh pip install resolves all nested imports
with the pem readable from site-packages.
This commit is contained in:
Jack Nagy committed 2026-07-06 20:29:19 +01:00
1 parent 9004bac729
commit 3fdc735141
23 files changed
+155 -37

No files matched your search

+2 -3
View File
@@ -8,9 +8,8 @@ RUN pip install --no-cache-dir -r requirements.txt
# Application code — build context is the repo root (see
# docker-compose.yml's `context: ..`) since mqtt_demo/ depends on the
# protocol/ and ocf/ library packages that live alongside it.
COPY protocol/ ./protocol/
COPY ocf/ ./ocf/
# smartthings_local library package that lives alongside it.
COPY smartthings_local/ ./smartthings_local/
COPY mqtt_demo/ ./mqtt_demo/
# /config holds the ab0b0ac4 client cert + key. Mount from the host so
+5 -5
View File
@@ -23,12 +23,12 @@ import time
import cbor2
from protocol.dtls_session import DtlsCoapSession, fmt_code
from smartthings_local.protocol.dtls_session import DtlsCoapSession, fmt_code
from ocf.keepalive import KeepaliveTask
from ocf.observe_refresh import ObserveRefreshTask
from ocf.poll_scheduler import PollScheduler
from ocf.state_cache import StateCache
from smartthings_local.ocf.keepalive import KeepaliveTask
from smartthings_local.ocf.observe_refresh import ObserveRefreshTask
from smartthings_local.ocf.poll_scheduler import PollScheduler
from smartthings_local.ocf.state_cache import StateCache
from .descriptor import ApplianceDescriptor, bridge_diagnostic_discovery
from .config import ApplianceConfig, SharedConfig
+4 -5
View File
@@ -22,7 +22,7 @@ set -e
# This script lives in mqtt_demo/ but the build context is the repo
# root (mqtt_demo/docker-compose.yml uses `context: ..`, since the
# image needs the protocol/ and ocf/ library packages alongside
# image needs the smartthings_local library package alongside
# mqtt_demo/). Run everything from the repo root so the tar allowlist
# and remote layout line up with that context.
cd "$(dirname "$0")/.."
@@ -51,12 +51,11 @@ ssh "${SSH_HOST}" mkdir -p "${REMOTE_DIR}" "${APPDATA_DIR}"
# Source code — explicit allowlist instead of an excludelist. Anything
# else in the repo (research files, certs, logs, the .git dir) stays
# local. protocol/ and ocf/ are the library packages mqtt_demo/ imports
# from; they need to land as REMOTE_DIR's siblings of mqtt_demo/ so the
# local. smartthings_local/ is the library package mqtt_demo/ imports
# from; it needs to land as REMOTE_DIR's sibling of mqtt_demo/ so the
# compose file's `context: ..` resolves the same way it does locally.
COPYFILE_DISABLE=1 tar cz \
protocol/ \
ocf/ \
smartthings_local/ \
mqtt_demo/ \
README.md \
.gitignore \
+1 -1
View File
@@ -27,7 +27,7 @@ from dataclasses import dataclass, field
from typing import Callable, Optional, TYPE_CHECKING
if TYPE_CHECKING:
from ocf.poll_scheduler import PollTier
from smartthings_local.ocf.poll_scheduler import PollTier
@dataclass
+1 -1
View File
@@ -13,7 +13,7 @@ from ..descriptor import (
device_block,
encode,
)
from ocf.poll_scheduler import PollTier
from smartthings_local.ocf.poll_scheduler import PollTier
# --- OBSERVE paths -----------------------------------------------------
+1 -1
View File
@@ -30,7 +30,7 @@ from ..descriptor import (
device_block,
encode,
)
from ocf.poll_scheduler import PollTier
from smartthings_local.ocf.poll_scheduler import PollTier
MODEL = 'ARTIK051_REF_17K'
+1 -1
View File
@@ -31,7 +31,7 @@ from ..descriptor import (
device_block,
encode,
)
from ocf.poll_scheduler import PollTier
from smartthings_local.ocf.poll_scheduler import PollTier
# ---------------------------------------------------------------------