From ae6ebc97effa3a58a577273c43bf1665e3727b2c Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Mon, 18 Nov 2019 10:01:15 +0100 Subject: Fixed spelling --- patternutils/commands/targs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patternutils/commands/targs.py b/patternutils/commands/targs.py index 63955ae..5971ea2 100644 --- a/patternutils/commands/targs.py +++ b/patternutils/commands/targs.py @@ -49,7 +49,7 @@ def run_command( help='Redirect stdout to /dev/null') @click.option('--redirect-stderr', is_flag=True, default=False, help='Redirect stderr to /dev/null') -@click.option('--stream', if_flag=True, defaults=False, +@click.option('--stream', is_flag=True, defaults=False, help='Input is a stream of JSON objects') @click.version_option() @click.argument('command') -- cgit v1.3.1 From 98d2d81045c1687caf0687502b98b21dd3eea255 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Mon, 18 Nov 2019 10:01:50 +0100 Subject: Bumped version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 80aca3e..f1e4de2 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ URL = 'https://projects.metalgamer.eu/patternutils' EMAIL = 'dennis.fink@c3l.lu' AUTHOR = 'Dennis Fink' -VERSION = '0.0.5' +VERSION = '0.0.6' ENTRY_POINTS = { 'console_scripts': [ 'pmatch=patternutils.commands.pmatch:pmatch', -- cgit v1.3.1 -- cgit v1.3.1 From 579ab3ee72d46454d62a55dc97902ce45d922356 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Mon, 18 Nov 2019 10:06:08 +0100 Subject: Updated PKGBUILD --- PKGBUILD/PKGBUILD | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PKGBUILD/PKGBUILD b/PKGBUILD/PKGBUILD index a24538b..b304302 100644 --- a/PKGBUILD/PKGBUILD +++ b/PKGBUILD/PKGBUILD @@ -1,22 +1,22 @@ # Maintainer: Dennis Fink pkgname=patternutils -pkgver=0.0.5 +pkgver=0.0.6 pkgrel=1 pkgdesc="Combine regular expressions with template engines in a powerful matter." arch=('any') url="https://projects.metalgamer.eu/patternutils" license=('GPL3') depends=('python' 'python-click' 'python-jinja' 'python-pygments') -source=('patternutils-0.0.5.zip::https://projects.metalgamer.eu/patternutils/archive/523a18c4fb635a42f935bc2907b8adba207ca000.zip?subrepos=false') -sha512sums=('466273a330acbd12b3e8004324dd6c03f75d48f91edbc4f495e7929b29b6a8369bfa9c6650d7d6cba0ebff679688f99acf02cb0b380377a447797e81147ec872') +source=('patternutils-0.0.6.zip::https://projects.metalgamer.eu/patternutils/archive/197b847bbf5304f568c7a7b36af002df601367c7.zip?subrepos=false') +sha512sums=('683bd060390e8654519bf5bc61876164a87fcea06c7c98a5ac9a8c1cda6c20548e0fd23936c4973ec36e1d50f3227f030b3299aafd5af710196c81f2258a21e1') build() { - cd "$srcdir/$pkgname-523a18c4fb63" + cd "$srcdir/$pkgname-197b847bbf53" python setup.py build } package() { - cd "$srcdir/$pkgname-523a18c4fb63" + cd "$srcdir/$pkgname-197b847bbf53" python setup.py install --root="$pkgdir" --optimize=1 } -- cgit v1.3.1 From bfc52551b5695c0b3f8779f40a0023c8852ab4ce Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Mon, 18 Nov 2019 10:14:19 +0100 Subject: Updated hgignore --- .hgignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.hgignore b/.hgignore index cfd8ddc..fc3ed61 100644 --- a/.hgignore +++ b/.hgignore @@ -11,3 +11,5 @@ dist/* PKGBUILD/pkg/* PKGBUILD/src/* PKGBUILD/*.zip +PKGBUILD/.git/* +PKGBUILD/.SRCINFO -- cgit v1.3.1 From 1ca9f29a4ca25b7a0d70bde1697b528482772a06 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Mon, 18 Nov 2019 16:47:10 +0100 Subject: Add a more helpful error message, if multiple files are found. --- patternutils/commands/patterncfg.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/patternutils/commands/patterncfg.py b/patternutils/commands/patterncfg.py index 96e9ac7..5215d56 100644 --- a/patternutils/commands/patterncfg.py +++ b/patternutils/commands/patterncfg.py @@ -75,7 +75,7 @@ def remove(command: Optional[str], name: str) -> None: click.secho('No files found!', fg='red', err=True) raise SystemExit elif len(files) != 1: - click.secho('Multiple files found!', fg='red', err=True) + click.secho('Multiple files found! Please specify the command from which to remove the file.', fg='red', err=True) for f in files: click.secho(f, fg='red', err=True) raise SystemExit @@ -96,7 +96,7 @@ def view(name: str, command: str, color: bool) -> None: click.secho('No files found!', fg='red', err=True) raise SystemExit elif len(files) != 1: - click.secho('Multiple files found!', fg='red', err=True) + click.secho('Multiple files found! Please specify the command from which to view the file.', fg='red', err=True) for f in files: click.secho(f, fg='red', err=True) raise SystemExit @@ -130,7 +130,7 @@ def edit(name: str, command: str) -> None: click.secho('No files found!', fg='red', err=True) raise SystemExit elif len(files) != 1: - click.secho('Multiple files found!', fg='red', err=True) + click.secho('Multiple files found! Please specify the command from which to edit the file.', fg='red', err=True) for f in files: click.secho(f, fg='red', err=True) raise SystemExit -- cgit v1.3.1 From 64295b80512a7a448d5a42803fa3fbac22d7bd25 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Mon, 18 Nov 2019 16:48:14 +0100 Subject: Bumped version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index f1e4de2..922e7e5 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ URL = 'https://projects.metalgamer.eu/patternutils' EMAIL = 'dennis.fink@c3l.lu' AUTHOR = 'Dennis Fink' -VERSION = '0.0.6' +VERSION = '0.0.7' ENTRY_POINTS = { 'console_scripts': [ 'pmatch=patternutils.commands.pmatch:pmatch', -- cgit v1.3.1 -- cgit v1.3.1 From 6763fe35f913e5e6ddc3d6d594a276ce48044006 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Mon, 18 Nov 2019 20:30:57 +0100 Subject: Updated PKGBUILD --- PKGBUILD/PKGBUILD | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PKGBUILD/PKGBUILD b/PKGBUILD/PKGBUILD index b304302..4e011f3 100644 --- a/PKGBUILD/PKGBUILD +++ b/PKGBUILD/PKGBUILD @@ -1,22 +1,22 @@ # Maintainer: Dennis Fink pkgname=patternutils -pkgver=0.0.6 +pkgver=0.0.7 pkgrel=1 pkgdesc="Combine regular expressions with template engines in a powerful matter." arch=('any') url="https://projects.metalgamer.eu/patternutils" license=('GPL3') depends=('python' 'python-click' 'python-jinja' 'python-pygments') -source=('patternutils-0.0.6.zip::https://projects.metalgamer.eu/patternutils/archive/197b847bbf5304f568c7a7b36af002df601367c7.zip?subrepos=false') -sha512sums=('683bd060390e8654519bf5bc61876164a87fcea06c7c98a5ac9a8c1cda6c20548e0fd23936c4973ec36e1d50f3227f030b3299aafd5af710196c81f2258a21e1') +source=('patternutils-0.0.7.zip::https://projects.metalgamer.eu/patternutils/archive/63e2ad2d42116041db43b33f5ad0aafe84ec38ad.zip?subrepos=false') +sha512sums=('efbae7ecd8eb17564db574fa4a8bc573ce0203fb7b6130ad118d695f3ba4cd4b1f66c2fd469a8c3003e7538467ee4d54a7b30d02dd3f28afe12b4c012e52a9bc') build() { - cd "$srcdir/$pkgname-197b847bbf53" + cd "$srcdir/$pkgname-63e2ad2d4211" python setup.py build } package() { - cd "$srcdir/$pkgname-197b847bbf53" + cd "$srcdir/$pkgname-63e2ad2d4211" python setup.py install --root="$pkgdir" --optimize=1 } -- cgit v1.3.1 From 9c096d663b113e40e9df30f47dd5133e69f6d03d Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Fri, 29 Nov 2019 15:16:28 +0100 Subject: Run black autoformatter on files --- patternutils/commands/patterncfg.py | 126 ++++++++++++++++++++++++------------ patternutils/commands/pmatch.py | 110 ++++++++++++++++++++----------- patternutils/commands/targs.py | 79 +++++++++++++--------- patternutils/commands/tln.py | 117 ++++++++++++++++++++++----------- patternutils/commands/tmv.py | 101 ++++++++++++++++++++--------- patternutils/config.py | 12 ++-- patternutils/match.py | 4 +- patternutils/template.py | 20 +++--- patternutils/utils.py | 12 ++-- setup.py | 40 ++++++------ 10 files changed, 398 insertions(+), 223 deletions(-) diff --git a/patternutils/commands/patterncfg.py b/patternutils/commands/patterncfg.py index 5215d56..b75fbdf 100644 --- a/patternutils/commands/patterncfg.py +++ b/patternutils/commands/patterncfg.py @@ -18,100 +18,131 @@ else: from .. import config -CURRENT_SUPPORTED_PROGRAMS = ('pmatch', 'tmv', 'targs', 'tln') +CURRENT_SUPPORTED_PROGRAMS = ("pmatch", "tmv", "targs", "tln") -@click.group(context_settings={'help_option_names': ('-h', '--help', '-?')}) +@click.group(context_settings={"help_option_names": ("-h", "--help", "-?")}) def patterncfg() -> None: pass -@patterncfg.command(name='init', help='initialize config folders') +@patterncfg.command(name="init", help="initialize config folders") def init() -> None: for dir in CURRENT_SUPPORTED_PROGRAMS: os.makedirs(os.path.join(config.CONFIG_PATH, dir), exist_ok=True) -@patterncfg.command(name='list', help='list all patternutils template files') +@patterncfg.command(name="list", help="list all patternutils template files") def list() -> None: try: for d in os.listdir(config.CONFIG_PATH): - click.secho(d, fg='blue') + click.secho(d, fg="blue") for f in os.listdir(os.path.join(config.CONFIG_PATH, d)): - click.echo('└── {}'.format(f)) + click.echo("└── {}".format(f)) except FileNotFoundError as e: - click.secho('{} not found! Please run patterncfg init first.'.format(e.filename), fg='red', err=True) + click.secho( + "{} not found! Please run patterncfg init first.".format(e.filename), + fg="red", + err=True, + ) raise SystemExit -@patterncfg.command(name='add', help='add new template file') -@click.option('-t', '--template-engine', default=None, type=click.Choice(('python', 'jinja2')), - help='select the template engine to use. Only applicable for tmv, targs and tln') -@click.argument('command', required=True, type=click.Choice(CURRENT_SUPPORTED_PROGRAMS)) -@click.argument('name') +@patterncfg.command(name="add", help="add new template file") +@click.option( + "-t", + "--template-engine", + default=None, + type=click.Choice(("python", "jinja2")), + help="select the template engine to use. Only applicable for tmv, targs and tln", +) +@click.argument("command", required=True, type=click.Choice(CURRENT_SUPPORTED_PROGRAMS)) +@click.argument("name") def add(template_engine: Optional[str], command: str, name: str) -> None: - if command == 'pmatch': - fileext = 'regex' + if command == "pmatch": + fileext = "regex" else: - if template_engine not in ('python', 'jinja2'): - fileext = 'python' + if template_engine not in ("python", "jinja2"): + fileext = "python" else: fileext = template_engine - filename = os.path.join(config.CONFIG_PATH, command, '{}.{}'.format(name, fileext)) + filename = os.path.join(config.CONFIG_PATH, command, "{}.{}".format(name, fileext)) click.edit(filename=filename) -@patterncfg.command(name='remove', help='remove template file') -@click.option('-c', '--command', default=None, type=click.Choice(CURRENT_SUPPORTED_PROGRAMS), - help='select the command from which to remove the file') -@click.argument('name') +@patterncfg.command(name="remove", help="remove template file") +@click.option( + "-c", + "--command", + default=None, + type=click.Choice(CURRENT_SUPPORTED_PROGRAMS), + help="select the command from which to remove the file", +) +@click.argument("name") def remove(command: Optional[str], name: str) -> None: files = config.find_templates(name, command) if not files: - click.secho('No files found!', fg='red', err=True) + click.secho("No files found!", fg="red", err=True) raise SystemExit elif len(files) != 1: - click.secho('Multiple files found! Please specify the command from which to remove the file.', fg='red', err=True) + click.secho( + "Multiple files found! Please specify the command from which to remove the file.", + fg="red", + err=True, + ) for f in files: - click.secho(f, fg='red', err=True) + click.secho(f, fg="red", err=True) raise SystemExit else: os.remove(files[0]) -@patterncfg.command(name='view', help='view template file') -@click.option('-c', '--command', default=None, type=click.Choice(CURRENT_SUPPORTED_PROGRAMS), - help='select the command from which to view the file') -@click.option('--color/--no-color', is_flag=True, default=has_pygments, - help='Colorize output using pygments') -@click.argument('name') +@patterncfg.command(name="view", help="view template file") +@click.option( + "-c", + "--command", + default=None, + type=click.Choice(CURRENT_SUPPORTED_PROGRAMS), + help="select the command from which to view the file", +) +@click.option( + "--color/--no-color", + is_flag=True, + default=has_pygments, + help="Colorize output using pygments", +) +@click.argument("name") def view(name: str, command: str, color: bool) -> None: files = config.find_templates(name, command) if not files: - click.secho('No files found!', fg='red', err=True) + click.secho("No files found!", fg="red", err=True) raise SystemExit elif len(files) != 1: - click.secho('Multiple files found! Please specify the command from which to view the file.', fg='red', err=True) + click.secho( + "Multiple files found! Please specify the command from which to view the file.", + fg="red", + err=True, + ) for f in files: - click.secho(f, fg='red', err=True) + click.secho(f, fg="red", err=True) raise SystemExit else: filename = files[0] try: - with open(filename, encoding='utf-8') as fd: + with open(filename, encoding="utf-8") as fd: text = fd.read() except FileNotFoundError: - click.secho('File not found!', fg='red', err=True) + click.secho("File not found!", fg="red", err=True) raise SystemExit else: if color: - if filename.endswith('jinja2'): + if filename.endswith("jinja2"): lexer = DjangoLexer else: lexer = Python3Lexer @@ -119,20 +150,29 @@ def view(name: str, command: str, color: bool) -> None: click.echo(text[:-1]) -@patterncfg.command(name='edit', help='edit a template file') -@click.option('-c', '--command', default=None, type=click.Choice(CURRENT_SUPPORTED_PROGRAMS), - help='select the command from which to edit the file') -@click.argument('name') +@patterncfg.command(name="edit", help="edit a template file") +@click.option( + "-c", + "--command", + default=None, + type=click.Choice(CURRENT_SUPPORTED_PROGRAMS), + help="select the command from which to edit the file", +) +@click.argument("name") def edit(name: str, command: str) -> None: files = config.find_templates(name, command) if not files: - click.secho('No files found!', fg='red', err=True) + click.secho("No files found!", fg="red", err=True) raise SystemExit elif len(files) != 1: - click.secho('Multiple files found! Please specify the command from which to edit the file.', fg='red', err=True) + click.secho( + "Multiple files found! Please specify the command from which to edit the file.", + fg="red", + err=True, + ) for f in files: - click.secho(f, fg='red', err=True) + click.secho(f, fg="red", err=True) raise SystemExit else: filename = files[0] diff --git a/patternutils/commands/pmatch.py b/patternutils/commands/pmatch.py index 383ef8b..bd88a03 100644 --- a/patternutils/commands/pmatch.py +++ b/patternutils/commands/pmatch.py @@ -13,7 +13,9 @@ from .. import match as mat from .. import config -def walk(dir: str, recursive: bool = False, match_directories: bool = False) -> Generator[os.DirEntry, None, None]: +def walk( + dir: str, recursive: bool = False, match_directories: bool = False +) -> Generator[os.DirEntry, None, None]: for entry in os.scandir(dir): is_dir = entry.is_dir() if recursive and is_dir: @@ -25,9 +27,7 @@ def walk(dir: str, recursive: bool = False, match_directories: bool = False) -> def apply_regex( - walk_function: Iterator[Any], - regex_pattern: Pattern[str], - match_full_path: bool, + walk_function: Iterator[Any], regex_pattern: Pattern[str], match_full_path: bool, ) -> Tuple[List[Dict[str, str]], bool]: matches = [] @@ -37,14 +37,14 @@ def apply_regex( try: match = mat.apply(subject, regex_pattern) except ValueError: - click.secho('{} did not match'.format(subject), fg='red', err=True) + click.secho("{} did not match".format(subject), fg="red", err=True) has_invalid_matches = True else: - match['_path'] = f.path - match['_name'] = f.name - match['_abspath'] = os.path.abspath(f.path) - match['_realpath'] = os.path.realpath(f.path) - match['_relpath'] = os.path.relpath(f.path) + match["_path"] = f.path + match["_name"] = f.name + match["_abspath"] = os.path.abspath(f.path) + match["_realpath"] = os.path.realpath(f.path) + match["_relpath"] = os.path.relpath(f.path) matches.append(match) return matches, has_invalid_matches @@ -57,26 +57,58 @@ def json_dumps(data: Any, human_readable: bool = False) -> str: return json.dumps(data) -@click.command(context_settings={'help_option_names': ('-h', '--help', '-?')}) -@click.option('-d', '--directory', multiple=True, default=['./']) -@click.option('-m', '--match-directories', is_flag=True, default=False, - help='search directory name also for matches') -@click.option('-r', '--recursive', is_flag=True, default=False, - help='search directories recursively') -@click.option('--abort-on-no-match', is_flag=True, default=False, - help='exit if a name does not match the INPUT_PATTERN') -@click.option('--match-full-path', is_flag=True, default=False, - help='match on full path instead of only filename') -@click.option('-p', '--use-predefined-pattern', is_flag=True, default=False, - help='use predefined regex pattern') -@click.option('--stream', is_flag=True, default=False, - help='Output a stream of objects instead a list of objects') -@click.option('--human-readable', is_flag=True, default=False, - help='output the JSON in a human readable format') -@click.option('-v', '--verbose', is_flag=True, default=False, - help='explain what is being done') +@click.command(context_settings={"help_option_names": ("-h", "--help", "-?")}) +@click.option("-d", "--directory", multiple=True, default=["./"]) +@click.option( + "-m", + "--match-directories", + is_flag=True, + default=False, + help="search directory name also for matches", +) +@click.option( + "-r", + "--recursive", + is_flag=True, + default=False, + help="search directories recursively", +) +@click.option( + "--abort-on-no-match", + is_flag=True, + default=False, + help="exit if a name does not match the INPUT_PATTERN", +) +@click.option( + "--match-full-path", + is_flag=True, + default=False, + help="match on full path instead of only filename", +) +@click.option( + "-p", + "--use-predefined-pattern", + is_flag=True, + default=False, + help="use predefined regex pattern", +) +@click.option( + "--stream", + is_flag=True, + default=False, + help="Output a stream of objects instead a list of objects", +) +@click.option( + "--human-readable", + is_flag=True, + default=False, + help="output the JSON in a human readable format", +) +@click.option( + "-v", "--verbose", is_flag=True, default=False, help="explain what is being done" +) @click.version_option() -@click.argument('regex-pattern') +@click.argument("regex-pattern") def pmatch( regex_pattern: str, directory: List[str], @@ -92,27 +124,31 @@ def pmatch( if use_predefined_pattern: try: - regex_pattern, _ = config.load_template(regex_pattern, 'pmatch') + regex_pattern, _ = config.load_template(regex_pattern, "pmatch") except FileNotFoundError: - click.secho('File not found!', fg='red', err=True) + click.secho("File not found!", fg="red", err=True) raise SystemExit except RuntimeError: - click.secho('Multiple files found!', fg='red', err=True) + click.secho("Multiple files found!", fg="red", err=True) raise SystemExit try: regex_pattern_c = re.compile(regex_pattern) except re.error as e: if verbose: - click.secho('Regular expression could not be compiled!', fg='red', err=True) - click.secho(e.msg, fg='red', err=True) # type: ignore + click.secho("Regular expression could not be compiled!", fg="red", err=True) + click.secho(e.msg, fg="red", err=True) # type: ignore raise SystemExit # Monkey patch walk function to include commandline options - walk_function = functools.partial(walk, recursive=recursive, match_directories=match_directories) + walk_function = functools.partial( + walk, recursive=recursive, match_directories=match_directories + ) new_walk = itertools.chain.from_iterable(map(walk_function, directory)) - matches, has_invalid_matches = apply_regex(new_walk, regex_pattern_c, match_full_path) + matches, has_invalid_matches = apply_regex( + new_walk, regex_pattern_c, match_full_path + ) if has_invalid_matches and abort_on_no_match: raise SystemExit @@ -124,5 +160,5 @@ def pmatch( click.echo(json_dumps(matches, human_readable)) -if __name__ == '__main__': +if __name__ == "__main__": pmatch() diff --git a/patternutils/commands/targs.py b/patternutils/commands/targs.py index 5971ea2..e25679f 100644 --- a/patternutils/commands/targs.py +++ b/patternutils/commands/targs.py @@ -34,25 +34,46 @@ def run_command( run(prepared_command) -@click.command(context_settings={'help_option_names': ('-h', '--help', '-?')}) -@click.option('--read-from', default='-', type=click.File('r')) -@click.option('-s', '--shell', is_flag=True, default=False, - help='run command in a shell') -@click.option('-t', '--template-engine', default='python', type=click.Choice(['python', 'jinja2']), - help='select the template engine to use') -@click.option('-v', '--verbose', is_flag=True, default=False, - help='explain what is being done') -@click.option('-P', '--max-procs', default=1, type=click.IntRange(min=0, clamp=True)) -@click.option('-p', '--use-predefined-template', is_flag=True, default=False, - help='use predefined template') -@click.option('--redirect-stdout', is_flag=True, default=False, - help='Redirect stdout to /dev/null') -@click.option('--redirect-stderr', is_flag=True, default=False, - help='Redirect stderr to /dev/null') -@click.option('--stream', is_flag=True, defaults=False, - help='Input is a stream of JSON objects') +@click.command(context_settings={"help_option_names": ("-h", "--help", "-?")}) +@click.option("--read-from", default="-", type=click.File("r")) +@click.option( + "-s", "--shell", is_flag=True, default=False, help="run command in a shell" +) +@click.option( + "-t", + "--template-engine", + default="python", + type=click.Choice(["python", "jinja2"]), + help="select the template engine to use", +) +@click.option( + "-v", "--verbose", is_flag=True, default=False, help="explain what is being done" +) +@click.option("-P", "--max-procs", default=1, type=click.IntRange(min=0, clamp=True)) +@click.option( + "-p", + "--use-predefined-template", + is_flag=True, + default=False, + help="use predefined template", +) +@click.option( + "--redirect-stdout", + is_flag=True, + default=False, + help="Redirect stdout to /dev/null", +) +@click.option( + "--redirect-stderr", + is_flag=True, + default=False, + help="Redirect stderr to /dev/null", +) +@click.option( + "--stream", is_flag=True, defaults=False, help="Input is a stream of JSON objects" +) @click.version_option() -@click.argument('command') +@click.argument("command") def targs( command: str, read_from: click.File, @@ -72,23 +93,23 @@ def targs( else: data = [json.loads(line) for line in read_from] except json.JSONDecodeError: - click.secho('JSON not valid!', fg='red', err=True) + click.secho("JSON not valid!", fg="red", err=True) raise SystemExit if use_predefined_template: try: - command, template_engine = config.load_template(command, 'targs') + command, template_engine = config.load_template(command, "targs") except FileNotFoundError: - click.secho('File not found!', fg='red', err=True) + click.secho("File not found!", fg="red", err=True) raise SystemExit except RuntimeError: - click.secho('Multiple files found!', fg='red', err=True) + click.secho("Multiple files found!", fg="red", err=True) raise SystemExit try: render = template.get_render_function(command, engine=template_engine) except RuntimeError: - click.secho('jinja2 not installed!', fg='red', err=True) + click.secho("jinja2 not installed!", fg="red", err=True) raise SystemExit max_procs = utils.max_procs() if max_procs == 0 else max_procs @@ -96,16 +117,10 @@ def targs( stdout = subprocess.DEVNULL if redirect_stdout else None stderr = subprocess.DEVNULL if redirect_stderr else None patched_subprocess = functools.partial( - subprocess.run, - shell=shell, - stdout=stdout, - stderr=stderr, + subprocess.run, shell=shell, stdout=stdout, stderr=stderr, ) patched_run_command = functools.partial( - run_command, - render=render, - run=patched_subprocess, - shell=shell, + run_command, render=render, run=patched_subprocess, shell=shell, ) if max_procs == 1: for r in data: @@ -115,5 +130,5 @@ def targs( p.map(patched_run_command, data) -if __name__ == '__main__': +if __name__ == "__main__": targs() diff --git a/patternutils/commands/tln.py b/patternutils/commands/tln.py index 27112ec..4e21f1f 100644 --- a/patternutils/commands/tln.py +++ b/patternutils/commands/tln.py @@ -20,32 +20,74 @@ def link_file(old_filename: str, new_filename: str, symbolic: bool) -> None: os.link(old_filename, new_filename) -@click.command(context_settings={'help_option_names': ('-h', '--help', '-?')}) -@click.option('-i', '--interactive', is_flag=True, default=False, - help='prompt wether to remove destinations') -@click.option('-e', '--editor', is_flag=True, default=False, - help='Open an editor before renaming files to allow manual changes') -@click.option('-f', '--force', is_flag=True, default=False, - help='remove existing destination files') -@click.option('-s', '--symbolic', is_flag=True, default=False, - help='make symbolic links instead of hard links') -@click.option('-t', '--template-engine', default='python', type=click.Choice(['python', 'jinja2']), - help='select the template engine to use') -@click.option('-k', '--key', default='_abspath', - help='select the key to use as the source file') -@click.option('--stream', is_flag=True, default=False, - help='Input is a stream of JSON objects') -@click.option('-p', '--use-predefined-template', is_flag=True, default=False, - help='use predefined template') -@click.option('--read-from', default='-', type=click.File('r')) -@click.option('--abort-on-path-exist', is_flag=True, default=False, - help='exit if a renamed path already exists') -@click.option('-n', '--dry-run', is_flag=True, default=False, - help='perform a trial run with no changes made') -@click.option('-v', '--verbose', is_flag=True, default=False, - help='explain what is being done') +@click.command(context_settings={"help_option_names": ("-h", "--help", "-?")}) +@click.option( + "-i", + "--interactive", + is_flag=True, + default=False, + help="prompt wether to remove destinations", +) +@click.option( + "-e", + "--editor", + is_flag=True, + default=False, + help="Open an editor before renaming files to allow manual changes", +) +@click.option( + "-f", + "--force", + is_flag=True, + default=False, + help="remove existing destination files", +) +@click.option( + "-s", + "--symbolic", + is_flag=True, + default=False, + help="make symbolic links instead of hard links", +) +@click.option( + "-t", + "--template-engine", + default="python", + type=click.Choice(["python", "jinja2"]), + help="select the template engine to use", +) +@click.option( + "-k", "--key", default="_abspath", help="select the key to use as the source file" +) +@click.option( + "--stream", is_flag=True, default=False, help="Input is a stream of JSON objects" +) +@click.option( + "-p", + "--use-predefined-template", + is_flag=True, + default=False, + help="use predefined template", +) +@click.option("--read-from", default="-", type=click.File("r")) +@click.option( + "--abort-on-path-exist", + is_flag=True, + default=False, + help="exit if a renamed path already exists", +) +@click.option( + "-n", + "--dry-run", + is_flag=True, + default=False, + help="perform a trial run with no changes made", +) +@click.option( + "-v", "--verbose", is_flag=True, default=False, help="explain what is being done" +) @click.version_option() -@click.argument('output-pattern') +@click.argument("output-pattern") def tln( output_pattern: str, interactive: bool, @@ -58,7 +100,8 @@ def tln( key: str, stream: bool, abort_on_path_exist: bool, - dry_run, bool, + dry_run, + bool, verbose: bool, ) -> None: @@ -68,39 +111,41 @@ def tln( else: data = [json.loads(line) for line in read_from] except json.JSONDecodeError: - click.secho('JSON not valid!', fg='red', err=True) + click.secho("JSON not valid!", fg="red", err=True) raise SystemExit if use_predefined_template: try: - output_pattern, template_engine = config.load_template(output_pattern, 'tln') + output_pattern, template_engine = config.load_template( + output_pattern, "tln" + ) except FileNotFoundError: - click.secho('File not found!', fg='red', err=True) + click.secho("File not found!", fg="red", err=True) raise SystemExit except RuntimeError: - click.secho('Multiple files found!', fg='red', err=True) + click.secho("Multiple files found!", fg="red", err=True) raise SystemExit try: render = template.get_render_function(output_pattern, engine=template_engine) except RuntimeError: - click.secho('jinja2 not installed!', fg='red', err=True) + click.secho("jinja2 not installed!", fg="red", err=True) raise SystemExit - new_filenames = dict((entry['_abspath'], render(**entry)) for entry in data) + new_filenames = dict((entry["_abspath"], render(**entry)) for entry in data) if editor: try: new_filenames = utils.edit(new_filenames) except RuntimeError: - click.secho('You edit is not parseable!', fg='red', err=True) + click.secho("You edit is not parseable!", fg="red", err=True) raise SystemExit has_existing = False non_existing = {} for old, new in new_filenames.items(): if os.path.exists(new): - click.secho('{} does exist!'.format(new), fg='red', err=True) + click.secho("{} does exist!".format(new), fg="red", err=True) has_existing = True else: non_existing[old] = new @@ -115,8 +160,8 @@ def tln( for old, new in files_to_move: if verbose or interactive: - click.echo('{} -> {}'.format(old, new)) + click.echo("{} -> {}".format(old, new)) - if not (interactive and not click.confirm('Is the match correct?')): + if not (interactive and not click.confirm("Is the match correct?")): if not dry_run: link_file(old, new, symbolic) diff --git a/patternutils/commands/tmv.py b/patternutils/commands/tmv.py index 25932bc..eb6dc99 100644 --- a/patternutils/commands/tmv.py +++ b/patternutils/commands/tmv.py @@ -18,30 +18,65 @@ def move_file(old_filename: str, new_filename: str) -> None: shutil.move(old_filename, new_filename) -@click.command(context_settings={'help_option_names': ('-h', '--help', '-?')}) -@click.option('-i', '--interactive', is_flag=True, default=False, - help='prompt before renaming files') -@click.option('-e', '--editor', is_flag=True, default=False, - help='Open an editor before renaming files to allow manual changes') -@click.option('-f', '--force', is_flag=True, default=False, - help='force rename') -@click.option('-t', '--template-engine', default='python', type=click.Choice(['python', 'jinja2']), - help='select the template engine to use') -@click.option('-k', '--key', default='_abspath', - help='select the key to use as the source file') -@click.option('-s', '--stream', is_flag=True, default=False, - help='Input is a stream of JSON objects') -@click.option('-p', '--use-predefined-template', is_flag=True, default=False, - help='use predefined template') -@click.option('--read-from', default='-', type=click.File('r')) -@click.option('--abort-on-path-exist', is_flag=True, default=False, - help='exit if a renamed path already exists') -@click.option('-n', '--dry-run', is_flag=True, default=False, - help='perform a trial run with no changes made') -@click.option('-v', '--verbose', is_flag=True, default=False, - help='explain what is being done') +@click.command(context_settings={"help_option_names": ("-h", "--help", "-?")}) +@click.option( + "-i", + "--interactive", + is_flag=True, + default=False, + help="prompt before renaming files", +) +@click.option( + "-e", + "--editor", + is_flag=True, + default=False, + help="Open an editor before renaming files to allow manual changes", +) +@click.option("-f", "--force", is_flag=True, default=False, help="force rename") +@click.option( + "-t", + "--template-engine", + default="python", + type=click.Choice(["python", "jinja2"]), + help="select the template engine to use", +) +@click.option( + "-k", "--key", default="_abspath", help="select the key to use as the source file" +) +@click.option( + "-s", + "--stream", + is_flag=True, + default=False, + help="Input is a stream of JSON objects", +) +@click.option( + "-p", + "--use-predefined-template", + is_flag=True, + default=False, + help="use predefined template", +) +@click.option("--read-from", default="-", type=click.File("r")) +@click.option( + "--abort-on-path-exist", + is_flag=True, + default=False, + help="exit if a renamed path already exists", +) +@click.option( + "-n", + "--dry-run", + is_flag=True, + default=False, + help="perform a trial run with no changes made", +) +@click.option( + "-v", "--verbose", is_flag=True, default=False, help="explain what is being done" +) @click.version_option() -@click.argument('output-pattern') +@click.argument("output-pattern") def tmv( output_pattern: str, interactive: bool, @@ -72,23 +107,25 @@ def tmv( else: data = [json.loads(line) for line in read_from] except json.JSONDecodeError: - click.secho('JSON not valid!', fg='red', err=True) + click.secho("JSON not valid!", fg="red", err=True) raise SystemExit if use_predefined_template: try: - output_pattern, template_engine = config.load_template(output_pattern, 'tmv') + output_pattern, template_engine = config.load_template( + output_pattern, "tmv" + ) except FileNotFoundError: - click.secho('File not found!', fg='red', err=True) + click.secho("File not found!", fg="red", err=True) raise SystemExit except RuntimeError: - click.secho('Multiple files found!', fg='red', err=True) + click.secho("Multiple files found!", fg="red", err=True) raise SystemExit try: render = template.get_render_function(output_pattern, engine=template_engine) except RuntimeError: - click.secho('jinja2 not installed!', fg='red', err=True) + click.secho("jinja2 not installed!", fg="red", err=True) raise SystemExit new_filenames = dict((entry[key], render(**entry)) for entry in data) @@ -97,14 +134,14 @@ def tmv( try: new_filenames = utils.edit(new_filenames) except RuntimeError: - click.secho('You edit is not parseable!', fg='red', err=True) + click.secho("You edit is not parseable!", fg="red", err=True) raise SystemExit has_existing = False non_existing = {} for old, new in new_filenames.items(): if os.path.exists(new): - click.secho('{} does exist!'.format(new), fg='red', err=True) + click.secho("{} does exist!".format(new), fg="red", err=True) has_existing = True else: non_existing[old] = new @@ -119,8 +156,8 @@ def tmv( for old, new in files_to_move: if verbose or interactive: - click.echo('{} -> {}'.format(old, new)) + click.echo("{} -> {}".format(old, new)) - if not (interactive and not click.confirm('Is the match correct?')): + if not (interactive and not click.confirm("Is the match correct?")): if not dry_run: move_file(old, new) diff --git a/patternutils/config.py b/patternutils/config.py index 155789b..59b6c89 100644 --- a/patternutils/config.py +++ b/patternutils/config.py @@ -5,7 +5,7 @@ import click from typing import Tuple, List, Optional -CONFIG_PATH = click.get_app_dir('patternutils') +CONFIG_PATH = click.get_app_dir("patternutils") def load_template(template_name: str, command_name: Optional[str]) -> Tuple[str, str]: @@ -14,21 +14,21 @@ def load_template(template_name: str, command_name: Optional[str]) -> Tuple[str, files = find_templates(template_name, command_name) if len(files) == 1: template_file = files[0] - with open(template_file, encoding='utf-8') as f: + with open(template_file, encoding="utf-8") as f: template_lines = f.read() elif not files: raise FileNotFoundError elif len(files) > 1: - raise RuntimeError('Multiple files found!') + raise RuntimeError("Multiple files found!") - output_pattern = template_lines.replace('\n', '') + output_pattern = template_lines.replace("\n", "") template_engine = os.path.splitext(template_file)[1][1:] return output_pattern, template_engine def find_templates(template_name: str, command_name: Optional[str] = None) -> List[str]: - template_glob = '{}.*'.format(template_name) - command_glob = '*' if command_name is None else command_name + template_glob = "{}.*".format(template_name) + command_glob = "*" if command_name is None else command_name command_glob = os.path.join(CONFIG_PATH, command_glob) return glob.glob(os.path.join(command_glob, template_glob)) diff --git a/patternutils/match.py b/patternutils/match.py index 01411c2..8f65802 100644 --- a/patternutils/match.py +++ b/patternutils/match.py @@ -5,7 +5,7 @@ def apply(subject: str, regex_pattern: Pattern[str]) -> Dict[str, str]: match = regex_pattern.search(subject) if match is not None: groupdict = match.groupdict() - groupdict['_subject'] = subject + groupdict["_subject"] = subject return groupdict else: - raise ValueError('subject doesn\'t match regex pattern') + raise ValueError("subject doesn't match regex pattern") diff --git a/patternutils/template.py b/patternutils/template.py index a4cf794..53746a2 100644 --- a/patternutils/template.py +++ b/patternutils/template.py @@ -12,10 +12,10 @@ else: jinja_feature = True jinja_env = jinja2.Environment() - def to_datetime(value: str, format: str = '%Y-%m-%d') -> datetime: + def to_datetime(value: str, format: str = "%Y-%m-%d") -> datetime: return datetime.strptime(value, format) - def format_datetime(value: datetime, format: str = '%Y-%m-%d') -> str: + def format_datetime(value: datetime, format: str = "%Y-%m-%d") -> str: return value.strftime(format) def to_int(value: str, base: int = 10) -> int: @@ -27,20 +27,20 @@ else: def quote(value: str) -> str: return shlex.quote(value) - jinja_env.filters['datetime'] = to_datetime - jinja_env.filters['datetimeformat'] = format_datetime - jinja_env.filters['int'] = to_int - jinja_env.filters['float'] = to_float - jinja_env.filters['quote'] = quote + jinja_env.filters["datetime"] = to_datetime + jinja_env.filters["datetimeformat"] = format_datetime + jinja_env.filters["int"] = to_int + jinja_env.filters["float"] = to_float + jinja_env.filters["quote"] = quote -def get_render_function(template: str, *, engine: str = 'python') -> Callable[..., str]: - if engine == 'jinja2': +def get_render_function(template: str, *, engine: str = "python") -> Callable[..., str]: + if engine == "jinja2": if jinja_feature: env_template = jinja_env.from_string(template) render_function = env_template.render else: - raise RuntimeError('jinja2 not installed!') + raise RuntimeError("jinja2 not installed!") else: render_function = template.format return render_function diff --git a/patternutils/utils.py b/patternutils/utils.py index e78a86b..6f8132d 100644 --- a/patternutils/utils.py +++ b/patternutils/utils.py @@ -13,14 +13,16 @@ def max_procs() -> int: def edit(data: Dict[str, str]) -> Dict[str, str]: longest = len(max(data, key=len)) - temporary = ['{}\t{}\n'.format(key.ljust(longest), value) for key, value in data.items()] - edited = click.edit(''.join(temporary)) + temporary = [ + "{}\t{}\n".format(key.ljust(longest), value) for key, value in data.items() + ] + edited = click.edit("".join(temporary)) if edited is not None: new_data = dict() - for line in edited.split('\n'): - if line and '\t' in line: - old, new = line.split('\t') + for line in edited.split("\n"): + if line and "\t" in line: + old, new = line.split("\t") new_data[old.strip()] = new if new_data: return new_data diff --git a/setup.py b/setup.py index 922e7e5..f21c8bb 100644 --- a/setup.py +++ b/setup.py @@ -3,31 +3,31 @@ from setuptools import find_packages, setup -NAME = 'patternutils' -DESCRIPTION = 'Combine regular expressions with template engines in a powerful matter.' -URL = 'https://projects.metalgamer.eu/patternutils' -EMAIL = 'dennis.fink@c3l.lu' -AUTHOR = 'Dennis Fink' +NAME = "patternutils" +DESCRIPTION = "Combine regular expressions with template engines in a powerful matter." +URL = "https://projects.metalgamer.eu/patternutils" +EMAIL = "dennis.fink@c3l.lu" +AUTHOR = "Dennis Fink" -VERSION = '0.0.7' +VERSION = "0.0.7" ENTRY_POINTS = { - 'console_scripts': [ - 'pmatch=patternutils.commands.pmatch:pmatch', - 'targs=patternutils.commands.targs:targs', - 'tmv=patternutils.commands.tmv:tmv', - 'tln=patternutils.commands.tln:tln', - 'patterncfg=patternutils.commands.patterncfg:patterncfg', + "console_scripts": [ + "pmatch=patternutils.commands.pmatch:pmatch", + "targs=patternutils.commands.targs:targs", + "tmv=patternutils.commands.tmv:tmv", + "tln=patternutils.commands.tln:tln", + "patterncfg=patternutils.commands.patterncfg:patterncfg", ], } REQUIRED = [ - 'click==7.0', + "click==7.0", ] OPTIONAL = { - 'jinja2': ['Jinja2==2.10.1'], - 'pygments': ['Pygments==2.4.2'], + "jinja2": ["Jinja2==2.10.1"], + "pygments": ["Pygments==2.4.2"], } setup( @@ -37,17 +37,17 @@ setup( author=AUTHOR, author_email=EMAIL, url=URL, - packages=find_packages(exclude=('tests',)), + packages=find_packages(exclude=("tests",)), entry_points=ENTRY_POINTS, install_requires=REQUIRED, extras_requires=OPTIONAL, include_package_data=True, - license='GPLv3+', + license="GPLv3+", classifiers=[ # Trove classifiers # Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers - 'Programming Language :: Python', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: Implementation :: CPython', + "Programming Language :: Python", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: Implementation :: CPython", ], ) -- cgit v1.3.1 From 04a9ce00a5eaf4df6d06896f3a785c992c8d66e5 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Sat, 18 Apr 2020 19:28:05 +0200 Subject: isort --- patternutils/commands/patterncfg.py | 6 ++---- patternutils/commands/pmatch.py | 5 ++--- patternutils/commands/targs.py | 12 ++---------- patternutils/commands/tln.py | 4 +--- patternutils/commands/tmv.py | 4 +--- patternutils/config.py | 5 ++--- patternutils/match.py | 2 +- patternutils/utils.py | 3 +-- 8 files changed, 12 insertions(+), 29 deletions(-) diff --git a/patternutils/commands/patterncfg.py b/patternutils/commands/patterncfg.py index b75fbdf..a1a7cb3 100644 --- a/patternutils/commands/patterncfg.py +++ b/patternutils/commands/patterncfg.py @@ -1,10 +1,11 @@ import os import os.path - from typing import Optional import click +from .. import config + try: from pygments import highlight from pygments.formatters import TerminalFormatter @@ -15,9 +16,6 @@ else: has_pygments = True -from .. import config - - CURRENT_SUPPORTED_PROGRAMS = ("pmatch", "tmv", "targs", "tln") diff --git a/patternutils/commands/pmatch.py b/patternutils/commands/pmatch.py index bd88a03..376776e 100644 --- a/patternutils/commands/pmatch.py +++ b/patternutils/commands/pmatch.py @@ -4,13 +4,12 @@ import json import os import os.path import re - -from typing import Generator, List, Iterator, Pattern, Any, Tuple, Dict +from typing import Any, Dict, Generator, Iterator, List, Pattern, Tuple import click -from .. import match as mat from .. import config +from .. import match as mat def walk( diff --git a/patternutils/commands/targs.py b/patternutils/commands/targs.py index e25679f..68512bb 100644 --- a/patternutils/commands/targs.py +++ b/patternutils/commands/targs.py @@ -4,19 +4,11 @@ import multiprocessing import os import shlex import subprocess - -from typing import ( - Union, - List, - Dict, - Callable, -) +from typing import Callable, Dict, List, Union import click -from .. import template -from .. import config -from .. import utils +from .. import config, template, utils def run_command( diff --git a/patternutils/commands/tln.py b/patternutils/commands/tln.py index 4e21f1f..70e7406 100644 --- a/patternutils/commands/tln.py +++ b/patternutils/commands/tln.py @@ -4,9 +4,7 @@ import os.path import click -from .. import template -from .. import config -from .. import utils +from .. import config, template, utils def link_file(old_filename: str, new_filename: str, symbolic: bool) -> None: diff --git a/patternutils/commands/tmv.py b/patternutils/commands/tmv.py index eb6dc99..cd56906 100644 --- a/patternutils/commands/tmv.py +++ b/patternutils/commands/tmv.py @@ -4,9 +4,7 @@ import shutil import click -from .. import template -from .. import config -from .. import utils +from .. import config, template, utils def move_file(old_filename: str, new_filename: str) -> None: diff --git a/patternutils/config.py b/patternutils/config.py index 59b6c89..2bce26c 100644 --- a/patternutils/config.py +++ b/patternutils/config.py @@ -1,10 +1,9 @@ -import os.path import glob +import os.path +from typing import List, Optional, Tuple import click -from typing import Tuple, List, Optional - CONFIG_PATH = click.get_app_dir("patternutils") diff --git a/patternutils/match.py b/patternutils/match.py index 8f65802..80f9553 100644 --- a/patternutils/match.py +++ b/patternutils/match.py @@ -1,4 +1,4 @@ -from typing import Pattern, Dict +from typing import Dict, Pattern def apply(subject: str, regex_pattern: Pattern[str]) -> Dict[str, str]: diff --git a/patternutils/utils.py b/patternutils/utils.py index 6f8132d..84720b7 100644 --- a/patternutils/utils.py +++ b/patternutils/utils.py @@ -1,9 +1,8 @@ import os +from typing import Dict import click -from typing import Dict - def max_procs() -> int: cpu_count = os.cpu_count() -- cgit v1.3.1 From 2802c9584bd9a1c56805a0593e1191f9867b9918 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Fri, 7 Aug 2020 11:46:42 +0200 Subject: Fix --stream option in targs --- patternutils/commands/targs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patternutils/commands/targs.py b/patternutils/commands/targs.py index 68512bb..4c9e670 100644 --- a/patternutils/commands/targs.py +++ b/patternutils/commands/targs.py @@ -62,7 +62,7 @@ def run_command( help="Redirect stderr to /dev/null", ) @click.option( - "--stream", is_flag=True, defaults=False, help="Input is a stream of JSON objects" + "--stream", is_flag=True, default=False, help="Input is a stream of JSON objects" ) @click.version_option() @click.argument("command") -- cgit v1.3.1 From 5d02bea91728ca15418da5dd7e942c6470fb9764 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Fri, 7 Aug 2020 12:11:22 +0200 Subject: Move json_dumps to utils and minimize json output if not human readable --- patternutils/commands/pmatch.py | 12 +++--------- patternutils/utils.py | 10 +++++++++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/patternutils/commands/pmatch.py b/patternutils/commands/pmatch.py index 376776e..b889145 100644 --- a/patternutils/commands/pmatch.py +++ b/patternutils/commands/pmatch.py @@ -10,6 +10,7 @@ import click from .. import config from .. import match as mat +from .. import utils def walk( @@ -49,13 +50,6 @@ def apply_regex( return matches, has_invalid_matches -def json_dumps(data: Any, human_readable: bool = False) -> str: - if human_readable: - return json.dumps(data, indent=4, sort_keys=True) - else: - return json.dumps(data) - - @click.command(context_settings={"help_option_names": ("-h", "--help", "-?")}) @click.option("-d", "--directory", multiple=True, default=["./"]) @click.option( @@ -154,9 +148,9 @@ def pmatch( if stream: for m in matches: - click.echo(json_dumps(m, human_readable)) + click.echo(utils.json_dumps(m, human_readable)) else: - click.echo(json_dumps(matches, human_readable)) + click.echo(utils.json_dumps(matches, human_readable)) if __name__ == "__main__": diff --git a/patternutils/utils.py b/patternutils/utils.py index 84720b7..266f3b9 100644 --- a/patternutils/utils.py +++ b/patternutils/utils.py @@ -1,5 +1,6 @@ import os -from typing import Dict +import json +from typing import Dict, Any import click @@ -29,3 +30,10 @@ def edit(data: Dict[str, str]) -> Dict[str, str]: raise RuntimeError else: return data + + +def json_dumps(data: Any, humand_readable: bool = False) -> str: + if humand_readable: + return json.dumps(data, indent=4, sort_keys=True) + else: + return json.dumps(data, separators=(",", ":")) -- cgit v1.3.1 From 583ca3c624978ff49f826157cdc4a66e17125334 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Wed, 23 Sep 2020 09:33:05 +0200 Subject: Use f-strings --- patternutils/commands/patterncfg.py | 6 +++--- patternutils/commands/pmatch.py | 2 +- patternutils/commands/tln.py | 4 ++-- patternutils/commands/tmv.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/patternutils/commands/patterncfg.py b/patternutils/commands/patterncfg.py index a1a7cb3..3ef0518 100644 --- a/patternutils/commands/patterncfg.py +++ b/patternutils/commands/patterncfg.py @@ -36,10 +36,10 @@ def list() -> None: for d in os.listdir(config.CONFIG_PATH): click.secho(d, fg="blue") for f in os.listdir(os.path.join(config.CONFIG_PATH, d)): - click.echo("└── {}".format(f)) + click.echo(f"└── {f}") except FileNotFoundError as e: click.secho( - "{} not found! Please run patterncfg init first.".format(e.filename), + f"{e.filename} not found! Please run patterncfg init first.", fg="red", err=True, ) @@ -66,7 +66,7 @@ def add(template_engine: Optional[str], command: str, name: str) -> None: else: fileext = template_engine - filename = os.path.join(config.CONFIG_PATH, command, "{}.{}".format(name, fileext)) + filename = os.path.join(config.CONFIG_PATH, command, f"{name}.{fileext}") click.edit(filename=filename) diff --git a/patternutils/commands/pmatch.py b/patternutils/commands/pmatch.py index b889145..e5880d6 100644 --- a/patternutils/commands/pmatch.py +++ b/patternutils/commands/pmatch.py @@ -37,7 +37,7 @@ def apply_regex( try: match = mat.apply(subject, regex_pattern) except ValueError: - click.secho("{} did not match".format(subject), fg="red", err=True) + click.secho(f"{subject} did not match", fg="red", err=True) has_invalid_matches = True else: match["_path"] = f.path diff --git a/patternutils/commands/tln.py b/patternutils/commands/tln.py index 70e7406..e84ddb4 100644 --- a/patternutils/commands/tln.py +++ b/patternutils/commands/tln.py @@ -143,7 +143,7 @@ def tln( non_existing = {} for old, new in new_filenames.items(): if os.path.exists(new): - click.secho("{} does exist!".format(new), fg="red", err=True) + click.secho(f"{new} does exist!", fg="red", err=True) has_existing = True else: non_existing[old] = new @@ -158,7 +158,7 @@ def tln( for old, new in files_to_move: if verbose or interactive: - click.echo("{} -> {}".format(old, new)) + click.echo(f"{old} -> {new}") if not (interactive and not click.confirm("Is the match correct?")): if not dry_run: diff --git a/patternutils/commands/tmv.py b/patternutils/commands/tmv.py index cd56906..04321f1 100644 --- a/patternutils/commands/tmv.py +++ b/patternutils/commands/tmv.py @@ -139,7 +139,7 @@ def tmv( non_existing = {} for old, new in new_filenames.items(): if os.path.exists(new): - click.secho("{} does exist!".format(new), fg="red", err=True) + click.secho(f"{new} does exist!", fg="red", err=True) has_existing = True else: non_existing[old] = new @@ -154,7 +154,7 @@ def tmv( for old, new in files_to_move: if verbose or interactive: - click.echo("{} -> {}".format(old, new)) + click.echo(f"{old} -> {new}") if not (interactive and not click.confirm("Is the match correct?")): if not dry_run: -- cgit v1.3.1 From 8da29f90ada284188abbbafda33f769d0536df00 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Wed, 23 Sep 2020 09:33:42 +0200 Subject: Autoformat --- patternutils/commands/pmatch.py | 4 +++- patternutils/commands/targs.py | 8 +------- patternutils/commands/tmv.py | 10 +++++----- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/patternutils/commands/pmatch.py b/patternutils/commands/pmatch.py index e5880d6..c276bf3 100644 --- a/patternutils/commands/pmatch.py +++ b/patternutils/commands/pmatch.py @@ -27,7 +27,9 @@ def walk( def apply_regex( - walk_function: Iterator[Any], regex_pattern: Pattern[str], match_full_path: bool, + walk_function: Iterator[Any], + regex_pattern: Pattern[str], + match_full_path: bool, ) -> Tuple[List[Dict[str, str]], bool]: matches = [] diff --git a/patternutils/commands/targs.py b/patternutils/commands/targs.py index 4c9e670..4ec9a17 100644 --- a/patternutils/commands/targs.py +++ b/patternutils/commands/targs.py @@ -11,13 +11,7 @@ import click from .. import config, template, utils -def run_command( - data: Dict[str, str], - render: Callable[..., str], - run: Callable[..., None], - shell: bool, -) -> None: - c = render(**data) +def run_command(data: Dict[str, str], run: Callable[..., None], shell: bool,) -> None: if not shell: prepared_command = shlex.split(c) # type: Union[str, List[str]] else: diff --git a/patternutils/commands/tmv.py b/patternutils/commands/tmv.py index 04321f1..e573c92 100644 --- a/patternutils/commands/tmv.py +++ b/patternutils/commands/tmv.py @@ -92,11 +92,11 @@ def tmv( """Rename files based on the OUTPUT_PATTERN. - It read a JSON list containing objects or a stream of objects - (if --stream option is defined). The object needs to have a - key named as the option KEY (default: _abspath), which points - to the file to move. The rest of the keys will be supplied to - the templating engine to generate the new filename. + It read a JSON list containing objects or a stream of objects + (if --stream option is defined). The object needs to have a + key named as the option KEY (default: _abspath), which points + to the file to move. The rest of the keys will be supplied to + the templating engine to generate the new filename. """ try: -- cgit v1.3.1 From 7917ff35e25f7335b8ef2c64233ec3270085515f Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Wed, 23 Sep 2020 09:40:14 +0200 Subject: Fix typos --- patternutils/commands/tmv.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patternutils/commands/tmv.py b/patternutils/commands/tmv.py index e573c92..1b25441 100644 --- a/patternutils/commands/tmv.py +++ b/patternutils/commands/tmv.py @@ -92,7 +92,7 @@ def tmv( """Rename files based on the OUTPUT_PATTERN. - It read a JSON list containing objects or a stream of objects + It reads a JSON list containing objects or a stream of objects (if --stream option is defined). The object needs to have a key named as the option KEY (default: _abspath), which points to the file to move. The rest of the keys will be supplied to @@ -132,7 +132,7 @@ def tmv( try: new_filenames = utils.edit(new_filenames) except RuntimeError: - click.secho("You edit is not parseable!", fg="red", err=True) + click.secho("Your edit is not parseable!", fg="red", err=True) raise SystemExit has_existing = False -- cgit v1.3.1 From 042b00fd50e09c2610e2c1e906769ccdd45d5b9c Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Wed, 23 Sep 2020 09:40:58 +0200 Subject: Better error message if the template/regex/command file is not found --- patternutils/commands/pmatch.py | 2 +- patternutils/commands/targs.py | 2 +- patternutils/commands/tln.py | 2 +- patternutils/commands/tmv.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/patternutils/commands/pmatch.py b/patternutils/commands/pmatch.py index c276bf3..6bbd349 100644 --- a/patternutils/commands/pmatch.py +++ b/patternutils/commands/pmatch.py @@ -121,7 +121,7 @@ def pmatch( try: regex_pattern, _ = config.load_template(regex_pattern, "pmatch") except FileNotFoundError: - click.secho("File not found!", fg="red", err=True) + click.secho(f"Regex {regex_pattern} not found!", fg="red", err=True) raise SystemExit except RuntimeError: click.secho("Multiple files found!", fg="red", err=True) diff --git a/patternutils/commands/targs.py b/patternutils/commands/targs.py index 4ec9a17..a3b3a02 100644 --- a/patternutils/commands/targs.py +++ b/patternutils/commands/targs.py @@ -86,7 +86,7 @@ def targs( try: command, template_engine = config.load_template(command, "targs") except FileNotFoundError: - click.secho("File not found!", fg="red", err=True) + click.secho(f"Command {command} not found!", fg="red", err=True) raise SystemExit except RuntimeError: click.secho("Multiple files found!", fg="red", err=True) diff --git a/patternutils/commands/tln.py b/patternutils/commands/tln.py index e84ddb4..295cda9 100644 --- a/patternutils/commands/tln.py +++ b/patternutils/commands/tln.py @@ -118,7 +118,7 @@ def tln( output_pattern, "tln" ) except FileNotFoundError: - click.secho("File not found!", fg="red", err=True) + click.secho(f"Template {output_pattern} not found!", fg="red", err=True) raise SystemExit except RuntimeError: click.secho("Multiple files found!", fg="red", err=True) diff --git a/patternutils/commands/tmv.py b/patternutils/commands/tmv.py index 1b25441..3e92342 100644 --- a/patternutils/commands/tmv.py +++ b/patternutils/commands/tmv.py @@ -114,7 +114,7 @@ def tmv( output_pattern, "tmv" ) except FileNotFoundError: - click.secho("File not found!", fg="red", err=True) + click.secho(f"Template {output_pattern} not found!", fg="red", err=True) raise SystemExit except RuntimeError: click.secho("Multiple files found!", fg="red", err=True) -- cgit v1.3.1 From 89f3121ed601f95f5e32952ff6ade90d565f193f Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Fri, 25 Sep 2020 15:37:31 +0200 Subject: Do not fix dependencies in PKGBUILD and put the hash in a variable --- PKGBUILD/PKGBUILD | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/PKGBUILD/PKGBUILD b/PKGBUILD/PKGBUILD index 4e011f3..581b9dc 100644 --- a/PKGBUILD/PKGBUILD +++ b/PKGBUILD/PKGBUILD @@ -2,6 +2,7 @@ pkgname=patternutils pkgver=0.0.7 +_pkghash=63e2ad2d4211 pkgrel=1 pkgdesc="Combine regular expressions with template engines in a powerful matter." arch=('any') @@ -11,12 +12,16 @@ depends=('python' 'python-click' 'python-jinja' 'python-pygments') source=('patternutils-0.0.7.zip::https://projects.metalgamer.eu/patternutils/archive/63e2ad2d42116041db43b33f5ad0aafe84ec38ad.zip?subrepos=false') sha512sums=('efbae7ecd8eb17564db574fa4a8bc573ce0203fb7b6130ad118d695f3ba4cd4b1f66c2fd469a8c3003e7538467ee4d54a7b30d02dd3f28afe12b4c012e52a9bc') +prepare() { + sed -i 's/==/>=/g' "$srcdir/$pkgname-$_pkghash/setup.py" +} + build() { - cd "$srcdir/$pkgname-63e2ad2d4211" + cd "$srcdir/$pkgname-$_pkghash" python setup.py build } package() { - cd "$srcdir/$pkgname-63e2ad2d4211" + cd "$srcdir/$pkgname-$_pkghash" python setup.py install --root="$pkgdir" --optimize=1 } -- cgit v1.3.1 From 1ac22bf82d12fad9b3019d96d27fd3d2b3455289 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Fri, 25 Sep 2020 21:22:53 +0200 Subject: Use conditional expression to set fileext in patterncfg add --- patternutils/commands/patterncfg.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/patternutils/commands/patterncfg.py b/patternutils/commands/patterncfg.py index 3ef0518..83168cf 100644 --- a/patternutils/commands/patterncfg.py +++ b/patternutils/commands/patterncfg.py @@ -61,10 +61,7 @@ def add(template_engine: Optional[str], command: str, name: str) -> None: if command == "pmatch": fileext = "regex" else: - if template_engine not in ("python", "jinja2"): - fileext = "python" - else: - fileext = template_engine + fileext = "jinja2" if template_engine == "jinja2" else "python" filename = os.path.join(config.CONFIG_PATH, command, f"{name}.{fileext}") click.edit(filename=filename) -- cgit v1.3.1 From c6ea4f1780d3366cbece5e8267d4fd96dc240e5a Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Fri, 25 Sep 2020 21:23:58 +0200 Subject: Black autoformat --- patternutils/commands/targs.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/patternutils/commands/targs.py b/patternutils/commands/targs.py index a3b3a02..79d906d 100644 --- a/patternutils/commands/targs.py +++ b/patternutils/commands/targs.py @@ -11,7 +11,11 @@ import click from .. import config, template, utils -def run_command(data: Dict[str, str], run: Callable[..., None], shell: bool,) -> None: +def run_command( + data: Dict[str, str], + run: Callable[..., None], + shell: bool, +) -> None: if not shell: prepared_command = shlex.split(c) # type: Union[str, List[str]] else: @@ -103,10 +107,15 @@ def targs( stdout = subprocess.DEVNULL if redirect_stdout else None stderr = subprocess.DEVNULL if redirect_stderr else None patched_subprocess = functools.partial( - subprocess.run, shell=shell, stdout=stdout, stderr=stderr, + subprocess.run, + shell=shell, + stdout=stdout, + stderr=stderr, ) patched_run_command = functools.partial( - run_command, render=render, run=patched_subprocess, shell=shell, + run_command, + run=patched_subprocess, + shell=shell, ) if max_procs == 1: for r in data: -- cgit v1.3.1 From 5ddcb6231032cf566b0dd45e84aa52b85ed559d6 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Fri, 25 Sep 2020 21:24:13 +0200 Subject: Add editor options to targs --- patternutils/commands/targs.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/patternutils/commands/targs.py b/patternutils/commands/targs.py index 79d906d..04c286d 100644 --- a/patternutils/commands/targs.py +++ b/patternutils/commands/targs.py @@ -62,6 +62,13 @@ def run_command( @click.option( "--stream", is_flag=True, default=False, help="Input is a stream of JSON objects" ) +@click.option( + "-e", + "--editor", + is_flag=True, + default=False, + help="Open an editor before running commands to allow manual changes", +) @click.version_option() @click.argument("command") def targs( @@ -74,6 +81,7 @@ def targs( redirect_stderr: bool, use_predefined_template: bool, stream: bool, + editor: bool, verbose: bool, ) -> None: @@ -102,6 +110,15 @@ def targs( click.secho("jinja2 not installed!", fg="red", err=True) raise SystemExit + commands = [render(r) for r in data] + + if editor: + try: + commands = utils.edit(commands) + except RuntimeErro: + click.secho("Your edit is not parseable!", fg="red", err=True) + raise SystemExit + max_procs = utils.max_procs() if max_procs == 0 else max_procs stdout = subprocess.DEVNULL if redirect_stdout else None @@ -118,11 +135,11 @@ def targs( shell=shell, ) if max_procs == 1: - for r in data: + for r in commands: patched_run_command(r) else: with multiprocessing.Pool(max_procs) as p: - p.map(patched_run_command, data) + p.map(patched_run_command, commands) if __name__ == "__main__": -- cgit v1.3.1 From 954ff69b17b5b7c81780dbd6aa03847dd26a1edf Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Fri, 25 Sep 2020 21:26:55 +0200 Subject: Bumped version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index f21c8bb..95a892f 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ URL = "https://projects.metalgamer.eu/patternutils" EMAIL = "dennis.fink@c3l.lu" AUTHOR = "Dennis Fink" -VERSION = "0.0.7" +VERSION = "0.0.8" ENTRY_POINTS = { "console_scripts": [ "pmatch=patternutils.commands.pmatch:pmatch", -- cgit v1.3.1 -- cgit v1.3.1 From 652070bb3e233c5333dc70325449d7a80ba13c92 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Fri, 25 Sep 2020 21:28:52 +0200 Subject: Updated PKGBUILD --- PKGBUILD/PKGBUILD | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PKGBUILD/PKGBUILD b/PKGBUILD/PKGBUILD index 581b9dc..ca4fba9 100644 --- a/PKGBUILD/PKGBUILD +++ b/PKGBUILD/PKGBUILD @@ -1,16 +1,16 @@ # Maintainer: Dennis Fink pkgname=patternutils -pkgver=0.0.7 -_pkghash=63e2ad2d4211 +pkgver=0.0.8 +_pkghash=853b2c08d397 pkgrel=1 pkgdesc="Combine regular expressions with template engines in a powerful matter." arch=('any') url="https://projects.metalgamer.eu/patternutils" license=('GPL3') depends=('python' 'python-click' 'python-jinja' 'python-pygments') -source=('patternutils-0.0.7.zip::https://projects.metalgamer.eu/patternutils/archive/63e2ad2d42116041db43b33f5ad0aafe84ec38ad.zip?subrepos=false') -sha512sums=('efbae7ecd8eb17564db574fa4a8bc573ce0203fb7b6130ad118d695f3ba4cd4b1f66c2fd469a8c3003e7538467ee4d54a7b30d02dd3f28afe12b4c012e52a9bc') +source=('patternutils-0.0.8.zip::https://projects.metalgamer.eu/patternutils/archive/853b2c08d397ad61442b8caf7d8cd4723a1dd04e.zip?subrepos=false') +sha512sums=('dc29e9403e260a04cbe986567a37ecd17bf2b335dbe99c3b274d5568252e22464b7bb52fd2e9dba459ac83d8f79eb39a832641f224fe0911522d60f6c0069a44') prepare() { sed -i 's/==/>=/g' "$srcdir/$pkgname-$_pkghash/setup.py" -- cgit v1.3.1