diff --git a/negromate/web/__init__.py b/negromate/web/__init__.py index 9f68fef..856eacc 100644 --- a/negromate/web/__init__.py +++ b/negromate/web/__init__.py @@ -1 +1 @@ -VERSION = "1.0" +VERSION = "1.1" diff --git a/negromate/web/builder.py b/negromate/web/builder.py index 71ff1b5..ff987e9 100644 --- a/negromate/web/builder.py +++ b/negromate/web/builder.py @@ -1,11 +1,10 @@ import os -from shutil import copy import subprocess +from shutil import copy -from jinja2 import Environment, FileSystemLoader, select_autoescape -from jinja2.utils import Markup import srt - +from jinja2 import Environment, FileSystemLoader, select_autoescape +from markupsafe import Markup from negromate.songs.loader import load_songs @@ -16,23 +15,23 @@ class SongPage: def get_context_data(self): parsed_srt = None if self.song.srt: - with self.song.srt.open('r') as srtfile: + with self.song.srt.open("r") as srtfile: try: - srt_str = srtfile.read().encode('utf-8').decode('utf-8-sig') + srt_str = srtfile.read().encode("utf-8").decode("utf-8-sig") parsed_srt = list(srt.parse(srt_str)) except Exception as e: print("{}: srt parse error: {}".format(self.song.path.name, e)) root_path = os.path.relpath(self.song.root, self.song.path) return { - 'song': self, - 'parsed_srt': parsed_srt, - 'root_path': root_path, + "song": self, + "parsed_srt": parsed_srt, + "root_path": root_path, } def render(self, builder, context): ctx = self.get_context_data() ctx.update(context) - builder.render('song.html', self.song.path, ctx) + builder.render("song.html", self.song.path, ctx) def __getattr__(self, name): return getattr(self.song, name) @@ -47,10 +46,10 @@ class Builder: self.env = Environment( loader=FileSystemLoader(template_folder), - autoescape=select_autoescape(['html']), + autoescape=select_autoescape(["html"]), ) - self.env.filters['url'] = self.url - self.env.filters['display_boolean'] = self.display_boolean + self.env.filters["url"] = self.url + self.env.filters["display_boolean"] = self.display_boolean self.current_path = self.root_folder def url(self, path): @@ -58,17 +57,17 @@ class Builder: def display_boolean(self, value): if value: - return Markup('✓') + return Markup("✓") else: - return Markup('✗') + return Markup("✗") def render(self, template, target, context): - html_file = target / 'index.html' + html_file = target / "index.html" page_template = self.env.get_template(template) root_path = os.path.relpath(self.root_folder, target) - context['root_path'] = root_path + context["root_path"] = root_path - with html_file.open('w') as page: + with html_file.open("w") as page: page.write(page_template.render(context)) def build(self): @@ -77,50 +76,52 @@ class Builder: pending_songs = [SongPage(s) for s in pending_songs] global_context = { - 'songs': songs, - 'root_folder': self.root_folder, + "songs": songs, + "root_folder": self.root_folder, } for song in songs: self.current_path = song.path song.render(self, global_context) - self.render('index.html', self.root_folder, global_context) + self.render("index.html", self.root_folder, global_context) - home = self.root_folder / 'home' + home = self.root_folder / "home" self.current_path = home if not home.exists(): home.mkdir() - self.render('home.html', home, global_context) + self.render("home.html", home, global_context) - playlist = self.root_folder / 'playlist' + playlist = self.root_folder / "playlist" self.current_path = playlist if not playlist.exists(): playlist.mkdir() - self.render('playlist.html', playlist, global_context) + self.render("playlist.html", playlist, global_context) - todo = self.root_folder / 'todo' + todo = self.root_folder / "todo" self.current_path = todo if not todo.exists(): todo.mkdir() todo_context = { - 'pending_songs': pending_songs, + "pending_songs": pending_songs, } todo_context.update(global_context) - self.render('todo.html', todo, todo_context) + self.render("todo.html", todo, todo_context) - static = self.root_folder / 'static' + static = self.root_folder / "static" if not static.exists(): static.mkdir() - subprocess.check_call([ - 'rsync', - '-ra', - str(self.static_folder), - str(self.root_folder.absolute()), - ]) + subprocess.check_call( + [ + "rsync", + "-ra", + str(self.static_folder), + str(self.root_folder.absolute()), + ] + ) - libreto = self.root_folder / 'static/libreto/libreto.pdf' + libreto = self.root_folder / "static/libreto/libreto.pdf" copy(str(self.libreto.absolute()), str(libreto.absolute())) diff --git a/negromate/web/commands/build.py b/negromate/web/commands/build.py index 426295a..2a07c8d 100644 --- a/negromate/web/commands/build.py +++ b/negromate/web/commands/build.py @@ -1,36 +1,45 @@ from pathlib import Path + from ..builder import Builder -name = 'build' -help_text = 'Generate static website' +name = "build" +help_text = "Generate static website" initial_config = { - 'template_folder': '~/negro_mate/web/templates', - 'static_folder': '~/negro_mate/web/static', + "template_folder": "~/negro_mate/web/templates", + "static_folder": "~/negro_mate/web/static", } def options(parser, config, **kwargs): parser.add_argument( - '-s', '--song_folder', type=Path, - default=config['global']['song_folder'], - help="Folder with the song database, defaults to {}".format( - config['global']['song_folder'])) + "-s", + "--song_folder", + type=Path, + default=config["global"]["song_folder"], + help="Folder with the song database, defaults to {}".format(config["global"]["song_folder"]), + ) parser.add_argument( - '-l', '--lyrics_file', type=Path, - default=config['global']['lyrics_file'], - help="File with the lyrics of the songs, defaults to {}".format( - config['global']['lyrics_file'])) + "-l", + "--lyrics_file", + type=Path, + default=config["global"]["lyrics_file"], + help="File with the lyrics of the songs, defaults to {}".format(config["global"]["lyrics_file"]), + ) parser.add_argument( - '-t', '--template_folder', type=Path, - default=config['build']['template_folder'], - help="Folder with jinja2 templates, defaults to {}".format( - config['build']['template_folder'])) + "-t", + "--template_folder", + type=Path, + default=config["build"]["template_folder"], + help="Folder with jinja2 templates, defaults to {}".format(config["build"]["template_folder"]), + ) parser.add_argument( - '-S', '--static_folder', type=Path, - default=config['build']['static_folder'], - help="Folder with static content, defaults to {}".format( - config['build']['static_folder'])) + "-S", + "--static_folder", + type=Path, + default=config["build"]["static_folder"], + help="Folder with static content, defaults to {}".format(config["build"]["static_folder"]), + ) def run(args, **kwargs): diff --git a/negromate/web/commands/ipfs.py b/negromate/web/commands/ipfs.py index ae05e26..45b2f7f 100644 --- a/negromate/web/commands/ipfs.py +++ b/negromate/web/commands/ipfs.py @@ -1,48 +1,52 @@ -from pathlib import Path import getpass import subprocess import urllib.request +from pathlib import Path from negromate.songs import logger -name = 'ipfs' -help_text = 'Upload the web to IPFS' +name = "ipfs" +help_text = "Upload the web to IPFS" initial_config = { - 'api': 'http://ipfs.negromate.rocks', - 'pinfile': '~/.negromate/ipfs.hash', - 'realm': 'IPFS Gitea Negromate', + "api": "http://ipfs.negromate.rocks", + "pinfile": "~/.negromate/ipfs.hash", + "realm": "IPFS Gitea Negromate", } def options(parser, config, **kwargs): parser.add_argument( - '-s', '--song_folder', type=Path, - default=config['global']['song_folder'], - help="Folder with the song database, defaults to {}".format( - config['global']['song_folder'])) + "-s", + "--song_folder", + type=Path, + default=config["global"]["song_folder"], + help="Folder with the song database, defaults to {}".format(config["global"]["song_folder"]), + ) parser.add_argument( - '-a', '--api', default=config[name]['api'], - help="IPFS API server, defaults to {}.".format(config[name]['api'])) + "-a", "--api", default=config[name]["api"], help="IPFS API server, defaults to {}.".format(config[name]["api"]) + ) parser.add_argument( - '-r', '--realm', default=config[name]['realm'], - help="IPFS API basic authentication realm, defaults to {}.".format(config[name]['realm'])) + "-r", + "--realm", + default=config[name]["realm"], + help="IPFS API basic authentication realm, defaults to {}.".format(config[name]["realm"]), + ) parser.add_argument( - '-p', '--pinfile', default=config[name]['pinfile'], type=Path, - help="file to store the current ipfs hash, defaults to {}".format( - config[name]['pinfile'])) + "-p", + "--pinfile", + default=config[name]["pinfile"], + type=Path, + help="file to store the current ipfs hash, defaults to {}".format(config[name]["pinfile"]), + ) def run(args, **kwargs): # Setup HTTP Basic authentication - user = input('Username: ') - password = getpass.getpass('Password:') + user = input("Username: ") + password = getpass.getpass("Password:") auth_handler = urllib.request.HTTPBasicAuthHandler() - auth_handler.add_password( - realm=args.realm, - uri=args.api, - user=user, - passwd=password) + auth_handler.add_password(realm=args.realm, uri=args.api, user=user, passwd=password) opener = urllib.request.build_opener(auth_handler) urllib.request.install_opener(opener) @@ -54,37 +58,41 @@ def run(args, **kwargs): "--quieter", args.song_folder.expanduser(), ] - new_hash = subprocess.check_output(command).decode('utf-8').strip() - logger.info('New hash: {}'.format(new_hash)) + new_hash = subprocess.check_output(command).decode("utf-8").strip() + logger.info("New hash: {}".format(new_hash)) # pin in server - data = urllib.parse.urlencode({ - 'arg': new_hash, - 'progress': 'false', - }) - url = '{}/api/v0/pin/add?{}'.format(args.api, data) + data = urllib.parse.urlencode( + { + "arg": new_hash, + "progress": "false", + } + ) + url = "{}/api/v0/pin/add?{}".format(args.api, data) logger.debug("server pin request: {}".format(url)) - request = urllib.request.Request(url, method='POST') + request = urllib.request.Request(url, method="POST") urllib.request.urlopen(request) - logger.info('Hash pinned on server.') + logger.info("Hash pinned on server.") # update ipns on server - data = urllib.parse.urlencode({ - 'arg': new_hash, - 'resolve': 'true', - }) + data = urllib.parse.urlencode( + { + "arg": new_hash, + "resolve": "true", + } + ) url = "{}/api/v0/name/publish?{}".format(args.api, data) logger.debug("server ipns request: {}".format(url)) - request = urllib.request.Request(url, method='POST') + request = urllib.request.Request(url, method="POST") urllib.request.urlopen(request) - logger.info('IPNS name updated.') + logger.info("IPNS name updated.") # read previous hash and update value pinfile = args.pinfile.expanduser() if pinfile.exists(): with pinfile.open() as f: previous_hash = f.read() - logger.info('Previous hash: {}'.format(previous_hash)) + logger.info("Previous hash: {}".format(previous_hash)) else: if not pinfile.parent.exists(): pinfile.parent.mkdir() @@ -93,26 +101,28 @@ def run(args, **kwargs): if previous_hash is not None and previous_hash != new_hash: # remove previous pin on local command = [ - 'ipfs', - 'pin', - 'rm', + "ipfs", + "pin", + "rm", previous_hash, ] result = subprocess.run(command) if result.returncode != 0: - logger.info('Previous {} hash not removed: {}'.format(previous_hash, result.stdout)) + logger.info("Previous {} hash not removed: {}".format(previous_hash, result.stdout)) else: - logger.info('Previous hash unpinned on local') + logger.info("Previous hash unpinned on local") # remove previous pin on server - data = urllib.parse.urlencode({ - 'arg': previous_hash, - }) + data = urllib.parse.urlencode( + { + "arg": previous_hash, + } + ) url = "{}/api/v0/pin/rm?{}".format(args.api, data) logger.debug("server unpin request: {}".format(url)) - request = urllib.request.Request(url, method='POST') + request = urllib.request.Request(url, method="POST") urllib.request.urlopen(request) - logger.info('Previous hash unpinned on server') + logger.info("Previous hash unpinned on server") - with pinfile.open('w') as f: + with pinfile.open("w") as f: f.write(new_hash) diff --git a/negromate/web/commands/rsync.py b/negromate/web/commands/rsync.py index bdc47fe..34bf6ea 100644 --- a/negromate/web/commands/rsync.py +++ b/negromate/web/commands/rsync.py @@ -1,38 +1,51 @@ import subprocess from pathlib import Path -name = 'rsync' -help_text = 'Sincronize the static web with the server' + +name = "rsync" +help_text = "Sincronize the static web with the server" initial_config = { - 'host': 'negromate.rocks', - 'user': 'root', - 'port': '22', - 'destination': "/var/www/html", + "host": "negromate.rocks", + "user": "root", + "port": "22", + "destination": "/var/www/html", } def options(parser, config, **kwargs): parser.add_argument( - '-s', '--song_folder', type=Path, - default=config['global']['song_folder'], - help="Folder with the song database, defaults to {}".format( - config['global']['song_folder'])) + "-s", + "--song_folder", + type=Path, + default=config["global"]["song_folder"], + help="Folder with the song database, defaults to {}".format(config["global"]["song_folder"]), + ) parser.add_argument( - '-H', '--host', default=config[name]['host'], - help="Target server, defaults to {}.".format(config[name]['host'])) + "-H", "--host", default=config[name]["host"], help="Target server, defaults to {}.".format(config[name]["host"]) + ) parser.add_argument( - '-u', '--user', default=config[name]['user'], - help="User in the server, defaults to {}.".format(config[name]['user'])) + "-u", + "--user", + default=config[name]["user"], + help="User in the server, defaults to {}.".format(config[name]["user"]), + ) parser.add_argument( - '-p', '--port', default=config[name]['port'], type=int, - help="Port of the ssh server, defaults to {}.".format(config[name]['port'])) + "-p", + "--port", + default=config[name]["port"], + type=int, + help="Port of the ssh server, defaults to {}.".format(config[name]["port"]), + ) parser.add_argument( - '-d', '--destination', default=config[name]['destination'], - help="Folder of the server, defaults to {}".format(config[name]['destination'])) + "-d", + "--destination", + default=config[name]["destination"], + help="Folder of the server, defaults to {}".format(config[name]["destination"]), + ) def run(args, **kwargs): - contents = str(args.song_folder.expanduser()) + '/' + contents = str(args.song_folder.expanduser()) + "/" destination = "{user}@{host}:{folder}".format( user=args.user, host=args.host, @@ -41,7 +54,7 @@ def run(args, **kwargs): command = [ "rsync", "-av", - '--rsh=ssh -p {}'.format(args.port), + "--rsh=ssh -p {}".format(args.port), contents, destination, ] diff --git a/negromate/web/commands/run.py b/negromate/web/commands/run.py index 4ada173..c898c0a 100644 --- a/negromate/web/commands/run.py +++ b/negromate/web/commands/run.py @@ -1,30 +1,40 @@ from functools import partial -from http.server import test, SimpleHTTPRequestHandler +from http.server import SimpleHTTPRequestHandler, test from pathlib import Path -name = 'run' -help_text = 'Start web server to test the website' +name = "run" +help_text = "Start web server to test the website" initial_config = { - 'port': '8000', - 'bind': '', + "port": "8000", + "bind": "", } def options(parser, config, **kwargs): parser.add_argument( - '-s', '--song_folder', type=Path, - default=config['global']['song_folder'], - help="Folder with the song database, defaults to {}".format( - config['global']['song_folder'])) + "-s", + "--song_folder", + type=Path, + default=config["global"]["song_folder"], + help="Folder with the song database, defaults to {}".format(config["global"]["song_folder"]), + ) parser.add_argument( - '-p', '--port', default=config[name]['port'], type=int, - help='Specify alternate port, defaults to {}'.format(config[name]['port'])) + "-p", + "--port", + default=config[name]["port"], + type=int, + help="Specify alternate port, defaults to {}".format(config[name]["port"]), + ) parser.add_argument( - '--bind', '-b', default=config[name]['bind'], metavar='ADDRESS', - help='Specify alternate bind address, defaults to {}'.format( - config[name]['bind'] or 'all interfaces', - )) + "--bind", + "-b", + default=config[name]["bind"], + metavar="ADDRESS", + help="Specify alternate bind address, defaults to {}".format( + config[name]["bind"] or "all interfaces", + ), + ) def run(args, **kwargs): diff --git a/pyproject.toml b/pyproject.toml index 9787c3b..5c8584a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,23 @@ [build-system] requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" + +[tool.black] +line_length = 120 + +[tool.isort] +profile = "black" +lines_after_imports = 2 + +[tool.pylint.'MESSAGES CONTROL'] +max-line-length = 120 +disable = "invalid-name, unused-wildcard-import, wildcard-import" + +[tool.ruff] +line-length = 120 +exclude = [ + "build", +] +include = ["negromate/*"] +fix = false +force-exclude = true diff --git a/requirements.txt b/requirements.txt index f107765..df7e488 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ webvtt-py -Jinja2 +Jinja2==3.1.3 ass==0.4.4 -negromate.songs==1.2 +negromate.songs==1.3 diff --git a/setup.cfg b/setup.cfg index 8a71f91..1e67bbe 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,9 +20,9 @@ packages = find_namespace: zip_safe = false python_requires = >= 3.4 install_requires = - Jinja2 + Jinja2 ==3.1.3 ass ==0.5.2 - negromate.songs ==1.3 + negromate.songs >=1.4 [options.entry_points] negromate.commands =