From 29817dfd24ca5b2536eb14aaadd84d3cbded7a32 Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Wed, 2 Jul 2025 20:58:43 +0200 Subject: Format (ruff) and use /bin/findmnt instead of opening /etc/mtab --- .ruff.toml | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ smount.py | 20 +++++++------ sumount.py | 71 +++++++++++++++++++++++++++------------------- 3 files changed, 149 insertions(+), 38 deletions(-) create mode 100644 .ruff.toml diff --git a/.ruff.toml b/.ruff.toml new file mode 100644 index 0000000..12d671b --- /dev/null +++ b/.ruff.toml @@ -0,0 +1,96 @@ +cache-dir = "~/.cache/ruff" +indent-width = 4 +line-length = 79 +target-version = "py311" + +[lint] +select = ["ALL", "D101", "D102", "D103", "D104"] +ignore = [ + "ANN", + "BLE001", + "COM812", + "D", + "EM101", # Exception must not use a string literal, assign to variable first + "EM102", # Exception must not use an f-string literal, assign to variable first + "ERA001", + #"FBT001", + #"FBT002", + #"INP001", + #"ISC001", + #"N802", + #"N806", + "PLR2004", + "PTH111", + "PTH123", + "RUF012", + #"RUF013", + #"S101", + "S308", + "S603", + "T201", + "TRY003", + "TRY300", + #"UP020" +] + +# D101 - Missing docstring in public class +# D102 - Missing docstring in public method +# D200 - One-line docstring should fit on one line +# D203 - 1 blank line required before class docstring +# D205 - 1 blank line required between summary line and description +# D403 - First word of the first line should be capitalized: `str` -> `Str` +# ERA001 - Found commented-out code +# FBT001 - Boolean-typed positional argument in function definition +# FBT002 - Boolean default positional argument in function definition +# INP001 - File `beinc_weechat.py` is part of an implicit namespace package. Add an `__init__.py` +# N802 - Function name `do_GET` should be lowercase +# N806 - Variable `POST_data` in function should be lowercase +# PTH111 - `os.path.expanduser()` should be replaced by `Path.expanduser()` +# PTH123 - `open()` should be replaced by `Path.open()` +# PLR2004 - Magic value used in comparison, consider replacing `200` with a constant variable +# RUF012 - Mutable class attributes should be annotated with `typing.ClassVar` +# RUF013 - PEP 484 prohibits implicit `Optional` +# S101 - Use of `assert` detected +# S308 - Use of `mark_safe` may expose cross-site scripting vulnerabilities +# S603 - `subprocess` call: check for execution of untrusted input +# T201 - `print` found +# TRY003 - Avoid specifying long messages outside the exception class +# TRY300 - Consider moving this statement to an `else` block +# UP020 - Use builtin `open` + +# Allow fix for all enabled rules (when `--fix`) is provided. +fixable = ["ALL"] +unfixable = [] + +[format] +# Like Black, use double quotes for strings. +quote-style = "single" + +# Like Black, indent with spaces, rather than tabs. +indent-style = "space" + +# Like Black, respect magic trailing commas. +skip-magic-trailing-comma = true + +# Like Black, automatically detect the appropriate line ending. +line-ending = "lf" + +# Enable auto-formatting of code examples in docstrings. Markdown, +# reStructuredText code/literal blocks and doctests are all supported. +# +# This is currently disabled by default, but it is planned for this +# to be opt-out in the future. +docstring-code-format = false + +# Set the line length limit used when formatting code snippets in +# docstrings. +# +# This only has an effect when the `docstring-code-format` setting is +# enabled. +docstring-code-line-length = "dynamic" + +[lint.flake8-quotes] +inline-quotes = "single" + +[lint.isort] +split-on-trailing-comma = false diff --git a/smount.py b/smount.py index 648c6e9..9a0a312 100755 --- a/smount.py +++ b/smount.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- import json import os @@ -9,27 +8,30 @@ import sys def main(): """Main entry point""" - if (len(sys.argv) != 2): - sys.exit('Invalid parameter. Usage: {0} \n'.format( - sys.argv[0])) + if len(sys.argv) != 2: + sys.exit(f'Invalid parameter. Usage: {sys.argv[0]} \n') + cstm_error = '' + try: cstm_error = 'Could not open config (~/.smount.json)' + with open(os.path.expanduser('~/.smount.json')) as fp: config_dict = json.load(fp) - cstm_error = 'Invalid / nonexistent mapping: {0}'.format(sys.argv[1]) + + cstm_error = f'Invalid / nonexistent mapping: {sys.argv[1]}' data = config_dict[sys.argv[1]] - cstm_error = 'system() error' + cstm_error = 'subprocess error' args = ['/usr/bin/sshfs'] if data.get('options'): for opt in data.get('options'): args.extend(['-o', opt]) args.extend([data['src'], data['dest']]) subprocess.check_call(args) - except subprocess.CalledProcessError as e: - print('Execution error: {0}'.format(e), file=sys.stderr, flush=True) + except subprocess.CalledProcessError as err: + print(f'Execution error: {err}', file=sys.stderr, flush=True) except Exception: - print('Error: {0}'.format(cstm_error), file=sys.stderr, flush=True) + print(f'Error: {cstm_error}', file=sys.stderr, flush=True) if __name__ == '__main__': diff --git a/sumount.py b/sumount.py index 544047d..db01d3e 100755 --- a/sumount.py +++ b/sumount.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- import json import os @@ -9,47 +8,61 @@ import sys def main(): """Main entry point""" - if (len(sys.argv) != 2): - sys.exit('Invalid parameter. Usage: {0} \n'.format( - sys.argv[0])) + if len(sys.argv) != 2: + sys.exit(f'Invalid parameter. Usage: {sys.argv[0]} \n') + cstm_error = '' + try: cstm_error = 'Could not open config (~/.smount.json)' + with open(os.path.expanduser('~/.smount.json')) as fp: config_dict = json.load(fp) + cstm_error = 'Errror while executing all' + if sys.argv[1].lower() == 'all': - mounts = set() - umounted = list() # already umounted - with open('/etc/mtab') as fp: - for line in fp: - mounts.update(line.strip().split()) + mounts = ( + subprocess.run( + [ + '/bin/findmnt', + '-t', + 'fuse.sshfs', + '--list', + '-n', + '-o', + 'TARGET', + ], + capture_output=True, + check=False, + encoding='utf-8', + ) + .stdout.strip() + .split() + ) + for key, value in config_dict.items(): if value['dest'] not in mounts: - print('{mount} not in /etc/mtab'.format(mount=key)) - continue - if value['dest'] in umounted: - print('{mount}: {dest} already umounted'.format( - mount=key, - dest=value['dest'])) + print(f'{key} not mounted') continue - subprocess.check_call(['/usr/bin/fusermount', - '-u', - value['dest']]) - umounted.append(value['dest']) - print('umonted: {key} - {dest}'.format( - key=key, - dest=value['dest'])) + + subprocess.run( + ['/usr/bin/fusermount3', '-u', value['dest']], check=True + ) + mounts.pop(mounts.index(value['dest'])) + print(f'umonted: {key} - {value["dest"]}') + sys.exit(0) - cstm_error = 'Invalid / nonexistent mapping: {0}'.format(sys.argv[1]) + + cstm_error = f'Invalid / nonexistent mapping: {sys.argv[1]}' data = config_dict[sys.argv[1]] - subprocess.check_call(['/usr/bin/fusermount', - '-u', - data['dest']]) - except subprocess.CalledProcessError as e: - print('Execution error: {0}'.format(e), file=sys.stderr, flush=True) + subprocess.run( + ['/usr/bin/fusermount3', '-u', data['dest']], check=True + ) + except subprocess.CalledProcessError as err: + print(f'Execution error: {err}', file=sys.stderr, flush=True) except Exception: - print('Error: {0}'.format(cstm_error), file=sys.stderr, flush=True) + print(f'Error: {cstm_error}', file=sys.stderr, flush=True) if __name__ == '__main__': -- cgit v1.3