예제 #1
0
    def _onUploadFinished(self, reply: QNetworkReply) -> None:
        """
        Checks whether a chunk of data was uploaded successfully, starting the next chunk if needed.
        """

        Logger.log("i", "Finished callback %s %s",
                   reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url().toString())

        status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)  # type: Optional[int]
        if not status_code:
            Logger.log("e", "Reply contained no status code.")
            self._onUploadError(reply, None)
            return

        # check if we should retry the last chunk
        if self._retries < self.MAX_RETRIES and status_code in self.RETRY_HTTP_CODES:
            self._retries += 1
            Logger.log("i", "Retrying %s/%s request %s", self._retries, self.MAX_RETRIES, reply.url().toString())
            try:
                self._upload()
            except ValueError:  # Asynchronously it could have completed in the meanwhile.
                pass
            return

        # Http codes that are not to be retried are assumed to be errors.
        if status_code > 308:
            self._onUploadError(reply, None)
            return

        Logger.log("d", "status_code: %s, Headers: %s, body: %s", status_code,
                   [bytes(header).decode() for header in reply.rawHeaderList()], bytes(reply.readAll()).decode())
        self._on_success(self._file_name)
        self.stop()
예제 #2
0
    def _finishedCallback(self, reply: QNetworkReply) -> None:
        Logger.log("i", "Finished callback %s %s",
                   reply.attribute(QNetworkRequest.HttpStatusCodeAttribute),
                   reply.url().toString())

        status_code = reply.attribute(
            QNetworkRequest.HttpStatusCodeAttribute)  # type: int

        # check if we should retry the last chunk
        if self._retries < self.MAX_RETRIES and status_code in self.RETRY_HTTP_CODES:
            self._retries += 1
            Logger.log("i", "Retrying %s/%s request %s", self._retries,
                       self.MAX_RETRIES,
                       reply.url().toString())
            try:
                self._uploadChunk()
            except ValueError:  # Asynchronously it could have completed in the meanwhile.
                pass
            return

        # Http codes that are not to be retried are assumed to be errors.
        if status_code > 308:
            self._errorCallback(reply, None)
            return

        Logger.log(
            "d", "status_code: %s, Headers: %s, body: %s", status_code,
            [bytes(header).decode() for header in reply.rawHeaderList()],
            bytes(reply.readAll()).decode())
        self._chunkUploaded()
예제 #3
0
 def sendingFinished(self, reply: QNetworkReply):
     if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
         Logger.log(
             "e",
             "Received error code from printer when syncing material: {code}"
             .format(code=reply.attribute(
                 QNetworkRequest.HttpStatusCodeAttribute)))
         Logger.log("e", reply.readAll().data().decode("utf-8"))
예제 #4
0
 def sendingFinished(reply: QNetworkReply) -> None:
     if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
         Logger.log(
             "e",
             "Received error code from printer when syncing material: {code}, {text}"
             .format(code=reply.attribute(
                 QNetworkRequest.HttpStatusCodeAttribute),
                     text=reply.errorString()))
예제 #5
0
 def log_request(self, reply: QNetworkReply) -> None:
     self.logger.info('request made at %s' % reply.header(
         QNetworkRequest.LastModifiedHeader).toString('dd-MM-yyyy hh:mm:ss')
                      )
     self.logger.info(
         'response: %s (%i)  type: %s' %
         (reply.attribute(
             QNetworkRequest.HttpReasonPhraseAttribute).upper(),
          reply.attribute(QNetworkRequest.HttpStatusCodeAttribute),
          reply.header(QNetworkRequest.ContentTypeHeader)))
예제 #6
0
    def _onUploadSlotCompleted(
            self,
            reply: QNetworkReply,
            error: Optional["QNetworkReply.NetworkError"] = None) -> None:
        if error is not None:
            Logger.warning(str(error))
            self.backup_upload_error_message = self.DEFAULT_UPLOAD_ERROR_MESSAGE
            self._job_done.set()
            return
        if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) >= 300:
            Logger.warning("Could not request backup upload: %s",
                           HttpRequestManager.readText(reply))
            self.backup_upload_error_message = self.DEFAULT_UPLOAD_ERROR_MESSAGE
            self._job_done.set()
            return

        backup_upload_url = HttpRequestManager.readJSON(
            reply)["data"]["upload_url"]

        # Upload the backup to storage.
        HttpRequestManager.getInstance().put(
            backup_upload_url,
            data=self._backup_zip,
            callback=self._uploadFinishedCallback,
            error_callback=self._uploadFinishedCallback)
예제 #7
0
def checkValidGetReply(reply: QNetworkReply) -> bool:
    status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)

    if status_code != 200:
        Logger.log("w", "Got status code {status_code} while trying to get data".format(status_code=status_code))
        return False
    return True
예제 #8
0
def checkValidGetReply(reply: QNetworkReply) -> bool:
    status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)

    if status_code != 200:
        Logger.log("w", "Got status code {status_code} while trying to get data".format(status_code=status_code))
        return False
    return True
예제 #9
0
    def gotResponse(self, QNetworkReply):

        try:
            status = QNetworkReply.attribute(
                QNetworkRequest.HttpStatusCodeAttribute)
        except Exception as e:
            log('[e] http/yaml error: %s' % str(e))
            self.updatesLabel.setText('Error')
            return

        if status != 200:
            self.updatesLabel.setText('Network error: ' + str(status))
            return

        try:
            response = QNetworkReply.readAll()
            response = str(response, 'utf-8')
            ver = safe_load(response)
        except Exception as e:
            log('[e] http/yaml error: %s' % str(e))
            self.updatesLabel.setText('error')
            return

        if ver is None:
            self.updatesLabel.setText('<network error>')
            return

        if 'version' in ver and 'date' in ver:
            verStr = 'Last published version is %s, build %s.' % (
                ver['version'], ver['date'])
            self.updatesLabel.setText(verStr)
예제 #10
0
 def parseReplyAsBytes(cls, reply: QNetworkReply) -> Tuple[int, bytes]:
     """
     Parse the given API reply into a status code and bytes.
     :param reply: The reply from the server.
     :return: A tuple with a status code and the response body as bytes.
     """
     status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
     return status_code, reply.readAll().data()
 def _parseReply(reply: QNetworkReply) -> Tuple[int, Dict[str, Any]]:
     status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
     try:
         response = bytes(reply.readAll()).decode()
         return status_code, json.loads(response)
     except (UnicodeDecodeError, JSONDecodeError, ValueError) as err:
         Logger.logException("e", "Could not parse the cluster response: %s", err)
         return status_code, {"errors": [err]}
예제 #12
0
파일: Toolbox.py 프로젝트: baskiotisn/Cura
    def _onRequestFinished(self, reply: QNetworkReply) -> None:
        if reply.error() == QNetworkReply.TimeoutError:
            Logger.log("w", "Got a timeout.")
            self.setViewPage("errored")
            self.resetDownload()
            return

        if reply.error() == QNetworkReply.HostNotFoundError:
            Logger.log("w", "Unable to reach server.")
            self.setViewPage("errored")
            self.resetDownload()
            return

        if reply.operation() == QNetworkAccessManager.GetOperation:
            for response_type, url in self._request_urls.items():
                if reply.url() == url:
                    if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 200:
                        try:
                            json_data = json.loads(bytes(reply.readAll()).decode("utf-8"))

                            # Check for errors:
                            if "errors" in json_data:
                                for error in json_data["errors"]:
                                    Logger.log("e", "%s", error["title"])
                                return

                            # Create model and apply metadata:
                            if not self._models[response_type]:
                                Logger.log("e", "Could not find the %s model.", response_type)
                                break
                            
                            self._server_response_data[response_type] = json_data["data"]
                            self._models[response_type].setMetadata(self._server_response_data[response_type])

                            if response_type is "packages":
                                self._models[response_type].setFilter({"type": "plugin"})
                                self.reBuildMaterialsModels()
                                self.reBuildPluginsModels()
                                self._notifyPackageManager()
                            elif response_type is "authors":
                                self._models[response_type].setFilter({"package_types": "material"})
                                self._models[response_type].setFilter({"tags": "generic"})

                            self.metadataChanged.emit()

                            if self.isLoadingComplete():
                                self.setViewPage("overview")

                        except json.decoder.JSONDecodeError:
                            Logger.log("w", "Received invalid JSON for %s.", response_type)
                            break
                    else:
                        Logger.log("w", "Unable to connect with the server, we got a response code %s while trying to connect to %s", reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url())
                        self.setViewPage("errored")
                        self.resetDownload()
        elif reply.operation() == QNetworkAccessManager.PutOperation:
            # Ignore any operation that is not a get operation
            pass
예제 #13
0
파일: Toolbox.py 프로젝트: TinkerGnome/Cura
    def _onRequestFinished(self, reply: QNetworkReply) -> None:
        if reply.error() == QNetworkReply.TimeoutError:
            Logger.log("w", "Got a timeout.")
            self.setViewPage("errored")
            self.resetDownload()
            return

        if reply.error() == QNetworkReply.HostNotFoundError:
            Logger.log("w", "Unable to reach server.")
            self.setViewPage("errored")
            self.resetDownload()
            return

        if reply.operation() == QNetworkAccessManager.GetOperation:
            for response_type, url in self._request_urls.items():
                if reply.url() == url:
                    if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 200:
                        try:
                            json_data = json.loads(bytes(reply.readAll()).decode("utf-8"))

                            # Check for errors:
                            if "errors" in json_data:
                                for error in json_data["errors"]:
                                    Logger.log("e", "%s", error["title"])
                                return

                            # Create model and apply metadata:
                            if not self._models[response_type]:
                                Logger.log("e", "Could not find the %s model.", response_type)
                                break
                            
                            self._server_response_data[response_type] = json_data["data"]
                            self._models[response_type].setMetadata(self._server_response_data[response_type])

                            if response_type is "packages":
                                self._models[response_type].setFilter({"type": "plugin"})
                                self.reBuildMaterialsModels()
                                self.reBuildPluginsModels()
                            elif response_type is "authors":
                                self._models[response_type].setFilter({"package_types": "material"})
                                self._models[response_type].setFilter({"tags": "generic"})

                            self.metadataChanged.emit()

                            if self.isLoadingComplete():
                                self.setViewPage("overview")

                        except json.decoder.JSONDecodeError:
                            Logger.log("w", "Received invalid JSON for %s.", response_type)
                            break
                    else:
                        Logger.log("w", "Unable to connect with the server, we got a response code %s while trying to connect to %s", reply.attribute(QNetworkRequest.HttpStatusCodeAttribute), reply.url())
                        self.setViewPage("errored")
                        self.resetDownload()
        elif reply.operation() == QNetworkAccessManager.PutOperation:
            # Ignore any operation that is not a get operation
            pass
예제 #14
0
def parse_qt_network_reply(
        reply: QtNetwork.QNetworkReply) -> ParsedNetworkReply:
    http_status_code = reply.attribute(
        QtNetwork.QNetworkRequest.HttpStatusCodeAttribute)
    http_status_reason = reply.attribute(
        QtNetwork.QNetworkRequest.HttpReasonPhraseAttribute)
    error = reply.error()
    if error == QtNetwork.QNetworkReply.NoError:
        qt_error = None
    else:
        qt_error = _Q_NETWORK_REPLY_ERROR_MAP[error]
    body = reply.readAll()
    return ParsedNetworkReply(
        http_status_code=http_status_code,
        http_status_reason=http_status_reason,
        qt_error=qt_error,
        response_body=body,
    )
예제 #15
0
 def _parseReply(reply: QNetworkReply) -> Tuple[int, Dict[str, Any]]:
     status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
     try:
         response = bytes(reply.readAll()).decode()
         return status_code, json.loads(response)
     except (UnicodeDecodeError, JSONDecodeError, ValueError) as err:
         error = CloudError(code=type(err).__name__, title=str(err), http_code=str(status_code),
                            id=str(time()), http_status="500")
         Logger.logException("e", "Could not parse the stardust response: %s", error.toDict())
         return status_code, {"errors": [error.toDict()]}
예제 #16
0
 def _parseReply(reply: QNetworkReply) -> Tuple[int, Dict[str, Any]]:
     status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
     try:
         response = bytes(reply.readAll()).decode()
         return status_code, json.loads(response)
     except (UnicodeDecodeError, JSONDecodeError, ValueError) as err:
         error = CloudError(code=type(err).__name__, title=str(err), http_code=str(status_code),
                            id=str(time()), http_status="500")
         Logger.logException("e", "Could not parse the stardust response: %s", error.toDict())
         return status_code, {"errors": [error.toDict()]}
예제 #17
0
    def _onGetRemoteMaterials(self, reply: QNetworkReply) -> None:
        # Got an error from the HTTP request. If we did not receive a 200 something happened.
        if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
            Logger.log("e", "Error fetching materials from printer: %s", reply.errorString())
            return

        # Collect materials from the printer's reply and send the missing ones if needed.
        remote_materials_by_guid = self._parseReply(reply)
        if remote_materials_by_guid:
            self._sendMissingMaterials(remote_materials_by_guid)
예제 #18
0
    def _onGetRemoteMaterials(self, reply: QNetworkReply) -> None:
        # Got an error from the HTTP request. If we did not receive a 200 something happened.
        if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
            Logger.log("e", "Error fetching materials from printer: %s",
                       reply.errorString())
            return

        # Collect materials from the printer's reply and send the missing ones if needed.
        remote_materials_by_guid = self._parseReply(reply)
        if remote_materials_by_guid:
            self._sendMissingMaterials(remote_materials_by_guid)
예제 #19
0
 def base_handler(self, reply: QNetworkReply):
     try:
         response = json.loads(str(reply.readAll(), encoding='utf-8'))
         status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
     except:
         self.parent.warn.add_warn("Http解析错误")
         return
     if reply.error() != QNetworkReply.NoError:
         self.handler_error(response, status_code)
     else:
         self.data.emit(response)
예제 #20
0
 def _sendingFinished(self, reply: QNetworkReply) -> None:
     if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
         Logger.log("w", "Error while syncing material: %s", reply.errorString())
         return
     body = reply.readAll().data().decode('utf8')
     if "not added" in body:
         # For some reason the cluster returns a 200 sometimes even when syncing failed.
         return
     # Inform the user that materials have been synced. This message only shows itself when not already visible.
     # Because of the guards above it is not shown when syncing failed (which is not always an actual problem).
     MaterialSyncMessage(self.device).show()
 def _parseReply(reply: QNetworkReply) -> Tuple[int, Optional[Union[List[Any], Dict[str, Any]]]]:
     """
     Parse the given JSON network reply into a status code and JSON object.
     :param reply: The reply from the server.
     :return: A tuple with a status code and a dictionary.
     """
     status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
     try:
         response = bytes(reply.readAll()).decode()
         return status_code, json.loads(response)
     except (UnicodeDecodeError, JSONDecodeError, ValueError) as err:
         Logger.logException("e", "Could not parse the API response: %s", err)
         return status_code, None
예제 #22
0
    def _onNetworkFinished(self, reply: QNetworkReply):
        status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
        url_string = reply.url().toString()
        if "modifier" in url_string:
            if status_code == 404:
                print("server was not found!")
                self._failed_update_modifier_timer.start()
                return
            data = bytes(reply.readAll())

            try:
                self._modifiers = json.loads(data)
            except:
                print("Failed to get modifier data")
                self._failed_update_modifier_timer.start()
                return
            self.modifiersChanged.emit()
        elif "RFID" in url_string:
            if status_code != 404:
                self._serial_worker.setReadResult(True)
                self.setAuthenticationRequired(False)
            else:
                self._serial_worker.setReadResult(False)
                self.setAuthenticationRequired(True)
        else:
            # Yeah it's hackish, but it's faster than building a real system. For now we don't need more
            if status_code == 404:
                print("Server was not found!")
                self._failed_update_nodes_timer.start()
                return
            data = bytes(reply.readAll())

            try:
                data = json.loads(data)
                for item in data:
                    new_node = Node(item["node_id"])
                    new_node.updateServerUrl(
                        self._zeroconf_worker.server_address)
                    self._data.append(new_node)
                    new_node.serverReachableChanged.connect(
                        self.serverReachableChanged)

                self._data = sorted(self._data,
                                    key=lambda node: node.id)  # sort by age
                self._data.reverse()
                self.nodesChanged.emit()
            except:
                print("Failed to get modifier data")
                self._failed_update_nodes_timer.start()
                return
예제 #23
0
 def parseReplyAsJson(cls, reply: QNetworkReply
                      ) -> Tuple[int, Optional[Union[Dict[str, Any], List[Dict[str, Any]]]]]:
     """
     Parse the given API reply into a status code and JSON object.
     :param reply: The reply from the server.
     :return: A tuple with a status code and the response body as JsonObject.
     """
     status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
     try:
         response = reply.readAll().data().decode()
         return status_code, json.loads(response)
     except (UnicodeDecodeError, JSONDecodeError, ValueError) as err:
         Logger.log("e", "Could not parse the API response: %s", err)
         return status_code, None
예제 #24
0
    def _parseReply(reply: QNetworkReply) -> Tuple[int, Dict[str, Any]]:
        """Parses the given JSON network reply into a status code and a dictionary, handling unexpected errors as well.

        :param reply: The reply from the server.
        :return: A tuple with a status code and a dictionary.
        """
        status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
        try:
            response = bytes(reply.readAll()).decode()
            return status_code, json.loads(response)
        except (UnicodeDecodeError, JSONDecodeError, ValueError) as err:
            Logger.logException("e",
                                "Could not parse the cluster response: %s",
                                err)
            return status_code, {"errors": [err]}
예제 #25
0
        def parse(reply: QNetworkReply) -> None:
            self._anti_gc_callbacks.remove(parse)

            # Don't try to parse the reply if we didn't get one
            if reply.attribute(
                    QNetworkRequest.HttpStatusCodeAttribute) is None:
                if on_error is not None:
                    on_error()
                return

            status_code, response = self._parseReply(reply)
            if status_code >= 300 and on_error is not None:
                on_error()
            else:
                self._parseModels(response, on_finished, model)
 def _readData(self, reply: QNetworkReply):
     status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
     if status_code == 404:
         print("Node was not found!")
         return
     # For some magical reason, it segfaults if I convert the readAll() data directly to bytes.
     # So, yes, the extra .data() is needed.
     data = bytes(reply.readAll().data())
     if not data or status_code == 503:
         self._failed_update_timer.start()
         self._update_timer.stop()
         self._setServerReachable(False)
         return None
     self._setServerReachable(True)
     try:
         return json.loads(data)
     except json.decoder.JSONDecodeError:
         return None
예제 #27
0
    def slot_reply_finished(self, data: QNetworkReply):

        self._reply = data
        self._text = data.readAll()
        self._string = bytes(self._text).decode()
        self._status_code = data.attribute(
            QNetworkRequest.HttpStatusCodeAttribute)
        self._save_header(data.rawHeaderPairs())

        if self.content_type() == 'json':
            if len(self._string):
                self._json = json.loads(self._string)
        else:
            self._json = None

        if self._status_code >= 400:
            print(self._string)

        self.sig_ended.emit(True)
        data.deleteLater()
예제 #28
0
    def _parseReply(reply: QNetworkReply) -> Tuple[int, Dict[str, Any]]:
        """Parses the given JSON network reply into a status code and a dictionary, handling unexpected errors as well.

        :param reply: The reply from the server.
        :return: A tuple with a status code and a dictionary.
        """

        status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
        try:
            response = bytes(reply.readAll()).decode()
            return status_code, json.loads(response)
        except (UnicodeDecodeError, JSONDecodeError, ValueError) as err:
            error = CloudError(code=type(err).__name__,
                               title=str(err),
                               http_code=str(status_code),
                               id=str(time()),
                               http_status="500")
            Logger.logException("e",
                                "Could not parse the stardust response: %s",
                                error.toDict())
            return status_code, {"errors": [error.toDict()]}
    def _handleOnFinished(self, reply: QNetworkReply) -> None:
        # Due to garbage collection, we need to cache certain bits of post operations.
        # As we don't want to keep them around forever, delete them if we get a reply.
        if reply.operation() == QNetworkAccessManager.PostOperation:
            self._clearCachedMultiPart(reply)

        if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) is None:
            # No status code means it never even reached remote.
            return

        self._last_response_time = time()

        if self._connection_state == ConnectionState.Connecting:
            self.setConnectionState(ConnectionState.Connected)

        callback_key = reply.url().toString() + str(reply.operation())
        try:
            if callback_key in self._onFinishedCallbacks:
                self._onFinishedCallbacks[callback_key](reply)
        except Exception:
            Logger.logException("w", "something went wrong with callback")
예제 #30
0
    def _handleOnFinished(self, reply: QNetworkReply) -> None:
        # Due to garbage collection, we need to cache certain bits of post operations.
        # As we don't want to keep them around forever, delete them if we get a reply.
        if reply.operation() == QNetworkAccessManager.PostOperation:
            self._clearCachedMultiPart(reply)

        if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) is None:
            # No status code means it never even reached remote.
            return

        self._last_response_time = time()

        if self._connection_state == ConnectionState.Connecting:
            self.setConnectionState(ConnectionState.Connected)

        callback_key = reply.url().toString() + str(reply.operation())
        try:
            if callback_key in self._onFinishedCallbacks:
                self._onFinishedCallbacks[callback_key](reply)
        except Exception:
            Logger.logException("w", "something went wrong with callback")
예제 #31
0
    def _onRestoreRequestCompleted(
            self,
            reply: QNetworkReply,
            error: Optional["QNetworkReply.NetworkError"] = None) -> None:
        if not HttpRequestManager.replyIndicatesSuccess(reply, error):
            Logger.warning(
                "Requesting backup failed, response code %s while trying to connect to %s",
                reply.attribute(QNetworkRequest.HttpStatusCodeAttribute),
                reply.url())
            self.restore_backup_error_message = self.DEFAULT_ERROR_MESSAGE
            self._job_done.set()
            return

        # We store the file in a temporary path fist to ensure integrity.
        temporary_backup_file = NamedTemporaryFile(delete=False)
        with open(temporary_backup_file.name, "wb") as write_backup:
            app = CuraApplication.getInstance()
            bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE)
            while bytes_read:
                write_backup.write(bytes_read)
                bytes_read = reply.read(self.DISK_WRITE_BUFFER_SIZE)
                app.processEvents()

        if not self._verifyMd5Hash(temporary_backup_file.name,
                                   self._backup.get("md5_hash", "")):
            # Don't restore the backup if the MD5 hashes do not match.
            # This can happen if the download was interrupted.
            Logger.log(
                "w",
                "Remote and local MD5 hashes do not match, not restoring backup."
            )
            self.restore_backup_error_message = self.DEFAULT_ERROR_MESSAGE

        # Tell Cura to place the backup back in the user data folder.
        with open(temporary_backup_file.name, "rb") as read_backup:
            cura_api = CuraApplication.getInstance().getCuraAPI()
            cura_api.backups.restoreBackup(read_backup.read(),
                                           self._backup.get("metadata", {}))

        self._job_done.set()
예제 #32
0
    def _onRequestFinished(self, reply: QNetworkReply) -> None:

        http_status_code = reply.attribute(
            QNetworkRequest.HttpStatusCodeAttribute)
        if not http_status_code:
            # Received no or empty reply
            return

        if reply.operation() == QNetworkAccessManager.PostOperation:
            if "/plugin/appkeys/request" in reply.url().toString(
            ):  # Initial AppKey request
                if http_status_code == 201 or http_status_code == 202:
                    Logger.log("w", "Start polling for AppKeys decision")
                    if not self._appkey_request:
                        return
                    self._appkey_request.setUrl(
                        reply.header(QNetworkRequest.LocationHeader))
                    self._appkey_request.setRawHeader(b"Content-Type", b"")
                    self._appkey_poll_timer.start()
                elif http_status_code == 404:
                    Logger.log(
                        "w",
                        "This instance of OctoPrint does not support AppKeys")
                    self._appkey_request = None  # type: Optional[QNetworkRequest]
                else:
                    response = bytes(reply.readAll()).decode()
                    Logger.log(
                        "w",
                        "Unknown response when requesting an AppKey: %d. OctoPrint said %s"
                        % (http_status_code, response))
                    self._appkey_request = None  # type: Optional[QNetworkRequest]

        if reply.operation() == QNetworkAccessManager.GetOperation:
            if "/plugin/appkeys/probe" in reply.url().toString(
            ):  # Probe for AppKey support
                if http_status_code == 204:
                    self._appkeys_supported = True
                else:
                    self._appkeys_supported = False
                self.appKeysSupportedChanged.emit()
            if "/plugin/appkeys/request" in reply.url().toString(
            ):  # Periodic AppKey request poll
                if http_status_code == 202:
                    self._appkey_poll_timer.start()
                elif http_status_code == 200:
                    Logger.log("d", "AppKey granted")
                    self._appkey_request = None  # type: Optional[QNetworkRequest]
                    try:
                        json_data = json.loads(
                            bytes(reply.readAll()).decode("utf-8"))
                    except json.decoder.JSONDecodeError:
                        Logger.log(
                            "w",
                            "Received invalid JSON from octoprint instance.")
                        return

                    self._keys_cache[
                        self._appkey_instance_id] = json_data["api_key"]
                    self.appKeyReceived.emit()
                elif http_status_code == 404:
                    Logger.log("d", "AppKey denied")
                    self._appkey_request = None  # type: Optional[QNetworkRequest]
                else:
                    response = bytes(reply.readAll()).decode()
                    Logger.log(
                        "w",
                        "Unknown response when waiting for an AppKey: %d. OctoPrint said %s"
                        % (http_status_code, response))
                    self._appkey_request = None  # type: Optional[QNetworkRequest]

            if "api/settings" in reply.url().toString(
            ):  # OctoPrint settings dump from /settings:
                self._instance_in_error = False

                if http_status_code == 200:
                    Logger.log("d", "API key accepted by OctoPrint.")
                    self._instance_api_key_accepted = True

                    try:
                        json_data = json.loads(
                            bytes(reply.readAll()).decode("utf-8"))
                    except json.decoder.JSONDecodeError:
                        Logger.log(
                            "w",
                            "Received invalid JSON from octoprint instance.")
                        json_data = {}

                    if "feature" in json_data and "sdSupport" in json_data[
                            "feature"]:
                        self._instance_supports_sd = json_data["feature"][
                            "sdSupport"]

                    if "webcam" in json_data and "streamUrl" in json_data[
                            "webcam"]:
                        stream_url = json_data["webcam"]["streamUrl"]
                        if stream_url:  #not empty string or None
                            self._instance_supports_camera = True

                elif http_status_code == 401:
                    Logger.log("d", "Invalid API key for OctoPrint.")
                    self._instance_api_key_accepted = False

                elif http_status_code == 502 or http_status_code == 503:
                    Logger.log("d", "OctoPrint is not running.")
                    self._instance_api_key_accepted = False
                    self._instance_in_error = True

                self._instance_responded = True
                self.selectedInstanceSettingsChanged.emit()
예제 #33
0
    def _onRequestFinished(self, reply: QNetworkReply) -> None:
        if reply.error() == QNetworkReply.TimeoutError:
            Logger.log("w", "Got a timeout.")
            self.setViewPage("errored")
            self.resetDownload()
            return

        if reply.error() == QNetworkReply.HostNotFoundError:
            Logger.log("w", "Unable to reach server.")
            self.setViewPage("errored")
            self.resetDownload()
            return

        # HACK: These request are not handled independently at this moment, but together from the "packages" call
        do_not_handle = [
            "materials_available",
            "materials_showcase",
            "materials_generic",
            "plugins_available",
            "plugins_showcase",
        ]

        if reply.operation() == QNetworkAccessManager.GetOperation:
            for type, url in self._request_urls.items():

                # HACK: Do nothing because we'll handle these from the "packages" call
                if type in do_not_handle:
                    continue

                if reply.url() == url:
                    if reply.attribute(
                            QNetworkRequest.HttpStatusCodeAttribute) == 200:
                        try:
                            json_data = json.loads(
                                bytes(reply.readAll()).decode("utf-8"))

                            # Check for errors:
                            if "errors" in json_data:
                                for error in json_data["errors"]:
                                    Logger.log("e", "%s", error["title"])
                                return

                            # Create model and apply metadata:
                            if not self._models[type]:
                                Logger.log("e", "Could not find the %s model.",
                                           type)
                                break

                            self._metadata[type] = json_data["data"]
                            self._models[type].setMetadata(
                                self._metadata[type])

                            # Do some auto filtering
                            # TODO: Make multiple API calls in the future to handle this
                            if type is "packages":
                                self._models[type].setFilter(
                                    {"type": "plugin"})
                                self.buildMaterialsModels()
                                self.buildPluginsModels()
                            if type is "authors":
                                self._models[type].setFilter(
                                    {"package_types": "material"})
                            if type is "materials_generic":
                                self._models[type].setFilter(
                                    {"tags": "generic"})

                            self.metadataChanged.emit()

                            if self.loadingComplete() is True:
                                self.setViewPage("overview")

                            return
                        except json.decoder.JSONDecodeError:
                            Logger.log(
                                "w",
                                "Marketplace: Received invalid JSON for %s.",
                                type)
                            break
                    else:
                        self.setViewPage("errored")
                        self.resetDownload()
                        return

        else:
            # Ignore any operation that is not a get operation
            pass
    def _onRequestFinished(self, reply: QNetworkReply) -> None:

        http_status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
        if not http_status_code:
            # Received no or empty reply
            return

        if reply.operation() == QNetworkAccessManager.PostOperation:
            if "/plugin/appkeys/request" in reply.url().toString():  # Initial AppKey request
                if http_status_code == 201 or http_status_code == 202:
                    Logger.log("w", "Start polling for AppKeys decision")
                    if not self._appkey_request:
                        return
                    self._appkey_request.setUrl(reply.header(QNetworkRequest.LocationHeader))
                    self._appkey_request.setRawHeader(b"Content-Type", b"")
                    self._appkey_poll_timer.start()
                elif http_status_code == 404:
                    Logger.log("w", "This instance of OctoPrint does not support AppKeys")
                    self._appkey_request = None # type: Optional[QNetworkRequest]
                else:
                    response = bytes(reply.readAll()).decode()
                    Logger.log("w", "Unknown response when requesting an AppKey: %d. OctoPrint said %s" % (http_status_code, response))
                    self._appkey_request = None # type: Optional[QNetworkRequest]

        if reply.operation() == QNetworkAccessManager.GetOperation:
            if "/plugin/appkeys/probe" in reply.url().toString():  # Probe for AppKey support
                if http_status_code == 204:
                    self._appkeys_supported = True
                else:
                    self._appkeys_supported = False
                self.appKeysSupportedChanged.emit()
            if "/plugin/appkeys/request" in reply.url().toString():  # Periodic AppKey request poll
                if http_status_code == 202:
                    self._appkey_poll_timer.start()
                elif http_status_code == 200:
                    Logger.log("d", "AppKey granted")
                    self._appkey_request = None # type: Optional[QNetworkRequest]
                    try:
                        json_data = json.loads(bytes(reply.readAll()).decode("utf-8"))
                    except json.decoder.JSONDecodeError:
                        Logger.log("w", "Received invalid JSON from octoprint instance.")
                        return

                    self._keys_cache[self._appkey_instance_id] = json_data["api_key"]
                    self.appKeyReceived.emit()
                elif http_status_code == 404:
                    Logger.log("d", "AppKey denied")
                    self._appkey_request = None # type: Optional[QNetworkRequest]
                else:
                    response = bytes(reply.readAll()).decode()
                    Logger.log("w", "Unknown response when waiting for an AppKey: %d. OctoPrint said %s" % (http_status_code, response))
                    self._appkey_request = None # type: Optional[QNetworkRequest]

            if "api/settings" in reply.url().toString():  # OctoPrint settings dump from /settings:
                self._instance_in_error = False

                if http_status_code == 200:
                    Logger.log("d", "API key accepted by OctoPrint.")
                    self._instance_api_key_accepted = True

                    try:
                        json_data = json.loads(bytes(reply.readAll()).decode("utf-8"))
                    except json.decoder.JSONDecodeError:
                        Logger.log("w", "Received invalid JSON from octoprint instance.")
                        json_data = {}

                    if "feature" in json_data and "sdSupport" in json_data["feature"]:
                        self._instance_supports_sd = json_data["feature"]["sdSupport"]

                    if "webcam" in json_data and "streamUrl" in json_data["webcam"]:
                        stream_url = json_data["webcam"]["streamUrl"]
                        if stream_url: #not empty string or None
                            self._instance_supports_camera = True

                elif http_status_code == 401:
                    Logger.log("d", "Invalid API key for OctoPrint.")
                    self._instance_api_key_accepted = False

                elif http_status_code == 502 or http_status_code == 503:
                    Logger.log("d", "OctoPrint is not running.")
                    self._instance_api_key_accepted = False
                    self._instance_in_error = True

                self._instance_responded = True
                self.selectedInstanceSettingsChanged.emit()
예제 #35
0
파일: Toolbox.py 프로젝트: qin2512/Cura
    def _onRequestFinished(self, reply: QNetworkReply) -> None:
        if reply.error() == QNetworkReply.TimeoutError:
            Logger.log("w", "Got a timeout.")
            self.setViewPage("errored")
            self.resetDownload()
            return

        if reply.error() == QNetworkReply.HostNotFoundError:
            Logger.log("w", "Unable to reach server.")
            self.setViewPage("errored")
            self.resetDownload()
            return

        if reply.operation() == QNetworkAccessManager.GetOperation:
            for type, url in self._request_urls.items():
                if reply.url() == url:
                    if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 200:
                        try:
                            json_data = json.loads(bytes(reply.readAll()).decode("utf-8"))

                            # Check for errors:
                            if "errors" in json_data:
                                for error in json_data["errors"]:
                                    Logger.log("e", "%s", error["title"])
                                return

                            # Create model and apply metadata:
                            if not self._models[type]:
                                Logger.log("e", "Could not find the %s model.", type)
                                break

                            # HACK: Eventually get rid of the code from here...
                            if type is "plugins_showcase" or type is "materials_showcase":
                                self._metadata["plugins_showcase"] = json_data["data"]["plugin"]["packages"]
                                self._models["plugins_showcase"].setMetadata(self._metadata["plugins_showcase"])
                                self._metadata["materials_showcase"] = json_data["data"]["material"]["authors"]
                                self._models["materials_showcase"].setMetadata(self._metadata["materials_showcase"])
                            else:
                                # ...until here.
                                # This hack arises for multiple reasons but the main
                                # one is because there are not separate API calls
                                # for different kinds of showcases.
                                self._metadata[type] = json_data["data"]
                                self._models[type].setMetadata(self._metadata[type])

                            # Do some auto filtering
                            # TODO: Make multiple API calls in the future to handle this
                            if type is "packages":
                                self._models[type].setFilter({"type": "plugin"})
                            if type is "authors":
                                self._models[type].setFilter({"package_types": "material"})
                            if type is "materials_generic":
                                self._models[type].setFilter({"tags": "generic"})

                            self.metadataChanged.emit()

                            if self.loadingComplete() is True:
                                self.setViewPage("overview")

                            return
                        except json.decoder.JSONDecodeError:
                            Logger.log("w", "Toolbox: Received invalid JSON for %s.", type)
                            break
                    else:
                        self.setViewPage("errored")
                        self.resetDownload()
                        return

        else:
            # Ignore any operation that is not a get operation
            pass
예제 #36
0
 def sendingFinished(reply: QNetworkReply) -> None:
     if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
         Logger.log("e", "Received error code from printer when syncing material: {code}, {text}".format(
             code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute),
             text = reply.errorString()
         ))
예제 #37
0
    def _onRequestFinished(self, reply: QNetworkReply) -> None:

        http_status_code = reply.attribute(
            QNetworkRequest.HttpStatusCodeAttribute)
        if not http_status_code:
            # Received no or empty reply
            self._onRequestFailed(reply)
            return

        if reply.operation() == QNetworkAccessManager.PostOperation:
            if "/plugin/appkeys/request" in reply.url().toString(
            ):  # Initial AppKey request
                if http_status_code == 201 or http_status_code == 202:
                    Logger.log("w", "Start polling for AppKeys decision")
                    if not self._appkey_request:
                        return
                    self._appkey_request.setUrl(
                        reply.header(QNetworkRequest.LocationHeader))
                    self._appkey_request.setRawHeader(b"Content-Type", b"")
                    self._appkey_poll_timer.start()
                elif http_status_code == 404:
                    Logger.log(
                        "w",
                        "This instance of OctoPrint does not support AppKeys")
                    self._appkey_request = None  # type: Optional[QNetworkRequest]
                else:
                    response = bytes(reply.readAll()).decode()
                    Logger.log(
                        "w",
                        "Unknown response when requesting an AppKey: %d. OctoPrint said %s"
                        % (http_status_code, response))
                    self._appkey_request = None  # type: Optional[QNetworkRequest]

        if reply.operation() == QNetworkAccessManager.GetOperation:
            if "/plugin/appkeys/probe" in reply.url().toString(
            ):  # Probe for AppKey support
                if http_status_code == 204:
                    self._instance_supports_appkeys = True
                else:
                    self._instance_supports_appkeys = False
                self.appKeysSupportedChanged.emit()

            if "/plugin/appkeys/request" in reply.url().toString(
            ):  # Periodic AppKey request poll
                if http_status_code == 202:
                    self._appkey_poll_timer.start()
                elif http_status_code == 200:
                    Logger.log("d", "AppKey granted")
                    self._appkey_request = None  # type: Optional[QNetworkRequest]
                    try:
                        json_data = json.loads(
                            bytes(reply.readAll()).decode("utf-8"))
                    except json.decoder.JSONDecodeError:
                        Logger.log(
                            "w",
                            "Received invalid JSON from octoprint instance.")
                        return

                    api_key = json_data["api_key"]
                    self._keys_cache[self._appkey_instance_id] = api_key

                    global_container_stack = self._application.getGlobalContainerStack(
                    )
                    if global_container_stack:
                        global_container_stack.setMetaDataEntry(
                            "octoprint_api_key",
                            base64.b64encode(
                                api_key.encode("ascii")).decode("ascii"))

                    self.appKeyReceived.emit()
                elif http_status_code == 404:
                    Logger.log("d", "AppKey denied")
                    self._appkey_request = None  # type: Optional[QNetworkRequest]
                else:
                    response = bytes(reply.readAll()).decode()
                    Logger.log(
                        "w",
                        "Unknown response when waiting for an AppKey: %d. OctoPrint said %s"
                        % (http_status_code, response))
                    self._appkey_request = None  # type: Optional[QNetworkRequest]

            if "api/settings" in reply.url().toString(
            ):  # OctoPrint settings dump from /settings:
                self._instance_in_error = False

                if http_status_code == 200:
                    Logger.log("d", "API key accepted by OctoPrint.")
                    self._instance_api_key_accepted = True

                    try:
                        json_data = json.loads(
                            bytes(reply.readAll()).decode("utf-8"))
                    except json.decoder.JSONDecodeError:
                        Logger.log(
                            "w",
                            "Received invalid JSON from octoprint instance.")
                        json_data = {}

                    if "feature" in json_data and "sdSupport" in json_data[
                            "feature"]:
                        self._instance_supports_sd = json_data["feature"][
                            "sdSupport"]

                    if "webcam" in json_data and "streamUrl" in json_data[
                            "webcam"]:
                        stream_url = json_data["webcam"]["streamUrl"]
                        if stream_url:  #not empty string or None
                            self._instance_supports_camera = True

                    if "plugins" in json_data:
                        self._power_plugins_manager.parsePluginData(
                            json_data["plugins"])
                        self._instance_installed_plugins = list(
                            json_data["plugins"].keys())

                    api_key = bytes(reply.request().rawHeader(
                        b"X-Api-Key")).decode("utf-8")
                    self.setApiKey(api_key)  # store api key in key cache
                    if self._settings_instance:
                        self._settings_instance.setApiKey(api_key)
                        self._settings_instance.resetOctoPrintUserName()
                        self._settings_instance.getAdditionalData()
                        self._settings_instance.parseSettingsData(json_data)

                    self._settings_instance = None

                elif http_status_code == 401:
                    Logger.log("d", "Invalid API key for OctoPrint.")
                    self._instance_api_key_accepted = False

                elif http_status_code == 502 or http_status_code == 503:
                    Logger.log("d", "OctoPrint is not running.")
                    self._instance_api_key_accepted = False
                    self._instance_in_error = True

                self._instance_responded = True
                self.selectedInstanceSettingsChanged.emit()
예제 #38
0
    def sendMissingMaterials(self, reply: QNetworkReply) -> None:
        if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute
                           ) != 200:  #Got an error from the HTTP request.
            Logger.log(
                "e",
                "Couldn't request current material storage on printer. Not syncing materials."
            )
            return

        remote_materials_list = reply.readAll().data().decode("utf-8")
        try:
            remote_materials_list = json.loads(remote_materials_list)
        except json.JSONDecodeError:
            Logger.log(
                "e",
                "Current material storage on printer was a corrupted reply.")
            return
        try:
            remote_materials_by_guid = {
                material["guid"]: material
                for material in remote_materials_list
            }  #Index by GUID.
        except KeyError:
            Logger.log(
                "e",
                "Current material storage on printer was an invalid reply (missing GUIDs)."
            )
            return

        container_registry = ContainerRegistry.getInstance()
        local_materials_list = filter(
            lambda material: ("GUID" in material and "version" in material and
                              "id" in material),
            container_registry.findContainersMetadata(type="material"))
        local_materials_by_guid = {
            material["GUID"]: material
            for material in local_materials_list
            if material["id"] == material["base_file"]
        }
        for material in local_materials_list:  #For each GUID get the material with the highest version number.
            try:
                if int(material["version"]) > local_materials_by_guid[
                        material["GUID"]]["version"]:
                    local_materials_by_guid[material["GUID"]] = material
            except ValueError:
                Logger.log(
                    "e",
                    "Material {material_id} has invalid version number {number}."
                    .format(material_id=material["id"],
                            number=material["version"]))
                continue

        materials_to_send = set()  #type: Set[Dict[str, Any]]
        for guid, material in local_materials_by_guid.items():
            if guid not in remote_materials_by_guid:
                materials_to_send.add(material["id"])
                continue
            try:
                if int(material["version"]
                       ) > remote_materials_by_guid[guid]["version"]:
                    materials_to_send.add(material["id"])
                    continue
            except KeyError:
                Logger.log(
                    "e",
                    "Current material storage on printer was an invalid reply (missing version)."
                )
                return

        for file_path in Resources.getAllResourcesOfType(
                CuraApplication.ResourceTypes.MaterialInstanceContainer):
            try:
                mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path)
            except MimeTypeDatabase.MimeTypeNotFoundError:
                continue  #Not the sort of file we'd like to send then.
            _, file_name = os.path.split(file_path)
            material_id = urllib.parse.unquote_plus(
                mime_type.stripExtension(file_name))
            if material_id not in materials_to_send:
                continue

            parts = []
            with open(file_path, "rb") as f:
                parts.append(
                    self.device._createFormPart(
                        "name=\"file\"; filename=\"{file_name}\"".format(
                            file_name=file_name), f.read()))
            signature_file_path = file_path + ".sig"
            if os.path.exists(signature_file_path):
                _, signature_file_name = os.path.split(signature_file_path)
                with open(signature_file_path, "rb") as f:
                    parts.append(
                        self.device._createFormPart(
                            "name=\"signature_file\"; filename=\"{file_name}\""
                            .format(file_name=signature_file_name), f.read()))

            Logger.log(
                "d", "Syncing material {material_id} with cluster.".format(
                    material_id=material_id))
            self.device.postFormWithParts(target="materials/",
                                          parts=parts,
                                          on_finished=self.sendingFinished)