mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-16 19:15:55 +08:00
Merge branch 'main' into CURA-11617-set-print-sequence
This commit is contained in:
commit
285a36a38a
@ -1082,6 +1082,10 @@ class CuraApplication(QtApplication):
|
|||||||
def getTextManager(self, *args) -> "TextManager":
|
def getTextManager(self, *args) -> "TextManager":
|
||||||
return self._text_manager
|
return self._text_manager
|
||||||
|
|
||||||
|
@pyqtSlot(bool)
|
||||||
|
def getWorkplaceDropToBuildplate(self, drop_to_build_plate: bool) ->None:
|
||||||
|
return self._physics.setAppPerModelDropDown(drop_to_build_plate)
|
||||||
|
|
||||||
def getCuraFormulaFunctions(self, *args) -> "CuraFormulaFunctions":
|
def getCuraFormulaFunctions(self, *args) -> "CuraFormulaFunctions":
|
||||||
if self._cura_formula_functions is None:
|
if self._cura_formula_functions is None:
|
||||||
self._cura_formula_functions = CuraFormulaFunctions(self)
|
self._cura_formula_functions = CuraFormulaFunctions(self)
|
||||||
|
@ -16,6 +16,7 @@ from UM.TaskManagement.HttpRequestManager import HttpRequestManager # To downlo
|
|||||||
|
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
TOKEN_TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S"
|
TOKEN_TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S"
|
||||||
|
REQUEST_TIMEOUT = 5 # Seconds
|
||||||
|
|
||||||
|
|
||||||
class AuthorizationHelpers:
|
class AuthorizationHelpers:
|
||||||
@ -53,7 +54,8 @@ class AuthorizationHelpers:
|
|||||||
data = urllib.parse.urlencode(data).encode("UTF-8"),
|
data = urllib.parse.urlencode(data).encode("UTF-8"),
|
||||||
headers_dict = headers,
|
headers_dict = headers,
|
||||||
callback = lambda response: self.parseTokenResponse(response, callback),
|
callback = lambda response: self.parseTokenResponse(response, callback),
|
||||||
error_callback = lambda response, _: self.parseTokenResponse(response, callback)
|
error_callback = lambda response, _: self.parseTokenResponse(response, callback),
|
||||||
|
timeout = REQUEST_TIMEOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
def getAccessTokenUsingRefreshToken(self, refresh_token: str, callback: Callable[[AuthenticationResponse], None]) -> None:
|
def getAccessTokenUsingRefreshToken(self, refresh_token: str, callback: Callable[[AuthenticationResponse], None]) -> None:
|
||||||
@ -77,7 +79,9 @@ class AuthorizationHelpers:
|
|||||||
data = urllib.parse.urlencode(data).encode("UTF-8"),
|
data = urllib.parse.urlencode(data).encode("UTF-8"),
|
||||||
headers_dict = headers,
|
headers_dict = headers,
|
||||||
callback = lambda response: self.parseTokenResponse(response, callback),
|
callback = lambda response: self.parseTokenResponse(response, callback),
|
||||||
error_callback = lambda response, _: self.parseTokenResponse(response, callback)
|
error_callback = lambda response, _: self.parseTokenResponse(response, callback),
|
||||||
|
urgent = True,
|
||||||
|
timeout = REQUEST_TIMEOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
def parseTokenResponse(self, token_response: QNetworkReply, callback: Callable[[AuthenticationResponse], None]) -> None:
|
def parseTokenResponse(self, token_response: QNetworkReply, callback: Callable[[AuthenticationResponse], None]) -> None:
|
||||||
@ -122,7 +126,8 @@ class AuthorizationHelpers:
|
|||||||
check_token_url,
|
check_token_url,
|
||||||
headers_dict = headers,
|
headers_dict = headers,
|
||||||
callback = lambda reply: self._parseUserProfile(reply, success_callback, failed_callback),
|
callback = lambda reply: self._parseUserProfile(reply, success_callback, failed_callback),
|
||||||
error_callback = lambda _, _2: failed_callback() if failed_callback is not None else None
|
error_callback = lambda _, _2: failed_callback() if failed_callback is not None else None,
|
||||||
|
timeout = REQUEST_TIMEOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
def _parseUserProfile(self, reply: QNetworkReply, success_callback: Optional[Callable[[UserProfile], None]], failed_callback: Optional[Callable[[], None]] = None) -> None:
|
def _parseUserProfile(self, reply: QNetworkReply, success_callback: Optional[Callable[[UserProfile], None]], failed_callback: Optional[Callable[[], None]] = None) -> None:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2021 Ultimaker B.V.
|
# Copyright (c) 2024 UltiMaker
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import json
|
import json
|
||||||
@ -6,13 +6,14 @@ from datetime import datetime, timedelta
|
|||||||
from typing import Callable, Dict, Optional, TYPE_CHECKING, Union
|
from typing import Callable, Dict, Optional, TYPE_CHECKING, Union
|
||||||
from urllib.parse import urlencode, quote_plus
|
from urllib.parse import urlencode, quote_plus
|
||||||
|
|
||||||
from PyQt6.QtCore import QUrl
|
from PyQt6.QtCore import QUrl, QTimer
|
||||||
from PyQt6.QtGui import QDesktopServices
|
from PyQt6.QtGui import QDesktopServices
|
||||||
|
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
from UM.Signal import Signal
|
from UM.Signal import Signal
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
from UM.TaskManagement.HttpRequestManager import HttpRequestManager # To download log-in tokens.
|
||||||
from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers, TOKEN_TIMESTAMP_FORMAT
|
from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers, TOKEN_TIMESTAMP_FORMAT
|
||||||
from cura.OAuth2.LocalAuthorizationServer import LocalAuthorizationServer
|
from cura.OAuth2.LocalAuthorizationServer import LocalAuthorizationServer
|
||||||
from cura.OAuth2.Models import AuthenticationResponse, BaseModel
|
from cura.OAuth2.Models import AuthenticationResponse, BaseModel
|
||||||
@ -25,6 +26,8 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
MYCLOUD_LOGOFF_URL = "https://account.ultimaker.com/logoff?utm_source=cura&utm_medium=software&utm_campaign=change-account-before-adding-printers"
|
MYCLOUD_LOGOFF_URL = "https://account.ultimaker.com/logoff?utm_source=cura&utm_medium=software&utm_campaign=change-account-before-adding-printers"
|
||||||
|
|
||||||
|
REFRESH_TOKEN_MAX_RETRIES = 15
|
||||||
|
REFRESH_TOKEN_RETRY_INTERVAL = 1000
|
||||||
|
|
||||||
class AuthorizationService:
|
class AuthorizationService:
|
||||||
"""The authorization service is responsible for handling the login flow, storing user credentials and providing
|
"""The authorization service is responsible for handling the login flow, storing user credentials and providing
|
||||||
@ -57,6 +60,12 @@ class AuthorizationService:
|
|||||||
|
|
||||||
self.onAuthStateChanged.connect(self._authChanged)
|
self.onAuthStateChanged.connect(self._authChanged)
|
||||||
|
|
||||||
|
self._refresh_token_retries = 0
|
||||||
|
self._refresh_token_retry_timer = QTimer()
|
||||||
|
self._refresh_token_retry_timer.setInterval(REFRESH_TOKEN_RETRY_INTERVAL)
|
||||||
|
self._refresh_token_retry_timer.setSingleShot(True)
|
||||||
|
self._refresh_token_retry_timer.timeout.connect(self.refreshAccessToken)
|
||||||
|
|
||||||
def _authChanged(self, logged_in):
|
def _authChanged(self, logged_in):
|
||||||
if logged_in and self._unable_to_get_data_message is not None:
|
if logged_in and self._unable_to_get_data_message is not None:
|
||||||
self._unable_to_get_data_message.hide()
|
self._unable_to_get_data_message.hide()
|
||||||
@ -167,16 +176,29 @@ class AuthorizationService:
|
|||||||
return
|
return
|
||||||
|
|
||||||
def process_auth_data(response: AuthenticationResponse) -> None:
|
def process_auth_data(response: AuthenticationResponse) -> None:
|
||||||
|
self._currently_refreshing_token = False
|
||||||
|
|
||||||
if response.success:
|
if response.success:
|
||||||
|
self._refresh_token_retries = 0
|
||||||
self._storeAuthData(response)
|
self._storeAuthData(response)
|
||||||
|
HttpRequestManager.getInstance().setDelayRequests(False)
|
||||||
self.onAuthStateChanged.emit(logged_in = True)
|
self.onAuthStateChanged.emit(logged_in = True)
|
||||||
else:
|
else:
|
||||||
Logger.warning("Failed to get a new access token from the server.")
|
if self._refresh_token_retries >= REFRESH_TOKEN_MAX_RETRIES:
|
||||||
self.onAuthStateChanged.emit(logged_in = False)
|
self._refresh_token_retries = 0
|
||||||
|
Logger.warning("Failed to get a new access token from the server, giving up.")
|
||||||
|
HttpRequestManager.getInstance().setDelayRequests(False)
|
||||||
|
self.onAuthStateChanged.emit(logged_in = False)
|
||||||
|
else:
|
||||||
|
# Retry a bit later, network may be offline right now and will hopefully be back soon
|
||||||
|
Logger.warning("Failed to get a new access token from the server, retrying later.")
|
||||||
|
self._refresh_token_retries += 1
|
||||||
|
self._refresh_token_retry_timer.start()
|
||||||
|
|
||||||
if self._currently_refreshing_token:
|
if self._currently_refreshing_token:
|
||||||
Logger.debug("Was already busy refreshing token. Do not start a new request.")
|
Logger.debug("Was already busy refreshing token. Do not start a new request.")
|
||||||
return
|
return
|
||||||
|
HttpRequestManager.getInstance().setDelayRequests(True)
|
||||||
self._currently_refreshing_token = True
|
self._currently_refreshing_token = True
|
||||||
self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token, process_auth_data)
|
self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token, process_auth_data)
|
||||||
|
|
||||||
|
@ -38,7 +38,14 @@ class PlatformPhysics:
|
|||||||
self._minimum_gap = 2 # It is a minimum distance (in mm) between two models, applicable for small models
|
self._minimum_gap = 2 # It is a minimum distance (in mm) between two models, applicable for small models
|
||||||
|
|
||||||
Application.getInstance().getPreferences().addPreference("physics/automatic_push_free", False)
|
Application.getInstance().getPreferences().addPreference("physics/automatic_push_free", False)
|
||||||
Application.getInstance().getPreferences().addPreference("physics/automatic_drop_down", True)
|
Application.getInstance().getPreferences().addPreference("physics/automatic_drop_down", False)
|
||||||
|
self._app_per_model_drop = Application.getInstance().getPreferences().getValue("physics/automatic_drop_down")
|
||||||
|
|
||||||
|
def getAppPerModelDropDown(self):
|
||||||
|
return self._app_per_model_drop
|
||||||
|
|
||||||
|
def setAppPerModelDropDown(self, drop_to_buildplate):
|
||||||
|
self._app_per_model_drop = drop_to_buildplate
|
||||||
|
|
||||||
def _onSceneChanged(self, source):
|
def _onSceneChanged(self, source):
|
||||||
if not source.callDecoration("isSliceable"):
|
if not source.callDecoration("isSliceable"):
|
||||||
@ -71,6 +78,7 @@ class PlatformPhysics:
|
|||||||
# We try to shuffle all the nodes to prevent "locked" situations, where iteration B inverts iteration A.
|
# We try to shuffle all the nodes to prevent "locked" situations, where iteration B inverts iteration A.
|
||||||
# By shuffling the order of the nodes, this might happen a few times, but at some point it will resolve.
|
# By shuffling the order of the nodes, this might happen a few times, but at some point it will resolve.
|
||||||
random.shuffle(nodes)
|
random.shuffle(nodes)
|
||||||
|
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
if node is root or not isinstance(node, SceneNode) or node.getBoundingBox() is None:
|
if node is root or not isinstance(node, SceneNode) or node.getBoundingBox() is None:
|
||||||
continue
|
continue
|
||||||
@ -80,7 +88,10 @@ class PlatformPhysics:
|
|||||||
# Move it downwards if bottom is above platform
|
# Move it downwards if bottom is above platform
|
||||||
move_vector = Vector()
|
move_vector = Vector()
|
||||||
|
|
||||||
if node.getSetting(SceneNodeSettings.AutoDropDown, app_automatic_drop_down) and not (node.getParent() and node.getParent().callDecoration("isGroup") or node.getParent() != root) and node.isEnabled(): #If an object is grouped, don't move it down
|
# if per model drop is different then app_automatic_drop, in case of 3mf loading when user changes this setting for that model
|
||||||
|
if (self._app_per_model_drop != app_automatic_drop_down):
|
||||||
|
node.setSetting(SceneNodeSettings.AutoDropDown, self._app_per_model_drop)
|
||||||
|
if node.getSetting(SceneNodeSettings.AutoDropDown, self._app_per_model_drop) and not (node.getParent() and node.getParent().callDecoration("isGroup") or node.getParent() != root) and node.isEnabled(): #If an object is grouped, don't move it down
|
||||||
z_offset = node.callDecoration("getZOffset") if node.getDecorator(ZOffsetDecorator.ZOffsetDecorator) else 0
|
z_offset = node.callDecoration("getZOffset") if node.getDecorator(ZOffsetDecorator.ZOffsetDecorator) else 0
|
||||||
move_vector = move_vector.set(y = -bbox.bottom + z_offset)
|
move_vector = move_vector.set(y = -bbox.bottom + z_offset)
|
||||||
|
|
||||||
@ -168,6 +179,8 @@ class PlatformPhysics:
|
|||||||
op = PlatformPhysicsOperation.PlatformPhysicsOperation(node, move_vector)
|
op = PlatformPhysicsOperation.PlatformPhysicsOperation(node, move_vector)
|
||||||
op.push()
|
op.push()
|
||||||
|
|
||||||
|
# setting this drop to model same as app_automatic_drop_down
|
||||||
|
self._app_per_model_drop = app_automatic_drop_down
|
||||||
# After moving, we have to evaluate the boundary checks for nodes
|
# After moving, we have to evaluate the boundary checks for nodes
|
||||||
build_volume.updateNodeBoundaryCheck()
|
build_volume.updateNodeBoundaryCheck()
|
||||||
|
|
||||||
|
@ -299,6 +299,11 @@ class WorkspaceDialog(QObject):
|
|||||||
|
|
||||||
Application.getInstance().getBackend().close()
|
Application.getInstance().getBackend().close()
|
||||||
|
|
||||||
|
@pyqtSlot(bool)
|
||||||
|
def setDropToBuildPlateForModel(self, drop_to_buildplate: bool) -> None:
|
||||||
|
CuraApplication.getInstance().getWorkplaceDropToBuildplate(drop_to_buildplate)
|
||||||
|
|
||||||
|
|
||||||
def setMaterialConflict(self, material_conflict: bool) -> None:
|
def setMaterialConflict(self, material_conflict: bool) -> None:
|
||||||
if self._has_material_conflict != material_conflict:
|
if self._has_material_conflict != material_conflict:
|
||||||
self._has_material_conflict = material_conflict
|
self._has_material_conflict = material_conflict
|
||||||
|
@ -300,6 +300,25 @@ UM.Dialog
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Row
|
||||||
|
{
|
||||||
|
id: dropToBuildPlate
|
||||||
|
width: parent.width
|
||||||
|
height: childrenRect.height
|
||||||
|
spacing: UM.Theme.getSize("default_margin").width
|
||||||
|
UM.CheckBox
|
||||||
|
{
|
||||||
|
id: checkDropModels
|
||||||
|
text: catalog.i18nc("@text:window", "Drop models to buildplate")
|
||||||
|
checked: UM.Preferences.getValue("physics/automatic_drop_down")
|
||||||
|
onCheckedChanged: manager.setDropToBuildPlateForModel(checked)
|
||||||
|
}
|
||||||
|
function reloadValue()
|
||||||
|
{
|
||||||
|
checkDropModels.checked = UM.Preferences.getValue("physics/automatic_drop_down")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Row
|
Row
|
||||||
{
|
{
|
||||||
id: clearBuildPlateWarning
|
id: clearBuildPlateWarning
|
||||||
@ -422,6 +441,7 @@ UM.Dialog
|
|||||||
materialSection.reloadValues()
|
materialSection.reloadValues()
|
||||||
profileSection.reloadValues()
|
profileSection.reloadValues()
|
||||||
printerSection.reloadValues()
|
printerSection.reloadValues()
|
||||||
|
dropToBuildPlate.reloadValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -509,11 +509,14 @@ UM.PreferencesPage
|
|||||||
id: dropDownCheckbox
|
id: dropDownCheckbox
|
||||||
text: catalog.i18nc("@option:check", "Automatically drop models to the build plate")
|
text: catalog.i18nc("@option:check", "Automatically drop models to the build plate")
|
||||||
checked: boolCheck(UM.Preferences.getValue("physics/automatic_drop_down"))
|
checked: boolCheck(UM.Preferences.getValue("physics/automatic_drop_down"))
|
||||||
onCheckedChanged: UM.Preferences.setValue("physics/automatic_drop_down", checked)
|
onCheckedChanged:
|
||||||
|
{
|
||||||
|
UM.Preferences.setValue("physics/automatic_drop_down", checked)
|
||||||
|
CuraApplication.getWorkplaceDropToBuildplate(checked)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UM.TooltipArea
|
UM.TooltipArea
|
||||||
{
|
{
|
||||||
width: childrenRect.width;
|
width: childrenRect.width;
|
||||||
|
@ -222,7 +222,7 @@ Item
|
|||||||
UM.Label
|
UM.Label
|
||||||
{
|
{
|
||||||
id: toolHint
|
id: toolHint
|
||||||
text: UM.Controller.properties.getValue("ToolHint") != undefined ? UM.ActiveTool.properties.getValue("ToolHint") : ""
|
text: UM.Controller.properties.getValue("ToolHint") != undefined ? UM.Controller.properties.getValue("ToolHint") : ""
|
||||||
color: UM.Theme.getColor("tooltip_text")
|
color: UM.Theme.getColor("tooltip_text")
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ def test__parseJWTNoRefreshToken():
|
|||||||
mock_reply = Mock() # The user profile that the service should respond with.
|
mock_reply = Mock() # The user profile that the service should respond with.
|
||||||
mock_reply.error = Mock(return_value = QNetworkReply.NetworkError.NoError)
|
mock_reply.error = Mock(return_value = QNetworkReply.NetworkError.NoError)
|
||||||
http_mock = Mock()
|
http_mock = Mock()
|
||||||
http_mock.get = lambda url, headers_dict, callback, error_callback: callback(mock_reply)
|
http_mock.get = lambda url, headers_dict, callback, error_callback, timeout: callback(mock_reply)
|
||||||
http_mock.readJSON = Mock(return_value = {"data": {"user_id": "id_ego_or_superego", "username": "Ghostkeeper"}})
|
http_mock.readJSON = Mock(return_value = {"data": {"user_id": "id_ego_or_superego", "username": "Ghostkeeper"}})
|
||||||
|
|
||||||
with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.getInstance", MagicMock(return_value = http_mock)):
|
with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.getInstance", MagicMock(return_value = http_mock)):
|
||||||
@ -119,8 +119,8 @@ def test__parseJWTFailOnRefresh():
|
|||||||
mock_reply = Mock() # The response that the request should give, containing an error about it failing to authenticate.
|
mock_reply = Mock() # The response that the request should give, containing an error about it failing to authenticate.
|
||||||
mock_reply.error = Mock(return_value = QNetworkReply.NetworkError.AuthenticationRequiredError) # The reply is 403: Authentication required, meaning the server responded with a "Can't do that, Dave".
|
mock_reply.error = Mock(return_value = QNetworkReply.NetworkError.AuthenticationRequiredError) # The reply is 403: Authentication required, meaning the server responded with a "Can't do that, Dave".
|
||||||
http_mock = Mock()
|
http_mock = Mock()
|
||||||
http_mock.get = lambda url, headers_dict, callback, error_callback: callback(mock_reply)
|
http_mock.get = lambda url, headers_dict, callback, error_callback, timeout: callback(mock_reply)
|
||||||
http_mock.post = lambda url, data, headers_dict, callback, error_callback: callback(mock_reply)
|
http_mock.post = lambda url, data, headers_dict, callback, error_callback, urgent, timeout: callback(mock_reply)
|
||||||
|
|
||||||
with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.readJSON", Mock(return_value = {"error_description": "Mock a failed request!"})):
|
with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.readJSON", Mock(return_value = {"error_description": "Mock a failed request!"})):
|
||||||
with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.getInstance", MagicMock(return_value = http_mock)):
|
with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.getInstance", MagicMock(return_value = http_mock)):
|
||||||
@ -142,7 +142,7 @@ def test__parseJWTSucceedOnRefresh():
|
|||||||
mock_reply_failure = Mock()
|
mock_reply_failure = Mock()
|
||||||
mock_reply_failure.error = Mock(return_value = QNetworkReply.NetworkError.AuthenticationRequiredError)
|
mock_reply_failure.error = Mock(return_value = QNetworkReply.NetworkError.AuthenticationRequiredError)
|
||||||
http_mock = Mock()
|
http_mock = Mock()
|
||||||
def mock_get(url, headers_dict, callback, error_callback):
|
def mock_get(url, headers_dict, callback, error_callback, timeout):
|
||||||
if(headers_dict == {"Authorization": "Bearer beep"}):
|
if(headers_dict == {"Authorization": "Bearer beep"}):
|
||||||
callback(mock_reply_success)
|
callback(mock_reply_success)
|
||||||
else:
|
else:
|
||||||
@ -181,8 +181,8 @@ def test_refreshAccessTokenFailed():
|
|||||||
mock_reply = Mock() # The response that the request should give, containing an error about it failing to authenticate.
|
mock_reply = Mock() # The response that the request should give, containing an error about it failing to authenticate.
|
||||||
mock_reply.error = Mock(return_value = QNetworkReply.NetworkError.AuthenticationRequiredError) # The reply is 403: Authentication required, meaning the server responded with a "Can't do that, Dave".
|
mock_reply.error = Mock(return_value = QNetworkReply.NetworkError.AuthenticationRequiredError) # The reply is 403: Authentication required, meaning the server responded with a "Can't do that, Dave".
|
||||||
http_mock = Mock()
|
http_mock = Mock()
|
||||||
http_mock.get = lambda url, headers_dict, callback, error_callback: callback(mock_reply)
|
http_mock.get = lambda url, headers_dict, callback, error_callback, timeout: callback(mock_reply)
|
||||||
http_mock.post = lambda url, data, headers_dict, callback, error_callback: callback(mock_reply)
|
http_mock.post = lambda url, data, headers_dict, callback, error_callback, urgent, timeout: callback(mock_reply)
|
||||||
|
|
||||||
with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.readJSON", Mock(return_value = {"error_description": "Mock a failed request!"})):
|
with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.readJSON", Mock(return_value = {"error_description": "Mock a failed request!"})):
|
||||||
with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.getInstance", MagicMock(return_value = http_mock)):
|
with patch("UM.TaskManagement.HttpRequestManager.HttpRequestManager.getInstance", MagicMock(return_value = http_mock)):
|
||||||
@ -263,7 +263,7 @@ def test_loginAndLogout() -> None:
|
|||||||
mock_reply = Mock() # The user profile that the service should respond with.
|
mock_reply = Mock() # The user profile that the service should respond with.
|
||||||
mock_reply.error = Mock(return_value = QNetworkReply.NetworkError.NoError)
|
mock_reply.error = Mock(return_value = QNetworkReply.NetworkError.NoError)
|
||||||
http_mock = Mock()
|
http_mock = Mock()
|
||||||
http_mock.get = lambda url, headers_dict, callback, error_callback: callback(mock_reply)
|
http_mock.get = lambda url, headers_dict, callback, error_callback, timeout: callback(mock_reply)
|
||||||
http_mock.readJSON = Mock(return_value = {"data": {"user_id": "di_resu", "username": "Emanresu"}})
|
http_mock.readJSON = Mock(return_value = {"data": {"user_id": "di_resu", "username": "Emanresu"}})
|
||||||
|
|
||||||
# Let the service think there was a successful response
|
# Let the service think there was a successful response
|
||||||
|
Loading…
x
Reference in New Issue
Block a user