Browse Source

Merge remote-tracking branch 'origin/master' into CURA-6983_sync_packages

# Conflicts:
#	plugins/Toolbox/src/CloudSync/SubscribedPackagesModel.py
#	plugins/Toolbox/src/Toolbox.py
Nino van Hooff 5 years ago
parent
commit
182bab6467

+ 116 - 0
.pylintrc

@@ -0,0 +1,116 @@
+# Copyright (c) 2019 Ultimaker B.V.
+# This file contains the Pylint rules used in the stardust projects.
+
+# To configure PyLint as an external tool in PyCharm, create a new External Tool with the settings:
+#
+# Name: PyLint
+# Program: Check with 'which pylint'. For example: ~/.local/bin/pylint
+# Arguments: $FileDirName$ --rcfile=.pylintrc --msg-template='{abspath}:{line}:{column}:({symbol}):{msg_id}:{msg}'
+# Working directory: $ContentRoot$
+# Output filters: $FILE_PATH$:$LINE$:$COLUMN$:.*
+#
+# You can add a keyboard shortcut in the keymap settings. To run Pylint to a project, select the module
+# you want to check (e.g. cura folder) before running the external tool.
+#
+# If you find a better way to configure the external tool please edit this file.
+
+[MASTER]
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=pylint_quotes
+
+# We expect double string quotes
+string-quote=double-avoid-escape
+
+# When enabled, pylint would attempt to guess common misconfiguration and emit
+# user-friendly hints instead of false-positive error messages.
+suggestion-mode=yes
+
+# Add files or directories to the blacklist. They should be base names, not paths.
+ignore=tests
+
+[REFACTORING]
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=5
+
+[MESSAGES CONTROL]
+# C0326: No space allowed around keyword argument assignment
+# C0411: Ignore import order because the rules are different than in PyCharm, so automatic imports break lots of builds
+# C0412: Ignore import order because the rules are different than in PyCharm, so automatic imports break lots of builds
+# C0413: Ignore import order because the rules are different than in PyCharm, so automatic imports break lots of builds
+# R0201: Method could be a function (no-self-use)
+# R0401: Cyclic imports (cyclic-import) are used for typing
+# R0801: Unfortunately the error is triggered for a lot of similar models (duplicate-code)
+# R1710: Either all return statements in a function should return an expression, or none of them should.
+# W0221: Parameters differ from overridden method (tornado http methods have a flexible number of parameters)
+# W0511: Ignore warnings generated for TODOs in the code
+# C0111: We don't use docstring
+# C0303: Trailing whitespace isn't something we care about
+# C4001: You can put " in a string if you escape it first... 
+disable=C0326,C0411,C0412,C0413,R0201,R0401,R0801,R1710,W0221,W0511, C0111, C0303,C4001
+
+[FORMAT]
+# Maximum number of characters on a single line.
+max-line-length=120
+
+# Maximum number of lines in a module.
+max-module-lines=500
+
+good-names=os
+
+[BASIC]
+# allow modules and functions to use PascalCase
+module-rgx=[a-zA-Z0-9_]+$
+function-rgx=
+## Allowed methods:
+# getSomething
+# _getSomething
+# __getSomething
+# __new__
+## Disallowed:
+# _GET
+# GetSomething 
+method-rgx=(_{,2}[a-z][A-Za-z0-9]*_{,2})$
+
+[DESIGN]
+# Maximum number of arguments for function / method.
+max-args=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=8
+
+# Maximum number of boolean expressions in an if statement.
+max-bool-expr=5
+
+# Maximum number of branch for function / method body.
+max-branches=12
+
+# Maximum number of locals for function / method body.
+max-locals=15
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+# Maximum number of return / yield for function / method body.
+max-returns=6
+
+# Maximum number of statements in function / method body.
+max-statements=50
+
+# Minimum number of public methods for a class (R0903).
+# We set this to 0 because our models and fields do not have methods.
+min-public-methods=0
+
+ignored-argument-names=arg|args|kwargs|_
+
+[CLASSES]
+defining-attr-methods=__init__,__new__,setUp,initialize
+
+[TYPECHECK]
+ignored-classes=NotImplemented
+
+[VARIABLES]
+dummy-variables-rgx=_+[a-z0-9_]{2,30}

+ 5 - 4
cura/Arranging/Arrange.py

@@ -1,6 +1,6 @@
 # Copyright (c) 2018 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
-from typing import List
+from typing import List, Optional
 
 from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
 from UM.Logger import Logger
@@ -8,6 +8,7 @@ from UM.Math.Polygon import Polygon
 from UM.Math.Vector import Vector
 from UM.Scene.SceneNode import SceneNode
 from cura.Arranging.ShapeArray import ShapeArray
+from cura.BuildVolume import BuildVolume
 from cura.Scene import ZOffsetDecorator
 
 from collections import namedtuple
@@ -27,7 +28,7 @@ LocationSuggestion = namedtuple("LocationSuggestion", ["x", "y", "penalty_points
 #
 #   Note: Make sure the scale is the same between ShapeArray objects and the Arrange instance.
 class Arrange:
-    build_volume = None
+    build_volume = None  # type: Optional[BuildVolume]
 
     def __init__(self, x, y, offset_x, offset_y, scale= 0.5):
         self._scale = scale  # convert input coordinates to arrange coordinates
@@ -68,7 +69,7 @@ class Arrange:
             points = copy.deepcopy(vertices._points)
 
             # After scaling (like up to 0.1 mm) the node might not have points
-            if len(points) == 0:
+            if not points.size:
                 continue
 
             shape_arr = ShapeArray.fromPolygon(points, scale = scale)
@@ -113,7 +114,7 @@ class Arrange:
             found_spot = True
             self.place(x, y, offset_shape_arr)  # place the object in arranger
         else:
-            Logger.log("d", "Could not find spot!"),
+            Logger.log("d", "Could not find spot!")
             found_spot = False
             node.setPosition(Vector(200, center_y, 100))
         return found_spot

+ 2 - 2
cura/Arranging/ArrangeObjectsAllBuildPlatesJob.py

@@ -29,7 +29,7 @@ class ArrangeArray:
         self._has_empty = False
         self._arrange = []  # type: List[Arrange]
 
-    def _update_first_empty(self):
+    def _updateFirstEmpty(self):
         for i, a in enumerate(self._arrange):
             if a.isEmpty:
                 self._first_empty = i
@@ -42,7 +42,7 @@ class ArrangeArray:
         new_arrange = Arrange.create(x = self._x, y = self._y, fixed_nodes = self._fixed_nodes)
         self._arrange.append(new_arrange)
         self._count += 1
-        self._update_first_empty()
+        self._updateFirstEmpty()
 
     def count(self):
         return self._count

+ 9 - 5
cura/AutoSave.py

@@ -2,12 +2,16 @@
 # Cura is released under the terms of the LGPLv3 or higher.
 
 from PyQt5.QtCore import QTimer
+from typing import Any, TYPE_CHECKING
 
 from UM.Logger import Logger
 
+if TYPE_CHECKING:
+    from cura.CuraApplication import CuraApplication
+
 
 class AutoSave:
-    def __init__(self, application):
+    def __init__(self, application: "CuraApplication") -> None:
         self._application = application
         self._application.getPreferences().preferenceChanged.connect(self._triggerTimer)
 
@@ -22,14 +26,14 @@ class AutoSave:
         self._enabled = True
         self._saving = False
 
-    def initialize(self):
+    def initialize(self) -> None:
         # only initialise if the application is created and has started
         self._change_timer.timeout.connect(self._onTimeout)
         self._application.globalContainerStackChanged.connect(self._onGlobalStackChanged)
         self._onGlobalStackChanged()
         self._triggerTimer()
 
-    def _triggerTimer(self, *args):
+    def _triggerTimer(self, *args: Any) -> None:
         if not self._saving:
             self._change_timer.start()
 
@@ -40,7 +44,7 @@ class AutoSave:
         else:
             self._change_timer.stop()
 
-    def _onGlobalStackChanged(self):
+    def _onGlobalStackChanged(self) -> None:
         if self._global_stack:
             self._global_stack.propertyChanged.disconnect(self._triggerTimer)
             self._global_stack.containersChanged.disconnect(self._triggerTimer)
@@ -51,7 +55,7 @@ class AutoSave:
             self._global_stack.propertyChanged.connect(self._triggerTimer)
             self._global_stack.containersChanged.connect(self._triggerTimer)
 
-    def _onTimeout(self):
+    def _onTimeout(self) -> None:
         self._saving = True # To prevent the save process from triggering another autosave.
         Logger.log("d", "Autosaving preferences, instances and profiles")
 

+ 17 - 11
cura/BuildVolume.py

@@ -1,15 +1,21 @@
 # Copyright (c) 2019 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
+
+import numpy
+import math
+
+from typing import List, Optional, TYPE_CHECKING, Any, Set, cast, Iterable, Dict
+
 from UM.Mesh.MeshData import MeshData
-from cura.Scene.CuraSceneNode import CuraSceneNode
-from cura.Settings.ExtruderManager import ExtruderManager
+from UM.Mesh.MeshBuilder import MeshBuilder
+
 from UM.Application import Application #To modify the maximum zoom level.
 from UM.i18n import i18nCatalog
 from UM.Scene.Platform import Platform
 from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
 from UM.Scene.SceneNode import SceneNode
 from UM.Resources import Resources
-from UM.Mesh.MeshBuilder import MeshBuilder
+
 from UM.Math.Vector import Vector
 from UM.Math.Matrix import Matrix
 from UM.Math.Color import Color
@@ -17,23 +23,23 @@ from UM.Math.AxisAlignedBox import AxisAlignedBox
 from UM.Math.Polygon import Polygon
 from UM.Message import Message
 from UM.Signal import Signal
-from PyQt5.QtCore import QTimer
 from UM.View.RenderBatch import RenderBatch
 from UM.View.GL.OpenGL import OpenGL
-from cura.Settings.GlobalStack import GlobalStack
 
-catalog = i18nCatalog("cura")
+from cura.Settings.GlobalStack import GlobalStack
+from cura.Scene.CuraSceneNode import CuraSceneNode
+from cura.Settings.ExtruderManager import ExtruderManager
 
-import numpy
-import math
+from PyQt5.QtCore import QTimer
 
-from typing import List, Optional, TYPE_CHECKING, Any, Set, cast, Iterable, Dict
 
 if TYPE_CHECKING:
     from cura.CuraApplication import CuraApplication
     from cura.Settings.ExtruderStack import ExtruderStack
     from UM.Settings.ContainerStack import ContainerStack
 
+catalog = i18nCatalog("cura")
+
 # Radius of disallowed area in mm around prime. I.e. how much distance to keep from prime position.
 PRIME_CLEARANCE = 6.5
 
@@ -1012,13 +1018,13 @@ class BuildVolume(SceneNode):
         all_values = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, "value")
         all_types = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, "type")
         for i, (setting_value, setting_type) in enumerate(zip(all_values, all_types)):
-            if not setting_value and (setting_type == "int" or setting_type == "float"):
+            if not setting_value and setting_type in ["int", "float"]:
                 all_values[i] = 0
         return all_values
 
     def _calculateBedAdhesionSize(self, used_extruders):
         if self._global_container_stack is None:
-            return
+            return None
 
         container_stack = self._global_container_stack
         adhesion_type = container_stack.getProperty("adhesion_type", "value")

+ 2 - 0
cura/CrashHandler.py

@@ -58,6 +58,8 @@ class CrashHandler:
         self.traceback = tb
         self.has_started = has_started
         self.dialog = None # Don't create a QDialog before there is a QApplication
+        self.cura_version = None
+        self.cura_locale = None
 
         Logger.log("c", "An uncaught error has occurred!")
         for line in traceback.format_exception(exception_type, value, tb):

+ 1 - 3
cura/CuraActions.py

@@ -3,17 +3,15 @@
 
 from PyQt5.QtCore import QObject, QUrl
 from PyQt5.QtGui import QDesktopServices
-from typing import List, Optional, cast
+from typing import List, cast
 
 from UM.Event import CallFunctionEvent
 from UM.FlameProfiler import pyqtSlot
-from UM.Math.Quaternion import Quaternion
 from UM.Math.Vector import Vector
 from UM.Scene.Selection import Selection
 from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
 from UM.Operations.GroupedOperation import GroupedOperation
 from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
-from UM.Operations.RotateOperation import RotateOperation
 from UM.Operations.TranslateOperation import TranslateOperation
 
 import cura.CuraApplication

+ 13 - 16
cura/CuraApplication.py

@@ -4,7 +4,7 @@
 import os
 import sys
 import time
-from typing import cast, TYPE_CHECKING, Optional, Callable, List
+from typing import cast, TYPE_CHECKING, Optional, Callable, List, Any
 
 import numpy
 
@@ -15,7 +15,7 @@ from PyQt5.QtQml import qmlRegisterUncreatableType, qmlRegisterSingletonType, qm
 
 from UM.i18n import i18nCatalog
 from UM.Application import Application
-from UM.Decorators import override, deprecated
+from UM.Decorators import override
 from UM.FlameProfiler import pyqtSlot
 from UM.Logger import Logger
 from UM.Message import Message
@@ -193,7 +193,7 @@ class CuraApplication(QtApplication):
 
         self._cura_package_manager = None
 
-        self._machine_action_manager = None
+        self._machine_action_manager = None  # type: Optional[MachineActionManager.MachineActionManager]
 
         self.empty_container = None  # type: EmptyInstanceContainer
         self.empty_definition_changes_container = None  # type: EmptyInstanceContainer
@@ -266,7 +266,6 @@ class CuraApplication(QtApplication):
         # Backups
         self._auto_save = None  # type: Optional[AutoSave]
 
-        from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
         self._container_registry_class = CuraContainerRegistry
         # Redefined here in order to please the typing.
         self._container_registry = None # type: CuraContainerRegistry
@@ -699,7 +698,7 @@ class CuraApplication(QtApplication):
             self._message_box_callback_arguments = []
 
     # Cura has multiple locations where instance containers need to be saved, so we need to handle this differently.
-    def saveSettings(self):
+    def saveSettings(self) -> None:
         if not self.started:
             # Do not do saving during application start or when data should not be saved on quit.
             return
@@ -989,8 +988,8 @@ class CuraApplication(QtApplication):
     ##  Get the machine action manager
     #   We ignore any *args given to this, as we also register the machine manager as qml singleton.
     #   It wants to give this function an engine and script engine, but we don't care about that.
-    def getMachineActionManager(self, *args):
-        return self._machine_action_manager
+    def getMachineActionManager(self, *args: Any) -> MachineActionManager.MachineActionManager:
+        return cast(MachineActionManager.MachineActionManager, self._machine_action_manager)
 
     @pyqtSlot(result = QObject)
     def getMaterialManagementModel(self) -> MaterialManagementModel:
@@ -1443,7 +1442,7 @@ class CuraApplication(QtApplication):
             if center is not None:
                 object_centers.append(center)
 
-        if object_centers and len(object_centers) > 0:
+        if object_centers:
             middle_x = sum([v.x for v in object_centers]) / len(object_centers)
             middle_y = sum([v.y for v in object_centers]) / len(object_centers)
             middle_z = sum([v.z for v in object_centers]) / len(object_centers)
@@ -1493,7 +1492,7 @@ class CuraApplication(QtApplication):
                 if center is not None:
                     object_centers.append(center)
 
-            if object_centers and len(object_centers) > 0:
+            if object_centers:
                 middle_x = sum([v.x for v in object_centers]) / len(object_centers)
                 middle_y = sum([v.y for v in object_centers]) / len(object_centers)
                 middle_z = sum([v.z for v in object_centers]) / len(object_centers)
@@ -1675,7 +1674,7 @@ class CuraApplication(QtApplication):
         extension = os.path.splitext(f)[1]
         extension = extension.lower()
         filename = os.path.basename(f)
-        if len(self._currently_loading_files) > 0:
+        if self._currently_loading_files:
             # If a non-slicable file is already being loaded, we prevent loading of any further non-slicable files
             if extension in self._non_sliceable_extensions:
                 message = Message(
@@ -1796,8 +1795,8 @@ class CuraApplication(QtApplication):
                 node.addDecorator(build_plate_decorator)
             build_plate_decorator.setBuildPlateNumber(target_build_plate)
 
-            op = AddSceneNodeOperation(node, scene.getRoot())
-            op.push()
+            operation = AddSceneNodeOperation(node, scene.getRoot())
+            operation.push()
 
             node.callDecoration("setActiveExtruder", default_extruder_id)
             scene.sceneChanged.emit(node)
@@ -1871,16 +1870,14 @@ class CuraApplication(QtApplication):
         main_window = QtApplication.getInstance().getMainWindow()
         if main_window:
             return main_window.width()
-        else:
-            return 0
+        return 0
 
     @pyqtSlot(result = int)
     def appHeight(self) -> int:
         main_window = QtApplication.getInstance().getMainWindow()
         if main_window:
             return main_window.height()
-        else:
-            return 0
+        return 0
 
     @pyqtSlot()
     def deleteAll(self, only_selectable: bool = True) -> None:

+ 7 - 3
cura/CuraPackageManager.py

@@ -1,7 +1,7 @@
 # Copyright (c) 2018 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 
-from typing import List, Tuple
+from typing import List, Tuple, TYPE_CHECKING, Optional
 
 from cura.CuraApplication import CuraApplication #To find some resource types.
 from cura.Settings.GlobalStack import GlobalStack
@@ -9,12 +9,16 @@ from cura.Settings.GlobalStack import GlobalStack
 from UM.PackageManager import PackageManager #The class we're extending.
 from UM.Resources import Resources #To find storage paths for some resource types.
 
+if TYPE_CHECKING:
+    from UM.Qt.QtApplication import QtApplication
+    from PyQt5.QtCore import QObject
+
 
 class CuraPackageManager(PackageManager):
-    def __init__(self, application, parent = None):
+    def __init__(self, application: "QtApplication", parent: Optional["QObject"] = None) -> None:
         super().__init__(application, parent)
 
-    def initialize(self):
+    def initialize(self) -> None:
         self._installation_dirs_dict["materials"] = Resources.getStoragePath(CuraApplication.ResourceTypes.MaterialInstanceContainer)
         self._installation_dirs_dict["qualities"] = Resources.getStoragePath(CuraApplication.ResourceTypes.QualityInstanceContainer)
 

+ 1 - 0
cura/CuraView.py

@@ -26,6 +26,7 @@ class CuraView(View):
     def mainComponent(self) -> QUrl:
         return self.getDisplayComponent("main")
 
+
     @pyqtProperty(QUrl, constant = True)
     def stageMenuComponent(self) -> QUrl:
         url = self.getDisplayComponent("menu")

Some files were not shown because too many files changed in this diff