Skip to content

vault

This module contains the classes that represent Obsidian vaults.

A vault is a collection of notes that can be searched through.

Vault(path: str, notes: list[Note] = [], filter: Filter = Filter(), adder: Adder = Adder())

A class that represents an Obsidian vault.

Parameters:

  • path (str) –

    The path of the vault.

  • notes (list[Note], default: [] ) –

    The list of notes in the vault

  • filter (Filter, default: Filter() ) –

    The filter applied to the vault

Source code in pyobsidian/vault.py
40
41
42
43
44
45
46
47
48
49
50
def __init__(
    self: Self,
    path: str,
    notes: list[Note] = [],
    filter: Filter = Filter(),
    adder: Adder = Adder()
) -> None:
    self.__path = path
    self.__notes = notes
    self.__filter = filter
    self.__adder = adder

adder: Adder property

The adder applied to the vault

Returns:

  • Filter

    The adder applied to the vault

adder_strategies: dict[AdderKey, AdderWhere] property

The adder strategies used by the vault

Returns:

  • dict[AdderKey, AdderWhere]

    The adder strategies used by the vault

filter: Filter property

The filter applied to the vault

Returns:

  • Filter

    The filter applied to the vault

formatters: dict[tuple[str, str], Formatter] property

The formatters used by the vault

Returns:

  • dict[tuple[str, str], Formatter]

    The formatters used by the vault

notes: list[Note] property

The list of notes in the vault

Returns:

  • list[Note]

    The list of notes in the vault

path: str property

The path of the vault

Returns:

  • str

    The path of the vault

search_strategies: dict[FieldKey, SearchBy] property

The search strategies used by the vault

Returns:

  • dict[FieldKey, SearchBy]

    The search strategies used by the vault

A function that searches for notes based on a given field using a specific search strategy.

Parameters:

  • notes (list[Note]) –

    A list of notes to search through.

  • field (Field) –

    The field to search for.

Returns:

  • list[Note]

    A list of notes that match the search criteria.

Source code in pyobsidian/vault.py
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
def __search(
    self,
    notes: list[Note], 
    field: Field
) -> list[Note]:
    """A function that searches for notes based on a given field using a specific search strategy.

    Parameters
    ----------
    notes : list[Note]
        A list of notes to search through.
    field : Field
        The field to search for.

    Returns
    -------
    list[Note]
        A list of notes that match the search criteria.
    """
    search_strategy = self.search_strategies[field.key]
    notes = search_strategy.search(notes, field)
    return notes

add(by: AdderKey, value: AdderValue, where: Literal['inline', 'yaml'] | Op) -> Vault

Add a new adder field to current adder.

by, value and where build the field to add.

  • by is used to find which AdderWhere to add to.
  • value is the value to add.
  • where is the where to add the value: inline, yaml or an Op.

Parameters:

  • by (AdderKey) –

    The field to add by.

  • value (AdderValue) –

    The value to add.

  • where (Literal['inline', 'yaml'] | Op) –

    The where to add the field.

Returns:

  • Vault

    A new Vault object with the new adder field added.

Source code in pyobsidian/vault.py
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
def add(
    self: Self, 
    by: AdderKey, 
    value: AdderValue,
    where: Literal['inline', 'yaml'] | Op
) -> Vault:
    """Add a new adder field to current adder.

    `by`, `value` and `where` build the field to add.

    - by is used to find which AdderWhere to add to.
    - value is the value to add.
    - where is the where to add the value: inline, yaml or an Op.

    Parameters
    ----------
    by : AdderKey
        The field to add by.
    value : AdderValue
        The value to add.
    where : Literal['inline', 'yaml'] | Op
        The where to add the field.

    Returns
    -------
    Vault
        A new Vault object with the new adder field added.
    """
    if isinstance(where, Op):
        adder_field = AdderField(by, value, (where.id, where))
    else:
        adder_field = AdderField(by, value, where)
    cur_adder = self.adder
    new_adder = cur_adder.add_field(adder_field)
    new_vault = Vault(path=self.path, notes=self.notes, filter=self.filter, adder=new_adder)
    return new_vault

add_new_adder_strategy(name: AdderKey, strategy: AdderWhere) -> dict[str, AdderWhere] classmethod

Adds a new adder strategy to Vault class.

Parameters:

  • name (AdderKey) –

    The name of the new adder strategy.

  • strategy (AdderField) –

    The adder strategy to be added.

Returns:

  • dict[str, AdderWhere]

    The updated adder strategies.

Source code in pyobsidian/vault.py
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
@classmethod
def add_new_adder_strategy(
    cls: type[Self],
    name: AdderKey,
    strategy: AdderWhere
) -> dict[str, AdderWhere]:
    """Adds a new adder strategy to Vault class.

    Parameters
    ----------
    name : AdderKey
        The name of the new adder strategy.
    strategy : AdderField
        The adder strategy to be added.

    Returns
    -------
    dict[str, AdderWhere]
        The updated adder strategies.
    """
    cls.__adder_strategies.registry.add_registry(name, strategy)
    return cls.__adder_strategies.registry.where

add_new_formatter(name: str, where: str, formatter: Formatter) -> dict[tuple[str, str], Formatter] classmethod

Adds a new adder formatter to Vault class.

Parameters:

  • name (AdderKey) –

    The name of the new adder formatter.

  • formatter (AdderField) –

    The formatter to be added.

Returns:

  • dict[tuple[str, str], Formatter]

    The updated adder formatters.

Source code in pyobsidian/vault.py
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
@classmethod
def add_new_formatter(
    cls: type[Self],
    name: str,
    where: str,
    formatter: Formatter
) -> dict[tuple[str, str], Formatter]:
    """Adds a new adder formatter to Vault class.

    Parameters
    ----------
    name : AdderKey
        The name of the new adder formatter.
    formatter : AdderField
        The formatter to be added.

    Returns
    -------
    dict[tuple[str, str], Formatter]
        The updated adder formatters.
    """
    cls.__adder_strategies.registry.add_formatter(name, where, formatter)
    return cls.__adder_strategies.registry.formatters

add_new_search_strategy(name: FieldKey, strategy: SearchBy) -> dict[FieldKey, SearchBy] classmethod

Adds a new search strategy to Vault class.

Parameters:

  • name (FieldKey) –

    The name of the new search strategy.

  • strategy (SearchBy) –

    The search strategy to be added.

Returns:

  • dict[FieldKey, SearchBy]

    The updated search strategies.

Source code in pyobsidian/vault.py
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
@classmethod
def add_new_search_strategy(
    cls: type[Self],
    name: FieldKey,
    strategy: SearchBy
) -> dict[FieldKey, SearchBy]:
    """Adds a new search strategy to Vault class.

    Parameters
    ----------
    name : FieldKey
        The name of the new search strategy.
    strategy : SearchBy
        The search strategy to be added.

    Returns
    -------
    dict[FieldKey, SearchBy]
        The updated search strategies.
    """
    cls.__search_strategies[name] = strategy
    new_strategy = cls.__search_strategies
    return new_strategy

execute() -> Vault

This method applies the filter and adder to the current Vault object.

First, all filter fields are applied. Then, all adder fields are applied.

Returns:

  • Vault

    A new Vault object with the filter applied.

Source code in pyobsidian/vault.py
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
def execute(self: Self) -> Vault:        
    """This method applies the filter and adder to the current Vault object.

    First, all filter fields are applied. Then, all adder fields are applied.

    Returns
    -------
    Vault
        A new Vault object with the filter applied.
    """
    filter = self.filter
    if not filter:
        return self
    notes = self.notes
    if not notes:
        notes = self.get_notes()

    filtered_notes = notes
    new_notes: list[Note] = []
    for f_field in filter:
        mode = f_field.mode
        if mode == 'and':
            new_notes = self.__search(new_notes or filtered_notes, f_field.field)
        elif mode == 'or':
            new_notes.extend(self.__search(notes, f_field.field))
        else:
            raise ValueError(f'`{mode}` is not a valid mode. Must be `and` or `or`')
    unique_new_notes = list(set(new_notes))

    adder = self.adder
    if not adder:
        return Vault(path=self.path, notes=unique_new_notes, filter=filter, adder=Adder())
    for note in unique_new_notes:
        for add in adder:
            key = add.key
            value = add.value
            where = add.where
            formatter = adder.registry.get_formatter(key, where)
            adder_where = adder.registry.get_where(where)
            if adder_where is None:
                message = textwrap.dedent(f"""
                    Invalid where: '{where}' in `.add('{key}', {value}, '{where}')`
                    Checking in {adder.registry.where} I found {list(adder.registry.where.keys())}.
                    Hints:
                        - Check that you haven't made any typing errors.
                        - Check if AdderWhere implementation exists.
                        - If you don't find it, add new adder strategy.
                            - To do this, implement your own AdderWhere.
                            - Use Vault.add_new_adder_strategy()
                """)
                raise ValueError(message)
            if formatter is None:
                message = textwrap.dedent(f"""
                    Invalid formatter: "{(key, where)}" in `.add('{key}', {value}, '{where}')`
                    Checking in {adder.registry.formatters} I found {list(adder.registry.formatters.keys())}.
                    I need a Formatter to format the value because this operation will modify the content of the note.
                    In your case, you need to implement at least a Formatter for '{key}' with '{where}'.
                    Hints:
                        - Check that you haven't made any typing errors.
                        - Check if Formatter implementation exists.
                        - If you don't find it, add new formatter.
                            - To do this, implement your own Formatter. 
                            - Use Vault.add_new_adder_formatter()
                """)
                raise ValueError(message)
            new_value = formatter.format(value)
            new_field = AdderField(key, new_value, where)
            new_content = adder_where.exec(note, new_field)
            if new_content is None:
                continue
            note.properties.content = new_content
        note.write()
    return Vault(path=self.path, notes=unique_new_notes, filter=filter, adder=Adder())

find_by(by: FieldKey, value: FieldValue, occurrence: FieldOcurrence = 'file', mode: FilterMode = 'and') -> Vault

Add a new filter field to current filter.

by, value and occurrence build the field to search for. mode is used to specify how the filter should be applied. If mode is 'and' (default) the filter will be applied in current vault notes. If mode is 'or' the filter will be applied in all vault notes. This can be used to create complex filters. The sequence of the filter fields will be preserved.

For example vault.find_by('folder', 'folder1').find_by('folder', 'folder2'). In this case, the filter will be applied to search for notes in folder1. After that, the filter will be applied in notes that are returned by first filter, returning notes in folder2. This example is equivalent to finding notes that are in 'folder2' which is a subfolder of 'folder1'.

If mode is 'or' the filter will be applied to search for notes in folder1 or folder2.

Parameters:

  • by (FieldKey) –

    The field to search by.

  • value (FieldValue) –

    The value to search for.

  • occurrence (FieldOcurrence, default: 'file' ) –

    The occurrence of the value to search for. Defaults to 'file'.

  • mode (FilterMode, default: 'and' ) –

    The mode of the filter. Defaults to 'and'.

Returns:

  • Vault

    A new Vault object with the new filter field added.

Source code in pyobsidian/vault.py
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
def find_by(
    self: Self, 
    by: FieldKey, 
    value: FieldValue,
    occurrence: FieldOcurrence = 'file',
    mode: FilterMode='and'
) -> Vault:
    """Add a new filter field to current filter.

    `by`, `value` and `occurrence` build the field to search for.
    mode is used to specify how the filter should be applied.
    If mode is 'and' (default) the filter will be applied in current vault notes.
    If mode is 'or' the filter will be applied in all vault notes.
    This can be used to create complex filters.
    The sequence of the filter fields will be preserved.

    For example vault.find_by('folder', 'folder1').find_by('folder', 'folder2').
    In this case, the filter will be applied to search for notes in folder1.
    After that, the filter will be applied in notes that are returned by first filter, returning notes in folder2.
    This example is equivalent to finding notes that are in 'folder2' which is a subfolder of 'folder1'. 

    If mode is 'or' the filter will be applied to search for notes in folder1 or folder2.

    Parameters
    ----------
    by : FieldKey
        The field to search by.
    value : FieldValue
        The value to search for.
    occurrence : FieldOcurrence, optional
        The occurrence of the value to search for. Defaults to 'file'.
    mode : FilterMode, optional
        The mode of the filter. Defaults to 'and'.

    Returns
    -------
    Vault
        A new Vault object with the new filter field added.
    """
    field = Field(by, value, occurrence)
    filter_field = FilterField(field, mode)
    cur_filter = self.filter
    new_filter = cur_filter.add_field(filter_field)
    new_vault = Vault(path=self.path, notes=self.notes, filter=new_filter)
    return new_vault

get_notes(extension: str = '.md') -> list[Note]

Retrieves a list of notes from the specified vault directory.

Parameters:

  • extension (str, default: '.md' ) –

    The file extension to filter the notes by. Defaults to '.md'.

Returns:

  • list[Note]

    A list of Note objects representing the notes found in the vault directory.

Source code in pyobsidian/vault.py
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
def get_notes(self: Self, extension: str='.md') -> list[Note]:
    """Retrieves a list of notes from the specified vault directory.

    Parameters
    ----------
    extension : str, optional
        The file extension to filter the notes by. Defaults to '.md'.

    Returns
    -------
    list[Note]
        A list of Note objects representing the notes found in the vault directory.
    """
    root = self.path
    notes = []
    for root, _, filenames in os.walk(root):
        for filename in filenames:
            if filename.endswith(extension):
                note_path = os.path.join(root, filename)
                notes.append(Note(note_path))
    return notes