Metadata-Version: 2.1
Name: cs.fstags
Version: 20210306
Summary: Simple filesystem based file tagging and the associated `fstags` command line script.
Home-page: https://bitbucket.org/cameron_simpson/css/commits/all
Author: Cameron Simpson
Author-email: cs@cskk.id.au
License: GNU General Public License v3 or later (GPLv3+)
Description: Simple filesystem based file tagging
        and the associated `fstags` command line script.
        
        *Latest release 20210306*:
        * FSTags: new tagfile_for(filepath) to obtain the TagFile for filepath.
        * FSTagsCommand: new -o ontology option to supply an ontology file for the FSTags.
        * FSTagsCommand.cmd_ont: drop -o/--ontology, superceded by global -o option.
        * Move BaseTagFile from cs.fstags to TagFile in cs.tagset.
        * FSTags.edit_dirpath: we now get (old_name,new_name,TaggedPath) back from edit_many, obviating the te_id_map.
        * TaggedPath: .name property returning basename(self.filepath), .set and .discard methods rejecting use of the 'name' tag.
        * FSTagsCommand: port to new cs.cmdutils API.
        * Many small refactors and bugfixes.
        
        Many basic tasks can be performed with the `fstags` command line utility,
        documented under the `FSTagsCommand` class below.
        
        Why `fstags`?
        By storing the tags in a separate file we:
        * can store tags without modifying a file
        * do not need to know the file's format,
          or even whether that format supports metadata
        * can process tags on any kind of file
        * because tags are inherited from parent directories,
          tags can be automatically acquired merely by arranging your file tree
        
        Tags are stored in the file `.fstags` in each directory;
        there is a line for each entry in the directory
        consisting of the directory entry name and the associated tags.
        
        Tags may be "bare", or have a value.
        If there is a value it is expressed with an equals (`'='`)
        followed by the JSON encoding of the value.
        
        The tags for a file are the union of its direct tags
        and all relevant ancestor tags,
        with priority given to tags closer to the file.
        
        For example, a media file for a television episode with the pathname
        `/path/to/series-name/season-02/episode-name--s02e03--something.mp4`
        might have the tags:
        
            series_title="Series Full Name"
            season=2
            sf
            episode=3
            episode_title="Full Episode Title"
        
        obtained from the following `.fstags` entries:
        * tag file `/path/to/.fstags`:
        
            series-name sf series_title="Series Full Name"
        
        * tag file `/path/to/series-name/.fstags`:
        
          season-02 season=2
        
        * tag file `/path/to/series-name/season-02/.fstags`:
        
          episode-name--s02e03--something.mp4 episode=3 episode_title="Full Episode Title"
        
        ## `fstags` Examples ##
        
        ### Backing up a media tree too big for the removable drives ###
        
        Walk the media tree for files tagged for backup to `archive2`:
        
            fstags find /path/to/media backup=archive2
        
        Walk the media tree for files not assigned to a backup archive:
        
            fstags find /path/to/media -backup
        
        Backup the `archive2` files using `rsync`:
        
            fstags find --for-rsync /path/to/media backup=archive2 \
            | rsync -ia --include-from=- /path/to/media /path/to/backup_archive2
        
        ## Class `CascadeRule`
        
        A cascade rule of possible source tag names to provide a target tag.
        
        ### Method `CascadeRule.infer_tag(self, tagset)`
        
        Apply the rule to the `TagSet` `tagset`.
        Return a new `Tag(self.target,value)`
        for the first cascade `value` found in `tagset`,
        or `None` if there is no match.
        
        ## Class `FSTags(cs.resources.MultiOpenMixin)`
        
        A class to examine filesystem tags.
        
        ### Method `FSTags.__getitem__(self, *a, **kw)`
        
        Return the `TaggedPath` for `abspath(path)`.
        
        ### Method `FSTags.apply_tag_choices(self, tag_choices, paths)`
        
        Apply the `tag_choices` to `paths`.
        
        Parameters:
        * `tag_choices`:
          an iterable of `Tag` or an equality `TagBasedTest`.
          Each item applies or removes a `Tag`
          from each path's direct tags.
        * `paths`:
          an iterable of filesystem paths.
        
        ### Method `FSTags.attach_path(self, attach, srcpath, dstpath, *, force=False, crop_ok=False)`
        
        Attach `srcpath` to `dstpath` using the `attach` callable.
        
        Parameters:
        * `attach`: callable accepting `attach(srcpath,dstpath)`
          to do the desired attachment,
          such as a copy, link or move
        * `srcpath`: the source filesystem object
        * `dstpath`: the destination filesystem object
        * `crop_ok`: if true and the OS raises `OSError(ENAMETOOLONG)`
          attempt to crop the name before the file extension and retry
        * `force`: default `False`.
          If true and the destination exists
          try to remove it before calling `attach`.
          Otherwise if the destination exists
          raise a `ValueError`.
        
        ### Method `FSTags.cascade_tags(self, tags, cascade_rules=None)`
        
        Yield `Tag`s
        which cascade from the `TagSet` `tags`
        via `cascade_rules` (an iterable of `CascadeRules`).
        
        ### Method `FSTags.copy(self, *a, **kw)`
        
        Copy `srcpath` to `dstpath`.
        
        ### Method `FSTags.dir_tagfile(self, *a, **kw)`
        
        Return the `FSTagsTagFile` associated with `dirpath`.
        
        ### Method `FSTags.edit_dirpath(self, *a, **kw)`
        
        Edit the filenames and tags in a directory.
        
        ### Method `FSTags.export_xattrs(self, paths)`
        
        Import the extended attributes of `paths`
        and use them to update the fstags.
        
        ### Method `FSTags.find(self, path, tag_tests, use_direct_tags=False, U=None)`
        
        Walk the file tree from `path`
        searching for files matching the supplied `tag_tests`.
        Yield the matching file paths.
        
        Parameters:
        * `path`: the top of the file tree to walk
        * `tag_tests`: an iterable of `TagBasedTest`s
        * `use_direct_tags`: test the direct_tags if true,
          otherwise the all_tags.
          Default: `False`
        
        ### Method `FSTags.import_xattrs(self, paths)`
        
        Update the extended attributes of `paths`
        from their fstags.
        
        ### Method `FSTags.link(self, *a, **kw)`
        
        Link `srcpath` to `dstpath`.
        
        ### Method `FSTags.move(self, *a, **kw)`
        
        Move `srcpath` to `dstpath`.
        
        ### Property `FSTags.ontology`
        
        The primary `TagsOntology`, or `None` if `self.ontologyfile` was `None`.
        
        ### Method `FSTags.ontology_for(self, *a, **kw)`
        
        Return the `TagsOntology` associated with `path`.
        Returns `None` if an ontology cannot be found.
        
        ### Property `FSTags.ontologyfile`
        
        The ontology file basename.
        
        ### Method `FSTags.path_tagfiles(self, filepath)`
        
        Generator yielding a sequence of `(FSTagsTagFile,name)` pairs
        where `name` is the key within the `FSTagsTagFile`
        for the `FSTagsTagFile`s affecting `filepath`
        in order from the root to `dirname(filepath)`.
        
        ### Method `FSTags.resolve_format_string(self, *a, **kw)`
        
        See if `format_string` looks like `[`*clausename*`]`*entryname*.
        if so, return the corresponding config entry string,
        otherwise return `format_string` unchanged.
        
        ### Method `FSTags.scrub(self, path)`
        
        Scrub tags for names which do not exist in the filesystem.
        
        ### Method `FSTags.shutdown(self)`
        
        Save any modified tag files on shutdown.
        
        ### Method `FSTags.startup(self)`
        
        Stub for startup.
        
        ### Method `FSTags.sync(self, *a, **kw)`
        
        Flush modified tag files.
        
        ### Method `FSTags.tagfile_for(self, filepath)`
        
        Return the `FSTagsTagFile` storing the `Tag`s for `filepath`.
        
        ### Property `FSTags.tagsfile_basename`
        
        The tag file basename.
        
        ### Method `FSTags.test(self, path, tag_tests, use_direct_tags=False)`
        
        Test a path against `tag_tests`.
        
        Parameters:
        * `path`: path to test
        * `tag_tests`: an iterable of `TagBasedTest`s
        * `use_direct_tags`: test the `direct_tags` if true,
          otherwise the `all_tags`.
          Default: `False`
        
        ## Class `FSTagsCommand(cs.cmdutils.BaseCommand,cs.tagset.TagsCommandMixin)`
        
        `fstags` main command line utility.
        
        
        Command line usage:
        
            Usage: FSTagsCommand [-o ontology] subcommand [...]
              -o ontology   Specify the path to an ontology file.
              Subcommands:
                autotag paths...
                  Tag paths based on rules from the rc file.
                cp [-finv] srcpath dstpath, cp [-finv] srcpaths... dstdirpath
                  POSIX cp(1) equivalent, but also copying tags:
                  copy files and their tags into targetdir.
                  -f  Force: remove destination if it exists.
                  -i  Interactive: fail if the destination exists.
                  -n  No remove: fail if the destination exists.
                  -v  Verbose: show copied files.
                edit [-d] [path]
                  Edit the direct tagsets of path, default: '.'
                  If path is a directory, provide the tags of its entries.
                  Otherwise edit just the tags for path.
                  -d          Treat directories like files: edit just its tags.
                export [-a] [--direct] path {tag[=value]|-tag}...
                  Export tags for files from path matching all the constraints.
                  -a        Export all paths, not just those with tags.
                  --direct  Export the direct tags instead of the computed tags.
                  The output is in the same CSV format as that from "sqltags export",
                  with the following columns:
                  * unixtime: the file's st_mtime from os.stat.
                  * id: empty
                  * name: the file path
                  * tags: the file's direct or indirect tags
                find [--direct] [--for-rsync] [-o output_format] path {tag[=value]|-tag}...
                  List files from path matching all the constraints.
                  --direct    Use direct tags instead of all tags.
                  --for-rsync Instead of listing matching paths, emit a
                              sequence of rsync(1) patterns suitable for use with
                              --include-from in order to do a selective rsync of the
                              matched paths.
                  -o output_format
                              Use output_format as a Python format string to lay out
                              the listing.
                              Default: {filepath.pathname}
                help [subcommand-names...]
                  Print the help for the named subcommands,
                  or for all subcommands if no names are specified.
                import {-|srcpath}...
                  Import CSV data in the format emitted by "export".
                  Each argument is a file path or "-", indicating standard input.
                json_import --prefix=tag_prefix {-|path} {-|tags.json}
                  Apply JSON data to path.
                  A path named "-" indicates that paths should be read from
                  the standard input.
                  The JSON tag data come from the file "tags.json"; the name
                  "-" indicates that the JSON data should be read from the
                  standard input.
                ln [-finv] srcpath dstpath, ln [-finv] srcpaths... dstdirpath
                  POSIX ln(1) equivalent, but also copying the tags:
                  link files and their tags into targetdir.
                  -f  Force: remove destination if it exists.
                  -i  Interactive: fail if the destination exists.
                  -n  No remove: fail if the destination exists.
                  -v  Verbose: show linked files.
                ls [-d] [--direct] [-o output_format] [paths...]
                  List files from paths and their tags.
                  -d          Treat directories like files, do not recurse.
                  --direct    List direct tags instead of all tags.
                  -o output_format
                              Use output_format as a Python format string to lay out
                              the listing.
                              Default: {filepath.encoded} {tags}
                mv [-finv] srcpath dstpath, mv [-finv] srcpaths... dstdirpath
                  POSIX mv(1) equivalent, but also copying the tags:
                  move files and their tags into targetdir.
                  -f  Force: remove destination if it exists.
                  -i  Interactive: fail if the destination exists.
                  -n  No remove: fail if the destination exists.
                  -v  Verbose: show moved files.
                ns [-d] [--direct] [paths...]
                  Report on the available primary namespace fields for formatting.
                  Note that because the namespace used for formatting has
                  inferred field names there are also unshown secondary field
                  names available in format strings.
                  -d          Treat directories like files, do not recurse.
                  --direct    List direct tags instead of all tags.
                ont [subcommand [args...]]
                  With no arguments, print the ontology.
                rename -n newbasename_format paths...
                  Rename paths according to a format string.
                  -n newbasename_format
                      Use newbasename_format as a Python format string to
                      compute the new basename for each path.
                scrub paths...
                  Remove all tags for missing paths.
                  If a path is a directory, scrub the immediate paths in the directory.
                tag {-|path} {tag[=value]|-tag}...
                  Tag a path with multiple tags.
                  With the form "-tag", remove that tag from the direct tags.
                  A path named "-" indicates that paths should be read from the
                  standard input.
                tagfile tagfile_path [subcommand ...]
                  Subcommands:
                    tag tagset_name {tag[=value]|-tag}...
                      Directly modify tag_name within the tag file tagfile_path.
                tagpaths {tag[=value]|-tag} {-|paths...}
                  Tag multiple paths.
                  With the form "-tag", remove the tag from the immediate tags.
                  A single path named "-" indicates that paths should be read
                  from the standard input.
                test [--direct] path {tag[=value]|-tag}...
                  Test whether the path matches all the constraints.
                  --direct    Use direct tags instead of all tags.
                xattr_export {-|paths...}
                  Import tag information from extended attributes.
                xattr_import {-|paths...}
                  Update extended attributes from tags.
        
        ### Method `FSTagsCommand.apply_defaults(self)`
        
        Set up the default values in `options`.
        
        ### Method `FSTagsCommand.apply_opt(self, opt, val)`
        
        Apply command line option.
        
        ### Method `FSTagsCommand.cmd_autotag(self, argv)`
        
        Usage: {cmd} paths...
        Tag paths based on rules from the rc file.
        
        ### Method `FSTagsCommand.cmd_cp(self, argv)`
        
        Usage: {cmd} [-finv] srcpath dstpath, {cmd} [-finv] srcpaths... dstdirpath
        POSIX cp(1) equivalent, but also copying tags:
        copy files and their tags into targetdir.
        -f  Force: remove destination if it exists.
        -i  Interactive: fail if the destination exists.
        -n  No remove: fail if the destination exists.
        -v  Verbose: show copied files.
        
        ### Method `FSTagsCommand.cmd_edit(self, argv)`
        
        Usage: {cmd} [-d] [path]
        Edit the direct tagsets of path, default: '.'
        If path is a directory, provide the tags of its entries.
        Otherwise edit just the tags for path.
        -d          Treat directories like files: edit just its tags.
        
        ### Method `FSTagsCommand.cmd_export(self, argv)`
        
        Usage: {cmd} [-a] [--direct] path {{tag[=value]|-tag}}...
        Export tags for files from path matching all the constraints.
        -a        Export all paths, not just those with tags.
        --direct  Export the direct tags instead of the computed tags.
        The output is in the same CSV format as that from "sqltags export",
        with the following columns:
        * unixtime: the file's st_mtime from os.stat.
        * id: empty
        * name: the file path
        * tags: the file's direct or indirect tags
        
        ### Method `FSTagsCommand.cmd_find(self, argv)`
        
        Usage: {cmd} [--direct] [--for-rsync] [-o output_format] path {{tag[=value]|-tag}}...
        List files from path matching all the constraints.
        --direct    Use direct tags instead of all tags.
        --for-rsync Instead of listing matching paths, emit a
                    sequence of rsync(1) patterns suitable for use with
                    --include-from in order to do a selective rsync of the
                    matched paths.
        -o output_format
                    Use output_format as a Python format string to lay out
                    the listing.
                    Default: {FIND_OUTPUT_FORMAT_DEFAULT}
        
        ### Method `FSTagsCommand.cmd_import(self, argv)`
        
        Usage: {cmd} {{-|srcpath}}...
        Import CSV data in the format emitted by "export".
        Each argument is a file path or "-", indicating standard input.
        
        ### Method `FSTagsCommand.cmd_json_import(self, argv)`
        
        Usage: json_import --prefix=tag_prefix {{-|path}} {{-|tags.json}}
        Apply JSON data to path.
        A path named "-" indicates that paths should be read from
        the standard input.
        The JSON tag data come from the file "tags.json"; the name
        "-" indicates that the JSON data should be read from the
        standard input.
        
        ### Method `FSTagsCommand.cmd_ln(self, argv)`
        
        Usage: {cmd} [-finv] srcpath dstpath, {cmd} [-finv] srcpaths... dstdirpath
        POSIX ln(1) equivalent, but also copying the tags:
        link files and their tags into targetdir.
        -f  Force: remove destination if it exists.
        -i  Interactive: fail if the destination exists.
        -n  No remove: fail if the destination exists.
        -v  Verbose: show linked files.
        
        ### Method `FSTagsCommand.cmd_ls(self, argv)`
        
        Usage: {cmd} [-d] [--direct] [-o output_format] [paths...]
        List files from paths and their tags.
        -d          Treat directories like files, do not recurse.
        --direct    List direct tags instead of all tags.
        -o output_format
                    Use output_format as a Python format string to lay out
                    the listing.
                    Default: {LS_OUTPUT_FORMAT_DEFAULT}
        
        ### Method `FSTagsCommand.cmd_mv(self, argv)`
        
        Usage: {cmd} [-finv] srcpath dstpath, {cmd} [-finv] srcpaths... dstdirpath
        POSIX mv(1) equivalent, but also copying the tags:
        move files and their tags into targetdir.
        -f  Force: remove destination if it exists.
        -i  Interactive: fail if the destination exists.
        -n  No remove: fail if the destination exists.
        -v  Verbose: show moved files.
        
        ### Method `FSTagsCommand.cmd_ns(self, argv)`
        
        Usage: {cmd} [-d] [--direct] [paths...]
        Report on the available primary namespace fields for formatting.
        Note that because the namespace used for formatting has
        inferred field names there are also unshown secondary field
        names available in format strings.
        -d          Treat directories like files, do not recurse.
        --direct    List direct tags instead of all tags.
        
        ### Method `FSTagsCommand.cmd_ont(self, argv)`
        
        Ontology operations.
        
        Usage: {cmd} [subcommand [args...]]
          With no arguments, print the ontology.
        
        ### Method `FSTagsCommand.cmd_rename(self, argv)`
        
        Usage: {cmd} -n newbasename_format paths...
        Rename paths according to a format string.
        -n newbasename_format
            Use newbasename_format as a Python format string to
            compute the new basename for each path.
        
        ### Method `FSTagsCommand.cmd_scrub(self, argv)`
        
        Usage: {cmd} paths...
        Remove all tags for missing paths.
        If a path is a directory, scrub the immediate paths in the directory.
        
        ### Method `FSTagsCommand.cmd_tag(self, argv)`
        
        Usage: {cmd} {{-|path}} {{tag[=value]|-tag}}...
        Tag a path with multiple tags.
        With the form "-tag", remove that tag from the direct tags.
        A path named "-" indicates that paths should be read from the
        standard input.
        
        ### Method `FSTagsCommand.cmd_tagfile(self, argv)`
        
        Usage: {cmd} tagfile_path [subcommand ...]
        Subcommands:
          tag tagset_name {{tag[=value]|-tag}}...
            Directly modify tag_name within the tag file tagfile_path.
        
        ### Method `FSTagsCommand.cmd_tagpaths(self, argv, options)`
        
        Usage: {cmd} {{tag[=value]|-tag}} {{-|paths...}}
        Tag multiple paths.
        With the form "-tag", remove the tag from the immediate tags.
        A single path named "-" indicates that paths should be read
        from the standard input.
        
        ### Method `FSTagsCommand.cmd_test(self, argv)`
        
        Usage: {cmd} [--direct] path {{tag[=value]|-tag}}...
        Test whether the path matches all the constraints.
        --direct    Use direct tags instead of all tags.
        
        ### Method `FSTagsCommand.cmd_xattr_export(self, argv)`
        
        Usage: {cmd} {{-|paths...}}
        Import tag information from extended attributes.
        
        ### Method `FSTagsCommand.cmd_xattr_import(self, argv, options)`
        
        Usage: {cmd} {{-|paths...}}
        Update extended attributes from tags.
        
        ### Method `FSTagsCommand.import_csv_file(self, f, *, convert_name=None)`
        
        Import CSV data from the file `f`.
        
        Parameters:
        * `f`: the source CSV file
        * `convert_name`: a callable to convert each input name
          into a file path; the default is to use the input name directly
        
        ### Method `FSTagsCommand.run_context(self)`
        
        Push the `FSTags`.
        
        ## Class `FSTagsConfig`
        
        A configuration for fstags.
        
        ### Method `FSTagsConfig.__init__(self, rcfilepath=None)`
        
        Initialise the config.
        
        Parameters:
        * `rcfilepath`: the path to the confguration file
          If `None`, default to `'~/.fstagsrc'` (from `RCFILE`).
        
        ### Method `FSTagsConfig.cascade_rules_from_config(config)`
        
        Return a list of the `[cascade]` tag rules from the config.
        
        ### Method `FSTagsConfig.filename_rules_from_config(config)`
        
        Return a list of the `[filename_autotag]` tag rules from the config.
        
        ### Method `FSTagsConfig.load_config(rcfilepath)`
        
        Read an rc file, return a `ConfigParser` instance.
        
        ### Property `FSTagsConfig.tagsfile_basename`
        
        The tags filename, default `'.fstags'`.
        
        ## Class `FSTagsTagFile(cs.tagset.TagFile,cs.obj.SingletonMixin,cs.tagset.TagSets,cs.resources.MultiOpenMixin,HasFSTagsMixin)`
        
        A `FSTagsTagFile` indexing `TagSet`s for file paths
        which lives in the file path's directory.
        
        ### Method `FSTagsTagFile.TagSetClass(self, name: str) -> cs.fstags.TaggedPath`
        
        factory to create a `TaggedPath` from a `name`.
        
        ### Property `FSTagsTagFile.dirpath`
        
        Return the path of the directory associated with this `FSTagsTagFile`.
        
        ## Function `get_xattr_value(filepath, xattr_name)`
        
        Read the extended attribute `xattr_name` of `filepath`.
        Return the extended attribute value as a string,
        or `None` if the attribute does not exist.
        
        Parameters:
        * `filepath`: the filesystem path to update
        * `xattr_name`: the extended attribute to obtain
          if this is a `str`, the attribute is the UTF-8 encoding of that name.
        
        ## Class `HasFSTagsMixin`
        
        Mixin providing an automatic `.fstags` property.
        
        ### Property `HasFSTagsMixin.fstags`
        
        Return the `.fstags` property,
        default a shared default `FSTags` instance.
        
        ## Function `is_valid_basename(name: str)`
        
        Test whether `name` is a valid basefile for something in a directory.
        
        ## Function `main(argv=None)`
        
        Command line mode.
        
        ## Function `rfilepaths(path, name_selector=None, U=None)`
        
        Generator yielding pathnames of files found under `path`.
        
        ## Function `rpaths(*a, **kw)`
        
        Recurse over `path`, yielding `(is_dir,subpath)`
        for all selected subpaths.
        
        ## Function `rsync_patterns(paths, top_path)`
        
        Return a list of rsync include lines
        suitable for use with the `--include-from` option.
        
        ## Class `TaggedPath(cs.tagset.TagSet,builtins.dict,cs.lex.FormatableMixin,cs.mappings.AttrableMappingMixin,HasFSTagsMixin)`
        
        Class to manipulate the tags for a specific path.
        
        ### Property `TaggedPath.all_tags`
        
        Cached cumulative tags for this path as a `TagSet`
        by merging the tags from the root to the path.
        
        Note that subsequent changes to some path component's `direct_tags`
        will not affect this `TagSet`.
        
        ### Method `TaggedPath.as_tags(self, prefix=None, all_tags=False)`
        
        Yield the tag data as `Tag`s.
        
        This overrides `TagSet.as_tags`,
        honouring an `optional `all_tags` parameter.
        
        ### Property `TaggedPath.basename`
        
        The name of the final path component.
        
        ### Method `TaggedPath.discard(self, name, value=None, *a, **kw)`
        
        pylint: disable=keyword-arg-before-vararg
        
        ### Method `TaggedPath.export_xattrs(self)`
        
        Update the extended attributes of the file.
        
        ### Method `TaggedPath.format_kwargs(self, *, direct=False)`
        
        Format arguments suitable for `str.format_map`.
        
        This returns an `ExtendedNamespace` from `TagSet.ns()`
        for a computed `TagSet`.
        
        In addition to the normal `TagSet.ns()` names
        the following additional names are available:
        * `filepath.basename`: basename of the `TaggedPath.filepath`
        * `filepath.pathname`: the `TaggedPath.filepath`
        * `filepath.encoded`: the JSON encoded filepath
        * `tags`: the `TagSet` as a string
        
        ### Method `TaggedPath.format_tagset(self, *, direct=False)`
        
        Compute a `TagSet` from this file's tags
        with additional derived tags.
        
        This can be converted into an `ExtendedNamespace`
        suitable for use with `str.format_map`
        via the `TagSet`'s `.format_kwargs()` method.
        
        In addition to the normal `TagSet.ns()` names
        the following additional names are available:
        * `filepath.basename`: basename of the `TaggedPath.filepath`
        * `filepath.ext`: the file extension of the basename
          of the `TaggedPath.filepath`
        * `filepath.pathname`: the `TaggedPath.filepath`
        * `filepath.encoded`: the JSON encoded filepath
        
        ### Method `TaggedPath.get_xattr_tagset(self, xattr_name=None)`
        
        Return a new `TagSet`
        from the extended attribute `xattr_name` of `self.filepath`.
        The default `xattr_name` is `XATTR_B` (`None`).
        
        ### Method `TaggedPath.import_xattrs(self)`
        
        Update the direct tags from the file's extended attributes.
        
        ### Method `TaggedPath.infer_from_basename(self, rules=None)`
        
        Apply `rules` to the basename of this `TaggedPath`,
        return a `TagSet` of inferred `Tag`s.
        
        Tag values from earlier rules override values from later rules.
        
        ### Method `TaggedPath.merged_tags(self)`
        
        Compute the cumulative tags for this path as a `TagSet`
        by merging the tags from the root to the path.
        
        ### Property `TaggedPath.name`
        
        The `.name` is `basename(self.filepath)`.
        
        ### Method `TaggedPath.save(self)`
        
        Update the associated `FSTagsTagFile`.
        
        ### Property `TaggedPath.tagfile`
        
        Return the `FSTagsTagFile` storing the state for this `TaggedPath`.
        
        ## Function `update_xattr_value(filepath, xattr_name, new_xattr_value)`
        
        Update the extended attributes of `filepath`
        with `new_xattr_value` for `xattr_name`.
        Return the previous value, or `None` if the attribute was missing.
        
        We avoid calling `os.setxattr` if the value will not change.
        
        Parameters:
        * `filepath`: the filesystem path to update
        * `xattr_name`: the extended attribute to update;
          if this is a `str`, the attribute is the UTF-8 encoding of that name.
        * `new_xattr_value`: the new extended attribute value, a `str`
          which should be the transcription of `TagSet`
          i.e. `str(tagset)`
        
        ## Function `verbose(msg, *a)`
        
        Emit message if in verbose mode.
        
        # Release Log
        
        
        
        *Release 20210306*:
        * FSTags: new tagfile_for(filepath) to obtain the TagFile for filepath.
        * FSTagsCommand: new -o ontology option to supply an ontology file for the FSTags.
        * FSTagsCommand.cmd_ont: drop -o/--ontology, superceded by global -o option.
        * Move BaseTagFile from cs.fstags to TagFile in cs.tagset.
        * FSTags.edit_dirpath: we now get (old_name,new_name,TaggedPath) back from edit_many, obviating the te_id_map.
        * TaggedPath: .name property returning basename(self.filepath), .set and .discard methods rejecting use of the 'name' tag.
        * FSTagsCommand: port to new cs.cmdutils API.
        * Many small refactors and bugfixes.
        
        *Release 20200717.1*:
        Add the manual page MarkDown source files. Note: well out of date, need updating.
        
        *Release 20200717*:
        DISTINFO: require cs.obj>=20200716 for SingletonMixin API change.
        
        *Release 20200716*:
        * Update for changed cs.obj.SingletonMixin API.
        * fstags: new "export" and "import" subcommands roughly paralleling those from "sqltags", providing CSV formatted export/import.
        * fstags export: ew -a (all paths) option - the default is not to not export paths with no tags.
        
        *Release 20200521.1*:
        fix DISTINFO.install_requires
        
        *Release 20200521*:
        * Add -i option to cp,ln,mv for command line compatibility, just disables -f.
        * New "rename" subcommand to rename files according to a format string.
        * Ontology support (optional).
        * Various classes are now singletons to avoid dissonance.
        * Fold "edittags" subcommand into "edit" via the "-d" (directories like files) option.
        * New "ns" subcommand reporting on the primary names available for formatting.
        * Accept [clausename]entryname as a format string to obtain the string from that entry of the config file.
        * Many bugfixes and improvements.
        
        *Release 20200229*:
        * New TaggedPath.modified property aliasing the TagSet.modified attribute.
        * ls: new -d option to treat directories like files (do not recurse), aiding reporting of tags for a directory.
        * find,ls subcommands: work off the realpath of the supplied top level path.
        * Tag: now subclasses namedtuple.
        * Rewrite rpaths() to use scandir and to also yield (is_dir,path) tuples.
        * TagSet, Tag, TagChoice moved into new cs.tagset module for reuse.
        * json_import: make --prefix mandatory, is "." as separator if not empty.
        * Move filename regexp rules to [filename_rules] config section.
        * New CascadeRule for representing a "target_tag_name = tag_name1 tag_name2..." config rules.
        * autotag: include the cascade rules in the autotagging after the filename rules.
        
        *Release 20200210*:
        * New "json_import" subcommand to import a JSON dict as tags, initial use case to load the metadata from youtube-dl.
        * New "scrub" command line operation, to purge tags of paths which do not exist.
        * New "cp", "ln" and "mv" subcommands to copy/link/move paths and take their tags with them.
        * New "test" subcommand to test paths against tag criteria, useful for find and scripts.
        * Small bugfixes.
        
        *Release 20200130*:
        * New FSTagsConfig class which parses the .fstagsrc as a .ini file; related adjustments.
        * New HasFSTagsMixin presenting a settable .fstags property with a shared default.
        * New xattr_import and xattr_export subcommands, remove implicit xattr access/update from other operations.
        * New TagSet.__len__ returning the number of tags.
        * Add "-" support for stdin to "tag" and "tagpaths" subcommands.
        
        *Release 20200113.2*:
        FSTagsCommand docstring tweak.
        
        *Release 20200113.1*:
        Small docstring updates.
        
        *Release 20200113*:
        Mirror tags to user.cs.fstags xattr to honour Linux namespace requirements. Add "filesize" to available tag string format (-o option). Small bugfixes.
        
        *Release 20191230*:
        * Command line: new "find" command to search a file tree based on tags.
        * Command line: new "mv" command to move a file and its tags.
        * Command line: Python string formats for "find" and "ls" output.
        * TaggedPath.autotag: new optional `no_save` parameter, default False, to suppress update of the associated .fstags file.
        * Inital and untested "mirror tags to xattrs" support.
        
        *Release 20191201*:
        New "edit" subcommand to rename files and edit tags.
        
        *Release 20191130.1*:
        Initial release: fstags, filesystem based tagging utility.
Keywords: python3
Platform: UNKNOWN
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Description-Content-Type: text/markdown
