mirror of https://github.com/patacrep/patacrep.git
Louis
9 years ago
11 changed files with 266 additions and 55 deletions
@ -0,0 +1,54 @@ |
|||||
|
"""Raw songbook utilities""" |
||||
|
|
||||
|
import logging |
||||
|
import os |
||||
|
import sys |
||||
|
import yaml |
||||
|
|
||||
|
from patacrep import encoding |
||||
|
import patacrep |
||||
|
|
||||
|
LOGGER = logging.getLogger() |
||||
|
|
||||
|
def open_songbook(filename): |
||||
|
"""Open songbook, and return a raw songbook object. |
||||
|
|
||||
|
:param str filename: Filename of the yaml songbook. |
||||
|
:rvalue: dict |
||||
|
:return: Songbook, as a dictionary. |
||||
|
""" |
||||
|
if os.path.exists(filename + ".sb") and not os.path.exists(filename): |
||||
|
filename += ".sb" |
||||
|
|
||||
|
try: |
||||
|
with patacrep.encoding.open_read(filename) as songbook_file: |
||||
|
songbook = yaml.load(songbook_file) |
||||
|
if 'encoding' in songbook: |
||||
|
with encoding.open_read( |
||||
|
filename, |
||||
|
encoding=songbook['encoding'] |
||||
|
) as songbook_file: |
||||
|
songbook = yaml.load(songbook_file) |
||||
|
except Exception as error: # pylint: disable=broad-except |
||||
|
raise patacrep.errors.YAMLError(str(error)) |
||||
|
|
||||
|
songbook['_basename'] = os.path.basename(filename)[:-3] |
||||
|
|
||||
|
# Gathering datadirs |
||||
|
datadirs = [] |
||||
|
if 'datadir' in songbook: |
||||
|
if isinstance(songbook['datadir'], str): |
||||
|
songbook['datadir'] = [songbook['datadir']] |
||||
|
datadirs += [ |
||||
|
os.path.join( |
||||
|
os.path.dirname(os.path.abspath(filename)), |
||||
|
path |
||||
|
) |
||||
|
for path in songbook['datadir'] |
||||
|
] |
||||
|
# Default value |
||||
|
datadirs.append(os.path.dirname(os.path.abspath(filename))) |
||||
|
|
||||
|
songbook['datadir'] = datadirs |
||||
|
|
||||
|
return songbook |
@ -0,0 +1,116 @@ |
|||||
|
#!/bin/env python3 |
||||
|
|
||||
|
"""Command line client to :mod:`tools`""" |
||||
|
|
||||
|
import argparse |
||||
|
import logging |
||||
|
import operator |
||||
|
import os |
||||
|
import pkgutil |
||||
|
import re |
||||
|
import sys |
||||
|
|
||||
|
import patacrep |
||||
|
|
||||
|
# Logging configuration |
||||
|
logging.basicConfig(level=logging.INFO) |
||||
|
LOGGER = logging.getLogger() |
||||
|
|
||||
|
def _execlp(program, args): |
||||
|
"""Call :func:`os.execlp`, adding `program` as the first argument to itself.""" |
||||
|
return os.execlp(program, program, *args) |
||||
|
|
||||
|
def _iter_subcommands(): |
||||
|
"""Iterate over subcommands. |
||||
|
|
||||
|
The objects returned are tuples of: |
||||
|
- the name of the command; |
||||
|
- its description; |
||||
|
- the function to call to execute the subcommand. |
||||
|
""" |
||||
|
subcommands = [] |
||||
|
|
||||
|
# Get python subcommands |
||||
|
path = [os.path.join(item, "patacrep", "tools") for item in sys.path] |
||||
|
prefix = "patacrep.tools." |
||||
|
module_re = re.compile(r'{}(?P<subcommand>[^\.]*)\.__main__'.format(prefix)) |
||||
|
for module_loader, name, _ in pkgutil.walk_packages(path, prefix): |
||||
|
match = module_re.match(name) |
||||
|
if match: |
||||
|
module = module_loader.find_module(match.string).load_module() |
||||
|
if hasattr(module, "SUBCOMMAND_DESCRIPTION"): |
||||
|
subcommands.append(match.groupdict()['subcommand']) |
||||
|
yield ( |
||||
|
match.groupdict()['subcommand'], |
||||
|
getattr(module, "SUBCOMMAND_DESCRIPTION"), |
||||
|
module.main, |
||||
|
) |
||||
|
|
||||
|
class ArgumentParser(argparse.ArgumentParser): |
||||
|
"""Proxy class to circumvent an :mod:`argparse` bug. |
||||
|
|
||||
|
Contrarily to what documented, the `argparse.REMAINDER |
||||
|
<https://docs.python.org/3/library/argparse.html#nargs>`_ `nargs` setting |
||||
|
does not include the remainder arguments if the first one begins with `-`. |
||||
|
|
||||
|
This bug is reperted as `17050 <https://bugs.python.org/issue17050>`_. This |
||||
|
class can be deleted once this bug has been fixed. |
||||
|
""" |
||||
|
|
||||
|
def parse_args(self, args=None, namespace=None): |
||||
|
if args is None: |
||||
|
args = sys.argv[1:] |
||||
|
subcommands = [command[0] for command in set(_iter_subcommands())] |
||||
|
if len(args) > 0: |
||||
|
if args[0] in subcommands: |
||||
|
args = [args[0], "--"] + args[1:] |
||||
|
|
||||
|
value = super().parse_args(args, namespace) |
||||
|
|
||||
|
if hasattr(value, 'remainder'): |
||||
|
value.remainder = value.remainder[1:] |
||||
|
return value |
||||
|
|
||||
|
|
||||
|
def commandline_parser(): |
||||
|
"""Return a command line parser.""" |
||||
|
|
||||
|
parser = ArgumentParser( |
||||
|
prog="patatools", |
||||
|
description=( |
||||
|
"Miscellaneous tools for patacrep." |
||||
|
), |
||||
|
formatter_class=argparse.RawTextHelpFormatter, |
||||
|
) |
||||
|
|
||||
|
parser.add_argument( |
||||
|
'--version', |
||||
|
help='Show version', |
||||
|
action='version', |
||||
|
version='%(prog)s ' + patacrep.__version__ |
||||
|
) |
||||
|
|
||||
|
subparsers = parser.add_subparsers( |
||||
|
title="Subcommands", |
||||
|
description="List of available subcommands.", |
||||
|
) |
||||
|
|
||||
|
for command, message, function in sorted(_iter_subcommands(), key=operator.itemgetter(0)): |
||||
|
sub1 = subparsers.add_parser(command, help=message, add_help=False) |
||||
|
sub1.add_argument('remainder', nargs=argparse.REMAINDER) |
||||
|
sub1.set_defaults(function=function) |
||||
|
|
||||
|
return parser |
||||
|
|
||||
|
def main(): |
||||
|
"""Main function""" |
||||
|
|
||||
|
parser = commandline_parser() |
||||
|
args = parser.parse_args() |
||||
|
if hasattr(args, "function"): |
||||
|
args.function(args.remainder) |
||||
|
else: |
||||
|
parser.error("Missing command.") |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
main() |
@ -0,0 +1,73 @@ |
|||||
|
"""`patatools cache` command: cache manipulation.""" |
||||
|
|
||||
|
import argparse |
||||
|
import logging |
||||
|
import os |
||||
|
import shutil |
||||
|
import sys |
||||
|
import textwrap |
||||
|
|
||||
|
from patacrep import errors |
||||
|
from patacrep import songbook |
||||
|
|
||||
|
LOGGER = logging.getLogger("patatools.cache") |
||||
|
SUBCOMMAND_DESCRIPTION = "Perform operations on cache." |
||||
|
|
||||
|
def filename(name): |
||||
|
"""Check that argument is an existing, readable file name. |
||||
|
|
||||
|
Return the argument for convenience. |
||||
|
""" |
||||
|
if os.path.isfile(name) and os.access(name, os.R_OK): |
||||
|
return name |
||||
|
raise argparse.ArgumentTypeError("Cannot read file '{}'.".format(name)) |
||||
|
|
||||
|
def commandline_parser(): |
||||
|
"""Return a command line parser.""" |
||||
|
|
||||
|
parser = argparse.ArgumentParser( |
||||
|
prog="patatools cache", |
||||
|
description=SUBCOMMAND_DESCRIPTION, |
||||
|
formatter_class=argparse.RawTextHelpFormatter, |
||||
|
) |
||||
|
|
||||
|
subparsers = parser.add_subparsers( |
||||
|
description="", |
||||
|
dest="command", |
||||
|
) |
||||
|
subparsers.required = True |
||||
|
|
||||
|
clear = subparsers.add_parser( |
||||
|
"clear", |
||||
|
description="Delete cache.", |
||||
|
help="Delete cache.", |
||||
|
) |
||||
|
clear.add_argument( |
||||
|
'songbook', |
||||
|
metavar="SONGBOOK", |
||||
|
help=textwrap.dedent("""Songbook file to used to look for cache path."""), |
||||
|
type=filename, |
||||
|
) |
||||
|
clear.set_defaults(command=do_clear) |
||||
|
|
||||
|
return parser |
||||
|
|
||||
|
def do_clear(namespace): |
||||
|
"""Execute the `patatools cache clear` command.""" |
||||
|
for datadir in songbook.open_songbook(namespace.songbook)['datadir']: |
||||
|
cachedir = os.path.join(datadir, ".cache") |
||||
|
LOGGER.info("Deleting cache directory '{}'...".format(cachedir)) |
||||
|
if os.path.isdir(cachedir): |
||||
|
shutil.rmtree(cachedir) |
||||
|
|
||||
|
def main(args=None): |
||||
|
"""Main function: run from command line.""" |
||||
|
options = commandline_parser().parse_args(args) |
||||
|
try: |
||||
|
options.command(options) |
||||
|
except errors.SongbookError as error: |
||||
|
LOGGER.error(str(error)) |
||||
|
sys.exit(1) |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
main() |
@ -0,0 +1,6 @@ |
|||||
|
#! /bin/sh |
||||
|
|
||||
|
# Do not edit this file. This file is just a helper file for development test. |
||||
|
# It is not part of the distributed software. |
||||
|
|
||||
|
python -m patacrep.tools $@ |
Loading…
Reference in new issue