trilium_alchemy.core.note#

Class index#

Canonical

Note

Encapsulates a note and provides a base class for declarative notes.

Mixin

Reusable collection of attributes, children, and fields (note_id, title, type, mime) which can be inherited by a Note.

Symbols#

class trilium_alchemy.core.note.Note(title: str = 'new note', note_type: str = 'text', mime: str = 'text/html', parents: collections.abc.Iterable[Note | Branch] | Note | Branch | None = None, children: collections.abc.Iterable[Note | Branch] | None = None, attributes: collections.abc.Iterable[Attribute] | None = None, content: str | bytes | IO | None = None, note_id: str | None = None, template: Note | type[Note] | None = None, session: Session | None = None, **kwargs)#
Parameters:
title: str = 'new note'

Note title

note_type: str = 'text'

Note type, one of: "text", "code", "file", "image", "search", "book", "relationMap", "render"

mime: str = 'text/html'

MIME type, needs to be specified only for note types "code", "file", "image"

parents: collections.abc.Iterable[Note | Branch] | Note | Branch | None = None

Parent note/branch, or iterable of notes/branches (internally modeled as a set)

children: collections.abc.Iterable[Note | Branch] | None = None

Iterable of child notes/branches (internally modeled as a list)

attributes: collections.abc.Iterable[Attribute] | None = None

Iterable of attributes (internally modeled as a list)

content: str | bytes | IO | None = None

Text/binary content or file handle

note_id: str | None = None

noteId to use, will create if it doesn’t exist

template: Note | type[Note] | None = None

Note to set as target of ~template relation

session: Session | None = None

Session, or None to use default

Bases:

trilium_alchemy.core.entity.Entity
trilium_alchemy.core.note.Mixin
collections.abc.MutableMapping
typing.Generic

Aliases:

trilium_alchemy.Note
trilium_alchemy.core.Note

Encapsulates a note and provides a base class for declarative notes.

For a detailed walkthrough of how to use this class, see Working with notes. Below summarizes a few of the features.

It’s first required to create a Session to connect to Trilium. These examples assume you’ve done so and assigned it to a variable session, and that you will invoke session.flush() or use a context manager to commit changes.

There are two fundamental ways of working with notes:

Imperative

# create new note under root
note = Note(title="My note", content="<p>Hello, world!</p>", parents=session.root)

Use the += operator to add attributes and branches:

# add label #sorted
note += Label("sorted")

# add child note with branch created implicitly
note += Note(title="Child 1")

# add child note with branch created explicitly
note += Branch(child=Note(title="Child 2"))

Use the clone operator ^= to add a note as a parent:

# clone first child to root with branch created implicitly
note.children[0] ^= session.root

For single-valued attributes, you can get and set values by indexing into the note object using the attribute name as a key. This works for both labels and relations; the attribute type is inferred by the value set.

# add label #hideChildrenOverview
note["hideChildrenOverview"] = ""
assert note["hideChildrenOverview"] == ""

Check if a note has an attribute by using in:

assert "hideChildrenOverview" in note

Declarative

You can declaratively specify a complete hierarchy of notes and their attributes. See Declarative notes: Notes as code for further discussion of this concept.

class ChildNote(Note):
    title = "Child note"

@label("sorted")
@children(ChildNote)
class MyNote(Note):
    title = "My note"
    content = "<p>Hello, world!</p>"

# create new note under root
note = MyNote(parents=session.root)
assert note.title == "My note"
note_id: str | None#

EntityIdDescriptor()

Read-only access to noteId. Will be None if newly created with no note_id specified and not yet flushed.

title: str#

FieldDescriptor()

Note title.

note_type: str#

FieldDescriptor()

Note type.

mime: str#

FieldDescriptor()

MIME type.

is_protected: bool#

ReadOnlyFieldDescriptor()

Whether this note is protected.

date_created: str#

ReadOnlyFieldDescriptor()

Local created datetime, e.g. 2021-12-31 20:18:11.939+0100.

date_modified: str#

ReadOnlyFieldDescriptor()

Local modified datetime, e.g. 2021-12-31 20:18:11.939+0100.

utc_date_created: str#

ReadOnlyFieldDescriptor()

UTC created datetime, e.g. 2021-12-31 19:18:11.939Z.

utc_date_modified: str#

ReadOnlyFieldDescriptor()

UTC modified datetime, e.g. 2021-12-31 19:18:11.939Z.

attributes: Attributes#

ExtensionDescriptor()

Interface to attributes, both owned and inherited.

branches: Branches#

ExtensionDescriptor()

Interface to branches, both parent and child.

parents: Parents#

ExtensionDescriptor()

Interface to parent notes.

children: Children#

ExtensionDescriptor()

Interface to child notes.

content: str | bytes#

ContentDescriptor()

Interface to note content. See trilium_alchemy.core.note.content.Content.

note_id_seed: str | None#

None

Inherited from: trilium_alchemy.core.note.Mixin

Seed from which to generate note_id. Useful to generate a collision-avoidant id from a human-friendly identifier. Generated as base64-encoded hash of seed.

If you want to fix the id of a subclassed note, it’s recommended to use Mixin.singleton, which internally generates Mixin.note_id_seed from the class name. However if you want note_id to be invariant of where the class is located in its package, you may prefer to use Mixin.note_id_seed directly.

singleton: bool#

False

Inherited from: trilium_alchemy.core.note.Mixin

If set on a Note subclass, enables deterministic calculation of note_id based on the fully qualified class name. This means the same class will always have the same note_id when instantiated.

Warning

If you move this class to a different module, it will result in a different note_id which will break any non-declarative relations to it. To avoid changing the note_id you can set note_id_seed to the original fully qualified class name.

leaf: bool#

False

Inherited from: trilium_alchemy.core.note.Mixin

If set to True on a Note subclass, disables setting of child notes declaratively, allowing children to be manually maintained by the user. Otherwise, notes added by the user will be deleted to match the children added declaratively.

Should be set on notes intended to hold user notes, e.g. todo lists.

If False and note_id is deterministically generated (e.g. it’s a singleton or child of a singleton), a label #cssClass=triliumAlchemyDeclarative is added by TriliumAlchemy. This enables hiding of the “Add child note” button in Trilium’s UI via the AppCss note added by BaseRootSystem.

content_file: str | None#

None

Inherited from: trilium_alchemy.core.note.Mixin

Name of file to use as content, relative to module’s location. Also adds #originalFilename label.

Note

Currently Trilium only shows #originalFilename if the note’s type is file.

property is_string: bool#

True if note as it’s currently configured has text content.

Mirrors Trilium’s src/services/utils.js:isStringNote().

property state: State#

Inherited from: trilium_alchemy.core.entity.Entity

Current state.

property session: Session#

Inherited from: trilium_alchemy.core.entity.Entity

Session to which this entity belongs.

property str_short: str#

Inherited from: trilium_alchemy.core.entity.Entity

Get a short description of this entity.

property str_summary: str#

Inherited from: trilium_alchemy.core.entity.Entity

Get a summary of this entity, including its current state and model values.

export_zip(dest_path: str, export_format: Literal[html, markdown] = 'html')#

Export this note subtree to zip file.

Parameters:
dest_path: str

Destination .zip file

export_format: Literal[html, markdown] = 'html'

Format of exported HTML notes

import_zip(src_path: str)#

Import this note subtree from zip file.

Parameters:
src_path: str

Source .zip file

flush()#

Flush note along with its owned attributes.

invalidate() None#

Inherited from: trilium_alchemy.core.entity.Entity

Discard cached contents and user-provided data for this object. Upon next access, data will be fetched from Trilium.

delete() None#

Inherited from: trilium_alchemy.core.entity.Entity

Mark this entity for pending delete.

init(attributes: list[Attribute], children: list[Note | type[Note] | Branch]) dict[str, Any] | None#

Inherited from: trilium_alchemy.core.note.Mixin

Optionally provided by Note or Mixin subclass to add attributes and/or children during instantiation. Use the following to create attribute/child with deterministic id:

Can return a dict of other fields to update, e.g. title.

Note

User should not invoke super().init(). To add attributes and children in an intuitive order, TriliumAlchemy manually traverses a Note subclass’s MRO and invokes decorator-patched inits followed by Mixin.init.

create_declarative_label(name: str, value: str = '', inheritable: bool = False) Label#

Inherited from: trilium_alchemy.core.note.Mixin

Create and return a Label with deterministic attribute_id based on its name and note’s note_id. Should be used in subclassed Note.init or Mixin.init to generate the same attribute_id upon every instantiation.

Multiple attributes of the same name are supported.

create_declarative_relation(name: str, target: Note, inheritable: bool = False) Relation#

Inherited from: trilium_alchemy.core.note.Mixin

Create and return a Relation with deterministic attribute_id based on its name and note’s note_id. Should be used in subclassed Note.init or Mixin.init to generate the same attribute_id upon every instantiation.

Multiple attributes of the same name are supported.

create_declarative_child(child_cls: type[Note], **kwargs) Branch#

Inherited from: trilium_alchemy.core.note.Mixin

Create a child Note with deterministic note_id and return a Branch. Should be used in subclassed Note.init or Mixin.init to generate the same child note_id upon every instantiation.

Instantiate provided class as a declarative child of the current note by generating a deterministic id and returning the corresponding branch.

If the parent note’s note_id is not set, the child note’s may not be. If the child’s note_id is not set, a new note will be created upon every instantiation. This is the case for non-singleton subclasses.

pop(key, default=__marker)#

Inherited from: collections.abc.MutableMapping

D.pop(k[,d]) -> v, remove specified key and return the corresponding value. If key is not found, d is returned if given, otherwise KeyError is raised.

popitem()#

Inherited from: collections.abc.MutableMapping

D.popitem() -> (k, v), remove and return some (key, value) pair as a 2-tuple; but raise KeyError if D is empty.

clear()#

Inherited from: collections.abc.MutableMapping

D.clear() -> None. Remove all items from D.

update(other=(), /, **kwds)#

Inherited from: collections.abc.MutableMapping

D.update([E, ]**F) -> None. Update D from mapping/iterable E and F. If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

setdefault(key, default=None)#

Inherited from: collections.abc.MutableMapping

D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D

get(key, default=None)#

Inherited from: collections.abc.Mapping

D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.

keys()#

Inherited from: collections.abc.Mapping

D.keys() -> a set-like object providing a view on D’s keys

items()#

Inherited from: collections.abc.Mapping

D.items() -> a set-like object providing a view on D’s items

values()#

Inherited from: collections.abc.Mapping

D.values() -> an object providing a view on D’s values

class trilium_alchemy.core.note.Mixin(child_id_seed: str | None)#

Bases:

abc.ABC
trilium_alchemy.core.session.SessionContainer
typing.Generic

Aliases:

trilium_alchemy.Mixin
trilium_alchemy.core.Mixin

Reusable collection of attributes, children, and fields (note_id, title, type, mime) which can be inherited by a Note.

Note

Since Note inherits from Mixin, any Note subclass is also a valid Mixin and can use the same semantics to set attributes/children/fields.

Todo

Add auto_mime=True to also set mime using magic package (or do so automatically if Mixin.content_file set, but Mixin.mime not set)

note_id: str | None#

None

note_id to explicitly assign.

note_id_seed: str | None#

None

Seed from which to generate note_id. Useful to generate a collision-avoidant id from a human-friendly identifier. Generated as base64-encoded hash of seed.

If you want to fix the id of a subclassed note, it’s recommended to use Mixin.singleton, which internally generates Mixin.note_id_seed from the class name. However if you want note_id to be invariant of where the class is located in its package, you may prefer to use Mixin.note_id_seed directly.

title: str | None#

None

Sets title of Note subclass. If None, title is set to the class’s __name__.

note_type: str#

"text"

Sets note_type of Note subclass.

mime: str#

"text/html"

Sets mime of Note subclass.

singleton: bool#

False

If set on a Note subclass, enables deterministic calculation of note_id based on the fully qualified class name. This means the same class will always have the same note_id when instantiated.

Warning

If you move this class to a different module, it will result in a different note_id which will break any non-declarative relations to it. To avoid changing the note_id you can set note_id_seed to the original fully qualified class name.

leaf: bool#

False

If set to True on a Note subclass, disables setting of child notes declaratively, allowing children to be manually maintained by the user. Otherwise, notes added by the user will be deleted to match the children added declaratively.

Should be set on notes intended to hold user notes, e.g. todo lists.

If False and note_id is deterministically generated (e.g. it’s a singleton or child of a singleton), a label #cssClass=triliumAlchemyDeclarative is added by TriliumAlchemy. This enables hiding of the “Add child note” button in Trilium’s UI via the AppCss note added by BaseRootSystem.

content_file: str | None#

None

Name of file to use as content, relative to module’s location. Also adds #originalFilename label.

Note

Currently Trilium only shows #originalFilename if the note’s type is file.

init(attributes: list[Attribute], children: list[Note | type[Note] | Branch]) dict[str, Any] | None#

Optionally provided by Note or Mixin subclass to add attributes and/or children during instantiation. Use the following to create attribute/child with deterministic id:

Can return a dict of other fields to update, e.g. title.

Note

User should not invoke super().init(). To add attributes and children in an intuitive order, TriliumAlchemy manually traverses a Note subclass’s MRO and invokes decorator-patched inits followed by Mixin.init.

create_declarative_label(name: str, value: str = '', inheritable: bool = False) Label#

Create and return a Label with deterministic attribute_id based on its name and note’s note_id. Should be used in subclassed Note.init or Mixin.init to generate the same attribute_id upon every instantiation.

Multiple attributes of the same name are supported.

create_declarative_relation(name: str, target: Note, inheritable: bool = False) Relation#

Create and return a Relation with deterministic attribute_id based on its name and note’s note_id. Should be used in subclassed Note.init or Mixin.init to generate the same attribute_id upon every instantiation.

Multiple attributes of the same name are supported.

create_declarative_child(child_cls: type[Note], **kwargs) Branch#

Create a child Note with deterministic note_id and return a Branch. Should be used in subclassed Note.init or Mixin.init to generate the same child note_id upon every instantiation.

Instantiate provided class as a declarative child of the current note by generating a deterministic id and returning the corresponding branch.

If the parent note’s note_id is not set, the child note’s may not be. If the child’s note_id is not set, a new note will be created upon every instantiation. This is the case for non-singleton subclasses.