pycommons package

pycommons is a package with utility functionality for Python projects.

Subpackages

Submodules

pycommons.types module

Some basic type handling routines.

class pycommons.types.T

the type variable for the data elements in an iterator

alias of TypeVar(‘T’)

pycommons.types.check_int_range(val, name=None, min_value=0, max_value=1000000000)[source]

Check whether a value val is an integer in a given range.

Via type annotation, this method actually accepts a value val of any type as input. However, if val is not an instance of int, it will throw an error. Also, if val is not in the prescribed range, it will throw an error, too. By default, the range is 0…1_000_000_000.

I noticed that often, we think that only want to check a lower limit for val, e.g., that a number of threads or a population size should be val > 0. However, in such cases, there also always a reasonable upper limits. We never actually want an EA to have a population larger than, say, 1_000_000_000. That would make no sense. So indeed, whenever we have a lower limit for a parameter, we also should have an upper limit resulting from physical constraints. 1_000_000_000 is a reasonably sane upper limit in many situations. If we need smaller or larger limits, we can of course specify them.

Notice that there is one strange border case: In Python, bool is a subtype of int, where True has value 1 and False has value 0. See <https://docs.python.org/3/library/functions.html#bool>. We therefore treat bool values indeed as instances of int.

Parameters:
  • val (Any) – the value to check

  • name (Optional[str], default: None) – the name of the value, or None

  • min_value (int | float, default: 0) – the minimum permitted value

  • max_value (int | float, default: 1000000000) – the maximum permitted value

Return type:

int

Returns:

val if everything is OK

Raises:
  • TypeError – if val is not an int

  • ValueError – if val is an int but outside the prescribed range

>>> try:
...   print(check_int_range(12, min_value=7, max_value=13))
... except (ValueError, TypeError) as err:
...   print(err)
12
>>> try:
...   print(check_int_range(123, min_value=7, max_value=13))
... except (ValueError, TypeError) as err:
...   print(err)
...   print(err.__class__)
Value=123 is invalid, must be in 7..13.
<class 'ValueError'>
>>> try:
...   print(check_int_range(5.0, name="ThisIsFloat"))
... except (ValueError, TypeError) as err:
...   print(err)
...   print(err.__class__)
ThisIsFloat should be an instance of int but is float, namely '5.0'.
<class 'TypeError'>

The behavior in the border case of bool instances actually also being instances of int:

>>> check_int_range(True, "true", 0, 2)
True
>>> check_int_range(False, "false", 0, 2)
False
>>> try:
...   print(check_int_range(True, min_value=7, max_value=13))
... except (ValueError, TypeError) as err:
...   print(err)
...   print(err.__class__)
Value=True is invalid, must be in 7..13.
<class 'ValueError'>
pycommons.types.check_to_int_range(val, name=None, min_value=0, max_value=1000000000)[source]

Check whether a value val can be converted an integer in a given range.

Parameters:
  • val (Any) – the value to convert via int(…) and then to check

  • name (Optional[str], default: None) – the name of the value, or None

  • min_value (int | float, default: 0) – the minimum permitted value

  • max_value (int | float, default: 1000000000) – the maximum permitted value

Return type:

int

Returns:

val if everything is OK

Raises:
  • TypeError – if val is None

  • ValueError – if val is not None but can either not be converted to an int or to an int outside the prescribed range

>>> try:
...   print(check_to_int_range(12))
... except (ValueError, TypeError) as err:
...   print(err)
12
>>> try:
...   print(check_to_int_range(12.0))
... except (ValueError, TypeError) as err:
...   print(err)
12
>>> try:
...   print(check_to_int_range("12"))
... except (ValueError, TypeError) as err:
...   print(err)
12
>>> try:
...   print(check_to_int_range("A"))
... except (ValueError, TypeError) as err:
...   print(err)
...   print(err.__class__)
Cannot convert value='A' to int, let alone in range 0..1000000000.
<class 'ValueError'>
>>> try:
...   print(check_to_int_range(None))
... except (ValueError, TypeError) as err:
...   print(err)
...   print(err.__class__)
Cannot convert value=None to int, let alone in range 0..1000000000.
<class 'TypeError'>
pycommons.types.reiterable(source)[source]

Ensure that an Iterable can be iterated over multiple times.

This function will solidify an Iterator into an Iterable. In Python, Iterator is a sub-class of Iterable. This means that if your function accepts instances of Iterable as input, it may expect to be able to iterate over them multiple times. However, if an Iterator is passed in, which also is an instance of Iterable and thus fulfills the function’s type requirement, this is not the case. A typical example of this would be if a Generator is passed in. A Generator is an instance of Iterator, which, in turn, is an instance of Iterable. However, you can iterate over a Generator only once.

Parameters:

source (Union[Iterable[TypeVar(T)], Iterator[TypeVar(T)]]) – the data source

Return type:

Iterable[TypeVar(T)]

Returns:

the resulting re-iterable iterator

>>> a = [1, 2, 3]
>>> reiterable(a) is a
True
>>> a = (1, 2, 3)
>>> reiterable(a) is a
True
>>> a = {1, 2, 3}
>>> reiterable(a) is a
True
>>> a = {1: 1, 2: 2, 3: 3}
>>> reiterable(a) is a
True
>>> k = a.keys()
>>> reiterable(k) is k
True
>>> k = a.values()
>>> reiterable(k) is k
True
>>> reiterable((x for x in range(5)))
(0, 1, 2, 3, 4)
>>> try:
...     reiterable(None)
... except TypeError as te:
...     print(str(te)[:60])
source should be an instance of any in {typing.Iterable, typ
>>> try:
...     reiterable(1)
... except TypeError as te:
...     print(str(te)[:60])
source should be an instance of any in {typing.Iterable, typ
pycommons.types.type_error(obj, name, expected=None, call=False)[source]

Create an error to raise if a type did not fit.

Parameters:
  • obj (Any) – the object that is of the wrong type

  • name (str) – the name of the object

  • expected (Union[None, type, Iterable[type]], default: None) – the expected types (or None)

  • call (bool, default: False) – the object should have been callable?

Return type:

ValueError | TypeError

Returns:

a TypeError with a descriptive information

>>> type_error(1.3, "var", int)
TypeError("var should be an instance of int but is float, namely '1.3'.")
>>> type_error("x", "z", (int, float)).args[0]
"z should be an instance of any in {float, int} but is str, namely 'x'."
>>> type_error("x", "z", (int, float, None)).args[0]
"z should be an instance of any in {None, float, int} but is str, namely 'x'."
>>> type_error("x", "z", (int, float, type(None))).args[0]
"z should be an instance of any in {None, float, int} but is str, namely 'x'."
>>> type_error("f", "q", call=True).args[0]
"q should be a callable but is str, namely 'f'."
>>> type_error("1", "2", bool, call=True).args[0]
"2 should be an instance of bool or a callable but is str, namely '1'."
>>> type_error(None, "x", str)
TypeError('x should be an instance of str but is None.')
pycommons.types.type_name(tpe)[source]

Convert a type to a string which represents its name.

Parameters:

tpe (type | None) – the type

Return type:

str

Returns:

the string

>>> type_name(None)
'None'
>>> type_name(type(None))
'None'
>>> type_name(int)
'int'
>>> from pycommons.io.path import file_path, Path
>>> type_name(Path)
'pycommons.io.path.Path'
>>> from typing import Callable
>>> type_name(Callable)
'typing.Callable'
>>> from typing import Callable as Ca
>>> type_name(Ca)
'typing.Callable'
>>> from typing import Callable as Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
>>> type_name(Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)
'typing.Callable'
>>> import typing as ttttttttttttttttttttttttttttttttttttttttttt
>>> type_name(ttttttttttttttttttttttttttttttttttttttttttt.Callable)
'typing.Callable'
pycommons.types.type_name_of(obj)[source]

Get the fully-qualified class name of an object.

Parameters:

obj (Any) – the object

Return type:

str

Returns:

the fully-qualified class name of the object

>>> from pycommons.io.path import Path, file_path
>>> type_name_of(Path)
'type'
>>> type_name_of(file_path(__file__))
'pycommons.io.path.Path'
>>> type_name_of(None)
'None'
>>> type_name_of(int)
'type'
>>> type_name_of(print)
'builtin_function_or_method'
>>> from typing import Callable
>>> type_name_of(Callable)
'typing._CallableType'
>>> from math import sin
>>> type_name_of(sin)
'builtin_function_or_method'
>>> import pycommons.io as iox
>>> type_name_of(iox)
'module'

pycommons.version module

An internal file with the version of the pycommons package.