mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-07-29 07:03:47 +00:00
rewrite options with click
+ fix cpu count multiprocessing errors
This commit is contained in:
+21
-135
@@ -2,60 +2,33 @@
|
||||
Handles arguments passed to the program.
|
||||
"""
|
||||
|
||||
from getpass import getpass
|
||||
import os.path
|
||||
import sys
|
||||
from getpass import getpass
|
||||
|
||||
import click
|
||||
import PyInstaller.__main__ as bundler
|
||||
|
||||
from app import settings
|
||||
from app.config import UserConfig
|
||||
from app.db.userdata import UserTable
|
||||
from app.logger import log
|
||||
from app.print_help import HELP_MESSAGE
|
||||
from app.setup.sqlite import setup_sqlite
|
||||
from app.utils.auth import hash_password
|
||||
from app.utils.paths import getFlaskOpenApiPath
|
||||
from app.utils.xdg_utils import get_xdg_config_dir
|
||||
from app.utils.wintools import is_windows
|
||||
|
||||
ALLARGS = settings.ALLARGS
|
||||
ARGS = sys.argv[1:]
|
||||
|
||||
|
||||
class ProcessArgs:
|
||||
def handle_build(*args, **kwargs):
|
||||
"""
|
||||
Processes the arguments passed to the program.
|
||||
Handles the --build argument. Builds the project into a single executable.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
# resolve config path
|
||||
self.handle_config_path() # 1
|
||||
|
||||
# handles that exit
|
||||
self.handle_password_recovery()
|
||||
self.handle_build()
|
||||
self.handle_help()
|
||||
self.handle_version()
|
||||
|
||||
# non-exiting handles
|
||||
self.handle_host()
|
||||
self.handle_port()
|
||||
self.handle_periodic_scan()
|
||||
self.handle_periodic_scan_interval()
|
||||
|
||||
@staticmethod
|
||||
def handle_build():
|
||||
"""
|
||||
Runs Pyinstaller.
|
||||
"""
|
||||
|
||||
if ALLARGS.build not in ARGS:
|
||||
if not args[2]:
|
||||
return
|
||||
|
||||
if settings.IS_BUILD:
|
||||
print("Do the cha cha slide instead!")
|
||||
print("https://www.youtube.com/watch?v=wZv62ShoStY")
|
||||
click.echo("Can't build the project. Exiting ...")
|
||||
sys.exit(0)
|
||||
|
||||
info_keys = [
|
||||
@@ -70,7 +43,9 @@ class ProcessArgs:
|
||||
value = settings.Info.get(key)
|
||||
|
||||
if not value:
|
||||
log.error(f"WARNING: {key} not resolved. Exiting ...")
|
||||
log.error(
|
||||
f"WARNING: {key} not resolved. Can't build the project. Exiting ..."
|
||||
)
|
||||
sys.exit(0)
|
||||
|
||||
lines.append(f'{key} = "{value}"\n')
|
||||
@@ -87,7 +62,7 @@ class ProcessArgs:
|
||||
|
||||
bundler.run(
|
||||
[
|
||||
"manage.py",
|
||||
"main.py",
|
||||
"--onefile",
|
||||
"--name",
|
||||
"swingmusic",
|
||||
@@ -107,108 +82,14 @@ class ProcessArgs:
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
@staticmethod
|
||||
def handle_port():
|
||||
if ALLARGS.port in ARGS:
|
||||
index = ARGS.index(ALLARGS.port)
|
||||
try:
|
||||
port = ARGS[index + 1]
|
||||
except IndexError:
|
||||
print("ERROR: Port not specified")
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
settings.FLASKVARS.FLASK_PORT = int(port) # type: ignore
|
||||
except ValueError:
|
||||
print("ERROR: Port should be a number")
|
||||
sys.exit(0)
|
||||
|
||||
@staticmethod
|
||||
def handle_host():
|
||||
if ALLARGS.host in ARGS:
|
||||
index = ARGS.index(ALLARGS.host)
|
||||
|
||||
try:
|
||||
host = ARGS[index + 1]
|
||||
except IndexError:
|
||||
print("ERROR: Host not specified")
|
||||
sys.exit(0)
|
||||
|
||||
settings.FLASKVARS.set_flask_host(host) # type: ignore
|
||||
|
||||
@staticmethod
|
||||
def handle_config_path():
|
||||
def handle_password_reset(*args, **kwargs):
|
||||
"""
|
||||
Modifies the config path.
|
||||
Handles the --password-reset argument. Resets the password.
|
||||
"""
|
||||
if ALLARGS.config in ARGS:
|
||||
index = ARGS.index(ALLARGS.config)
|
||||
|
||||
try:
|
||||
config_path = ARGS[index + 1]
|
||||
resolved = os.path.abspath(config_path)
|
||||
|
||||
if os.path.exists(resolved):
|
||||
settings.Paths.set_config_dir(resolved)
|
||||
if not args[2]:
|
||||
return
|
||||
|
||||
log.warn(f"Config path {resolved} doesn't exist")
|
||||
sys.exit(0)
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
settings.Paths.set_config_dir(get_xdg_config_dir())
|
||||
|
||||
@staticmethod
|
||||
def handle_periodic_scan():
|
||||
if any((a in ARGS for a in ALLARGS.no_periodic_scan)):
|
||||
UserConfig().enablePeriodicScans = False
|
||||
|
||||
@staticmethod
|
||||
def handle_periodic_scan_interval():
|
||||
if any((a in ARGS for a in ALLARGS.periodic_scan_interval)):
|
||||
index = [
|
||||
ARGS.index(a) for a in ALLARGS.periodic_scan_interval if a in ARGS
|
||||
][0]
|
||||
|
||||
try:
|
||||
interval = ARGS[index + 1]
|
||||
except IndexError:
|
||||
print("ERROR: Interval not specified")
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
psi = int(interval)
|
||||
except ValueError:
|
||||
print("ERROR: Interval should be a number")
|
||||
sys.exit(0)
|
||||
|
||||
if psi < 0:
|
||||
print("WHAT ARE YOU TRYING?")
|
||||
sys.exit(0)
|
||||
|
||||
UserConfig().scanInterval = psi
|
||||
|
||||
@staticmethod
|
||||
def handle_help():
|
||||
if any((a in ARGS for a in ALLARGS.help)):
|
||||
print(HELP_MESSAGE)
|
||||
sys.exit(0)
|
||||
|
||||
@staticmethod
|
||||
def handle_version():
|
||||
if any((a in ARGS for a in ALLARGS.version)):
|
||||
print(f"VERSION: v{settings.Info.SWINGMUSIC_APP_VERSION}")
|
||||
print(
|
||||
f"COMMIT#: {settings.Info.GIT_CURRENT_BRANCH}/{settings.Info.GIT_LATEST_COMMIT_HASH}"
|
||||
)
|
||||
sys.exit(0)
|
||||
|
||||
@staticmethod
|
||||
def handle_password_recovery():
|
||||
if ALLARGS.pswd in ARGS:
|
||||
print("SWING MUSIC v2.0.0 ")
|
||||
print("PASSWORD RECOVERY \n")
|
||||
setup_sqlite()
|
||||
|
||||
username: str = ""
|
||||
@@ -218,23 +99,28 @@ class ProcessArgs:
|
||||
try:
|
||||
username = input("Enter username: ")
|
||||
except KeyboardInterrupt:
|
||||
print("\nOperation cancelled! Exiting ...")
|
||||
click.echo("\nOperation cancelled! Exiting ...")
|
||||
sys.exit(0)
|
||||
|
||||
username = username.strip()
|
||||
user = UserTable.get_by_username(username)
|
||||
|
||||
if not user:
|
||||
print(f"User {username} not found")
|
||||
click.echo(f"User {username} not found")
|
||||
sys.exit(0)
|
||||
|
||||
# collect password
|
||||
try:
|
||||
password = getpass("Enter new password: ")
|
||||
except KeyboardInterrupt:
|
||||
print("\nOperation cancelled! Exiting ...")
|
||||
click.echo("\nOperation cancelled! Exiting ...")
|
||||
sys.exit(0)
|
||||
|
||||
try:
|
||||
UserTable.update_one({"id": user.id, "password": hash_password(password)})
|
||||
click.echo("Password reset successfully!")
|
||||
except Exception as e:
|
||||
click.echo(f"Error resetting password: {e}")
|
||||
sys.exit(0)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
@@ -157,8 +157,7 @@ class CheckArtistImages:
|
||||
]
|
||||
|
||||
# Use number of CPU cores minus 1 to leave one core free for system processes
|
||||
num_workers = max(1, math.floor(multiprocessing.cpu_count() / 2))
|
||||
print("num_workers", num_workers)
|
||||
num_workers = max(1, os.cpu_count() // 2)
|
||||
|
||||
with ProcessPoolExecutor(max_workers=num_workers) as executor:
|
||||
res = list(
|
||||
|
||||
@@ -5,12 +5,10 @@ from app.lib.sortlib import sort_folders, sort_tracks
|
||||
from app.logger import log
|
||||
from app.models import Folder
|
||||
from app.serializers.track import serialize_tracks
|
||||
from app.settings import SUPPORTED_FILES
|
||||
from app.utils.filesystem import SUPPORTED_FILES
|
||||
from app.store.folder import FolderStore
|
||||
from app.utils.wintools import win_replace_slash
|
||||
|
||||
# from app.db.libdata import TrackTable as TrackDB
|
||||
|
||||
|
||||
def create_folder(path: str, trackcount=0) -> Folder:
|
||||
"""
|
||||
|
||||
+3
-10
@@ -22,6 +22,7 @@ from app.utils.progressbar import tqdm
|
||||
|
||||
from app.db.userdata import SimilarArtistTable
|
||||
|
||||
|
||||
class CordinateMedia:
|
||||
"""
|
||||
Cordinates the extracting of thumbnails
|
||||
@@ -72,14 +73,6 @@ def get_image(album: Album):
|
||||
return
|
||||
|
||||
|
||||
def get_cpu_count():
|
||||
"""
|
||||
Returns the number of CPUs on the machine.
|
||||
"""
|
||||
cpu_count = os.cpu_count() or 0
|
||||
return cpu_count // 2 if cpu_count > 2 else cpu_count
|
||||
|
||||
|
||||
class ProcessTrackThumbnails:
|
||||
"""
|
||||
Extracts the album art from all albums in album store.
|
||||
@@ -93,7 +86,7 @@ class ProcessTrackThumbnails:
|
||||
if platform.system() == "Linux":
|
||||
# INFO: Processess are forked with access to global stores
|
||||
# It's "safe" to use a process pool
|
||||
cpus = math.floor(get_cpu_count() / 2)
|
||||
cpus = max(1, os.cpu_count() // 2)
|
||||
with ProcessPoolExecutor(max_workers=cpus) as executor:
|
||||
results = list(
|
||||
tqdm(
|
||||
@@ -160,7 +153,7 @@ class FetchSimilarArtistsLastFM:
|
||||
)
|
||||
artists = list(artists)
|
||||
|
||||
with ProcessPoolExecutor(max_workers=get_cpu_count()) as executor:
|
||||
with ProcessPoolExecutor(max_workers=max(1, os.cpu_count() // 2)) as executor:
|
||||
try:
|
||||
print("Processing similar artists")
|
||||
results = list(
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
from app.settings import ALLARGS, Info
|
||||
from tabulate import tabulate
|
||||
|
||||
args = ALLARGS
|
||||
|
||||
help_args_list = [
|
||||
["--help", "-h", "Show this help message"],
|
||||
["--version", "-v", "Show the app version"],
|
||||
["--host", "", "Set the host"],
|
||||
["--port", "", "Set the port"],
|
||||
["--config", "", "Set the config path"],
|
||||
["--no-periodic-scan", "-nps", "Disable periodic scan"],
|
||||
["--pswd", "", "Recover a password"],
|
||||
[
|
||||
"--scan-interval",
|
||||
"-psi",
|
||||
"Set the scan interval in seconds. Default 600s (10 minutes)",
|
||||
],
|
||||
[
|
||||
"--build",
|
||||
"",
|
||||
"Build the application (in development)",
|
||||
],
|
||||
]
|
||||
|
||||
HELP_MESSAGE = f"""
|
||||
Swing Music v{Info.SWINGMUSIC_APP_VERSION}
|
||||
|
||||
A beautiful, self-hosted music player for your local audio files.
|
||||
Like Spotify ... but bring your own music.
|
||||
|
||||
Usage: ./swingmusic [options] [args]
|
||||
|
||||
{tabulate(help_args_list, headers=["Option", "Alias", "Description"], tablefmt="psql", maxcolwidths=[None, None, 40])}
|
||||
"""
|
||||
+10
-4
@@ -7,6 +7,7 @@ import subprocess
|
||||
import sys
|
||||
|
||||
from app import configs
|
||||
from app.utils.filesystem import get_home_res_path
|
||||
|
||||
join = os.path.join
|
||||
|
||||
@@ -159,10 +160,6 @@ class Defaults:
|
||||
API_CARD_LIMIT = 6
|
||||
|
||||
|
||||
FILES = ["flac", "mp3", "wav", "m4a", "ogg", "wma", "opus", "alac", "aiff"]
|
||||
SUPPORTED_FILES = tuple(f".{file}" for file in FILES)
|
||||
|
||||
|
||||
# ===== SQLite =====
|
||||
class DbPaths:
|
||||
APP_DB_NAME = "swingmusic.db"
|
||||
@@ -304,6 +301,15 @@ class Info:
|
||||
"""
|
||||
|
||||
SWINGMUSIC_APP_VERSION = os.environ.get("SWINGMUSIC_APP_VERSION")
|
||||
|
||||
if not SWINGMUSIC_APP_VERSION:
|
||||
path = get_home_res_path("version.txt")
|
||||
if not path:
|
||||
raise ValueError("Version file not found")
|
||||
|
||||
with open(path, "r") as f:
|
||||
SWINGMUSIC_APP_VERSION = f.read().strip()
|
||||
|
||||
GIT_LATEST_COMMIT_HASH = "<unset>"
|
||||
GIT_CURRENT_BRANCH = "<unset>"
|
||||
|
||||
|
||||
+14
-18
@@ -1,30 +1,26 @@
|
||||
import os
|
||||
|
||||
from app.settings import FLASKVARS, TCOLOR, Info, Paths
|
||||
from app.settings import TCOLOR, Info, Paths
|
||||
from app.utils.network import get_ip
|
||||
import click
|
||||
|
||||
|
||||
def log_startup_info():
|
||||
lines = "------------------------------"
|
||||
def log_startup_info(host: str, port: int):
|
||||
lines = "-"*30
|
||||
# clears terminal 👇
|
||||
# os.system("cls" if os.name == "nt" else "echo -e \\\\033c")
|
||||
|
||||
print(lines)
|
||||
print(f"{TCOLOR.HEADER}Swing Music v{Info.SWINGMUSIC_APP_VERSION} {TCOLOR.ENDC}")
|
||||
click.echo(f"{TCOLOR.HEADER}Swing Music v{Info.SWINGMUSIC_APP_VERSION} {TCOLOR.ENDC}")
|
||||
|
||||
adresses = [FLASKVARS.get_flask_host()]
|
||||
addresses = [host]
|
||||
|
||||
if FLASKVARS.get_flask_host() == "0.0.0.0":
|
||||
if host == "0.0.0.0":
|
||||
remote_ip = get_ip()
|
||||
adresses = ["localhost"] + ([remote_ip] if remote_ip else [])
|
||||
addresses.extend(["127.0.0.1"] + ([remote_ip] if remote_ip else []))
|
||||
|
||||
print("Started app on:")
|
||||
for address in adresses:
|
||||
# noinspection HttpUrlsUsage
|
||||
print(
|
||||
f"➤ {TCOLOR.OKGREEN}http://{address}:{FLASKVARS.get_flask_port()}{TCOLOR.ENDC}"
|
||||
click.echo("Server running on:\n")
|
||||
for address in addresses:
|
||||
click.echo(
|
||||
f"{TCOLOR.OKGREEN}http://{address}:{port}{TCOLOR.ENDC}"
|
||||
)
|
||||
|
||||
print(lines + "\n")
|
||||
|
||||
print(f"{TCOLOR.YELLOW}Data folder: {Paths.get_app_dir()}{TCOLOR.ENDC}")
|
||||
click.echo("")
|
||||
click.echo(f"{TCOLOR.YELLOW}Data folder: {Paths.get_app_dir()}{TCOLOR.ENDC}\n")
|
||||
|
||||
@@ -114,6 +114,8 @@ class TrackStore:
|
||||
else:
|
||||
cls.trackhashmap[track.trackhash].append(track)
|
||||
|
||||
print("Done!")
|
||||
|
||||
@classmethod
|
||||
def add_track(cls, track: Track):
|
||||
"""
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from app.settings import SUPPORTED_FILES
|
||||
from app.utils.wintools import win_replace_slash
|
||||
|
||||
CWD = Path(__file__).parent.resolve()
|
||||
|
||||
FILES = ["flac", "mp3", "wav", "m4a", "ogg", "wma", "opus", "alac", "aiff"]
|
||||
SUPPORTED_FILES = tuple(f".{file}" for file in FILES)
|
||||
|
||||
|
||||
def run_fast_scandir(_dir: str, full=False) -> tuple[list[str], list[str]]:
|
||||
"""
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import multiprocessing
|
||||
import pathlib
|
||||
import click
|
||||
import sys
|
||||
from app.arg_handler import handle_build, handle_password_reset
|
||||
from app.utils.filesystem import get_home_res_path
|
||||
from app.utils.xdg_utils import get_xdg_config_dir
|
||||
from manage import run_app
|
||||
|
||||
|
||||
def version(*args, **kwargs):
|
||||
if not args[2]:
|
||||
return
|
||||
|
||||
path = get_home_res_path("version.txt")
|
||||
if not path:
|
||||
click.echo("Version file not found.")
|
||||
sys.exit(1)
|
||||
|
||||
with open(path, "r") as f:
|
||||
version = f.read()
|
||||
|
||||
click.echo(version)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
@click.command(options_metavar="<options>", context_settings={"show_default": True})
|
||||
@click.option(
|
||||
"--build",
|
||||
default=False,
|
||||
help="Build the project.",
|
||||
is_eager=True,
|
||||
callback=handle_build,
|
||||
is_flag=True,
|
||||
)
|
||||
@click.option("--host", default="0.0.0.0", help="Host to run the app on.")
|
||||
@click.option("--port", default=1970, help="HTTP port to run the app on.")
|
||||
@click.option(
|
||||
"--config",
|
||||
default=lambda: get_xdg_config_dir(),
|
||||
show_default="XDG_CONFIG_HOME",
|
||||
help="Path to the config file.",
|
||||
type=click.Path(
|
||||
exists=True,
|
||||
file_okay=False,
|
||||
dir_okay=True,
|
||||
writable=True,
|
||||
resolve_path=True,
|
||||
allow_dash=False,
|
||||
path_type=pathlib.Path,
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--password-reset",
|
||||
is_flag=True,
|
||||
help="Reset the password.",
|
||||
is_eager=True,
|
||||
callback=handle_password_reset,
|
||||
)
|
||||
@click.option(
|
||||
"--version",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
callback=version,
|
||||
help="Show the version and exit",
|
||||
is_eager=True,
|
||||
)
|
||||
def run(*args, **kwargs):
|
||||
run_app(kwargs["host"], kwargs["port"], kwargs["config"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
multiprocessing.freeze_support()
|
||||
run()
|
||||
@@ -2,14 +2,11 @@
|
||||
This file is used to run the application.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import psutil
|
||||
import waitress
|
||||
# import bjoern
|
||||
import logging
|
||||
import mimetypes
|
||||
import setproctitle
|
||||
import multiprocessing
|
||||
from pathlib import Path
|
||||
|
||||
from flask_jwt_extended import (
|
||||
create_access_token,
|
||||
@@ -21,18 +18,20 @@ from flask_jwt_extended import (
|
||||
from datetime import datetime, timezone
|
||||
from flask import Response, request
|
||||
|
||||
from app import settings
|
||||
from app.api import create_api
|
||||
from app.crons import start_cron_jobs
|
||||
from app.arg_handler import ProcessArgs
|
||||
from app.lib.index import IndexEverything
|
||||
from app.utils.threading import background
|
||||
from app.setup import load_into_mem, run_setup
|
||||
from app.settings import FLASKVARS, TCOLOR, Info
|
||||
from app.plugins.register import register_plugins
|
||||
from app.start_info_logger import log_startup_info
|
||||
from app.utils.filesystem import get_home_res_path
|
||||
from app.utils.paths import getClientFilesExtensions
|
||||
|
||||
|
||||
def run_app(host: str, port: int, config: Path):
|
||||
settings.Paths.set_config_dir(config)
|
||||
|
||||
# Load mimetypes for the web client's static files
|
||||
# Loading mimetypes should happen automatically but
|
||||
# sometimes the mimetypes are not loaded correctly
|
||||
@@ -60,41 +59,20 @@ mimetypes.add_type("application/manifest+json", ".webmanifest")
|
||||
waitress_logger = logging.getLogger("waitress")
|
||||
waitress_logger.setLevel(logging.ERROR)
|
||||
|
||||
# # logging.basicConfig()
|
||||
# logging.getLogger("sqlalchemy.engine").setLevel(logging.ERROR)
|
||||
|
||||
|
||||
# Background tasks
|
||||
# @background
|
||||
def bg_run_setup():
|
||||
IndexEverything()
|
||||
|
||||
|
||||
# @background
|
||||
# def start_watchdog():
|
||||
# WatchDog().run()
|
||||
|
||||
log_startup_info(host, port)
|
||||
|
||||
@background
|
||||
def run_swingmusic():
|
||||
log_startup_info()
|
||||
register_plugins()
|
||||
|
||||
# start_watchdog()
|
||||
|
||||
setproctitle.setproctitle(f"swingmusic ::{FLASKVARS.get_flask_port()}")
|
||||
# bg_run_setup()
|
||||
setproctitle.setproctitle(f"swingmusic {host}:{port}")
|
||||
start_cron_jobs()
|
||||
|
||||
|
||||
# Setup function calls
|
||||
Info.load()
|
||||
ProcessArgs()
|
||||
settings.Info.load()
|
||||
run_setup()
|
||||
|
||||
|
||||
# Create the Flask app
|
||||
|
||||
app = create_api()
|
||||
app.static_folder = get_home_res_path("client")
|
||||
|
||||
@@ -109,7 +87,6 @@ whitelisted_routes = {
|
||||
}
|
||||
blacklist_extensions = {".webp", ".jpg"}.union(getClientFilesExtensions())
|
||||
|
||||
|
||||
def skipAuthAction():
|
||||
"""
|
||||
Skips the JWT verification for the current request.
|
||||
@@ -125,7 +102,6 @@ def skipAuthAction():
|
||||
|
||||
return False
|
||||
|
||||
|
||||
@app.before_request
|
||||
def verify_auth():
|
||||
"""
|
||||
@@ -136,7 +112,6 @@ def verify_auth():
|
||||
|
||||
verify_jwt_in_request()
|
||||
|
||||
|
||||
@app.after_request
|
||||
def refresh_expiring_jwt(response: Response):
|
||||
"""
|
||||
@@ -161,7 +136,6 @@ def refresh_expiring_jwt(response: Response):
|
||||
except (RuntimeError, KeyError):
|
||||
return response
|
||||
|
||||
|
||||
@app.route("/<path:path>")
|
||||
def serve_client_files(path: str):
|
||||
"""
|
||||
@@ -177,7 +151,9 @@ def serve_client_files(path: str):
|
||||
# INFO: Safari doesn't support gzip encoding
|
||||
# See issue: https://github.com/swingmx/swingmusic/issues/155
|
||||
is_safari = (
|
||||
user_agent and user_agent.find("Safari") >= 0 and user_agent.find("Chrome") < 0
|
||||
user_agent
|
||||
and user_agent.find("Safari") >= 0
|
||||
and user_agent.find("Chrome") < 0
|
||||
)
|
||||
|
||||
if is_safari:
|
||||
@@ -193,7 +169,6 @@ def serve_client_files(path: str):
|
||||
|
||||
return app.send_static_file(path)
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def serve_client():
|
||||
"""
|
||||
@@ -201,43 +176,17 @@ def serve_client():
|
||||
"""
|
||||
return app.send_static_file("index.html")
|
||||
|
||||
|
||||
prev_memory = 0
|
||||
|
||||
|
||||
# INFO: For debugging memory usage
|
||||
# @app.after_request
|
||||
def print_memory_usage(response: Response):
|
||||
# INFO: Ignore assets
|
||||
if (
|
||||
request.path.startswith("/img")
|
||||
or request.path.endswith(".js")
|
||||
or request.path.endswith(".css")
|
||||
):
|
||||
return response
|
||||
|
||||
process = psutil.Process(os.getpid())
|
||||
global prev_memory
|
||||
current_mem = process.memory_info().rss
|
||||
diff = (current_mem - prev_memory) / 1024**2
|
||||
prev_memory = current_mem
|
||||
|
||||
# INFO: Print memory usage (highlights if diff is more than 0.1 MB)
|
||||
print(
|
||||
f"\n{request.path} | TOTAL: {current_mem/1024**2} MB | DIFF: {TCOLOR.FAIL if diff > 0.1 else ''}{diff} MB{TCOLOR.ENDC if diff > 0.1 else ''} \n"
|
||||
)
|
||||
|
||||
return response
|
||||
|
||||
if __name__ == "__main__":
|
||||
multiprocessing.freeze_support()
|
||||
load_into_mem()
|
||||
run_swingmusic()
|
||||
# TrackStore.export()
|
||||
# ArtistStore.export()
|
||||
|
||||
host = FLASKVARS.get_flask_host()
|
||||
port = FLASKVARS.get_flask_port()
|
||||
try:
|
||||
import bjoern
|
||||
|
||||
bjoern.run(app, host, port)
|
||||
except ImportError:
|
||||
import waitress
|
||||
|
||||
waitress.serve(
|
||||
app,
|
||||
@@ -247,5 +196,3 @@ if __name__ == "__main__":
|
||||
ipv6=True,
|
||||
ipv4=True,
|
||||
)
|
||||
# app.run(host=host, port=port, debug=False)
|
||||
# bjoern.run(app, host, port)
|
||||
|
||||
@@ -33,6 +33,7 @@ dependencies = [
|
||||
"rapidfuzz==3.11.0",
|
||||
"waitress>=3.0.2",
|
||||
"pendulum>=3.0.0",
|
||||
"bjoern>=3.2.2",
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
version = 1
|
||||
revision = 1
|
||||
requires-python = "==3.11.*"
|
||||
resolution-markers = [
|
||||
"platform_python_implementation != 'PyPy'",
|
||||
@@ -23,6 +24,12 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bjoern"
|
||||
version = "3.2.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d5/a0/fba55eb58a502dabc0915137ff44eaacaba58a60196fd94dc8cd4e9fe67d/bjoern-3.2.2.tar.gz", hash = "sha256:16e5a02a9a17a7f5f8bea0d7c58650e78ab80ead6fe3e390037573d4355baf31", size = 45716 }
|
||||
|
||||
[[package]]
|
||||
name = "blinker"
|
||||
version = "1.9.0"
|
||||
@@ -826,6 +833,7 @@ name = "swingmusic"
|
||||
version = "2.0.2"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "bjoern" },
|
||||
{ name = "colorgram-py" },
|
||||
{ name = "ffmpeg-python" },
|
||||
{ name = "flask" },
|
||||
@@ -861,6 +869,7 @@ dev = [
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "bjoern", specifier = ">=3.2.2" },
|
||||
{ name = "colorgram-py", specifier = ">=1.2.0" },
|
||||
{ name = "ffmpeg-python", specifier = ">=0.2.0" },
|
||||
{ name = "flask", specifier = ">=3.1.0" },
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
2.0.3
|
||||
Reference in New Issue
Block a user