modularize src

+ merge main.py and manage.py
+ move start logic to swingmusic/__main__.py
+ add a run.py on the project root
This commit is contained in:
cwilvx
2025-05-25 20:35:54 +03:00
parent 76fc97e088
commit 86fabcd5e3
171 changed files with 658 additions and 627 deletions
+1 -1
View File
@@ -107,7 +107,7 @@ jobs:
# python -m poetry install
- name: Build server
run: |
python main.py --build
python run.py --build
env:
SWINGMUSIC_APP_VERSION: ${{ inputs.tag }}
- name: Rename Unix binary
+1 -1
View File
@@ -35,4 +35,4 @@ RUN pip install bjoern
ARG app_version
ENV SWINGMUSIC_APP_VERSION=$app_version
ENTRYPOINT ["python", "main.py", "--host", "0.0.0.0", "--config", "/config"]
ENTRYPOINT ["python", "run.py", "--host", "0.0.0.0", "--config", "/config"]
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 Mungai Njoroge
Copyright (c) 2025 Mungai Njoroge
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+52 -1
View File
@@ -122,12 +122,63 @@ services:
restart: unless-stopped
```
### Contributing
### Contributing and Development
Swing Music is looking for contributors. If you're interested, please join us at the [Swing Music Community](https://t.me/+9n61PFcgKhozZDE0) group on Telegram. For more information, take a look at https://github.com/swing-opensource/swingmusic/issues/186.
[**CONTRIBUTING GUIDELINES**](.github/contributing.md).
> [!TIP]
> This project runs on Python 3.11 or newer and uses [uv](https://docs.astral.sh/uv) to manage dependencies. Please [install uv](https://docs.astral.sh/uv/getting-started/installation/) before continuing for an easy setup.
To set up this project on your computer follow the following steps:
```sh
# 1. Fork the project
git clone https://github.com/swingmx/swingmusic.git
# or via SSH
git clone [email protected]:swingmx/swingmusic.git
```
```sh
# 2. Install dependencies
uv sync
```
```sh
# 3. Install wsgi server
# If you are on Windows, install waitress:
uv add waitress
# If you are on Unix, install bjoern:
uv add bjoern
```
> [!TIP]
> The `libev` package is needed on Linux and MacOS. You can install it on other system as shown:
>
> ```sh
> # Arch Linux
> pacman -S libev
>
> # Fedora, CentOS
> dnf install libev-devel
>
> # MacOS
> brew install libev
> ```
```sh
# 4. Run the program
uv run python run.py
```
### License
This software is provided to you with terms stated in the MIT License. Read the full text in the `LICENSE` file located at the root of this repository.
+1 -1
View File
@@ -44,7 +44,7 @@ cd ../swingmusic
# poetry install
# Swing gives error if this is not set. Set to version of repo you cloned.
export SWINGMUSIC_APP_VERSION="TAG"
python main.py --build
python run.py --build
# rename binary
mv dist/swingmusic dist/swingmusic_linux_arm64
View File
-19
View File
@@ -1,19 +0,0 @@
#!/bin/bash
# REVIEW Above: bash is way more compatible than other shells
# builds the latest version of the client and server
# REVIEW These are not useful if you dont have the source code
#cd ../swingmusic-client
#yarn build --outDir ../swingmusic/client
#../swingmusic
# REVIEW Cleaning up
rm -rf build dist
# REVIEW Install poetry & requirements
poetry || pip install poetry
poetry install --no-root
# Build the app
poetry run python manage.py --build
-16
View File
@@ -1,16 +0,0 @@
#!/bin/bash
# REVIEW Above: bash is way more compatible than other shells
# builds the latest version of the client and server
# NOTE Changes directory to the webclient directory and builds it
cd ../swingmusic-client || exit # REVIEW Failsafe exit
yarn build --outDir ../swingmusic/client
cd ../swingmusic || exit # REVIEW Failsafe exit
# REVIEW Optional cleaning up
# rm -rf build dist
# REVIEW Install poetry & requirements
# Build the app
poetry run python manage.py --build
-80
View File
@@ -1,80 +0,0 @@
import os
import sys
import click
import pathlib
import multiprocessing
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 create_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):
# INFO: Set the config dir as an environment variable
os.environ["SWINGMUSIC_XDG_CONFIG_DIR"] = str(
pathlib.Path(kwargs["config"]).resolve()
)
create_app(kwargs["host"], kwargs["port"], kwargs["config"])
if __name__ == "__main__":
multiprocessing.freeze_support()
multiprocessing.set_start_method("spawn")
run()
+1 -2
View File
@@ -1,6 +1,6 @@
[project]
name = "swingmusic"
version = "2.0.2"
version = "2.0.6"
description = "Swing Music"
readme = "README.md"
requires-python = ">=3.11, <3.12"
@@ -31,7 +31,6 @@ dependencies = [
"pillow>=11.1.0",
"flask-openapi3==3.0.2",
"rapidfuzz==3.11.0",
"waitress>=3.0.2",
"pendulum>=3.0.0",
"bjoern>=3.2.2",
]
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
poetry run python manage.py
+9
View File
@@ -0,0 +1,9 @@
# Launcher script
import multiprocessing
import swingmusic.__main__ as app
if __name__ == "__main__":
multiprocessing.freeze_support()
multiprocessing.set_start_method("spawn")
app.run()
+114 -16
View File
@@ -1,12 +1,12 @@
"""
This file is used to run the application.
"""
import os
import sys
import click
import pathlib
import logging
import mimetypes
import setproctitle
from pathlib import Path
import multiprocessing
from flask_jwt_extended import (
create_access_token,
@@ -18,19 +18,58 @@ 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.utils.threading import background
from app.setup import load_into_mem, run_setup
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
from swingmusic import settings
from swingmusic.api import create_api
from swingmusic.crons import start_cron_jobs
from swingmusic.utils.threading import background
from swingmusic.setup import load_into_mem, run_setup
from swingmusic.plugins.register import register_plugins
from swingmusic.utils.xdg_utils import get_xdg_config_dir
from swingmusic.start_info_logger import log_startup_info
from swingmusic.utils.filesystem import get_home_res_path
from swingmusic.utils.paths import getClientFilesExtensions
from swingmusic.arg_handler import handle_build, handle_password_reset
def print_version(*args, **kwargs):
"""
Prints the version of the application.
"""
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)
def create_app(host: str, port: int, config: Path):
# settings.Paths.set_config_dir(config)
def start_swingmusic(host: str, port: int):
"""
Creates and starts the Flask application server for Swing Music.
This function sets up the Flask application with all necessary
configurations, including static file handling, authentication middleware, and
server setup, then runs it. It also sets up background tasks and cron jobs.
Args:
host (str): The host address to bind the server to (e.g., 'localhost' or '0.0.0.0')
port (int): The port number to run the server on
Note:
The application uses either bjoern or waitress as the WSGI server,
depending on availability. It also includes JWT authentication,
static file serving with gzip compression support, and automatic
token refresh functionality.
"""
# Example: Setting up dirs, database, and loading stuff into memory.
# TIP: Be careful with the order of the setup functions.
# Load mimetypes for the web client's static files
# Loading mimetypes should happen automatically but
@@ -196,3 +235,62 @@ def create_app(host: str, port: int, config: Path):
ipv6=True,
ipv4=True,
)
@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=print_version,
help="Show the version and exit",
is_eager=True,
)
def run(*args, **kwargs):
"""
Swing Music entry point. All commandline arguments are handled
here by the click decorators and configuration.
"""
# INFO: Set the config dir as an environment variable
os.environ["SWINGMUSIC_XDG_CONFIG_DIR"] = str(
pathlib.Path(kwargs["config"]).resolve()
)
start_swingmusic(kwargs["host"], kwargs["port"])
if __name__ == "__main__":
multiprocessing.freeze_support()
multiprocessing.set_start_method("spawn")
run()
@@ -9,13 +9,13 @@ from flask_compress import Compress
from flask_openapi3 import Info
from flask_openapi3 import OpenAPI
from flask_jwt_extended import JWTManager
from app.config import UserConfig
from swingmusic.config import UserConfig
from app.db.userdata import UserTable
from app.settings import Info as AppInfo
from swingmusic.db.userdata import UserTable
from swingmusic.settings import Info as AppInfo
from .plugins import lyrics as lyrics_plugin
from .plugins import mixes as mixes_plugin
from app.api import (
from swingmusic.api import (
album,
artist,
collections,
+13 -13
View File
@@ -9,20 +9,20 @@ import random
from pydantic import BaseModel, Field
from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from app.api.apischemas import AlbumHashSchema, AlbumLimitSchema, ArtistHashSchema
from swingmusic.api.apischemas import AlbumHashSchema, AlbumLimitSchema, ArtistHashSchema
from app.config import UserConfig
from app.db.userdata import SimilarArtistTable
from app.models.album import Album
from app.settings import Defaults
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from app.store.tracks import TrackStore
from app.utils.hashing import create_hash
from app.lib.albumslib import sort_by_track_no
from app.serializers.album import serialize_for_card_many
from app.serializers.track import serialize_tracks
from app.utils.stats import get_track_group_stats
from swingmusic.config import UserConfig
from swingmusic.db.userdata import SimilarArtistTable
from swingmusic.models.album import Album
from swingmusic.settings import Defaults
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from swingmusic.store.tracks import TrackStore
from swingmusic.utils.hashing import create_hash
from swingmusic.lib.albumslib import sort_by_track_no
from swingmusic.serializers.album import serialize_for_card_many
from swingmusic.serializers.track import serialize_tracks
from swingmusic.utils.stats import get_track_group_stats
bp_tag = Tag(name="Album", description="Single album")
@@ -4,7 +4,7 @@ Reusable Pydantic basic schemas for the API
from pydantic import BaseModel, Field
from app.settings import Defaults
from swingmusic.settings import Defaults
class AlbumHashSchema(BaseModel):
+11 -11
View File
@@ -11,25 +11,25 @@ from typing import Any
from flask_openapi3 import APIBlueprint, Tag
from pydantic import Field
from app.api.apischemas import (
from swingmusic.api.apischemas import (
AlbumLimitSchema,
ArtistHashSchema,
ArtistLimitSchema,
TrackLimitSchema,
)
from app.config import UserConfig
from app.db.userdata import SimilarArtistTable
from app.lib.sortlib import sort_tracks
from swingmusic.config import UserConfig
from swingmusic.db.userdata import SimilarArtistTable
from swingmusic.lib.sortlib import sort_tracks
from app.serializers.album import serialize_for_card_many
from app.serializers.artist import serialize_for_cards, serialize_for_card
from app.serializers.track import serialize_track
from swingmusic.serializers.album import serialize_for_card_many
from swingmusic.serializers.artist import serialize_for_cards, serialize_for_card
from swingmusic.serializers.track import serialize_track
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from app.store.tracks import TrackStore
from app.utils.stats import get_track_group_stats
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from swingmusic.store.tracks import TrackStore
from swingmusic.utils.stats import get_track_group_stats
bp_tag = Tag(name="Artist", description="Single artist")
api = APIBlueprint("artist", __name__, url_prefix="/artist", abp_tags=[bp_tag])
+3 -3
View File
@@ -14,9 +14,9 @@ from pydantic import BaseModel, Field
from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from app.db.userdata import UserTable
from app.utils.auth import check_password, hash_password
from app.config import UserConfig
from swingmusic.db.userdata import UserTable
from swingmusic.utils.auth import check_password, hash_password
from swingmusic.config import UserConfig
bp_tag = Tag(name="Auth", description="Authentication stuff")
api = APIBlueprint("auth", __name__, url_prefix="/auth", abp_tags=[bp_tag])
@@ -7,13 +7,13 @@ import shutil
from time import time
from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from app.api.auth import admin_required
from swingmusic.api.auth import admin_required
from app.db.userdata import FavoritesTable, PlaylistTable, ScrobbleTable
from app.lib.index import index_everything
from app.settings import Paths
from swingmusic.db.userdata import FavoritesTable, PlaylistTable, ScrobbleTable
from swingmusic.lib.index import index_everything
from swingmusic.settings import Paths
from datetime import datetime
from app.utils.dates import timestamp_to_time_passed
from swingmusic.utils.dates import timestamp_to_time_passed
from pydantic import BaseModel, Field
from typing import Optional
@@ -8,9 +8,9 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field
from app.db.userdata import CollectionTable
from app.lib.pagelib import recover_page_items, remove_page_items, validate_page_items
from app.utils.auth import get_current_userid
from swingmusic.db.userdata import CollectionTable
from swingmusic.lib.pagelib import recover_page_items, remove_page_items, validate_page_items
from swingmusic.utils.auth import get_current_userid
bp_tag = Tag(name="Collections", description="Collections")
api = APIBlueprint(
@@ -1,7 +1,7 @@
from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from app.api.apischemas import AlbumHashSchema
from app.store.albums import AlbumStore as Store
from swingmusic.api.apischemas import AlbumHashSchema
from swingmusic.store.albums import AlbumStore as Store
bp_tag = Tag(name="Colors", description="Get item colors")
api = APIBlueprint("colors", __name__, url_prefix="/colors", abp_tags=[bp_tag])
@@ -4,23 +4,23 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field
from app.api.apischemas import GenericLimitSchema
from app.db.userdata import FavoritesTable
from app.lib.extras import get_extra_info
from app.models import FavType
from app.settings import Defaults
from swingmusic.api.apischemas import GenericLimitSchema
from swingmusic.db.userdata import FavoritesTable
from swingmusic.lib.extras import get_extra_info
from swingmusic.models import FavType
from swingmusic.settings import Defaults
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from app.store.tracks import TrackStore
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from swingmusic.store.tracks import TrackStore
from app.serializers.track import serialize_track, serialize_tracks
from app.serializers.artist import (
from swingmusic.serializers.track import serialize_track, serialize_tracks
from swingmusic.serializers.artist import (
serialize_for_card as serialize_artist,
serialize_for_cards,
)
from app.utils.dates import timestamp_to_time_passed
from app.serializers.album import serialize_for_card, serialize_for_card_many
from swingmusic.utils.dates import timestamp_to_time_passed
from swingmusic.serializers.album import serialize_for_card, serialize_for_card_many
bp_tag = Tag(name="Favorites", description="Your favorite items")
api = APIBlueprint("favorites", __name__, url_prefix="/favorites", abp_tags=[bp_tag])
@@ -12,14 +12,14 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from showinfm import show_in_file_manager
from app import settings
from app.config import UserConfig
from app.db.libdata import TrackTable
from app.db.userdata import FavoritesTable, PlaylistTable
from app.lib.folderslib import get_files_and_dirs, get_folders
from app.serializers.track import serialize_track, serialize_tracks
from app.store.tracks import TrackStore
from app.utils.wintools import is_windows, win_replace_slash
from swingmusic import settings
from swingmusic.config import UserConfig
from swingmusic.db.libdata import TrackTable
from swingmusic.db.userdata import FavoritesTable, PlaylistTable
from swingmusic.lib.folderslib import get_files_and_dirs, get_folders
from swingmusic.serializers.track import serialize_track, serialize_tracks
from swingmusic.store.tracks import TrackStore
from swingmusic.utils.wintools import is_windows, win_replace_slash
tag = Tag(name="Folders", description="Get folders and tracks in a directory")
api = APIBlueprint("folder", __name__, url_prefix="/folder", abp_tags=[tag])
@@ -3,14 +3,14 @@ from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field
from datetime import datetime
from app.api.apischemas import GenericLimitSchema
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from swingmusic.api.apischemas import GenericLimitSchema
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from app.serializers.album import serialize_for_card as serialize_album
from app.serializers.artist import serialize_for_card as serialize_artist
from app.utils import format_number
from app.utils.dates import (
from swingmusic.serializers.album import serialize_for_card as serialize_album
from swingmusic.serializers.artist import serialize_for_card as serialize_artist
from swingmusic.utils import format_number
from swingmusic.utils.dates import (
create_new_date,
date_string_to_time_passed,
seconds_to_time_string,
@@ -2,10 +2,10 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field
from app.api.apischemas import GenericLimitSchema
from app.lib.home.recentlyadded import get_recently_added_items
from app.lib.home.get_recently_played import get_recently_played
from app.store.homepage import HomepageStore
from swingmusic.api.apischemas import GenericLimitSchema
from swingmusic.lib.home.recentlyadded import get_recently_added_items
from swingmusic.lib.home.get_recently_played import get_recently_played
from swingmusic.store.homepage import HomepageStore
bp_tag = Tag(name="Home", description="Homepage items")
api = APIBlueprint("home", __name__, url_prefix="/nothome", abp_tags=[bp_tag])
@@ -5,10 +5,10 @@ from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field
from flask import send_from_directory
from app.settings import Defaults, Paths
from app.store.albums import AlbumStore
from app.store.tracks import TrackStore
from app.utils.threading import background
from swingmusic.settings import Defaults, Paths
from swingmusic.store.albums import AlbumStore
from swingmusic.store.tracks import TrackStore
from swingmusic.utils.threading import background
from PIL import Image
bp_tag = Tag(
@@ -2,8 +2,8 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from pydantic import Field
from app.api.apischemas import TrackHashSchema
from app.lib.lyrics import (
from swingmusic.api.apischemas import TrackHashSchema
from swingmusic.lib.lyrics import (
get_lyrics,
check_lyrics_file,
get_lyrics_from_duplicates,
@@ -14,21 +14,21 @@ from pydantic import BaseModel, Field, GetCoreSchemaHandler
from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint, FileStorage as _FileStorage
from app import models
from app.api.apischemas import GenericLimitSchema
from app.db.userdata import PlaylistTable
from app.lib import playlistlib
from app.lib.albumslib import sort_by_track_no
from app.lib.home.recentlyadded import get_recently_added_playlist
from app.lib.home.recentlyplayed import get_recently_played_playlist
from app.lib.sortlib import sort_tracks
from app.models.playlist import Playlist
from app.serializers.playlist import serialize_for_card
from app.serializers.track import serialize_tracks
from swingmusic import models
from swingmusic.api.apischemas import GenericLimitSchema
from swingmusic.db.userdata import PlaylistTable
from swingmusic.lib import playlistlib
from swingmusic.lib.albumslib import sort_by_track_no
from swingmusic.lib.home.recentlyadded import get_recently_added_playlist
from swingmusic.lib.home.recentlyplayed import get_recently_played_playlist
from swingmusic.lib.sortlib import sort_tracks
from swingmusic.models.playlist import Playlist
from swingmusic.serializers.playlist import serialize_for_card
from swingmusic.serializers.track import serialize_tracks
from app.store.tracks import TrackStore
from app.utils.dates import create_new_date, date_string_to_time_passed
from app.settings import Paths
from swingmusic.store.tracks import TrackStore
from swingmusic.utils.dates import create_new_date, date_string_to_time_passed
from swingmusic.settings import Paths
tag = Tag(name="Playlists", description="Get and manage playlists")
api = APIBlueprint("playlists", __name__, url_prefix="/playlists", abp_tags=[tag])
@@ -1,11 +1,11 @@
from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field
from app.api.auth import admin_required
from app.config import UserConfig
from app.db.userdata import PluginTable
from app.plugins.lastfm import LastFmPlugin
from app.utils.auth import get_current_userid
from swingmusic.api.auth import admin_required
from swingmusic.config import UserConfig
from swingmusic.db.userdata import PluginTable
from swingmusic.plugins.lastfm import LastFmPlugin
from swingmusic.utils.auth import get_current_userid
bp_tag = Tag(name="Plugins", description="Manage plugins")
api = APIBlueprint("plugins", __name__, url_prefix="/plugins", abp_tags=[bp_tag])
@@ -1,12 +1,12 @@
from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from pydantic import Field
from app.api.apischemas import TrackHashSchema
from app.lib.lyrics import format_synced_lyrics
from swingmusic.api.apischemas import TrackHashSchema
from swingmusic.lib.lyrics import format_synced_lyrics
from app.plugins.lyrics import Lyrics
from app.settings import Defaults
from app.utils.hashing import create_hash
from swingmusic.plugins.lyrics import Lyrics
from swingmusic.settings import Defaults
from swingmusic.utils.hashing import create_hash
bp_tag = Tag(name="Lyrics Plugin", description="Musixmatch lyrics plugin")
api = APIBlueprint(
@@ -3,10 +3,10 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field
from app.db.userdata import MixTable
from app.plugins.mixes import MixesPlugin
from app.store.homepage import HomepageStore
from app.store.tracks import TrackStore
from swingmusic.db.userdata import MixTable
from swingmusic.plugins.mixes import MixesPlugin
from swingmusic.store.homepage import HomepageStore
from swingmusic.store.tracks import TrackStore
bp_tag = Tag(name="Mixes Plugin", description="Mixes plugin hehe")
@@ -3,30 +3,30 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
import pendulum
from pydantic import Field, BaseModel
from app.api.apischemas import TrackHashSchema
from swingmusic.api.apischemas import TrackHashSchema
from typing import Literal
import locale
from app.db.userdata import FavoritesTable, ScrobbleTable
from app.lib.extras import get_extra_info
from app.lib.recipes.recents import RecentlyPlayed
from app.models.album import Album
from app.models.stats import StatItem
from app.models.track import Track
from app.plugins.lastfm import LastFmPlugin
from app.serializers.artist import serialize_for_card
from app.serializers.album import serialize_for_card as serialize_for_album_card
from app.serializers.track import serialize_track, serialize_tracks
from app.settings import Defaults
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from app.store.tracks import TrackStore
from app.utils.dates import (
from swingmusic.db.userdata import FavoritesTable, ScrobbleTable
from swingmusic.lib.extras import get_extra_info
from swingmusic.lib.recipes.recents import RecentlyPlayed
from swingmusic.models.album import Album
from swingmusic.models.stats import StatItem
from swingmusic.models.track import Track
from swingmusic.plugins.lastfm import LastFmPlugin
from swingmusic.serializers.artist import serialize_for_card
from swingmusic.serializers.album import serialize_for_card as serialize_for_album_card
from swingmusic.serializers.track import serialize_track, serialize_tracks
from swingmusic.settings import Defaults
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from swingmusic.store.tracks import TrackStore
from swingmusic.utils.dates import (
get_date_range,
get_duration_in_seconds,
seconds_to_time_string,
)
from app.utils.stats import (
from swingmusic.utils.stats import (
calculate_album_trend,
calculate_artist_trend,
calculate_new_albums,
@@ -8,12 +8,12 @@ from pydantic import Field
from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from app import models
from app.api.apischemas import GenericLimitSchema
from app.lib import searchlib
from app.serializers.artist import serialize_for_cards
from app.settings import Defaults
from app.store.tracks import TrackStore
from swingmusic import models
from swingmusic.api.apischemas import GenericLimitSchema
from swingmusic.lib import searchlib
from swingmusic.serializers.artist import serialize_for_cards
from swingmusic.settings import Defaults
from swingmusic.store.tracks import TrackStore
tag = Tag(name="Search", description="Search for tracks, albums and artists")
@@ -3,13 +3,13 @@ from typing import Any
from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint
from pydantic import BaseModel, Field
from app.api.auth import admin_required
from swingmusic.api.auth import admin_required
from app.db.userdata import PluginTable
from app.lib.index import index_everything
from app.settings import Info
from app.config import UserConfig
from app.utils.auth import get_current_userid
from swingmusic.db.userdata import PluginTable
from swingmusic.lib.index import index_everything
from swingmusic.settings import Info
from swingmusic.config import UserConfig
from swingmusic.utils.auth import get_current_userid
bp_tag = Tag(name="Settings", description="Customize stuff")
api = APIBlueprint("settings", __name__, url_prefix="/notsettings", abp_tags=[bp_tag])
@@ -12,12 +12,12 @@ from flask import send_file, request, Response, send_from_directory
from flask_openapi3 import APIBlueprint, Tag
from pydantic import BaseModel, Field
import werkzeug.wsgi
from app.api.apischemas import TrackHashSchema
from app.lib.trackslib import get_silence_paddings
from app.lib.transcoder import start_transcoding
from swingmusic.api.apischemas import TrackHashSchema
from swingmusic.lib.trackslib import get_silence_paddings
from swingmusic.lib.transcoder import start_transcoding
from app.store.tracks import TrackStore
from app.utils.files import guess_mime_type
from swingmusic.store.tracks import TrackStore
from swingmusic.utils.files import guess_mime_type
bp_tag = Tag(name="File", description="Audio files")
api = APIBlueprint("track", __name__, url_prefix="/file", abp_tags=[bp_tag])
@@ -8,13 +8,13 @@ from getpass import getpass
import click
import PyInstaller.__main__ as bundler
from app import settings
from app.db.userdata import UserTable
from app.logger import log
from app.setup.sqlite import setup_sqlite
from app.utils.auth import hash_password
from app.utils.paths import getFlaskOpenApiPath
from app.utils.wintools import is_windows
from swingmusic import settings
from swingmusic.db.userdata import UserTable
from swingmusic.logger import log
from swingmusic.setup.sqlite import setup_sqlite
from swingmusic.utils.auth import hash_password
from swingmusic.utils.paths import getFlaskOpenApiPath
from swingmusic.utils.wintools import is_windows
ALLARGS = settings.ALLARGS
ARGS = sys.argv[1:]
@@ -52,7 +52,7 @@ def handle_build(*args, **kwargs):
try:
# write the info to the config file
with open("./app/configs.py", "w", encoding="utf-8") as file:
with open("./swingmusic/configs.py", "w", encoding="utf-8") as file:
# copy the api keys to the config file
file.writelines(lines)
@@ -63,7 +63,7 @@ def handle_build(*args, **kwargs):
bundler.run(
[
"main.py",
"run.py",
"--onefile",
"--name",
"swingmusic",
@@ -73,13 +73,17 @@ def handle_build(*args, **kwargs):
f"--add-data=version.txt{_s}.",
f"--add-data={flask_openapi_path}/templates/static{_s}flask_openapi3/templates/static",
f"--hidden-import={server_module}",
"--collect-submodules=swingmusic",
"--icon=assets/logo-fill.light.ico",
"-y",
]
)
except Exception as e:
print(f"Error building the project: {e}")
sys.exit(0)
finally:
# revert and remove the api keys for dev mode
with open("./app/configs.py", "w", encoding="utf-8") as file:
with open("./swingmusic/configs.py", "w", encoding="utf-8") as file:
lines = [f'{key} = ""\n' for key in info_keys]
file.writelines(lines)
@@ -1,10 +1,10 @@
import time
import schedule
from app.crons.mixes import Mixes
from app.lib.recipes.recents import RecentlyAdded, RecentlyPlayed
from app.lib.recipes.topstreamed import TopArtists
from app.utils.threading import background
from swingmusic.crons.mixes import Mixes
from swingmusic.lib.recipes.recents import RecentlyAdded, RecentlyPlayed
from swingmusic.lib.recipes.topstreamed import TopArtists
from swingmusic.utils.threading import background
@background
@@ -1,6 +1,6 @@
from app.crons.cron import CronJob
from app.lib.recipes.artistmixes import ArtistMixes
from app.lib.recipes.because import BecauseYouListened
from swingmusic.crons.cron import CronJob
from swingmusic.lib.recipes.artistmixes import ArtistMixes
from swingmusic.lib.recipes.because import BecauseYouListened
class Mixes(CronJob):
@@ -8,7 +8,7 @@ from sqlalchemy import (
)
from sqlalchemy.orm import DeclarativeBase, MappedAsDataclass
from app.db.engine import DbEngine
from swingmusic.db.engine import DbEngine
class Base(MappedAsDataclass, DeclarativeBase):
+1 -1
View File
@@ -2,7 +2,7 @@ from contextlib import contextmanager
from sqlalchemy import Engine, create_engine, event
from sqlalchemy.orm import sessionmaker
from app.settings import DbPaths
from swingmusic.settings import DbPaths
@event.listens_for(Engine, "connect")
@@ -1,7 +1,7 @@
from app.config import UserConfig
from app.db import Base
from app.db.utils import track_to_dataclass, tracks_to_dataclasses
from app.db.engine import DbEngine
from swingmusic.config import UserConfig
from swingmusic.db import Base
from swingmusic.db.utils import track_to_dataclass, tracks_to_dataclasses
from swingmusic.db.engine import DbEngine
from sqlalchemy import JSON, Integer, String, delete, select
from sqlalchemy.orm import Mapped, mapped_column
@@ -1,10 +1,10 @@
from app.db import Base
from swingmusic.db import Base
from sqlalchemy import Integer, insert, select, update
from sqlalchemy.orm import Mapped, mapped_column
from app.db.engine import DbEngine
from swingmusic.db.engine import DbEngine
class MigrationTable(Base):
@@ -2,7 +2,7 @@
Reads and saves the latest database migrations version.
"""
from app.db.sqlite.utils import SQLiteManager
from swingmusic.db.sqlite.utils import SQLiteManager
class MigrationManager:
@@ -7,8 +7,8 @@ from sqlite3 import Connection, Cursor
import time
from typing import Optional
from app.models import Album, Playlist, Track
from app import settings
from swingmusic.models import Album, Playlist, Track
from swingmusic import settings
def tuple_to_track(track: tuple):
@@ -17,8 +17,8 @@ from sqlalchemy import (
from sqlalchemy.orm import Mapped, mapped_column, sessionmaker
from app.db.engine import DbEngine
from app.db.utils import (
from swingmusic.db.engine import DbEngine
from swingmusic.db.utils import (
favorite_to_dataclass,
favorites_to_dataclass,
playlist_to_dataclass,
@@ -28,9 +28,9 @@ from app.db.utils import (
user_to_dataclass,
)
from app.db import Base
from app.models.mix import Mix
from app.utils.auth import get_current_userid, hash_password
from swingmusic.db import Base
from swingmusic.models.mix import Mix
from swingmusic.utils.auth import get_current_userid, hash_password
class UserTable(Base):
+8 -8
View File
@@ -1,13 +1,13 @@
from typing import Any
from app.config import UserConfig
from app.models import Album as AlbumModel, Artist as ArtistModel, Track as TrackModel
from app.models.favorite import Favorite
from app.models.lastfm import SimilarArtist
from app.models.logger import TrackLog
from app.models.playlist import Playlist
from app.models.plugins import Plugin
from app.models.user import User
from swingmusic.config import UserConfig
from swingmusic.models import Album as AlbumModel, Artist as ArtistModel, Track as TrackModel
from swingmusic.models.favorite import Favorite
from swingmusic.models.lastfm import SimilarArtist
from swingmusic.models.logger import TrackLog
from swingmusic.models.playlist import Playlist
from swingmusic.models.plugins import Plugin
from swingmusic.models.user import User
def row_to_dict(row: Any):
@@ -3,7 +3,7 @@ Contains methods relating to albums.
"""
from app.models.track import Track
from swingmusic.models.track import Track
def remove_duplicate_on_merge_versions(tracks: list[Track]):
@@ -12,16 +12,16 @@ from PIL import Image, PngImagePlugin, UnidentifiedImageError
from requests.exceptions import ConnectionError as RequestConnectionError
from requests.exceptions import ReadTimeout
from app import settings
from app.models.artist import Artist
from app.store.artists import ArtistStore
from swingmusic import settings
from swingmusic.models.artist import Artist
from swingmusic.store.artists import ArtistStore
# from app.db.libdata import ArtistTable
# from swingmusic.db.libdata import ArtistTable
# from app.store import artists as artist_store
# from app.store.tracks import TrackStore
from app.utils.hashing import create_hash
from app.utils.progressbar import tqdm
# from swingmusic.store import artists as artist_store
# from swingmusic.store.tracks import TrackStore
from swingmusic.utils.hashing import create_hash
from swingmusic.utils.progressbar import tqdm
LARGE_ENOUGH_NUMBER = 100
@@ -6,13 +6,13 @@ from pathlib import Path
import colorgram
from app import settings
from swingmusic import settings
from app.db.userdata import LibDataTable
from app.logger import log
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from app.utils.progressbar import tqdm
from swingmusic.db.userdata import LibDataTable
from swingmusic.logger import log
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from swingmusic.utils.progressbar import tqdm
def get_image_colors(image: str, count=1) -> list[str]:
"""Extracts n number of the most dominant colors from an image."""
@@ -1,7 +1,7 @@
from typing import Any
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from app.store.tracks import TrackStore
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from swingmusic.store.tracks import TrackStore
def get_extra_info(hash: str, type: str):
@@ -1,13 +1,13 @@
import os
from pathlib import Path
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.utils.filesystem import SUPPORTED_FILES
from app.store.folder import FolderStore
from app.utils.wintools import win_replace_slash
from swingmusic.lib.sortlib import sort_folders, sort_tracks
from swingmusic.logger import log
from swingmusic.models import Folder
from swingmusic.serializers.track import serialize_tracks
from swingmusic.utils.filesystem import SUPPORTED_FILES
from swingmusic.store.folder import FolderStore
from swingmusic.utils.wintools import win_replace_slash
def create_folder(path: str, trackcount=0) -> Folder:
@@ -1,12 +1,12 @@
from app.db.userdata import MixTable
from app.plugins.mixes import MixesPlugin
from swingmusic.db.userdata import MixTable
from swingmusic.plugins.mixes import MixesPlugin
def find_mix(mixid: str, sourcehash: str):
"""
Find a mix in the homepage store or the db.
"""
from app.store.homepage import HomepageStore
from swingmusic.store.homepage import HomepageStore
mixtype = "custom_mixes" if mixid[0] == "t" else "artist_mixes"
@@ -1,12 +1,12 @@
import os
from app.db.userdata import PlaylistTable
from app.lib.home import find_mix
from app.lib.home.recentlyadded import get_recently_added_playlist
from app.lib.home.recentlyplayed import get_recently_played_playlist
from app.models.logger import TrackLog
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from app.store.tracks import TrackStore
from swingmusic.db.userdata import PlaylistTable
from swingmusic.lib.home import find_mix
from swingmusic.lib.home.recentlyadded import get_recently_added_playlist
from swingmusic.lib.home.recentlyplayed import get_recently_played_playlist
from swingmusic.models.logger import TrackLog
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from swingmusic.store.tracks import TrackStore
def create_items(entries: list[TrackLog], limit: int):
@@ -1,6 +1,6 @@
from app.db.userdata import ScrobbleTable
from app.lib.home.create_items import create_items
from app.models.logger import TrackLog
from swingmusic.db.userdata import ScrobbleTable
from swingmusic.lib.home.create_items import create_items
from swingmusic.models.logger import TrackLog
def get_recently_played(
@@ -1,17 +1,17 @@
from datetime import datetime
from app.lib.playlistlib import get_first_4_images
from app.models.playlist import Playlist
from app.models.track import Track
from swingmusic.lib.playlistlib import get_first_4_images
from swingmusic.models.playlist import Playlist
from swingmusic.models.track import Track
from app.store.tracks import TrackStore
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from swingmusic.store.tracks import TrackStore
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from itertools import groupby
from app.utils import flatten
from app.utils.dates import (
from swingmusic.utils import flatten
from swingmusic.utils.dates import (
create_new_date,
date_string_to_time_passed,
)
@@ -1,13 +1,13 @@
from datetime import datetime
from app.models.playlist import Playlist
from app.lib.playlistlib import get_first_4_images
from app.utils.dates import (
from swingmusic.models.playlist import Playlist
from swingmusic.lib.playlistlib import get_first_4_images
from swingmusic.utils.dates import (
create_new_date,
date_string_to_time_passed,
)
from app.store.tracks import TrackStore
from swingmusic.store.tracks import TrackStore
def get_recently_played_playlist(limit: int = 100):
@@ -1,17 +1,17 @@
from app.db.userdata import FavoritesTable, MixTable, PlaylistTable
from app.lib.home import find_mix
from app.lib.home.recentlyadded import get_recently_added_playlist
from app.lib.home.recentlyplayed import get_recently_played_playlist
from app.lib.playlistlib import get_first_4_images
from app.serializers.album import album_serializer
from app.serializers.artist import serialize_for_card
from app.serializers.playlist import serialize_for_card as serialize_playlist
from app.serializers.track import serialize_track
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from app.store.folder import FolderStore
from app.store.tracks import TrackStore
from app.utils.dates import timestamp_to_time_passed
from swingmusic.db.userdata import FavoritesTable, MixTable, PlaylistTable
from swingmusic.lib.home import find_mix
from swingmusic.lib.home.recentlyadded import get_recently_added_playlist
from swingmusic.lib.home.recentlyplayed import get_recently_played_playlist
from swingmusic.lib.playlistlib import get_first_4_images
from swingmusic.serializers.album import album_serializer
from swingmusic.serializers.artist import serialize_for_card
from swingmusic.serializers.playlist import serialize_for_card as serialize_playlist
from swingmusic.serializers.track import serialize_track
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from swingmusic.store.folder import FolderStore
from swingmusic.store.tracks import TrackStore
from swingmusic.utils.dates import timestamp_to_time_passed
def recover_items(items: list[dict]):
+9 -9
View File
@@ -1,19 +1,19 @@
import gc
from time import time
from app.lib.mapstuff import (
from swingmusic.lib.mapstuff import (
map_album_colors,
map_artist_colors,
map_favorites,
map_scrobble_data,
)
from app.lib.populate import CordinateMedia
from app.lib.recipes.recents import RecentlyAdded
from app.lib.tagger import IndexTracks
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from app.store.folder import FolderStore
from app.store.tracks import TrackStore
from app.utils.threading import background
from swingmusic.lib.populate import CordinateMedia
from swingmusic.lib.recipes.recents import RecentlyAdded
from swingmusic.lib.tagger import IndexTracks
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from swingmusic.store.folder import FolderStore
from swingmusic.store.tracks import TrackStore
from swingmusic.utils.threading import background
class IndexEverything:
@@ -1,7 +1,7 @@
from pathlib import Path
from typing import Iterable
from app.store.tracks import TrackStore
from swingmusic.store.tracks import TrackStore
def split_line(line: str):
@@ -1,7 +1,7 @@
from app.db.userdata import LibDataTable, FavoritesTable, ScrobbleTable
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from app.store.tracks import TrackStore
from swingmusic.db.userdata import LibDataTable, FavoritesTable, ScrobbleTable
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from swingmusic.store.tracks import TrackStore
from typing import Any
@@ -1,10 +1,10 @@
import json
from typing import Any
from app.serializers.album import serialize_for_card
from app.serializers.artist import serialize_for_card as serialize_artist
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from app.utils.hashing import create_hash
from swingmusic.serializers.album import serialize_for_card
from swingmusic.serializers.artist import serialize_for_card as serialize_artist
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from swingmusic.utils.hashing import create_hash
def validate_page_items(items: list[dict[str, str]], existing: list[dict[str, str]]):
@@ -9,10 +9,10 @@ from typing import Any
from PIL import Image, ImageSequence
from app import settings
from app.models.track import Track
from app.store.albums import AlbumStore
from app.store.tracks import TrackStore
from swingmusic import settings
from swingmusic.models.track import Track
from swingmusic.store.albums import AlbumStore
from swingmusic.store.tracks import TrackStore
def create_thumbnail(image: Any, img_path: str) -> str:
@@ -6,20 +6,20 @@ import platform
from requests import ConnectionError as RequestConnectionError
from requests import ReadTimeout
from app import settings
from app.lib.artistlib import CheckArtistImages
from app.lib.colorlib import ProcessAlbumColors, ProcessArtistColors
from app.lib.taglib import extract_thumb
from app.logger import log
from app.models import Album, Artist
from app.models.lastfm import SimilarArtist
from app.requests.artists import fetch_similar_artists
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from app.utils.network import has_connection
from app.utils.progressbar import tqdm
from swingmusic import settings
from swingmusic.lib.artistlib import CheckArtistImages
from swingmusic.lib.colorlib import ProcessAlbumColors, ProcessArtistColors
from swingmusic.lib.taglib import extract_thumb
from swingmusic.logger import log
from swingmusic.models import Album, Artist
from swingmusic.models.lastfm import SimilarArtist
from swingmusic.requests.artists import fetch_similar_artists
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from swingmusic.utils.network import has_connection
from swingmusic.utils.progressbar import tqdm
from app.db.userdata import SimilarArtistTable
from swingmusic.db.userdata import SimilarArtistTable
class CordinateMedia:
@@ -1,7 +1,7 @@
from app.db.userdata import UserTable
from app.lib.recipes import HomepageRoutine
from app.plugins.mixes import MixesPlugin
from app.store.homepage import HomepageStore
from swingmusic.db.userdata import UserTable
from swingmusic.lib.recipes import HomepageRoutine
from swingmusic.plugins.mixes import MixesPlugin
from swingmusic.store.homepage import HomepageStore
class ArtistMixes(HomepageRoutine):
@@ -1,10 +1,10 @@
from pprint import pprint
from app.db.userdata import UserTable
from app.lib.recipes import HomepageRoutine
from app.lib.recipes.artistmixes import ArtistMixes
from app.models.mix import Mix
from app.plugins.mixes import MixesPlugin
from app.store.homepage import HomepageStore
from swingmusic.db.userdata import UserTable
from swingmusic.lib.recipes import HomepageRoutine
from swingmusic.lib.recipes.artistmixes import ArtistMixes
from swingmusic.models.mix import Mix
from swingmusic.plugins.mixes import MixesPlugin
from swingmusic.store.homepage import HomepageStore
class BecauseYouListened(HomepageRoutine):
@@ -1,9 +1,9 @@
import pprint
from app.db.userdata import ScrobbleTable, UserTable
from app.lib.home.recentlyadded import get_recently_added_items
from app.lib.home.get_recently_played import get_recently_played
from app.lib.recipes import HomepageRoutine
from app.store.homepage import HomepageStore
from swingmusic.db.userdata import ScrobbleTable, UserTable
from swingmusic.lib.home.recentlyadded import get_recently_added_items
from swingmusic.lib.home.get_recently_played import get_recently_played
from swingmusic.lib.recipes import HomepageRoutine
from swingmusic.store.homepage import HomepageStore
class RecentlyPlayed(HomepageRoutine):
@@ -1,12 +1,12 @@
from gettext import ngettext
import pendulum
from app.crons.cron import CronJob
from app.db.userdata import UserTable
from app.lib.recipes import HomepageRoutine
from app.store.homepage import HomepageStore
from app.utils.dates import get_date_range, seconds_to_time_string
from app.utils.stats import get_artists_in_period
from swingmusic.crons.cron import CronJob
from swingmusic.db.userdata import UserTable
from swingmusic.lib.recipes import HomepageRoutine
from swingmusic.store.homepage import HomepageStore
from swingmusic.utils.dates import get_date_range, seconds_to_time_string
from swingmusic.utils.stats import get_artists_in_period
class TopArtists(CronJob, HomepageRoutine):
@@ -7,27 +7,27 @@ from typing import Any, Generator, List, TypeVar
from rapidfuzz import process, utils, fuzz
from unidecode import unidecode
from app import models
from app.config import UserConfig
from swingmusic import models
from swingmusic.config import UserConfig
# from app.db.libdata import AlbumTable, ArtistTable, TrackTable
# from swingmusic.db.libdata import AlbumTable, ArtistTable, TrackTable
# from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
from app.models.album import Album
from app.models.artist import Artist
from app.models.enums import FavType
from app.models.playlist import Playlist
from app.models.track import Track
from app.serializers.album import serialize_for_card as serialize_album
from app.serializers.album import serialize_for_card_many as serialize_albums
from app.serializers.artist import serialize_for_card, serialize_for_cards
from app.serializers.track import serialize_track, serialize_tracks
# from swingmusic.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
from swingmusic.models.album import Album
from swingmusic.models.artist import Artist
from swingmusic.models.enums import FavType
from swingmusic.models.playlist import Playlist
from swingmusic.models.track import Track
from swingmusic.serializers.album import serialize_for_card as serialize_album
from swingmusic.serializers.album import serialize_for_card_many as serialize_albums
from swingmusic.serializers.artist import serialize_for_card, serialize_for_cards
from swingmusic.serializers.track import serialize_track, serialize_tracks
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from app.store.tracks import TrackStore
from swingmusic.store.albums import AlbumStore
from swingmusic.store.artists import ArtistStore
from swingmusic.store.tracks import TrackStore
from app.utils.remove_duplicates import remove_duplicates
from swingmusic.utils.remove_duplicates import remove_duplicates
# ratio = fuzz.ratio
# wratio = fuzz.WRatio

Some files were not shown because too many files have changed in this diff Show More