Enum Class

Enum classes represent an enumeration

Overview

It is not possible to import a uno.Enum in the same way as a python enum. from com.sun.star.sheet import FillDateMode would result in an import error.

However uno.Enum attributes can be imported.

>>> from com.sun.star.sheet.FillDateMode import FILL_DATE_DAY
>>> print(FILL_DATE_DAY)
<Enum instance com.sun.star.sheet.FillDateMode ('FILL_DATE_DAY')>

Also uno.Enum attributes instance of the uno.Enum class behave similar to python Enum values.

Example: In this example the value is a string containing "FILL_DATE_DAY" .

>>> from com.sun.star.sheet.FillDateMode import FILL_DATE_DAY
>>> print(FILL_DATE_DAY.value)
FILL_DATE_DAY

OOOUNO Dynamic Enums

Overview

ooouno has python enums for each uno.Enum. At runtime the values of ooouno enum are actual uno.Enum values. This gives the best of both worlds when working with enums in the LibreOffice API.

import uno
from ooo.dyn.sheet.solver_constraint_operator import SolverConstraintOperator
from com.sun.star.sheet.SolverConstraintOperator import (
    BINARY, EQUAL, GREATER_EQUAL, INTEGER, LESS_EQUAL
)

def main() -> None:
    print(com.sun.star.sheet.SolverConstraintOperator.BINARY == BINARY) # True

Typing Support

In many cases is it much more desirable to import uno.Enum as if it is a python enum. This especially valuable when a method takes a uno:Enum type.

Dynamic Enum

In the following example type checkers have something to work with. If the underlying value are changed in a different version of LibreOffice it will not break the function as ooouno loads the enum values dynamically.

Example: Normal python behavior using ooouno.

import uno
from ooo.dyn.sheet.solver_constraint_operator import SolverConstraintOperator

def solve_operation(value: int, x: SolverConstraintOperator) -> int:
    # do some work
    if x == SolverConstraintOperator.BINARY:
        ...
    elif x == SolverConstraintOperator.EQUAL:
        ...
    elif x == SolverConstraintOperator.GREATER_EQUAL:
        ...
    elif x == SolverConstraintOperator.INTEGER:
        ...
    elif x == SolverConstraintOperator.LESS_EQUAL:
        ...
    else:
        # future proofing
        raise ValueError(f"x value is unknown: {x.value}")
    ...

def main() -> None:
    y = solve_operation(13, SolverConstraintOperator.BINARY)
    y = solve_operation(101, SolverConstraintOperator.EQUAL)

Standard LibreOffice API Enum

In the following example, each enum value as to be imported separately. The solve_operation() has limited type information as uno:Enum only exposes typeName and value.

The method has to ensure the proper type has been passed in. Conditions have to be checked against the x.value to find a match.

Example: Have to import each enum value separately and use values for checking.

import uno
from typing import cast
from com.sun.star.sheet.SolverConstraintOperator import (
    BINARY, EQUAL, GREATER_EQUAL, INTEGER, LESS_EQUAL
)

def solve_operation(value: int, x: uno.Enum) -> int:
    # risky if SolverConstraintOperator values change in the future
    # then this function will break.
    if x.typeName != "com.sun.star.sheet.SolverConstraintOperator":
        raise TypeError("x is not a SolverConstraintOperator")

    if x.value == "BINARY":
        ...
    elif x.value == "EQUAL":
        ...
    elif x.value == "GREATER_EQUAL":
        ...
    elif x.value == "INTEGER":
        ...
    elif x.value == "LESS_EQUAL":
        ...
    else:
        # future proofing
        raise ValueError(f"x value is unknown: {x.value}")

def main() -> None:
    # cast so type checkers like mypy and pyright will pass
    y = solve_operation(13, cast(uno.Enum, BINARY))
    y = solve_operation(101, cast(uno.Enum, EQUAL))

Enum Protocol

ooouno uses types-unopy for type support.

types-unopy handles typing for uno.Enum groups by using a protocol for each enum.

A protocol for com.sun.star.sheet.SolverConstraintOperator would look something like this.

class SolverConstraintOperatorProto(Protocol):
    @property
    def typeName(self) -> Literal["com.sun.star.sheet.SolverConstraintOperator"]:
        ...
    value: Any
    BINARY: SolverConstraintOperatorProto
    EQUAL: SolverConstraintOperatorProto
    GREATER_EQUAL: SolverConstraintOperatorProto
    INTEGER: SolverConstraintOperatorProto
    LESS_EQUAL: SolverConstraintOperatorProto

Each value in the com.sun.star.sheet.SolverConstraintOperator namespace when imported is now considered to be a protocol.

Type Guarding Protocol

The Enum Protocols in ooouno are a special case and do not exist at runtime. For this reason it is necessary to guard the import. Since typing.TYPE_CHECKING is always False at runtime we can use it.

There are two way to handle importing a protocol class. The first way is by importing annotations.

from __future__ import annotations
import uno
from com.sun.star.sheet.SolverConstraintOperator import SolverConstraintOperatorProto
# ...

def solve_operation(value: int, x: SolverConstraintOperatorProto) -> int:
    ...

Note when using annotations the cast to protocol must be wrapped in a string.

from typing import cast
from com.sun.star.sheet.SolverConstraintOperator import SolverConstraintOperatorProto
from ooo.dyn.sheet.solver_constraint_operator import SolverConstraintOperator
# ...

# SolverConstraintOperatorProto must be wrapped in a string
# if it has not been assigned to object at runtime.
solve_operation(
    11, cast("SolverConstraintOperatorProto", SolverConstraintOperator.BINARY)
)

The other way is to assign the protocol class as an object at runtime.

from typing import TYPE_CHECKING
import uno
from com.sun.star.sheet.SolverConstraintOperator import SolverConstraintOperatorProto

if TYPE_CHECKING:
    # While writing code we have the advantages of protocol
    from com.sun.star.sheet.SolverConstraintOperator import SolverConstraintOperatorProto
else:
    # code is executing. Now protocol is an object and basically ignored
    SolverConstraintOperatorProto = object

Examples

Taking advantage of type support.

ooouno assigns standard Enum constants type as a protocol. Standard Enum constants are now imported and the type is reported as a Protocol.

import uno
from typing import TYPE_CHECKING
from ooo.dyn.sheet.solver_constraint_operator import SolverConstraintOperator
from com.sun.star.sheet.SolverConstraintOperator import (
    BINARY, EQUAL, GREATER_EQUAL, INTEGER, LESS_EQUAL
)

if TYPE_CHECKING:
    from com.sun.star.sheet.SolverConstraintOperator import SolverConstraintOperatorProto
else:
    SolverConstraintOperatorProto = object

def solve_operation(value: int, x: SolverConstraintOperatorProto) -> int:
    # at runtime x and SolverConstraintOperator enum values are identical
    if x == SolverConstraintOperator.BINARY:
        ...
    elif x == SolverConstraintOperator.EQUAL:
        ...
    elif x == SolverConstraintOperator.GREATER_EQUAL:
        ...
    elif x == SolverConstraintOperator.INTEGER:
        ...
    elif x == SolverConstraintOperator.LESS_EQUAL:
        ...
    else:
        # future proofing
        raise ValueError(f"x value is unknown: {x.value}")

def main() -> None:
    # cast is not needed because types-unopy imports the constants
    # as SolverConstraintOperatorProto automatically
    y = solve_operation(13, BINARY)
    y = solve_operation(101, EQUAL)

Passing incorrect type will result in a typing error for type checkers such as mypy and pyright.

from com.sun.star.sheet.FillDateMode import FILL_DATE_DAY

# ...
# Fails type checking because FILL_DATE_DAY is not SolverConstraintOperatorProto
solve_operation(3, FILL_DATE_DAY)

Screenshot of type error.

Enum protocol error

Enum protocol error

Using Dynamic Enums with a method that expects a Protocol will need a casting. This is perfectly fine as Dynamic Enum values are identical to their uno.Enum constant counterparts.

import uno
from typing import TYPE_CHECKING
from ooo.dyn.sheet.solver_constraint_operator import SolverConstraintOperator
from com.sun.star.sheet.SolverConstraintOperator import (
    BINARY, EQUAL, GREATER_EQUAL, INTEGER, LESS_EQUAL
)

if TYPE_CHECKING:
    from com.sun.star.sheet.SolverConstraintOperator import SolverConstraintOperatorProto
else:
    SolverConstraintOperatorProto = object

def solve_operation(value: int, x: SolverConstraintOperatorProto) -> int:
    # at runtime x and SolverConstraintOperator enum values are identical
    if x == SolverConstraintOperator.BINARY:
        ...
    elif x == SolverConstraintOperator.EQUAL:
        ...
    elif x == SolverConstraintOperator.GREATER_EQUAL:
        ...
    elif x == SolverConstraintOperator.INTEGER:
        ...
    elif x == SolverConstraintOperator.LESS_EQUAL:
        ...
    else:
        # future proofing
        raise ValueError(f"x value is unknown: {x.value}")

def main() -> None:
    # cast is not needed becuase types-unopy imports the constants
    # as SolverConstraintOperatorProto automatically
    y = solve_operation(
        3,
        cast(SolverConstraintOperatorProto, SolverConstraintOperator.GREATER_EQUAL)
    )
    y = solve_operation(
    101,
    cast(SolverConstraintOperatorProto, SolverConstraintOperator.EQUAL)
    )

Static

Enum classes in ooo.lo and ooo.csslo namespaces are static classes.

As of version 2.0.0 the ooo.csslo namespace is deprecated. Use the ooo.lo namespace instead.

Example static:
from ooo.csslo.awt import FontSlant
assert FontSlant.ITALIC.__module__ == 'ooo.lo.awt.font_slant'
assert FontSlant.NONE.__module__ == 'ooo.lo.awt.font_slant'
e = FontSlant('OBLIQUE')
assert e == FontSlant.OBLIQUE
assert e.value == FontSlant.OBLIQUE.value
assert e.__module__ == 'ooo.lo.awt.font_slant'
e = FontSlant(FontSlant.OBLIQUE)
assert e == FontSlant.OBLIQUE
assert e.__module__ == 'ooo.lo.awt.font_slant'

Enum classes in ooo.lo and ooo.csslo namespaces are the same classes.

Example:
from ooo.lo.awt.font_slant import FontSlant as LoFontSlant
from ooo.csslo.awt import FontSlant as CssFontSlant
from ooo.dyn.awt.font_slant import FontSlant as DynFontSlant
same = LoFontSlant is CssFontSlant
assert same == True
same = LoFontSlant is DynFontSlant
assert same == False

Dynamic

Enum classes in ooo.dyn and ooo.cssdyn namespaces are dynamic classes and are changed during runtime. All enumeration values are UNO equivalent.

As of version 2.0.0 the ooo.cssdyn namespace is deprecated. Use the ooo.dyn namespace instead.

Example dynamic:
from ooo.cssdyn.awt import FontSlant

e = FontSlant('OBLIQUE')
assert e == FontSlant.OBLIQUE
assert e.value == FontSlant.OBLIQUE.value

e = FontSlant(FontSlant.OBLIQUE)
assert e == FontSlant.OBLIQUE

At runtime dynamic enum are the same as UNO enum.

from ooo.cssdyn.awt import FontSlant
from com.sun.star.awt.FontSlant import ITALIC
same = FontSlant.ITALIC is ITALIC
assert same

Enum classes in ooo.dyn and ooo.cssdyn namespaces are the same classes.

Example:
from ooo.dyn.awt.font_slant import FontSlant as DynFontSlant
from ooo.cssdyn.awt import FontSlant as CssFontSlant
from ooo.lo.awt.font_slant import FontSlant as LoFontSlant
same = DynFontSlant is CssFontSlant
assert same == True
same = DynFontSlant is LoFontSlant
assert same == False