Contacto package

Exports

contacto.main()

CLI entrypoint, initializes the Click main command

Module contacto.storage

The data layer containing all contact data.

Contains objects forming the contact hierarchy: Group, Entity, Attribute; and the top-most storage container, Storage.

The contact storage is a tree, rooted at the Storage object, and branching through Groups, Entities and Attributes. The tree members have parent references towards the root, which wraps around an SQLite database connection.

Storage manipulation is transactional. For all transformations a safe variant is provided, <transform>_safe, which handles a single transaction. Unsafe transformations should be wrapped in a transaction manually.

class contacto.storage.Attribute(aid, name, dtype, data, parent)

Bases: contacto.storage.StorageElement

The leaf of the storage tree containing contact data.

An Attribute has a name, data and data type.

There are 4 types of Attribute data, listed in contacto.helpers.DType: BIN(ary), TEXT, A(ttribute) X-REF(erence) and E(ntity) X-REF(erence).

AXREF attributes may form an oriented graph which must not form loops. Operations Create, Update and Merge are checked for loop induction.

X-REF attributes register at their targets and are deleted when their target is deleted. Hence deleting an Entity or Attribute may cascade. These registrations are properly handled on mutations.

delete()

Deletes Attribute from tree and DB (may cascade!)

get()

Gets the actual data the Attribute references.

For non-XREF Attributes this returns own data. For XREFs, the REF chain is traced to a non-REF source. This may be an Entity or a non-XREF Attribute.

Returns

resolved type and data

Return type

(class:contacto.helpers.DType, Union[str, bytes])

merge(other)

Merges another Attribute into self, checked for loops.

read()

Updates Attribute data from the DB.

ref_register()

Registers a reference to its target.

ref_unregister()

Unregisters a reference from its target.

rotate()

Rotates the attribute in a logrotate way.

A single Attribute named “A” is copied into one named “A_1”. If “A_1” already exists, it is copied into “A_2” and so on. This helps maintain an attribute value history.

rotate_safe()

A single-transaction variant of rotate.

update()

Saves Attribute data into the DB, checked for loops.

class contacto.storage.Entity(eid, name, thumbnail, parent)

Bases: contacto.storage.StorageElement

The Entity tree element that carries Attributes.

Entity hosts an Attribute dictionary, its name and an optional binary thumbnail (image).

create_attribute(name, dtype, data)

Creates a new Attribute for this Entity.

Note that Attribute names are unique in an Entity.

Parameters
  • name (str) – Attribute name

  • dtype (class:contacto.helpers.DType) – data type

Returns

created thumbnail

Return type

class:contacto.storage.Attribute

create_attribute_safe(name, dtype, data)

A single-transaction variant of create_attribute.

delete()

Deletes Entity (and its Attributes) from DB and tree.

merge(other)

Merges another Entity into self.

read()

Reads Entity data from DB.

thumbnail_from_attr()

Sets a thumbnail from a “thumbnail” attribute.

For convenience, a “thumbnail” attribute may carry an entity’s thumbnail. This is a notification hook to try querying it for data.

update()

Saves Entity data to DB.

class contacto.storage.Group(gid, name, parent)

Bases: contacto.storage.StorageElement

An entity group with unique name and pointer to the root storage.

A Group hosts Entities in a name-indexed dictionary.

create_entity(name)

Creates a new Entity in this Group.

Note that Entity names are unique in a Group.

Parameters

name (str) – Entity name

Returns

created Entity

Return type

class:contacto.storage.Entity

create_entity_safe(name)

A single-transaction variant of create_entity.

delete()

Deletes Group (and its Entities) from tree and DB.

merge(other)

Merges another Group into self.

read()

Reads Group from DB.

update()

Saves Group data to DB.

class contacto.storage.Storage(db_file)

Bases: object

The root of the storage tree and wrapper of the DB connection.

Provides communication with an SQLite database and reads the tree from it. A Storage object is needed for all of Contacto’s functionality.

Access its Group children with the “groups” name-indexed dictionary.

create_db()

Creates DB structure using the prepared DML

create_group(name)

Creates a new Group. Mind that Group names are unique in a DB.

Parameters

name (str) – Group name

Returns

created Group

Return type

class:contacto.storage.Group

create_group_safe(name)

A single-transaction variant of the create_group method

elem_from_refid(dtype, elem_id)

Returns an Entity or Attribute from its database ID.

The type of element is decided by a DType XREF specifier. This method is used to find the target of a XREF from ID only.

Parameters
  • dtype (class:contacto.helpers.DType) – type of element (XREF spec)

  • elem_id (int) – ID of the element

Returns

tree element if one is found

Return type

Union[None, class:contacto.storage.StorageElement]

get_attribute(group_name, entity_name, name)

Gets an Attribute by its name and the names of its parents.

Parameters
  • group_name (str) – Group name

  • entity_name (str) – Entity name

  • name (str) – Attribute name

Returns

found Attribute or None, if one isn’t found

Return type

Union[class:contacto.storage.Attribute, None]

get_entity(group_name, name)

Gets an Entity by its name and Group name.

Parameters
  • group_name (str) – Group name

  • name (str) – Entity name

Returns

found Entity or None, if one isn’t found

Return type

Union[class:contacto.storage.Entity, None]

get_from_rspec(p_rspec)

Gets a tree element from a parsed refspec. Parsed refspec is a triplet of None|element names scoping the tree.

Parameters

p_rspec (tuple) – parsed refspec

Returns

tree element if one is found

Return type

Union[None, class:contacto.storage.StorageElement]

get_group(name)

Gets a Group by its name.

Parameters

name (str) – Group name

Returns

found Group or None, if one isn’t found

Return type

Union[class:contacto.storage.Group, None]

reload()

Discards any existing storage tree and reads it anew from DB.

Constructs the entire tree including Attributes.

set_foreign_keys(on)

Turns foreign keys ON or OFF.

Parameters

on (bool) – FK mode

class contacto.storage.StorageElement(parent, name)

Bases: abc.ABC

An abstract class generalizing Groups, Entities and Attributes.

These tree elements have scope-unique names and parent references. Traversal through the tree is based on names.

abstract delete()

Recursively deletes the subtree rooted at this element.

delete_safe()

Single-transaction delete.

Returns

success

Return type

bool

get_conn()

Gets database connection from the root.

Returns

database connection

Return type

class:sqlite3.Connection

get_storage()

Gets the tree root using upward traversal.

Returns

tree root

Return type

class:contacto.storage.Storage

abstract merge(other)

Merges another element of the same type into self.

This deletes the other element and updates self.

merge_safe(other)

Single-transaction merge.

Returns

success

Return type

bool

abstract read()

Loads all element data from the database.

abstract update()

Saves all element data to the database.

May modify other (linked) elements.

update_safe()

Single-transaction update.

Returns

success

Return type

bool

Module contacto.serial

Serialization features: import, export, human-readable dumping.

class contacto.serial.Serial(storage)

Bases: object

Serialization handler, accepts a data storage.

dump(direct=False, lscope=<Scope.GROUP: 1>, rscope=<Scope.ATTRIBUTE: 3>)

Dumps storage in a human-readable form to stdout.

This dump type may be scoped from the left if a specific element is directly requested (lscope), such as with a G/E refspec.

Right scope (rscope) cuts data from the right (starting with attrs.). It is possible to dump entities only (<E, E>), entities and attributes (<E, A>) or just attribute values (<AV, A>)…

Passing the direct flag causes attributes to be printed without names. Desirable when printing a single-scoped attr’s value (<AV, A>).

Parameters
  • direct (bool, optional) – do not print attribute names

  • lscope (class:contacto.helpers.Scope, optional) – leftmost tree scope to export

  • rscope (class:contacto.helpers.Scope, optional) – rightmost tree scope to export

export_yaml(file, max_scope=<Scope.ATTRIBUTE: 3>, max_bin_size=0)

Exports storage in YAML format into a file.

Maximum scope may be provided to cut away attributes or even entities. If maximum binary size is set, binary data bigger than this limit will be dumped into files in the dump file’s directory and linked by refs.

Parameters
  • file (class:io.TextIOWrapper) – file to dump to

  • max_scope (class:contacto.helpers.Scope, optional) – rightmost tree scope to export

  • max_bin_size (int, optional) – maximum binary data size to inline

Returns

success

Return type

bool

import_yaml(file)

Imports YAML data from a file into the storage.

Parameters

file (class:io.TextIOWrapper) – YAML file

Returns

success

Return type

bool

Module contacto.view

Module used for searching within the storage tree.

It creates induced subgraphs from the tree by filtering out elements. These subgraphs may then be viewed as search results.

class contacto.view.View(storage)

Bases: object

A read-only representation of a Storage slice.

Provides a “groups” member that mimics that of the Storage object. Therefore the View itself is a read-only storage root and may be passed to contexts that do not modify the tree, such as serialization.

To filter the tree, set your filters first using the provided methods.

empty()

Tests if no filters have been set

Returns

True if no filters are set

Return type

bool

filter()

Generates an induced subgraph from the current tree using the saved filters

reset()

Resets the View back to the full tree, discarding any prior scoping.

Also discards any set filters.

set_attr_value_filter(needle, fuzzy)

Sets a string needle that matches on a TEXT Attribute’s value.

Non-TEXT Attributes are not considered a match. May be specified both as exact and fuzzy search. An empty string is not considered a valid value filter.

Parameters
  • needle (str) – search needle

  • fuzzy (bool) – use fuzzy search for the needle

set_index_filters(filters)

Sets string needles that match exactly on an element’s name.

Parameters

filters (tuple) – parsed generic refspec (G/E/A)

set_name_filters(filters)

Sets string needles that match fuzzily on an element’s name.

This means a case-insensitive substring search. Example: “abc” matches an element named “zAbcDeF”

Parameters

filters (tuple) – parsed generic refspec (G/E/A)

set_value_predicates(preds)

Sets generic predicates that determine if an element is matched.

Receives 3 predicates, one for each tree element type. This method may be called multiple times to stack multiple predicates on a single element. Stacked predicates are joined with logical AND.

Example predicates:

L(attr): attr is binary

L(entity): entity has thumbnail

Parameters

preds (tuple) – element predicates

Module contacto.helpers

Support structures and functions.

class contacto.helpers.DType

Bases: enum.IntEnum

Attribute data types.

AXREF = 3
BIN = 2
EXREF = 4
TEXT = 1
is_xref()

True if the data type is a reference.

class contacto.helpers.Scope

Bases: enum.IntEnum

Level in the contact hierarchy.

ATTRIBUTE = 3
ATTR_VAL = 4
ENTITY = 2
GROUP = 1
from_str = <bound method Scope.from_str of <enum 'Scope'>>
contacto.helpers.attr_val_str(attr, direct)

A human-readable representation of attribute data.

Parameters
  • attr (class:contacto.storage.Attribute) – contact attribute

  • direct (bool, optional) – attribute name won’t be printed

Returns

string representation

Return type

str

contacto.helpers.attrdata_to_bytes(dtype, attr_data)

Packs attribute data into a binary form (for database storage).

Parameters
  • dtype (class:contacto.helpers.DType) – data type

  • attr_data (Union[bytes, str, int]) – attribute data

Returns

packed attribute data

Return type

bytes

contacto.helpers.bytes_to_attrdata(dtype, bin_data)

Parses attribute data from its binary-packed form.

Parameters
  • dtype (class:contacto.helpers.DType) – data type

  • bin_data (bytes) – data in binary form

Returns

parsed attribute data

Return type

Union[bytes, str, int]

contacto.helpers.dump_lscope(index_filters)

Leftmost tree scope to apply when dumping contacts.

This corresponds to the leftmost directly specified element

Parameters

index_filters (tuple) – parsed refspec

Returns

leftmost scope

Return type

class:contacto.helpers.Scope

contacto.helpers.fmatch(needle, haystack)

A case-insensitive substring search.

contacto.helpers.get_plugins()

Uses pkgutil to find plugins among top-level modules.

Returns

found plugins

Return type

dict

contacto.helpers.parse_ref(rspec)

Parse a refspec into a reference and its type (entity or attribute).

Requires a fully-specified refspec: G/E or G/E/A

Parameters

rspec (str) – text refspec

Raises

Exception – the refspec is not a valid entity/attribute reference

Returns

reference type and parsed refspec

Return type

(class:contacto.helpers.DType, tuple)

contacto.helpers.parse_refspec(rspec)

Parses a generic text refspec into its tuple form.

A generic refspec may have any parts omitted as long as it has at most 3.

Therefore /E/, G//A, //A, G/E/A are all valid refspecs Omitted parts are replaced with None

Parameters

rspec (str) – text refspec

Returns

parsed refspec

Return type

tuple

contacto.helpers.parse_valspec(value)

Parses an attribute value specifier (used in data input/import).

Parameters

value (str) – value specifier

Returns

parsed attr value with its type

Return type

(class:contacto.helpers.DType, Union[bytes, str, tuple])

contacto.helpers.print_error(err)

Prints a formatted error message to stderr.

contacto.helpers.print_warning(warn)

Prints a formatted warning message to stderr.

contacto.helpers.refspec_scope(p_rspec)

The actual tree (depth) scope a refspec directly represents.

A not-fully-specified scope such as /E/ represents nothing.

Fully-specified scopes such as G, G/E and G/E/A do.

Parameters

p_rspec (tuple) – parsed refspec

Returns

refspec scope

Return type

class:contacto.helpers.Scope

contacto.helpers.run_plugins(storage, whitelist=[])

Runs found and selected plugins.

Parameters
  • storage (class:contacto.storage.Storage) – used storage

  • whitelist (list, optional) – allowed plugin names

Returns

lists of successful and failed run plugins

Return type

(list, list)

contacto.helpers.size_str(blob)

Gets binary data size in human-readable units.

Parameters

blob (bytes) – binary data

Returns

data size with units

Return type

str

contacto.helpers.validate_img(data)

Checks if data are an image.

Parameters

data – binary data

Returns

true if data is an image

Return type

bool

Module contacto.cli

CLI interface using Click.

contacto.cli.entity_set(storage, gname, ename, recursive)

Creates or update an entity.

Parameters
  • storage (class:contacto.storage.Storage) – used storage

  • gname (str) – group name

  • ename (str) – entity name

  • recursive (bool) – create group if non-existent

Returns

created entity

Return type

class:contacto.storage.Entity

contacto.cli.group_set(storage, gname)

Creates or update a group.

Parameters
  • storage (class:contacto.storage.Storage) – used storage

  • gname (str) – group name

Returns

created group

Return type

class:contacto.storage.Group

contacto.cli.main()

CLI entrypoint, initializes the Click main command

contacto.cli.validate_full_refspec(ctx, param, value)

Validates a full refspec (specified from the left).

Parameters
  • ctx (class:click.Context) – Click context

  • param (dict) – Click params

  • value (str) – refspec

Returns

parsed refspec

Return type

list

contacto.cli.validate_refspec(ctx, param, value)

Validates a generic refspec (without restrictions).

Parameters
  • ctx (class:click.Context) – Click context

  • param (dict) – Click params

  • value (str) – refspec

Returns

parsed refspec

Return type

list

Module contacto.gui

A Qt5 frontend for Contacto

For now it it read-only.

class contacto.gui.GUI

Bases: object

Wrapper for all GUI logic

action_about()

Qt action: display About dialog

action_export()

Qt action: export DB into a YAML file

action_import()

Qt action: import a YAML file

action_open()

Qt action: open new DB

init_tree()

Loads contact data into the tree widget

open(dbname)

Open a new Storage around a filename

Parameters

dbname (str) – name of database holding raw data

run()

Object entry-point (open and run)

contacto.gui.main()

GUI entry-point