migrate to black 24
This commit is contained in:
parent
a71283e6d5
commit
55b1f1b365
29 changed files with 176 additions and 76 deletions
|
@ -1,12 +1,15 @@
|
|||
exclude: ^test_data/
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.4.0
|
||||
rev: v4.6.0
|
||||
hooks:
|
||||
- id: check-yaml
|
||||
- id: check-json
|
||||
- id: check-xml
|
||||
- id: check-toml
|
||||
- id: check-ast
|
||||
- id: check-docstring-first
|
||||
- id: check-executables-have-shebangs
|
||||
- id: check-symlinks
|
||||
- id: check-added-large-files
|
||||
args: [--maxkb=1024]
|
||||
|
@ -21,7 +24,7 @@ repos:
|
|||
- id: mixed-line-ending
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.3.5
|
||||
rev: v0.4.7
|
||||
hooks:
|
||||
- id: ruff
|
||||
# - id: ruff-format
|
||||
|
@ -33,7 +36,7 @@ repos:
|
|||
args: ["--profile=black"]
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.12.0
|
||||
rev: 24.4.2
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ Including another URLconf
|
|||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib import admin
|
||||
from django.urls import include, path
|
||||
|
|
|
@ -279,7 +279,8 @@ class BooksTWTestCase(TestCase):
|
|||
self.assertEqual(site.resource.id_value, "0010947886")
|
||||
self.assertEqual(site.resource.item.isbn, "9786263152236")
|
||||
self.assertEqual(
|
||||
site.resource.item.title, "阿拉伯人三千年:從民族、部落、語言、文化、宗教到帝國,綜覽阿拉伯世界的崛起、衰落與再興"
|
||||
site.resource.item.title,
|
||||
"阿拉伯人三千年:從民族、部落、語言、文化、宗教到帝國,綜覽阿拉伯世界的崛起、衰落與再興",
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
ResourceContent persists as an ExternalResource which may link to an Item
|
||||
"""
|
||||
|
||||
import json
|
||||
import re
|
||||
from dataclasses import dataclass, field
|
||||
|
|
|
@ -71,7 +71,8 @@ class SteamTestCase(TestCase):
|
|||
self.assertEqual(site.ready, True)
|
||||
self.assertEqual(site.resource.metadata["title"], "Portal 2")
|
||||
self.assertEqual(
|
||||
site.resource.metadata["brief"], "“终身测试计划”现已升级,您可以为您自己或您的好友设计合作谜题!"
|
||||
site.resource.metadata["brief"],
|
||||
"“终身测试计划”现已升级,您可以为您自己或您的好友设计合作谜题!",
|
||||
)
|
||||
self.assertIsInstance(site.resource.item, Game)
|
||||
self.assertEqual(site.resource.item.steam, "620")
|
||||
|
@ -102,7 +103,9 @@ class DoubanGameTestCase(TestCase):
|
|||
self.assertEqual(site.resource.metadata["title"], "传送门2 Portal 2")
|
||||
self.assertIsInstance(site.resource.item, Game)
|
||||
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, [])
|
||||
|
||||
|
||||
|
|
|
@ -118,14 +118,21 @@ class Migration(migrations.Migration):
|
|||
"title",
|
||||
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",
|
||||
models.CharField(max_length=50, null=True, verbose_name="主要标识类型"),
|
||||
models.CharField(
|
||||
max_length=50, null=True, verbose_name="主要标识类型"
|
||||
),
|
||||
),
|
||||
(
|
||||
"primary_lookup_id_value",
|
||||
models.CharField(max_length=1000, null=True, verbose_name="主要标识数值"),
|
||||
models.CharField(
|
||||
max_length=1000, null=True, verbose_name="主要标识数值"
|
||||
),
|
||||
),
|
||||
(
|
||||
"metadata",
|
||||
|
@ -184,14 +191,21 @@ class Migration(migrations.Migration):
|
|||
"title",
|
||||
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",
|
||||
models.CharField(max_length=50, null=True, verbose_name="主要标识类型"),
|
||||
models.CharField(
|
||||
max_length=50, null=True, verbose_name="主要标识类型"
|
||||
),
|
||||
),
|
||||
(
|
||||
"primary_lookup_id_value",
|
||||
models.CharField(max_length=1000, null=True, verbose_name="主要标识数值"),
|
||||
models.CharField(
|
||||
max_length=1000, null=True, verbose_name="主要标识数值"
|
||||
),
|
||||
),
|
||||
(
|
||||
"metadata",
|
||||
|
@ -505,12 +519,17 @@ class Migration(migrations.Migration):
|
|||
),
|
||||
(
|
||||
"id_value",
|
||||
models.CharField(blank=True, max_length=1000, verbose_name="源网站ID"),
|
||||
models.CharField(
|
||||
blank=True, max_length=1000, verbose_name="源网站ID"
|
||||
),
|
||||
),
|
||||
(
|
||||
"raw_url",
|
||||
models.CharField(
|
||||
blank=True, max_length=1000, unique=True, verbose_name="源网站ID"
|
||||
blank=True,
|
||||
max_length=1000,
|
||||
unique=True,
|
||||
verbose_name="源网站ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
# Generated by Django 4.2.13 on 2024-06-02 16:17
|
||||
|
||||
import catalog.common.utils
|
||||
from django.db import migrations, models
|
||||
|
||||
import catalog.common.utils
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
|
|
|
@ -396,9 +396,7 @@ class PerformanceProduction(Item):
|
|||
return (
|
||||
self.cover.url # type:ignore
|
||||
if self.cover and self.cover != DEFAULT_ITEM_COVER
|
||||
else self.show.cover_image_url
|
||||
if self.show
|
||||
else None
|
||||
else self.show.cover_image_url if self.show else None
|
||||
)
|
||||
|
||||
def update_linked_items_from_external_resource(self, resource: ExternalResource):
|
||||
|
|
|
@ -30,7 +30,9 @@ class DoubanDramaTestCase(TestCase):
|
|||
resource = site.get_resource_ready()
|
||||
item = site.get_item()
|
||||
self.assertEqual(item.title, "不眠之人·拿破仑")
|
||||
self.assertEqual(item.other_title, ["眠らない男・ナポレオン ―愛と栄光の涯(はて)に―"])
|
||||
self.assertEqual(
|
||||
item.other_title, ["眠らない男・ナポレオン ―愛と栄光の涯(はて)に―"]
|
||||
)
|
||||
self.assertEqual(item.genre, ["音乐剧"])
|
||||
self.assertEqual(item.troupe, ["宝塚歌剧团"])
|
||||
self.assertEqual(item.composer, ["ジェラール・プレスギュルヴィック"])
|
||||
|
@ -74,7 +76,9 @@ class DoubanDramaTestCase(TestCase):
|
|||
# item.version, ["08星组公演版", "10年月組公演版", "17年星組公演版", "ュージカル(2017年)版"]
|
||||
# )
|
||||
self.assertEqual(item.director, ["小池修一郎", "小池 修一郎", "石丸さち子"])
|
||||
self.assertEqual(item.playwright, ["小池修一郎", "Baroness Orczy(原作)", "小池 修一郎"])
|
||||
self.assertEqual(
|
||||
item.playwright, ["小池修一郎", "Baroness Orczy(原作)", "小池 修一郎"]
|
||||
)
|
||||
self.assertEqual(
|
||||
item.actor,
|
||||
[
|
||||
|
|
|
@ -354,7 +354,7 @@ class Indexer:
|
|||
"query_by": ",".join(SEARCHABLE_ATTRIBUTES),
|
||||
"filter_by": filters,
|
||||
# "facet_by": "category",
|
||||
"sort_by": "_text_match:desc,rating_count:desc"
|
||||
"sort_by": "_text_match:desc,rating_count:desc",
|
||||
# 'facetsDistribution': ['_class'],
|
||||
# 'sort_by': None,
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ Scraping the website directly.
|
|||
- It requires Apple Developer Membership ($99 per year) to obtain a token.
|
||||
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
|
|
|
@ -43,7 +43,9 @@ class Bangumi(AbstractSite):
|
|||
model = "TVSeason" if is_series else "Movie"
|
||||
if dt:
|
||||
year = dt.split("-")[0]
|
||||
showtime = [{"time": dt, "region": "首播日期" if is_series else "发布日期"}]
|
||||
showtime = [
|
||||
{"time": dt, "region": "首播日期" if is_series else "发布日期"}
|
||||
]
|
||||
case 3:
|
||||
model = "Album"
|
||||
case 4:
|
||||
|
|
|
@ -3,6 +3,7 @@ BoardGameGeek
|
|||
|
||||
ref: https://boardgamegeek.com/wiki/page/BGG_XML_API2
|
||||
"""
|
||||
|
||||
import html
|
||||
|
||||
from langdetect import detect
|
||||
|
|
|
@ -55,7 +55,9 @@ class BooksTW(AbstractSite):
|
|||
)
|
||||
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_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 = re.match(
|
||||
r"(\d+)/(\d+)/(\d+)\s*$",
|
||||
(
|
||||
pub_date.strip().split(":", 1)[1].strip().split(" ", 1)[0] # type: ignore
|
||||
if pub_date
|
||||
else "",
|
||||
else ""
|
||||
),
|
||||
)
|
||||
if pub_date:
|
||||
pub_year = int(pub_date[1])
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""
|
||||
Discogs.
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
|
|
|
@ -139,10 +139,11 @@ class IGDB(AbstractSite):
|
|||
"brief": brief,
|
||||
"official_site": official_site,
|
||||
"igdb_id": r["id"],
|
||||
"cover_image_url": "https:"
|
||||
+ r["cover"]["url"].replace("t_thumb", "t_cover_big")
|
||||
"cover_image_url": (
|
||||
"https:" + r["cover"]["url"].replace("t_thumb", "t_cover_big")
|
||||
if r.get("cover")
|
||||
else None,
|
||||
else None
|
||||
),
|
||||
}
|
||||
)
|
||||
if steam_url:
|
||||
|
|
|
@ -83,13 +83,13 @@ class IMDB(AbstractSite):
|
|||
"year": d["releaseYear"]["year"] if d.get("releaseYear") else None,
|
||||
"is_series": d["titleType"]["isSeries"],
|
||||
"is_episode": d["titleType"]["isEpisode"],
|
||||
"genre": [x["text"] for x in d["genres"]["genres"]]
|
||||
if d.get("genres")
|
||||
else [],
|
||||
"genre": (
|
||||
[x["text"] for x in d["genres"]["genres"]] if d.get("genres") else []
|
||||
),
|
||||
"brief": d["plot"].get("plotText") if d.get("plot") else None,
|
||||
"cover_image_url": d["primaryImage"].get("url")
|
||||
if d.get("primaryImage")
|
||||
else None,
|
||||
"cover_image_url": (
|
||||
d["primaryImage"].get("url") if d.get("primaryImage") else None
|
||||
),
|
||||
}
|
||||
if d.get("series"):
|
||||
episode_info = d["series"].get("episodeNumber")
|
||||
|
|
|
@ -90,9 +90,9 @@ class RSS(AbstractSite):
|
|||
metadata={
|
||||
"title": feed["title"],
|
||||
"brief": bleach.clean(feed["description"], strip=True),
|
||||
"hosts": [feed.get("itunes_author")]
|
||||
if feed.get("itunes_author")
|
||||
else [],
|
||||
"hosts": (
|
||||
[feed.get("itunes_author")] if feed.get("itunes_author") else []
|
||||
),
|
||||
"official_site": feed.get("link"),
|
||||
"cover_image_url": feed.get("cover_url"),
|
||||
"genre": feed.get("itunes_categories", [None])[0],
|
||||
|
@ -126,9 +126,11 @@ class RSS(AbstractSite):
|
|||
"brief": bleach.clean(episode.get("description"), strip=True),
|
||||
"description_html": episode.get("description_html"),
|
||||
"cover_url": episode.get("episode_art_url"),
|
||||
"media_url": episode.get("enclosures")[0].get("url")
|
||||
"media_url": (
|
||||
episode.get("enclosures")[0].get("url")
|
||||
if episode.get("enclosures")
|
||||
else None,
|
||||
else None
|
||||
),
|
||||
"pub_date": make_aware(
|
||||
datetime.fromtimestamp(episode.get("published"))
|
||||
),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""
|
||||
Spotify
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
import time
|
||||
|
|
|
@ -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...
|
||||
|
||||
"""
|
||||
|
||||
import re
|
||||
from functools import cached_property
|
||||
from typing import TYPE_CHECKING, overload
|
||||
|
|
|
@ -37,7 +37,18 @@ def export_marks_task(user):
|
|||
)
|
||||
if not os.path.exists(os.path.dirname(filename)):
|
||||
os.makedirs(os.path.dirname(filename))
|
||||
heading = ["标题", "简介", "豆瓣评分", "链接", "创建时间", "我的评分", "标签", "评论", "NeoDB链接", "其它ID"]
|
||||
heading = [
|
||||
"标题",
|
||||
"简介",
|
||||
"豆瓣评分",
|
||||
"链接",
|
||||
"创建时间",
|
||||
"我的评分",
|
||||
"标签",
|
||||
"评论",
|
||||
"NeoDB链接",
|
||||
"其它ID",
|
||||
]
|
||||
wb = Workbook()
|
||||
# adding write_only=True will speed up but corrupt the xlsx and won't be importable
|
||||
for status, label in [
|
||||
|
|
|
@ -207,7 +207,10 @@ class DoubanImporter:
|
|||
f"豆瓣标记和评论导入完成,共处理{self.total}篇,已存在{self.skipped}篇,新增{self.imported}篇。",
|
||||
)
|
||||
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):
|
||||
prefix = f"{self.user} {sheet_name}|"
|
||||
|
|
|
@ -71,7 +71,10 @@ class Migration(migrations.Migration):
|
|||
"title",
|
||||
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",
|
||||
models.ImageField(
|
||||
|
|
|
@ -32,27 +32,51 @@ def user_stats_of(collection: Collection, identity: APIdentity):
|
|||
def prural_items(count: int, category: str):
|
||||
match category:
|
||||
case "book":
|
||||
return ngettext("%(count)d book", "%(count)d books", count,) % {
|
||||
return ngettext(
|
||||
"%(count)d book",
|
||||
"%(count)d books",
|
||||
count,
|
||||
) % {
|
||||
"count": count,
|
||||
}
|
||||
case "movie":
|
||||
return ngettext("%(count)d movie", "%(count)d movies", count,) % {
|
||||
return ngettext(
|
||||
"%(count)d movie",
|
||||
"%(count)d movies",
|
||||
count,
|
||||
) % {
|
||||
"count": count,
|
||||
}
|
||||
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,
|
||||
}
|
||||
case "music":
|
||||
return ngettext("%(count)d album", "%(count)d albums", count,) % {
|
||||
return ngettext(
|
||||
"%(count)d album",
|
||||
"%(count)d albums",
|
||||
count,
|
||||
) % {
|
||||
"count": count,
|
||||
}
|
||||
case "game":
|
||||
return ngettext("%(count)d game", "%(count)d games", count,) % {
|
||||
return ngettext(
|
||||
"%(count)d game",
|
||||
"%(count)d games",
|
||||
count,
|
||||
) % {
|
||||
"count": count,
|
||||
}
|
||||
case "podcast":
|
||||
return ngettext("%(count)d podcast", "%(count)d podcasts", count,) % {
|
||||
return ngettext(
|
||||
"%(count)d podcast",
|
||||
"%(count)d podcasts",
|
||||
count,
|
||||
) % {
|
||||
"count": count,
|
||||
}
|
||||
case "performance":
|
||||
|
@ -64,6 +88,10 @@ def prural_items(count: int, category: str):
|
|||
"count": count,
|
||||
}
|
||||
case _:
|
||||
return ngettext("%(count)d item", "%(count)d items", count,) % {
|
||||
return ngettext(
|
||||
"%(count)d item",
|
||||
"%(count)d items",
|
||||
count,
|
||||
) % {
|
||||
"count": count,
|
||||
}
|
||||
|
|
|
@ -294,13 +294,15 @@ def get_related_acct_list(site, token, api):
|
|||
r: list[dict[str, str]] = response.json()
|
||||
results.extend(
|
||||
map(
|
||||
lambda u: ( # type: ignore
|
||||
lambda u: (
|
||||
( # type: ignore
|
||||
u["acct"]
|
||||
if u["acct"].find("@") != -1
|
||||
else u["acct"] + "@" + site
|
||||
)
|
||||
if "acct" in u
|
||||
else u,
|
||||
else u
|
||||
),
|
||||
r,
|
||||
)
|
||||
)
|
||||
|
@ -684,12 +686,14 @@ def share_collection(collection, comment, user, visibility_no, link):
|
|||
if user == collection.owner.user
|
||||
else (
|
||||
_("shared {username}'s collection").format(
|
||||
username=" @" + collection.owner.user.mastodon_acct + " "
|
||||
username=(
|
||||
" @" + collection.owner.user.mastodon_acct + " "
|
||||
if collection.owner.user.mastodon_acct
|
||||
else " " + collection.owner.username + " "
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
content = f"{user_str}:{collection.title}\n{link}\n{comment}{tags}"
|
||||
response = post_toot(user.mastodon_site, content, visibility, user.mastodon_token)
|
||||
if response is not None and response.status_code in [200, 201]:
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
black~=22.12.0
|
||||
black~=24.4.2
|
||||
coverage
|
||||
django-debug-toolbar
|
||||
django-stubs
|
||||
djlint~=1.34.0
|
||||
djlint~=1.34.1
|
||||
isort~=5.13.2
|
||||
lxml-stubs
|
||||
pre-commit
|
||||
|
|
|
@ -206,9 +206,9 @@ def connect_redirect_back(request):
|
|||
)
|
||||
return register_new_user(
|
||||
request,
|
||||
username=None
|
||||
if settings.MASTODON_ALLOW_ANY_SITE
|
||||
else user_data["username"],
|
||||
username=(
|
||||
None if settings.MASTODON_ALLOW_ANY_SITE else user_data["username"]
|
||||
),
|
||||
mastodon_username=user_data["username"],
|
||||
mastodon_id=user_data["id"],
|
||||
mastodon_site=site,
|
||||
|
|
|
@ -86,9 +86,11 @@ def init_identity(apps, schema_editor):
|
|||
local=True,
|
||||
username=username,
|
||||
domain_name=domain,
|
||||
deleted=None
|
||||
deleted=(
|
||||
None
|
||||
if user.is_active
|
||||
else user.mastodon_last_reachable + timedelta(days=90),
|
||||
else user.mastodon_last_reachable + timedelta(days=90)
|
||||
),
|
||||
)
|
||||
takahe_user = TakaheUser.objects.create(
|
||||
pk=user.pk, email=handler, admin=user.is_superuser, password=user.password
|
||||
|
|
|
@ -427,12 +427,16 @@ class User(AbstractUser):
|
|||
sp = name.split("@")
|
||||
if len(sp) == 2:
|
||||
query_kwargs = {
|
||||
(
|
||||
"mastodon_username__iexact"
|
||||
if case_sensitive
|
||||
else "mastodon_username": sp[0],
|
||||
else "mastodon_username"
|
||||
): sp[0],
|
||||
(
|
||||
"mastodon_site__iexact"
|
||||
if case_sensitive
|
||||
else "mastodon_site": sp[1],
|
||||
else "mastodon_site"
|
||||
): sp[1],
|
||||
}
|
||||
else:
|
||||
return None
|
||||
|
|
Loading…
Add table
Reference in a new issue