notesdir package¶
Subpackages¶
Submodules¶
notesdir.api module¶
Provides the main entry point for using the library, Notesdir
-
exception
notesdir.api.
Error
¶ Bases:
Exception
-
class
notesdir.api.
Notesdir
(conf: notesdir.conf.NotesdirConf)¶ Bases:
object
Main entry point for working programmatically with your collection of notes.
Generally, you should get an instance using the
Notesdir.for_user()
method. Callclose()
when you’re done with it, or else use it as a context manager.This class contains various methods such as
Notesdir.move()
andNotesdir.standardize()
for performing high-level operations. Therepo
attribute, which is an instance ofnotesdir.repos.base.Repo
, provides additional operations, some lower-level.-
conf
: notesdir.conf.NotesdirConf¶ Typically loaded from the variable
conf
in the file~/.notesdir.conf.py
Here’s an example of how to use this class. This would add the tag “personal” to every note tagged with “journal”.
from notesdir.api import Notesdir with Notesdir.for_user() as nd: infos = nd.repo.query('tag:journal', 'path') nd.change({info.path for info in infos}, add_tags={'personal'})
-
backfill
()¶ Finds all files missing title or created metadata, and attempts to set that metadata.
Missing titles are set to the filename, minus the file extension. Missing created dates are set based on the birthtime or ctime of the file.
Returns a list of all successfully changed files, and a list of exceptions encountered for other files.
-
change
(paths: Set[str], add_tags: Set[str] = {}, del_tags: Set[str] = {}, title: Optional[str] = None, created: Optional[datetime.datetime] = None) → None¶ Applies all the specified changes to the specified paths.
This is a convenience method that wraps
notesdir.repos.base.Repo.change()
-
close
()¶ Closes the associated repo and releases any other resources.
-
static
for_user
() → notesdir.api.Notesdir¶ Creates an instance using the user’s
~/.notesdir.conf.py
file.Raises
Exception
if it does not exist or does not define configuration.
-
move
(moves: Dict[str, str], *, into_dirs=True, check_exists=True, create_parents=False, delete_empty_parents=False) → Dict[str, str]¶ Moves files/directories and updates references to/from them appropriately.
moves is a dict where the keys are source paths that should be moved, and the values are the destinations. If a destination is a directory and into_dirs is True, the source will be moved into it, using the source’s filename; otherwise, the source is renamed to the destination.
This method tries not to overwrite files; if a destination path already exists, a shortened UUID will be appended to the path. You can disable that behavior by setting check_exists=False.
It’s OK for a path to occur as a key and also another key’s value. For example,
{'foo': 'bar', 'bar': 'foo'}
will swap the two files.If create_parents is True, any directories in a destination path that do not yet exist will be created.
If delete_empty_parents is True, after moving files out of a directory, if the directory or any of its parent directories are empty, they will be deleted. (The root folder or current working directory will not be deleted regardless.)
Returns a dict mapping paths of files that were moved, to their final paths.
-
new
(template_name: str, dest: Optional[str] = None) → str¶ Creates a new file using the specified template.
The template name will be looked up using
template_for-name()
.Raises
FileNotFoundError
if the template cannot be found.If dest is not given, a target file name will be generated.
The following names are defined in the template’s namespace:
nd
: this instance ofNotesdir
directives
: an instance ofnotesdir.models.TemplateDirectives
template_path
: thepathlib.Path
of the template being rendered
Returns the path of the created file.
-
organize
() → Dict[str, str]¶ Reorganizes files using the function set in
notesdir.conf.NotesdirConf.path_organizer
.For every file in your note directories (defined by
notesdir.conf.RepoConf.root_paths
), this method will call that function with the file’s FileInfo, and move the file to the path the function returns.Note that the function will only be called for files, not directories. You cannot directly move a directory by this method, but you can effectively move one by moving all the files from it to the same new directory.
This method deletes any empty directories that result from the moves it makes, and creates any directories it needs to.
The FileInfo is retrieved using
notesdir.models.FileInfoReq.full()
.
-
replace_path_hrefs
(original: str, replacement: str) → None¶ Finds and replaces links to the original path with links to the new path.
Note that this does not currently replace links to children of the original path - e.g., if original is “/foo/bar”, a link to “/foo/bar/baz” will not be updated.
No files are moved, and this method does not care whether or not the original or replacement paths refer to actual files.
-
template_for_name
(name: str) → Optional[str]¶ Returns the path to the template for the given name, if one is found.
If treating the name as a relative or absolute path leads to a file, that file is used. Otherwise, the name is looked up from
Notesdir.templates_by_name()
, case-insensitively. Returns None if a matching template cannot be found.
-
templates_by_name
() → Dict[str, str]¶ Returns paths of note templates that are known based on the config.
The name is the part of the filename before any . character. If multiple templates have the same name, the one whose path is lexicographically first will appear in the dict.
-
notesdir.cli module¶
Command-line interface for notesdir.
-
notesdir.cli.
argparser
() → argparse.ArgumentParser¶
-
notesdir.cli.
main
(args=None) → int¶ Runs the tool and returns its exit code.
args may be an array of string command-line arguments; if absent, the process’s arguments are used.
notesdir.conf module¶
-
class
notesdir.conf.
DirectRepoConf
(root_paths: Set[str], ignore: Callable[[str, str], bool] = <function default_ignore>, skip_parse: Callable[[str, str], bool] = <function default_skip_parse>, preview_mode: bool = False)¶ Bases:
notesdir.conf.RepoConf
Configures notesdir to access notes without caching, via
notesdir.repos.DirectRepo
.-
instantiate
()¶
-
root_paths
: Set[str]¶ The folders that should be searched (recursively) when querying for notes, finding backlinks, etc.
Must not be empty.
-
-
class
notesdir.conf.
NotesdirConf
(repo_conf: 'RepoConf', template_globs: 'Set[str]' = <factory>, path_organizer: 'Callable[[FileInfo], str]' = <function NotesdirConf.<lambda> at 0x1050f3dc0>, cli_path_output_rewriter: 'Callable[[str], str]' = <function NotesdirConf.<lambda> at 0x1050f3ca0>)¶ Bases:
object
-
cli_path_output_rewriter
()¶ Changes how paths are printed to the console by the CLI.
By default paths are printed in their absolute, canonical form. This setting lets you change that by defining a function which takes the absolute path as a parameter and returns the path that should be printed.
My use case for this is that I store some notes in iCloud, and the absolute path to the iCloud folder contains a space, which means command-clicking the path in the terminal does not work. By creating a symlink and rewriting the paths to use the symlink before printing them, I can ensure the paths are clickable.
conf.cli_path_output_rewriter = lambda path: path.replace('/Users/jacob/Library/Mobile Documents/com~apple~CloudDocs/', '/Users/jacob/iCloud/')
-
classmethod
for_user
() → notesdir.conf.NotesdirConf¶
-
instantiate
()¶
-
path_organizer
()¶ Defines the rule for rewriting paths used by the
organize
command andnotesdir.api.Notesdir.organize()
.You can use this to standardize filenames or to organize your files via tags, date, or other criteria.
For example, the following converts all filenames to lowercase versions of the note title (if any):
import os.path def path_organizer(info): dirname, filename = os.path.split(info.path) suffix = os.path.splitext(filename)[1] if info.title: return os.path.join(dirname, into.title.lower() + suffix) return os.path.join(dirname, filename.lower()) conf.path_organizer = path_organizer
Here’s an example of organizing by important tags:
import os.path def path_organizer(info): for tag in ['secrets', 'journal', 'grievances']: if tag in info.tags: return f'/Users/jacob/notes/{tag}/{os.path.basename(info.path)}' return f'/Users/jacob/notes/misc/{os.path.basename(info.path)}' conf.path_organizer = path_organizer
Some helper functions are provided for use in path organizers:
-
repo_conf
: notesdir.conf.RepoConf¶ Configures how to access your collection of notes.
-
standardize
()¶
-
template_globs
: Set[str]¶ A set of path globs such as
{"/notes/templates/*.mako"}
to search for templates.This is used for the CLI command
new
, and template-related methods ofnotesdir.api.Notesdir
.
-
-
class
notesdir.conf.
RepoConf
(root_paths: Set[str], ignore: Callable[[str, str], bool] = <function default_ignore>, skip_parse: Callable[[str, str], bool] = <function default_skip_parse>, preview_mode: bool = False)¶ Bases:
object
Base class for repo config. Use a subclass such as
SqliteRepoConf
.-
ignore
(filename: str) → bool¶ Use this to indicate files or folders that should not be processed by notesdir at all.
The first argument is the path to the directory containing the file/folder, and the second argument is the filename.
If this function returns True for a given path, neither that path nor any of its child paths will be parsed, or returned in any queries, or affected by the
organize
command.The
mv
command may still move these files when explicitly instructed to do so or when moving a directory containing them, and theinfo
command will still show backlinks from other (non-ignored) files.The current default behavior is to ignore all files or folders whose name begins with a period (
.
), and also.icloud
files.
-
instantiate
()¶
-
preview_mode
: bool = False¶ If True, commands that would change notes should instead just print a list of changes to the console.
Instead of setting this in your
.notesdir.conf.py
, you can pass a--preview
command-line argument to relevant commands.
-
root_paths
: Set[str]¶ The folders that should be searched (recursively) when querying for notes, finding backlinks, etc.
Must not be empty.
-
skip_parse
(filename: str) → bool¶ Use this to indicate files or folders that should not be parsed (or edited) by notesdir.
The first argument is the path to the directory containing the file/folder, and the second argument is the filename.
If this function returns True for a given path, parsing will be skipped for both it and its child paths. For such files, only the path and backlinks attributes will be populated on
notesdir.models.FileInfo
.Unlike
notesdir.conf.RepoConf.ignore
, unparsed files are still potentially returned in queries and affected by theorganize
command. Note that parsing is automatically skipped for ignored files.The current default behavior does not skip anything.
-
standardize
()¶
-
-
class
notesdir.conf.
SqliteRepoConf
(root_paths: Set[str], ignore: Callable[[str, str], bool] = <function default_ignore>, skip_parse: Callable[[str, str], bool] = <function default_skip_parse>, preview_mode: bool = False, cache_path: Optional[str] = None)¶ Bases:
notesdir.conf.DirectRepoConf
Configures notesdir to access notes with caching, via
notesdir.repos.SqliteRepo
.-
cache_path
: str = None¶ Required. Path where the SQLite database file should be stored.
The file will be created if it does not exist. The file is only a cache; you can safely delete it when the tool is not running, though you will then have to wait for the cache to be rebuilt the next time you run the tool.
-
instantiate
()¶
-
-
notesdir.conf.
default_ignore
(parentpath: str, filename: str) → bool¶
-
notesdir.conf.
default_skip_parse
(parentpath: str, filename: str) → bool¶
-
notesdir.conf.
resource_path_fn
(path: str) → Optional[notesdir.models.DependentPathFn]¶ Enables moving files in
.resources
directories when the owner moves.This is meant for use in a
NotesdirConf.path_organizer
if you’d like to follow the convention of putting attachments for a file in a directory next to the file, with a suffix of.resources
. For example, an attachmentcat.png
for the file/notes/foo.md
would be at/notes/foo.md.resources/cat.png
.This function lets you ensure that if
foo.md
is renamed by your organizer,foo.md.resources
will be too.Example usage:
def my_path_organizer(info): rewrite = resource_path_fn(info.path) if rewrite: return rewrite # put the rest of your organizer rules here conf.path_organizer = my_path_organizer
-
notesdir.conf.
rewrite_name_using_title
(info: notesdir.models.FileInfo) → str¶ If the given info has a title, returns an updated path using that title.
The following adjustments are made:
Title is truncated to 60 characters
Characters are converted to lowercase
Only the letters a-z and digits 0-9 are kept; all other characters are replaced with dashes
Consecutive dashes are collapsed to a single dash
Leading and trailing dashes are removed
For example, for a file at
/foo/bar.md
with title “Everything is awful”, the path returned would be/foo/everything-is-awful.md
.The file extension from the original path is kept, but note that currently this will not work properly for files with multiple extensions (eg
tar.gz
). That shouldn’t be an issue right now since none of the file types for which title metadata is supported typically use multiple extensions.If there is no title, the path is returned unchanged.
This is meant to be used as, or as part of, a
NotesdirConf.path_organizer
.
notesdir.models module¶
Defines classes for representing note details, queries, and update requests.
The most important classes are FileInfo
, FileEditCmd
, and FileQuery
-
class
notesdir.models.
AddTagCmd
(path: str, value: str)¶ Bases:
notesdir.models.FileEditCmd
Represents a request to add a tag to a document.
If the document already contains the tag, this request should be treated as a no-op.
-
value
: str¶ The tag to add.
-
-
class
notesdir.models.
CreateCmd
(path: str, contents: str)¶ Bases:
notesdir.models.FileEditCmd
Represents a request to create a new file.
-
contents
: str¶
-
-
class
notesdir.models.
DelTagCmd
(path: str, value: str)¶ Bases:
notesdir.models.FileEditCmd
Represents a request to remove a tag from a document.
If the document does not contain the tag, this request should be treated as a no-op.
-
value
: str¶ The tag to remove.
-
-
class
notesdir.models.
DependentPathFn
(determinant: str, fn: Callable[[notesdir.models.FileInfo], str])¶ Bases:
object
Indicates that a path can be calculated based on the FileInfo for another path.
You can return this from a
notesdir.conf.NotesdirConf.path_organizer
when one file’s path depends on another’s.notesdir.api.Notesdir.organize()
will call the givenfn
with the info for the path specified bydeterminant
, but the path in the info will reflect any pending move for that file (even if they have not been executed in the filesystem yet).-
determinant
: str¶
-
fn
: Callable[[notesdir.models.FileInfo], str]¶
-
-
class
notesdir.models.
FileEditCmd
(path: str)¶ Bases:
object
Base class for requests to make changes to a file.
-
path
: str¶ Path to the file or folder that should be changed.
-
-
class
notesdir.models.
FileInfo
(path: str, links: List[notesdir.models.LinkInfo] = <factory>, tags: Set[str] = <factory>, title: Optional[str] = None, created: Optional[datetime.datetime] = None, backlinks: List[notesdir.models.LinkInfo] = <factory>)¶ Bases:
object
Container for the details Notesdir can parse or calculate about a file or folder.
A FileInfo instance does not imply that its path actually exists - instances may be created for nonexistent paths that have just the
path
andbacklinks
attributes filled in.When you retrieve instances of this from methods like
notesdir.repos.base.Repo.info()
, which fields are populated depends on which fields you request via theFileInfoReq
, as well as what fields are supported for the file type and what data is populated in the particular file.-
as_json
() → dict¶ Returns a dict representing the instance, suitable for serializing as json.
-
backlinks
: List[notesdir.models.LinkInfo]¶ Links from other files to this file.
-
created
: Optional[datetime.datetime] = None¶ The creation date of the document, according to metadata within the document, if any.
This will not automatically be populated with timestamps from the filesystem, but see
guess_created()
.
-
guess_created
() → Optional[datetime.datetime]¶ Returns the first available of:
created
, or the file’s birthtime, or the file’s ctime.Returns None for paths that don’t exist.
-
links
: List[notesdir.models.LinkInfo]¶ Links from this file to other files or resources.
-
path
: str¶ The resolved, absolute path for which this information applies.
Tags for the file (e.g. “journal” or “project-idea”).
-
title
: Optional[str] = None¶ The title of the document, if any.
-
-
class
notesdir.models.
FileInfoReq
(path: bool = False, links: bool = False, tags: bool = False, title: bool = False, created: bool = False, backlinks: bool = False)¶ Bases:
object
Allows you to specify which attributes you want when loading or querying for files.
For each attribute of
FileInfo
, there is a corresponding boolean attribute here, which you should set to True to indicate that you want that attribute.Some methods that take a FileInfoReq parameter also accept strings or lists of strings as a convenience, which they will pass to
parse()
.-
backlinks
: bool = False¶
-
created
: bool = False¶
-
classmethod
full
() → notesdir.models.FileInfoReq¶ Returns an instance that requests everything.
-
classmethod
internal
() → notesdir.models.FileInfoReq¶ Returns an instance that requests everything which can be determined by looking at a file in isolation.
Currently this means everything except backlinks.
-
links
: bool = False¶
-
classmethod
parse
(val: Union[str, Iterable[str], notesdir.models.FileInfoReq]) → notesdir.models.FileInfoReq¶ Converts the parameter to a FileInfoReq, if it isn’t one already.
You can pass a comma-separated string like
"path,backlinks"
or a list of strings like['path', 'backlinks']
. Each listed field will be set to True in the resulting FileInfoReq.
-
path
: bool = False¶
-
title
: bool = False¶
-
-
class
notesdir.models.
FileQuery
(include_tags: Set[str] = <factory>, exclude_tags: Set[str] = <factory>, sort_by: List[notesdir.models.FileQuerySort] = <factory>)¶ Bases:
object
Represents criteria for searching for notes.
Some methods that take a FileQuery parameter also accept strings as a convenience, which they pass to
parse()
If multiple criteria are specified, the query should only return notes that satisfy all the criteria.
-
apply_filtering
(infos: Iterable[notesdir.models.FileInfo]) → Iterator[notesdir.models.FileInfo]¶ Yields the entries from the given iterable which match the criteria of this query.
-
apply_sorting
(infos: Iterable[notesdir.models.FileInfo]) → List[notesdir.models.FileInfo]¶ Returns a copy of the given file info collection sorted using this query’s sort_by.
If non-empty, the query should only return files that have none of the specified tags.
If non-empty, the query should only return files that have all of the specified tags.
-
classmethod
parse
(strquery: Union[str, notesdir.models.FileQuery]) → notesdir.models.FileQuery¶ Converts the parameter to a FileQuery, if it isn’t one already.
Query strings are split on spaces. Each part can be one of the following:
tag:TAG1,TAG2
- notes must include all the specified tags-tag:TAG1,TAG2
- notes must not include any of the specified tagssort:FIELD1,FIELD2
- sort by the given fieldsfields on the left take higher priority, e.g.
sort:created,title
sorts by created date firsta minus sign in front of a field name indicates to sort descending, e.g.
sort:-backlinks
orsort:filename,-created
supported fields:
backlinks
(count),created
,filename
,tags
(count)title
,path
Examples:
"tag:journal,food -tag:personal"
- notes that are tagged both “journal” and “food” but not “personal”
-
sort_by
: List[notesdir.models.FileQuerySort]¶ Indicates how to sort the results.
For example,
[(FileQuerySort.BACKLINKS_COUNT, Order.DESC), (FileQuerySort.FILENAME, Order.ASC)]
would sort the results so that the most-linked-to files appear first; files with equal numbers of backlinks would be sorted lexicographically.
-
-
class
notesdir.models.
FileQuerySort
(field: FileQuerySortField, reverse: bool = False, ignore_case: bool = True, missing_first: bool = False)¶ Bases:
object
-
ignore_case
: bool = True¶ If True, strings are sorted as if they were lower case.
-
key
(info: notesdir.models.FileInfo) → Union[str, int, datetime.datetime]¶ Returns sort key for the given file info for the
field
specified in this instance.This is affected by the values of
ignore_case
andmissing_first
, but not the value ofreverse
.
-
missing_first
: bool = False¶ Affects the behavior for None values and empty strings.
If True, they should come before other values; if False, they should come after. This definition is based on the assumption that reverse=False; when reverse=True, the ultimate result will be the opposite.
-
reverse
: bool = False¶ If True, sort descending.
-
-
class
notesdir.models.
FileQuerySortField
(value)¶ Bases:
enum.Enum
An enumeration.
-
BACKLINKS_COUNT
= 'backlinks'¶
-
CREATED
= 'created'¶
-
FILENAME
= 'filename'¶
-
PATH
= 'path'¶
-
TAGS_COUNT
= 'tags'¶
-
TITLE
= 'title'¶
-
-
class
notesdir.models.
LinkInfo
(referrer: str, href: str)¶ Bases:
object
Represents a link from a file to some resource.
Not all links target local files, but those are the ones most important to notesdir. The
referent()
method can be used to determine what local file, if any, the href targets.-
as_json
() → dict¶ Returns a dict representing the instance, suitable for serializing as json.
-
href
: str¶ The linked address.
Normally this is some sort of URI - it’s the address portion of a Markdown link, or the
href
orsrc
attribute of an HTML tag, etc.
-
referent
() → Optional[str]¶ Returns the resolved, absolute local path that this link refers to.
The path will be returned even if no file or folder actually exists at that location.
None will be returned if the href cannot be parsed or appears to be a non-file URI.
-
referrer
: str¶ The file that contains the link. This should be a resolved, absolute path.
-
-
class
notesdir.models.
MoveCmd
(path: str, dest: str, create_parents: bool = False, delete_empty_parents: bool = False)¶ Bases:
notesdir.models.FileEditCmd
Represents a request to move a file or folder from one location to another.
This does not imply that any links should be rewritten; that is a higher-level operation, which is provided by
notesdir.api.Notesdir.move()
.-
create_parents
: bool = False¶ If True, any nonexistent parent directories should be created.
-
delete_empty_parents
: bool = False¶ If True, any parent directories that are empty after performing the move should be deleted.
-
dest
: str¶ The new path and filename.
-
-
class
notesdir.models.
ReplaceHrefCmd
(path: str, original: str, replacement: str)¶ Bases:
notesdir.models.FileEditCmd
Represents a request to replace link addresses in a document.
All occurrences will be replaced, but only if they are exact matches.
-
replacement
: str¶ The new link address.
-
-
class
notesdir.models.
SetCreatedCmd
(path: str, value: Optional[datetime.datetime])¶ Bases:
notesdir.models.FileEditCmd
Represents a request to change the creation date stored in a document’s metadata (not filesystem metadata).
-
value
: Optional[datetime.datetime]¶ The new creation date, or None to delete it from the metadata.
-
-
class
notesdir.models.
SetTitleCmd
(path: str, value: Optional[str])¶ Bases:
notesdir.models.FileEditCmd
Represents a request to change a document’s title.
-
value
: Optional[str]¶ The new title, or None to delete the title.
-
-
class
notesdir.models.
TemplateDirectives
(dest: Optional[str] = None)¶ Bases:
object
Passed by
notesdir.api.Notesdir.new()
when it is rendering one of a user’s templates.It is used for passing data in and out of the template.
-
dest
: Optional[str] = None¶ The path at which the new file should be created.
If this is set before rendering the template, it is the path the user suggested. But the template can change it, and the template’s suggestion will take precedence. If the path already exists, notesdir will adjust it further to get a unique path before creating the file.
-
notesdir.rearrange module¶
Helper functions for moving files and updating links between them.
Generally, you should use notesdir.api.Notesdir.move()
or notesdir.api.Notesdir.replace_path_hrefs()
instead of using anything in this module directly.
-
notesdir.rearrange.
edits_for_path_replacement
(referrer: str, hrefs: Set[str], replacement: str) → Iterator[notesdir.models.ReplaceHrefCmd]¶ Yields commands to replace a file’s links to a path with links to another path.
-
notesdir.rearrange.
edits_for_raw_moves
(renames: Dict[str, str]) → Iterator[notesdir.models.MoveCmd]¶ Yields commands that will rename a set of files/folders.
The keys of the dictionary are the paths to be renamed, and the values are what they should be renamed to. If a path appears as both a key and as a value, it will be moved to a temporary file as an intermediate step.
-
notesdir.rearrange.
edits_for_rearrange
(store: notesdir.repos.base.Repo, renames: Dict[str, str]) → Iterator[notesdir.models.FileEditCmd]¶ Yields commands that will rename files and update links accordingly.
The keys of the dictionary are the paths to be renamed, and the values are what they should be renamed to. (If a path appears as both a key and as a value, it will be moved to a temporary file as an intermediate step.)
The given store is used to search for files that link to any of the paths that are keys in the dictionary, so that ReplaceHrefEditCmd instances can be generated for them. The files that are being renamed will also be checked for outbound links, and ReplaceRef edits will be generated for those too.
Source paths may be directories; the directory as a whole will be moved, and links to/from all files/folders within it will be updated too.
-
notesdir.rearrange.
find_available_name
(dest: str, also_unavailable: Set[str], src: Optional[str] = None) → str¶ Given a desired destination path, adjusts it so that it will not overwrite any existing files.
dest should be the full desired path.
also_unavailable should be any paths that may be created between the time this method executes and the time the destination file is actually created.
If dest already exists or is in also_unavailable, a new path will be generated in the same directory, with a short UUID appended.
If you are moving an existing file, it is recommended to include the src parameter. Then, if the filename of dest and the filename of src are the same except that src includes a short UUID in the format generated by this function, this function will prefer keeping that UUID rather than generating a new one (but it will still prefer no UUID at all when possible).
-
notesdir.rearrange.
href_path
(src: str, dest: str) → str¶ Returns the path to use for a reference from file src to file dest.
This is a relative path to dest from the directory containing src.
For example, for src /foo/bar/baz.md and dest /foo/meh/blah.png, returns ../meh/blah.png.
src and dest are resolved before calculating the relative path.
-
notesdir.rearrange.
path_as_href
(path: str, into_url: Optional[urllib.parse.ParseResult] = None) → str¶ Returns the string to use for referring to the given path in a file.
This percent-encodes characters as necessary to make the path a valid URL. If into_url is provided, it copies every part of that URL except the path into the resulting URL.
Note that if into_url contains a scheme or netloc, the given path must be absolute.
Module contents¶
Helps manage notes stored as plain files in the filesystem.
If you installed via pip
, run notesdir -h` to get help.
Or, run ``python3 -m notesdir -h
.
To use the Python API, look at notesdir.api.Notesdir