Compare commits
No commits in common. "3062378a7bbf8f560731088a8d42a15da10e53da" and "b3f9566b8b8863ec85a00ce424d77c8e19576c44" have entirely different histories.
3062378a7b
...
b3f9566b8b
12 changed files with 145 additions and 185 deletions
51
.github/workflows/publish_assets.yaml
vendored
Normal file
51
.github/workflows/publish_assets.yaml
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
# CI Code for generating and publishing beta assets
|
||||||
|
|
||||||
|
name: publish_assets
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
jobs:
|
||||||
|
generate_assets:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout Moonraker
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
ref: ${{ github.ref }}
|
||||||
|
path: moonraker
|
||||||
|
|
||||||
|
- name: Checkout Klipper
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
repository: Klipper3d/klipper
|
||||||
|
path: klipper
|
||||||
|
|
||||||
|
- name: Build Beta Assets
|
||||||
|
if: ${{ github.event.release.prerelease }}
|
||||||
|
run: >
|
||||||
|
./moonraker/scripts/build-zip-release.sh -b
|
||||||
|
-o ${{ github.workspace }}
|
||||||
|
-k ${{ github.workspace }}/klipper
|
||||||
|
|
||||||
|
- name: Build Stable Assets
|
||||||
|
if: ${{ !github.event.release.prerelease }}
|
||||||
|
run: >
|
||||||
|
./moonraker/scripts/build-zip-release.sh
|
||||||
|
-o ${{ github.workspace }}
|
||||||
|
-k ${{ github.workspace }}/klipper
|
||||||
|
|
||||||
|
- name: Upload assets
|
||||||
|
run: |
|
||||||
|
cd moonraker
|
||||||
|
gh release upload ${{ env.TAG }} ${{ env.FILES }}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
FILES: >
|
||||||
|
${{ github.workspace }}/moonraker.zip
|
||||||
|
${{ github.workspace }}/klipper.zip
|
||||||
|
${{ github.workspace }}/RELEASE_INFO
|
||||||
|
${{ github.workspace }}/COMMIT_LOG
|
||||||
|
TAG: ${{ github.event.release.tag_name }}
|
||||||
|
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -8,13 +8,7 @@ __pycache__/
|
||||||
venv
|
venv
|
||||||
start_moonraker
|
start_moonraker
|
||||||
*.env
|
*.env
|
||||||
*.egg-info
|
|
||||||
.pdm-python
|
.pdm-python
|
||||||
build
|
build
|
||||||
dist
|
dist
|
||||||
share
|
share
|
||||||
|
|
||||||
.vscode
|
|
||||||
.mypy_cache
|
|
||||||
.pdm-build
|
|
||||||
.pytest_cache
|
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,6 @@ from ..common import (
|
||||||
KlippyState
|
KlippyState
|
||||||
)
|
)
|
||||||
from ..utils import json_wrapper as jsonw
|
from ..utils import json_wrapper as jsonw
|
||||||
try:
|
|
||||||
from paho.mqtt.reasoncodes import ReasonCode
|
|
||||||
except ImportError:
|
|
||||||
from paho.mqtt.reasoncodes import ReasonCodes as ReasonCode
|
|
||||||
|
|
||||||
# Annotation imports
|
# Annotation imports
|
||||||
from typing import (
|
from typing import (
|
||||||
|
|
@ -45,7 +41,6 @@ if TYPE_CHECKING:
|
||||||
from ..common import JsonRPC, APIDefinition
|
from ..common import JsonRPC, APIDefinition
|
||||||
from ..eventloop import FlexTimer
|
from ..eventloop import FlexTimer
|
||||||
from .klippy_apis import KlippyAPI
|
from .klippy_apis import KlippyAPI
|
||||||
from paho.mqtt.properties import Properties
|
|
||||||
FlexCallback = Callable[[bytes], Optional[Coroutine]]
|
FlexCallback = Callable[[bytes], Optional[Coroutine]]
|
||||||
RPCCallback = Callable[..., Coroutine]
|
RPCCallback = Callable[..., Coroutine]
|
||||||
|
|
||||||
|
|
@ -78,7 +73,7 @@ class ExtPahoClient(paho_mqtt.Client):
|
||||||
"remaining_count": [],
|
"remaining_count": [],
|
||||||
"remaining_mult": 1,
|
"remaining_mult": 1,
|
||||||
"remaining_length": 0,
|
"remaining_length": 0,
|
||||||
"packet": b"", # type: ignore
|
"packet": b"",
|
||||||
"to_process": 0,
|
"to_process": 0,
|
||||||
"pos": 0
|
"pos": 0
|
||||||
}
|
}
|
||||||
|
|
@ -105,7 +100,7 @@ class ExtPahoClient(paho_mqtt.Client):
|
||||||
self._last_msg_out = paho_mqtt.time_func()
|
self._last_msg_out = paho_mqtt.time_func()
|
||||||
|
|
||||||
self._ping_t = 0
|
self._ping_t = 0
|
||||||
self._state = paho_mqtt.mqtt_cs_new # type: ignore
|
self._state = paho_mqtt.mqtt_cs_new
|
||||||
|
|
||||||
self._sock_close()
|
self._sock_close()
|
||||||
|
|
||||||
|
|
@ -154,16 +149,16 @@ class ExtPahoClient(paho_mqtt.Client):
|
||||||
|
|
||||||
if self._transport == "websockets":
|
if self._transport == "websockets":
|
||||||
sock.settimeout(self._keepalive)
|
sock.settimeout(self._keepalive)
|
||||||
sock = paho_mqtt.WebsocketWrapper( # type: ignore
|
sock = paho_mqtt.WebsocketWrapper(
|
||||||
sock, self._host, self._port, self._ssl,
|
sock, self._host, self._port, self._ssl,
|
||||||
self._websocket_path, self._websocket_extra_headers
|
self._websocket_path, self._websocket_extra_headers
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
|
||||||
self._sock = sock # type: ignore
|
self._sock = sock
|
||||||
assert self._sock is not None
|
assert self._sock is not None
|
||||||
self._sock.setblocking(False)
|
self._sock.setblocking(False)
|
||||||
self._registered_write = False
|
self._registered_write = False
|
||||||
self._call_socket_open() # type: ignore
|
self._call_socket_open()
|
||||||
|
|
||||||
return self._send_connect(self._keepalive)
|
return self._send_connect(self._keepalive)
|
||||||
|
|
||||||
|
|
@ -238,7 +233,7 @@ class BrokerAckLogger:
|
||||||
|
|
||||||
def __call__(self, fut: asyncio.Future) -> None:
|
def __call__(self, fut: asyncio.Future) -> None:
|
||||||
if self.action == "subscribe":
|
if self.action == "subscribe":
|
||||||
res: Union[List[int], List[ReasonCode]]
|
res: Union[List[int], List[paho_mqtt.ReasonCodes]]
|
||||||
res = fut.result()
|
res = fut.result()
|
||||||
log_msg = "MQTT Subscriptions Acknowledged"
|
log_msg = "MQTT Subscriptions Acknowledged"
|
||||||
if len(res) != len(self.topics):
|
if len(res) != len(self.topics):
|
||||||
|
|
@ -248,7 +243,7 @@ class BrokerAckLogger:
|
||||||
else:
|
else:
|
||||||
for topic, qos in zip(self.topics, res):
|
for topic, qos in zip(self.topics, res):
|
||||||
log_msg += f"\n Topic: {topic} | "
|
log_msg += f"\n Topic: {topic} | "
|
||||||
if isinstance(qos, ReasonCode):
|
if isinstance(qos, paho_mqtt.ReasonCodes):
|
||||||
log_msg += qos.getName()
|
log_msg += qos.getName()
|
||||||
else:
|
else:
|
||||||
log_msg += f"Granted QoS {qos}"
|
log_msg += f"Granted QoS {qos}"
|
||||||
|
|
@ -270,44 +265,41 @@ class AIOHelper:
|
||||||
self.client.on_socket_open = self._on_socket_open
|
self.client.on_socket_open = self._on_socket_open
|
||||||
self.client.on_socket_close = self._on_socket_close
|
self.client.on_socket_close = self._on_socket_close
|
||||||
self.client._on_socket_register_write = self._on_socket_register_write
|
self.client._on_socket_register_write = self._on_socket_register_write
|
||||||
self.client._on_socket_unregister_write = self._on_socket_unregister_write
|
self.client._on_socket_unregister_write = \
|
||||||
|
self._on_socket_unregister_write
|
||||||
self.misc_task: Optional[asyncio.Task] = None
|
self.misc_task: Optional[asyncio.Task] = None
|
||||||
|
|
||||||
def _on_socket_open(
|
def _on_socket_open(self,
|
||||||
self,
|
client: paho_mqtt.Client,
|
||||||
client: paho_mqtt.Client,
|
userdata: Any,
|
||||||
userdata: Any,
|
sock: socket.socket
|
||||||
sock: socket.socket | paho_mqtt.SocketLike
|
) -> None:
|
||||||
) -> None:
|
|
||||||
logging.info("MQTT Socket Opened")
|
logging.info("MQTT Socket Opened")
|
||||||
self.loop.add_reader(sock, client.loop_read)
|
self.loop.add_reader(sock, client.loop_read)
|
||||||
self.misc_task = self.loop.create_task(self.misc_loop())
|
self.misc_task = self.loop.create_task(self.misc_loop())
|
||||||
|
|
||||||
def _on_socket_close(
|
def _on_socket_close(self,
|
||||||
self,
|
client: paho_mqtt.Client,
|
||||||
client: paho_mqtt.Client,
|
userdata: Any,
|
||||||
userdata: Any,
|
sock: socket.socket
|
||||||
sock: socket.socket | paho_mqtt.SocketLike
|
) -> None:
|
||||||
) -> None:
|
|
||||||
logging.info("MQTT Socket Closed")
|
logging.info("MQTT Socket Closed")
|
||||||
self.loop.remove_reader(sock)
|
self.loop.remove_reader(sock)
|
||||||
if self.misc_task is not None:
|
if self.misc_task is not None:
|
||||||
self.misc_task.cancel()
|
self.misc_task.cancel()
|
||||||
|
|
||||||
def _on_socket_register_write(
|
def _on_socket_register_write(self,
|
||||||
self,
|
client: paho_mqtt.Client,
|
||||||
client: paho_mqtt.Client,
|
userdata: Any,
|
||||||
userdata: Any,
|
sock: socket.socket
|
||||||
sock: socket.socket | paho_mqtt.SocketLike
|
) -> None:
|
||||||
) -> None:
|
|
||||||
self.loop.add_writer(sock, client.loop_write)
|
self.loop.add_writer(sock, client.loop_write)
|
||||||
|
|
||||||
def _on_socket_unregister_write(
|
def _on_socket_unregister_write(self,
|
||||||
self,
|
client: paho_mqtt.Client,
|
||||||
client: paho_mqtt.Client,
|
userdata: Any,
|
||||||
userdata: Any,
|
sock: socket.socket
|
||||||
sock: socket.socket | paho_mqtt.SocketLike
|
) -> None:
|
||||||
) -> None:
|
|
||||||
self.loop.remove_writer(sock)
|
self.loop.remove_writer(sock)
|
||||||
|
|
||||||
async def misc_loop(self) -> None:
|
async def misc_loop(self) -> None:
|
||||||
|
|
@ -362,9 +354,7 @@ class MQTTClient(APITransport):
|
||||||
config.getboolean("publish_split_status", False)
|
config.getboolean("publish_split_status", False)
|
||||||
client_id: str = config.get("client_id", "")
|
client_id: str = config.get("client_id", "")
|
||||||
if PAHO_MQTT_VERSION < (2, 0):
|
if PAHO_MQTT_VERSION < (2, 0):
|
||||||
self.client = ExtPahoClient(
|
self.client = ExtPahoClient(client_id, protocol=self.protocol)
|
||||||
client_id, protocol=self.protocol # type: ignore
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
self.client = ExtPahoClient(
|
self.client = ExtPahoClient(
|
||||||
paho_mqtt.CallbackAPIVersion.VERSION1, client_id, # type: ignore
|
paho_mqtt.CallbackAPIVersion.VERSION1, client_id, # type: ignore
|
||||||
|
|
@ -482,7 +472,7 @@ class MQTTClient(APITransport):
|
||||||
self._publish_status_update(payload, self.last_status_time)
|
self._publish_status_update(payload, self.last_status_time)
|
||||||
|
|
||||||
def _on_message(self,
|
def _on_message(self,
|
||||||
client: str | paho_mqtt.Client,
|
client: str,
|
||||||
user_data: Any,
|
user_data: Any,
|
||||||
message: paho_mqtt.MQTTMessage
|
message: paho_mqtt.MQTTMessage
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
@ -501,8 +491,8 @@ class MQTTClient(APITransport):
|
||||||
client: paho_mqtt.Client,
|
client: paho_mqtt.Client,
|
||||||
user_data: Any,
|
user_data: Any,
|
||||||
flags: Dict[str, Any],
|
flags: Dict[str, Any],
|
||||||
reason_code: Union[int, ReasonCode],
|
reason_code: Union[int, paho_mqtt.ReasonCodes],
|
||||||
properties: Optional[Properties] = None
|
properties: Optional[paho_mqtt.Properties] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
logging.info("MQTT Client Connected")
|
logging.info("MQTT Client Connected")
|
||||||
if reason_code == 0:
|
if reason_code == 0:
|
||||||
|
|
@ -531,7 +521,7 @@ class MQTTClient(APITransport):
|
||||||
client: paho_mqtt.Client,
|
client: paho_mqtt.Client,
|
||||||
user_data: Any,
|
user_data: Any,
|
||||||
reason_code: int,
|
reason_code: int,
|
||||||
properties: Optional[Properties] = None
|
properties: Optional[paho_mqtt.Properties] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
if self.disconnect_evt is not None:
|
if self.disconnect_evt is not None:
|
||||||
self.disconnect_evt.set()
|
self.disconnect_evt.set()
|
||||||
|
|
@ -557,8 +547,8 @@ class MQTTClient(APITransport):
|
||||||
client: paho_mqtt.Client,
|
client: paho_mqtt.Client,
|
||||||
user_data: Any,
|
user_data: Any,
|
||||||
msg_id: int,
|
msg_id: int,
|
||||||
flex: Union[List[int], List[ReasonCode]],
|
flex: Union[List[int], List[paho_mqtt.ReasonCodes]],
|
||||||
properties: Optional[Properties] = None
|
properties: Optional[paho_mqtt.Properties] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
sub_fut = self.pending_acks.pop(msg_id, None)
|
sub_fut = self.pending_acks.pop(msg_id, None)
|
||||||
if sub_fut is not None and not sub_fut.done():
|
if sub_fut is not None and not sub_fut.done():
|
||||||
|
|
@ -568,8 +558,8 @@ class MQTTClient(APITransport):
|
||||||
client: paho_mqtt.Client,
|
client: paho_mqtt.Client,
|
||||||
user_data: Any,
|
user_data: Any,
|
||||||
msg_id: int,
|
msg_id: int,
|
||||||
properties: Optional[Properties] = None,
|
properties: Optional[paho_mqtt.Properties] = None,
|
||||||
reasoncodes: Optional[ReasonCode] = None
|
reasoncodes: Optional[paho_mqtt.ReasonCodes] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
unsub_fut = self.pending_acks.pop(msg_id, None)
|
unsub_fut = self.pending_acks.pop(msg_id, None)
|
||||||
if unsub_fut is not None and not unsub_fut.done():
|
if unsub_fut is not None and not unsub_fut.done():
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,7 @@ import asyncio
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import contextlib
|
import contextlib
|
||||||
import base64
|
|
||||||
import tornado.websocket as tornado_ws
|
import tornado.websocket as tornado_ws
|
||||||
from tornado.httpclient import HTTPRequest
|
|
||||||
from tornado import version_info as tornado_version
|
from tornado import version_info as tornado_version
|
||||||
from ..common import RequestType, HistoryFieldData
|
from ..common import RequestType, HistoryFieldData
|
||||||
from ..utils import json_wrapper as jsonw
|
from ..utils import json_wrapper as jsonw
|
||||||
|
|
@ -88,23 +86,6 @@ class SpoolManager:
|
||||||
self.spoolman_url = f"{scheme}://{host}/api"
|
self.spoolman_url = f"{scheme}://{host}/api"
|
||||||
self.ws_url = f"{ws_scheme}://{host}/api/v1/spool"
|
self.ws_url = f"{ws_scheme}://{host}/api/v1/spool"
|
||||||
|
|
||||||
headers_raw = config.get("headers", "")
|
|
||||||
self.http_headers = {}
|
|
||||||
for c in headers_raw.split(";"):
|
|
||||||
c = c.strip()
|
|
||||||
if not c:
|
|
||||||
continue
|
|
||||||
c_parts = c.split(":", 1)
|
|
||||||
if len(c_parts) != 2:
|
|
||||||
raise config.error(f"Section [spoolman], Option headers: {c}: Invalid header format")
|
|
||||||
self.http_headers[c_parts[0]] = c_parts[1]
|
|
||||||
|
|
||||||
username = config.get("http_username", None)
|
|
||||||
password = config.get("http_password", None)
|
|
||||||
if username and password:
|
|
||||||
creds = base64.b64encode(f"{username}:{password}".encode()).decode()
|
|
||||||
self.http_headers["Authorization"] = "Basic " + creds
|
|
||||||
|
|
||||||
def _register_notifications(self):
|
def _register_notifications(self):
|
||||||
self.server.register_notification("spoolman:active_spool_set")
|
self.server.register_notification("spoolman:active_spool_set")
|
||||||
self.server.register_notification("spoolman:spoolman_status_changed")
|
self.server.register_notification("spoolman:spoolman_status_changed")
|
||||||
|
|
@ -149,10 +130,10 @@ class SpoolManager:
|
||||||
if log_connect:
|
if log_connect:
|
||||||
logging.info(f"Connecting To Spoolman: {self.ws_url}")
|
logging.info(f"Connecting To Spoolman: {self.ws_url}")
|
||||||
log_connect = False
|
log_connect = False
|
||||||
request = HTTPRequest(url=self.ws_url, headers=self.http_headers, connect_timeout=5.)
|
|
||||||
try:
|
try:
|
||||||
self.spoolman_ws = await tornado_ws.websocket_connect(
|
self.spoolman_ws = await tornado_ws.websocket_connect(
|
||||||
request,
|
self.ws_url,
|
||||||
|
connect_timeout=5.,
|
||||||
ping_interval=None if tornado_version < (6, 5) else 20.
|
ping_interval=None if tornado_version < (6, 5) else 20.
|
||||||
)
|
)
|
||||||
setattr(self.spoolman_ws, "on_ping", self._on_ws_ping)
|
setattr(self.spoolman_ws, "on_ping", self._on_ws_ping)
|
||||||
|
|
@ -236,7 +217,7 @@ class SpoolManager:
|
||||||
if self.spool_id is not None:
|
if self.spool_id is not None:
|
||||||
response = await self.http_client.get(
|
response = await self.http_client.get(
|
||||||
f"{self.spoolman_url}/v1/spool/{self.spool_id}",
|
f"{self.spoolman_url}/v1/spool/{self.spool_id}",
|
||||||
connect_timeout=1., request_timeout=2., headers=self.http_headers
|
connect_timeout=1., request_timeout=2.
|
||||||
)
|
)
|
||||||
if response.status_code == 404:
|
if response.status_code == 404:
|
||||||
logging.info(f"Spool ID {self.spool_id} not found, setting to None")
|
logging.info(f"Spool ID {self.spool_id} not found, setting to None")
|
||||||
|
|
@ -327,8 +308,7 @@ class SpoolManager:
|
||||||
response = await self.http_client.request(
|
response = await self.http_client.request(
|
||||||
method="PUT",
|
method="PUT",
|
||||||
url=f"{self.spoolman_url}/v1/spool/{spool_id}/use",
|
url=f"{self.spoolman_url}/v1/spool/{spool_id}/use",
|
||||||
body={"use_length": used_length},
|
body={"use_length": used_length}
|
||||||
headers=self.http_headers
|
|
||||||
)
|
)
|
||||||
if response.has_error():
|
if response.has_error():
|
||||||
if response.status_code == 404:
|
if response.status_code == 404:
|
||||||
|
|
@ -390,7 +370,6 @@ class SpoolManager:
|
||||||
method=method,
|
method=method,
|
||||||
url=full_url,
|
url=full_url,
|
||||||
body=body,
|
body=body,
|
||||||
headers=self.http_headers
|
|
||||||
)
|
)
|
||||||
if not use_v2_response:
|
if not use_v2_response:
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
|
||||||
|
|
@ -392,9 +392,6 @@ class PackageKitTransaction:
|
||||||
summary: str
|
summary: str
|
||||||
) -> None:
|
) -> None:
|
||||||
info = PkEnum.Info.from_index(info_code & 0xFFFF)
|
info = PkEnum.Info.from_index(info_code & 0xFFFF)
|
||||||
severity = PkEnum.Info.from_index((info_code >> 16) & 0xFFFF)
|
|
||||||
if info == PkEnum.Info.UNKNOWN:
|
|
||||||
info = severity
|
|
||||||
if self._role in self.GET_PKG_ROLES:
|
if self._role in self.GET_PKG_ROLES:
|
||||||
pkg_data = {
|
pkg_data = {
|
||||||
'package_id': package_id,
|
'package_id': package_id,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
#
|
#
|
||||||
# This file may be distributed under the terms of the GNU GPLv3 license
|
# This file may be distributed under the terms of the GNU GPLv3 license
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import os
|
|
||||||
import shlex
|
import shlex
|
||||||
import re
|
import re
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
@ -62,22 +61,15 @@ class SysDepsParser:
|
||||||
version = distro_info.get("distro_version")
|
version = distro_info.get("distro_version")
|
||||||
if version:
|
if version:
|
||||||
self.distro_version = _convert_version(version)
|
self.distro_version = _convert_version(version)
|
||||||
self.vendor: str = os.getenv("MOONRAKER_VENDOR", "")
|
self.vendor: str = ""
|
||||||
if not self.vendor and pathlib.Path("/etc/rpi-issue").is_file():
|
if pathlib.Path("/etc/rpi-issue").is_file():
|
||||||
self.vendor = "raspberry-pi"
|
self.vendor = "raspberry-pi"
|
||||||
exclusions = os.getenv("MOONRAKER_EXCLUDED_PKGS", "")
|
|
||||||
self.exclusions: List[str] = [
|
|
||||||
excl.strip() for excl in exclusions.split() if excl.strip()
|
|
||||||
]
|
|
||||||
|
|
||||||
def _parse_spec(self, full_spec: str) -> str | None:
|
def _parse_spec(self, full_spec: str) -> str | None:
|
||||||
parts = full_spec.split(";", maxsplit=1)
|
parts = full_spec.split(";", maxsplit=1)
|
||||||
pkg_name = parts[0].strip()
|
|
||||||
if pkg_name in self.exclusions or not pkg_name:
|
|
||||||
logging.info(f"Package '{full_spec}' excluded by environment")
|
|
||||||
return None
|
|
||||||
if len(parts) == 1:
|
if len(parts) == 1:
|
||||||
return pkg_name
|
return full_spec
|
||||||
|
pkg_name = parts[0].strip()
|
||||||
expressions = re.split(r"( and | or )", parts[1].strip())
|
expressions = re.split(r"( and | or )", parts[1].strip())
|
||||||
if not len(expressions) & 1:
|
if not len(expressions) & 1:
|
||||||
# There should always be an odd number of expressions. Each
|
# There should always be an odd number of expressions. Each
|
||||||
|
|
|
||||||
|
|
@ -6,22 +6,23 @@ authors = [
|
||||||
{name = "Eric Callahan", email = "arksine.code@gmail.com"},
|
{name = "Eric Callahan", email = "arksine.code@gmail.com"},
|
||||||
]
|
]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tornado>=6.2.0, <=6.5.4",
|
"tornado>=6.2.0, <=6.5.1",
|
||||||
"pyserial==3.4",
|
"pyserial==3.4",
|
||||||
"pillow>=9.5.0, <=12.1.0",
|
"pillow>=9.5.0, <=11.1.0",
|
||||||
"streaming-form-data>=1.11.0, <=1.19.1",
|
"streaming-form-data>=1.11.0, <=1.19.1",
|
||||||
"distro==1.9.0",
|
"distro==1.9.0",
|
||||||
"inotify-simple==2.0.1",
|
"inotify-simple==1.3.5",
|
||||||
"libnacl==2.1.0",
|
"libnacl==2.1.0",
|
||||||
"paho-mqtt==2.1.0",
|
"paho-mqtt==1.6.1",
|
||||||
"zeroconf>=0.131.0, <=0.148.0",
|
"zeroconf==0.131.0",
|
||||||
"preprocess-cancellation==0.2.1",
|
"preprocess-cancellation==0.2.1",
|
||||||
"jinja2==3.1.6",
|
"jinja2==3.1.5",
|
||||||
"dbus-fast>=2.21.3, <=3.1.2",
|
"dbus-fast>=2.21.3, <=2.44.1",
|
||||||
"apprise>=1.9.3, <=1.9.6",
|
"apprise==1.9.2",
|
||||||
"ldap3==2.9.1",
|
"ldap3==2.9.1",
|
||||||
"python-periphery==2.4.1",
|
"python-periphery==2.4.1",
|
||||||
"importlib_metadata>=6.7.0, <=8.7.1"
|
"importlib_metadata==6.7.0 ; python_version=='3.7'",
|
||||||
|
"importlib_metadata==8.2.0 ; python_version>='3.8'"
|
||||||
]
|
]
|
||||||
requires-python = ">=3.7"
|
requires-python = ">=3.7"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
@ -37,8 +38,6 @@ classifiers = [
|
||||||
"Programming Language :: Python :: 3.10",
|
"Programming Language :: Python :: 3.10",
|
||||||
"Programming Language :: Python :: 3.11",
|
"Programming Language :: Python :: 3.11",
|
||||||
"Programming Language :: Python :: 3.12",
|
"Programming Language :: Python :: 3.12",
|
||||||
"Programming Language :: Python :: 3.13",
|
|
||||||
"Programming Language :: Python :: 3.14"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
|
|
@ -54,7 +53,7 @@ speedups = [
|
||||||
"msgspec>=0.18.4 ; python_version>='3.8'",
|
"msgspec>=0.18.4 ; python_version>='3.8'",
|
||||||
"uvloop>=0.17.0"
|
"uvloop>=0.17.0"
|
||||||
]
|
]
|
||||||
dev = ["pre-commit", "build", "mypy", "ruff", "twine"]
|
dev = ["pre-commit"]
|
||||||
|
|
||||||
[tool.pdm.version]
|
[tool.pdm.version]
|
||||||
source = "scm"
|
source = "scm"
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@ LOG_PATH="${MOONRAKER_LOG_PATH}"
|
||||||
DATA_PATH="${MOONRAKER_DATA_PATH}"
|
DATA_PATH="${MOONRAKER_DATA_PATH}"
|
||||||
INSTANCE_ALIAS="${MOONRAKER_ALIAS:-moonraker}"
|
INSTANCE_ALIAS="${MOONRAKER_ALIAS:-moonraker}"
|
||||||
SPEEDUPS="${MOONRAKER_SPEEDUPS:-n}"
|
SPEEDUPS="${MOONRAKER_SPEEDUPS:-n}"
|
||||||
DEV_INSTALL="${MOONRAKER_DEV_INSTALL:-n}"
|
|
||||||
PY_INST_TYPE="${MOONRAKER_PYTHON_INSTALL_TYPE:-venv}"
|
|
||||||
SERVICE_VERSION="1"
|
SERVICE_VERSION="1"
|
||||||
DISTRIBUTION=""
|
DISTRIBUTION=""
|
||||||
DISTRO_VERSION=""
|
DISTRO_VERSION=""
|
||||||
|
|
@ -27,14 +25,6 @@ if [ ! -z "${MOONRAKER_FORCE_DEFAULTS}" ]; then
|
||||||
FORCE_SYSTEM_INSTALL=$MOONRAKER_FORCE_DEFAULTS
|
FORCE_SYSTEM_INSTALL=$MOONRAKER_FORCE_DEFAULTS
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if this is a dev container, apply dev defaults if not set by environment
|
|
||||||
if [ "${MOONRAKER_VENDOR}" = "vscode-dev" ]; then
|
|
||||||
echo "VSCode Dev Container detected..."
|
|
||||||
[ -z "${MOONRAKER_DEV_INSTALL}" ] && DEV_INSTALL="y"
|
|
||||||
[ -z "${MOONRAKER_PYTHON_INSTALL_TYPE}" ] && PY_INST_TYPE="user"
|
|
||||||
[ -z "${MOONRAKER_DISABLE_SYSTEMCTL}" ] && DISABLE_SYSTEMCTL="y"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Force script to exit if an error occurs
|
# Force script to exit if an error occurs
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
|
@ -44,7 +34,6 @@ SRCDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
|
||||||
# Determine if Moonraker is to be installed from source
|
# Determine if Moonraker is to be installed from source
|
||||||
if [ -f "${SRCDIR}/moonraker/__init__.py" ]; then
|
if [ -f "${SRCDIR}/moonraker/__init__.py" ]; then
|
||||||
echo "Installing from Moonraker source..."
|
echo "Installing from Moonraker source..."
|
||||||
cd $SRCDIR
|
|
||||||
IS_SRC_DIST="y"
|
IS_SRC_DIST="y"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -59,7 +48,6 @@ detect_distribution() {
|
||||||
# *** AUTO GENERATED OS PACKAGE SCRIPT START ***
|
# *** AUTO GENERATED OS PACKAGE SCRIPT START ***
|
||||||
get_pkgs_script=$(cat << EOF
|
get_pkgs_script=$(cat << EOF
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import os
|
|
||||||
import shlex
|
import shlex
|
||||||
import re
|
import re
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
@ -113,22 +101,15 @@ class SysDepsParser:
|
||||||
version = distro_info.get("distro_version")
|
version = distro_info.get("distro_version")
|
||||||
if version:
|
if version:
|
||||||
self.distro_version = _convert_version(version)
|
self.distro_version = _convert_version(version)
|
||||||
self.vendor: str = os.getenv("MOONRAKER_VENDOR", "")
|
self.vendor: str = ""
|
||||||
if not self.vendor and pathlib.Path("/etc/rpi-issue").is_file():
|
if pathlib.Path("/etc/rpi-issue").is_file():
|
||||||
self.vendor = "raspberry-pi"
|
self.vendor = "raspberry-pi"
|
||||||
exclusions = os.getenv("MOONRAKER_EXCLUDED_PKGS", "")
|
|
||||||
self.exclusions: List[str] = [
|
|
||||||
excl.strip() for excl in exclusions.split() if excl.strip()
|
|
||||||
]
|
|
||||||
|
|
||||||
def _parse_spec(self, full_spec: str) -> str | None:
|
def _parse_spec(self, full_spec: str) -> str | None:
|
||||||
parts = full_spec.split(";", maxsplit=1)
|
parts = full_spec.split(";", maxsplit=1)
|
||||||
pkg_name = parts[0].strip()
|
|
||||||
if pkg_name in self.exclusions or not pkg_name:
|
|
||||||
logging.info(f"Package '{full_spec}' excluded by environment")
|
|
||||||
return None
|
|
||||||
if len(parts) == 1:
|
if len(parts) == 1:
|
||||||
return pkg_name
|
return full_spec
|
||||||
|
pkg_name = parts[0].strip()
|
||||||
expressions = re.split(r"( and | or )", parts[1].strip())
|
expressions = re.split(r"( and | or )", parts[1].strip())
|
||||||
if not len(expressions) & 1:
|
if not len(expressions) & 1:
|
||||||
logging.info(
|
logging.info(
|
||||||
|
|
@ -156,7 +137,7 @@ class SysDepsParser:
|
||||||
continue
|
continue
|
||||||
elif last_logical_op is None:
|
elif last_logical_op is None:
|
||||||
logging.info(
|
logging.info(
|
||||||
f"Requirement specifier contains two sequential expressions "
|
f"Requirement specifier contains two seqential expressions "
|
||||||
f"without a logical operator: {full_spec}")
|
f"without a logical operator: {full_spec}")
|
||||||
return None
|
return None
|
||||||
dep_parts = re.split(r"(==|!=|<=|>=|<|>)", exp.strip())
|
dep_parts = re.split(r"(==|!=|<=|>=|<|>)", exp.strip())
|
||||||
|
|
@ -289,52 +270,38 @@ install_packages()
|
||||||
# Step 4: Create python virtual environment
|
# Step 4: Create python virtual environment
|
||||||
create_virtualenv()
|
create_virtualenv()
|
||||||
{
|
{
|
||||||
if [ $PY_INST_TYPE = "system" ]; then
|
report_status "Installing python virtual environment..."
|
||||||
pip_inst="pip install"
|
|
||||||
elif [ $PY_INST_TYPE = "user" ]; then
|
|
||||||
pip_inst="pip install --user"
|
|
||||||
else
|
|
||||||
pip_inst="${PYTHONDIR}/bin/pip install"
|
|
||||||
report_status "Installing python virtual environment..."
|
|
||||||
|
|
||||||
# If venv exists and user prompts a rebuild, then do so
|
# If venv exists and user prompts a rebuild, then do so
|
||||||
if [ -d ${PYTHONDIR} ] && [ $REBUILD_ENV = "y" ]; then
|
if [ -d ${PYTHONDIR} ] && [ $REBUILD_ENV = "y" ]; then
|
||||||
report_status "Removing old virtualenv"
|
report_status "Removing old virtualenv"
|
||||||
rm -rf ${PYTHONDIR}
|
rm -rf ${PYTHONDIR}
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -d ${PYTHONDIR} ]; then
|
|
||||||
virtualenv -p python3 ${PYTHONDIR}
|
|
||||||
#GET_PIP="${HOME}/get-pip.py"
|
|
||||||
#curl https://bootstrap.pypa.io/pip/3.6/get-pip.py -o ${GET_PIP}
|
|
||||||
#${PYTHONDIR}/bin/python ${GET_PIP}
|
|
||||||
#rm ${GET_PIP}
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
echo "Using pip install command '${pip_inst}'..."
|
|
||||||
|
if [ ! -d ${PYTHONDIR} ]; then
|
||||||
|
virtualenv -p /usr/bin/python3 ${PYTHONDIR}
|
||||||
|
#GET_PIP="${HOME}/get-pip.py"
|
||||||
|
#curl https://bootstrap.pypa.io/pip/3.6/get-pip.py -o ${GET_PIP}
|
||||||
|
#${PYTHONDIR}/bin/python ${GET_PIP}
|
||||||
|
#rm ${GET_PIP}
|
||||||
|
fi
|
||||||
|
|
||||||
# Install/update dependencies
|
# Install/update dependencies
|
||||||
export SKIP_CYTHON=1
|
export SKIP_CYTHON=1
|
||||||
if [ $IS_SRC_DIST = "y" ]; then
|
if [ $IS_SRC_DIST = "y" ]; then
|
||||||
report_status "Installing Moonraker python dependencies..."
|
report_status "Installing Moonraker python dependencies..."
|
||||||
$pip_inst -r ${SRCDIR}/scripts/moonraker-requirements.txt
|
${PYTHONDIR}/bin/pip install -r ${SRCDIR}/scripts/moonraker-requirements.txt
|
||||||
|
|
||||||
if [ $DEV_INSTALL = "y" ]; then
|
if [ ${SPEEDUPS} = "y" ]; then
|
||||||
report_status "Installing dev requirements..."
|
|
||||||
$pip_inst -r ${SRCDIR}/scripts/moonraker-speedups.txt
|
|
||||||
$pip_inst -r ${SRCDIR}/scripts/moonraker-dev-reqs.txt
|
|
||||||
$pip_inst -r ${SRCDIR}/docs/doc-requirements.txt
|
|
||||||
elif [ $SPEEDUPS = "y" ]; then
|
|
||||||
report_status "Installing Speedups..."
|
report_status "Installing Speedups..."
|
||||||
$pip_inst -r ${SRCDIR}/scripts/moonraker-speedups.txt
|
${PYTHONDIR}/bin/pip install -r ${SRCDIR}/scripts/moonraker-speedups.txt
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
report_status "Installing Moonraker package via Pip..."
|
report_status "Installing Moonraker package via Pip..."
|
||||||
if [ $DEV_INSTALL = "y" ]; then
|
if [ ${SPEEDUPS} = "y" ]; then
|
||||||
$pip_inst -U moonraker[speedups,dev]
|
${PYTHONDIR}/bin/pip install -U moonraker[speedups]
|
||||||
elif [ $SPEEDUPS = "y" ]; then
|
|
||||||
$pip_inst -U moonraker[speedups]
|
|
||||||
else
|
else
|
||||||
$pip_inst -U moonraker
|
${PYTHONDIR}/bin/pip install -U moonraker
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
@ -382,13 +349,9 @@ EOF
|
||||||
# Step 6: Install startup script
|
# Step 6: Install startup script
|
||||||
install_script()
|
install_script()
|
||||||
{
|
{
|
||||||
if [ ! -d $SYSTEMDDIR ]; then
|
|
||||||
report_status "Systemd not detected, aborting service installation"
|
|
||||||
fi
|
|
||||||
# Create systemd service file
|
# Create systemd service file
|
||||||
ENV_FILE="${DATA_PATH}/systemd/moonraker.env"
|
ENV_FILE="${DATA_PATH}/systemd/moonraker.env"
|
||||||
if [ ! -f $ENV_FILE ] || [ $FORCE_SYSTEM_INSTALL = "y" ]; then
|
if [ ! -f $ENV_FILE ] || [ $FORCE_SYSTEM_INSTALL = "y" ]; then
|
||||||
report_status "Creating systemd environment file ${ENV_FILE}..."
|
|
||||||
rm -f $ENV_FILE
|
rm -f $ENV_FILE
|
||||||
env_vars="MOONRAKER_DATA_PATH=\"${DATA_PATH}\""
|
env_vars="MOONRAKER_DATA_PATH=\"${DATA_PATH}\""
|
||||||
[ -n "${CONFIG_PATH}" ] && env_vars="${env_vars}\nMOONRAKER_CONFIG_PATH=\"${CONFIG_PATH}\""
|
[ -n "${CONFIG_PATH}" ] && env_vars="${env_vars}\nMOONRAKER_CONFIG_PATH=\"${CONFIG_PATH}\""
|
||||||
|
|
@ -398,9 +361,7 @@ install_script()
|
||||||
echo -e $env_vars > $ENV_FILE
|
echo -e $env_vars > $ENV_FILE
|
||||||
fi
|
fi
|
||||||
[ -f $SERVICE_FILE ] && [ $FORCE_SYSTEM_INSTALL = "n" ] && return
|
[ -f $SERVICE_FILE ] && [ $FORCE_SYSTEM_INSTALL = "n" ] && return
|
||||||
report_status "Installing systemd service unit..."
|
report_status "Installing system start script..."
|
||||||
python_bin="${PYTHONDIR}/bin/python"
|
|
||||||
[ $PY_INST_TYPE != "venv" ] && python_bin="python3"
|
|
||||||
sudo groupadd -f moonraker-admin
|
sudo groupadd -f moonraker-admin
|
||||||
sudo /bin/sh -c "cat > ${SERVICE_FILE}" << EOF
|
sudo /bin/sh -c "cat > ${SERVICE_FILE}" << EOF
|
||||||
# systemd service file for moonraker
|
# systemd service file for moonraker
|
||||||
|
|
@ -418,7 +379,7 @@ User=$USER
|
||||||
SupplementaryGroups=moonraker-admin
|
SupplementaryGroups=moonraker-admin
|
||||||
RemainAfterExit=yes
|
RemainAfterExit=yes
|
||||||
EnvironmentFile=${ENV_FILE}
|
EnvironmentFile=${ENV_FILE}
|
||||||
ExecStart=${python_bin} \$MOONRAKER_ARGS
|
ExecStart=${PYTHONDIR}/bin/python \$MOONRAKER_ARGS
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=10
|
RestartSec=10
|
||||||
EOF
|
EOF
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1 @@
|
||||||
pre-commit
|
pre-commit
|
||||||
build
|
|
||||||
mypy
|
|
||||||
ruff
|
|
||||||
twine
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,19 @@
|
||||||
# Python dependencies for Moonraker
|
# Python dependencies for Moonraker
|
||||||
--find-links=python_wheels
|
--find-links=python_wheels
|
||||||
tornado>=6.2.0, <=6.5.4
|
tornado>=6.2.0, <=6.5.1
|
||||||
pyserial==3.4
|
pyserial==3.4
|
||||||
pillow>=9.5.0, <=12.1.0
|
pillow>=9.5.0, <=11.1.0
|
||||||
streaming-form-data>=1.11.0, <=1.19.1
|
streaming-form-data>=1.11.0, <=1.19.1
|
||||||
distro==1.9.0
|
distro==1.9.0
|
||||||
inotify-simple==2.0.1
|
inotify-simple==1.3.5
|
||||||
libnacl==2.1.0
|
libnacl==2.1.0
|
||||||
paho-mqtt==2.1.0
|
paho-mqtt==1.6.1
|
||||||
zeroconf>=0.131.0, <=0.148.0
|
zeroconf==0.131.0
|
||||||
preprocess-cancellation==0.2.1
|
preprocess-cancellation==0.2.1
|
||||||
jinja2==3.1.6
|
jinja2==3.1.5
|
||||||
dbus-fast>=2.21.3, <=3.1.2
|
dbus-fast>=2.21.3, <=2.44.1
|
||||||
apprise>=1.9.3, <=1.9.6
|
apprise==1.9.2
|
||||||
ldap3==2.9.1
|
ldap3==2.9.1
|
||||||
python-periphery==2.4.1
|
python-periphery==2.4.1
|
||||||
importlib_metadata>=6.7.0, <=8.7.1
|
importlib_metadata==6.7.0 ; python_version=='3.7'
|
||||||
|
importlib_metadata==8.2.0 ; python_version>='3.8'
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue