Move backend files to root level for cleaner GitHub display

- Move all backend files from swingmusic/ to root level
- Backend files now display directly on GitHub repository page
- Keep client applications as submodules (swingmusic-android, swingmusic-desktop, swingmusic-webclient)
- Update README to reflect new structure (no cd swingmusic needed)
- Cleaner, more professional GitHub repository layout

Files moved to root:
- src/ (main source code)
- pyproject.toml, requirements.txt, run.py
- swingmusic.spec, uv.lock, version.txt
- services/

Result: GitHub shows backend files directly while maintaining organized structure
This commit is contained in:
Tomas Dvorak
2026-03-17 22:37:49 +01:00
parent 297315f5ba
commit 38f1981283
206 changed files with 0 additions and 3 deletions
+49
View File
@@ -0,0 +1,49 @@
from dataclasses import asdict
from swingmusic.models import Album
def album_serializer(album: Album, to_remove: set[str]) -> dict:
try:
album_dict = asdict(album)
except TypeError:
return {}
to_remove.update(key for key in album_dict.keys() if key.startswith("is_"))
for key in to_remove:
album_dict.pop(key, None)
# remove artist images
for artist in album_dict["albumartists"]:
artist.pop("image", None)
album_dict["type"] = "album"
return album_dict
def serialize_for_card(album: Album):
props_to_remove = {
"duration",
"count",
"artisthashes",
"albumartists_hashes",
"created_date",
"og_title",
"base_title",
"genres",
"playcount",
"trackcount",
"type",
"playduration",
"genrehashes",
"fav_userids",
"extra",
"id",
"lastplayed",
"weakhash",
}
return album_serializer(album, props_to_remove)
def serialize_for_card_many(albums: list[Album]):
return [serialize_for_card(a) for a in albums]
+42
View File
@@ -0,0 +1,42 @@
from dataclasses import asdict
from swingmusic.models.artist import Artist
def serialize_for_card(artist: Artist, include: set[str] = set()):
try:
artist_dict = asdict(artist)
except TypeError:
return {}
props_to_remove = {
"is_favorite",
"trackcount",
"duration",
"albumcount",
"playcount",
"playduration",
"playcount",
"lastplayed",
"id",
"genres",
"genrehashes",
"extra",
"created_date",
"date",
"fav_userids",
"_score",
}
if include:
props_to_remove = props_to_remove - include
for key in props_to_remove:
artist_dict.pop(key, None)
artist_dict["type"] = "artist"
return artist_dict
def serialize_for_cards(artists: list[Artist]):
return [serialize_for_card(a) for a in artists]
+13
View File
@@ -0,0 +1,13 @@
from dataclasses import asdict
from swingmusic.models.playlist import Playlist
def serialize_for_card(playlist: Playlist, to_remove=set()):
p_dict = asdict(playlist)
props = {"trackhashes"}.union(to_remove)
for key in props:
p_dict.pop(key, None)
return p_dict
+64
View File
@@ -0,0 +1,64 @@
from dataclasses import asdict
from swingmusic.models.track import Track
def serialize_track(track: Track, to_remove:set=set(), remove_disc:bool=True) -> dict:
"""
Convert `Track` to dict
:params track: Track to convert
:params to_remove: custom tags which should also be removed from Track.
:params remove_disc:
"""
album_dict = asdict(track)
album_keys = ( key for key in album_dict.keys() if key.startswith(("is_", "_")) )
# add all keys from album_dict starting with "is_" or "_"
props = {
"date",
"genre",
"last_mod",
"og_title",
"og_album",
"copyright",
"config",
"artist_hashes",
"created_date",
"fav_userids",
"playcount",
"genrehashes",
"id",
"lastplayed",
"playduration",
"genres",
*to_remove,
*album_keys,
}
if remove_disc:
props.add("disc")
props.add("track")
for key in props:
album_dict.pop(key, None)
# remove images
for key in ["artists", "albumartists"]:
for artist in album_dict[key]:
artist.pop("image", None)
# is_favorite @property is not included in `asdict`
album_dict["is_favorite"] = track.is_favorite
return album_dict
def serialize_tracks(tracks: list[Track], _remove: set = set(), remove_disc=True) -> list[dict]:
"""
wrapper for iterable type with Tracks.
convert Tracks to dict and return as list[dict]
"""
return [serialize_track(t, _remove, remove_disc) for t in tracks]