Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: colour-science/colour-datasets
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.2.6
Choose a base ref
...
head repository: colour-science/colour-datasets
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: develop
Choose a head ref
  • 12 commits
  • 59 files changed
  • 1 contributor

Commits on Oct 12, 2024

  1. Update README.rst file.

    KelSolaar committed Oct 12, 2024
    Copy the full SHA
    db6e32d View commit details
  2. Merge branch 'feature/v0.2.7' into develop

    KelSolaar committed Oct 12, 2024
    Copy the full SHA
    37c3e80 View commit details

Commits on Oct 13, 2024

  1. Copy the full SHA
    fcd9a81 View commit details
  2. Require *colour* 0.4.5.

    KelSolaar committed Oct 13, 2024
    Copy the full SHA
    50a419f View commit details

Commits on Nov 24, 2024

  1. Update various social links.

    KelSolaar committed Nov 24, 2024
    Copy the full SHA
    5d14c28 View commit details

Commits on Dec 14, 2024

  1. Ignore *RUF022*.

    KelSolaar committed Dec 14, 2024
    Copy the full SHA
    d01c74e View commit details
  2. Update .gitignore file.

    KelSolaar committed Dec 14, 2024
    Copy the full SHA
    d6b934b View commit details
  3. Copy the full SHA
    c811b56 View commit details
  4. Disable isort glob.

    KelSolaar committed Dec 14, 2024
    Copy the full SHA
    cf11200 View commit details

Commits on Dec 22, 2024

  1. Copy the full SHA
    91ac338 View commit details

Commits on Dec 23, 2024

  1. Use colour checks configuration.

    KelSolaar committed Dec 23, 2024
    Copy the full SHA
    06f43bb View commit details

Commits on Dec 24, 2024

  1. Merge branch 'feature/v0.2.8' into develop

    KelSolaar committed Dec 24, 2024
    Copy the full SHA
    aa4ae7b View commit details
Showing with 685 additions and 619 deletions.
  1. +1 −0 .coveragerc
  2. +17 −12 .gitignore
  3. +8 −11 .pre-commit-config.yaml
  4. +3 −2 README.rst
  5. +8 −4 colour_datasets/__init__.py
  6. +6 −1 colour_datasets/loaders/__init__.py
  7. +5 −3 colour_datasets/loaders/abstract.py
  8. +19 −27 colour_datasets/loaders/asano2015.py
  9. +5 −1 colour_datasets/loaders/brendel2020.py
  10. +123 −107 colour_datasets/loaders/dyer2017.py
  11. +29 −16 colour_datasets/loaders/ebner1998.py
  12. +22 −8 colour_datasets/loaders/hung1995.py
  13. +4 −1 colour_datasets/loaders/jakob2019.py
  14. +5 −1 colour_datasets/loaders/jiang2013.py
  15. +5 −1 colour_datasets/loaders/karge2015.py
  16. +15 −9 colour_datasets/loaders/kuopio.py
  17. +8 −2 colour_datasets/loaders/labsphere2019.py
  18. +25 −20 colour_datasets/loaders/luo1997.py
  19. +21 −20 colour_datasets/loaders/luo1999.py
  20. +5 −1 colour_datasets/loaders/solomotav2023.py
  21. +2 −2 colour_datasets/loaders/tests/test_abstract.py
  22. +4 −5 colour_datasets/loaders/tests/test_asano2015.py
  23. +4 −4 colour_datasets/loaders/tests/test_brendel2020.py
  24. +4 −5 colour_datasets/loaders/tests/test_dyer2017.py
  25. +4 −4 colour_datasets/loaders/tests/test_ebner1998.py
  26. +4 −5 colour_datasets/loaders/tests/test_hung1995.py
  27. +4 −5 colour_datasets/loaders/tests/test_jakob2019.py
  28. +4 −5 colour_datasets/loaders/tests/test_jiang2013.py
  29. +4 −5 colour_datasets/loaders/tests/test_karge2015.py
  30. +4 −4 colour_datasets/loaders/tests/test_kuopio.py
  31. +4 −5 colour_datasets/loaders/tests/test_labsphere2019.py
  32. +4 −5 colour_datasets/loaders/tests/test_luo1997.py
  33. +4 −5 colour_datasets/loaders/tests/test_luo1999.py
  34. +4 −5 colour_datasets/loaders/tests/test_solomotav2023.py
  35. +4 −5 colour_datasets/loaders/tests/test_winquist2022.py
  36. +4 −5 colour_datasets/loaders/tests/test_xrite2016.py
  37. +4 −5 colour_datasets/loaders/tests/test_zhao2009.py
  38. +3 −1 colour_datasets/loaders/winquist2022.py
  39. +7 −4 colour_datasets/loaders/xrite2016.py
  40. +4 −1 colour_datasets/loaders/zhao2009.py
  41. +2 −1 colour_datasets/records/__init__.py
  42. +8 −4 colour_datasets/records/configuration.py
  43. +3 −3 colour_datasets/records/tests/test_configuration.py
  44. +34 −34 colour_datasets/records/tests/test_zenodo.py
  45. +24 −21 colour_datasets/records/zenodo.py
  46. +2 −0 colour_datasets/utilities/__init__.py
  47. +24 −15 colour_datasets/utilities/common.py
  48. +5 −2 colour_datasets/utilities/spreadsheet.py
  49. +9 −9 colour_datasets/utilities/tests/test_common.py
  50. +5 −5 colour_datasets/utilities/tests/test_spreadsheet.py
  51. +1 −1 docs/conf.py
  52. +2 −1 docs/index.rst
  53. +1 −1 docs/installation.rst
  54. +19 −19 docs/requirements.txt
  55. +40 −82 pyproject.toml
  56. +65 −65 requirements.txt
  57. +25 −22 tasks.py
  58. +1 −1 utilities/export_todo.py
  59. +1 −1 utilities/unicode_to_ascii.py
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -5,4 +5,5 @@ sigterm = True
exclude_lines =
pragma: no cover
if __name__ == .__main__.:
if TYPE_CHECKING:
pass
29 changes: 17 additions & 12 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
# Common Files
*.egg-info
*.pyc
*.pyo
.DS_Store
.coverage*
.fleet
.idea
.ipynb_checkpoints
uv.lock

# Common Directories
.fleet/
.idea/
.ipynb_checkpoints/
.python-version
.sandbox
.vs
.vscode
.vs/
.vscode/
.sandbox/
build/
dist/
docs/_build/
docs/generated/
node_modules/
references/

__pycache__

build
dist
docs/_build
docs/generated
references
# Project Directories
zenodo
uv.lock
19 changes: 8 additions & 11 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: "v4.5.0"
rev: "v5.0.0"
hooks:
- id: check-added-large-files
- id: check-case-conflict
@@ -15,32 +15,29 @@ repos:
- id: requirements-txt-fixer
- id: trailing-whitespace
- repo: https://github.com/codespell-project/codespell
rev: v2.2.6
rev: v2.3.0
hooks:
- id: codespell
args: ["--ignore-words-list=exitance,seperately"]
args:
["--ignore-words-list=assertIn,exitance,seperately,socio-economic"]
exclude: "BIBLIOGRAPHY.bib|CONTRIBUTORS.rst"
- repo: https://github.com/ikamensh/flynt
rev: "1.0.1"
hooks:
- id: flynt
args: [--verbose]
- repo: https://github.com/PyCQA/isort
rev: "5.13.2"
hooks:
- id: isort
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.1.14"
rev: "v0.8.2"
hooks:
- id: ruff-format
- id: ruff
args: [--fix]
- repo: https://github.com/adamchainz/blacken-docs
rev: 1.16.0
rev: 1.19.1
hooks:
- id: blacken-docs
language_version: python3.10
- repo: https://github.com/pre-commit/mirrors-prettier
rev: "v3.1.0"
rev: "v4.0.0-alpha.8"
hooks:
- id: prettier
- repo: https://github.com/pre-commit/pygrep-hooks
5 changes: 3 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
@@ -162,7 +162,7 @@ Primary Dependencies

- `python >= 3.10, < 3.14 <https://www.python.org/download/releases>`__
- `cachetools <https://pypi.org/project/cachetools>`__
- `colour-science >= 4.4 <https://pypi.org/project/colour-science>`__
- `colour-science >= 4.5 <https://pypi.org/project/colour-science>`__
- `imageio >= 2, < 3 <https://imageio.github.io>`__
- `numpy >= 1.24, < 3 <https://pypi.org/project/numpy>`__
- `scipy >= 1.10, < 2 <https://pypi.org/project/scipy>`__
@@ -217,7 +217,8 @@ The *Colour Developers* can be reached via different means:
- `Facebook <https://www.facebook.com/python.colour.science>`__
- `Github Discussions <https://github.com/colour-science/colour-datasets/discussions>`__
- `Gitter <https://gitter.im/colour-science/colour>`__
- `Twitter <https://twitter.com/colour_science>`__
- `X <https://x.com/colour_science>`__
- `Bluesky <https://bsky.app/profile/colour-science.bsky.social>`__

About
-----
12 changes: 8 additions & 4 deletions colour_datasets/__init__.py
Original file line number Diff line number Diff line change
@@ -15,6 +15,10 @@
- utilities: Various utilities.
"""

# isort: skip_file

from __future__ import annotations

import contextlib
import os
import subprocess
@@ -52,19 +56,19 @@
__major_version__ = "0"
__minor_version__ = "2"
__change_version__ = "6"
__version__ = ".".join((__major_version__, __minor_version__, __change_version__))
__version__ = f"{__major_version__}.{__minor_version__}.{__change_version__}"

try:
_version = (
subprocess.check_output(
["git", "describe"], # noqa: S603, S607
subprocess.check_output( # noqa: S603
["git", "describe"], # noqa: S607
cwd=os.path.dirname(__file__),
stderr=subprocess.STDOUT,
)
.strip()
.decode("utf-8")
)
except Exception:
except Exception: # noqa: BLE001
_version = __version__

colour.utilities.ANCILLARY_COLOUR_SCIENCE_PACKAGES["colour-datasets"] = _version # pyright: ignore
7 changes: 6 additions & 1 deletion colour_datasets/loaders/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# isort: skip_file

from __future__ import annotations

import sys
import typing

if typing.TYPE_CHECKING:
from colour.hints import Any

from colour.hints import Any
from colour.utilities import CanonicalMapping, warning

from colour_datasets.records import datasets
8 changes: 5 additions & 3 deletions colour_datasets/loaders/abstract.py
Original file line number Diff line number Diff line change
@@ -9,11 +9,13 @@

from __future__ import annotations

import typing
from abc import ABC, abstractmethod

from colour.hints import Any
if typing.TYPE_CHECKING:
from colour.hints import Any

from colour_datasets.records import Record
from colour_datasets.records import Record

__author__ = "Colour Developers"
__copyright__ = "Copyright 2019 Colour Developers"
@@ -122,7 +124,7 @@ def load(self) -> Any:
when they implement it, e.g., ``super().sync()``.
"""

def sync(self):
def sync(self) -> None:
"""
Sync the dataset content, i.e., checks whether it is synced and pulls
it if required.
46 changes: 19 additions & 27 deletions colour_datasets/loaders/asano2015.py
Original file line number Diff line number Diff line change
@@ -17,7 +17,8 @@
from __future__ import annotations

import os
from collections import namedtuple
import typing
from dataclasses import dataclass, field

import numpy as np
import xlrd
@@ -26,7 +27,10 @@
LMS_ConeFundamentals,
XYZ_ColourMatchingFunctions,
)
from colour.hints import Dict, NDArrayFloat

if typing.TYPE_CHECKING:
from colour.hints import Dict

from colour.utilities import as_float_array, tstack

from colour_datasets.loaders import AbstractDatasetLoader
@@ -47,12 +51,8 @@
]


class Specification_Asano2015(
namedtuple(
"Specification_Asano2015",
("XYZ_2", "XYZ_10", "LMS_2", "LMS_10", "parameters", "others"),
)
):
@dataclass(frozen=True)
class Specification_Asano2015:
"""
Define the *Asano (2015)* specification for an observer.
@@ -74,24 +74,14 @@ class Specification_Asano2015(
References
----------
:cite:`Asano2015`
""" # noqa: D405, D407, D410, D411

def __new__(
cls,
XYZ_2: XYZ_ColourMatchingFunctions,
XYZ_10: XYZ_ColourMatchingFunctions,
LMS_2: LMS_ConeFundamentals,
LMS_10: LMS_ConeFundamentals,
parameters: NDArrayFloat,
others: Dict | None = None,
):
"""
Return a new instance of the
:class:`colour_datasets.loaders.asano2015.Specification_Asano2015`
class.
"""
"""

return super().__new__(cls, XYZ_2, XYZ_10, LMS_2, LMS_10, parameters, others)
XYZ_2: XYZ_ColourMatchingFunctions
XYZ_10: XYZ_ColourMatchingFunctions
LMS_2: LMS_ConeFundamentals
LMS_10: LMS_ConeFundamentals
parameters: Dict
others: Dict = field(default_factory=dict)


class DatasetLoader_Asano2015(AbstractDatasetLoader):
@@ -199,7 +189,7 @@ def load(self) -> Dict[str, Dict[int, Specification_Asano2015]]:
observer["LMS_2"],
observer["LMS_10"],
observer["parameters"],
dict(zip(header, values[i])),
dict(zip(header, values[i], strict=False)),
)

return self._content
@@ -284,7 +274,9 @@ def parse_workbook_Asano2015(

for i in range(observers[1]):
observer = i + 1
data[observer]["parameters"] = dict(zip(header, as_float_array(values[i])))
data[observer]["parameters"] = dict(
zip(header, as_float_array(values[i]), strict=False)
)

return data

6 changes: 5 additions & 1 deletion colour_datasets/loaders/brendel2020.py
Original file line number Diff line number Diff line change
@@ -18,10 +18,14 @@
from __future__ import annotations

import os
import typing

import numpy as np
from colour import LinearInterpolator, SpectralDistribution, SpectralShape
from colour.hints import Dict

if typing.TYPE_CHECKING:
from colour.hints import Dict

from colour.utilities import as_int

from colour_datasets.loaders import AbstractDatasetLoader
230 changes: 123 additions & 107 deletions colour_datasets/loaders/dyer2017.py

Large diffs are not rendered by default.

45 changes: 29 additions & 16 deletions colour_datasets/loaders/ebner1998.py
Original file line number Diff line number Diff line change
@@ -20,10 +20,14 @@

import codecs
import os
from collections import namedtuple
import typing
from dataclasses import dataclass

import numpy as np
from colour.hints import Dict, NDArrayFloat

if typing.TYPE_CHECKING:
from colour.hints import Dict, NDArrayFloat

from colour.utilities import as_float_array

from colour_datasets.loaders import AbstractDatasetLoader
@@ -43,12 +47,8 @@
]


class ConstantPerceivedHueColourMatches_Ebner1998(
namedtuple(
"ConstantPerceivedHueColourMatches_Ebner1998",
("name", "XYZ_r", "XYZ_cr", "XYZ_ct", "metadata"),
)
):
@dataclass(frozen=True)
class ConstantPerceivedHueColourMatches_Ebner1998:
"""
Define *Ebner and Fairchild (1998)* *Constant Perceived-Hue Data*
colour matches data for a given hue angle.
@@ -70,6 +70,19 @@ class ConstantPerceivedHueColourMatches_Ebner1998(
Dataset metadata.
"""

name: str
XYZ_r: NDArrayFloat
XYZ_cr: NDArrayFloat
XYZ_ct: NDArrayFloat
metadata: Dict

def __post_init__(self) -> None:
"""Post-initialise the class."""

object.__setattr__(self, "XYZ_r", as_float_array(self.XYZ_r))
object.__setattr__(self, "XYZ_cr", as_float_array(self.XYZ_cr))
object.__setattr__(self, "XYZ_ct", as_float_array(self.XYZ_ct))


class DatasetLoader_Ebner1998(AbstractDatasetLoader):
"""
@@ -148,14 +161,14 @@ def _parse_float_values(data: str) -> NDArrayFloat:
attribute, value = line.split("\t", 1)
hue, data = int(attribute), _parse_float_values(value)

self._content["Constant Perceived-Hue Data"][
hue
] = ConstantPerceivedHueColourMatches_Ebner1998(
f"Reference Hue Angle - {hue}",
XYZ_r,
data[0],
data[1:],
{"h": hue},
self._content["Constant Perceived-Hue Data"][hue] = (
ConstantPerceivedHueColourMatches_Ebner1998(
f"Reference Hue Angle - {hue}",
XYZ_r,
data[0],
data[1:],
{"h": hue},
)
)

return self._content
30 changes: 22 additions & 8 deletions colour_datasets/loaders/hung1995.py
Original file line number Diff line number Diff line change
@@ -19,11 +19,16 @@
from __future__ import annotations

import os
from collections import namedtuple
import typing
from dataclasses import dataclass

import numpy as np
from colour import CCS_ILLUMINANTS, xy_to_XYZ, xyY_to_XYZ
from colour.hints import Dict

if typing.TYPE_CHECKING:
from colour.hints import Dict, NDArrayFloat

from colour.utilities import as_float_array

from colour_datasets.loaders import AbstractDatasetLoader
from colour_datasets.records import datasets
@@ -42,12 +47,8 @@
]


class ConstantPerceivedHueColourMatches_Hung1995(
namedtuple(
"ConstantPerceivedHueColourMatches_Hung1995",
("name", "XYZ_r", "XYZ_cr", "XYZ_ct", "metadata"),
)
):
@dataclass(frozen=True)
class ConstantPerceivedHueColourMatches_Hung1995:
"""
Define *Hung and Berns (1995)* *Constant Hue Loci Data*
colour matches data for a given hue angle.
@@ -69,6 +70,19 @@ class ConstantPerceivedHueColourMatches_Hung1995(
Dataset metadata.
"""

name: str
XYZ_r: NDArrayFloat
XYZ_cr: NDArrayFloat
XYZ_ct: NDArrayFloat
metadata: Dict

def __post_init__(self) -> None:
"""Post-initialise the class."""

object.__setattr__(self, "XYZ_r", as_float_array(self.XYZ_r))
object.__setattr__(self, "XYZ_cr", as_float_array(self.XYZ_cr))
object.__setattr__(self, "XYZ_ct", as_float_array(self.XYZ_ct))


class DatasetLoader_Hung1995(AbstractDatasetLoader):
"""
5 changes: 4 additions & 1 deletion colour_datasets/loaders/jakob2019.py
Original file line number Diff line number Diff line change
@@ -19,8 +19,11 @@

import glob
import os
import typing

if typing.TYPE_CHECKING:
from colour.hints import Dict

from colour.hints import Dict
from colour.recovery import LUT3D_Jakob2019

from colour_datasets.loaders import AbstractDatasetLoader
6 changes: 5 additions & 1 deletion colour_datasets/loaders/jiang2013.py
Original file line number Diff line number Diff line change
@@ -21,11 +21,15 @@
import codecs
import os
import re
import typing

import numpy as np
from colour import SpectralShape

if typing.TYPE_CHECKING:
from colour.hints import Dict

from colour.characterisation import RGB_CameraSensitivities
from colour.hints import Dict
from colour.utilities import as_float_array

from colour_datasets.loaders import AbstractDatasetLoader
6 changes: 5 additions & 1 deletion colour_datasets/loaders/karge2015.py
Original file line number Diff line number Diff line change
@@ -20,10 +20,14 @@

import os
import re
import typing
from collections import defaultdict

from colour.algebra import LinearInterpolator
from colour.hints import Dict

if typing.TYPE_CHECKING:
from colour.hints import Dict

from colour.io import read_sds_from_csv_file

from colour_datasets.loaders import AbstractDatasetLoader
24 changes: 15 additions & 9 deletions colour_datasets/loaders/kuopio.py
Original file line number Diff line number Diff line change
@@ -40,13 +40,18 @@
import os
import re
import sys
from collections import namedtuple
import typing
from dataclasses import dataclass
from typing import ClassVar

import numpy as np
import scipy.io
from colour import SpectralDistribution, SpectralShape
from colour.hints import Any, Dict, Tuple, Type, cast

if typing.TYPE_CHECKING:
from colour.hints import Any, Dict, Tuple, Type

from colour.hints import cast

from colour_datasets.loaders import AbstractDatasetLoader
from colour_datasets.records import datasets
@@ -68,12 +73,8 @@
]


class MatFileMetadata_KuopioUniversity(
namedtuple(
"MatFileMetadata_KuopioUniversity",
("key", "shape", "transpose", "identifiers"),
)
):
@dataclass(frozen=True)
class MatFileMetadata_KuopioUniversity:
"""
Metadata storage for an *University of Kuopio* dataset spectral
distributions.
@@ -90,6 +91,11 @@ class MatFileMetadata_KuopioUniversity(
Identifiers for the spectral distributions.
"""

key: str
shape: SpectralShape
transpose: bool
identifiers: str | None


def read_sds_from_mat_file_KuopioUniversity(
mat_file: str, metadata: MatFileMetadata_KuopioUniversity
@@ -132,7 +138,7 @@ def read_sds_from_mat_file_KuopioUniversity(
identifier = f"{identifier} ({i})"

sds[identifier] = SpectralDistribution(
dict(zip(wavelengths, data)), name=identifier
dict(zip(wavelengths, data, strict=False)), name=identifier
)

return sds
10 changes: 8 additions & 2 deletions colour_datasets/loaders/labsphere2019.py
Original file line number Diff line number Diff line change
@@ -14,11 +14,17 @@
doi:10.5281/zenodo.3245875
"""

from __future__ import annotations

import os
import typing

import numpy as np
from colour import SpectralDistribution
from colour.hints import Dict, Optional

if typing.TYPE_CHECKING:
from colour.hints import Dict

from colour.utilities import tsplit

from colour_datasets.loaders import AbstractDatasetLoader
@@ -95,7 +101,7 @@ def load(self) -> Dict[str, SpectralDistribution]:
return self._content


_DATASET_LOADER_LABSPHERE2019: Optional[DatasetLoader_Labsphere2019] = None
_DATASET_LOADER_LABSPHERE2019: DatasetLoader_Labsphere2019 | None = None
"""
Singleton instance of the *Labsphere (2019)* *Labsphere SRS-99-020* dataset
loader.
45 changes: 25 additions & 20 deletions colour_datasets/loaders/luo1997.py
Original file line number Diff line number Diff line change
@@ -32,10 +32,14 @@
from __future__ import annotations

import os
from collections import namedtuple
import typing
from dataclasses import dataclass

import numpy as np
from colour.hints import Dict, Tuple

if typing.TYPE_CHECKING:
from colour.hints import Dict, NDArrayFloat, Tuple

from colour.utilities import as_float_array, usage_warning

from colour_datasets.loaders import AbstractDatasetLoader
@@ -56,9 +60,8 @@
]


class ExperimentalGroupLuo1997(
namedtuple("ExperimentalGroupLuo1997", ("name", "phases", "metadata"))
):
@dataclass(frozen=True)
class ExperimentalGroupLuo1997:
"""
Define a *Luo and Rhodes (1997)* *LUTCHI Colour Appearance Data*
experimental group, i.e., a group of experimental phases.
@@ -74,22 +77,13 @@ class ExperimentalGroupLuo1997(
Experimental group metadata.
"""

name: str
phases: Dict
metadata: Dict

class ExperimentalPhaseLuo1997(
namedtuple(
"ExperimentalPhaseLuo1997",
(
"name",
"JQCH_v",
"xyY_c",
"S_Y_c",
"Y_b",
"Y_r",
"XYZ_o",
"metadata",
),
)
):

@dataclass(frozen=True)
class ExperimentalPhaseLuo1997:
"""
Define a *Luo and Rhodes (1997)* *LUTCHI Colour Appearance Data*
experimental phase.
@@ -123,6 +117,15 @@ class ExperimentalPhaseLuo1997(
Experimental phase metadata.
"""

name: str
JQCH_v: NDArrayFloat
xyY_c: NDArrayFloat
S_Y_c: NDArrayFloat
Y_b: float
Y_r: float
XYZ_o: NDArrayFloat
metadata: Dict


class DatasetLoader_Luo1997(AbstractDatasetLoader):
"""
@@ -1032,6 +1035,7 @@ def load(self) -> Dict[str, ExperimentalGroupLuo1997]:
zip(
phase_metadata_headers,
[samples_count, (neutrals_start, neutrals_end)],
strict=False,
)
),
)
@@ -1043,6 +1047,7 @@ def load(self) -> Dict[str, ExperimentalGroupLuo1997]:
zip(
group_metadata_headers,
experimental_groups_summary[group],
strict=False,
)
),
)
41 changes: 21 additions & 20 deletions colour_datasets/loaders/luo1999.py
Original file line number Diff line number Diff line change
@@ -27,10 +27,15 @@

import codecs
import os
from collections import namedtuple
import typing
from dataclasses import dataclass

import numpy as np
from colour.hints import Dict, Tuple, cast

if typing.TYPE_CHECKING:
from colour.hints import Dict, NDArrayFloat, Tuple

from colour.hints import cast
from colour.utilities import as_float_array

from colour_datasets.loaders import AbstractDatasetLoader
@@ -50,23 +55,8 @@
]


class CorrespondingColourDataset_Luo1999(
namedtuple(
"CorrespondingColourDataset_Luo1999",
(
"name",
"XYZ_r",
"XYZ_t",
"XYZ_cr",
"XYZ_ct",
"Y_r",
"Y_t",
"B_r",
"B_t",
"metadata",
),
)
):
@dataclass(frozen=True)
class CorrespondingColourDataset_Luo1999:
"""
Define a *Luo and Rhodes (1999)* *Corresponding-Colour Datasets* dataset.
@@ -97,6 +87,17 @@ class CorrespondingColourDataset_Luo1999(
Dataset metadata.
"""

name: str
XYZ_r: NDArrayFloat
XYZ_t: NDArrayFloat
XYZ_cr: NDArrayFloat
XYZ_ct: NDArrayFloat
Y_r: float
Y_t: float
B_r: float
B_t: float
metadata: Dict


class DatasetLoader_Luo1999(AbstractDatasetLoader):
"""
@@ -449,7 +450,7 @@ def load(self) -> Dict[str, CorrespondingColourDataset_Luo1999]:
XYZ_ct.append(list(map(float, values[3:])))

name = f"{key} - {filename.split('.')[1]}"
dataset_metadata = dict(zip(metadata_headers, metadata))
dataset_metadata = dict(zip(metadata_headers, metadata, strict=False))

Y_r = dataset_metadata["Illuminance (lux)"][i][0]
Y_t = dataset_metadata["Illuminance (lux)"][i][1]
6 changes: 5 additions & 1 deletion colour_datasets/loaders/solomotav2023.py
Original file line number Diff line number Diff line change
@@ -19,9 +19,13 @@

import glob
import os
import typing

from colour.characterisation import RGB_CameraSensitivities
from colour.hints import Dict

if typing.TYPE_CHECKING:
from colour.hints import Dict

from colour.io import read_sds_from_csv_file

from colour_datasets.loaders import AbstractDatasetLoader
4 changes: 2 additions & 2 deletions colour_datasets/loaders/tests/test_abstract.py
Original file line number Diff line number Diff line change
@@ -20,15 +20,15 @@ class TestAbstractDatasetLoader:
class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID", "record", "id", "content")

for attribute in required_attributes:
assert attribute in dir(AbstractDatasetLoader)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load", "sync")
9 changes: 4 additions & 5 deletions colour_datasets/loaders/tests/test_asano2015.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Define the unit tests for the :mod:`colour_datasets.loaders.asano2015` module."""


import numpy as np
from colour import SpectralShape
from colour.constants import TOLERANCE_ABSOLUTE_TESTS
@@ -26,23 +25,23 @@ class TestDatasetLoader_Asano2015:
class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_Asano2015)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load", "parse_workbook_Asano2015")

for method in required_methods:
assert method in dir(DatasetLoader_Asano2015)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.asano2015.\
DatasetLoader_Asano2015.load` method.
@@ -134,7 +133,7 @@ class TestBuildAsano2015:
definition unit tests methods.
"""

def test_build_Asano2015(self):
def test_build_Asano2015(self) -> None:
"""
Test :func:`colour_datasets.loaders.asano2015.build_Asano2015`
definition.
8 changes: 4 additions & 4 deletions colour_datasets/loaders/tests/test_brendel2020.py
Original file line number Diff line number Diff line change
@@ -29,23 +29,23 @@ class TestDatasetLoader_Brendel2020:
DatasetLoader_Brendel2020` class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_Brendel2020)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")

for method in required_methods:
assert method in dir(DatasetLoader_Brendel2020)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.brendel2020.\
DatasetLoader_Brendel2020.load` method.
@@ -66,7 +66,7 @@ class TestBuildBrendel2020:
definition unit tests methods.
"""

def test_build_Brendel2020(self):
def test_build_Brendel2020(self) -> None:
"""
Test :func:`colour_datasets.loaders.brendel2020.build_Brendel2020`
definition.
9 changes: 4 additions & 5 deletions colour_datasets/loaders/tests/test_dyer2017.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Define the unit tests for the :mod:`colour_datasets.loaders.dyer2017` module."""


import numpy as np
from colour.constants import TOLERANCE_ABSOLUTE_TESTS

@@ -25,23 +24,23 @@ class TestDatasetLoader_Dyer2017:
class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_Dyer2017)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")

for method in required_methods:
assert method in dir(DatasetLoader_Dyer2017)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.dyer2017.DatasetLoader_Dyer2017.\
load` method.
@@ -288,7 +287,7 @@ class TestBuildDyer2017:
definition unit tests methods.
"""

def test_build_Dyer2017(self):
def test_build_Dyer2017(self) -> None:
"""
Test :func:`colour_datasets.loaders.dyer2017.build_Dyer2017`
definition.
8 changes: 4 additions & 4 deletions colour_datasets/loaders/tests/test_ebner1998.py
Original file line number Diff line number Diff line change
@@ -24,23 +24,23 @@ class TestDatasetLoader_Ebner1998:
class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_Ebner1998)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")

for method in required_methods:
assert method in dir(DatasetLoader_Ebner1998)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.ebner1998.\
DatasetLoader_Ebner1998.load` method.
@@ -125,7 +125,7 @@ class TestBuildEbner1998:
definition unit tests methods.
"""

def test_build_Ebner1998(self):
def test_build_Ebner1998(self) -> None:
"""
Test :func:`colour_datasets.loaders.ebner1998.build_Ebner1998`
definition.
9 changes: 4 additions & 5 deletions colour_datasets/loaders/tests/test_hung1995.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Define the unit tests for the :mod:`colour_datasets.loaders.hung1995` module."""


import numpy as np
from colour.constants import TOLERANCE_ABSOLUTE_TESTS

@@ -25,23 +24,23 @@ class TestDatasetLoader_Hung1995:
class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_Hung1995)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")

for method in required_methods:
assert method in dir(DatasetLoader_Hung1995)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.hung1995.DatasetLoader_Hung1995.\
load` method.
@@ -113,7 +112,7 @@ class TestBuildHung1995:
definition unit tests methods.
"""

def test_build_Hung1995(self):
def test_build_Hung1995(self) -> None:
"""
Test :func:`colour_datasets.loaders.hung1995.build_Hung1995`
definition.
9 changes: 4 additions & 5 deletions colour_datasets/loaders/tests/test_jakob2019.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Define the unit tests for the :mod:`colour_datasets.loaders.jakob2019` module."""


from colour_datasets.loaders import DatasetLoader_Jakob2019, build_Jakob2019

__author__ = "Colour Developers"
@@ -22,23 +21,23 @@ class TestDatasetLoader_Jakob2019:
class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_Jakob2019)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")

for method in required_methods:
assert method in dir(DatasetLoader_Jakob2019)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.jakob2019.\
DatasetLoader_Jakob2019.load` method.
@@ -59,7 +58,7 @@ class TestBuildJakob2019:
definition unit tests methods.
"""

def test_build_Jakob2019(self):
def test_build_Jakob2019(self) -> None:
"""
Test :func:`colour_datasets.loaders.jakob2019.build_Jakob2019`
definition.
9 changes: 4 additions & 5 deletions colour_datasets/loaders/tests/test_jiang2013.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Define the unit tests for the :mod:`colour_datasets.loaders.jiang2013` module."""


from colour import SpectralShape

from colour_datasets.loaders import DatasetLoader_Jiang2013, build_Jiang2013
@@ -24,23 +23,23 @@ class TestDatasetLoader_Jiang2013:
class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_Jiang2013)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")

for method in required_methods:
assert method in dir(DatasetLoader_Jiang2013)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.jiang2013.\
DatasetLoader_Jiang2013.load` method.
@@ -86,7 +85,7 @@ class TestBuildJiang2013:
definition unit tests methods.
"""

def test_build_Jiang2013(self):
def test_build_Jiang2013(self) -> None:
"""
Test :func:`colour_datasets.loaders.jiang2013.build_Jiang2013`
definition.
9 changes: 4 additions & 5 deletions colour_datasets/loaders/tests/test_karge2015.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Define the unit tests for the :mod:`colour_datasets.loaders.karge2015` module."""


from colour import SpectralShape

from colour_datasets.loaders import DatasetLoader_Karge2015, build_Karge2015
@@ -24,23 +23,23 @@ class TestDatasetLoader_Karge2015:
class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_Karge2015)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")

for method in required_methods:
assert method in dir(DatasetLoader_Karge2015)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.karge2015.\
DatasetLoader_Karge2015.load` method.
@@ -67,7 +66,7 @@ class TestBuildKarge2015:
definition unit tests methods.
"""

def test_build_Karge2015(self):
def test_build_Karge2015(self) -> None:
"""
Test :func:`colour_datasets.loaders.karge2015.build_Karge2015`
definition.
8 changes: 4 additions & 4 deletions colour_datasets/loaders/tests/test_kuopio.py
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ class TestReadSdsFromMatFileKuopioUniversity:
read_sds_from_mat_file_KuopioUniversity` definition unit tests methods.
"""

def test_read_sds_from_mat_file_KuopioUniversity(self):
def test_read_sds_from_mat_file_KuopioUniversity(self) -> None:
"""
Test :func:`colour_datasets.loaders.kuopio.\
read_sds_from_mat_file_KuopioUniversity` definition.
@@ -105,7 +105,7 @@ class TestDatasetLoader_KuopioUniversity:
DatasetLoader_KuopioUniversity` class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID", "METADATA")
@@ -123,7 +123,7 @@ def test_required_attributes(self):
for attribute in required_attributes:
assert attribute in dir(dataset_loader)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")
@@ -141,7 +141,7 @@ def test_required_methods(self):
for method in required_methods:
assert method in dir(dataset_loader)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.kuopio.\
DatasetLoader_KuopioUniversity.load` method.
9 changes: 4 additions & 5 deletions colour_datasets/loaders/tests/test_labsphere2019.py
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@
module.
"""


from colour import SpectralShape

from colour_datasets.loaders import (
@@ -30,23 +29,23 @@ class TestDatasetLoader_Labsphere2019:
DatasetLoader_Labsphere2019` class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_Labsphere2019)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")

for method in required_methods:
assert method in dir(DatasetLoader_Labsphere2019)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.labsphere2019.\
DatasetLoader_Labsphere2019.load` method.
@@ -65,7 +64,7 @@ class TestBuildLabsphere2019:
definition unit tests methods.
"""

def test_build_Labsphere2019(self):
def test_build_Labsphere2019(self) -> None:
"""
Test :func:`colour_datasets.loaders.labsphere2019.build_Labsphere2019`
definition.
9 changes: 4 additions & 5 deletions colour_datasets/loaders/tests/test_luo1997.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Define the unit tests for the :mod:`colour_datasets.loaders.luo1997` module."""


import numpy as np
from colour.constants import TOLERANCE_ABSOLUTE_TESTS

@@ -25,23 +24,23 @@ class TestDatasetLoader_Luo1997:
class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_Luo1997)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")

for method in required_methods:
assert method in dir(DatasetLoader_Luo1997)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.luo1997.DatasetLoader_Luo1997.\
load` method.
@@ -176,7 +175,7 @@ class TestBuildLuo1997:
definition unit tests methods.
"""

def test_build_Luo1997(self):
def test_build_Luo1997(self) -> None:
"""
Test :func:`colour_datasets.loaders.luo1997.build_Luo1997`
definition.
9 changes: 4 additions & 5 deletions colour_datasets/loaders/tests/test_luo1999.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Define the unit tests for the :mod:`colour_datasets.loaders.luo1999` module."""


import numpy as np
from colour.constants import TOLERANCE_ABSOLUTE_TESTS

@@ -25,23 +24,23 @@ class TestDatasetLoader_Luo1999:
class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_Luo1999)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")

for method in required_methods:
assert method in dir(DatasetLoader_Luo1999)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.luo1999.DatasetLoader_Luo1999.\
load` method.
@@ -159,7 +158,7 @@ class TestBuildLuo1999:
definition unit tests methods.
"""

def test_build_Luo1999(self):
def test_build_Luo1999(self) -> None:
"""
Test :func:`colour_datasets.loaders.luo1999.build_Luo1999`
definition.
9 changes: 4 additions & 5 deletions colour_datasets/loaders/tests/test_solomotav2023.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Define the unit tests for the :mod:`colour_datasets.loaders.solomotav2023` module."""


from colour import SpectralShape

from colour_datasets.loaders import (
@@ -27,23 +26,23 @@ class TestDatasetLoader_Solomotav2023:
class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_Solomotav2023)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")

for method in required_methods:
assert method in dir(DatasetLoader_Solomotav2023)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.solomotav2023.\
DatasetLoader_Solomotav2023.load` method.
@@ -63,7 +62,7 @@ class TestBuildSolomotav2023:
definition unit tests methods.
"""

def test_build_Solomotav2023(self):
def test_build_Solomotav2023(self) -> None:
"""
Test :func:`colour_datasets.loaders.solomotav2023.build_Solomotav2023`
definition.
9 changes: 4 additions & 5 deletions colour_datasets/loaders/tests/test_winquist2022.py
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@
module.
"""


import numpy as np
from colour.constants import TOLERANCE_ABSOLUTE_TESTS

@@ -32,23 +31,23 @@ class TestDatasetLoader_Winquist2022:
class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_Winquist2022)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")

for method in required_methods:
assert method in dir(DatasetLoader_Winquist2022)

def test_load(self):
def test_load(self) -> None:
"""
Test
:func:`colour_datasets.loaders.winquist2022.DatasetLoader_Winquist2022.\
@@ -71,7 +70,7 @@ class TestBuildWinquist2022:
definition unit tests methods.
"""

def test_build_Winquist2022(self):
def test_build_Winquist2022(self) -> None:
"""
Test :func:`colour_datasets.loaders.winquist2022.build_Winquist2022`
definition.
9 changes: 4 additions & 5 deletions colour_datasets/loaders/tests/test_xrite2016.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Define the unit tests for the :mod:`colour_datasets.loaders.xrite2016` module."""


from colour.characterisation import ColourChecker

from colour_datasets.loaders import DatasetLoader_XRite2016, build_XRite2016
@@ -24,23 +23,23 @@ class TestDatasetLoader_XRite2016:
class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_XRite2016)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")

for method in required_methods:
assert method in dir(DatasetLoader_XRite2016)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.xrite2016.\
DatasetLoader_XRite2016.load` method.
@@ -67,7 +66,7 @@ class TestBuildXRite2016:
definition unit tests methods.
"""

def test_build_XRite2016(self):
def test_build_XRite2016(self) -> None:
"""
Test :func:`colour_datasets.loaders.xrite2016.build_XRite2016`
definition.
9 changes: 4 additions & 5 deletions colour_datasets/loaders/tests/test_zhao2009.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Define the unit tests for the :mod:`colour_datasets.loaders.zhao2009` module."""


from colour import SpectralShape

from colour_datasets.loaders import DatasetLoader_Zhao2009, build_Zhao2009
@@ -24,23 +23,23 @@ class TestDatasetLoader_Zhao2009:
class unit tests methods.
"""

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = ("ID",)

for attribute in required_attributes:
assert attribute in dir(DatasetLoader_Zhao2009)

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = ("__init__", "load")

for method in required_methods:
assert method in dir(DatasetLoader_Zhao2009)

def test_load(self):
def test_load(self) -> None:
"""
Test :func:`colour_datasets.loaders.zhao2009.\
DatasetLoader_Zhao2009.load` method.
@@ -72,7 +71,7 @@ class TestBuildZhao2009:
definition unit tests methods.
"""

def test_build_Zhao2009(self):
def test_build_Zhao2009(self) -> None:
"""
Test :func:`colour_datasets.loaders.zhao2009.build_Zhao2009`
definition.
4 changes: 3 additions & 1 deletion colour_datasets/loaders/winquist2022.py
Original file line number Diff line number Diff line change
@@ -20,8 +20,10 @@

import glob
import os
import typing

from colour.hints import Dict
if typing.TYPE_CHECKING:
from colour.hints import Dict

from colour_datasets.loaders import AbstractDatasetLoader
from colour_datasets.loaders.dyer2017 import MultiSpectralDistributions_AMPAS
11 changes: 7 additions & 4 deletions colour_datasets/loaders/xrite2016.py
Original file line number Diff line number Diff line change
@@ -20,11 +20,14 @@

import codecs
import os
import typing

import numpy as np
from colour import CCS_ILLUMINANTS, Lab_to_XYZ, XYZ_to_xyY
from colour.characterisation import ColourChecker
from colour.hints import Dict

if typing.TYPE_CHECKING:
from colour.hints import Dict

from colour_datasets.loaders import AbstractDatasetLoader
from colour_datasets.records import datasets
@@ -110,7 +113,7 @@ def load(self) -> Dict[str, ColourChecker]:
illuminant = CCS_ILLUMINANTS["CIE 1931 2 Degree Standard Observer"]["ICC D50"]

self._content = {}
for key, filename in zip(keys, filenames):
for key, filename in zip(keys, filenames, strict=False):
directory = os.path.splitext(filename)[0]
path = os.path.join(self.record.repository, "dataset", directory, filename)

@@ -142,10 +145,10 @@ def load(self) -> Dict[str, ColourChecker]:
np.reshape(np.array(samples_data, dtype=object), (i, j, 2)),
[1, 0, 2],
)
keys, values = zip(*np.reshape(samples, (-1, 2)))
keys, values = zip(*np.reshape(samples, (-1, 2)), strict=False)
values = XYZ_to_xyY(Lab_to_XYZ(values, illuminant))
self._content[key] = ColourChecker(
key, dict(zip(keys, values)), illuminant, j, i
key, dict(zip(keys, values, strict=False)), illuminant, j, i
)

return self._content
5 changes: 4 additions & 1 deletion colour_datasets/loaders/zhao2009.py
Original file line number Diff line number Diff line change
@@ -18,10 +18,13 @@
from __future__ import annotations

import os
import typing

import numpy as np
from colour.characterisation import RGB_CameraSensitivities
from colour.hints import Dict

if typing.TYPE_CHECKING:
from colour.hints import Dict

from colour_datasets.loaders import AbstractDatasetLoader
from colour_datasets.records import datasets
3 changes: 2 additions & 1 deletion colour_datasets/records/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations
# isort: skip_file

from __future__ import annotations

from .configuration import Configuration, sandbox, use_sandbox
from .zenodo import Community, Record
12 changes: 8 additions & 4 deletions colour_datasets/records/configuration.py
Original file line number Diff line number Diff line change
@@ -9,13 +9,17 @@

import functools
import os
import typing

from colour.hints import Any, Callable, Dict
from colour.utilities import Structure
from colour.utilities.documentation import (
DocstringDict,
is_documentation_building,
)
from typing_extensions import Self

if typing.TYPE_CHECKING:
from colour.hints import Any, Callable, Dict

__author__ = "Colour Developers"
__copyright__ = "Copyright 2019 Colour Developers"
@@ -75,7 +79,7 @@ def use_sandbox(
state: bool = True,
api_url: str = "https://sandbox.zenodo.org/api",
community: str = "colour-science-datasets",
):
) -> None:
"""
Modify the *Colour - Datasets* configuration to use *Zenodo* sandbox.
@@ -120,7 +124,7 @@ def __init__(
self._api_url = api_url
self._community = community

def __enter__(self) -> sandbox:
def __enter__(self) -> Self:
"""
Set the configuration to the *Zenodo* sandbox upon entering the context
manager.
@@ -130,7 +134,7 @@ def __enter__(self) -> sandbox:

return self

def __exit__(self, *args: Any):
def __exit__(self, *args: Any) -> None:
"""Restore the configuration upon exiting the context manager."""

use_sandbox(False)
6 changes: 3 additions & 3 deletions colour_datasets/records/tests/test_configuration.py
Original file line number Diff line number Diff line change
@@ -24,12 +24,12 @@ class TestUseSandbox:
definition unit tests methods.
"""

def teardown_method(self):
def teardown_method(self) -> None:
"""After tests actions."""

use_sandbox(False)

def test_use_sandbox(self):
def test_use_sandbox(self) -> None:
"""
Test :func:`colour_datasets.records.configuration.use_sandbox`
definition.
@@ -47,7 +47,7 @@ class TestSandbox:
definition unit tests methods.
"""

def test_sandbox(self):
def test_sandbox(self) -> None:
"""
Test :func:`colour_datasets.records.configuration.sandbox`
definition.
68 changes: 34 additions & 34 deletions colour_datasets/records/tests/test_zenodo.py
Original file line number Diff line number Diff line change
@@ -29,15 +29,15 @@ class TestRecord(unittest.TestCase):
methods.
"""

def setUp(self):
def setUp(self) -> None:
"""Initialise the common tests attributes."""

self._data = json_open("https://zenodo.org/api/records/3245883")
self._configuration = Configuration()

self._record = Record(self._data, self._configuration)

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = (
@@ -51,7 +51,7 @@ def test_required_attributes(self):
for attribute in required_attributes:
self.assertIn(attribute, dir(Record))

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = (
@@ -67,20 +67,20 @@ def test_required_methods(self):
for method in required_methods:
self.assertIn(method, dir(Record))

def test_configuration(self):
def test_configuration(self) -> None:
"""
Test :func:colour_datasets.records.zenodo.Record.configuration`
property.
"""

self.assertEqual(self._record.configuration, self._configuration)

def test_data(self):
def test_data(self) -> None:
"""Test :func:colour_datasets.records.zenodo.Record.data` property."""

self.assertEqual(self._record.data, self._data)

def test_repository(self):
def test_repository(self) -> None:
"""
Test :func:colour_datasets.records.zenodo.Record.repository`
property.
@@ -91,12 +91,12 @@ def test_repository(self):
os.path.join(self._configuration.repository, "3245883"),
)

def test_id(self):
def test_id(self) -> None:
"""Test :func:colour_datasets.records.zenodo.Record.id` property."""

self.assertEqual(self._record.id, "3245883")

def test_title(self):
def test_title(self) -> None:
"""
Test :func:colour_datasets.records.zenodo.Record.title`
property.
@@ -107,7 +107,7 @@ def test_title(self):
"Camera Spectral Sensitivity Database - Jiang et al. (2013)",
)

def test__init__(self):
def test__init__(self) -> None:
"""
Test :func:`colour_datasets.records.zenodo.Record.__init__` method.
"""
@@ -119,7 +119,7 @@ def test__init__(self):
"Camera Spectral Sensitivity Database - Jiang et al. (2013)",
)

def test__str__(self):
def test__str__(self) -> None:
"""
Test :func:`colour_datasets.records.zenodo.Record.__str__` method.
"""
@@ -166,21 +166,21 @@ def test__str__(self):
)[1:],
)

def test__repr__(self):
def test__repr__(self) -> None:
"""
Test :func:`colour_datasets.records.zenodo.Record.__repr__` method.
"""

self.assertIsInstance(
eval( # noqa: PGH001, S307
eval( # noqa: S307
repr(self._record),
{},
{"Record": Record, "Configuration": Configuration},
),
Record,
)

def test_from_id(self):
def test_from_id(self) -> None:
"""Test :func:`colour_datasets.records.zenodo.Record.from_id` method."""

record = Record.from_id("3245883")
@@ -191,22 +191,22 @@ def test_from_id(self):
"Camera Spectral Sensitivity Database - Jiang et al. (2013)",
)

def test_synced(self):
def test_synced(self) -> None:
"""Test :func:`colour_datasets.records.zenodo.Record.synced` method."""

self._record.pull()
self.assertTrue(self._record.synced())
self._record.remove()
self.assertFalse(self._record.synced())

def test_pull(self):
def test_pull(self) -> None:
"""Test :func:`colour_datasets.records.zenodo.Record.pull` method."""

self._record.remove()
self._record.pull()
self.assertTrue(self._record.synced())

def test_remove(self):
def test_remove(self) -> None:
"""Test :func:`colour_datasets.records.zenodo.Record.remove` method."""

self._record.pull()
@@ -220,7 +220,7 @@ class TestCommunity(unittest.TestCase):
methods.
"""

def setUp(self):
def setUp(self) -> None:
"""Initialise the common tests attributes."""

community_data = json_open(
@@ -236,7 +236,7 @@ def setUp(self):

self._community = Community(self._data, self._configuration)

def test_required_attributes(self):
def test_required_attributes(self) -> None:
"""Test the presence of required attributes."""

required_attributes = (
@@ -249,7 +249,7 @@ def test_required_attributes(self):
for attribute in required_attributes:
self.assertIn(attribute, dir(Community))

def test_required_methods(self):
def test_required_methods(self) -> None:
"""Test the presence of required methods."""

required_methods = (
@@ -268,37 +268,37 @@ def test_required_methods(self):
for method in required_methods:
self.assertIn(method, dir(Community))

def test_configuration(self):
def test_configuration(self) -> None:
"""
Test :func:colour_datasets.records.zenodo.Community.configuration`
property.
"""

self.assertEqual(self._community.configuration, self._configuration)

def test_data(self):
def test_data(self) -> None:
"""
Test :func:colour_datasets.records.zenodo.Community.data` property.
"""

self.assertEqual(self._community.data, self._data)

def test_repository(self):
def test_repository(self) -> None:
"""
Test :func:colour_datasets.records.zenodo.Community.repository`
property.
"""

self.assertEqual(self._community.repository, self._configuration.repository)

def test_records(self):
def test_records(self) -> None:
"""
Test :func:colour_datasets.records.zenodo.Community.records` property.
"""

self.assertIn("3245883", list(self._community.records))

def test__init__(self):
def test__init__(self) -> None:
"""
Test :func:`colour_datasets.records.zenodo.Community.__init__` method.
"""
@@ -310,7 +310,7 @@ def test__init__(self):
"Camera Spectral Sensitivity Database - Jiang et al. (2013)",
)

def test__str__(self):
def test__str__(self) -> None:
"""
Test :func:`colour_datasets.records.zenodo.Community.__str__` method.
"""
@@ -339,45 +339,45 @@ def test__str__(self):
)[1:],
)

def test__repr__(self):
def test__repr__(self) -> None:
"""
Test :func:`colour_datasets.records.zenodo.Community.__repr__` method.
"""

self.assertIsInstance(
eval( # noqa: PGH001, S307
eval( # noqa: S307
repr(self._community),
{},
{"Community": Community, "Configuration": Configuration},
),
Community,
)

def test__getitem__(self):
def test__getitem__(self) -> None:
"""
Test :func:`colour_datasets.records.zenodo.Community.__getitem__`
method.
"""

self.assertIs(self._community["3245883"], self._community.records["3245883"])

def test__iter__(self):
def test__iter__(self) -> None:
"""
Test :func:`colour_datasets.records.zenodo.Community.__iter__`
method.
"""

self.assertListEqual(list(self._community), list(self._community.records))

def test__len__(self):
def test__len__(self) -> None:
"""
Test :func:`colour_datasets.records.zenodo.Community.__getitem__`
method.
"""

self.assertEqual(len(self._community), len(self._community.records))

def test_from_id(self):
def test_from_id(self) -> None:
"""
Test :func:`colour_datasets.records.zenodo.Community.from_id` method.
"""
@@ -390,7 +390,7 @@ def test_from_id(self):
"Camera Spectral Sensitivity Database - Jiang et al. (2013)",
)

def test_synced(self):
def test_synced(self) -> None:
"""
Test :func:`colour_datasets.records.zenodo.Community.synced` method.
"""
@@ -400,7 +400,7 @@ def test_synced(self):
self._community.remove()
self.assertFalse(self._community.synced())

def test_pull(self):
def test_pull(self) -> None:
"""
Test :func:`colour_datasets.records.zenodo.Community.pull` method.
"""
@@ -409,7 +409,7 @@ def test_pull(self):
self._community.pull()
self.assertTrue(self._community.synced())

def test_remove(self):
def test_remove(self) -> None:
"""
Test :func:`colour_datasets.records.zenodo.Community.remove` method.
"""
45 changes: 24 additions & 21 deletions colour_datasets/records/zenodo.py
Original file line number Diff line number Diff line change
@@ -18,25 +18,28 @@
import stat
import tempfile
import textwrap
import typing
import urllib
import urllib.error
from collections.abc import Mapping
from html.parser import HTMLParser
from pprint import pformat

import setuptools.archive_util
from colour.hints import (
Any,
Callable,
Dict,
Generator,
List,
)
from colour.utilities import optional, warning

from colour_datasets.records import Configuration
from colour_datasets.utilities import json_open, url_download

if typing.TYPE_CHECKING:
from colour.hints import (
Any,
Callable,
Dict,
Generator,
List,
)

__author__ = "Colour Developers"
__copyright__ = "Copyright 2019 Colour Developers"
__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
@@ -202,7 +205,7 @@ def strip_html(text: str) -> str:
]
)

representation = "\n".join(
return "\n".join(
[
f'{metadata["title"]} - {metadata["version"]}',
f'{"=" * (len(self.title) + 3 + len(metadata["version"]))}',
@@ -225,8 +228,6 @@ def strip_html(text: str) -> str:
]
)

return representation

def __repr__(self) -> str:
"""
Return an evaluable string representation of the *Zenodo* record.
@@ -331,7 +332,7 @@ def synced(self) -> bool:
]
)

def pull(self, use_urls_txt_file: bool = True, retries: int = 3):
def pull(self, use_urls_txt_file: bool = True, retries: int = 3) -> None:
"""
Pull the *Zenodo* record data to the local repository.
@@ -392,7 +393,7 @@ def urls_download(urls: Dict) -> None:
try:
if use_urls_txt_file and urls_txt:
urls = {}
urls_txt_file = tempfile.NamedTemporaryFile(delete=False).name
urls_txt_file = tempfile.NamedTemporaryFile(delete=False).name # noqa: SIM115
url_download(
urls_txt["links"]["self"],
urls_txt_file,
@@ -414,10 +415,13 @@ def urls_download(urls: Dict) -> None:

urls_download(urls)
else:
raise ValueError( # noqa: TRY301
msg = (
f'"{self._configuration.urls_txt_file}" file was not '
f"found in record data!"
)
raise ValueError( # noqa: TRY301
msg
)
except (urllib.error.URLError, ValueError) as error:
warning(
f"An error occurred using urls from "
@@ -472,7 +476,7 @@ def urls_download(urls: Dict) -> None:
with open(os.path.join(self.repository, "record.json"), "w") as record_json:
json.dump(self.data, record_json, indent=4, sort_keys=True)

def remove(self):
def remove(self) -> None:
"""
Remove the *Zenodo* record data local repository.
@@ -634,7 +638,7 @@ def __str__(self) -> str:

synced = len([dataset for dataset in self.values() if dataset.synced()])

representation = "\n".join(
return "\n".join(
[
f"{self._configuration.community}",
f'{"=" * len(self._configuration.community)}',
@@ -650,8 +654,6 @@ def __str__(self) -> str:
]
)

return representation

def __repr__(self) -> str:
"""
Return an evaluable string representation of the *Zenodo* community.
@@ -809,7 +811,8 @@ def from_id(
os.path.exists(records_json_filename),
]
):
raise RuntimeError("Local files were not found, aborting!") from error
msg = "Local files were not found, aborting!"
raise RuntimeError(msg) from error

with open(community_json_filename) as json_file:
community_data = json.loads(json_file.read())
@@ -850,7 +853,7 @@ def synced(self) -> bool:

return all(record.synced() for record in self._records.values())

def pull(self, use_urls_txt_file: bool = True, retries: int = 3):
def pull(self, use_urls_txt_file: bool = True, retries: int = 3) -> None:
"""
Pull the *Zenodo* community data to the local repository.
@@ -882,7 +885,7 @@ def pull(self, use_urls_txt_file: bool = True, retries: int = 3):
for record in self._records.values():
record.pull(use_urls_txt_file, retries)

def remove(self):
def remove(self) -> None:
"""
Remove the *Zenodo* community data local repository.
@@ -905,7 +908,7 @@ def _remove_readonly(
function: Callable,
path: str,
excinfo: Any, # noqa: ARG001
):
) -> None:
"""
Error handler for :func:`shutil.rmtree` definition that removes read-only
files.
2 changes: 2 additions & 0 deletions colour_datasets/utilities/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# isort: skip_file

from .common import (
suppress_stdout,
hash_md5,
39 changes: 24 additions & 15 deletions colour_datasets/utilities/common.py
Original file line number Diff line number Diff line change
@@ -15,13 +15,17 @@
import shutil
import socket
import sys
import typing
import urllib.error
import urllib.request

import setuptools.archive_util
from cachetools import TTLCache, cached
from colour.hints import Any, Callable, Dict
from tqdm import tqdm
from typing_extensions import Self

if typing.TYPE_CHECKING:
from colour.hints import Any, Callable, Dict

__author__ = "Colour Developers"
__copyright__ = "Copyright 2019 Colour Developers"
@@ -44,15 +48,15 @@
class suppress_stdout:
"""A context manager and decorator temporarily suppressing standard output."""

def __enter__(self) -> suppress_stdout:
def __enter__(self) -> Self:
"""Redirect the standard output upon entering the context manager."""

self._stdout = sys.stdout
sys.stdout = open(os.devnull, "w") # noqa: SIM115
sys.stdout = open(os.devnull, "w")

return self

def __exit__(self, *args: Any):
def __exit__(self, *args: Any) -> None:
"""Restore the standard output upon exiting the context manager."""

sys.stdout.close()
@@ -77,7 +81,7 @@ def update_to(
chunks_count: int = 1,
chunk_size: int = 1,
total_size: int | None = None,
):
) -> None:
"""
Report the progress of an action.
@@ -127,7 +131,9 @@ def hash_md5(filename: str, chunk_size: int = 2**16) -> str:
return md5.hexdigest()


def url_download(url: str, filename: str, md5: str | None = None, retries: int = 3):
def url_download(
url: str, filename: str, md5: str | None = None, retries: int = 3
) -> None:
"""
Download given url and saves its content at given file.
@@ -172,13 +178,16 @@ def url_download(url: str, filename: str, md5: str | None = None, retries: int =
socket.setdefaulttimeout(timeout)

if md5 is not None and md5.lower() != hash_md5(filename):
raise ValueError( # noqa: TRY301
msg = (
f'"MD5" hash of "{filename}" file does not match the '
f"expected hash!"
)
raise ValueError( # noqa: TRY301
msg
)

attempt = retries
except (urllib.error.URLError, OSError, ValueError):
except (urllib.error.URLError, OSError, ValueError): # noqa: PERF203
attempt += 1
print( # noqa: T201
f'An error occurred while downloading "{filename}" file '
@@ -229,7 +238,7 @@ def json_open(url: str, retries: int = 3) -> Dict:
request = urllib.request.Request(url) # noqa: S310
with urllib.request.urlopen(request) as response: # noqa: S310
return json.loads(response.read())
except (urllib.error.URLError, ValueError):
except (urllib.error.URLError, ValueError): # noqa: PERF203
attempt += 1
print( # noqa: T201
f'An error occurred while opening "{url}" url during attempt '
@@ -280,15 +289,15 @@ def unpack_gzipfile(
os.makedirs(extraction_directory)

try:
with gzip.open(filename) as gzip_file, open(
extraction_path, "wb"
) as output_file:
with (
gzip.open(filename) as gzip_file,
open(extraction_path, "wb") as output_file,
):
shutil.copyfileobj(gzip_file, output_file)
except Exception as error:
print(error) # noqa: T201
raise setuptools.archive_util.UnrecognizedFormat(
f'{filename} is not a "GZIP" file!'
) from error
msg = f'{filename} is not a "GZIP" file!'
raise setuptools.archive_util.UnrecognizedFormat(msg) from error

return True

7 changes: 5 additions & 2 deletions colour_datasets/utilities/spreadsheet.py
Original file line number Diff line number Diff line change
@@ -13,11 +13,14 @@
from __future__ import annotations

import re
import typing

import xlrd
from colour.hints import Dict, List
from colour.utilities import CanonicalMapping, attest

if typing.TYPE_CHECKING:
from colour.hints import Dict, List

__author__ = "Colour Developers, Openpyxl Developers"
__copyright__ = "Copyright 2019 Colour Developers"
__copyright__ += ", "
@@ -234,7 +237,7 @@ def cell_range_values(sheet: xlrd.sheet.Sheet, cell_range: str) -> List[str]:
row_out = row_to_index(groups["row_out"])

for row in range(row_in, row_out + 1, 1):
table.append(
table.append( # noqa: PERF401
sheet.row_values(row, start_colx=column_in, end_colx=column_out + 1)
)

18 changes: 9 additions & 9 deletions colour_datasets/utilities/tests/test_common.py
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ class TestHashMd5:
tests methods.
"""

def test_hash_md5(self):
def test_hash_md5(self) -> None:
"""Test :func:`colour_datasets.utilities.common.hash_md5` definition."""

dataset = build_Labsphere2019()
@@ -63,17 +63,17 @@ class TestUrlDownload:
unit tests methods.
"""

def setup_method(self):
def setup_method(self) -> None:
"""Initialise the common tests attributes."""

self._temporary_file = tempfile.NamedTemporaryFile(delete=False).name
self._temporary_file = tempfile.NamedTemporaryFile(delete=False).name # noqa: SIM115

def teardown_method(self):
def teardown_method(self) -> None:
"""After tests actions."""

os.remove(self._temporary_file)

def test_url_download(self):
def test_url_download(self) -> None:
"""Test :func:`colour_datasets.utilities.common.url_download` definition."""

dataset = build_Labsphere2019()
@@ -118,7 +118,7 @@ class TestJsonOpen:
unit tests methods.
"""

def test_json_open(self):
def test_json_open(self) -> None:
"""Test :func:`colour_datasets.utilities.common.json_open` definition."""

data = json_open("https://zenodo.org/api/records/3245883")
@@ -134,17 +134,17 @@ class TestUnpackGzipfile:
unit tests methods.
"""

def setup_method(self):
def setup_method(self) -> None:
"""Initialise the common tests attributes."""

self._temporary_directory = tempfile.mkdtemp()

def teardown_method(self):
def teardown_method(self) -> None:
"""After tests actions."""

shutil.rmtree(self._temporary_directory)

def test_unpack_gzipfile(self):
def test_unpack_gzipfile(self) -> None:
"""
Test :func:`colour_datasets.utilities.common.unpack_gzipfile`
definition.
10 changes: 5 additions & 5 deletions colour_datasets/utilities/tests/test_spreadsheet.py
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ class TestRowToIndex:
definition unit tests methods.
"""

def test_row_to_index(self):
def test_row_to_index(self) -> None:
"""
Test :func:`colour_datasets.utilities.spreadsheet.row_to_index`
definition.
@@ -59,7 +59,7 @@ class TestIndexToRow:
definition unit tests methods.
"""

def test_index_to_row(self):
def test_index_to_row(self) -> None:
"""
Test :func:`colour_datasets.utilities.spreadsheet.index_to_row`
definition.
@@ -78,7 +78,7 @@ class TestColumnToIndex:
definition unit tests methods.
"""

def test_column_to_index(self):
def test_column_to_index(self) -> None:
"""
Test :func:`colour_datasets.utilities.spreadsheet.column_to_index`
definition.
@@ -99,7 +99,7 @@ class TestIndexToColumn:
definition unit tests methods.
"""

def test_index_to_column(self):
def test_index_to_column(self) -> None:
"""
Test :func:`colour_datasets.utilities.spreadsheet.index_to_column`
definition.
@@ -118,7 +118,7 @@ class TestCellRangeValues:
definition unit tests methods.
"""

def test_cell_range_values(self):
def test_cell_range_values(self) -> None:
"""
Test :func:`colour_datasets.utilities.spreadsheet.cell_range_values`
definition.
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@

sys.path.append(str(Path(__file__).parent.parent))

import colour_datasets as package # noqa: E402
import colour_datasets as package

basename = re.sub("_(\\w)", lambda x: x.group(1).upper(), package.__name__.title())

3 changes: 2 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
@@ -156,7 +156,8 @@ The *Colour Developers* can be reached via different means:
- `Facebook <https://www.facebook.com/python.colour.science>`__
- `Github Discussions <https://github.com/colour-science/colour-datasets/discussions>`__
- `Gitter <https://gitter.im/colour-science/colour>`__
- `Twitter <https://twitter.com/colour_science>`__
- `X <https://x.com/colour_science>`__
- `Bluesky <https://bsky.app/profile/colour-science.bsky.social>`__

About
-----
2 changes: 1 addition & 1 deletion docs/installation.rst
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ Primary Dependencies

- `python >= 3.10, < 3.14 <https://www.python.org/download/releases>`__
- `cachetools <https://pypi.org/project/cachetools>`__
- `colour-science >= 4.4 <https://pypi.org/project/colour-science>`__
- `colour-science >= 4.5 <https://pypi.org/project/colour-science>`__
- `imageio >= 2, < 3 <https://imageio.github.io>`__
- `numpy >= 1.24, < 3 <https://pypi.org/project/numpy>`__
- `scipy >= 1.10, < 2 <https://pypi.org/project/scipy>`__
38 changes: 19 additions & 19 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -6,50 +6,50 @@ babel==2.16.0
beautifulsoup4==4.12.3
biblib-simple==0.1.2
cachetools==5.5.0
certifi==2024.8.30
certifi==2024.12.14
charset-normalizer==3.4.0
colorama==0.4.6 ; sys_platform == 'win32' or platform_system == 'Windows'
colorama==0.4.6 ; sys_platform == 'win32'
colour-science==0.4.6
contourpy==1.3.0
contourpy==1.3.1
cycler==0.12.1
docutils==0.21.2
fonttools==4.54.1
fonttools==4.55.3
idna==3.10
imageio==2.35.1
imageio==2.36.1
imagesize==1.4.1
jinja2==3.1.4
jinja2==3.1.5
kiwisolver==1.4.7
latexcodec==3.0.0
markupsafe==3.0.1
matplotlib==3.9.2
numpy==2.1.2
markupsafe==3.0.2
matplotlib==3.10.0
numpy==2.2.1
opencv-python==4.10.0.84
packaging==24.1
pillow==10.4.0
packaging==24.2
pillow==11.0.0
pybtex==0.24.0
pybtex-docutils==1.0.3
pydata-sphinx-theme==0.15.4
pydata-sphinx-theme==0.16.1
pygments==2.18.0
pyparsing==3.1.4
pyparsing==3.2.0
python-dateutil==2.9.0.post0
pyyaml==6.0.2
requests==2.32.3
restructuredtext-lint==1.4.0
scipy==1.14.1
setuptools==75.1.0 ; python_full_version >= '3.12'
six==1.16.0
setuptools==75.6.0 ; python_full_version >= '3.12'
six==1.17.0
snowballstemmer==2.2.0
soupsieve==2.6
sphinx==8.1.2
sphinx==8.1.3
sphinxcontrib-applehelp==2.0.0
sphinxcontrib-bibtex==2.6.3
sphinxcontrib-devhelp==2.0.0
sphinxcontrib-htmlhelp==2.1.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==2.0.0
sphinxcontrib-serializinghtml==2.0.0
tomli==2.0.2 ; python_full_version < '3.11'
tqdm==4.66.5
tomli==2.2.1 ; python_full_version < '3.11'
tqdm==4.67.1
typing-extensions==4.12.2
urllib3==2.2.3
urllib3==2.3.0
xlrd==1.2.0
122 changes: 40 additions & 82 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@ classifiers = [
]
dependencies = [
"cachetools",
"colour-science>=0.4.4",
"colour-science>=0.4.5",
"imageio>=2,<3",
"numpy>=1.24,<3",
"opencv-python>=4,<5",
@@ -100,19 +100,15 @@ build-backend = "hatchling.build"
packages = [ "colour_datasets" ]

[tool.codespell]
ignore-words-list = "exitance,seperately"
ignore-words-list = "assertIn,exitance,seperately,socio-economic"
skip = "BIBLIOGRAPHY.bib,CONTRIBUTORS.rst"

[tool.flynt]
line_length=999

[tool.isort]
ensure_newline_before_comments = true
force_grid_wrap = 0
include_trailing_comma = true
line_length = 88
multi_line_output = 3
skip_glob = ["colour_datasets/**/__init__.py"]
split_on_trailing_comma = true
use_parentheses = true

@@ -129,91 +125,53 @@ reportUnusedExpression = false
addopts = "--durations=5"

[tool.ruff]
target-version = "py39"
target-version = "py310"
line-length = 88
select = [
"A", # flake8-builtins
"ARG", # flake8-unused-arguments
# "ANN", # flake8-annotations
"B", # flake8-bugbear
# "BLE", # flake8-blind-except
"C4", # flake8-comprehensions
# "C90", # mccabe
# "COM", # flake8-commas
"DTZ", # flake8-datetimez
"D", # pydocstyle
"E", # pydocstyle
# "ERA", # eradicate
# "EM", # flake8-errmsg
"EXE", # flake8-executable
"F", # flake8
# "FBT", # flake8-boolean-trap
"G", # flake8-logging-format
"I", # isort
"ICN", # flake8-import-conventions
"INP", # flake8-no-pep420
"ISC", # flake8-implicit-str-concat
"N", # pep8-naming
# "PD", # pandas-vet
"PIE", # flake8-pie
"PGH", # pygrep-hooks
"PL", # pylint
# "PT", # flake8-pytest-style
# "PTH", # flake8-use-pathlib [Enable]
"Q", # flake8-quotes
"RET", # flake8-return
"RUF", # Ruff
"S", # flake8-bandit
"SIM", # flake8-simplify
"T10", # flake8-debugger
"T20", # flake8-print
# "TCH", # flake8-type-checking
"TID", # flake8-tidy-imports
"TRY", # tryceratops
"UP", # pyupgrade
"W", # pydocstyle
"YTT" # flake8-2020
]
select = ["ALL"]
ignore = [
"B008",
"B905",
"D104",
"D200",
"D202",
"D205",
"D301",
"D400",
"I001",
"N801",
"N802",
"N803",
"N806",
"N813",
"N815",
"N816",
"PGH003",
"PIE804",
"PLE0605",
"PLR0911",
"PLR0912",
"PLR0913",
"PLR0915",
"PLR2004",
"RET504",
"RET505",
"RET506",
"RET507",
"RET508",
"TRY003",
"TRY300",
"C", # Pylint - Convention
"C90", # mccabe
"COM", # flake8-commas
"ERA", # eradicate
"FBT", # flake8-boolean-trap
"FIX", # flake8-fixme
"PT", # flake8-pytest-style
"PTH", # flake8-use-pathlib [Enable]
"TD", # flake8-todos
"ANN401", # Dynamically typed expressions (typing.Any) are disallowed in `**kwargs`
"D200", # One-line docstring should fit on one line
"D202", # No blank lines allowed after function docstring
"D205", # 1 blank line required between summary line and description
"D301", # Use `r"""` if any backslashes in a docstring
"D400", # First line should end with a period
"I001", # Import block is un-sorted or un-formatted
"N801", # Class name `.*` should use CapWords convention
"N802", # Function name `.*` should be lowercase
"N803", # Argument name `.*` should be lowercase
"N806", # Variable `.*` in function should be lowercase
"N813", # Camelcase `.*` imported as lowercase `.*`
"N815", # Variable `.*` in class scope should not be mixedCase
"N816", # Variable `.*` in global scope should not be mixedCase
"NPY002", # Replace legacy `np.random.random` call with `np.random.Generator`
"PGH003", # Use specific rule codes when ignoring type issues
"PLR0912", # Too many branches
"PLR0913", # Too many arguments in function definition
"PLR0915", # Too many statements
"PLR2004", # Magic value used in comparison, consider replacing `.*` with a constant variable
"PYI036", # Star-args in `.*` should be annotated with `object`
"PYI051", # `Literal[".*"]` is redundant in a union with `str`
"PYI056", # Calling `.append()` on `__all__` may not be supported by all type checkers (use `+=` instead)
"RUF022", # [*] `__all__` is not sorted
"TRY003", # Avoid specifying long messages outside the exception class
"UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)`
]
typing-modules = ["colour.hints"]
fixable = ["B", "C", "E", "F", "PIE", "RUF", "SIM", "UP", "W"]

[tool.ruff.pydocstyle]
convention = "numpy"

[tool.ruff.per-file-ignores]
"__init__.py" = ["D104"]
"colour_datasets/examples/*" = ["INP", "T201", "T203"]
"docs/*" = ["INP"]
"tasks.py" = ["INP"]
130 changes: 65 additions & 65 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -2,34 +2,34 @@
# uv export --no-hashes --all-extras
accessible-pygments==0.0.5
alabaster==1.0.0
anyio==4.6.0
appnope==0.1.4 ; platform_system == 'Darwin'
anyio==4.7.0
appnope==0.1.4 ; sys_platform == 'darwin'
argon2-cffi==23.1.0
argon2-cffi-bindings==21.2.0
arrow==1.3.0
asttokens==2.4.1
asttokens==3.0.0
async-lru==2.0.4
attrs==24.2.0
attrs==24.3.0
babel==2.16.0
backports-tarfile==1.2.0 ; python_full_version < '3.12'
beautifulsoup4==4.12.3
biblib-simple==0.1.2
bleach==6.1.0
bleach==6.2.0
cachetools==5.5.0
certifi==2024.8.30
certifi==2024.12.14
cffi==1.17.1
cfgv==3.4.0
charset-normalizer==3.4.0
click==8.1.7
colorama==0.4.6 ; sys_platform == 'win32' or platform_system == 'Windows'
click==8.1.8
colorama==0.4.6 ; sys_platform == 'win32'
colour-science==0.4.6
comm==0.2.2
contourpy==1.3.0
coverage==7.6.2
contourpy==1.3.1
coverage==7.6.9
coveralls==4.0.1
cryptography==43.0.1 ; sys_platform == 'linux'
cryptography==44.0.0 ; sys_platform == 'linux'
cycler==0.12.1
debugpy==1.8.7
debugpy==1.8.11
decorator==5.1.1
defusedxml==0.7.1
distlib==0.3.9
@@ -38,100 +38,100 @@ docutils==0.21.2
exceptiongroup==1.2.2 ; python_full_version < '3.11'
execnet==2.1.1
executing==2.1.0
fastjsonschema==2.20.0
fastjsonschema==2.21.1
filelock==3.16.1
fonttools==4.54.1
fonttools==4.55.3
fqdn==1.5.1
h11==0.14.0
hatch==1.12.0
hatchling==1.25.0
httpcore==1.0.6
httpx==0.27.2
hatch==1.14.0
hatchling==1.27.0
httpcore==1.0.7
httpx==0.28.1
hyperlink==21.0.0
identify==2.6.1
identify==2.6.3
idna==3.10
imageio==2.35.1
imageio==2.36.1
imagesize==1.4.1
importlib-metadata==8.5.0
importlib-metadata==8.5.0 ; python_full_version < '3.12'
iniconfig==2.0.0
invoke==2.2.0
ipykernel==6.29.5
ipython==8.28.0
ipython==8.31.0
ipywidgets==8.1.5
isoduration==20.11.0
jaraco-classes==3.4.0
jaraco-context==6.0.1
jaraco-functools==4.1.0
jedi==0.19.1
jedi==0.19.2
jeepney==0.8.0 ; sys_platform == 'linux'
jinja2==3.1.4
json5==0.9.25
jinja2==3.1.5
json5==0.10.0
jsonpointer==3.0.0
jsonschema==4.23.0
jsonschema-specifications==2024.10.1
jupyter==1.1.1
jupyter-client==8.6.3
jupyter-console==6.6.3
jupyter-core==5.7.2
jupyter-events==0.10.0
jupyter-events==0.11.0
jupyter-lsp==2.2.5
jupyter-server==2.14.2
jupyter-server==2.15.0
jupyter-server-terminals==0.5.3
jupyterlab==4.2.5
jupyterlab==4.3.4
jupyterlab-pygments==0.3.0
jupyterlab-server==2.27.3
jupyterlab-widgets==3.0.13
keyring==25.4.1
keyring==25.5.0
kiwisolver==1.4.7
latexcodec==3.0.0
markdown-it-py==3.0.0
markupsafe==3.0.1
matplotlib==3.9.2
markupsafe==3.0.2
matplotlib==3.10.0
matplotlib-inline==0.1.7
mdurl==0.1.2
mistune==3.0.2
more-itertools==10.5.0
nbclient==0.10.0
nbclient==0.10.2
nbconvert==7.16.4
nbformat==5.10.4
nest-asyncio==1.6.0
nh3==0.2.18
nh3==0.2.20
nodeenv==1.9.1
notebook==7.2.2
notebook==7.3.2
notebook-shim==0.2.4
numpy==2.1.2
numpy==2.2.1
opencv-python==4.10.0.84
overrides==7.7.0
packaging==24.1
packaging==24.2
pandocfilters==1.5.1
parso==0.8.4
pathspec==0.12.1
pexpect==4.9.0
pillow==10.4.0
pkginfo==1.10.0
pillow==11.0.0
pkginfo==1.12.0
platformdirs==4.3.6
pluggy==1.5.0
pre-commit==4.0.1
prometheus-client==0.21.0
prometheus-client==0.21.1
prompt-toolkit==3.0.48
psutil==6.0.0
psutil==6.1.1
ptyprocess==0.7.0
pure-eval==0.2.3
pybtex==0.24.0
pybtex-docutils==1.0.3
pycparser==2.22
pydata-sphinx-theme==0.15.4
pydata-sphinx-theme==0.16.1
pygments==2.18.0
pyparsing==3.1.4
pyright==1.1.384
pytest==8.3.3
pytest-cov==5.0.0
pyparsing==3.2.0
pyright==1.1.391
pytest==8.3.4
pytest-cov==6.0.0
pytest-xdist==3.6.1
python-dateutil==2.9.0.post0
python-json-logger==2.0.7
pywin32==307 ; platform_python_implementation != 'PyPy' and sys_platform == 'win32'
python-json-logger==3.2.1
pywin32==308 ; platform_python_implementation != 'PyPy' and sys_platform == 'win32'
pywin32-ctypes==0.2.3 ; sys_platform == 'win32'
pywinpty==2.0.13 ; os_name == 'nt'
pywinpty==2.0.14 ; os_name == 'nt' and sys_platform != 'darwin' and sys_platform != 'linux'
pyyaml==6.0.2
pyzmq==26.2.0
readme-renderer==44.0
@@ -142,18 +142,18 @@ restructuredtext-lint==1.4.0
rfc3339-validator==0.1.4
rfc3986==2.0.0
rfc3986-validator==0.1.1
rich==13.9.2
rpds-py==0.20.0
rich==13.9.4
rpds-py==0.22.3
scipy==1.14.1
secretstorage==3.3.3 ; sys_platform == 'linux'
send2trash==1.8.3
setuptools==75.1.0
setuptools==75.6.0
shellingham==1.5.4
six==1.16.0
six==1.17.0
sniffio==1.3.1
snowballstemmer==2.2.0
soupsieve==2.6
sphinx==8.1.2
sphinx==8.1.3
sphinxcontrib-applehelp==2.0.0
sphinxcontrib-bibtex==2.6.3
sphinxcontrib-devhelp==2.0.0
@@ -163,28 +163,28 @@ sphinxcontrib-qthelp==2.0.0
sphinxcontrib-serializinghtml==2.0.0
stack-data==0.6.3
terminado==0.18.1
tinycss2==1.3.0
tinycss2==1.4.0
toml==0.10.2
tomli==2.0.2 ; python_full_version <= '3.11'
tomli==2.2.1 ; python_full_version <= '3.11'
tomli-w==1.1.0
tomlkit==0.13.2
tornado==6.4.1
tqdm==4.66.5
tornado==6.4.2
tqdm==4.67.1
traitlets==5.14.3
trove-classifiers==2024.10.12
twine==5.1.1
types-python-dateutil==2.9.0.20241003
trove-classifiers==2024.10.21.16
twine==6.0.1
types-python-dateutil==2.9.0.20241206
typing-extensions==4.12.2
uri-template==1.3.0
urllib3==2.2.3
urllib3==2.3.0
userpath==1.9.2
uv==0.4.20
virtualenv==20.26.6
uv==0.5.11
virtualenv==20.28.0
wcwidth==0.2.13
webcolors==24.8.0
webcolors==24.11.1
webencodings==0.5.1
websocket-client==1.8.0
widgetsnbextension==4.0.13
xlrd==1.2.0
zipp==3.20.2
zipp==3.21.0 ; python_full_version < '3.12'
zstandard==0.23.0
47 changes: 25 additions & 22 deletions tasks.py
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
import inspect
import os
import re
import typing
import uuid

import biblib.bib
@@ -20,7 +21,9 @@
if not hasattr(inspect, "getargspec"):
inspect.getargspec = inspect.getfullargspec # pyright: ignore

from invoke.context import Context
if typing.TYPE_CHECKING:
from invoke.context import Context

from invoke.tasks import task

__author__ = "Colour Developers"
@@ -72,7 +75,7 @@ def clean(
docs: bool = True,
bytecode: bool = False,
pytest: bool = True,
):
) -> None:
"""
Clean the project.
@@ -112,7 +115,7 @@ def formatting(
ctx: Context,
asciify: bool = True,
bibtex: bool = True,
):
) -> None:
"""
Convert unicode characters to ASCII and cleanup the *BibTeX* file.
@@ -155,7 +158,7 @@ def quality(
ctx: Context,
pyright: bool = True,
rstlint: bool = True,
):
) -> None:
"""
Check the codebase with *Pyright* and lints various *restructuredText*
files with *rst-lint*.
@@ -180,7 +183,7 @@ def quality(


@task
def precommit(ctx: Context):
def precommit(ctx: Context) -> None:
"""
Run the "pre-commit" hooks on the codebase.
@@ -195,7 +198,7 @@ def precommit(ctx: Context):


@task
def tests(ctx: Context):
def tests(ctx: Context) -> None:
"""
Run the unit tests with *Pytest*.
@@ -216,7 +219,7 @@ def tests(ctx: Context):


@task
def examples(ctx: Context):
def examples(ctx: Context) -> None:
"""
Run the examples.
@@ -236,7 +239,7 @@ def examples(ctx: Context):


@task(formatting, quality, precommit, tests, examples)
def preflight(ctx: Context): # noqa: ARG001
def preflight(ctx: Context) -> None: # noqa: ARG001
"""
Perform the preflight tasks, i.e., *formatting*, *tests*, *quality*, and
*examples*.
@@ -251,7 +254,7 @@ def preflight(ctx: Context): # noqa: ARG001


@task
def docs(ctx: Context, html: bool = True, pdf: bool = True):
def docs(ctx: Context, html: bool = True, pdf: bool = True) -> None:
"""
Build the documentation.
@@ -276,7 +279,7 @@ def docs(ctx: Context, html: bool = True, pdf: bool = True):


@task
def todo(ctx: Context):
def todo(ctx: Context) -> None:
"""
Export the TODO items.
@@ -293,7 +296,7 @@ def todo(ctx: Context):


@task
def requirements(ctx: Context):
def requirements(ctx: Context) -> None:
"""
Export the *requirements.txt* file.
@@ -314,7 +317,7 @@ def requirements(ctx: Context):


@task(clean, preflight, docs, todo, requirements)
def build(ctx: Context):
def build(ctx: Context) -> None:
"""
Build the project and runs dependency tasks, i.e., *docs*, *todo*, and
*preflight*.
@@ -331,7 +334,7 @@ def build(ctx: Context):


@task
def virtualise(ctx: Context, tests: bool = True):
def virtualise(ctx: Context, tests: bool = True) -> None:
"""
Create a virtual environment for the project build.
@@ -349,9 +352,7 @@ def virtualise(ctx: Context, tests: bool = True):
ctx.run(f"mv {PYPI_ARCHIVE_NAME}-{APPLICATION_VERSION} {unique_name}")
ctx.run(f"rm -rf {unique_name}/{PYTHON_PACKAGE_NAME}/resources")
ctx.run(
"ln -s ../../../{0}/resources {1}/{0}".format(
PYTHON_PACKAGE_NAME, unique_name
)
f"ln -s ../../../{PYTHON_PACKAGE_NAME}/resources {unique_name}/{PYTHON_PACKAGE_NAME}" # noqa: E501
)

with ctx.cd(unique_name):
@@ -371,7 +372,7 @@ def virtualise(ctx: Context, tests: bool = True):


@task
def tag(ctx: Context):
def tag(ctx: Context) -> None:
"""
Tag the repository according to defined version using *git-flow*.
@@ -385,7 +386,8 @@ def tag(ctx: Context):
result = ctx.run("git rev-parse --abbrev-ref HEAD", hide="both")

if result.stdout.strip() != "develop": # pyright: ignore
raise RuntimeError("Are you still on a feature or master branch?")
msg = "Are you still on a feature or master branch?"
raise RuntimeError(msg)

with open(os.path.join(PYTHON_PACKAGE_NAME, "__init__.py")) as file_handle:
file_content = file_handle.read()
@@ -405,7 +407,7 @@ def tag(ctx: Context):
1
)

version = ".".join((major_version, minor_version, change_version))
version = f"{major_version}.{minor_version}.{change_version}"

result = ctx.run("git ls-remote --tags upstream", hide="both")
remote_tags = result.stdout.strip().split("\n") # pyright: ignore
@@ -414,17 +416,18 @@ def tag(ctx: Context):
tags.add(remote_tag.split("refs/tags/")[1].replace("refs/tags/", "^{}"))
version_tags = sorted(tags)
if f"v{version}" in version_tags:
raise RuntimeError(
msg = (
f'A "{PYTHON_PACKAGE_NAME}" "v{version}" tag already exists in '
f"remote repository!"
)
raise RuntimeError(msg)

ctx.run(f"git flow release start v{version}")
ctx.run(f"git flow release finish v{version}")


@task(build)
def release(ctx: Context):
def release(ctx: Context) -> None:
"""
Release the project to *Pypi* with *Twine*.
@@ -441,7 +444,7 @@ def release(ctx: Context):


@task
def sha256(ctx: Context):
def sha256(ctx: Context) -> None:
"""
Compute the project *Pypi* package *sha256* with *OpenSSL*.
2 changes: 1 addition & 1 deletion utilities/export_todo.py
Original file line number Diff line number Diff line change
@@ -93,7 +93,7 @@ def extract_todo_items(root_directory: str) -> dict:
return todo_items


def export_todo_items(todo_items: dict, file_path: str):
def export_todo_items(todo_items: dict, file_path: str) -> None:
"""
Export TODO items to given file.
2 changes: 1 addition & 1 deletion utilities/unicode_to_ascii.py
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@
}


def unicode_to_ascii(root_directory: str):
def unicode_to_ascii(root_directory: str) -> None:
"""
Recursively convert from unicode to ASCII *.py*, *.bib* and *.rst* files
in given directory.