heliport.core.utils package

Submodules

heliport.core.utils.IDs module

class heliport.core.utils.IDs.IdentifierScheme(prefix, datacite_id, label)

Bases: tuple

datacite_id

Alias for field number 1

label

Alias for field number 2

prefix

Alias for field number 0

heliport.core.utils.IDs.find_identifier_scheme(identifier)
heliport.core.utils.IDs.generate_object_id()
heliport.core.utils.IDs.generate_project_id(user, group, date)
heliport.core.utils.IDs.is_globally_unique(identifier: str)
heliport.core.utils.IDs.is_resolvable(identifier: str)
heliport.core.utils.IDs.remove_special_chars(raw_id)
heliport.core.utils.IDs.test_resolvability(identifier)

heliport.core.utils.collections module

Custom collections similar to builtin collections like dict or list but with additional or different functionality.

class heliport.core.utils.collections.DecoratorDict(allow_reassign_key=False)

Bases: SingleAssignDict

A dict that provides register() decorator and can be used like this:

function_collection = DecoratorDict()

@function_collection.register("a nice function")
def a_nice_function():
    pass

function_collection["a nice function"]()
register(key)

Decorator to assign a function to key.

class heliport.core.utils.collections.DecoratorIndex(field, allow_reassign_key=False)

Bases: SingleAssignDict

A dict that provides register() decorator for classes. It can be used like this:

numbered_classes = DecoratorIndex("x")

@numbered_classes.register
class OneClass:
    x = 1

one_instance = numbered_classes[1]()
register(value)

Decorator to assign a class to the key specified by field.

transform_key(key)

This allows to add transformations to the key in subclasses.

class heliport.core.utils.collections.DecoratorList(iterable=(), /)

Bases: list

A list that provides register() decorator to append a function or class to the list:

my_functions = DecoratorList()

@my_functions.register
def f():
    pass

my_functions[0]()
register(object, /)

Append object to the end of the list.

class heliport.core.utils.collections.ExitContext

Bases: ExitStack

Allows optimizations where expensive setup and teardown operations are reused.

Contexts are handled safely by using Pythons contextlib.ExitStack.

In the following example the file is only opened and closed once:

@dataclass(frozen=True)
class File:
    name: str

def read_file_at(pos, file_name, context):
    file = context.get(File(file_name))
    if file is None:
        file = context.set_context(File(file_name), open(file_name))
    file.seek(pos)
    print(file.read())

with ExitContext() as context:
    read_file_at(0, "hello.txt", context)
    read_file_at(4, "hello.txt", context)
discard(key)

Prematurely exit context with this key. The context is exited again when the ExitContext itself is closed later.

get(key, default_func=None, *args, **kwargs)

Get value associated with key or None if no value was set.

The exact same object is returned as from the set() function when setting the key. If a default_func is supplied and the key was not found, it is called with *args and **kwargs. The return value is than passed to set_context() or set_value() depending on if the returned value has an __enter__ method. Finally, the result is returned. Note that the result is not always the value returned by default_func. Given that f returns a context manager the following lines are equivalent with respect to the value stored in x:

x = f().__enter__()
x = exit_context.get(new_key, f)
set_context(key, context: ContextManager[T]) T

Enter context and store at key.

set_value(key, value: T) T

Similar to set_context() but allows to insert things that are not a ContextManager into the ExitContext.

class heliport.core.utils.collections.FDecoratorIndex(field, allow_reassign_key=False)

Bases: DecoratorIndex

A dict that provides register() decorator for classes. It can be used like this:

numbered_classes = FDecoratorIndex("x")

@numbered_classes.register
class OneClass:
    @staticmethod
    def x():
        return 1

one_instance = numbered_classes[1]()
transform_key(key)
class heliport.core.utils.collections.HashableDictWrapper(the_dict)

Bases: UserDict

Normally dict s are not hashable in python because they are mutable for the default notion of equality. Two HashableDictWrapper s are equal only if they are the same object (like classes that don’t implement __eq__). Under this notion dictionaries are immutable and can be hashable.

class heliport.core.utils.collections.IndexedSet

Bases: object

IndexedSet behaves similar to pythons set however it provides additional query functions:

Fruit = namedtuple("Fruit", "name color")
fruits = IndexedSet()
fruits.add(Fruit("Apple", "red"))
fruits.add(Fruit("Walnut", "brown"))
fruits.get_by(color="red")  # returns Fruit("Apple", "red")

All members in an IndexedSet must be hashable. All methods (except build_index()) return in constant amortized time for a fixed number of key combinations used in queries.

add(item: Hashable)

Add item to this IndexedSet. add takes time linear in the number of indexes (see filter_by()).

build_index(index_name: Tuple[str])

Used by find_by() to build indices.

Parameters:

index_name – Note that order matters. Please sort the tuple before passing into this function.

discard(item: Hashable)

Remove item from this IndexedSet if present. discard takes time linear in the number of indexes (see filter_by()).

filter_by(**conditions) set

Returns all items in this IndexedSet, that meet the specified conditions, as a set. Normally this function runs in constant time, however the first time, some combination of keys is used, an index is created in linear time.

get_any_or_none(**conditions)

Similar to find_by() but returns only one item. If no items match conditions, None is returned.

get_by(**conditions)

Similar to find_by() but returns only one item.

Raises:

AssertionError – if there is no or more than one item matching the conditions

remove(item)

Remove item from this IndexedSet. remove takes time linear in the number of indexes (see filter_by()).

Raises:

KeyError – if not present

class heliport.core.utils.collections.RootedRDFGraph(root: Node, graph: Graph | None = None)

Bases: object

Represent a rdflib Graph that has a special root node. For example the root could be the thing that is described in the rdf graph.

Example usage:

a = rdflib.URIRef("https://example.org/a")
graph_a = rdflib.Graph()
graph_a.add((a, rdflib.RDFS.label, rdflib.Literal("a")))
roted_graph_a = RootedRDFGraph(a, graph_a)  # a is described in graph_a

b = rdflib.URIRef("https://example.org/b")
rooted_graph_b = RootedRDFGraph(b)  # b is not described

root_b, graph_b = rooted_graph_b  # tuple unpacking is supported
static from_atomic(value) RootedRDFGraph

Generate a RootedRDFGraph that represents a simple python value such as a string or int.

static from_blank() RootedRDFGraph
static from_uri_str(uri: str) RootedRDFGraph

Generate a RootedRDFGraph that represents the uri.

graph: Graph

An rdflib graph that describes the root (may be empty)

root: Node

Root of the graph (the node that is described in the graph)

class heliport.core.utils.collections.SingleAssignDict(allow_reassign_key=False)

Bases: dict

A dict that has an option to disallow reassigning keys.

heliport.core.utils.collections.first(collection: Iterable[T]) T | None

Return first element of an iterable or None if the iterable is empty.

heliport.core.utils.collections.merge_iterables(*iterables, block_size=1)

Yields all elements from all iterables similar to itertools.chain(). Only block_size many items are taken from each iterable at a time. This allows to get elements from all iterables even if one iterable is very large and the result is truncated. See this example:

from itertools import islice

ab_generator = merge_iterables("A"*100, "BBB", block_size=2)
ab_max_len_10 = islice(ab_generator, 10)  # still contains all Bs
print(''.join(ab_max_len_10))  # example output: BBAABAAAAA

heliport.core.utils.colors module

Collection of functions that work with colors.

class heliport.core.utils.colors.Color(color: Color | None = None)

Bases: object

Represent a color. Translating between different color representations.

b: float

blue value as a float between 0 and 1

classmethod from_html(html: str)

Formats like #0055FF or #05F are allowed for html.

classmethod from_rgb(r: float, g: float, b: float)

Color from r, g, b floats between 0 and 1.

classmethod from_rgb255(r: int, g: int, b: int)

Color from r, g, b ints between 0 and 255.

g: float

green value as a float between 0 and 1

property html

Color like in HTML. e.g. #00ff33.

property matching_foreground: Color

Use pick_foreground_color() to select a color with high contrast.

r: float

red value as a float between 0 and 1

property rgb

red, green, blue tuple of float values between 0 and 1.

property rgb255

red, gree, blue tuple of values as int between 0 and 255.

heliport.core.utils.colors.color_dist(c1, c2)

Compute distance of colors based on some heuristic.

Parameters:
  • c1 – A color represented by three values e.g. (1, 2, 3)

  • c2 – A color represented by three values e.g. (1, 2, 3)

Returns:

Score how different c1 and c2 are. Larger score means more different.

heliport.core.utils.colors.color_dist_array(c1, colors)

Compute minimum distance of c1 to any color in colors. Input and output format is the same as in color_dist().

heliport.core.utils.colors.pick_color() tuple

Return color from uniform distribution as tuple of three numbers in range(255).

heliport.core.utils.colors.pick_color_not_in(colors)

Pick random color. Colors more different from all colores in colors are preferred. For color representation see pick_color() and color_dist() functions.

heliport.core.utils.colors.pick_foreground_color(background_html_color: str) str

Return a color visible on some background_html_color. Colores are represented like in HTML e.g. #FFF (different length, lowercase or without # is also supported).

heliport.core.utils.command_line_execution module

class heliport.core.utils.command_line_execution.CommandExecutor(allow_shell_syntax: bool = True, shell: bool = False, host: str | None = None, username: str | None = None, password: str | None = None, key: str | None = None, indirection: CommandExecutor | None = None, auto_connect: bool = True)

Bases: object

close()
abstract connect()
abstract execute(command: str) CommandResults
abstract file(path: str, mode: str = 'r')
class heliport.core.utils.command_line_execution.CommandResults(stdout: str, stderr: str, status: int)

Bases: object

extract_http_content()
extract_http_json()
property last_complete_line: str
property last_line: str
property result: str
property status_result: Tuple[int, str]
property stdout_stderr: Tuple[str, str]
class heliport.core.utils.command_line_execution.SSHCommandExecutor(host: str | None = None, username: str | None = None, password: str | None = None, key: str | None = None, indirection: CommandExecutor | None = None, auto_connect: bool = True, missing_host_key_policy=None, set_shell_to_true: bool = False)

Bases: CommandExecutor

connect(max_depth: int = 10)
connect_error_message(hint=None)
property decrypted_key: RSAKey | None
execute(command: str, command_input: str | None = None) CommandResults
file(path: str, mode: str = 'r')
get_parent_channel(max_depth: int)
list_dir(path: str)
setup_new_ssh()
class heliport.core.utils.command_line_execution.ShellSSHCommandExecutor(host: str | None = None, username: str | None = None, password: str | None = None, key: str | None = None, indirection: CommandExecutor | None = None, auto_connect: bool = True, default_result_callback: Callable[[str], None] | None = None, missing_host_key_policy=None)

Bases: SSHCommandExecutor

await_command_result(output_callback=None)
connect(max_depth: int = 10)
property echo_command_separator
execute(command: str, output_callback: Callable[[str], None] | None = None)
read_output() str
heliport.core.utils.command_line_execution.create_command_executor(allow_shell_syntax: bool = True, shell: bool = False, host: str | None = None, username: str | None = None, password: str | None = None, key: str | None = None, indirection: CommandExecutor | None = None, auto_connect: bool = True, default_result_callback: Callable[[str], None] | None = None, missing_host_key_policy=None) CommandExecutor

heliport.core.utils.context module

class heliport.core.utils.context.Context(user: HeliportUser = None, project: Project = None, context: ExitContext = None)

Bases: object

A context can be used for optimizations where expensive setup and teardown steps can be shared between operations or to access the current logged-in user.

See heliport.utils.collections.ExitContext for more details.

activate_manual_closing()

Disable automatic closing when exiting a with statement once.

This allows to return to a calling function that is trusted to close this context:

def create_context():
    with Context() as c:
        maybe_raise_error(c)  # c is closed if error is raised
        c.activate_manual_closing()
        # an error here would not close c
        # c.close() would still work normally
        return c  # exiting with block is ignored

with create_context() as context:
    print(context, "is not closed yet")
    # an error here would close context properly again

# now the context is closed

Instead of another with block, close() could be called manually in the calling context.

cache(key, value)

Just cache the value - nothing fancy - nothing is entered, closed or generated.

close()

Close the context and all contexts registered on it.

get_cached(key)

Just get a cached value; returns None if not found.

property user

The current user; raises an assertion error if there is none.

class heliport.core.utils.context.Description(*args, **kwargs)

Bases: Protocol

Can be used to get or create values in some Context:

from dataclasses import dataclass

@dataclass(frozen=True)
class MyConnection:
    my_connection_param: str

    def generate(self, context):
        ...  # open connection
        return connection  # connection may be a context manager

def f(context):
    connection = context[MyConnection("foo")]
    ...

with Context() as context:
    f(context)  # opens new connection
    f(context)  # takes existing connection from context
# if generate returned a context manager, connection is closed after leaving with block
generate(context: Context) Any

Generate the value that the dataclass is describing. Program with caution, handle all errors to close everything before raising. Automatic closing only works after the context manager is returned.

heliport.core.utils.context.digital_object_breadcrumbs(session, url_query_params, label, link)

Manage breadcrumbs in sessions and add label pointing to link. Current breadcrumb path is reset if url_query_params don’t include "breadcrumb" == True.

heliport.core.utils.context.project_header_breadcrumbs(request, label, link, reset=False)

Manage breadcrumbs for project header in session.

If the reset parameter is True, only the first breadcrumb is kept.

heliport.core.utils.encryption module

heliport.core.utils.encryption.decrypt(data: str)
heliport.core.utils.encryption.encrypt(value: str)

heliport.core.utils.exceptions module

exception heliport.core.utils.exceptions.AccessDenied(message=None)

Bases: UserMessage

For when permission check fails.

exception heliport.core.utils.exceptions.LoginInfoMissing(message)

Bases: UserMessage

The exception when a user has not provided a valid login info. In the future support for linking to a prefilled login info creation page may be added.

exception heliport.core.utils.exceptions.UserMessage(message)

Bases: Exception

An exception that caries a message that should be shown to the user.

heliport.core.utils.form_description module

Classes for describing an input form.

These are used in the heliport.custom_views.HeliportObjectListView.

class heliport.core.utils.form_description.FormColumn(display_name, column_name, attrs=None)

Bases: object

Represents the keys that a user is asked for in an FormDescription. Information how to render a form input for this field is available via attr() or the attrs property.

attr(key)

Return some attribute named key intended for display of this FormColumn taken from attrs parameter.

bind(obj: Any) FormItem

Return a FormItem where the attribute described by this FormColumn takes on the value from obj.

unbound() FormItem

Return a FormItem where the attribute described by this FormColumn takes on no value. (The FormItem is “unbound”). This is useful when a new object should be created with a form, where no current values exist.

class heliport.core.utils.form_description.FormDescription

Bases: object

Class for building up the description of a form including the relevant columns, a potential obj that should be edited by the form, some add_text for display next to the submit button (see get_add_text()) and a cancel_url when the form is canceled.

add_column(display_name: str, column_name: str, attrs: dict | None = None)

Appends a FormColumn with the given attributes to the form.

Parameters:
  • display_name – Name to be shown to the user as label for this input.

  • column_name – Name of the attribute where the value for this input is stored on some object.

  • attrs – Attributes to store information about presenting this input.

columns: List[FormColumn]

fields of the form

generate_items() List[FormItem]

Returns bound FormItem s if obj is specified unbound ones otherwise.

get_add_text()

The add_text property should be set to an iterable or None. This function returns the add_text as a list, where strings are represented as {"text": the_string} for example:

f = FormDescription()
f.add_text = ["see", {"text": "this", "link": "https://..."}, "docu"]
f.get_add_text() == [{"text": "see"}, {"text": "this", "link": "https://..."}, {"text": "docu"}]
has_required_elements() bool

Decides if a column has the FormColumn.attr() "required" set to True.

remove_column(column_name: str)

Remove all columns with column_name.

class heliport.core.utils.form_description.FormItem(original, value=None, unbound=False)

Bases: object

Represents a key value pair in a FormDescription. If the FormItem is not bound, the value may be None or "".

property bound: bool

Determines if the FormItem is bound to some value. A property “unbound” also exists.

property html_id: str

Something that is usable as id in html documents.

heliport.core.utils.handles module

class heliport.core.utils.handles.HandleServer

Bases: object

static do_request(method, url, **kwargs)
get(url, json_data=Ellipsis)
handle_server_request(method, url, json_data=Ellipsis, authenticate=False)
put(url, json_data=Ellipsis)
heliport.core.utils.handles.get_handle_from_response(answer)
heliport.core.utils.handles.get_handle_url(handle, server=None)
heliport.core.utils.handles.get_key_values(handle, server=None) List[Tuple[str, str]]
heliport.core.utils.handles.register_handle(handle_name, target_url, server=None)

heliport.core.utils.http module

Functionality for working with http requests and responses.

heliport.core.utils.http.directory_api_response(request, directory_obj: DirectoryObj, file_url=None, directory_url=None, context=None)

Render directory response.

file_url and directory_url are completely optional but can be used to keep the user in a particular endpoint. If they are not supplied the generic complete digital object api is used.

heliport.core.utils.http.directory_from_description_api_response(request, file_url=None, directory_url=None)

Generate directory response where directory is specified in GET params.

heliport.core.utils.http.file_api_response(request, file_obj: FileObj, file_name: str, add_extension=False)

Get download response for digital object that represents a file.

The response is either a streaming file response or a JSON response of an error.

heliport.core.utils.http.file_from_description_api_response(request, file_name_callback: Callable[[FileObj], str], add_extension=False)

Get download response for digital object that represents a file.

The digital object is resolved from GET parameters of the request. This allows to download also files that are not stored in heliport directly e.g. files in subdirectories.

heliport.core.utils.http.get_streaming_file_response(file: File, filename, context: Context)

Construct a streaming response for downloading the file.

heliport.core.utils.json_ld module

class heliport.core.utils.json_ld.LdContext

Bases: object

get_context_dict()
rename(entry, offset)

Rename all dicts that contain entry and update index.

resolve_conflicts(entry, offset=0)
tentative_set(the_dict, the_key, the_value, id_for_context, reduce=None)
class heliport.core.utils.json_ld.LdContextEntry(original_key, context_id, key_counter=0)

Bases: object

property context_id
property current_key
format_key(offset=0)
property match_condition
property original_key
rename(offset=1)
tentative_set(the_dict, the_value, reduce=None)
class heliport.core.utils.json_ld.TargetDescription(name, uri, mapping_target)

Bases: tuple

mapping_target

Alias for field number 2

name

Alias for field number 0

uri

Alias for field number 1

heliport.core.utils.json_ld.lowest_matching_key(the_key, candidates)
heliport.core.utils.json_ld.reverse_context_mapping(value_descriptions, data_dict)

Yields tuples of the form (value_descriptions[i].mapping_target, data_dict[key]) where key is a key that LdContext would generate for the Target Description value_descriptions[i] given a list of TargetDescription and a dictionary of values.

heliport.core.utils.normalization module

heliport.core.utils.normalization.url_normalizer(value)

heliport.core.utils.queries module

class heliport.core.utils.queries.ListOfQuerySets(list_of_query_sets: List[QuerySet] | None = None)

Bases: object

Manage a list of Django query sets. This is useful to query different kinds of DigitalObject subclasses simultaneously.

all_digital_objects()

bring this ListOfQuerySets into a state to include all heliport.core.models.DigitalObject instances.

as_list(max_count=None)

Get first max_count many items from the query sets. max_count of None means all items.

extend(list_of_query_sets: List[QuerySet])

Add the query sets form a list of django query sets to this ListOfQuerySets.

filter(*args, **kwargs)

Filter all query sets.

heliport.core.utils.queries.at_least_one_group()

context with at least one group in the database:

with at_least_one_group():
    HeliportGroup.objects.first()  # does not return None

The group is not deleted after the context is exited.

heliport.core.utils.queries.create_empty_project(request, authentication_backend_manager=None, metadata=None)

Create an empty HELIPORT project in the database and return it.

The following parameters are already set: - owner - group - hzdr_id - category (pid namespace) - persistent_id (if configured in settings).

heliport.core.utils.queries.create_sample_project(request, authentication_backend_manager=None)

Create a sample HELIPORT project in the database and return it.

heliport.core.utils.queries.delete_by_id(digital_object_id: int | str)

Mark the digital object with specified id as deleted.

heliport.core.utils.queries.digital_objects_by_type(the_type: int | str | DigitalObject) List[QuerySet]

Returns a list of QuerySets of objects of the_type. Each QuerySet is either a filter() of digital objects or all() objects of a model.

Parameters:

the_type – DigitalObject that is the type. int or decimal str queries digital object by digital_object_id ; other string queries by persistent_id

heliport.core.utils.queries.get_or_create_from_label(label, pk, request, c_category=None, c_type=None, c_project=None, default=None)

Get digital object instance by the first applicable method.

  • get by digital object id (if pk is truthy)

  • get by label (if label uniquely identifies the digital object)

  • create new digital object with label (if label is truthy)

  • return default

Parameters:
  • label – The label of the digital object (when need)

  • pk – digital object id of the digital object (always used if valid)

  • default – the value that is returned if nothing else is applicable

  • request – needed for registering handle when creating a new object

  • c_category – Used when creating a new digital object. Sets core.models.DigitalObject.category_str. Defaults to DEFAULT_OBJECT_NAMESPACE in settings.

  • c_type – Used when creating a new digital object. Must be a core.models.DigitalObject instance. No type is set if not provided.

  • c_project – Used when creating a new digital object. Must be a core.models.Project instance. No project is added if not provided.

Returns:

a saved core.models.DigitalObject instance or the value of the default parameter.

Note: This uses core.models.digital_object_from_label_and_pk().

heliport.core.utils.queries.get_or_create_tag(project: Project, request, label: str, attribute_label: str | None = None, attribute_pk: str | int | None = None, value_label: str | None = None, value_pk: str | int | None = None)

Create a new core.models.Tag or get an existing one having label. Uses get_or_create_from_label() to get/create attribute and value. Tries to generate a color for the tag that is most different from existing colors of tags in the project.

Parameters:
  • project – project where tag should be created or gotten from

  • request – is needed to register handles for new tag, attribute or value

  • label – label to get or create new tag.

  • attribute_label – label of attribute that is set by setting tag (ignored if attribute_pk is valid)

  • attribute_pk – digital object id of attribute that is set by setting tag.

  • value_label – label of value that is set as attribute by setting tag (ignored if value_pk is valid)

  • value_pk – digital object id of value that is set as attribute by setting tag.

heliport.core.utils.queries.get_tag_attribute(label, pk, project, request)

Helper function to get the tag attribute from label or pk.

heliport.core.utils.queries.get_tag_value(label, pk, tag: Tag, project: Project, request)

helper function to get tag value form label or pk.

Important: tag.attribute should already be set. The tag should be saved before setting tag.value.

heliport.core.utils.queries.has_inferred_tag(obj: DigitalObject, tag: Tag)

helper function to test if obj has metadata that would allow to infer being tagged by tag.

heliport.core.utils.queries.inferred_tags_of(obj: DigitalObject, limit_to_project: Project | None = None)

Helper function to get tags inferred from metadata attributes.

heliport.core.utils.queries.pick_tag_color(project)

Helper function to pick a new tag color in the contest of project.

heliport.core.utils.queries.tags_of(obj: DigitalObject, limit_to_project: Project | None = None) Iterable[Tag]

Get the tags some digital object is tagged with. The result can be limited to only tags belonging to some project.

heliport.core.utils.serialization module

class heliport.core.utils.serialization.GeneralValue

Bases: object

Abstract base class for values that some property of a digital object can take on. This is an abstract class but doesn’t inherit form ABC because metaclass conflict when inheriting from it in Django models.

abstract as_html() str

Represent the value in HTML. Everything is escaped by default. If you want to use HTML tags return a django.utils.safestring.SafeString (e.g. obtained by using Django rendering functions).

abstract as_rdf() RootedRDFGraph

Represent the value in RDF.

abstract as_text() str

Represent the value as a string for the user.

heliport.core.utils.string_tools module

Helper functions to work with strings.

heliport.core.utils.string_tools.bool_from_url(potential_bool)

Parse a boolean value that originated e.g. form request.GET.get(“abc”).

heliport.core.utils.string_tools.format_byte_count(size)

Format size in bytes into human-readable unit.

heliport.core.utils.string_tools.format_time(time: float | int | str)

format time like YYYY-mm-dd HH:MM:SS.

Parameters:

time – use parse_date_time() to interpret time, interpret as POSIX time if instance of float or int (e.g. time.time() returns a POSIX time).

heliport.core.utils.string_tools.parse_date_time(string_date) datetime | None

Try different time formats to parse the string into a python datetime object.

heliport.core.utils.string_tools.remove_prefix(chars: str, prefix_options: str | List[str], raise_on_error=False) str

Remove a prefix (potentially from a list of prefixes) from chars. Note that this function should be used instead of builtin str.removeprefix as long as we support versions that don’t have this function.

Parameters:
  • chars – The string before removal of the prefix.

  • prefix_options – The first matching prefix option is removed. Supplying a string is equivalent to a list with one element.

  • raise_on_error – If False nothing happens when no prefix matches

Raises:

ValueError – If raise_on_error is True and no prefix matches

Returns:

chars but without the prefix

heliport.core.utils.string_tools.remove_trailing_newline(text: str)

Remove a single trailing newline.

CR LF, LF, and CR are tried in this order, returning after the first successful find.

heliport.core.utils.table_description module

Classes for describing a table.

This is used in the heliport.custom_views.HeliportObjectListView.

class heliport.core.utils.table_description.BoundTableAction(original_action, link=None, disabled=False)

Bases: object

An Action that is bound to some concrete object; including.

  • display_name - text on a button invoking this action

  • action_name - unique name to identify this type of action

  • style - dictionary of information how to display the action

  • link - concrete target url if this action is a “link” action

  • disabled - if this action can not be executed

Bound table actions are usually generated by TableDescription.generate_rows() via the TableAction.bind() function.

Determines if this action takes the user to an external web page. External web pages are specified starting with the protocol while internal pages are linked to via relative urls.

Determines if this action takes the user to some web page (is a “link” action).

class heliport.core.utils.table_description.TableAction(display_name, action_name, link_callback=None, action_callback=None, disabled_callback=None, style=None)

Bases: object

Action that can be executed on an object represented by a TableRow.

Properties are:

  • display_name - text on a button invoking this action

  • action_name - unique name to identify this action

  • style - dictionary of information how to display the action

  • link_callback - function to generate the link if this is a “link” action given an object

  • action_callback - function to execute the action if this is not a “link” action given an object

  • disabled_callback - function to return if the action is disabled given an object

Note that link_callback is executed before the table is shown while action_callback is executed when user requests the action

bind(obj) BoundTableAction

Generate a BoundTableAction that gets its properties from obj.

execute(obj)

Execute this action on obj.

class heliport.core.utils.table_description.TableColumnDescription(display_name, column_name, computed_property=None, style=None)

Bases: object

A column in a TableDescription including.

  • display_name - the table heading

  • column_name - the name of the attribute where this column gets its values from

  • computed_property - call this function with the obj instead of getting column_name from the obj

  • style - dictionary that contains how to present this column

Note that either column_name or computed_property must not be None

class heliport.core.utils.table_description.TableDescription

Bases: object

Class for building up the description of a table including.

  • columns - list of TableColumn

  • actions - list of TableAction

  • data - list of objects to generate one row per object

add_action(display_name, action_name, link_callback=None, action_callback=None, disabled_callback=None, style=None)

Append an action.

Parameters:
  • display_name – text on a button invoking this action

  • action_name – unique name to identify this action

  • style – dictionary of information how to display the action

  • link_callback – function to generate the link if this is a “link” action given an object; executed before table is shown

  • action_callback – function to execute the action if this is not a “link” action given an object; executed when user requests the action

  • disabled_callback – function to return if the action is disabled given an object

add_column(display_name, row_name, computed_property=None, style=None)

Append a new column.

Parameters:
  • display_name – column heading

  • row_name – name of the attribute where the column gets its value from

  • computed_property – function that computes the value of this column given an object

  • style – dict with information how to show the column

Raises:

AssertionError – if row_name and computed_property are None

execute(action_name, obj)

Execute an action.

Parameters:
  • action_name – the unique name given to an action when describing the table

  • obj – the object on which the action should be executed

Raises:

ValueError – if action_name is not a registered name of some action

generate_rows() Iterator[TableRow]

Generator of TableRow s based on data.

Raises:

ValueError – if this table has no data yet

property has_actions

True if this table has any actions.

remove_action(action_name)

Remove all actions that have action_name.

remove_column(column_name)

Removes all columns having column_name.

property row_list: List[TableRow]

Same as generate_rows() but is a list.

class heliport.core.utils.table_description.TableRow(pk, data: Iterable, actions: Iterable[BoundTableAction] | None = None, digital_object_id=None)

Bases: object

A row in a TableDescription including.

  • pk - A unique identifier for this row; used to find the relevant object when an action is triggered

  • actions - List of BoundTableAction that can be executed on this row

  • data - List of values for this row; one value per column

  • digital_object_id - Use heliport.models.DigitalObject specific features; in the heliport.custom_views.HeliportObjectListView tags are editable for this DigitalObject

Rows are generated by TableDescription.generate_rows()

property has_actions

True if this column has any actions.

heliport.core.utils.url module

url helper functions.

heliport.core.utils.url.url_encode(url)

Remove characters not allowed in turtle encoding from the url. Swap host for www.example.org and protocol for https if they contain erroneous (not allowed) characters. Other characters are removed by url encoding them.

heliport.core.utils.version module

Provides the HELIPORT version as a string and as a numerical tuple.

Module contents

This module contains generally helpful functions used throughout HELIPORT.