traxsource: GENRES + TraxsourceTrack + list_genres
This commit is contained in:
1 parent
7feda99720
commit
a95912f78c
2 files changed
+108
No files matched your search
@@ -0,0 +1,61 @@
|
|||||||
|
"""Fetch Top 100 Traxsource per genere.
|
||||||
|
|
||||||
|
Approccio: session curl_cffi (bypass CF via cookie) + BeautifulSoup HTML scraping.
|
||||||
|
Spec: docs/superpowers/specs/2026-08-01-traxsource-charts-design.md.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
|
# Generi musicali Traxsource (slug -> (id, display_name)).
|
||||||
|
# Aggiornato via scripts/refresh_traxsource_genres.py. Esclusi "sounds/samples/loops",
|
||||||
|
# "acapella", "beats", "efx-dj-tools", "stems" (non generi ma tipi di prodotto).
|
||||||
|
GENRES: dict = {
|
||||||
|
"afro-house": (27, "Afro House"),
|
||||||
|
"afro-latin-brazilian": (23, "Afro / Latin / Brazilian"),
|
||||||
|
"broken-beat-nu-jazz": (2, "Broken Beat / Nu Jazz"),
|
||||||
|
"classic-house": (12, "Classic House"),
|
||||||
|
"deep-house": (13, "Deep House"),
|
||||||
|
"drum-and-bass": (31, "Drum & Bass"),
|
||||||
|
"electro-house": (11, "Electro House"),
|
||||||
|
"electronica": (5, "Electronica"),
|
||||||
|
"garage": (29, "Garage"),
|
||||||
|
"house": (4, "House"),
|
||||||
|
"jackin-house": (15, "Jackin House"),
|
||||||
|
"leftfield": (14, "Leftfield"),
|
||||||
|
"lounge-chill-out": (1, "Lounge / Chill Out"),
|
||||||
|
"melodic-progressive-house": (19, "Melodic / Progressive House"),
|
||||||
|
"minimal-deep-tech": (16, "Minimal / Deep Tech"),
|
||||||
|
"nu-disco-indie-dance": (17, "Nu Disco / Indie Dance"),
|
||||||
|
"pop-dance": (32, "Pop Dance"),
|
||||||
|
"r-and-b-hip-hop": (6, "R&B / Hip Hop"),
|
||||||
|
"soul-funk-disco": (3, "Soul / Funk / Disco"),
|
||||||
|
"soulful-house": (24, "Soulful House"),
|
||||||
|
"tech-house": (18, "Tech House"),
|
||||||
|
"techno": (20, "Techno"),
|
||||||
|
"world": (30, "World"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class TraxsourceTrack:
|
||||||
|
position: int
|
||||||
|
title: str
|
||||||
|
mix: str
|
||||||
|
artists: str
|
||||||
|
label: str
|
||||||
|
traxsource_id: int
|
||||||
|
slug: str
|
||||||
|
image_url: str = ""
|
||||||
|
cover_url_large: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
def list_genres() -> list:
|
||||||
|
result = [
|
||||||
|
{"slug": slug, "id": gid, "name": name}
|
||||||
|
for slug, (gid, name) in GENRES.items()
|
||||||
|
]
|
||||||
|
result.sort(key=lambda g: g["name"].casefold())
|
||||||
|
return result
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
"""Test per core.traxsource."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from core import traxsource
|
||||||
|
|
||||||
|
|
||||||
|
class TestListGenres:
|
||||||
|
def test_returns_list_of_dicts(self):
|
||||||
|
result = traxsource.list_genres()
|
||||||
|
assert isinstance(result, list)
|
||||||
|
assert len(result) >= 10
|
||||||
|
for g in result:
|
||||||
|
assert set(g.keys()) == {"slug", "id", "name"}
|
||||||
|
assert isinstance(g["slug"], str) and g["slug"]
|
||||||
|
assert isinstance(g["id"], int) and g["id"] > 0
|
||||||
|
assert isinstance(g["name"], str) and g["name"]
|
||||||
|
|
||||||
|
def test_sorted_alphabetically_by_name(self):
|
||||||
|
result = traxsource.list_genres()
|
||||||
|
names = [g["name"] for g in result]
|
||||||
|
assert names == sorted(names, key=str.casefold)
|
||||||
|
|
||||||
|
def test_tech_house_present(self):
|
||||||
|
result = traxsource.list_genres()
|
||||||
|
slugs = [g["slug"] for g in result]
|
||||||
|
assert "tech-house" in slugs
|
||||||
|
|
||||||
|
|
||||||
|
class TestTraxsourceTrack:
|
||||||
|
def test_frozen(self):
|
||||||
|
t = traxsource.TraxsourceTrack(
|
||||||
|
position=1, title="X", mix="Y", artists="A", label="L",
|
||||||
|
traxsource_id=1, slug="x",
|
||||||
|
)
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
t.title = "Z"
|
||||||
|
|
||||||
|
def test_defaults(self):
|
||||||
|
t = traxsource.TraxsourceTrack(
|
||||||
|
position=1, title="X", mix="", artists="A", label="",
|
||||||
|
traxsource_id=1, slug="x",
|
||||||
|
)
|
||||||
|
assert t.image_url == ""
|
||||||
|
assert t.cover_url_large == ""
|
||||||
Reference in new issue
Block a user