API reference¶
Contents
Introduction¶
First, a few remarks to the code documentation. Classes start with an upper case letter and are written in CamelCase. Underscores show inheritance (not always, e.g. controllers). Functions are all lowercase, with underscores seperating words. Variables start with a lowercase letter (except for one-letter variables). They can contain underscores (like functions) or continie with camelCase.
Controller classes start with letter ‘C’ View classes start with letter ‘V’
Core functionality¶
List operations¶
-
tagit.
fst
(lst)¶
-
tagit.
snd
(lst)¶
-
tagit.
head
(lst)¶
-
tagit.
tail
(lst)¶
-
tagit.
unique
(lst)¶
-
tagit.
union
(*args)¶
-
tagit.
difference
(lstA, lstB)¶
-
tagit.
split
(callback, lst)[source]¶ Split the list lst via boolean return value of callback. True is returned first.
Settings¶
-
class
tagit.
Settings
[source]¶ Less strict dictionary for missing settings.
Return None instead of raising KeyError if a key is not in the settings dictionary.
The settings dictionary looks like this:
{ "section" : { "config" : value, ... }, ... }
This class makes the dictionary keys “section” and “config” optional.
-
tagit.
get_config
(settings, *args)[source]¶ Traverse the settings dictionary and subdict’s args are (section, [<more dicts>,] key, default value)
-
class
tagit.bindings.
Binding
[source]¶ Handle keybindings.
A keybinding is a set of three constraints: * Key code * Inclusive modifiers * Exclusive modifiers
Inclusive modifiers must be present, exclusive ones must not be present. Modifiers occuring in neither of the two lists are ignored.
Modifiers are always lowercase strings. Additionally to SHIFT, CTRL and ALT, the modifiers “all” and “rest” can be used. “all” is a shortcut for all of the modifiers known. “rest” means all modifiers not consumed by the other list yet. “rest” can therefore only occur in at most one of the lists.
Usage example:
>>> # From settings, with PGUP w/o modifiers as default >>> Binding.check(evt, self.settings.trace("bindings", "browser", "page_prev", Binding.simple(Binding.PGUP, None, Binding.ALL)))
>>> # ESC or CTRL + SHIFT + a >>> Binding.check(evt, Binding.multi((Binding.ESC, ), (97, (Binding.CTRL, Binding.SHIFT), Binding.REST))))
Console¶
Debugging¶
-
tagit.debug.
debug
(local, abort=False)[source]¶ Enter a debug shell.
In your code, place the following statement
>>> debug(locals())
to enter the debug shell at that point. You’ll have all local variables available, plus some extra modules (see below).
To get the current stack trace, call
tr.print_stack()
.Extra modules: code, traceback (tr), os, sys, itertools, copy, time.
Model¶
-
class
tagit.model.
DataModel
(settings, path=None, meta_adapter=None)[source]¶ Open a database from the file path or memory (if None, the default, or empty). If a path is given but does not exist, a new database will be created. Version constraints on existing databases may apply.
-
has_file_connection
()[source]¶ Return True if the database is stored in a file. As opposed to in-memory database.
-
index_dir
(path, recursive=False, sync_method='set', insert_only=False, update_only=False)[source]¶ Index or reindex files in path. The database will not be saved!
-
index_file
(path, sync_method='set', insert_only=False, update_only=False)[source]¶ Index or reindex path. The database will not be saved!
-
index_files
(files, sync_method='set', insert_only=False, update_only=False, common_root=None)[source]¶ Index or reindex may files. The database will not be saved.
-
load_database
(path=None)[source]¶ Load a database from path. If path is None, the database is created in the memory. If path does not exist, a new database is created.
-
merge
(other, sync_method='union')[source]¶ Merge this database into other. The other database will be changed, not this instance. Changes are not commited. Indexed images are merged. If an image is indexed in both, the basic information is taken from the later one. Tags are always merged according to sync_method. SYNC_SET then means to use the information of this database.
-
query
(tokens=None)[source]¶ Return all images which satisfy all constraining tokens. Tokens is a list of tags (exact match).
-
remove_dir
(path, recursive=False)[source]¶ Remove images in path from the database. Traverses subdirectories if recursive is set. path has to be a directory.
-
save
(path=None)[source]¶ Save changes to the database.
If path is set, creates a new database with the current content at that location. The new database is returned, the old one is neither changed (i.e. reverted) nor saved.
If path is not set, changes to the database are commited.
If ‘write-through’ is True the changes are saved to the file as well (-> update_files(sync_method=SYNC_SET))
-
sync_dir
(path, recursive)[source]¶ Synchronize all files in path with the database. Creates an UNION of file and database and writes to both. Files will be changed, database not saved!
-
sync_file
(path)[source]¶ Synchronize file path with the database. Creates an UNION of file and database and writes to both. Files will be changed, database not saved!
-
sync_files
(files)[source]¶ Synchronize all files in files with the database. Creates an UNION of file and database and writes to both. Files will be changed, database not saved!
-
update_dir
(path, recursive=False, sync_method='set')[source]¶ Update all files in path with information from the database. If path is a directory, all files in that directory are updated. If path is a directory and recursive is true, all subdirectories will be changed as well. Files will be changed.
-
-
class
tagit.model.db_path.
DBpath
(settings, database)[source]¶ Path operations on database entries.
-
exists
(path)[source]¶ Return whether path exists in the database. path should be a file. For directories, the result is always False because directories are not mapped in the database.
-
getdir
(path)[source]¶ List contents of directory path. path must be a directory. Files and directories are listed, without ‘.’ and ‘..’
-
is_prefix
(prefix, path)[source]¶ Return True if path is a subdirectory of prefix or a file within prefix.
-
Tags¶
The Tags baseclass and interface.
Tags are keywords which can be attached to images. Tags can be retrieved (get) and modified (add, set, remove). Other actions may be available.
Add all tags to each of images.
Search and remove tags without images.
Return tags of image.
Return all tags in the database.
Return all images which satisfy all constraining tags.
Remove all of tags from all of images.
Remove all tags from each of images.
Rename from old tags to new.
Set tags of images to be exactly tags.
Bases:
object
Tag operations based on a SQLite database.
The database link is to be passed as conn. Database changes are not saved. It’s assumed that the basic scheme is present (i.e. image table).
Add all tags to each of images. images is a list of images (path). If an image is not in the database, it is ignored. tags is a list of strings. If a tag is not in the database, it is added.
Search and remove tags without images. This operation may take some time.
Return a dict with frequency of each tag. Tags are keys, values are the number of occurrences. If include is not None, only images of this list are considered. If exclude is not None, images of this list are not considered.
Return all images which satisfy all constraining tags.
Rename a tag from source to target. source and target are the tag names. If target exists, the tags will be merged.
Bases:
tagit.model.tags.Tags
Tags-like interface to EXIF/IPTC metadata.
A meta_adapter is required to do the IPTC operations. Some operations are not meaningful and return dummy values.
MetaAdapter¶
-
class
tagit.model.meta_adapter.
MetaAdapter
[source]¶ Handle IPTC/EXIF reads and writes to files.
-
add
(path, tags)[source]¶ Add tags to IPTC of image path. path has to be a writeable file (not checked). Image data is written. tags is added to the existing tags.
-
get
(path)[source]¶ Read IPTC keywords from path. Return a list of tags. path has to be a readable file (not checked).
Return the image author.
-
get_thumbnail
(path)[source]¶ Return the thumbnail embedded in image path. path has to be a readable file.
-
-
class
tagit.model.meta_adapter.
MetaAdapter_PyExiv2
[source]¶ Bases:
tagit.model.meta_adapter.MetaAdapter
Makes use of the pyexiv2 library to manipulate files.
Extractor¶
-
class
tagit.model.extractor.
Extractor
[source]¶ Return a list of automatically extracted tags from image.
-
class
tagit.model.extractor.
Extractor_Constant
[source]¶ Bases:
tagit.model.extractor.Extractor
Constant information, user-provided.
-
class
tagit.model.extractor.
Extractor_Date
[source]¶ Bases:
tagit.model.extractor.Extractor
Date information: * Year : Year (4 digit) * Day : Day of month * Month : Month (int 1-12 or name Jan-Dec) * Weekday : Weekday (int 1-7 (iso) or name Mon-Sun) * Hour : Hour (int) * Minute : Minute (int) * Day/Night : day or night
-
class
tagit.model.extractor.
Extractor_Photometrics
[source]¶ Bases:
tagit.model.extractor.Extractor
Image and camera metrics: * Resolution : Image resolution (width, height) * Exposure : Exposure time (float, seconds, inverted) * Focal length : Reported focal length or 35mm equivalent (float, mm) * Aperture : Aperture (‘F’ + float) * ISO : ISO level (int)
-
class
tagit.model.extractor.
Extractor_Path
[source]¶ Bases:
tagit.model.extractor.Extractor
Path information: * mime : Mime type (image/jpeg, ...) * extension : File extension (jpg, png, ...) * dir_after : Folder after specified path * dir_last : Image’s parent directory * dir_after_call: Folder after search root
strip_date: Remove leading or trailing date information
-
class
tagit.model.extractor.
Extractor_Aggregator
(children=None)[source]¶ Bases:
tagit.model.extractor.Extractor
Combine multiple Extractor instances into one.
-
class
tagit.model.extractor.
Extractor_Aggregator_all
(children=None)[source]¶ Bases:
tagit.model.extractor.Extractor_Aggregator
Aggregate all known Extractors.
Thumbnailer¶
-
class
tagit.model.thumbnail.
Thumbnailer
[source]¶ Interface for thumbnail operations.
Thumbnailer defines an interface for any thumbnail handling method. It implements creation but remains abstract for get and set.
-
create
(image, resolution=(400, 400))[source]¶ Create a thumbnail of image and return the Image object.
-
get
(image, resolution=(400, 400))[source]¶ Search for a thumbnail of image. Return the path (file-based) or object (embedded) image. Return None if no thumbnail was found.
-
-
class
tagit.model.thumbnail.
Thumbnailer_Chain
(*args)[source]¶ Bases:
tagit.model.thumbnail.Thumbnailer
Link several Thumbnailers together.
get: The first match is returned. set: Applied on all childs.
-
class
tagit.model.thumbnail.
Thumbnailer_FS
(root)[source]¶ Bases:
tagit.model.thumbnail.Thumbnailer
Read and write thumbnails from/to the file system. Clones the original file structure within a root directory.
-
class
tagit.model.thumbnail.
Thumbnailer_FS_Flat
(conn, root)[source]¶ Bases:
tagit.model.thumbnail.Thumbnailer
Read and write thumbnails from/to the file system. All thumbnails go to the same directory, with a generic file name. The database links the image and its thumb file.
-
class
tagit.model.thumbnail.
Thumbnailer_Exif
(meta_adapter)[source]¶ Bases:
tagit.model.thumbnail.Thumbnailer
Read and write the exif thumbnail
-
class
tagit.model.thumbnail.
Thumbnailer_Database
(conn)[source]¶ Bases:
tagit.model.thumbnail.Thumbnailer
Read and write thumbnails from/to the database.
Program¶
-
class
tagit.program.program.
Program
(notification_clbk=None)[source]¶ Program State-Machine:
States: * uninitialized * initialized * running * paused * stopped
Transitions: * uninitialized -> initialized (init) * {initialized, stopped} -> uninitialized (unload) * {initialized, stopped} -> running (start) * {running, paused} -> stopped (stop) * running -> paused (pause) * paused -> running (resume)
User interface¶
Controller¶
-
class
tagit.controller.controller.
Controller
(widget, settings, parent=None, **kwargs)[source]¶ Controller base class. Any controller receives a dict with the settings, a data model and a parent.
The parent being None implies that the object is the root controller.
The controller supports a simple event meachanism. You can bind callbacks on events on a controller object and later dispatch the event. Note that dispatching an event only affects callback bound to the same controller instance.
Similar to the event mechanism, data can be requested from controllers, announced via the rbind function.
>>> def callback_fu(arg1, arg2): pass >>> >>> c = Controller() >>> c.bind(event_name=callback_fu) >>> c.dispatch('event_name', arg1, arg2) >>> c.rbind(request_name=callback_fu) >>> c.request('request_name', arg1, arg2) # Returns [] >>> Controller().dispatch('event_name', arg1, args2) # Doesn't do anything >>> Controller().request('request_name', arg1, args2) # Returns []
-
dispatch
(event, *args, **kwargs)[source]¶ Dispatch an event. Extra arguments after the event will be passed to the event handler>
-
-
class
tagit.controller.controller.
DataController
(widget, model, settings, parent=None, **kwargs)[source]¶ Bases:
tagit.controller.controller.Controller
A controller with access to a model.
View¶
Kivy widgets will be extended by the following three functions. They allow easy creation of the Controller instances.
-
tagit.view.wx_adapter.
on_parent
(obj, self, parent)[source]¶ Default behaviour if the parent of a widget is changed. Calls on_parent of all childs, even though the direct parent has not changed. This behaviour is usefull to pass down widget tree changes to lower widgets.
-
tagit.view.wx_adapter.
get_root
(self)[source]¶ Traverse the widget tree upwards until the root is found. Note that this is not the same as basics.get_root (or app.root from a debug shell) unless the calling widget is attached to the main widget tree. Specifically, if a widget or any of its parents is created but not yet attached.
Main¶
-
class
tagit.controller.main.
CMainWindow
(widget, settings, parent=None, **kwargs)[source]¶ Bases:
tagit.controller.controller.Controller
MainWindow controller.
Receives the key events and passes them on.
Browser¶
-
class
tagit.controller.browser.
CBrowser
(widget, model, settings, parent=None, **kwargs)[source]¶ Bases:
tagit.controller.controller.DataController
-
delete
()[source]¶ Delete selected images from the database. Not to be confused with the ‘exclusive’ filter / remove selected.
-
edit_tag
(original, modified)[source]¶ Remove tags from images. Original and modified are strings, split at TAGS_SEPERATOR. Tags are added and removed with respect to the difference between those two variables.
-
on_key_up
(wx, (code, key))[source]¶ Watch out for those modifiers. Can receive some ups when modifier pressed at app start
-
on_results_changed
(filter_, images, frame)[source]¶ Called when the set of images to be displayed was changed.
-
Filter¶
-
class
tagit.controller.filter.
CFilter
(widget, model, settings, parent=None, **kwargs)[source]¶
-
class
tagit.view.filter.
VFilter
(**kwargs)[source]¶ Bases:
kivy.uix.boxlayout.BoxLayout
A row of filter tokens (i.e. some filter text) and its management.
A filter is used to search in the image database. The filter consists of several tokens. Each token adds a search constraint.
Tokens can be added, changed and removed. The filter can be applied to an image source. This has effects on other parts of the UI, namely the Browser.
Sideboxes¶
Bases:
kivy.uix.gridlayout.GridLayout
Load configured sideboxes, present them stacked.
Set the controller factory. Reinitializes parts of the browser.
Re-initialize the Sideboxes to a new mainWidget.
-
class
tagit.controller.sidebox.db_management.
CSidebox_DB_Management
(widget, model, settings, parent=None)[source]¶ Bases:
tagit.controller.controller.DataController
A set of functions to manage the model.
-
class
tagit.view.sidebox.db_management.
VSidebox_DB_Management
(**kwargs)[source]¶ Bases:
kivy.uix.gridlayout.GridLayout
,tagit.view.sidebox.sidebox.VSidebox
A bunch of buttons to control the database.
Bases:
tagit.controller.controller.DataController
Base class for tag-oriented sideboxes.
Bases:
tagit.controller.sidebox.tags.CSidebox_Tags
Give a recommendation which tags to include next in the filter.
Update the sidebox.
Bases:
kivy.uix.label.Label
,tagit.view.sidebox.sidebox.VSidebox
Show tags to include next in the filter.
Bases:
tagit.controller.sidebox.tags.CSidebox_Tags
Show tags if images displayed. Highlight tags of selected images and the cursor.
Update the sidebox widget.
Bases:
kivy.uix.label.Label
,tagit.view.sidebox.sidebox.VSidebox
Show tags if images displayed. Highlight tags of selected images and the cursor.
Bases:
tagit.controller.controller.DataController
List tags of selected images.
Update the sidebox widget.
Bases:
kivy.uix.label.Label
,tagit.view.sidebox.sidebox.VSidebox
List tags of selected images.
Bases:
tagit.controller.controller.DataController
List tags of the image under the cursor.
Update the sidebox widget.
Bases:
kivy.uix.label.Label
,tagit.view.sidebox.sidebox.VSidebox
List tags of the image under the cursor.
-
class
tagit.controller.sidebox.pgm.
CSidebox_Program_Control
(widget, model, settings, parent=None, main_widget=None)[source]¶ Bases:
tagit.controller.controller.DataController
A set of functions to manage the model.
Dialogues¶
-
class
tagit.view.dialogues.dialogue.
Dialogue
(**kwargs)[source]¶ Bases:
kivy.uix.popup.Popup
Popup dialogue with OK and Cancel buttons.
Use like below:
>>> dlg = Dialogue() >>> dlg.bind(on_ok=....) >>> dlg.bind(on_cancel=...) >>> dlg.open()
-
class
tagit.view.dialogues.
TextInputDialogue
(**kwargs)[source]¶ Bases:
tagit.view.dialogues.dialogue.Dialogue
Dialogue with a single line text input field.
keyboard_ctrl is an object supporting request_exclusive_keyboard and release_exclusive_keyboard for exclusive keyboard access. Usually the root_widget.
Pass the default text as text.
>>> TextInputDialogue(text='Hello world', keyboard_ctrl=root_widget).open()
In case of touch events, they need to be inhibited to change the focus.
>>> FocusBehavior.ignored_touch.append(touch)
-
class
tagit.view.dialogues.
LabelDialogue
(**kwargs)[source]¶ Bases:
tagit.view.dialogues.dialogue.Dialogue
Dialogue with some text.
Set the default text as text.
>>> LabelDialogue(text='Hello world').open()
-
class
tagit.view.dialogues.
FilePickerDialogue
(**kwargs)[source]¶ Bases:
tagit.view.dialogues.dialogue.Dialogue
Dialogue with a file browser to select a file.
Pass the default text as text.
>>> FilePickerDialogue(text='Hello world').open()
-
class
tagit.view.dialogues.
DirPickerDialogue
(**kwargs)[source]¶ Bases:
tagit.view.dialogues.dialogue.Dialogue
Dialogue with a file browser to select a directory.
Pass the default text as text.
>>> DirPickerDialogue(text='Hello world').open()
-
class
tagit.view.dialogues.
FileCreatorDialogue
(**kwargs)[source]¶ Bases:
tagit.view.dialogues.dialogue.Dialogue
Dialogue with a file browser to select a file.
Pass the default text as text.
>>> FileCreatorDialogue(text='Hello world').open()
-
class
tagit.view.dialogues.
ErrorDialogue
(**kwargs)[source]¶ Bases:
tagit.view.dialogues.dialogue.Dialogue
Dialogue with some text.
Set the default text as text.
>>> try: >>> ... >>> except Exception, e: >>> ErrorDialogue(text=e.message).open()
-
class
tagit.view.dialogues.
BindingsDialogue
(bindings, *args, **kwargs)[source]¶ Bases:
tagit.view.dialogues.dialogue.Dialogue
Dialogue with some text.
Set the default text as text.
Tools¶
- Similar case
- Similar word (typo: common errors, change of two letters)
- Synonym
- Prefix (one word is subset of the other)
- Similar results
- One is a subset of the other (w.r.t images)
- Tag statistics:
- Tag Histogram
- correlation btw. tags (matrix, top-N list)
Goes through all tags and queries the user if it should be merged with a similar one.
The user can choose the following actions for each pair of tags: * l Merge to the left; Keeps the left tag, removes the right one * r Merge to the right; Keeps the right tag, removes the left one * n Don’t merge, keep both tags * s Skip this pair, ask later * q Quit
-
tagit.tools.
images_export
(images, target, method=None, keep_structure=False, simulate=False, verbose=False, overwrite=False)[source]¶ Export images to a target directory.
Method can be either of: * symlink Create symlinks in the target directory * hardlink Create hardlinks in the target directory * copy Copy the images to the target directory
If keep_structure is True, the original directory structure is recreated starting after the shared prefix of images. Otherwise, the images will be exported to the target folder directly. If so, naming conflicts are handled by adding a sequence number to the image name. E.g. /foo/image.jpg, /bar/image.jpg -> export/image.jpg, export/image-1.jpg
If simulate is True, path translations are returned (src, trg) but no action is actually taken.