Utils

exception psynet.utils.DuplicateKeyError[source]

Bases: ValueError

class psynet.utils.NoArgumentProvided[source]

Bases: object

We use this class as a replacement for None as a default argument, to distinguish cases where the user doesn’t provide an argument from cases where they intentionally provide None as an argument.

exception psynet.utils.TranslationNotFoundError[source]

Bases: KeyError

psynet.utils.cache(user_function, /)[source]

Simple lightweight unbounded cache. Sometimes called “memoize”.

psynet.utils.call_function(function, *args, **kwargs)[source]

Calls a function with *args and **kwargs, but omits any **kwargs that are not requested explicitly.

psynet.utils.classproperty(func)[source]

Defines an analogous version of @property but for classes, after https://stackoverflow.com/questions/5189699/how-to-make-a-class-property.

psynet.utils.get_custom_sql_classes()[source]
Returns:

  • A dictionary of all custom SQLAlchemy classes defined in the local experiment

  • (excluding any which are defined within packages).

psynet.utils.get_descendent_class_by_name(parent_class, name)[source]

Attempt to return a subclass by name.

Actual class names and known nicknames are both supported.

psynet.utils.get_installed_package_source_directory(package_name)[source]

Get the source directory of an installed package.

Parameters:

package_name (str) – The name of the package.

Returns:

The path to the package root directory.

Return type:

Path

Raises:

FileNotFoundError – If the package root directory cannot be found.

psynet.utils.get_object_from_module(module_name, object_name)[source]

Finds and returns an object from a module.

Parameters:
  • module_name (str) – The name of the module.

  • object_name (str) – The name of the object.

psynet.utils.get_package_name(path='.')[source]

Finds the name of the package by introspecting the current working directory. Assumes that either setup.py or pyproject.toml is present.

psynet.utils.get_package_name_from_pyproject()[source]

Get package name from pyproject.toml file.

Returns:

The package name from pyproject.toml.

Return type:

str

psynet.utils.get_package_name_from_setup()[source]

Get package name from setup.py file.

Returns:

The package name from setup.py.

Return type:

str

psynet.utils.get_package_source_directory(path='.')[source]

Get the source directory of the package by inspecting pyproject.toml or setup.py. Does not assume that the package is installed.

Parameters:

path (str) – The path to the package source directory.

Returns:

The path to the package source directory.

Return type:

str

Raises:

FileNotFoundError – If the package source directory cannot be found.

psynet.utils.get_translator(context=False, locale=None, namespace=None, locales_dir=None)[source]

Return a translator.

In most cases this function should be called with no arguments, in which case the locale will be taken from the config.txt file, the namespace will be inferred from the context in which the function was called, and the locales directory will be inferred from the namespace.

The default translator is context-free, which means that it only takes a message argument. We recommend using this in most cases. You can obtain a context-aware translator by setting context = True; such a translator takes both a context and a message argument.

PsyNet uses automated code inspection tools to extract all translatable strings from your code. In order for these tools to work properly, you should save the returned translator with the name _ if context = False or _p if context = True.

Once you have marked up your code with the _ and _p functions, you can then run psynet translate to generate automatically translated versions of your strings.

Example usage

>>> _ = get_translator()
>>> _("Hello")  # Translate "Hello" into the current locale.
>>> _p = get_translator(context=True)
>>> _p("welcome message", "Hello")  # Translate "Hello" into the current locale, with context "welcome message".
type context:

param context:

Whether to use the context argument. If True, the translator will be a function that takes a context argument and a message argument. If False, the translator will be a function that just takes a message argument.

type context:

bool, optional

type locale:

param locale:

The locale to use for translations. If not provided, the locale will be taken from the experiment config.

type locale:

str, optional

type namespace:

param namespace:

The namespace to use for translations. If not provided, the namespace will be inferred from the context in which the function was called. The experiment directory has a namespace of “experiment”, and the package directory has a namespace of the package name.

type namespace:

str, optional

type locales_dir:

param locales_dir:

The directory to use for translations. If not provided, the locales directory will be inferred from the namespace. In the case of an experiment, the locales directory will be the “locales” directory of the experiment’s source directory. In the case of a package, the locales directory will be the “locales” directory of the package’s source directory.

type locales_dir:

str, optional

psynet.utils.in_python_package()[source]

Test whether the current directory is the root of a Python package.

Returns:

True if the current directory contains either pyproject.toml or setup.py, indicating it is likely a Python package root directory.

Return type:

bool

psynet.utils.is_method_overridden(obj, ancestor, method)[source]

Test whether a method has been overridden.

Parameters:
  • obj – Object to test.

  • ancestor (Type) – Ancestor class to test against.

  • method (str) – Method name.

Returns:

  • Returns True if the object shares a method with its ancestor,

  • or False if that method has been overridden.

psynet.utils.linspace(lower, upper, length)[source]

Returns a list of equally spaced numbers between two closed bounds.

Parameters:
  • lower (number) – The lower bound.

  • upper (number) – The upper bound.

  • length (int) – The length of the resulting list.

psynet.utils.make_parents(path)[source]

Creates the parent directories for a specified file if they don’t exist already.

Returns:

  • The original path.

psynet.utils.merge_dicts(*args, overwrite)[source]

Merges a collection of dictionaries, with later dictionaries taking precedence when the same key appears twice.

Parameters:
  • *args – Dictionaries to merge.

  • overwrite (bool) – If True, when the same key appears twice in multiple dictionaries, the key from the latter dictionary takes precedence. If False, an error is thrown if such duplicates occur.

psynet.utils.merge_two_dicts(x, y, overwrite)[source]

Merges two dictionaries.

Parameters:
  • x (dict) – First dictionary.

  • y (dict) – Second dictionary.

  • overwrite (bool) – If True, when the same key appears twice in the two dictionaries, the key from the latter dictionary takes precedence. If False, an error is thrown if such duplicates occur.

psynet.utils.negate(f)[source]

Negates a function.

Parameters:

f – Function to negate.

psynet.utils.null_translator(message)[source]

A translator that returns the message unchanged.

psynet.utils.null_translator_with_context(context, message)[source]

A translator that returns the message unchanged.

psynet.utils.organize_by_key(lst, key, sort_key=None)[source]

Sorts a list of items into groups.

Parameters:
  • lst – List to sort.

  • key – Function applied to elements of lst which defines the grouping key.

Returns:

  • A dictionary keyed by the outputs of key.

psynet.utils.query_yes_no(question, default='yes')[source]

Ask a yes/no question via raw_input() and return their answer.

“question” is a string that is presented to the user. “default” is the presumed answer if the user just hits <Enter>.

It must be “yes” (the default), “no” or None (meaning an answer is required of the user).

The “answer” return value is True for “yes” or False for “no”.

psynet.utils.require_exp_directory(f)[source]

Decorator to verify that a command is run inside a valid PsyNet experiment directory.

psynet.utils.require_requirements_txt(f)[source]

Decorator to verify that a command is run inside a directory which contains a requirements.txt file.

psynet.utils.serialise(obj)[source]

Serialise objects not serialisable by default