Merge remote-tracking branch 'origin/master' into doxygen_to_restructuredtext_comments

# Conflicts:
#	cura/API/__init__.py
#	cura/Settings/CuraContainerRegistry.py
#	cura/Settings/ExtruderManager.py
#	plugins/PostProcessingPlugin/scripts/PauseAtHeight.py
#	plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py
#	plugins/UM3NetworkPrinting/src/Cloud/ToolPathUploader.py
#	plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDeviceManager.py
This commit is contained in:
Nino van Hooff 2020-05-28 17:31:24 +02:00
commit 58ffc9dcae
234 changed files with 3945 additions and 1142 deletions

View file

@ -1,11 +1,11 @@
# Copyright (c) 2019 Ultimaker B.V.
# !/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5.QtCore import QUrl
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager
from typing import Optional, Callable, Any, Tuple, cast
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
from typing import Callable, Any, Tuple, cast, Dict, Optional
from UM.Logger import Logger
from UM.TaskManagement.HttpRequestManager import HttpRequestManager
from ..Models.Http.CloudPrintJobResponse import CloudPrintJobResponse
@ -23,11 +23,11 @@ class ToolPathUploader:
# The amount of bytes to send per request
BYTES_PER_REQUEST = 256 * 1024
def __init__(self, manager: QNetworkAccessManager, print_job: CloudPrintJobResponse, data: bytes,
def __init__(self, http: HttpRequestManager, print_job: CloudPrintJobResponse, data: bytes,
on_finished: Callable[[], Any], on_progress: Callable[[int], Any], on_error: Callable[[], Any]
) -> None:
"""Creates a mesh upload object.
:param manager: The network access manager that will handle the HTTP requests.
:param print_job: The print job response that was returned by the cloud after registering the upload.
:param data: The mesh bytes to be uploaded.
@ -36,7 +36,7 @@ class ToolPathUploader:
:param on_error: The method to be called when an error occurs.
"""
self._manager = manager
self._http = http
self._print_job = print_job
self._data = data
@ -47,7 +47,6 @@ class ToolPathUploader:
self._sent_bytes = 0
self._retries = 0
self._finished = False
self._reply = None # type: Optional[QNetworkReply]
@property
def printJob(self):
@ -55,22 +54,9 @@ class ToolPathUploader:
return self._print_job
def _createRequest(self) -> QNetworkRequest:
"""Creates a network request to the print job upload URL, adding the needed content range header."""
request = QNetworkRequest(QUrl(self._print_job.upload_url))
request.setHeader(QNetworkRequest.ContentTypeHeader, self._print_job.content_type)
first_byte, last_byte = self._chunkRange()
content_range = "bytes {}-{}/{}".format(first_byte, last_byte - 1, len(self._data))
request.setRawHeader(b"Content-Range", content_range.encode())
Logger.log("i", "Uploading %s to %s", content_range, self._print_job.upload_url)
return request
def _chunkRange(self) -> Tuple[int, int]:
"""Determines the bytes that should be uploaded next.
:return: A tuple with the first and the last byte to upload.
"""
last_byte = min(len(self._data), self._sent_bytes + self.BYTES_PER_REQUEST)
@ -99,17 +85,27 @@ class ToolPathUploader:
raise ValueError("The upload is already finished")
first_byte, last_byte = self._chunkRange()
request = self._createRequest()
content_range = "bytes {}-{}/{}".format(first_byte, last_byte - 1, len(self._data))
# now send the reply and subscribe to the results
self._reply = self._manager.put(request, self._data[first_byte:last_byte])
self._reply.finished.connect(self._finishedCallback)
self._reply.uploadProgress.connect(self._progressCallback)
self._reply.error.connect(self._errorCallback)
headers = {
"Content-Type": cast(str, self._print_job.content_type),
"Content-Range": content_range
} # type: Dict[str, str]
Logger.log("i", "Uploading %s to %s", content_range, self._print_job.upload_url)
self._http.put(
url = cast(str, self._print_job.upload_url),
headers_dict = headers,
data = self._data[first_byte:last_byte],
callback = self._finishedCallback,
error_callback = self._errorCallback,
upload_progress_callback = self._progressCallback
)
def _progressCallback(self, bytes_sent: int, bytes_total: int) -> None:
"""Handles an update to the upload progress
:param bytes_sent: The amount of bytes sent in the current request.
:param bytes_total: The amount of bytes to send in the current request.
"""
@ -118,7 +114,8 @@ class ToolPathUploader:
total_sent = self._sent_bytes + bytes_sent
self._on_progress(int(total_sent / len(self._data) * 100))
def _errorCallback(self) -> None:
## Handles an error uploading.
def _errorCallback(self, reply: QNetworkReply, error: QNetworkReply.NetworkError) -> None:
"""Handles an error uploading."""
reply = cast(QNetworkReply, self._reply)
@ -127,7 +124,7 @@ class ToolPathUploader:
self.stop()
self._on_error()
def _finishedCallback(self) -> None:
def _finishedCallback(self, reply: QNetworkReply) -> None:
"""Checks whether a chunk of data was uploaded successfully, starting the next chunk if needed."""
reply = cast(QNetworkReply, self._reply)
@ -148,7 +145,7 @@ class ToolPathUploader:
# Http codes that are not to be retried are assumed to be errors.
if status_code > 308:
self._errorCallback()
self._errorCallback(reply, None)
return
Logger.log("d", "status_code: %s, Headers: %s, body: %s", status_code,