Skip to content

Commit

Permalink
Python copy support (#1575) (#1589)
Browse files Browse the repository at this point in the history
* Add deepcopy support for object with createEditableCopy method

Signed-off-by: Rémi Achard <[email protected]>

* Minor fixes

Signed-off-by: Rémi Achard <[email protected]>

* Removing python shallow copy method

Signed-off-by: Rémi Achard <[email protected]>

* Update comment and formating

Signed-off-by: Rémi Achard <[email protected]>

* Testing COnfig FileRules deepCopy

Signed-off-by: Rémi Achard <[email protected]>

* Add comment for ConfigTest

Signed-off-by: Rémi Achard <[email protected]>

Co-authored-by: Patrick Hodoul <[email protected]>

Co-authored-by: Rémi Achard <[email protected]>
  • Loading branch information
hodoulp and remia authored Jan 24, 2022
1 parent bb28982 commit 03cb778
Show file tree
Hide file tree
Showing 23 changed files with 349 additions and 16 deletions.
2 changes: 1 addition & 1 deletion include/OpenColorIO/OpenColorIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -1331,7 +1331,7 @@ extern OCIOEXPORT std::ostream & operator<< (std::ostream &, const FileRules &);
* ViewingRules
*
* Viewing Rules allow config authors to filter the list of views an application should offer
* based on the color space of an image. For example, a config may define a large number of
* based on the color space of an image. For example, a config may define a large number of
* views but not all of them may be appropriate for use with all color spaces. E.g., some views
* may be intended for use with scene-linear color space encodings and others with video color
* space encodings.
Expand Down
6 changes: 6 additions & 0 deletions src/bindings/python/PyBaker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ Each item is a tuple containing format name and format extension.
"shaperSize"_a = DEFAULT->getShaperSize(),
DOC(Baker, Create))

.def("__deepcopy__", [](const ConstBakerRcPtr & self, py::dict)
{
return self->createEditableCopy();
},
"memo"_a)

.def_static("getFormats", []()
{
return FormatIterator(nullptr);
Expand Down
6 changes: 6 additions & 0 deletions src/bindings/python/PyColorSpace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ void bindPyColorSpace(py::module & m)
"categories"_a = getCategoriesStdVec(DEFAULT),
DOC(ColorSpace, Create, 2))

.def("__deepcopy__", [](const ConstColorSpaceRcPtr & self, py::dict)
{
return self->createEditableCopy();
},
"memo"_a)

.def("getName", &ColorSpace::getName,
DOC(ColorSpace, getName))
.def("setName", &ColorSpace::setName, "name"_a.none(false),
Expand Down
6 changes: 6 additions & 0 deletions src/bindings/python/PyColorSpaceSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ void bindPyColorSpaceSet(py::module & m)
.def(py::init(&ColorSpaceSet::Create),
DOC(ColorSpaceSet, Create))

.def("__deepcopy__", [](const ConstColorSpaceSetRcPtr & self, py::dict)
{
return self->createEditableCopy();
},
"memo"_a)

.def("__eq__", &ColorSpaceSet::operator==, py::is_operator(),
DOC(ColorSpaceSet, operator, eq))
.def("__ne__", &ColorSpaceSet::operator!=, py::is_operator(),
Expand Down
6 changes: 6 additions & 0 deletions src/bindings/python/PyConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ void bindPyConfig(py::module & m)
.def(py::init(&Config::Create),
DOC(Config, Create))

.def("__deepcopy__", [](const ConstConfigRcPtr & self, py::dict)
{
return self->createEditableCopy();
},
"memo"_a)

.def_static("CreateRaw", &Config::CreateRaw,
DOC(Config, CreateRaw))
.def_static("CreateFromEnv", &Config::CreateFromEnv,
Expand Down
8 changes: 7 additions & 1 deletion src/bindings/python/PyContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,13 @@ void bindPyContext(py::module & m)
"searchPaths"_a = getSearchPathsStdVec(DEFAULT),
"stringVars"_a = getStringVarsStdMap(DEFAULT),
"environmentMode"_a = DEFAULT->getEnvironmentMode(),
DOC(Context, Create))
DOC(Context, Create))

.def("__deepcopy__", [](const ConstContextRcPtr & self, py::dict)
{
return self->createEditableCopy();
},
"memo"_a)

.def("__iter__", [](ContextRcPtr & self)
{
Expand Down
6 changes: 6 additions & 0 deletions src/bindings/python/PyFileRules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ void bindPyFileRules(py::module & m)
.def(py::init(&FileRules::Create),
DOC(FileRules, Create))

.def("__deepcopy__", [](const ConstFileRulesRcPtr & self, py::dict)
{
return self->createEditableCopy();
},
"memo"_a)

.def("getNumEntries", &FileRules::getNumEntries,
DOC(FileRules, getNumEntries))
.def("getIndexForRule", &FileRules::getIndexForRule, "ruleName"_a,
Expand Down
6 changes: 6 additions & 0 deletions src/bindings/python/PyLook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ void bindPyLook(py::module & m)
"description"_a = DEFAULT->getDescription(),
DOC(Look, Create))

.def("__deepcopy__", [](const ConstLookRcPtr & self, py::dict)
{
return self->createEditableCopy();
},
"memo"_a)

.def("getName", &Look::getName,
DOC(Look, getName))
.def("setName", &Look::setName, "name"_a.none(false),
Expand Down
8 changes: 7 additions & 1 deletion src/bindings/python/PyNamedTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ void bindPyNamedTransform(py::module & m)
"categories"_a = getCategoriesStdVec(DEFAULT),
DOC(NamedTransform, Create))

.def("__deepcopy__", [](const ConstNamedTransformRcPtr & self, py::dict)
{
return self->createEditableCopy();
},
"memo"_a)

.def("getName", &NamedTransform::getName,
DOC(NamedTransform, getName))
.def("setName", &NamedTransform::setName, "name"_a.none(false),
Expand Down Expand Up @@ -145,7 +151,7 @@ void bindPyNamedTransform(py::module & m)
DOC(NamedTransform, setDescription))
.def("getEncoding", &NamedTransform::getEncoding,
DOC(NamedTransform, getEncoding))
.def("setEncoding", &NamedTransform::setEncoding, "encodig"_a.none(false),
.def("setEncoding", &NamedTransform::setEncoding, "encoding"_a.none(false),
DOC(NamedTransform, setEncoding))

// Transform
Expand Down
6 changes: 6 additions & 0 deletions src/bindings/python/PyTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ void bindPyTransform(py::module & m)
py::class_<Transform, TransformRcPtr>(
m.attr("Transform"))

.def("__deepcopy__", [](const ConstTransformRcPtr & self, py::dict)
{
return self->createEditableCopy();
},
"memo"_a)

.def("validate", &Transform::validate,
DOC(Transform, validate))
.def("getTransformType", &Transform::getTransformType,
Expand Down
8 changes: 7 additions & 1 deletion src/bindings/python/PyViewTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,13 @@ void bindPyViewTransform(py::module & m)
"toReference"_a = DEFAULT->getTransform(VIEWTRANSFORM_DIR_TO_REFERENCE),
"fromReference"_a = DEFAULT->getTransform(VIEWTRANSFORM_DIR_FROM_REFERENCE),
"categories"_a = getCategoriesStdVec(DEFAULT),
DOC(ViewTransform, Create))
DOC(ViewTransform, Create))

.def("__deepcopy__", [](const ConstViewTransformRcPtr & self, py::dict)
{
return self->createEditableCopy();
},
"memo"_a)

.def("getName", &ViewTransform::getName,
DOC(ViewTransform, getName))
Expand Down
8 changes: 7 additions & 1 deletion src/bindings/python/PyViewingRules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@ void bindPyViewingRules(py::module & m)
clsViewingRules
.def(py::init(&ViewingRules::Create),
DOC(ViewingRules, Create))


.def("__deepcopy__", [](const ConstViewingRulesRcPtr & self, py::dict)
{
return self->createEditableCopy();
},
"memo"_a)

.def("getNumEntries", &ViewingRules::getNumEntries,
DOC(ViewingRules, getNumEntries))
.def("getIndexForRule", &ViewingRules::getIndexForRule, "ruleName"_a,
Expand Down
28 changes: 27 additions & 1 deletion tests/python/BakerTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# TODO: Add getFormatMetadata tests.

import unittest, os, sys
import copy, unittest, os, sys
import PyOpenColorIO as OCIO

class BakerTest(unittest.TestCase):
Expand Down Expand Up @@ -55,6 +55,32 @@ class BakerTest(unittest.TestCase):
"""

def test_copy(self):
"""
Test the deepcopy() method.
"""
cfg = OCIO.Config().CreateFromStream(self.SIMPLE_PROFILE)

bake = OCIO.Baker()
bake.setConfig(cfg)
bake.setFormat("cinespace")
bake.setInputSpace("lnh")
bake.setLooks("foo, +bar")
bake.setTargetSpace("test")
bake.setShaperSize(4)
bake.setCubeSize(2)

other = copy.deepcopy(bake)
self.assertFalse(other is bake)

self.assertEqual(other.getConfig(), bake.getConfig())
self.assertEqual(other.getFormat(), bake.getFormat())
self.assertEqual(other.getInputSpace(), bake.getInputSpace())
self.assertEqual(other.getLooks(), bake.getLooks())
self.assertEqual(other.getTargetSpace(), bake.getTargetSpace())
self.assertEqual(other.getShaperSize(), bake.getShaperSize())
self.assertEqual(other.getCubeSize(), bake.getCubeSize())

def test_interface(self):
"""
Test similar to C++ CPU test.
Expand Down
38 changes: 38 additions & 0 deletions tests/python/ColorSpaceTest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright Contributors to the OpenColorIO Project.

import copy
import unittest
import os
import sys
Expand All @@ -10,6 +11,7 @@


class ColorSpaceTest(unittest.TestCase):

def setUp(self):
self.colorspace = OCIO.ColorSpace()
self.log_tr = OCIO.LogTransform(10)
Expand All @@ -18,6 +20,42 @@ def tearDown(self):
self.colorspace = None
self.log_tr = None

def test_copy(self):
"""
Test the deepcopy() method.
"""
self.colorspace.setName('colorspace1')
self.colorspace.setFamily('family')
self.colorspace.setEqualityGroup('group')
self.colorspace.setDescription('description')
self.colorspace.setBitDepth(OCIO.BIT_DEPTH_UINT8)
self.colorspace.setEncoding('encoding')
self.colorspace.setIsData(False)
self.colorspace.setAllocation(OCIO.ALLOCATION_LG2)
self.colorspace.setAllocationVars([-8, 5, 0.00390625])
mat = OCIO.MatrixTransform()
self.colorspace.setTransform(mat, OCIO.COLORSPACE_DIR_TO_REFERENCE)
self.colorspace.setTransform(direction=OCIO.COLORSPACE_DIR_FROM_REFERENCE, transform=mat)
self.colorspace.addAlias('alias')
self.colorspace.addCategory('cat')

other = copy.deepcopy(self.colorspace)
self.assertFalse(other is self.colorspace)

self.assertEqual(other.getName(), self.colorspace.getName())
self.assertEqual(other.getFamily(), self.colorspace.getFamily())
self.assertEqual(other.getEqualityGroup(), self.colorspace.getEqualityGroup())
self.assertEqual(other.getDescription(), self.colorspace.getDescription())
self.assertEqual(other.getBitDepth(), self.colorspace.getBitDepth())
self.assertEqual(other.getEncoding(), self.colorspace.getEncoding())
self.assertEqual(other.isData(), self.colorspace.isData())
self.assertEqual(other.getAllocation(), self.colorspace.getAllocation())
self.assertEqual(other.getAllocationVars(), self.colorspace.getAllocationVars())
self.assertTrue(other.getTransform(OCIO.COLORSPACE_DIR_TO_REFERENCE).equals(self.colorspace.getTransform(OCIO.COLORSPACE_DIR_TO_REFERENCE)))
self.assertTrue(other.getTransform(OCIO.COLORSPACE_DIR_FROM_REFERENCE).equals(self.colorspace.getTransform(OCIO.COLORSPACE_DIR_FROM_REFERENCE)))
self.assertEqual(list(other.getAliases()), list(self.colorspace.getAliases()))
self.assertEqual(list(other.getCategories()), list(self.colorspace.getCategories()))

def test_allocation(self):
"""
Test the setAllocation() and getAllocation() methods.
Expand Down
41 changes: 41 additions & 0 deletions tests/python/ConfigTest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright Contributors to the OpenColorIO Project.

import copy
import unittest
import os
import sys
Expand Down Expand Up @@ -244,6 +245,46 @@


class ConfigTest(unittest.TestCase):

def test_copy(self):
"""
Test the deepcopy() method.
"""
cfg = OCIO.Config.CreateRaw()
cfg.setMajorVersion(2)
cfg.setMinorVersion(1)
cfg.setName('test config')
cfg.setDescription('test description')

cfg.addColorSpace(
OCIO.ColorSpace(OCIO.REFERENCE_SPACE_DISPLAY,
"display_cs",
toReference=OCIO.CDLTransform(sat=1.5)))
cfg.addColorSpace(
OCIO.ColorSpace(OCIO.REFERENCE_SPACE_SCENE,
"raw",
isData=True))

rules = OCIO.FileRules()
rules.insertRule(0, 'A', 'raw', '*', 'exr')
rules.insertRule(1, 'B', 'display_cs', '*', 'png')
cfg.setFileRules(rules)

other = copy.deepcopy(cfg)
self.assertFalse(other is cfg)

self.assertEqual(other.getMajorVersion(), cfg.getMajorVersion())
self.assertEqual(other.getMinorVersion(), cfg.getMinorVersion())
self.assertEqual(other.getName(), cfg.getName())
self.assertEqual(other.getDescription(), cfg.getDescription())
self.assertEqual(list(other.getColorSpaceNames()), list(cfg.getColorSpaceNames()))
self.assertEqual(other.getFileRules().getNumEntries(), cfg.getFileRules().getNumEntries())

# Check that the file rules are not shared between the two config instances.
rules.removeRule(0)
other.setFileRules(rules)
self.assertEqual(other.getFileRules().getNumEntries(), cfg.getFileRules().getNumEntries() - 1)

def test_shared_views(self):
# Test these Config functions: addSharedView, getSharedViews, removeSharedView.

Expand Down
22 changes: 21 additions & 1 deletion tests/python/ContextTest.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright Contributors to the OpenColorIO Project.

import unittest, os, sys
import copy, unittest, os, sys
import PyOpenColorIO as OCIO

class ContextTest(unittest.TestCase):

def test_copy(self):
"""
Test the deepcopy() method.
"""
cont = OCIO.Context()
cont.setSearchPath('testing123:testing456')
cont.setWorkingDir('/dir/123')
cont.setEnvironmentMode(OCIO.ENV_ENVIRONMENT_LOAD_PREDEFINED)
cont['TeSt'] = 'foobar'
cont['Bar'] = 'Foo'

other = copy.deepcopy(cont)
self.assertFalse(other is cont)

self.assertEqual(other.getCacheID(), cont.getCacheID())
self.assertEqual(other.getSearchPath(), cont.getSearchPath())
self.assertEqual(other.getWorkingDir(), cont.getWorkingDir())
self.assertEqual(other.getEnvironmentMode(), cont.getEnvironmentMode())
self.assertEqual(list(other), list(cont))

def test_interface(self):
"""
Construct and use Context.
Expand Down
27 changes: 26 additions & 1 deletion tests/python/FileRulesTest.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,36 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright Contributors to the OpenColorIO Project.

import unittest, os, sys
import copy, unittest, os, sys
import PyOpenColorIO as OCIO

class FileRulesTest(unittest.TestCase):

def test_copy(self):
"""
Test the deepcopy() method.
"""
rules = OCIO.FileRules()
rules.insertRule(0, 'test0', 'colorspace', 'pattern', 'ext')
rules.setCustomKey(0, 'key1', 'val1')
rules.insertRule(1, 'test2', 'colorspace', 'regex')
rules.setCustomKey(1, 'key2', 'val2')

other = copy.deepcopy(rules)
self.assertFalse(other is rules)

self.assertEqual(other.getNumEntries(), rules.getNumEntries())
for idx in range(other.getNumEntries()):
self.assertEqual(other.getName(idx), rules.getName(idx))
self.assertEqual(other.getPattern(idx), rules.getPattern(idx))
self.assertEqual(other.getExtension(idx), rules.getExtension(idx))
self.assertEqual(other.getRegex(idx), rules.getRegex(idx))
self.assertEqual(other.getColorSpace(idx), rules.getColorSpace(idx))
self.assertEqual(other.getNumCustomKeys(idx), rules.getNumCustomKeys(idx))
for idx_inner in range(other.getNumCustomKeys(idx)):
self.assertEqual(other.getCustomKeyName(idx, idx_inner), rules.getCustomKeyName(idx, idx_inner))
self.assertEqual(other.getCustomKeyValue(idx, idx_inner), rules.getCustomKeyValue(idx, idx_inner))

def test_default(self):
"""
Construct and verify default values.
Expand Down
Loading

0 comments on commit 03cb778

Please sign in to comment.