File: conftest.py

package info (click to toggle)
displaycal-py3 3.9.17-1
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 29,124 kB
  • sloc: python: 115,810; javascript: 11,545; xml: 598; sh: 257; makefile: 173
file content (265 lines) | stat: -rw-r--r-- 8,744 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# -*- coding: utf-8 -*-

import glob
import os
import pathlib
import shutil
import subprocess
import sys
import tarfile
import tempfile
import zipfile

from requests import HTTPError

import pytest

from DisplayCAL import config
from DisplayCAL.util_os import which
from DisplayCAL.worker import Worker

import DisplayCAL
from DisplayCAL import RealDisplaySizeMM
from DisplayCAL.argyll import (
    get_argyll_latest_version,
    get_argyll_version_string,
    parse_argyll_version_string,
)
from DisplayCAL.colormath import get_rgb_space
from DisplayCAL.config import setcfg, writecfg
from DisplayCAL.icc_profile import ICCProfile


@pytest.fixture(scope="module")
def data_files():
    """Generate data file list."""
    #  test/data
    extensions = ["*.txt", "*.tsv", "*.lin", "*.cal", "*.ti1", "*.ti3", "*.icc"]

    displaycal_parent_dir = pathlib.Path(DisplayCAL.__file__).parent
    search_paths = [
        displaycal_parent_dir,
        displaycal_parent_dir / "presets",
        displaycal_parent_dir / "ti1",
        displaycal_parent_dir.parent / "misc" / "ti3",
        displaycal_parent_dir.parent / "tests" / "data",
        displaycal_parent_dir.parent / "tests" / "data" / "sample",
        displaycal_parent_dir.parent / "tests" / "data" / "sample" / "issue129",
        displaycal_parent_dir.parent / "tests" / "data" / "sample" / "issue268",
        displaycal_parent_dir.parent / "tests" / "data" / "icc",
    ]
    d_files = {}
    for path in search_paths:
        for extension in extensions:
            # add files from DisplayCal/presets folder
            for element in path.glob(extension):
                d_files[element.name] = element

    yield d_files


@pytest.fixture(scope="module")
def data_path():
    """Return the tests/data folder path."""
    displaycal_parent_dir = pathlib.Path(DisplayCAL.__file__).parent
    return displaycal_parent_dir.parent / "tests" / "data"


@pytest.fixture(scope="module")
def setup_argyll():
    """Setup ArgyllCMS.

    This will search for ArgyllCMS binaries under ``.local/bin/Argyll*/bin`` and if it
    can not find it, it will download from the source.
    """
    # check if ArgyllCMS is already installed
    xicclu_path = which("xicclu")
    if xicclu_path:
        # ArgyllCMS is already installed
        argyll_path = pathlib.Path(xicclu_path).parent
        setcfg("argyll.dir", str(argyll_path.absolute()))
        argyll_version_string = get_argyll_version_string("xicclu", True, [str(argyll_path)])
        argyll_version = parse_argyll_version_string(argyll_version_string)
        print(f"argyll_version_string: {argyll_version_string}")
        print(f"argyll_version: {argyll_version}")
        setcfg("argyll.version", argyll_version_string)
        writecfg()
        yield argyll_path
        return

    # first look in to ~/local/bin/ArgyllCMS
    home = pathlib.Path().home()
    argyll_search_paths = glob.glob(str(home / ".local" / "bin" / "Argyll*" / "bin"))

    argyll_path = None
    for path in reversed(argyll_search_paths):
        path = pathlib.Path(path)
        if path.is_dir():
            argyll_path = path
            setcfg("argyll.dir", str(argyll_path.absolute()))
            argyll_version_string = get_argyll_version_string(
                "xicclu", True, [str(path)]
            )
            argyll_version = parse_argyll_version_string(argyll_version_string)
            print(f"argyll_version_string: {argyll_version_string}")
            print(f"argyll_version: {argyll_version}")
            setcfg("argyll.version", argyll_version_string)
            writecfg()
            break

    print(f"argyll_path: {argyll_path}")
    if argyll_path:
        yield argyll_path
        return

    # apparently argyll has not been found
    # download from source
    get_argyll_latest_version.cache_clear()
    argyll_version = get_argyll_latest_version()
    argyll_domain = config.defaults.get("argyll.domain", "")
    argyll_download_url = {
        "win32": f"{argyll_domain}/Argyll_V{argyll_version}_win64_exe.zip",
        "darwin": f"{argyll_domain}/Argyll_V{argyll_version}_osx10.6_x86_64_bin.tgz",
        "linux": f"{argyll_domain}/Argyll_V{argyll_version}_linux_x86_64_bin.tgz",
    }

    url = argyll_download_url[sys.platform]

    argyll_temp_path = tempfile.mkdtemp()
    # store current working directory
    current_working_directory = os.getcwd()

    # change dir to argyll temp path
    os.chdir(argyll_temp_path)

    # Download the package file if it doesn't already exist
    argyll_package_file_name = "Argyll.tgz" if sys.platform != "win32" else "Argyll.zip"
    if not os.path.exists(argyll_package_file_name):
        print(f"Downloading: {argyll_package_file_name}")
        print(f"URL: {url}")
        worker = Worker()
        result = worker.download(url, download_dir=argyll_temp_path)
        if isinstance(result, HTTPError):
            print(f"Error downloading {url}: {result}")
            raise result
        download_path = result
        print(f"Downloaded to: {download_path}")
        if os.path.exists(download_path):
            shutil.move(download_path, argyll_package_file_name)
    else:
        print(f"Package file already exists: {argyll_package_file_name}")
        print("Not downloading it again!")

    print(f"Decompressing Argyll Package: {argyll_package_file_name}")
    if sys.platform == "win32":
        with zipfile.ZipFile(argyll_package_file_name, "r") as zip_ref:
            zip_ref.extractall()
    else:
        with tarfile.open(argyll_package_file_name) as tar:
            tar.extractall()

    def cleanup():
        # cleanup the test
        shutil.rmtree(argyll_temp_path, ignore_errors=True)
        os.chdir(current_working_directory)

    argyll_path = pathlib.Path(argyll_temp_path) / f"Argyll_V{argyll_version}" / "bin"
    print(f"argyll_path: {argyll_path}")
    if argyll_path.is_dir():
        print("argyll_path is valid!")
        setcfg("argyll.dir", str(argyll_path.absolute()))
        argyll_version_string = get_argyll_version_string("xicclu", True, [str(argyll_path)])
        argyll_version = parse_argyll_version_string(argyll_version_string)
        print(f"argyll_version_string: {argyll_version_string}")
        print(f"argyll_version: {argyll_version}")
        setcfg("argyll.version", argyll_version_string)
        writecfg()
        os.environ["PATH"] = f"{argyll_path}{os.pathsep}{os.environ['PATH']}"
        yield argyll_path
        cleanup()
    else:
        print("argyll_path is invalid!")
        cleanup()
        pytest.skip("ArgyllCMS can not be setup!")


@pytest.fixture(scope="function")
def random_icc_profile():
    """Create a random ICCProfile suitable for modification."""
    rec709_gamma18 = list(get_rgb_space("Rec. 709"))
    icc_profile = ICCProfile.from_rgb_space(
        rec709_gamma18, b"Rec. 709 gamma 1.8"
    )
    icc_profile_path = tempfile.mktemp(suffix=".icc")
    icc_profile.write(icc_profile_path)

    yield icc_profile, icc_profile_path

    # clean the file
    os.remove(icc_profile_path)


@pytest.fixture(scope="function")
def patch_subprocess():
    """Patch subprocess.

    Yields:
        Any: The patched subprocess class.
    """

    class Process:
        def __init__(self, output=None):
            self.output = output

        def communicate(self):
            return self.output, None

    class PatchedSubprocess:
        passed_args = []
        passed_kwargs = {}
        STDOUT = None
        PIPE = None
        output = {}
        wShowWindow = None
        STARTUPINFO = subprocess.STARTUPINFO if sys.platform == "win32" else None
        STARTF_USESHOWWINDOW = (
            subprocess.STARTF_USESHOWWINDOW if sys.platform == "win32" else None
        )
        SW_HIDE = subprocess.SW_HIDE if sys.platform == "win32" else None

        @classmethod
        def Popen(cls, *args, **kwargs):
            cls.passed_args += args
            cls.passed_kwargs.update(kwargs)
            process = Process(output=cls.output.get("".join(*args)))
            return process

    yield PatchedSubprocess


@pytest.fixture(scope="function")
def patch_argyll_util(monkeypatch):
    """Patch argyll.

    Yields:
        Any: The patched argyll class.
    """

    class PatchedArgyll:
        passed_util_name = []

        @classmethod
        def get_argyll_util(cls, util_name):
            cls.passed_util_name.append(util_name)
            return "dispwin"

    monkeypatch.setattr("DisplayCAL.RealDisplaySizeMM.argyll", PatchedArgyll)

    yield PatchedArgyll


@pytest.fixture(scope="function")
def clear_displays():
    """Clear RealDisplaySizeMM._displays."""
    RealDisplaySizeMM._displays = None
    assert RealDisplaySizeMM._displays is None