Skip to content

Utilities

format_number(value)

Format a number to 8 significant figures

Parameters:

Name Type Description Default
value float

Number to format

required

Returns:

Name Type Description
str str

Formatted number

Examples:

>>> format_number(0.123456789)
"0.12345679"
>>> format_number(123456789)
"123456789"
Source code in onshape_robotics_toolkit\utilities\helpers.py
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
def format_number(value: float) -> str:
    """
    Format a number to 8 significant figures

    Args:
        value (float): Number to format

    Returns:
        str: Formatted number

    Examples:
        >>> format_number(0.123456789)
        "0.12345679"

        >>> format_number(123456789)
        "123456789"
    """

    return f"{value:.8g}"

generate_uid(values)

Generate a 16-character unique identifier from a list of strings

Parameters:

Name Type Description Default
values list[str]

List of strings to concatenate

required

Returns:

Name Type Description
str str

Unique identifier

Examples:

>>> generate_uid(["hello", "world"])
"c4ca4238a0b92382"
Source code in onshape_robotics_toolkit\utilities\helpers.py
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
def generate_uid(values: list[str]) -> str:
    """
    Generate a 16-character unique identifier from a list of strings

    Args:
        values (list[str]): List of strings to concatenate

    Returns:
        str: Unique identifier

    Examples:
        >>> generate_uid(["hello", "world"])
        "c4ca4238a0b92382"
    """

    _value = "".join(values)
    return hashlib.sha256(_value.encode()).hexdigest()[:16]

get_random_files(directory, file_extension, count)

Get random files from a directory with a specific file extension and count

Parameters:

Name Type Description Default
directory str

Directory path

required
file_extension str

File extension

required
count int

Number of files to select

required

Returns:

Type Description
list[str]

list[str]: List of file paths

Raises:

Type Description
ValueError

Not enough files in directory if count exceeds number of files

Examples:

>>> get_random_files("json", ".json", 1)
["json/file.json"]
>>> get_random_files("json", ".json", 2)
["json/file1.json", "json/file2.json"]
Source code in onshape_robotics_toolkit\utilities\helpers.py
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
def get_random_files(directory: str, file_extension: str, count: int) -> list[str]:
    """
    Get random files from a directory with a specific file extension and count

    Args:
        directory (str): Directory path
        file_extension (str): File extension
        count (int): Number of files to select

    Returns:
        list[str]: List of file paths

    Raises:
        ValueError: Not enough files in directory if count exceeds number of files

    Examples:
        >>> get_random_files("json", ".json", 1)
        ["json/file.json"]

        >>> get_random_files("json", ".json", 2)
        ["json/file1.json", "json/file2.json"]
    """

    _files = [file for file in os.listdir(directory) if file.endswith(file_extension)]

    if len(_files) < count:
        raise ValueError("Not enough files in directory")

    selected_files = random.sample(_files, count)
    file_paths = [os.path.join(directory, file) for file in selected_files]

    LOGGER.info(f"Selected files: {file_paths}")

    return file_paths, [x.split(".")[0] for x in selected_files]

get_random_names(directory, count, filename='words.txt')

Generate random names from a list of words in a file

Parameters:

Name Type Description Default
directory str

Path to directory containing words file

required
count int

Number of random names to generate

required
filename str

File containing list of words. Default is "words.txt"

'words.txt'

Returns:

Type Description
list[str]

List of random names

Raises:

Type Description
ValueError

If count exceeds the number of available words

Examples:

>>> get_random_names(directory="../", count=1)
["charizard"]
>>> get_random_names(directory="../", count=2)
["charizard", "pikachu"]
Source code in onshape_robotics_toolkit\utilities\helpers.py
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
def get_random_names(directory: str, count: int, filename: str = "words.txt") -> list[str]:
    """
    Generate random names from a list of words in a file

    Args:
        directory: Path to directory containing words file
        count: Number of random names to generate
        filename: File containing list of words. Default is "words.txt"

    Returns:
        List of random names

    Raises:
        ValueError: If count exceeds the number of available words

    Examples:
        >>> get_random_names(directory="../", count=1)
        ["charizard"]

        >>> get_random_names(directory="../", count=2)
        ["charizard", "pikachu"]
    """

    words_file_path = os.path.join(directory, filename)

    with open(words_file_path) as file:
        words = file.read().splitlines()

    if count > len(words):
        raise ValueError("count exceeds the number of available words")

    return random.sample(words, count)

get_sanitized_name(name, replace_with='_', remove_onshape_tags=False)

Sanitize a name by removing special characters, preserving only the specified replacement character, and replacing spaces with it. Ensures no consecutive replacement characters in the result. Optionally preserves a trailing " " tag where n is a number.

Parameters:

Name Type Description Default
name str

Name to sanitize.

required
replace_with str

Character to replace spaces and other special characters with (default is '_').

'_'
remove_onshape_tags bool

If True, removes a trailing " " tag where n is a number. Default is False.

False

Returns:

Name Type Description
str str

Sanitized name.

Examples:

>>> get_sanitized_name("wheel1 <3>")
"wheel1_3"
>>> get_sanitized_name("wheel1 <3>", remove_onshape_tags=True)
"wheel1"
>>> get_sanitized_name("wheel1 <3>", replace_with='-', remove_onshape_tags=False)
"wheel1-3"
Source code in onshape_robotics_toolkit\utilities\helpers.py
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
def get_sanitized_name(name: str, replace_with: str = "_", remove_onshape_tags: bool = False) -> str:
    """
    Sanitize a name by removing special characters, preserving only the specified
    replacement character, and replacing spaces with it. Ensures no consecutive
    replacement characters in the result.
    Optionally preserves a trailing " <n>" tag where n is a number.

    Args:
        name (str): Name to sanitize.
        replace_with (str): Character to replace spaces and other special characters with (default is '_').
        remove_onshape_tags (bool): If True, removes a trailing " <n>" tag where n is a number. Default is False.

    Returns:
        str: Sanitized name.

    Examples:
        >>> get_sanitized_name("wheel1 <3>")
        "wheel1_3"

        >>> get_sanitized_name("wheel1 <3>", remove_onshape_tags=True)
        "wheel1"

        >>> get_sanitized_name("wheel1 <3>", replace_with='-', remove_onshape_tags=False)
        "wheel1-3"
    """

    if replace_with not in "-_":
        raise ValueError("replace_with must be either '-' or '_'")

    tag = ""
    if remove_onshape_tags:
        # Regular expression to detect a trailing " <n>" where n is one or more digits
        tag_pattern = re.compile(r"\s<\d+>$")
        match = tag_pattern.search(name)
        if match:
            tag = match.group()  # e.g., " <3>"
            if tag:
                name = name[: match.start()]

    sanitized_name = "".join(char if char.isalnum() or char in "-_ " else "" for char in name)
    sanitized_name = sanitized_name.replace(" ", replace_with)
    sanitized_name = re.sub(f"{re.escape(replace_with)}{{2,}}", replace_with, sanitized_name)

    return sanitized_name

make_unique_keys(keys)

Make a list of keys unique by appending a number to duplicate keys and return a mapping of unique keys to their original indices.

Parameters:

Name Type Description Default
keys list[str]

List of keys.

required

Returns:

Type Description
dict[str, int]

A dictionary mapping unique keys to their original indices.

Examples:

>>> make_unique_keys(["a", "b", "a", "a"])
{"a": 0, "b": 1, "a-1": 2, "a-2": 3}
Source code in onshape_robotics_toolkit\utilities\helpers.py
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
def make_unique_keys(keys: list[str]) -> dict[str, int]:
    """
    Make a list of keys unique by appending a number to duplicate keys and
    return a mapping of unique keys to their original indices.

    Args:
        keys: List of keys.

    Returns:
        A dictionary mapping unique keys to their original indices.

    Examples:
        >>> make_unique_keys(["a", "b", "a", "a"])
        {"a": 0, "b": 1, "a-1": 2, "a-2": 3}
    """
    unique_key_map = {}
    key_count = {}

    for index, key in enumerate(keys):
        if key in key_count:
            key_count[key] += 1
            unique_key = f"{key}-{key_count[key]}"
        else:
            key_count[key] = 0
            unique_key = key

        unique_key_map[unique_key] = index

    return unique_key_map

make_unique_name(name, existing_names)

Make a name unique by appending a number to the name if it already exists in a set.

Parameters:

Name Type Description Default
name str

Name to make unique.

required
existing_names set[str]

Set of existing names.

required

Returns:

Type Description
str

A unique name.

Examples:

>>> make_unique_name("name", {"name"})
"name-1"
>>> make_unique_name("name", {"name", "name-1"})
"name-2"
Source code in onshape_robotics_toolkit\utilities\helpers.py
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
def make_unique_name(name: str, existing_names: set[str]) -> str:
    """
    Make a name unique by appending a number to the name if it already exists in a set.

    Args:
        name: Name to make unique.
        existing_names: Set of existing names.

    Returns:
        A unique name.

    Examples:
        >>> make_unique_name("name", {"name"})
        "name-1"
        >>> make_unique_name("name", {"name", "name-1"})
        "name-2"
    """
    if name not in existing_names:
        return name

    count = 1
    while f"{name}-{count}" in existing_names:
        count += 1

    return f"{name}-{count}"

print_dict(d, indent=0)

Print a dictionary with indentation for nested dictionaries

Parameters:

Name Type Description Default
d dict

Dictionary to print

required
indent int

Number of tabs to indent

0

Returns:

Type Description
None

None

Examples:

>>> print_dict({"a": 1, "b": {"c": 2}})
a
    1
b
    c
        2
Source code in onshape_robotics_toolkit\utilities\helpers.py
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
def print_dict(d: dict, indent=0) -> None:
    """
    Print a dictionary with indentation for nested dictionaries

    Args:
        d (dict): Dictionary to print
        indent (int): Number of tabs to indent

    Returns:
        None

    Examples:
        >>> print_dict({"a": 1, "b": {"c": 2}})
        a
            1
        b
            c
                2
    """

    for key, value in d.items():
        print()
        print("\t" * indent + str(key))
        if isinstance(value, dict):
            print_dict(value, indent + 1)
        else:
            print("\t" * (indent + 1) + str(value))

save_model_as_json(model, file_path, indent=4)

Save a Pydantic model as a JSON file

Parameters:

Name Type Description Default
model BaseModel

Pydantic model to save

required
file_path str

File path to save JSON file

required

Returns:

Type Description
None

None

Examples:

>>> class TestModel(BaseModel):
...     a: int
...     b: str
...
>>> save_model_as_json(TestModel(a=1, b="hello"), "test.json")
Source code in onshape_robotics_toolkit\utilities\helpers.py
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
def save_model_as_json(model: BaseModel, file_path: str, indent: int = 4) -> None:
    """
    Save a Pydantic model as a JSON file

    Args:
        model (BaseModel): Pydantic model to save
        file_path (str): File path to save JSON file

    Returns:
        None

    Examples:
        >>> class TestModel(BaseModel):
        ...     a: int
        ...     b: str
        ...
        >>> save_model_as_json(TestModel(a=1, b="hello"), "test.json")
    """

    with open(file_path, "w") as file:
        json.dump(model.model_dump(), file, indent=indent, cls=CustomJSONEncoder)

xml_escape(unescaped)

Escape XML characters in a string

Parameters:

Name Type Description Default
unescaped str

Unescaped string

required

Returns:

Name Type Description
str str

Escaped string

Examples:

>>> xml_escape("hello 'world' "world"")
"hello &apos;world&apos; &quot;world&quot;"
>>> xml_escape("hello <world>")
"hello &lt;world&gt;"
Source code in onshape_robotics_toolkit\utilities\helpers.py
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
def xml_escape(unescaped: str) -> str:
    """
    Escape XML characters in a string

    Args:
        unescaped (str): Unescaped string

    Returns:
        str: Escaped string

    Examples:
        >>> xml_escape("hello 'world' \"world\"")
        "hello &apos;world&apos; &quot;world&quot;"

        >>> xml_escape("hello <world>")
        "hello &lt;world&gt;"
    """

    return escape(unescaped, entities={"'": "&apos;", '"': "&quot;"})