migrate to black 24

This commit is contained in:
Your Name 2024-06-02 14:50:07 -04:00 committed by Henri Dickson
parent a71283e6d5
commit 55b1f1b365
29 changed files with 176 additions and 76 deletions

View file

@ -1,12 +1,15 @@
exclude: ^test_data/ exclude: ^test_data/
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0 rev: v4.6.0
hooks: hooks:
- id: check-yaml - id: check-yaml
- id: check-json - id: check-json
- id: check-xml - id: check-xml
- id: check-toml - id: check-toml
- id: check-ast
- id: check-docstring-first
- id: check-executables-have-shebangs
- id: check-symlinks - id: check-symlinks
- id: check-added-large-files - id: check-added-large-files
args: [--maxkb=1024] args: [--maxkb=1024]
@ -21,7 +24,7 @@ repos:
- id: mixed-line-ending - id: mixed-line-ending
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.5 rev: v0.4.7
hooks: hooks:
- id: ruff - id: ruff
# - id: ruff-format # - id: ruff-format
@ -33,7 +36,7 @@ repos:
args: ["--profile=black"] args: ["--profile=black"]
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 22.12.0 rev: 24.4.2
hooks: hooks:
- id: black - id: black

View file

@ -13,6 +13,7 @@ Including another URLconf
1. Import the include() function: from django.urls import include, path 1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
""" """
from django.conf import settings from django.conf import settings
from django.contrib import admin from django.contrib import admin
from django.urls import include, path from django.urls import include, path

View file

@ -279,7 +279,8 @@ class BooksTWTestCase(TestCase):
self.assertEqual(site.resource.id_value, "0010947886") self.assertEqual(site.resource.id_value, "0010947886")
self.assertEqual(site.resource.item.isbn, "9786263152236") self.assertEqual(site.resource.item.isbn, "9786263152236")
self.assertEqual( self.assertEqual(
site.resource.item.title, "阿拉伯人三千年:從民族、部落、語言、文化、宗教到帝國,綜覽阿拉伯世界的崛起、衰落與再興" site.resource.item.title,
"阿拉伯人三千年:從民族、部落、語言、文化、宗教到帝國,綜覽阿拉伯世界的崛起、衰落與再興",
) )

View file

@ -6,6 +6,7 @@ a Site should map to a unique set of url patterns.
a Site may scrape a url and store result in ResourceContent a Site may scrape a url and store result in ResourceContent
ResourceContent persists as an ExternalResource which may link to an Item ResourceContent persists as an ExternalResource which may link to an Item
""" """
import json import json
import re import re
from dataclasses import dataclass, field from dataclasses import dataclass, field

View file

@ -71,7 +71,8 @@ class SteamTestCase(TestCase):
self.assertEqual(site.ready, True) self.assertEqual(site.ready, True)
self.assertEqual(site.resource.metadata["title"], "Portal 2") self.assertEqual(site.resource.metadata["title"], "Portal 2")
self.assertEqual( self.assertEqual(
site.resource.metadata["brief"], "“终身测试计划”现已升级,您可以为您自己或您的好友设计合作谜题!" site.resource.metadata["brief"],
"“终身测试计划”现已升级,您可以为您自己或您的好友设计合作谜题!",
) )
self.assertIsInstance(site.resource.item, Game) self.assertIsInstance(site.resource.item, Game)
self.assertEqual(site.resource.item.steam, "620") self.assertEqual(site.resource.item.steam, "620")
@ -102,7 +103,9 @@ class DoubanGameTestCase(TestCase):
self.assertEqual(site.resource.metadata["title"], "传送门2 Portal 2") self.assertEqual(site.resource.metadata["title"], "传送门2 Portal 2")
self.assertIsInstance(site.resource.item, Game) self.assertIsInstance(site.resource.item, Game)
self.assertEqual(site.resource.item.douban_game, "10734307") self.assertEqual(site.resource.item.douban_game, "10734307")
self.assertEqual(site.resource.item.genre, ["第一人称射击", "益智", "射击", "动作"]) self.assertEqual(
site.resource.item.genre, ["第一人称射击", "益智", "射击", "动作"]
)
self.assertEqual(site.resource.item.other_title, []) self.assertEqual(site.resource.item.other_title, [])

View file

@ -118,14 +118,21 @@ class Migration(migrations.Migration):
"title", "title",
models.CharField(default="", max_length=1000, verbose_name="标题"), models.CharField(default="", max_length=1000, verbose_name="标题"),
), ),
("brief", models.TextField(blank=True, default="", verbose_name="简介")), (
"brief",
models.TextField(blank=True, default="", verbose_name="简介"),
),
( (
"primary_lookup_id_type", "primary_lookup_id_type",
models.CharField(max_length=50, null=True, verbose_name="主要标识类型"), models.CharField(
max_length=50, null=True, verbose_name="主要标识类型"
),
), ),
( (
"primary_lookup_id_value", "primary_lookup_id_value",
models.CharField(max_length=1000, null=True, verbose_name="主要标识数值"), models.CharField(
max_length=1000, null=True, verbose_name="主要标识数值"
),
), ),
( (
"metadata", "metadata",
@ -184,14 +191,21 @@ class Migration(migrations.Migration):
"title", "title",
models.CharField(default="", max_length=1000, verbose_name="标题"), models.CharField(default="", max_length=1000, verbose_name="标题"),
), ),
("brief", models.TextField(blank=True, default="", verbose_name="简介")), (
"brief",
models.TextField(blank=True, default="", verbose_name="简介"),
),
( (
"primary_lookup_id_type", "primary_lookup_id_type",
models.CharField(max_length=50, null=True, verbose_name="主要标识类型"), models.CharField(
max_length=50, null=True, verbose_name="主要标识类型"
),
), ),
( (
"primary_lookup_id_value", "primary_lookup_id_value",
models.CharField(max_length=1000, null=True, verbose_name="主要标识数值"), models.CharField(
max_length=1000, null=True, verbose_name="主要标识数值"
),
), ),
( (
"metadata", "metadata",
@ -505,12 +519,17 @@ class Migration(migrations.Migration):
), ),
( (
"id_value", "id_value",
models.CharField(blank=True, max_length=1000, verbose_name="源网站ID"), models.CharField(
blank=True, max_length=1000, verbose_name="源网站ID"
),
), ),
( (
"raw_url", "raw_url",
models.CharField( models.CharField(
blank=True, max_length=1000, unique=True, verbose_name="源网站ID" blank=True,
max_length=1000,
unique=True,
verbose_name="源网站ID",
), ),
), ),
( (

View file

@ -1,8 +1,9 @@
# Generated by Django 4.2.13 on 2024-06-02 16:17 # Generated by Django 4.2.13 on 2024-06-02 16:17
import catalog.common.utils
from django.db import migrations, models from django.db import migrations, models
import catalog.common.utils
class Migration(migrations.Migration): class Migration(migrations.Migration):

View file

@ -396,9 +396,7 @@ class PerformanceProduction(Item):
return ( return (
self.cover.url # type:ignore self.cover.url # type:ignore
if self.cover and self.cover != DEFAULT_ITEM_COVER if self.cover and self.cover != DEFAULT_ITEM_COVER
else self.show.cover_image_url else self.show.cover_image_url if self.show else None
if self.show
else None
) )
def update_linked_items_from_external_resource(self, resource: ExternalResource): def update_linked_items_from_external_resource(self, resource: ExternalResource):

View file

@ -30,7 +30,9 @@ class DoubanDramaTestCase(TestCase):
resource = site.get_resource_ready() resource = site.get_resource_ready()
item = site.get_item() item = site.get_item()
self.assertEqual(item.title, "不眠之人·拿破仑") self.assertEqual(item.title, "不眠之人·拿破仑")
self.assertEqual(item.other_title, ["眠らない男・ナポレオン ―愛と栄光の涯(はて)に―"]) self.assertEqual(
item.other_title, ["眠らない男・ナポレオン ―愛と栄光の涯(はて)に―"]
)
self.assertEqual(item.genre, ["音乐剧"]) self.assertEqual(item.genre, ["音乐剧"])
self.assertEqual(item.troupe, ["宝塚歌剧团"]) self.assertEqual(item.troupe, ["宝塚歌剧团"])
self.assertEqual(item.composer, ["ジェラール・プレスギュルヴィック"]) self.assertEqual(item.composer, ["ジェラール・プレスギュルヴィック"])
@ -74,7 +76,9 @@ class DoubanDramaTestCase(TestCase):
# item.version, ["08星组公演版", "10年月組公演版", "17年星組公演版", "ュージカル2017年版"] # item.version, ["08星组公演版", "10年月組公演版", "17年星組公演版", "ュージカル2017年版"]
# ) # )
self.assertEqual(item.director, ["小池修一郎", "小池 修一郎", "石丸さち子"]) self.assertEqual(item.director, ["小池修一郎", "小池 修一郎", "石丸さち子"])
self.assertEqual(item.playwright, ["小池修一郎", "Baroness Orczy原作", "小池 修一郎"]) self.assertEqual(
item.playwright, ["小池修一郎", "Baroness Orczy原作", "小池 修一郎"]
)
self.assertEqual( self.assertEqual(
item.actor, item.actor,
[ [

View file

@ -354,7 +354,7 @@ class Indexer:
"query_by": ",".join(SEARCHABLE_ATTRIBUTES), "query_by": ",".join(SEARCHABLE_ATTRIBUTES),
"filter_by": filters, "filter_by": filters,
# "facet_by": "category", # "facet_by": "category",
"sort_by": "_text_match:desc,rating_count:desc" "sort_by": "_text_match:desc,rating_count:desc",
# 'facetsDistribution': ['_class'], # 'facetsDistribution': ['_class'],
# 'sort_by': None, # 'sort_by': None,
} }

View file

@ -7,6 +7,7 @@ Scraping the website directly.
- It requires Apple Developer Membership ($99 per year) to obtain a token. - It requires Apple Developer Membership ($99 per year) to obtain a token.
""" """
import json import json
import logging import logging

View file

@ -43,7 +43,9 @@ class Bangumi(AbstractSite):
model = "TVSeason" if is_series else "Movie" model = "TVSeason" if is_series else "Movie"
if dt: if dt:
year = dt.split("-")[0] year = dt.split("-")[0]
showtime = [{"time": dt, "region": "首播日期" if is_series else "发布日期"}] showtime = [
{"time": dt, "region": "首播日期" if is_series else "发布日期"}
]
case 3: case 3:
model = "Album" model = "Album"
case 4: case 4:

View file

@ -3,6 +3,7 @@ BoardGameGeek
ref: https://boardgamegeek.com/wiki/page/BGG_XML_API2 ref: https://boardgamegeek.com/wiki/page/BGG_XML_API2
""" """
import html import html
from langdetect import detect from langdetect import detect

View file

@ -55,7 +55,9 @@ class BooksTW(AbstractSite):
) )
translators = [s.strip() for s in translators] translators = [s.strip() for s in translators]
language_elem = content.xpath("//div/ul/li[starts-with(text(),'語言:')]/text()") language_elem = content.xpath(
"//div/ul/li[starts-with(text(),'語言:')]/text()"
)
language = ( language = (
language_elem[0].strip().split("")[1].strip() if language_elem else None # type: ignore language_elem[0].strip().split("")[1].strip() if language_elem else None # type: ignore
) )
@ -70,9 +72,11 @@ class BooksTW(AbstractSite):
pub_date = content.xpath("string(//div/ul/li[contains(text(),'出版日期:')])") pub_date = content.xpath("string(//div/ul/li[contains(text(),'出版日期:')])")
pub_date = re.match( pub_date = re.match(
r"(\d+)/(\d+)/(\d+)\s*$", r"(\d+)/(\d+)/(\d+)\s*$",
pub_date.strip().split("", 1)[1].strip().split(" ", 1)[0] # type: ignore (
if pub_date pub_date.strip().split("", 1)[1].strip().split(" ", 1)[0] # type: ignore
else "", if pub_date
else ""
),
) )
if pub_date: if pub_date:
pub_year = int(pub_date[1]) pub_year = int(pub_date[1])

View file

@ -1,6 +1,7 @@
""" """
Discogs. Discogs.
""" """
import json import json
import logging import logging

View file

@ -139,10 +139,11 @@ class IGDB(AbstractSite):
"brief": brief, "brief": brief,
"official_site": official_site, "official_site": official_site,
"igdb_id": r["id"], "igdb_id": r["id"],
"cover_image_url": "https:" "cover_image_url": (
+ r["cover"]["url"].replace("t_thumb", "t_cover_big") "https:" + r["cover"]["url"].replace("t_thumb", "t_cover_big")
if r.get("cover") if r.get("cover")
else None, else None
),
} }
) )
if steam_url: if steam_url:

View file

@ -83,13 +83,13 @@ class IMDB(AbstractSite):
"year": d["releaseYear"]["year"] if d.get("releaseYear") else None, "year": d["releaseYear"]["year"] if d.get("releaseYear") else None,
"is_series": d["titleType"]["isSeries"], "is_series": d["titleType"]["isSeries"],
"is_episode": d["titleType"]["isEpisode"], "is_episode": d["titleType"]["isEpisode"],
"genre": [x["text"] for x in d["genres"]["genres"]] "genre": (
if d.get("genres") [x["text"] for x in d["genres"]["genres"]] if d.get("genres") else []
else [], ),
"brief": d["plot"].get("plotText") if d.get("plot") else None, "brief": d["plot"].get("plotText") if d.get("plot") else None,
"cover_image_url": d["primaryImage"].get("url") "cover_image_url": (
if d.get("primaryImage") d["primaryImage"].get("url") if d.get("primaryImage") else None
else None, ),
} }
if d.get("series"): if d.get("series"):
episode_info = d["series"].get("episodeNumber") episode_info = d["series"].get("episodeNumber")

View file

@ -90,9 +90,9 @@ class RSS(AbstractSite):
metadata={ metadata={
"title": feed["title"], "title": feed["title"],
"brief": bleach.clean(feed["description"], strip=True), "brief": bleach.clean(feed["description"], strip=True),
"hosts": [feed.get("itunes_author")] "hosts": (
if feed.get("itunes_author") [feed.get("itunes_author")] if feed.get("itunes_author") else []
else [], ),
"official_site": feed.get("link"), "official_site": feed.get("link"),
"cover_image_url": feed.get("cover_url"), "cover_image_url": feed.get("cover_url"),
"genre": feed.get("itunes_categories", [None])[0], "genre": feed.get("itunes_categories", [None])[0],
@ -126,9 +126,11 @@ class RSS(AbstractSite):
"brief": bleach.clean(episode.get("description"), strip=True), "brief": bleach.clean(episode.get("description"), strip=True),
"description_html": episode.get("description_html"), "description_html": episode.get("description_html"),
"cover_url": episode.get("episode_art_url"), "cover_url": episode.get("episode_art_url"),
"media_url": episode.get("enclosures")[0].get("url") "media_url": (
if episode.get("enclosures") episode.get("enclosures")[0].get("url")
else None, if episode.get("enclosures")
else None
),
"pub_date": make_aware( "pub_date": make_aware(
datetime.fromtimestamp(episode.get("published")) datetime.fromtimestamp(episode.get("published"))
), ),

View file

@ -1,6 +1,7 @@
""" """
Spotify Spotify
""" """
import datetime import datetime
import logging import logging
import time import time

View file

@ -24,6 +24,7 @@ tv specials are are shown as movies
For now, we follow Douban convention, but keep an eye on it in case it breaks its own rules... For now, we follow Douban convention, but keep an eye on it in case it breaks its own rules...
""" """
import re import re
from functools import cached_property from functools import cached_property
from typing import TYPE_CHECKING, overload from typing import TYPE_CHECKING, overload

View file

@ -37,7 +37,18 @@ def export_marks_task(user):
) )
if not os.path.exists(os.path.dirname(filename)): if not os.path.exists(os.path.dirname(filename)):
os.makedirs(os.path.dirname(filename)) os.makedirs(os.path.dirname(filename))
heading = ["标题", "简介", "豆瓣评分", "链接", "创建时间", "我的评分", "标签", "评论", "NeoDB链接", "其它ID"] heading = [
"标题",
"简介",
"豆瓣评分",
"链接",
"创建时间",
"我的评分",
"标签",
"评论",
"NeoDB链接",
"其它ID",
]
wb = Workbook() wb = Workbook()
# adding write_only=True will speed up but corrupt the xlsx and won't be importable # adding write_only=True will speed up but corrupt the xlsx and won't be importable
for status, label in [ for status, label in [

View file

@ -207,7 +207,10 @@ class DoubanImporter:
f"豆瓣标记和评论导入完成,共处理{self.total}篇,已存在{self.skipped}篇,新增{self.imported}篇。", f"豆瓣标记和评论导入完成,共处理{self.total}篇,已存在{self.skipped}篇,新增{self.imported}篇。",
) )
if len(self.failed): if len(self.failed):
msg.error(self.user, f'豆瓣评论导入时未能处理以下网址:\n{" , ".join(self.failed)}') msg.error(
self.user,
f'豆瓣评论导入时未能处理以下网址:\n{" , ".join(self.failed)}',
)
def import_mark_sheet(self, worksheet, shelf_type, sheet_name): def import_mark_sheet(self, worksheet, shelf_type, sheet_name):
prefix = f"{self.user} {sheet_name}|" prefix = f"{self.user} {sheet_name}|"

View file

@ -71,7 +71,10 @@ class Migration(migrations.Migration):
"title", "title",
models.CharField(default="", max_length=1000, verbose_name="标题"), models.CharField(default="", max_length=1000, verbose_name="标题"),
), ),
("brief", models.TextField(blank=True, default="", verbose_name="简介")), (
"brief",
models.TextField(blank=True, default="", verbose_name="简介"),
),
( (
"cover", "cover",
models.ImageField( models.ImageField(

View file

@ -32,27 +32,51 @@ def user_stats_of(collection: Collection, identity: APIdentity):
def prural_items(count: int, category: str): def prural_items(count: int, category: str):
match category: match category:
case "book": case "book":
return ngettext("%(count)d book", "%(count)d books", count,) % { return ngettext(
"%(count)d book",
"%(count)d books",
count,
) % {
"count": count, "count": count,
} }
case "movie": case "movie":
return ngettext("%(count)d movie", "%(count)d movies", count,) % { return ngettext(
"%(count)d movie",
"%(count)d movies",
count,
) % {
"count": count, "count": count,
} }
case "tv": case "tv":
return ngettext("%(count)d tv show", "%(count)d tv shows", count,) % { return ngettext(
"%(count)d tv show",
"%(count)d tv shows",
count,
) % {
"count": count, "count": count,
} }
case "music": case "music":
return ngettext("%(count)d album", "%(count)d albums", count,) % { return ngettext(
"%(count)d album",
"%(count)d albums",
count,
) % {
"count": count, "count": count,
} }
case "game": case "game":
return ngettext("%(count)d game", "%(count)d games", count,) % { return ngettext(
"%(count)d game",
"%(count)d games",
count,
) % {
"count": count, "count": count,
} }
case "podcast": case "podcast":
return ngettext("%(count)d podcast", "%(count)d podcasts", count,) % { return ngettext(
"%(count)d podcast",
"%(count)d podcasts",
count,
) % {
"count": count, "count": count,
} }
case "performance": case "performance":
@ -64,6 +88,10 @@ def prural_items(count: int, category: str):
"count": count, "count": count,
} }
case _: case _:
return ngettext("%(count)d item", "%(count)d items", count,) % { return ngettext(
"%(count)d item",
"%(count)d items",
count,
) % {
"count": count, "count": count,
} }

View file

@ -294,13 +294,15 @@ def get_related_acct_list(site, token, api):
r: list[dict[str, str]] = response.json() r: list[dict[str, str]] = response.json()
results.extend( results.extend(
map( map(
lambda u: ( # type: ignore lambda u: (
u["acct"] ( # type: ignore
if u["acct"].find("@") != -1 u["acct"]
else u["acct"] + "@" + site if u["acct"].find("@") != -1
) else u["acct"] + "@" + site
if "acct" in u )
else u, if "acct" in u
else u
),
r, r,
) )
) )
@ -684,9 +686,11 @@ def share_collection(collection, comment, user, visibility_no, link):
if user == collection.owner.user if user == collection.owner.user
else ( else (
_("shared {username}'s collection").format( _("shared {username}'s collection").format(
username=" @" + collection.owner.user.mastodon_acct + " " username=(
if collection.owner.user.mastodon_acct " @" + collection.owner.user.mastodon_acct + " "
else " " + collection.owner.username + " " if collection.owner.user.mastodon_acct
else " " + collection.owner.username + " "
)
) )
) )
) )

View file

@ -1,8 +1,8 @@
black~=22.12.0 black~=24.4.2
coverage coverage
django-debug-toolbar django-debug-toolbar
django-stubs django-stubs
djlint~=1.34.0 djlint~=1.34.1
isort~=5.13.2 isort~=5.13.2
lxml-stubs lxml-stubs
pre-commit pre-commit

View file

@ -206,9 +206,9 @@ def connect_redirect_back(request):
) )
return register_new_user( return register_new_user(
request, request,
username=None username=(
if settings.MASTODON_ALLOW_ANY_SITE None if settings.MASTODON_ALLOW_ANY_SITE else user_data["username"]
else user_data["username"], ),
mastodon_username=user_data["username"], mastodon_username=user_data["username"],
mastodon_id=user_data["id"], mastodon_id=user_data["id"],
mastodon_site=site, mastodon_site=site,

View file

@ -86,9 +86,11 @@ def init_identity(apps, schema_editor):
local=True, local=True,
username=username, username=username,
domain_name=domain, domain_name=domain,
deleted=None deleted=(
if user.is_active None
else user.mastodon_last_reachable + timedelta(days=90), if user.is_active
else user.mastodon_last_reachable + timedelta(days=90)
),
) )
takahe_user = TakaheUser.objects.create( takahe_user = TakaheUser.objects.create(
pk=user.pk, email=handler, admin=user.is_superuser, password=user.password pk=user.pk, email=handler, admin=user.is_superuser, password=user.password

View file

@ -427,12 +427,16 @@ class User(AbstractUser):
sp = name.split("@") sp = name.split("@")
if len(sp) == 2: if len(sp) == 2:
query_kwargs = { query_kwargs = {
"mastodon_username__iexact" (
if case_sensitive "mastodon_username__iexact"
else "mastodon_username": sp[0], if case_sensitive
"mastodon_site__iexact" else "mastodon_username"
if case_sensitive ): sp[0],
else "mastodon_site": sp[1], (
"mastodon_site__iexact"
if case_sensitive
else "mastodon_site"
): sp[1],
} }
else: else:
return None return None