converters

Utility functions for converting values between various formats.

These functions focus on converting between different string and numeric formats related to measurements, Unicode codepoints, and letter casing.

To import the module:

>>> from smufolib import converters
convertMeasurement(measurement: int | float | str, targetUnit: str, unitsPerEm: int | float, rounded: bool = False) int | float[source]

Convert between units of measurement based on UPM size.

Parameters:
  • measurement – The value to convert.

  • targetUnit – Unit to convert to.

  • unitsPerEm – The UPM value to base conversion on.

  • rounded – Whether to round result to nearest integer.

Raises:
  • TypeError – If measurement is not an accepted type.

  • ValueError – If targetUnit is neither "spaces" nor "units".

Example:

>>> converters.convertMeasurement(0.795, "units", 1000, rounded=False)
198.75
>>> converters.convertMeasurement(0.795, "units", 1000, rounded=True)
199
>>> converters.convertMeasurement("198.75", "spaces", 1000, rounded=True)
0.795
toDecimal(string: str) int[source]

Convert formatted unicode or uni name to decimal codepoint.

Function accepts any hexadecimal string within the Unicode range (U+0000 – U+10FFFF) prefixed by "u", "U+" or "uni".

Parameters:

string – The value to convert.

Raises:
  • TypeError – If string is not the accepted type.

  • ValueError – If string is not a valid formatted unicode codepoint or outside the unicode range (U+0000 – U+10FFFF).

Example:

>>> converters.toDecimal("uniE000")
57344
>>> converters.toDecimal("u1D100")
119040
>>> converters.toDecimal("U+0A00")
2560
toIntIfWhole(number: int | float) int | float[source]

Convert float without a fractional part to integer.

If number is already an int or the float has a fractional part, it is left unchanged.

Parameters:

number – The value to convert.

Example:

>>> converters.toIntIfWhole(34.0)
34
>>> converters.toIntIfWhole(34.1)
34.1
toKebab(camelCaseString: str) str[source]

Convert camelCase to kebab-case.

Parameters:

camelCaseString – The string to convert.

Example:

>>> converters.toKebab("camelCase")
'camel-case'
toNumber(numericString: str) int | float[source]

Convert numeric string to number.

Parameters:

numericString – The value to convert.

Raises:

ValueError – If numericString is not a valid int or float.

Example:

>>> converters.toNumber("57344")
57344
>>> converters.toNumber("57.344")
57.344
>>> converters.toNumber("E000")
57344
toUniHex(value: int | str) str[source]

Convert decimal codepoint or uni-name to formatted Unicode hex.

Parameters:

value – The decimal value to convert.

Raises:
  • TypeError – If value is not the accepted type.

  • ValueError – If value is outside the Unicode range (U+0000 – U+10FFFF).

Example:

>>> converters.toUniHex(2560)
'U+0A00'
>>> converters.toUniHex("uni0A00")
'U+0A00'
toUniName(value: int | str, short: bool = False) str[source]

Convert decimal codepoint or Unicode notation string to uni-name.

Function accepts any integer or prefixed hexadecimal string (e.g., "U+E000", "uE000", "uniE000") within the Unicode range (U+0000 – U+10FFFF).

Parameters:
  • value – The value to convert.

  • short – Whether to return name with single "u" prefix.

Raises:
  • TypeError – If value is not an accepted type.

  • ValueError – If value is outside the Unicode range (U+0000 – U+10FFFF) or not a valid formatted string.

Example:

>>> converters.toUniName("U+E000")
'uniE000'
>>> converters.toUniName('U+E000', short=True)
'uE000'
>>> converters.toUniName(57344)
'uniE000'

error

Utility functions for error message generation and type validation.

This module provides functions to generate and validate error messages, check types, and suggest corrections for invalid values. It includes a dictionary of error message templates to ensure streamlined and consistent error reporting.

To import the module:

>>> from smufolib import error
ERROR_TEMPLATES: dict[str, str]

Dictionary of error message templates.

Key

Template

"alphanumericValue"

The value for objectName!r must be alphanumeric

"alphanumericValueItems"

Value items for objectName!r must be alphanumeric

"argumentConflict"

The option ‘key’ is already added as positional argument or flag

"attributeError"

objectName!r has no attribute attribute!r

"contextualAttributeError"

The attribute attribute!r is not available when context

"contextualSetAttributeError"

Cannot set attribute attribute!r when context

"contextualTypeError"

Expected objectName!r to be of type validTypes when context, but got valueType

"contextualItemsTypeError"

Items in objectName!r must be validTypes when context, not valueType

"deprecated"

objectName!r is deprecated and will be removed in the next version of SMufoLib (after version)

"deprecatedReplacement"

Use replacement!r instead

"duplicateFlags"

Arguments argument1!r and argument2!r have duplicate short flag: flag

"duplicateAttributeValue"

The value value!r for attribute!r is already assigned to another objectName instance: conflictingInstance!r

"duplicateItems"

Items in objectName!r cannot be duplicates

"emptyValue"

The value for objectName!r cannot be empty

"emptyValueItems"

Value items for objectName!r cannot be empty

"fileNotFound"

The file or directory for objectName!r does not exist

"invalidFormat"

The value for objectName!r is not correctly formatted

"invalidInitialCharacter"

The value for objectName!r must start with a lowercase letter or number

"invalidInitialItemsCharacter"

Value items for objectName!r must start with a lowercase letter or number

"itemsTypeError"

Items in objectName!r must be validTypes, not valueType

"itemsValueError"

Invalid value for item in objectName!r: value!r

"missingDependency"

Cannot set objectName!r because dependency!r is None

"missingExtension"

The value for objectName!r must have a extension!r extension

"missingGlyph"

No SMuFL glyph named name!r

"missingValue"

Required values for objectName!r are missing

"nonIncreasingRange"

The values in objectName!r must form an increasing range

"notImplementedError"

The objectName!r subclass does not implement this method

"numericValue"

The value for objectName!r must be numeric

"overlappingRange"

Range ‘name’ (start-end) overlaps with an existing range

"permissionError"

Permission denied: context

"recommendScript"

Consider running the script scriptName!r before the current process

"serializationError"

Error serializing JSON data or writing to the file

"singleItem"

objectName!r must contain a value pair

"suggestion"

Did you mean suggestion!r?

"typeError"

Expected objectName!r to be of type validTypes, but got valueType

"unicodeOutOfRange"

The value for objectName!r is outside the Unicode range start-end

"urlError"

Could not connect to URL: url!r

"valueError"

Invalid value for objectName!r: value!r

"valueTooHigh"

The value for objectName!r must be value!r or lower

"valueTooLow"

The value for objectName!r must be value!r or higher

exception URLWarning[source]

URL connection failure warning.

generateErrorMessage(*templateNames: Literal['alphanumericValue', 'alphanumericValueItems', 'argumentConflict', 'attributeError', 'contextualAttributeError', 'contextualItemsTypeError', 'contextualSetAttributeError', 'contextualTypeError', 'deprecated', 'deprecatedReplacement', 'duplicateAttributeValue', 'duplicateFlags', 'duplicateItems', 'emptyValue', 'emptyValueItems', 'fileNotFound', 'invalidFormat', 'invalidInitialCharacter', 'invalidInitialItemsCharacter', 'itemsTypeError', 'itemsValueError', 'missingDependency', 'missingExtension', 'missingGlyph', 'missingValue', 'nonIncreasingRange', 'notImplementedError', 'numericValue', 'overlappingRange', 'permissionError', 'recommendScript', 'serializationError', 'singleItem', 'suggestion', 'typeError', 'unicodeOutOfRange', 'urlError', 'valueError', 'valueTooHigh', 'valueTooLow'], string: str | None = None, **kwargs) str[source]

Generate an error message from a template and keyword arguments.

The templateNames and string will be concatenated in order.

Parameters:
  • *templateNames – The error message template string, which should contain placeholders for keyword arguments.

  • string – An additional message string to include. Defaults to None

  • **kwargs – Arbitrary keyword arguments corresponding to the placeholders in the template string.

Raises:

KeyError – If a placeholder in the template does not have a corresponding keyword argument.

Examples:

>>> error.generateErrorMessage("alphanumericValue", objectName="unicode")
"The value for 'unicode' must be alphanumeric"
>>> error.generateErrorMessage(
...     "typeError", objectName="index", validTypes="int", valueType="str"
...     )
"Expected 'index' to be of type int, but got str"
>>> error.generateErrorMessage(
...     "urlError", string="Please try again", url="some/url.com"
...     )
"Could not connect to URL: 'some/url.com'. Please try again"
generateTypeError(value: Any, validTypes: type | tuple[type, ...], objectName: str, context: str | None = None, items: bool = False) str[source]

Generate a TypeError message.

This function generates an error message based on the number of valid types. By default, the message is generated from ERROR_TEMPLATES:"typeError".

If context in not None (or empty) and items is False, ERROR_TEMPLATES:"contextualTypeError" is used. If items is True and context is None, ERROR_TEMPLATES:"itemsTypeError" is used. If both context is not None and items is True, ERROR_TEMPLATES:"contextualItemsTypeError" is used.

Parameters:
  • value – The value to be validated.

  • validTypes – A tuple or list of valid types.

  • objectName – The name of the object being validated.

  • context – Additional substring for contextual type errors. Defaults to None

  • items – Whether to use items-specific template. Defaults to False.

Raises:
  • TypeError – If value does not match any of the valid types.

  • ValueError – If items is True and value is not an iterable.

Examples:

>>> error.generateTypeError(123, (str,), "path")
"Expected 'path' to be of type str, but got int"
>>> from pathlib import Path
>>> error.generateTypeError(123, (str, Path), "path")
"Expected 'path' to be of type str or Path, but got int"
>>> from smufolib import Request
>>> error.generateTypeError(123, (str, Path, Request), "path")
"Expected 'path' to be of type str, Path or Request, but got int"
suggestValue(value: str, possibilities: list[str] | tuple[str, ...], objectName: str, cutoff: float = 0.6, items=False) str[source]

Validate value and suggests a valid close match.

If items is True, an alternate error message template is used to validate the values of items within an iterable value rather than the value itself.

Parameters:
  • value – The value to be validated.

  • possibilities – A list of valid possibilities for the value.

  • objectName – The name of the object being validated.

  • cutoff – A float value representing the cutoff threshold for similarity matches. Defaults to 0.6.

  • items – Whether to use items-specific template. Defaults to False.

Raises:

ValueError – If the provided value is not found in possibilities or if items is True and value is not an iterable.

Example:

>>> try:
...     error.suggestValue(
...         "spiltStemUpSE", ["splitStemUpSE", "splitStemUpSW"],
...         "anchorName", cutoff=0.5)
... except ValueError as e:
...     print(e)
Invalid value for 'anchorName': 'spiltStemUpSE'. Did you mean 'splitStemUpSE'?
validateType(value: Any, validTypes: type | tuple[type, ...] | UnionType, objectName: str, items=False) None[source]

Validate if a value matches any of the valid types.

Parameters:
  • value – The value to be validated.

  • validTypes – A single valid type or tuple of valid types.

  • objectName – The name of the object being validated.

  • items – Whether to validate value items rather than value itself. Defaults to False.

Raises:
  • TypeError – If value does not match any of the valid types.

  • ValueError – If items is True and any value item does not match any of the valid types.

Examples:

>>> try:
...     error.validateType(123, str, "glyphName")
... except TypeError as e:
...     print(e)
Expected 'glyphName' to be of type str, but got int
>>> myList = ["uniE000", 1]
>>> for item in myList:
...     try:
...         error.validateType(item, str, "myList", items=True)
...     except ValueError as e:
...         print(e)
Items in 'myList' must be str, not int

normalizers

Utilities for normalizing various data types in SMufoLib.

This module extends fontParts.base.normalizers and provides functions to normalize objects and data related to SMuFL fonts and metadata requests. It includes normalization for:

These functions ensure that the data adheres to expected formats and values, handling type validation and normalization as needed.

In addition to the documented functions below, it provides direct access to the following external normalizers for convenience:

To import the module:

>>> from smufolib import normalizers
normalizeClasses(value: list[str] | tuple[str, ...] | None) tuple[str, ...][source]

Normalize smufl classes.

Parameters:

value – The value to normalize.

Raises:
normalizeDescription(value: str | None, attributeName: str) str | None[source]

Normalize human-readable smufl descriptions.

Parameters:
  • value – The value to normalize.

  • attributeName – The name of the attribute to normalize.

Raises:
normalizeDesignSize(value: int | None) int | None[source]

Normalize design size.

Parameters:

value – The value to normalize.

Raises:
normalizeEngravingDefaults(value: EngravingDefaults) EngravingDefaults[source]

Normalize EngravingDefaults object.

Parameters:

value – The value to normalize.

Raises:

TypeError – If value is not the accepted type.

normalizeEngravingDefaultsAttr(name: str, value: int | float | list[str] | tuple[str, ...] | None) int | float | tuple[str, ...] | None[source]

Normalize engraving defaults attribute.

Parameters:
  • name – The attribute name to normalize.

  • value – The attribute value to normalize.

Raises:
normalizeFont(value: Font) Font[source]

Normalize Font object.

Parameters:

value – The value to normalize.

Raises:

TypeError – If value is not the accepted type.

normalizeRequest(value: Request) Request[source]

Normalize Request object.

Parameters:

value – The value to normalize.

Raises:

TypeError – If value is not the accepted type.

normalizeRequestPath(value: Path | str | None, parameter: str) str | None[source]

Normalize Request path.

Relative paths are resolved automatically.

Parameters:
  • value – The value to normalize.

  • parameter – The name of the parameter being validated.

Raises:

TypeError – If value is not the accepted type.

normalizeSizeRange(value: list[int] | tuple[int, int] | None) tuple[int, int] | None[source]

Normalize design size.

Parameters:

value – The value to normalize.

Raises:
  • TypeError – If value or it’s contents is not an accepted type.

  • ValueError

    • If value does not contain a value pair.

    • If value is not an increasing range.

    • If value items do not normalize with normalizeDesignSize(), except not be None.

normalizeSmufl(value: Smufl) Smufl[source]

Normalize Smufl object.

Parameters:

value – The value to normalize.

Raises:

TypeError – If value is not the accepted type.

normalizeSmuflName(value: str | None, attributeName: str, items: bool = False) str | None[source]

Normalize cannonical SMuFL names of glyphs, classes and ranges.

Parameters:
  • value – The value to normalize.

  • attributeName – The name of the attribute to normalize.

  • items – Whether to normalize value items rather than value itself. Defaults to False.

Raises:
  • TypeError – If value is not an accepted type.

  • ValueError

    • If value is an empty string.

    • If value is value contains non-alphanumeric characters.

    • If value does not start with a lowercase letter or number.

rulers

Measurement utilities for calculating glyph geometry.

This module provides functions to retrieve, measure and inspect various parts of glyphs. It also defines:

To import the module:

>>> from smufolib import rulers
ENGRAVING_DEFAULTS_MAPPING: dict[str, dict[str, str]]

Default mapping of rulers and glyphs to EngravingDefaults attributes.

Attribute

Glyph

Ruler Function

arrowShaftThickness

U+EB60

xStrokeWidthAtOrigin()

barlineSeparation

U+E031

xDistanceBetweenContours()

beamSpacing

U+E1F9

yDistanceBetweenContours()

beamThickness

U+E1F7

glyphBoundsHeight()

bracketThickness

U+E003

xStrokeWidthAtOrigin()

dashedBarlineDashLength

U+E036

yStrokeWidthAtMinimum()

dashedBarlineGapLength

U+E036

yDistanceBetweenContours()

dashedBarlineThickness

U+E036

glyphBoundsWidth()

hairpinThickness

U+E53E

wedgeArmStrokeWidth()

hBarThickness

U+E4F0

yStrokeWidthAtMinimum()

legerLineExtension

U+E022

glyphBoundsXMinAbs()

legerLineThickness

U+E022

glyphBoundsHeight()

lyricLineThickness

U+E010

glyphBoundsHeight()

octaveLineThickness

U+E010

glyphBoundsHeight()

pedalLineThickness

U+E010

glyphBoundsHeight()

repeatBarlineDotSeparation

U+E040

xDistanceStemToDot()

repeatEndingLineThickness

U+E030

xStrokeWidthAtOrigin()

slurEndpointThickness

U+E1FD

xStrokeWidthAtOrigin()

slurMidpointThickness

U+E1FD

yStrokeWidthAtMinimum()

staffLineThickness

U+E010

glyphBoundsHeight()

stemThickness

U+E210

glyphBoundsWidth()

subBracketThickness

U+E030

xStrokeWidthAtOrigin()

textEnclosureThickness

U+E010

glyphBoundsHeight()

textFontFamily

thickBarlineThickness

U+E034

glyphBoundsWidth()

thinBarlineThickness

U+E030

glyphBoundsWidth()

thinThickBarlineSeparation

U+E032

xDistanceBetweenContours()

tieEndpointThickness

U+E1FD

xStrokeWidthAtOrigin()

tieMidpointThickness

U+E1FD

yStrokeWidthAtMinimum()

tupletBracketThickness

U+E1FE

xStrokeWidthAtOrigin()

areAlligned(points: tuple[RPoint, ...], axis: str, tolerance: int | float = 6) bool[source]

Check if the specified points are aligned on axis.

Parameters:
  • points – The points to check for alignment.

  • axis – The axis ("x" or "y") accross which to check for alignment.

  • tolerance – The tolerance for misalignment to apply in font units. Defaults to 6.

Example:

>>> glyph = font["uniE050"]
>>> point1, point2 = glyph[0].points[:2]
>>> rulers.areAlligned((point1, point2), axis="x", tolerance=3)
False
combineBounds(boundsList: list[tuple[int | float, int | float, int | float, int | float]]) tuple[int | float, int | float, int | float, int | float] | None[source]

Combine a list of bounds into one bounding box.

Example:

>>> glyph1, glyph2 = font["uniE050"], font["uniE260"]
>>> boundsList = [glyph1.bounds, glyph2.bounds]
>>> rulers.combineBounds(boundsList)
(-50, -634, 648, 1167)
getGlyphContours(glyph: Glyph, includeComponents: bool = True) Generator[RContour][source]

Return all contours in glyph, including component references.

Parameters:
  • glyph – The Glyph containing the contours to retrieve.

  • includeComponents – Whether to include any referenced contours in the glyph. Defaults to True.

Example:

>>> glyph = font["uniE050"]
>>> rulers.getGlyphContours(glyph)  
<generator object getGlyphContours.<locals>.<genexpr> at 0x...>
getGlyphPoints(glyph, types: str | tuple[str, ...] = ('line', 'curve', 'qcurve'), includeComponents: bool = True) Generator[RPoint][source]

Return all points in glyph, matching given types.

Any points referenced by components may be included.

Parameters:
  • glyph – The Glyph containing the points to retrieve.

  • types – The type values to include. Defaults to ("line", "curve", "qcurve").

  • includeComponents – Whether to include any referenced contours in the glyph.

Example:

>>> glyph = font["uniE050"]
>>> rulers.getGlyphPoints(glyph)  
<generator object getGlyphPoints.<locals>.<genexpr> at 0x...>
getGlyphSegments(glyph, types: str | tuple[str, ...] = ('line', 'curve', 'qcurve'), includeComponents: bool = True) Generator[RSegment][source]

Return all segments in glyph, matching given types.

Any segments referenced by components may be included.

Parameters:
  • glyph – The Glyph containing the segments to retrieve.

  • types – The type values to include. Defaults to ("line", "curve", "qcurve").

  • includeComponents – Whether to include any referenced contours in the glyph.

Example:

>>> glyph = font["uniE050"]
>>> rulers.getGlyphSegments(glyph)  
<generator object getGlyphSegments.<locals>.<genexpr> at 0x...>
getParentSegment(point: RPoint) RSegment | None[source]

Get the segment which the given point belongs to.

Parameters:

point – The point to find the parent segment for.

Example:

>>> glyph = font["uniE050"]
>>> point = glyph[0].points[0]
>>> rulers.getParentSegment(point)  
<RSegment line index='3' at ...>
glyphBoundsHeight(glyph: Glyph) int | float | None[source]

Return height of the glyph’s bounding box.

Parameters:

glyph – Source Glyph of contours to measure.

Example:

>>> glyph = font["uniE050"]
>>> rulers.glyphBoundsHeight(glyph)
1801
glyphBoundsWidth(glyph: Glyph) int | float | None[source]

Return width of the glyph’s bounding box.

Parameters:

glyph – Source Glyph of contours to measure.

Example:

>>> glyph = font["uniE050"]
>>> rulers.glyphBoundsWidth(glyph)
648
glyphBoundsXMinAbs(glyph: Glyph) int | float | None[source]

Return absolute value of glyph’s xMin bound.

Parameters:

glyph – Source Glyph of contours to measure.

Example:

>>> glyph = font["uniE022"]
>>> rulers.glyphBoundsXMinAbs(glyph)
80
hasHorizontalOffCurve(point: RPoint) bool[source]

Check if the given point has a predominantly horizontal off-curve.

An off-curve control point is considered horizontal if its x-difference from the on-curve point is greater than its y-difference.

Parameters:

point – The on-curve point to check.

Example:

>>> glyph = font["uniE260"]
>>> point = glyph[0].points[0]
>>> rulers.hasHorizontalOffCurve(point)
True
hasVerticalOffCurve(point: RPoint) bool[source]

Check if the given point has a predominantly vertical off-curve.

An off-curve control point is considered vertical if its y-difference from the on-curve point is greater than its x-difference.

Parameters:

point – The on-curve point to check.

Example:

>>> glyph = font["uniE260"]
>>> point = glyph[0].points[0]
>>> rulers.hasVerticalOffCurve(point)
False
wedgeArmStrokeWidth(glyph: Glyph)[source]

Measure thickness of arm in a wedge-shaped glyph.

Parameters:

glyph – Source Glyph of contours to measure.

Example:

>>> glyph = font["uniE1FD"]
>>> rulers.yStrokeWidthAtMinimum(glyph)
50
xDistanceBetweenContours(glyph: Glyph) int | float | None[source]

Measure horizontal distance between two adjacent contours in a glyph.

Parameters:

glyph – Source Glyph of contours to measure.

Example:

>>> glyph = font["uniE031"]
>>> rulers.xDistanceBetweenContours(glyph)
85
xDistanceStemToDot(glyph: Glyph) int | float | None[source]

Measure horizontal distance between a stem and a dot contour.

The contours may be placed on either side of each other.

Parameters:

glyph – Source Glyph of contours to measure.

Example:

>>> glyph = font["uniE040"]
>>> rulers.glyphBoundsXMinAbs(glyph)
63
xStrokeWidthAtOrigin(glyph: Glyph) int | float | None[source]

Measure horizontal distance between aligned points closest to origin.

Parameters:

glyph – Source Glyph of contours to measure.

Example:

>>> glyph = font["uniE1FE"]
>>> rulers.xStrokeWidthAtOrigin(glyph)
32
yDistanceBetweenContours(glyph: Glyph) int | float | None[source]

Measure vertical distance between two adjacent contours in a glyph.

Parameters:

glyph – Source Glyph of contours to measure.

Example:

>>> glyph = font["uniE036"]
>>> rulers.yDistanceBetweenContours(glyph)
119
yStrokeWidthAtMinimum(glyph: Glyph) int | float | None[source]

Measure vertical distance between aligned low-points in the glyph.

Parameters:

glyph – Source Glyph of contours to measure.

Example:

>>> glyph = font["uniE1FD"]
>>> rulers.yStrokeWidthAtMinimum(glyph)
50
DISPATCHER: dict[str, Callable[[Glyph], int | float | None]] = {'glyphBoundsHeight': <function glyphBoundsHeight>, 'glyphBoundsWidth': <function glyphBoundsWidth>, 'glyphBoundsXMinAbs': <function glyphBoundsXMinAbs>, 'wedgeArmStrokeWidth': <function wedgeArmStrokeWidth>, 'xDistanceBetweenContours': <function xDistanceBetweenContours>, 'xDistanceStemToDot': <function xDistanceStemToDot>, 'xStrokeWidthAtOrigin': <function xStrokeWidthAtOrigin>, 'yDistanceBetweenContours': <function yDistanceBetweenContours>, 'yStrokeWidthAtMinimum': <function yStrokeWidthAtMinimum>}

Dispatch the different ruler functions by their str name.

scriptUtils

Script utility functions.

This module provides a set of utility functions specifically intended for use in scripts and applications. Particualarly, it provides a set of noramlizers to ensure the integrity of objects frequently passed by the user in an application setting.

To import the module:

>>> from smufolib import scriptUtils
normalizeColor(color: tuple[int | float, int | float, int | float, int | float] | None, mark: bool) tuple[int | float, int | float, int | float, int | float] | None[source]

Ensure that color is valid based on the mark setting.”

If the input color is None and mark is True, a TypeError is raised. Otherwise, the color is normalized each dictionary value

Parameters:
  • color – The color value to normalize.

  • mark – Mark objects with the specified color.

Raises:

TypeError – If color is not the expected type.

normalizeColorDict(colorDict: dict[str, tuple[int | float, int | float, int | float, int | float]] | None, mark: bool) dict[str, tuple[int | float, int | float, int | float, int | float]] | None[source]

Ensure that ColorDict is valid based on the mark setting.”

If the input ColorDict is None and mark is True, a TypeError is raised. Otherwise, each value is normalized using normalizeColor().

Parameters:
  • colorDict – The color dictionary to normalize.

  • mark – Mark objects with the specified colors in colorDict.

Raises:

TypeError – If colorDict is not the expected type.

normalizeFont(font: Font | Path | str) Font[source]

Ensure that font represents a font object.

If font is a str or Path, it is treated as a path and passed to the Font constructor.

Parameters:

font – The font to normalize.

Raises:

TypeError – If font is not the expected type.

normalizeJsonDict(jsonDict: dict[str, Any] | None) dict[str, Any][source]

Ensure that jsonDict is not None.

Parameters:

jsonDict – The JSON dictionary to validate.

Raises:

TypeError – If jsonDict is None.

normalizeRequest(request: Request | Path | str) Request[source]

Ensure that request represents a request object.

If request is a str or Path, it is treated as a path and passed to the Request constructor.

Parameters:

request – The request to normalize.

Raises:

TypeError – If request is not the expected type.

normalizeTargetPath(targetPath: str | Path) Path[source]

Ensure that targetPath is an existing Path.

Parameters:

targetPath – The target path to normalize.

Raises:

stdUtils

Miscellaneous general-purpose utility functions.

This module provides a set of utility functions for various common tasks, including flattening nested iterables, summing tuples, and extracting summary lines from docstrings. It also includes functions for validating class attributes and string representations of floats, printing verbose messages, as well as a a no-op function for placeholder purposes.

To import the module:

>>> from smufolib import stdUtils
addTuples(*tuples: tuple[int | float, ...]) tuple[int | float, ...][source]

Sumize tuple values.

Parameters:

*tuples – tuples to add.

Example:

>>> stdUtils.addTuples((2, 4), (2, 4))
(4, 8)
doNothing(*args: Any, **kwargs: Any) None[source]

Do nothing at all.

This function accepts any arguments but does nothing with them.

Parameters:
  • *args – Positional arguments.

  • **kwargs – Keyword arguments.

Example:

>>> stdUtils.doNothing(1, 2, 3)
>>> stdUtils.doNothing(a=1, b=2)
flatten(iterable: Iterable[Any], depth: int | None = None) Generator[source]

Flatten irregularly nested iterables of any depth.

Parameters:
  • iterable – The iterable to flatten.

  • depth – The number of levels to flatten. depth=None employs maximum flattening. Defaults to None.

Examples:

>>> list(stdUtils.flatten([1, [2, [3, [4, 5]]]], depth=2))
[1, 2, 3, [4, 5]]
>>> list(stdUtils.flatten([1, [2, [3, [4, [5]]]]], depth=None))
[1, 2, 3, 4, 5]
getSummary(docstring: str | None) str | None[source]

Extract the summary line from a docstring.

Parameters:

docstring – The docstring from which to get the summary line.

Example:

>>> def showcaseGetSummary():
...     """Provide an example for the `getSummary()` function.
...
...     This function provides an example to show how to
...     extract a summary line from a docstring.
...
...     """
...
>>> docstring = showcaseGetSummary.__doc__
>>> stdUtils.getSummary(docstring)
"Give example for `getSummary()` function."
isFloat(string: str) bool[source]

Check if string represents a float.

Parameters:

string – The string to check.

Examples:

>>> stdUtils.isFloat("3.14")
True
>>> stdUtils.isFloat("314")
False
isInUnicodeRange(codepoint: int) bool[source]

Check if an integer is within the Unicode range (U+0000 to U+10FFFF).

validateAttr(obj, attributes: Iterable[str] | None = None) bool[source]

Validate obj based on whether the given attributes have been set.

This function returns False if any given attribute is not None, otherwise itreturns True. It supports validation of nested attributes, e.g.: "attr1.attr2.attr3".

Parameters:
  • obj – The object to validate.

  • attributes – The attribute names to check.

Example:

>>> class MyClass:
...     def __init__(self):
...         self.attr1 = 1
...         self.attr2 = None
...         self.attr3 = False
...
>>> obj = MyClass()
>>> stdUtils.validateAttr(obj, "attr1")
True
>>> stdUtils.validateAttr(obj, "attr2")
False
>>> stdUtils.validateAttr(obj, "attr3")
True
>>> stdUtils.validateAttr(obj, ["attr1", "attr2"])
False
verbosePrint(message: str, verbose: bool, *args: Any, **kwargs: Any) None[source]

Print a message if verbose is True.

This function behaves like the built-in print() function, but only prints the message if verbose is True. If verbose is False, it does nothing.

Parameters:
  • message – The message to be printed.

  • verbose – A flag indicating whether to print the message.

  • *args – Additional positional arguments passed to the print() function.

  • **kwargs – Additional keyword arguments passed to the print() function.

Example:

>>> stdUtils.verbosePrint("Hello, world!", True)
Hello, world!
>>> stdUtils.verbosePrint("Hello, world!", False)