Skip to content

Commit

Permalink
Merge branch 'feature/decimal' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
shidarin committed Jun 16, 2014
2 parents ea89e9a + e824e46 commit 231ed4b
Show file tree
Hide file tree
Showing 16 changed files with 553 additions and 307 deletions.
18 changes: 17 additions & 1 deletion cdl_convert/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
parse_cdl, parse_file, parse_flex,
parse_rnh_cdl
)
from .utils import reset_all, sanity_check
from .utils import sanity_check, to_decimal
from .write import write_cc, write_ccc, write_cdl, write_rnh_cdl

# ==============================================================================
Expand Down Expand Up @@ -110,8 +110,24 @@
'sanity_check',
'SatNode',
'SopNode',
'to_decimal',
'write_cc',
'write_ccc',
'write_cdl',
'write_rnh_cdl',
]

# ==============================================================================
# PUBLIC FUNCTIONS
# ==============================================================================


def reset_all():
"""Resets all class level member lists and dictionaries"""
# Import these here to avoid cyclic imports

ColorCorrection.reset_members()
ColorCorrectionRef.reset_members()
ColorDecision.reset_members()
ColorCollection.reset_members()
MediaRef.reset_members()
29 changes: 10 additions & 19 deletions cdl_convert/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@
from __future__ import absolute_import, print_function

# Standard Imports
from xml.dom import minidom
from decimal import Decimal
import re
import sys
from xml.dom import minidom
from xml.etree import ElementTree

# cdl_convert Imports
from . import config
from .utils import to_decimal

# ==============================================================================
# GLOBALS
Expand Down Expand Up @@ -384,7 +386,7 @@ def _check_single_value(value, name, negative_allow=False):
"""Checks given value for legitimacy.
**Args:**
value : (str, float, int)
value : (Decimal, str, float, int)
Any numeric value to be checked.
name : (str)
Expand All @@ -394,8 +396,8 @@ def _check_single_value(value, name, negative_allow=False):
If false, do not allow negative values.
**Returns:**
(float)
If value passes all tests, returns value as float.
(Decimal)
If value passes all tests, returns value as Decimal.
**Raises:**
TypeError:
Expand All @@ -405,20 +407,9 @@ def _check_single_value(value, name, negative_allow=False):
If negative is False, raised if value given is negative.
"""
# If given as a string, the string must be convertible to a float
if type(value) == str:
try:
value = float(value)
except ValueError:
raise TypeError(
'Error setting {name} with value: "{value}". '
'Value is not a number.'.format(
name=name,
value=value
)
)
value = to_decimal(value, name)
# If given as a single number, that number must be positive
if type(value) in [float, int] and not negative_allow:
if not negative_allow:
if value < 0:
if config.HALT_ON_ERROR:
raise ValueError(
Expand All @@ -429,6 +420,6 @@ def _check_single_value(value, name, negative_allow=False):
)
)
else:
value = 0
value = Decimal('0.0')

return float(value)
return value
100 changes: 68 additions & 32 deletions cdl_convert/correction.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

# Standard Imports

from decimal import Decimal
import os
import re
from xml.etree import ElementTree
Expand Down Expand Up @@ -330,12 +331,12 @@ def sop_node(self):

@property
def sat(self):
"""Returns float value for saturation"""
"""Returns value for saturation"""
return self.sat_node.sat

@sat.setter
def sat(self, sat_value):
"""Makes sure provided sat value is a positive float"""
"""Makes sure provided sat value is a positive"""
self.sat_node.sat = sat_value

# Private Methods =========================================================
Expand Down Expand Up @@ -432,12 +433,12 @@ class SatNode(ColorNodeBase):
The parent :class:`ColorCorrection` instance that created this
instance.
sat : (float)
sat : (Decimal)
The saturation value (to be applied with Rec 709 coefficients) is
stored here. Saturation is the last operation to be applied when
applying a CDL.
sat can be set with a float, int or numeric string.
sat can be set with a Decimal, float, int or numeric string.
xml : (str)
A nicely formatted XML string representing the node. Inherited from
Expand Down Expand Up @@ -472,7 +473,7 @@ def __init__(self, parent):
super(SatNode, self).__init__()

self._parent = parent
self._sat = 1.0
self._sat = Decimal('1.0')

# Properties ==============================================================

Expand All @@ -489,14 +490,14 @@ def sat(self):
@sat.setter
def sat(self, value):
"""Runs checks and converts saturation value before setting"""
# If given as a string, the string must be convertible to a float
if type(value) in [float, int, str]:
# If given as a string, the string must be convertible to a Decimal
if type(value) in [Decimal, float, int, str]:
try:
value = self._check_single_value(value, 'saturation')
except (TypeError, ValueError):
raise
else:
self._sat = value
self._sat = Decimal(value)
else:
raise TypeError(
'Saturation cannot be set directly with objects of type: '
Expand Down Expand Up @@ -530,7 +531,7 @@ class SopNode(ColorNodeBase):
Slope, offset and saturation are stored internally as lists, but always
returned as tuples to prevent index assignment from being successful. This
protects the user from inadvertently setting a single value in the list
to be a non-valid value, which might result in values not being floats or
to be a non-valid value, which might result in values not being Decimals or
even numbers at all.
**Class Attributes:**
Expand Down Expand Up @@ -561,32 +562,33 @@ class SopNode(ColorNodeBase):
The parent :class:`ColorCorrection` instance that created this
instance.
slope : (float, float, float)
slope : (Decimal, Decimal, Decimal)
An rgb tuple representing the slope, which changes the slope of the
input without shifting the black level established by the offset.
These values must be positive. If you set this attribute with a
single value, it will be copied over all 3 colors. Any single value
given can be a float, int or numeric string.
given can be a Decimal, float, int or numeric string.
default: (1.0, 1.0, 1.0)
default: (Decimal('1.0'), Decimal('1.0'), Decimal('1.0'))
offset : (float, float, float)
offset : (Decimal, Decimal, Decimal)
An rgb tuple representing the offset, which raises or lowers the
input brightness while holding the slope constant. If you set this
attribute with a single value, it will be copied over all 3 colors.
Any single value given can be a float, int or numeric string.
Any single value given can be a Decimal, float, int or numeric
string.
default: (0.0, 0.0, 0.0)
default: (Decimal('0.0'), Decimal('0.0'), Decimal('0.0'))
power : (float, float, float)
power : (Decimal, Decimal, Decimal)
An rgb tuple representing the power, which is the only function
that changes the response curve of the function. Note that this has
the opposite response to adjustments than a traditional gamma
operator. These values must be positive. If you set this attribute
with a single value, it will be copied over all 3 colors. Any
single value given can be a float, int or numeric string.
single value given can be a Decimal, float, int or numeric string.
default: (1.0, 1.0, 1.0)
default: (Decimal('1.0'), Decimal('1.0'), Decimal('1.0'))
xml : (str)
A nicely formatted XML string representing the node. Inherited from
Expand Down Expand Up @@ -622,9 +624,9 @@ def __init__(self, parent):

self._parent = parent

self._slope = [1.0, 1.0, 1.0]
self._offset = [0.0, 0.0, 0.0]
self._power = [1.0, 1.0, 1.0]
self._slope = [Decimal('1.0')] * 3
self._offset = [Decimal('0.0')] * 3
self._power = [Decimal('1.0')] * 3

# Properties ==============================================================

Expand Down Expand Up @@ -672,7 +674,7 @@ def _check_rgb_values(self, values, name, negative_allow=False):
"""Checks a list or tuple containing 3 values for legitimacy
**Args:**
value : [(str, float, int)]
value : [(Decimal, str, float, int)]
A list of three numeric values to be checked.
name : (str)
Expand All @@ -682,9 +684,9 @@ def _check_rgb_values(self, values, name, negative_allow=False):
If false, do not allow negative values.
**Returns:**
[float, float, float]
[Decimal, Decimal, Decimal]
If all values pass all tests, returns values as a list of
floats.
Decimals.
**Raises:**
TypeError:
Expand Down Expand Up @@ -729,8 +731,8 @@ def _check_setter_value(self, value, name, negative_allow=False):
Ties together _check_single_value and _check_rgb_values
**Args:**
value : [(str, float, int)] or (str, float, int)
**Args:**
value : [(Decimal, str, float, int)]
A list of three (or one) numeric values to be checked.
name : (str)
Expand All @@ -740,9 +742,9 @@ def _check_setter_value(self, value, name, negative_allow=False):
If false, do not allow negative values.
**Returns:**
[float, float, float]
[Decimal, Decimal, Decimal]
If all values pass all tests, returns values as a list of
floats.
Decimals.
**Raises:**
TypeError:
Expand All @@ -753,7 +755,7 @@ def _check_setter_value(self, value, name, negative_allow=False):
raised if value given is negative.
"""
if type(value) in [float, int, str]:
if type(value) in [Decimal, float, int, str]:
try:
value = self._check_single_value(value, name, negative_allow)
except (TypeError, ValueError):
Expand Down Expand Up @@ -803,8 +805,24 @@ def build_element(self):


def _de_exponent(notation):
"""Translates scientific notation into float strings"""
notation = str(notation)
"""Translates scientific notation into non-normalized strings
Unlike the methods to quantize a Decimal found on the Decimal FAQ, this
always works.
Args:
notation : (Decimal, str, int, float)
Any numeric value that may or may not be normalized.
Raises:
N/A
Returns:
(str)
Returns a quantized value without any scientific notation.
"""
notation = str(notation).lower()
if 'e' not in notation:
return notation

Expand Down Expand Up @@ -833,7 +851,25 @@ def _de_exponent(notation):


def _sanitize(name):
"""Removes any characters in string name that aren't alnum or in '_.'"""
"""Removes any characters in string name that aren't alnum or in '_.
Any spaces will be replaced with underscores. If a name starts with an
underscore or a period it's removed.
Only alphanumeric characters, or underscores and periods, are allowed.
Args:
name : (str)
The name to be sanitized.
Raises:
N/A
Returns:
(str)
Sanitized name.
"""
if not name:
# If not name, it's probably an empty string, but let's throw back
# exactly what we got.
Expand Down
2 changes: 1 addition & 1 deletion cdl_convert/decision.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ class ColorDecision(AscDescBase, AscColorSpaceBase, AscXMLBase): # pylint: disa
**Attributes:**
cc : (:class:`ColorCorrection` | :class:`ColorCorrectionRef`)
cc : (:class:`ColorCorrection` , :class:`ColorCorrectionRef`)
Returns the contained ColorCorrection, even if it's a reference.
desc : [str]
Expand Down

0 comments on commit 231ed4b

Please sign in to comment.