1# Copyright (c) 2018 Ultimaker B.V.
2# Uranium is released under the terms of the LGPLv3 or higher.
3
4# The purpose of this class is to create fixtures or methods that can be shared
5# among all settings tests.
6
7import os.path
8import pytest
9import unittest.mock #For mocking the container provider priority.
10
11from UM.PluginRegistry import PluginRegistry
12from UM.VersionUpgradeManager import VersionUpgradeManager
13from UM.Resources import Resources
14from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase
15from UM.Settings.ContainerProvider import ContainerProvider #To provide the fixtures for container providers.
16from UM.Settings.ContainerRegistry import ContainerRegistry
17import UM.Settings.ContainerStack
18from UM.Settings.DefinitionContainer import DefinitionContainer #To provide definition containers in the registry fixtures.
19import UM.Settings.InstanceContainer
20
21##  Creates a brand new container registry.
22#
23#   To force a new container registry, the registry is first set to None and
24#   then re-requested.
25#
26#   \return A brand new container registry.
27@pytest.fixture
28def container_registry(application, test_containers_provider, plugin_registry: PluginRegistry):
29    MimeTypeDatabase.addMimeType(
30        MimeType(
31            name = "application/x-uranium-definitioncontainer",
32            comment = "Uranium Definition Container",
33            suffixes = ["def.json"]
34        )
35    )
36
37    MimeTypeDatabase.addMimeType(
38        MimeType(
39            name = "application/x-uranium-instancecontainer",
40            comment = "Uranium Instance Container",
41            suffixes = [ "inst.cfg" ]
42        )
43    )
44
45    MimeTypeDatabase.addMimeType(
46        MimeType(
47            name = "application/x-uranium-containerstack",
48            comment = "Uranium Container Stack",
49            suffixes = [ "stack.cfg" ]
50        )
51    )
52
53    ContainerRegistry._ContainerRegistry__instance = None # Reset the private instance variable every time
54    registry = ContainerRegistry(application)
55
56    #We need to mock the "priority" plug-in metadata field, but preferably without mocking an entire plug-in.
57    with unittest.mock.patch("UM.PluginRegistry.PluginRegistry.getMetaData", unittest.mock.MagicMock(return_value = {"container_provider": {}})):
58        registry.addProvider(test_containers_provider)
59
60    UM.Settings.ContainerStack.setContainerRegistry(registry)
61    UM.Settings.InstanceContainer.setContainerRegistry(registry)
62    return registry
63
64@pytest.fixture
65def loaded_container_registry(container_registry: ContainerRegistry, test_containers_provider: ContainerProvider):
66    container_registry.addResourceType(Resources.InstanceContainers, "test_type")
67    container_registry.load()
68
69    return container_registry
70
71##  Empty container provider which returns nothing.
72@pytest.fixture
73def container_provider():
74    return TestContainerProvider()
75
76##  Container provider which provides the containers that are in the setting
77#   test directory.
78@pytest.fixture
79def test_containers_provider(container_provider: ContainerProvider, upgrade_manager: VersionUpgradeManager) -> ContainerProvider:
80    my_folder = os.path.dirname(os.path.abspath(__file__))
81
82    definition_ids = {"basic_definition", "children", "functions", "inherits", "metadata_definition", "multiple_settings", "single_setting"}
83    for definition_id in definition_ids:
84        container = DefinitionContainer(definition_id)
85        container.deserialize(open(os.path.join(my_folder, "definitions", definition_id + ".def.json"), encoding = "utf-8").read())
86        container_provider._containers[definition_id] = container
87        container_provider.addMetadata(container.getMetaData())
88
89    instance_ids = {"basic_instance", "metadata_instance", "setting_values"}
90    for instance_id in instance_ids:
91        container = UM.Settings.InstanceContainer.InstanceContainer(instance_id)
92        container.deserialize(open(os.path.join(my_folder, "instances", instance_id + ".inst.cfg"), encoding = "utf-8").read())
93        container_provider._containers[instance_id] = container
94        container_provider.addMetadata(container.getMetaData())
95
96    return container_provider
97
98##  Extremely basic implementation of a container provider.
99#
100#   To add something to this provider, add it to its `_containers` and its
101#   `_metadata` fields.
102class TestContainerProvider(ContainerProvider):
103
104    def __init__(self) -> None:
105        super().__init__()
106        self._plugin_id = "TestContainerProvider"
107        self._version = "0.1.0"
108
109    def getAllIds(self, *args, **kwargs):
110        return self._containers.keys()
111
112    def isReadOnly(self, *args, **kwargs):
113        return True
114
115    def loadContainer(self, container_id, *args, **kwargs):
116        return self._containers[container_id]
117
118    def loadMetadata(self, container_id, *args, **kwargs):
119        return self._metadata[container_id]
120
121    def saveContainer(self, *args, **kwargs):
122        return None