Skip to content

Unit

Unit class for conversion between ODF units and Python types.

Currently, this module primarily supports distance conversions to pixels.

Supported units: - mm: millimeter - cm: centimeter - m: meter - km: kilometer - pt: point - pc: pica - in: inch - ft: foot - mi: mile

Classes:

Name Description
Unit

Represents a measurement with a value and a unit for length.

Attributes:

Name Type Description
INCH_CONVERSION

INCH_CONVERSION module-attribute

INCH_CONVERSION = {
    "in": Fraction("1/1"),
    "inch": Fraction("1/1"),
    "cm": Fraction("100/254"),
    "mm": Fraction("10/254"),
    "m": Fraction("10000/254"),
    "km": Fraction("10000000/254"),
    "pt": Fraction("1/72"),
    "pc": Fraction("1/6"),
    "ft": Fraction("12/1"),
    "mi": Fraction("63360/1"),
}

Unit

Represents a measurement with a value and a unit for length.

Provides utilities for parsing, comparing, and converting length units, especially for conversion to pixels.

Attributes:

Name Type Description
value Fraction

The numerical value of the measurement.

text str

The str value of the measurement.

unit str

The unit of the measurement (e.g., ‘cm’, ‘in’).

Methods:

Name Description
__eq__
__init__

Initializes a Unit instance.

__lt__
__repr__
__str__
convert

Converts the current unit to another unit.

Source code in odfdo/unit.py
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
@total_ordering
class Unit:
    """Represents a measurement with a value and a unit for length.

    Provides utilities for parsing, comparing, and converting length units,
    especially for conversion to pixels.

    Attributes:
        value (Fraction): The numerical value of the measurement.
        text (str): The str value of the measurement.
        unit (str): The unit of the measurement (e.g., 'cm', 'in').
    """

    def __init__(self, value: str | float | int | Decimal, unit: str = "cm") -> None:
        """Initializes a Unit instance.

        The constructor can parse a string containing both a value and a unit
        (e.g., "10.5cm") or accept a numerical value and a unit separately.

        Args:
            value: The value of the measurement.
                If a string, it can include the unit.
            unit: The unit of measurement (e.g., 'cm', 'in', 'pt').
                Defaults to 'cm'. This is ignored if the unit is present in
                the `value` string.
        """
        if isinstance(value, str):
            digits = []
            nondigits = []
            for char in value:
                if char.isdigit() or char == ".":
                    digits.append(char)
                else:
                    nondigits.append(char)
            value = "".join(digits)
            if nondigits:
                unit = "".join(nondigits)
        elif isinstance(value, float):
            value = str(value)
        self.txt = str(value)
        self.value = Fraction(value)
        self.unit = unit

    def __str__(self) -> str:
        return self.txt + self.unit

    def __repr__(self) -> str:
        return f"{object.__repr__(self)} {self}"

    def _check_other(self, other: Unit) -> None:
        """Checks if the 'other' object is a compatible Unit for comparison.

        Args:
            other: The other Unit instance to compare against.

        Raises:
            TypeError: If 'other' is not a Unit instance.
            NotImplementedError: If the units are different.
        """
        if not isinstance(other, Unit):
            raise TypeError(f"Can only compare Unit: {other!r}")
        if self.unit != other.unit:
            raise NotImplementedError(f"Conversion not implemented yet {other!r}")

    def __lt__(self, other: Unit) -> bool:
        self._check_other(other)
        return self.value < other.value

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, Unit):
            return False
        self._check_other(other)
        return self.value == other.value

    def convert(self, unit: str, dpi: int | Decimal | float = 72) -> Unit:
        """Converts the current unit to another unit.

        Currently, only conversion to pixels ('px') is supported from various
        length units.

        Args:
            unit: The target unit to convert to. Must be 'px'.
            dpi: The dots per inch resolution to use
                for pixel conversion. Defaults to 72.

        Returns:
            Unit: A new Unit instance representing the converted value.

        Raises:
            NotImplementedError: If conversion to the target `unit` or from
                the instance's current unit is not supported.
        """
        try:
            conversion = INCH_CONVERSION[self.unit]
        except KeyError as e:
            raise NotImplementedError(f"unit {str(self.unit)!r}") from e
        if unit == "px":
            return Unit(int(self.value * conversion * int(dpi)), "px")
        raise NotImplementedError(f"unit {str(unit)!r}")

txt instance-attribute

txt = str(value)

unit instance-attribute

unit = unit

value instance-attribute

value = Fraction(value)

__eq__

__eq__(other: object) -> bool
Source code in odfdo/unit.py
125
126
127
128
129
def __eq__(self, other: object) -> bool:
    if not isinstance(other, Unit):
        return False
    self._check_other(other)
    return self.value == other.value

__init__

__init__(
    value: str | float | int | Decimal, unit: str = "cm"
) -> None

Initializes a Unit instance.

The constructor can parse a string containing both a value and a unit (e.g., “10.5cm”) or accept a numerical value and a unit separately.

Parameters:

Name Type Description Default
value str | float | int | Decimal

The value of the measurement. If a string, it can include the unit.

required
unit str

The unit of measurement (e.g., ‘cm’, ‘in’, ‘pt’). Defaults to ‘cm’. This is ignored if the unit is present in the value string.

'cm'
Source code in odfdo/unit.py
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
def __init__(self, value: str | float | int | Decimal, unit: str = "cm") -> None:
    """Initializes a Unit instance.

    The constructor can parse a string containing both a value and a unit
    (e.g., "10.5cm") or accept a numerical value and a unit separately.

    Args:
        value: The value of the measurement.
            If a string, it can include the unit.
        unit: The unit of measurement (e.g., 'cm', 'in', 'pt').
            Defaults to 'cm'. This is ignored if the unit is present in
            the `value` string.
    """
    if isinstance(value, str):
        digits = []
        nondigits = []
        for char in value:
            if char.isdigit() or char == ".":
                digits.append(char)
            else:
                nondigits.append(char)
        value = "".join(digits)
        if nondigits:
            unit = "".join(nondigits)
    elif isinstance(value, float):
        value = str(value)
    self.txt = str(value)
    self.value = Fraction(value)
    self.unit = unit

__lt__

__lt__(other: Unit) -> bool
Source code in odfdo/unit.py
121
122
123
def __lt__(self, other: Unit) -> bool:
    self._check_other(other)
    return self.value < other.value

__repr__

__repr__() -> str
Source code in odfdo/unit.py
103
104
def __repr__(self) -> str:
    return f"{object.__repr__(self)} {self}"

__str__

__str__() -> str
Source code in odfdo/unit.py
100
101
def __str__(self) -> str:
    return self.txt + self.unit

_check_other

_check_other(other: Unit) -> None

Checks if the ‘other’ object is a compatible Unit for comparison.

Parameters:

Name Type Description Default
other Unit

The other Unit instance to compare against.

required

Raises:

Type Description
TypeError

If ‘other’ is not a Unit instance.

NotImplementedError

If the units are different.

Source code in odfdo/unit.py
106
107
108
109
110
111
112
113
114
115
116
117
118
119
def _check_other(self, other: Unit) -> None:
    """Checks if the 'other' object is a compatible Unit for comparison.

    Args:
        other: The other Unit instance to compare against.

    Raises:
        TypeError: If 'other' is not a Unit instance.
        NotImplementedError: If the units are different.
    """
    if not isinstance(other, Unit):
        raise TypeError(f"Can only compare Unit: {other!r}")
    if self.unit != other.unit:
        raise NotImplementedError(f"Conversion not implemented yet {other!r}")

convert

convert(unit: str, dpi: int | Decimal | float = 72) -> Unit

Converts the current unit to another unit.

Currently, only conversion to pixels (‘px’) is supported from various length units.

Parameters:

Name Type Description Default
unit str

The target unit to convert to. Must be ‘px’.

required
dpi int | Decimal | float

The dots per inch resolution to use for pixel conversion. Defaults to 72.

72

Returns:

Name Type Description
Unit Unit

A new Unit instance representing the converted value.

Raises:

Type Description
NotImplementedError

If conversion to the target unit or from the instance’s current unit is not supported.

Source code in odfdo/unit.py
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
def convert(self, unit: str, dpi: int | Decimal | float = 72) -> Unit:
    """Converts the current unit to another unit.

    Currently, only conversion to pixels ('px') is supported from various
    length units.

    Args:
        unit: The target unit to convert to. Must be 'px'.
        dpi: The dots per inch resolution to use
            for pixel conversion. Defaults to 72.

    Returns:
        Unit: A new Unit instance representing the converted value.

    Raises:
        NotImplementedError: If conversion to the target `unit` or from
            the instance's current unit is not supported.
    """
    try:
        conversion = INCH_CONVERSION[self.unit]
    except KeyError as e:
        raise NotImplementedError(f"unit {str(self.unit)!r}") from e
    if unit == "px":
        return Unit(int(self.value * conversion * int(dpi)), "px")
    raise NotImplementedError(f"unit {str(unit)!r}")