From 553b09b6cf35568e1ee791cc4c2bab8026872ae7 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 8 May 2020 16:20:55 +0200 Subject: [PATCH] Convert doxygen to rst for GcodeWriter, LegacyProfileReader, MachineSettingsAction, ModelChecker --- plugins/GCodeWriter/GCodeWriter.py | 91 ++++++++++--------- .../LegacyProfileReader.py | 77 +++++++++------- .../tests/TestLegacyProfileReader.py | 6 +- .../MachineSettingsAction.py | 12 ++- plugins/ModelChecker/ModelChecker.py | 18 ++-- 5 files changed, 117 insertions(+), 87 deletions(-) diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index 792b2aff10..93ff0f51ff 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -14,34 +14,40 @@ from cura.Machines.ContainerTree import ContainerTree from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") -## Writes g-code to a file. -# -# While this poses as a mesh writer, what this really does is take the g-code -# in the entire scene and write it to an output device. Since the g-code of a -# single mesh isn't separable from the rest what with rafts and travel moves -# and all, it doesn't make sense to write just a single mesh. -# -# So this plug-in takes the g-code that is stored in the root of the scene -# node tree, adds a bit of extra information about the profiles and writes -# that to the output device. -class GCodeWriter(MeshWriter): - ## The file format version of the serialised g-code. - # - # It can only read settings with the same version as the version it was - # written with. If the file format is changed in a way that breaks reverse - # compatibility, increment this version number! - version = 3 - ## Dictionary that defines how characters are escaped when embedded in - # g-code. - # - # Note that the keys of this dictionary are regex strings. The values are - # not. +class GCodeWriter(MeshWriter): + """Writes g-code to a file. + + While this poses as a mesh writer, what this really does is take the g-code + in the entire scene and write it to an output device. Since the g-code of a + single mesh isn't separable from the rest what with rafts and travel moves + and all, it doesn't make sense to write just a single mesh. + + So this plug-in takes the g-code that is stored in the root of the scene + node tree, adds a bit of extra information about the profiles and writes + that to the output device. + """ + + version = 3 + """The file format version of the serialised g-code. + + It can only read settings with the same version as the version it was + written with. If the file format is changed in a way that breaks reverse + compatibility, increment this version number! + """ + escape_characters = { re.escape("\\"): "\\\\", # The escape character. re.escape("\n"): "\\n", # Newlines. They break off the comment. re.escape("\r"): "\\r" # Carriage return. Windows users may need this for visualisation in their editors. } + """Dictionary that defines how characters are escaped when embedded in + + g-code. + + Note that the keys of this dictionary are regex strings. The values are + not. + """ _setting_keyword = ";SETTING_" @@ -50,17 +56,19 @@ class GCodeWriter(MeshWriter): self._application = Application.getInstance() - ## Writes the g-code for the entire scene to a stream. - # - # Note that even though the function accepts a collection of nodes, the - # entire scene is always written to the file since it is not possible to - # separate the g-code for just specific nodes. - # - # \param stream The stream to write the g-code to. - # \param nodes This is ignored. - # \param mode Additional information on how to format the g-code in the - # file. This must always be text mode. def write(self, stream, nodes, mode = MeshWriter.OutputMode.TextMode): + """Writes the g-code for the entire scene to a stream. + + Note that even though the function accepts a collection of nodes, the + entire scene is always written to the file since it is not possible to + separate the g-code for just specific nodes. + + :param stream: The stream to write the g-code to. + :param nodes: This is ignored. + :param mode: Additional information on how to format the g-code in the + file. This must always be text mode. + """ + if mode != MeshWriter.OutputMode.TextMode: Logger.log("e", "GCodeWriter does not support non-text mode.") self.setInformation(catalog.i18nc("@error:not supported", "GCodeWriter does not support non-text mode.")) @@ -88,8 +96,9 @@ class GCodeWriter(MeshWriter): self.setInformation(catalog.i18nc("@warning:status", "Please prepare G-code before exporting.")) return False - ## Create a new container with container 2 as base and container 1 written over it. def _createFlattenedContainerInstance(self, instance_container1, instance_container2): + """Create a new container with container 2 as base and container 1 written over it.""" + flat_container = InstanceContainer(instance_container2.getName()) # The metadata includes id, name and definition @@ -106,15 +115,15 @@ class GCodeWriter(MeshWriter): return flat_container - ## Serialises a container stack to prepare it for writing at the end of the - # g-code. - # - # The settings are serialised, and special characters (including newline) - # are escaped. - # - # \param settings A container stack to serialise. - # \return A serialised string of the settings. def _serialiseSettings(self, stack): + """Serialises a container stack to prepare it for writing at the end of the g-code. + + The settings are serialised, and special characters (including newline) + are escaped. + + :param stack: A container stack to serialise. + :return: A serialised string of the settings. + """ container_registry = self._application.getContainerRegistry() prefix = self._setting_keyword + str(GCodeWriter.version) + " " # The prefix to put before each line. diff --git a/plugins/LegacyProfileReader/LegacyProfileReader.py b/plugins/LegacyProfileReader/LegacyProfileReader.py index 87b26eb4ec..c67136ce9b 100644 --- a/plugins/LegacyProfileReader/LegacyProfileReader.py +++ b/plugins/LegacyProfileReader/LegacyProfileReader.py @@ -16,58 +16,67 @@ from UM.Settings.InstanceContainer import InstanceContainer # The new profile t from cura.ReaderWriters.ProfileReader import ProfileReader # The plug-in type to implement. -## A plugin that reads profile data from legacy Cura versions. -# -# It reads a profile from an .ini file, and performs some translations on it. -# Not all translations are correct, mind you, but it is a best effort. class LegacyProfileReader(ProfileReader): - ## Initialises the legacy profile reader. - # - # This does nothing since the only other function is basically stateless. + """A plugin that reads profile data from legacy Cura versions. + + It reads a profile from an .ini file, and performs some translations on it. + Not all translations are correct, mind you, but it is a best effort. + """ + def __init__(self): + """Initialises the legacy profile reader. + + This does nothing since the only other function is basically stateless. + """ + super().__init__() - ## Prepares the default values of all legacy settings. - # - # These are loaded from the Dictionary of Doom. - # - # \param json The JSON file to load the default setting values from. This - # should not be a URL but a pre-loaded JSON handle. - # \return A dictionary of the default values of the legacy Cura version. def prepareDefaults(self, json: Dict[str, Dict[str, str]]) -> Dict[str, str]: + """Prepares the default values of all legacy settings. + + These are loaded from the Dictionary of Doom. + + :param json: The JSON file to load the default setting values from. This + should not be a URL but a pre-loaded JSON handle. + :return: A dictionary of the default values of the legacy Cura version. + """ + defaults = {} if "defaults" in json: for key in json["defaults"]: # We have to copy over all defaults from the JSON handle to a normal dict. defaults[key] = json["defaults"][key] return defaults - ## Prepares the local variables that can be used in evaluation of computing - # new setting values from the old ones. - # - # This fills a dictionary with all settings from the legacy Cura version - # and their values, so that they can be used in evaluating the new setting - # values as Python code. - # - # \param config_parser The ConfigParser that finds the settings in the - # legacy profile. - # \param config_section The section in the profile where the settings - # should be found. - # \param defaults The default values for all settings in the legacy Cura. - # \return A set of local variables, one for each setting in the legacy - # profile. def prepareLocals(self, config_parser, config_section, defaults): + """Prepares the local variables that can be used in evaluation of computing + + new setting values from the old ones. + + This fills a dictionary with all settings from the legacy Cura version + and their values, so that they can be used in evaluating the new setting + values as Python code. + + :param config_parser: The ConfigParser that finds the settings in the + legacy profile. + :param config_section: The section in the profile where the settings + should be found. + :param defaults: The default values for all settings in the legacy Cura. + :return: A set of local variables, one for each setting in the legacy + profile. + """ copied_locals = defaults.copy() # Don't edit the original! for option in config_parser.options(config_section): copied_locals[option] = config_parser.get(config_section, option) return copied_locals - ## Reads a legacy Cura profile from a file and returns it. - # - # \param file_name The file to read the legacy Cura profile from. - # \return The legacy Cura profile that was in the file, if any. If the - # file could not be read or didn't contain a valid profile, \code None - # \endcode is returned. def read(self, file_name): + """Reads a legacy Cura profile from a file and returns it. + + :param file_name: The file to read the legacy Cura profile from. + :return: The legacy Cura profile that was in the file, if any. If the + file could not be read or didn't contain a valid profile, None is returned. + """ + if file_name.split(".")[-1] != "ini": return None global_container_stack = Application.getInstance().getGlobalContainerStack() diff --git a/plugins/LegacyProfileReader/tests/TestLegacyProfileReader.py b/plugins/LegacyProfileReader/tests/TestLegacyProfileReader.py index cd0f681828..64f3e1d404 100644 --- a/plugins/LegacyProfileReader/tests/TestLegacyProfileReader.py +++ b/plugins/LegacyProfileReader/tests/TestLegacyProfileReader.py @@ -13,7 +13,7 @@ import UM.PluginRegistry # To mock the plug-in registry out. import UM.Settings.ContainerRegistry # To mock the container registry out. import UM.Settings.InstanceContainer # To intercept the serialised data from the read() function. -import LegacyProfileReader as LegacyProfileReaderModule # To get the directory of the module. +import LegacyProfileReader as LegacyProfileReaderModule # To get the directory of the module. @pytest.fixture @@ -126,9 +126,11 @@ test_prepareLocalsNoSectionErrorData = [ ) ] -## Test cases where a key error is expected. + @pytest.mark.parametrize("parser_data, defaults", test_prepareLocalsNoSectionErrorData) def test_prepareLocalsNoSectionError(legacy_profile_reader, parser_data, defaults): + """Test cases where a key error is expected.""" + parser = configparser.ConfigParser() parser.read_dict(parser_data) diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index 28535024a7..c82ef8f351 100755 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -23,9 +23,11 @@ if TYPE_CHECKING: catalog = UM.i18n.i18nCatalog("cura") -## This action allows for certain settings that are "machine only") to be modified. -# It automatically detects machine definitions that it knows how to change and attaches itself to those. class MachineSettingsAction(MachineAction): + """This action allows for certain settings that are "machine only") to be modified. + + It automatically detects machine definitions that it knows how to change and attaches itself to those. + """ def __init__(self, parent: Optional["QObject"] = None) -> None: super().__init__("MachineSettingsAction", catalog.i18nc("@action", "Machine Settings")) self._qml_url = "MachineSettingsAction.qml" @@ -56,9 +58,11 @@ class MachineSettingsAction(MachineAction): if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine": self._application.getMachineActionManager().addSupportedAction(container.getId(), self.getKey()) - ## Triggered when the global container stack changes or when the g-code - # flavour setting is changed. def _updateHasMaterialsInContainerTree(self) -> None: + """Triggered when the global container stack changes or when the g-code + + flavour setting is changed. + """ global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack() if global_stack is None: return diff --git a/plugins/ModelChecker/ModelChecker.py b/plugins/ModelChecker/ModelChecker.py index 057ee14945..138d84cc86 100644 --- a/plugins/ModelChecker/ModelChecker.py +++ b/plugins/ModelChecker/ModelChecker.py @@ -18,8 +18,8 @@ catalog = i18nCatalog("cura") class ModelChecker(QObject, Extension): - ## Signal that gets emitted when anything changed that we need to check. onChanged = pyqtSignal() + """Signal that gets emitted when anything changed that we need to check.""" def __init__(self): super().__init__() @@ -47,11 +47,13 @@ class ModelChecker(QObject, Extension): if not isinstance(args[0], Camera): self._change_timer.start() - ## Called when plug-ins are initialized. - # - # This makes sure that we listen to changes of the material and that the - # button is created that indicates warnings with the current set-up. def _pluginsInitialized(self): + """Called when plug-ins are initialized. + + This makes sure that we listen to changes of the material and that the + button is created that indicates warnings with the current set-up. + """ + Application.getInstance().getMachineManager().rootMaterialChanged.connect(self.onChanged) self._createView() @@ -106,8 +108,12 @@ class ModelChecker(QObject, Extension): if node.callDecoration("isSliceable"): yield node - ## Creates the view used by show popup. The view is saved because of the fairly aggressive garbage collection. def _createView(self): + """Creates the view used by show popup. + + The view is saved because of the fairly aggressive garbage collection. + """ + Logger.log("d", "Creating model checker view.") # Create the plugin dialog component