update lint: replace black and isort with ruff

This commit is contained in:
mein Name 2025-01-11 17:20:02 -05:00 committed by Henri Dickson
parent a93d9668f7
commit 2a048a3719
151 changed files with 282 additions and 394 deletions

View file

@ -25,21 +25,21 @@ repos:
- id: mixed-line-ending
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.4
rev: v0.9.1
hooks:
- id: ruff
# - id: ruff-format
- id: ruff-format
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
args: ["--profile=black"]
# - repo: https://github.com/pycqa/isort
# rev: 5.13.2
# hooks:
# - id: isort
# args: ["--profile=black"]
- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
- id: black
# - repo: https://github.com/psf/black
# rev: 24.4.2
# hooks:
# - id: black
- repo: https://github.com/Riverside-Healthcare/djLint
rev: v1.36.4

View file

@ -75,4 +75,4 @@ Please see [docs/install.md](docs/install.md)
- To translate NeoDB to more languages, please join [our project on Weblate](https://hosted.weblate.org/projects/neodb/neodb/)
## Sponsor
If you like this project, please consider donating to [NeoDB on ko-fi](https://ko-fi.com/neodb), or our friends at [NiceDB](https://patreon.com/tertius) without whom this project won't be possible.
If you like this project, please consider donating to [NeoDB.social on ko-fi](https://ko-fi.com/neodb), or [Takahē](https://www.patreon.com/takahe) and [NiceDB](https://patreon.com/tertius) without whom this project won't be possible.

View file

@ -1,3 +1 @@
from django.contrib import admin
# Register your models here.

View file

@ -1,5 +1,5 @@
from enum import Enum
from typing import Any, Callable, List, Optional, Tuple, Type
from typing import List
from django.core.cache import cache
from django.http import HttpResponse

View file

@ -7,12 +7,9 @@ class CatalogConfig(AppConfig):
def ready(self):
# load key modules in proper order, make sure class inject and signal works as expected
from catalog import api, models, sites
from catalog.models import init_catalog_audit_log, init_catalog_search_models
from journal import models as journal_models
# register cron jobs
from catalog.jobs import DiscoverGenerator, PodcastUpdater # isort:skip
init_catalog_search_models()
init_catalog_audit_log()

View file

@ -33,8 +33,6 @@ from catalog.common import (
Item,
ItemCategory,
ItemInSchema,
ItemSchema,
ItemType,
PrimaryLookupIdDescriptor,
jsondata,
)
@ -286,7 +284,7 @@ class Edition(Item):
logger.warning(f"Unable to find work for {work_res}")
else:
logger.warning(
f'Unable to find resource for {w["id_type"]}:{w["id_value"]}'
f"Unable to find resource for {w['id_type']}:{w['id_value']}"
)
work = Work.objects.filter(
primary_lookup_id_type=w["id_type"],
@ -431,7 +429,7 @@ class Work(Item):
logger.warning(f"Unable to find edition for {edition_res}")
else:
logger.warning(
f'Unable to find resource for {e["id_type"]}:{e["id_value"]}'
f"Unable to find resource for {e['id_type']}:{e['id_value']}"
)
edition = Edition.objects.filter(
primary_lookup_id_type=e["id_type"],

View file

@ -1,5 +1,4 @@
import json
import logging
import re
import time
from io import BytesIO, StringIO

View file

@ -1,20 +1,16 @@
# pyright: reportIncompatibleMethodOverride=false
import copy
from base64 import b64decode, b64encode
from base64 import b64encode
from datetime import date, datetime
from functools import partialmethod
from hashlib import sha256
from importlib import import_module
import django
import loguru
from cryptography.fernet import Fernet, MultiFernet
from django.conf import settings
from django.core.exceptions import FieldError
from django.db.models import DEFERRED, fields # type:ignore
from django.utils import dateparse, timezone
from django.utils.encoding import force_bytes
from django.utils.translation import gettext_lazy as _
from django_jsonform.forms.fields import JSONFormField as DJANGO_JSONFormField
# from django.db.models import JSONField as DJANGO_JSONField
@ -22,7 +18,6 @@ from django_jsonform.forms.fields import JSONFormField as DJANGO_JSONFormField
# from django.contrib.postgres.fields import ArrayField as DJANGO_ArrayField
from django_jsonform.models.fields import ArrayField as DJANGO_ArrayField
from django_jsonform.models.fields import JSONField as DJANGO_JSONField
from loguru import logger
class Patched_DJANGO_JSONField(DJANGO_JSONField):

View file

@ -1,19 +1,17 @@
import re
import uuid
from functools import cached_property
from typing import TYPE_CHECKING, Any, Iterable, Self, Sequence, Type, cast
from typing import TYPE_CHECKING, Any, Self
from auditlog.context import disable_auditlog
from auditlog.models import AuditlogHistoryField, LogEntry
from auditlog.models import LogEntry
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.signing import b62_decode, b62_encode
from django.db import connection, models
from django.db.models import QuerySet, Value
from django.template.defaultfilters import default
from django.db.models import QuerySet
from django.utils import timezone
from django.utils.translation import get_language
from django.utils.translation import gettext_lazy as _
from loguru import logger
from ninja import Field, Schema
@ -72,36 +70,24 @@ class IdType(models.TextChoices):
IMDB = "imdb", _("IMDb") # type:ignore[reportCallIssue]
TMDB_TV = "tmdb_tv", _("TMDB TV Serie") # type:ignore[reportCallIssue]
TMDB_TVSeason = "tmdb_tvseason", _("TMDB TV Season") # type:ignore[reportCallIssue]
TMDB_TVEpisode = "tmdb_tvepisode", _(
"TMDB TV Episode"
) # type:ignore[reportCallIssue]
TMDB_TVEpisode = "tmdb_tvepisode", _("TMDB TV Episode") # type:ignore[reportCallIssue]
TMDB_Movie = "tmdb_movie", _("TMDB Movie") # type:ignore[reportCallIssue]
Goodreads = "goodreads", _("Goodreads") # type:ignore[reportCallIssue]
Goodreads_Work = "goodreads_work", _(
"Goodreads Work"
) # type:ignore[reportCallIssue]
Goodreads_Work = "goodreads_work", _("Goodreads Work") # type:ignore[reportCallIssue]
GoogleBooks = "googlebooks", _("Google Books") # type:ignore[reportCallIssue]
DoubanBook = "doubanbook", _("Douban Book") # type:ignore[reportCallIssue]
DoubanBook_Work = "doubanbook_work", _(
"Douban Book Work"
) # type:ignore[reportCallIssue]
DoubanBook_Work = "doubanbook_work", _("Douban Book Work") # type:ignore[reportCallIssue]
DoubanMovie = "doubanmovie", _("Douban Movie") # type:ignore[reportCallIssue]
DoubanMusic = "doubanmusic", _("Douban Music") # type:ignore[reportCallIssue]
DoubanGame = "doubangame", _("Douban Game") # type:ignore[reportCallIssue]
DoubanDrama = "doubandrama", _("Douban Drama") # type:ignore[reportCallIssue]
DoubanDramaVersion = "doubandrama_version", _(
"Douban Drama Version"
) # type:ignore[reportCallIssue]
DoubanDramaVersion = "doubandrama_version", _("Douban Drama Version") # type:ignore[reportCallIssue]
BooksTW = "bookstw", _("BooksTW Book") # type:ignore[reportCallIssue]
Bandcamp = "bandcamp", _("Bandcamp") # type:ignore[reportCallIssue]
Spotify_Album = "spotify_album", _("Spotify Album") # type:ignore[reportCallIssue]
Spotify_Show = "spotify_show", _("Spotify Podcast") # type:ignore[reportCallIssue]
Discogs_Release = "discogs_release", _(
"Discogs Release"
) # type:ignore[reportCallIssue]
Discogs_Master = "discogs_master", _(
"Discogs Master"
) # type:ignore[reportCallIssue]
Discogs_Release = "discogs_release", _("Discogs Release") # type:ignore[reportCallIssue]
Discogs_Master = "discogs_master", _("Discogs Master") # type:ignore[reportCallIssue]
MusicBrainz = "musicbrainz", _("MusicBrainz ID") # type:ignore[reportCallIssue]
# DoubanBook_Author = "doubanbook_author", _("Douban Book Author") # type:ignore[reportCallIssue]
# DoubanCelebrity = "doubanmovie_celebrity", _("Douban Movie Celebrity") # type:ignore[reportCallIssue]
@ -142,13 +128,9 @@ class ItemType(models.TextChoices):
Album = "music", _("Album") # type:ignore[reportCallIssue]
Game = "game", _("Game") # type:ignore[reportCallIssue]
Podcast = "podcast", _("Podcast Program") # type:ignore[reportCallIssue]
PodcastEpisode = "podcastepisode", _(
"Podcast Episode"
) # type:ignore[reportCallIssue]
PodcastEpisode = "podcastepisode", _("Podcast Episode") # type:ignore[reportCallIssue]
Performance = "performance", _("Performance") # type:ignore[reportCallIssue]
PerformanceProduction = "production", _(
"Production"
) # type:ignore[reportCallIssue]
PerformanceProduction = "production", _("Production") # type:ignore[reportCallIssue]
FanFic = "fanfic", _("Fanfic") # type:ignore[reportCallIssue]
Exhibition = "exhibition", _("Exhibition") # type:ignore[reportCallIssue]
Collection = "collection", _("Collection") # type:ignore[reportCallIssue]

View file

@ -10,7 +10,7 @@ ResourceContent persists as an ExternalResource which may link to an Item
import json
import re
from dataclasses import dataclass, field
from typing import Any, Callable, Type, TypeVar
from typing import Type, TypeVar
import django_rq
import requests

View file

@ -1,10 +1,6 @@
from django.test import TestCase
from common.models import (
LANGUAGE_CHOICES,
LOCALE_CHOICES,
SCRIPT_CHOICES,
SITE_DEFAULT_LANGUAGE,
SITE_PREFERRED_LANGUAGES,
SITE_PREFERRED_LOCALES,
detect_language,

View file

@ -1,17 +1,14 @@
from datetime import date
from django.db import models
from django.template.defaultfilters import default
from django.utils.translation import gettext_lazy as _
from catalog.common import (
BaseSchema,
ExternalResource,
IdType,
Item,
ItemCategory,
ItemInSchema,
ItemSchema,
ItemType,
PrimaryLookupIdDescriptor,
jsondata,

View file

@ -1,2 +1,7 @@
from .discover import DiscoverGenerator
from .podcast import PodcastUpdater
__all__ = [
"DiscoverGenerator",
"PodcastUpdater",
]

View file

@ -7,7 +7,6 @@ from django.db.models import Count, F, Q
from django.utils import timezone
from loguru import logger
from boofilsic.settings import MIN_MARKS_FOR_DISCOVER
from catalog.models import *
from common.models import SITE_PREFERRED_LOCALES, BaseJob, JobManager
from journal.models import (
@ -19,7 +18,6 @@ from journal.models import (
q_item_in_category,
)
from takahe.utils import Takahe
from users.models import APIdentity
MAX_ITEMS_PER_PERIOD = 12
MIN_MARKS = settings.MIN_MARKS_FOR_DISCOVER

View file

@ -1,6 +1,4 @@
import pprint
from datetime import timedelta
from time import sleep
from loguru import logger
@ -30,6 +28,6 @@ class PodcastUpdater(BaseJob):
site = RSS(p.feed_url)
site.scrape_additional_data()
c2 = p.episodes.count()
logger.info(f"updated {p}, {c2-c} new episodes.")
logger.info(f"updated {p}, {c2 - c} new episodes.")
count += c2 - c
logger.info(f"Podcasts update finished, {count} new episodes total.")

View file

@ -46,4 +46,4 @@ class Command(BaseCommand):
resource = site.scrape()
pprint.pp(resource.metadata)
pprint.pp(resource.lookup_ids)
self.stdout.write(self.style.SUCCESS(f"Done."))
self.stdout.write(self.style.SUCCESS("Done."))

View file

@ -1,6 +1,3 @@
import pprint
import re
from django.contrib.contenttypes.models import ContentType
from django.core.management.base import BaseCommand
from django.db.models import Count, F
@ -9,7 +6,6 @@ from tqdm import tqdm
from catalog.book.tests import uniq
from catalog.models import *
from common.models.lang import detect_language
from journal.models import update_journal_for_merged_item
class Command(BaseCommand):
@ -49,7 +45,7 @@ class Command(BaseCommand):
self.integrity()
if options["localize"]:
self.localize()
self.stdout.write(self.style.SUCCESS(f"Done."))
self.stdout.write(self.style.SUCCESS("Done."))
def localize(self):
c = Item.objects.all().count()
@ -94,14 +90,14 @@ class Command(BaseCommand):
cls.objects.filter(is_deleted=True).delete()
def integrity(self):
self.stdout.write(f"Checking circulated merge...")
self.stdout.write("Checking circulated merge...")
for i in Item.objects.filter(merged_to_item=F("id")):
self.stdout.write(f"! {i} : {i.absolute_url}?skipcheck=1")
if self.fix:
i.merged_to_item = None
i.save()
self.stdout.write(f"Checking chained merge...")
self.stdout.write("Checking chained merge...")
for i in (
Item.objects.filter(merged_to_item__isnull=False)
.annotate(n=Count("merged_from_items"))
@ -113,14 +109,14 @@ class Command(BaseCommand):
j.merged_to_item = i.merged_to_item
j.save()
self.stdout.write(f"Checking deleted merge...")
self.stdout.write("Checking deleted merge...")
for i in Item.objects.filter(merged_to_item__isnull=False, is_deleted=True):
self.stdout.write(f"! {i} : {i.absolute_url}?skipcheck=1")
if self.fix:
i.is_deleted = False
i.save()
self.stdout.write(f"Checking deleted item with external resources...")
self.stdout.write("Checking deleted item with external resources...")
for i in (
Item.objects.filter(is_deleted=True)
.annotate(n=Count("external_resources"))
@ -132,7 +128,7 @@ class Command(BaseCommand):
r.item = None
r.save()
self.stdout.write(f"Checking merged item with external resources...")
self.stdout.write("Checking merged item with external resources...")
for i in (
Item.objects.filter(merged_to_item__isnull=False)
.annotate(n=Count("external_resources"))
@ -145,7 +141,7 @@ class Command(BaseCommand):
r.save()
tvshow_ct_id = ContentType.objects.get_for_model(TVShow).id
self.stdout.write(f"Checking TVShow merged to other class...")
self.stdout.write("Checking TVShow merged to other class...")
for i in (
TVShow.objects.filter(merged_to_item__isnull=False)
.filter(merged_to_item__isnull=False)
@ -161,7 +157,7 @@ class Command(BaseCommand):
if self.fix:
i.recast_to(i.merged_to_item.__class__) # type:ignore
self.stdout.write(f"Checking TVSeason is child of other class...")
self.stdout.write("Checking TVSeason is child of other class...")
for i in TVSeason.objects.filter(show__isnull=False).exclude(
show__polymorphic_ctype_id=tvshow_ct_id
):
@ -172,7 +168,7 @@ class Command(BaseCommand):
i.show = None
i.save()
self.stdout.write(f"Checking deleted item with child TV Season...")
self.stdout.write("Checking deleted item with child TV Season...")
for i in TVSeason.objects.filter(show__is_deleted=True):
if not i.show:
continue
@ -181,7 +177,7 @@ class Command(BaseCommand):
i.show.is_deleted = False
i.show.save()
self.stdout.write(f"Checking merged item with child TV Season...")
self.stdout.write("Checking merged item with child TV Season...")
for i in TVSeason.objects.filter(show__merged_to_item__isnull=False):
if not i.show:
continue

View file

@ -1,12 +1,8 @@
import pprint
from datetime import timedelta
from time import sleep
from typing import TYPE_CHECKING
from django.conf import settings
from django.core.management.base import BaseCommand
from django.core.paginator import Paginator
from django.utils import timezone
from tqdm import tqdm
from catalog.models import Item

View file

@ -3,7 +3,6 @@
import uuid
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
import catalog.common.utils

View file

@ -4,7 +4,6 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("catalog", "0010_alter_item_polymorphic_ctype"),
]

View file

@ -6,7 +6,6 @@ import catalog.common.utils
class Migration(migrations.Migration):
dependencies = [
("catalog", "0011_alter_externalresource_id_type_and_more"),
]

View file

@ -38,7 +38,7 @@ from .tv.models import (
TVShowSchema,
)
from .search.models import Indexer, ExternalSearchResultItem # isort:skip
from .search.models import Indexer # isort:skip
# class Exhibition(Item):

View file

@ -3,12 +3,10 @@ from django.utils.translation import gettext_lazy as _
from catalog.common import (
BaseSchema,
ExternalResource,
IdType,
Item,
ItemCategory,
ItemInSchema,
ItemSchema,
ItemType,
PrimaryLookupIdDescriptor,
jsondata,

View file

@ -6,12 +6,10 @@ from django.utils.translation import pgettext_lazy
from catalog.common import (
BaseSchema,
ExternalResource,
IdType,
Item,
ItemCategory,
ItemInSchema,
ItemSchema,
ItemType,
PrimaryLookupIdDescriptor,
jsondata,

View file

@ -391,7 +391,9 @@ class PerformanceProduction(Item):
return (
self.cover.url # type:ignore
if self.cover and self.cover != settings.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):

View file

@ -6,14 +6,10 @@ from ninja import Field
from catalog.common import (
BaseSchema,
ExternalResource,
IdType,
Item,
ItemCategory,
ItemInSchema,
ItemSchema,
ItemType,
PrimaryLookupIdDescriptor,
jsondata,
)
from catalog.common.models import LIST_OF_ONE_PLUS_STR_SCHEMA, LanguageListField

View file

@ -62,7 +62,7 @@ class PodcastRSSFeedTestCase(TestCase):
site = SiteManager.get_site_by_url(t_url)
site.get_resource_ready()
self.assertEqual(site.ready, True)
metadata = site.resource.metadata
# metadata = site.resource.metadata
self.assertIsNotNone(site.get_item().cover.url)
self.assertIsNotNone(site.get_item().recent_episodes[0].title)
self.assertIsNotNone(site.get_item().recent_episodes[0].link)
@ -74,7 +74,7 @@ class PodcastRSSFeedTestCase(TestCase):
site = SiteManager.get_site_by_url(t_url)
site.get_resource_ready()
self.assertEqual(site.ready, True)
metadata = site.resource.metadata
# metadata = site.resource.metadata
self.assertIsNotNone(site.get_item().recent_episodes[0].title)
self.assertIsNotNone(site.get_item().recent_episodes[0].link)
self.assertIsNotNone(site.get_item().recent_episodes[0].media_url)

View file

@ -1,6 +1,5 @@
import asyncio
import logging
import time
from urllib.parse import quote_plus, urlparse
import httpx
@ -90,7 +89,7 @@ class GoogleBooks:
@classmethod
def search(cls, q, page=1):
results = []
api_url = f"https://www.googleapis.com/books/v1/volumes?country=us&q={quote_plus(q)}&startIndex={SEARCH_PAGE_SIZE*(page-1)}&maxResults={SEARCH_PAGE_SIZE}&maxAllowedMaturityRating=MATURE"
api_url = f"https://www.googleapis.com/books/v1/volumes?country=us&q={quote_plus(q)}&startIndex={SEARCH_PAGE_SIZE * (page - 1)}&maxResults={SEARCH_PAGE_SIZE}&maxAllowedMaturityRating=MATURE"
try:
j = requests.get(api_url, timeout=2).json()
if "items" in j:
@ -183,7 +182,7 @@ class Spotify:
@classmethod
def search(cls, q, page=1):
results = []
api_url = f"https://api.spotify.com/v1/search?q={q}&type=album&limit={SEARCH_PAGE_SIZE}&offset={page*SEARCH_PAGE_SIZE}"
api_url = f"https://api.spotify.com/v1/search?q={q}&type=album&limit={SEARCH_PAGE_SIZE}&offset={page * SEARCH_PAGE_SIZE}"
try:
headers = {"Authorization": f"Bearer {get_spotify_token()}"}
j = requests.get(api_url, headers=headers, timeout=2).json()
@ -255,7 +254,7 @@ class ApplePodcast:
@classmethod
def search(cls, q, page=1):
results = []
search_url = f"https://itunes.apple.com/search?entity=podcast&limit={page*SEARCH_PAGE_SIZE}&term={quote_plus(q)}"
search_url = f"https://itunes.apple.com/search?entity=podcast&limit={page * SEARCH_PAGE_SIZE}&term={quote_plus(q)}"
try:
r = requests.get(search_url, timeout=2).json()
for p in r["results"][(page - 1) * SEARCH_PAGE_SIZE :]:
@ -291,7 +290,7 @@ class IGDB:
class Fediverse:
@staticmethod
async def search_task(host, q, category=None):
api_url = f"https://{host}/api/catalog/search?query={quote_plus(q)}{'&category='+category if category else ''}"
api_url = f"https://{host}/api/catalog/search?query={quote_plus(q)}{'&category=' + category if category else ''}"
async with httpx.AsyncClient() as client:
results = []
try:

View file

@ -6,7 +6,6 @@ import django_rq
from auditlog.context import set_actor
from django.conf import settings
from django.core.cache import cache
from django.utils.translation import gettext_lazy as _
from loguru import logger
from rq.job import Job

View file

@ -1,6 +1,5 @@
import types
from datetime import timedelta
from pprint import pprint
from time import sleep
import django_rq

View file

@ -1,5 +1,4 @@
import re
from urllib.parse import quote
import django_rq
from django.conf import settings
@ -7,7 +6,6 @@ from django.contrib.auth.decorators import login_required
from django.core.cache import cache
from django.core.exceptions import BadRequest
from django.shortcuts import redirect, render
from django.urls import reverse
from django.utils.translation import gettext as _
from django.views.decorators.http import require_http_methods
from rq.job import Job
@ -162,7 +160,7 @@ def external_search(request):
keywords = request.GET.get("q", default="").strip()
page_number = int_(request.GET.get("page"), 1)
items = ExternalSources.search(category, keywords, page_number) if keywords else []
cache_key = f"search_{category if category!='movietv' else 'movie,tv'}_{keywords}"
cache_key = f"search_{category if category != 'movietv' else 'movie,tv'}_{keywords}"
dedupe_urls = cache.get(cache_key, [])
items = [i for i in items if i.source_url not in dedupe_urls]

View file

@ -25,3 +25,33 @@ from .tmdb import TMDB_Movie
from .ypshuo import Ypshuo
# from .apple_podcast import ApplePodcast
__all__ = [
"SiteManager",
"ArchiveOfOurOwn",
"AppleMusic",
"Bandcamp",
"Bangumi",
"BoardGameGeek",
"BooksTW",
"DiscogsMaster",
"DiscogsRelease",
"DoubanBook",
"DoubanDrama",
"DoubanGame",
"DoubanMovie",
"DoubanMusic",
"FediverseInstance",
"Goodreads",
"GoogleBooks",
"IGDB",
"IMDB",
"JJWXC",
"Qidian",
"RSS",
"Spotify",
"Steam",
"TMDB_Movie",
"Ypshuo",
# "ApplePodcast",
]

View file

@ -1,5 +1,3 @@
import logging
from catalog.book.models import *
from catalog.common import *

View file

@ -10,7 +10,6 @@ Scraping the website directly.
import json
import logging
from threading import local
import dateparser

View file

@ -6,8 +6,6 @@ ref: https://boardgamegeek.com/wiki/page/BGG_XML_API2
import html
from langdetect import detect
from loguru import logger
from catalog.common import *
from catalog.game.models import GameReleaseType

View file

@ -3,7 +3,6 @@ import logging
from catalog.book.models import *
from catalog.book.utils import *
from catalog.common import *
from common.models.lang import detect_language
from .douban import *

View file

@ -2,10 +2,8 @@
Discogs.
"""
import json
import logging
import requests
from django.conf import settings
from catalog.common import *

View file

@ -37,12 +37,10 @@ class DoubanDownloader(ProxiedDownloader):
class DoubanSearcher:
@classmethod
def search(cls, cat: ItemCategory, c: str, q: str, p: int = 1):
url = f"https://search.douban.com/{c}/subject_search?search_text={q}&start={15*(p-1)}"
url = f"https://search.douban.com/{c}/subject_search?search_text={q}&start={15 * (p - 1)}"
content = DoubanDownloader(url).download().html()
j = json.loads(
content.xpath(
"//script[text()[contains(.,'window.__DATA__')]]/text()"
)[ # type:ignore
content.xpath("//script[text()[contains(.,'window.__DATA__')]]/text()")[ # type:ignore
0
]
.split("window.__DATA__ = ")[1] # type:ignore

View file

@ -7,7 +7,7 @@ from catalog.common import *
from catalog.models import *
from common.models.lang import detect_language
from .douban import DoubanDownloader, DoubanSearcher
from .douban import DoubanDownloader
def _cache_key(url):

View file

@ -1,5 +1,3 @@
import logging
import dateparser
from catalog.common import *
@ -7,7 +5,7 @@ from catalog.models import *
from common.models.lang import detect_language
from common.models.misc import uniq
from .douban import DoubanDownloader, DoubanSearcher
from .douban import DoubanDownloader
@SiteManager.register

View file

@ -1,5 +1,5 @@
import json
import logging
import re
from loguru import logger
@ -10,7 +10,7 @@ from common.models.lang import detect_language
from common.models.misc import int_
from .douban import DoubanDownloader, DoubanSearcher
from .tmdb import TMDB_TV, TMDB_TVSeason, query_tmdb_tv_episode, search_tmdb_by_imdb_id
from .tmdb import TMDB_TV, search_tmdb_by_imdb_id
@SiteManager.register

View file

@ -1,5 +1,3 @@
import logging
import dateparser
from catalog.common import *

View file

@ -1,5 +1,3 @@
import re
from django.conf import settings
from django.core.validators import URLValidator
from loguru import logger

View file

@ -1,6 +1,5 @@
import json
import logging
import re
from datetime import datetime
from django.utils.timezone import make_aware

View file

@ -1,6 +1,6 @@
import json
import logging
import re
from catalog.common import *
from catalog.movie.models import *
from catalog.tv.models import *

View file

@ -1,5 +1,3 @@
import logging
from catalog.common import *
from catalog.models import *

View file

@ -7,7 +7,6 @@ import bleach
import podcastparser
from django.conf import settings
from django.core.cache import cache
from django.core.exceptions import ValidationError
from django.core.validators import URLValidator
from django.utils.timezone import make_aware

View file

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

View file

@ -1,7 +1,5 @@
import logging
import re
import dateparser
from django.conf import settings
from catalog.common import *

View file

@ -242,9 +242,9 @@ class TMDB_TV(AbstractSite):
lambda s: {
"model": "TVSeason",
"id_type": IdType.TMDB_TVSeason,
"id_value": f'{self.id_value}-{s["season_number"]}',
"id_value": f"{self.id_value}-{s['season_number']}",
"title": s["name"],
"url": f'{self.url}/season/{s["season_number"]}',
"url": f"{self.url}/season/{s['season_number']}",
},
res_data["seasons"],
)
@ -359,7 +359,7 @@ class TMDB_TVSeason(AbstractSite):
pd.metadata["title"] = (
pd.metadata["title"]
if pd.metadata.get("title")
else f'Season {d["season_number"]}'
else f"Season {d['season_number']}"
)
pd.metadata["episode_number_list"] = list(
map(lambda ep: ep["episode_number"], d["episodes"])
@ -460,7 +460,7 @@ class TMDB_TVEpisode(AbstractSite):
pd.metadata["title"] = (
pd.metadata["title"]
if pd.metadata["title"]
else f'S{d["season_number"]} E{d["episode_number"]}'
else f"S{d['season_number']} E{d['episode_number']}"
)
if pd.lookup_ids.get(IdType.IMDB):

View file

@ -25,15 +25,12 @@ For now, we follow Douban convention, but keep an eye on it in case it breaks it
"""
import re
from functools import cached_property
from typing import TYPE_CHECKING, overload
from typing import TYPE_CHECKING
from auditlog.diff import ForeignKey
from auditlog.models import QuerySet
from django.db import models
from django.utils.translation import gettext_lazy as _
from typing_extensions import override
from catalog.common import (
BaseSchema,

View file

@ -128,7 +128,7 @@ class DoubanMovieTVTestCase(TestCase):
url = "https://movie.douban.com/subject/35597581/"
item = SiteManager.get_site_by_url(url).get_resource_ready().item
# disable this test to make douban data less disrupted
# self.assertEqual(item.imdb, "tt21599650")
self.assertEqual(item.imdb, "tt21599650")
class MultiTVSitesTestCase(TestCase):
@ -186,7 +186,7 @@ class MovieTVModelRecastTestCase(TestCase):
@use_local_response
def test_recast(self):
from catalog.models import Movie, TVShow
from catalog.models import Movie
url2 = "https://www.imdb.com/title/tt0436992/"
p2 = SiteManager.get_site_by_url(url2).get_resource_ready()
@ -232,10 +232,10 @@ class IMDBTestCase(TestCase):
@use_local_response
def test_get_episode_list(self):
l = IMDB.get_episode_list("tt0436992", 4)
self.assertEqual(len(l), 14)
l = IMDB.get_episode_list("tt1205438", 4)
self.assertEqual(len(l), 14)
episodes = IMDB.get_episode_list("tt0436992", 4)
self.assertEqual(len(episodes), 14)
episodes = IMDB.get_episode_list("tt1205438", 4)
self.assertEqual(len(episodes), 14)
@use_local_response
def test_tvshow(self):

View file

@ -22,12 +22,10 @@ from journal.models import (
Review,
ShelfManager,
ShelfMember,
ShelfType,
q_piece_in_home_feed_of_user,
q_piece_visible_to_user,
)
from takahe.utils import Takahe
from users.views import announcements
from .forms import *
from .models import *

View file

@ -1,4 +1,4 @@
from typing import Any, Callable, List, Optional, Tuple, Type
from typing import Any, List
from django.conf import settings
from django.db.models import QuerySet
@ -91,7 +91,7 @@ class PageNumberPagination(NinjaPageNumberPagination):
api = NinjaAPI(
auth=OAuthAccessTokenAuth(),
title=f'{settings.SITE_INFO["site_name"]} API',
title=f"{settings.SITE_INFO['site_name']} API",
version="1.0.0",
description=f"{settings.SITE_INFO['site_name']} API <hr/><a href='{settings.SITE_INFO['site_url']}'>Learn more</a>",
)

View file

@ -1,12 +1,5 @@
import json
import django.contrib.postgres.forms as postgres
from django import forms
from django.core.exceptions import ValidationError
from django.forms import ModelForm
from django.utils import formats
from django.utils.translation import gettext_lazy as _
from markdownx.fields import MarkdownxFormField
class NeoModelForm(ModelForm):

View file

@ -1,10 +1,7 @@
import random
from time import sleep
from django.core.management.base import BaseCommand
from loguru import logger
from common.models import BaseJob, JobManager
from common.models import JobManager
# @JobManager.register
# class DummyJob(BaseJob):

View file

@ -1,9 +1,6 @@
import pprint
import django_rq
from django.conf import settings
from django.core.management.base import BaseCommand
from redis import Redis
from rq import Queue
from rq.job import Job

View file

@ -1,12 +1,11 @@
import re
from functools import cached_property
from time import sleep
from typing import Iterable, Self, TypeVar
from typing import Iterable, Self
import typesense
from django.conf import settings
from loguru import logger
from ninja import Query
from typesense.collection import Collection
from typesense.exceptions import ObjectNotFound

View file

@ -1,24 +1,24 @@
"""
Language support utilities
Language support utilities
get site wide preferences:
SITE_DEFAULT_LANGUAGE
SITE_PREFERRED_LANGUAGES
SITE_PREFERRED_LOCALES
get site wide preferences:
SITE_DEFAULT_LANGUAGE
SITE_PREFERRED_LANGUAGES
SITE_PREFERRED_LOCALES
get available choices based on site wide preferences:
LANGUAGE_CHOICES
LOCALE_CHOICES
SCRIPT_CHOICES
get available choices based on site wide preferences:
LANGUAGE_CHOICES
LOCALE_CHOICES
SCRIPT_CHOICES
based on user preferences:
get_current_locales()
based on user preferences:
get_current_locales()
detect language based on text:
detect_language()
detect language based on text:
detect_language()
refereneces:
https://en.wikipedia.org/wiki/IETF_language_tag
refereneces:
https://en.wikipedia.org/wiki/IETF_language_tag
"""
import re

View file

@ -9,9 +9,7 @@ from takahe.models import Config as TakaheConfig
from takahe.models import Domain as TakaheDomain
from takahe.models import Identity as TakaheIdentity
from takahe.models import Relay as TakaheRelay
from takahe.models import User as TakaheUser
from takahe.utils import Takahe
from users.models import User
class Setup:

View file

@ -24,19 +24,26 @@
{% if site_color == 'azure' %}
<link rel="stylesheet"
href="{{ cdn_url }}/npm/@picocss/pico@2/css/pico.min.css" />
<style>
{% else %}
<link rel="stylesheet" href="{{ cdn_url }}/npm/@picocss/pico@2/css/pico.{{site_color}}.min.css" />
<style>
<link rel="stylesheet"
href="{{ cdn_url }}/npm/@picocss/pico@2/css/pico.{{ site_color }}.min.css" />
{% endif %}
<style>
:where(nav li)::before {
float: none;
content: " ";
}
</style>
<link href="{% sass_src 'scss/neodb.scss' %}" rel="stylesheet" type="text/css" />
<link href="{{ cdn_url }}/npm/@fortawesome/fontawesome-free@6.5.2/css/all.min.css" rel="stylesheet" type="text/css">
<link rel="search" type="application/opensearchdescription+xml" title="{{ site_name }}" href="{% static 'opensearch.xml' %}">
<link href="{% sass_src 'scss/neodb.scss' %}"
rel="stylesheet"
type="text/css" />
<link href="{{ cdn_url }}/npm/@fortawesome/fontawesome-free@6.5.2/css/all.min.css"
rel="stylesheet"
type="text/css">
<link rel="search"
type="application/opensearchdescription+xml"
title="{{ site_name }}"
href="{% static 'opensearch.xml' %}">
<script defer>
(function(){
const s = localStorage.getItem("user_style");
@ -59,8 +66,8 @@
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-title" content="{{ site_name }}">
{% if request.META.HTTP_HOST == site_domain %}
<style type="text/css">.hide_unless_alter_domain{display:none;}</style>
<style type="text/css">.hide_unless_alter_domain{display:none;}</style>
{% else %}
<meta name="robots" content="noindex">
<meta name="robots" content="noindex">
{% endif %}
{{ site_head|safe }}

View file

@ -1,4 +1,4 @@
from datetime import date, datetime, timedelta, timezone
from datetime import datetime
from django import template
from django.conf import settings
@ -48,16 +48,16 @@ def naturaldelta(v: datetime | None):
if d < 60:
return _("just now")
if d < 3600:
return f"{d//60}m"
return f"{d // 60}m"
if d < 86400:
return f"{d//3600}h"
return f"{d // 3600}h"
if d < 86400 * 14:
return f"{d//86400}d"
return f"{d // 86400}d"
if d < 86400 * 56:
return f"{d//86400//7}w"
return f"{d // 86400 // 7}w"
if d < 86400 * 30 * 18:
return f"{d//86400//30}mo"
return f"{d//86400//365}yr"
return f"{d // 86400 // 30}mo"
return f"{d // 86400 // 365}yr"
@register.filter(is_safe=True)

View file

@ -1,5 +1,3 @@
import re
from django import template
from django.template.defaultfilters import stringfilter
from django.utils.safestring import mark_safe
@ -31,7 +29,7 @@ def highlight(text, search):
m = None
for w in words:
if otext[i : i + len(w)] == w:
m = f"<mark>{text[i:i+len(w)]}</mark>"
m = f"<mark>{text[i : i + len(w)]}</mark>"
i += len(w)
break
if not m:

View file

@ -5,10 +5,9 @@ from typing import TYPE_CHECKING
import django_rq
from discord import SyncWebhook
from django.conf import settings
from django.conf.locale import LANG_INFO
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.core.paginator import Paginator
from django.core.signing import b62_decode, b62_encode
from django.core.signing import b62_decode
from django.http import Http404, HttpRequest, HttpResponseRedirect, QueryDict
from django.utils import timezone
from django.utils.translation import gettext as _

View file

@ -1,3 +1 @@
from django.contrib import admin
# Register your models here.

View file

@ -14,7 +14,6 @@ from .models import (
Review,
ShelfType,
Tag,
TagManager,
q_item_in_category,
)

View file

@ -9,7 +9,6 @@ class JournalConfig(AppConfig):
# load key modules in proper order, make sure class inject and signal works as expected
from catalog.models import Indexer
from . import api
from .models import Rating, Tag
Indexer.register_list_model(Tag)

View file

@ -35,7 +35,7 @@ def _fetch_remote_image(url):
# logger.info(f'remote image saved as {local_url}')
return local_url
except Exception as e:
logger.error(f"unable to fetch image", extra={"url": url, "exception": e})
logger.error("unable to fetch image", extra={"url": url, "exception": e})
return url
@ -140,7 +140,7 @@ class DoubanImporter(Task):
timestamp
- (
datetime.strptime(c[1], "%Y-%m-%d %H:%M:%S")
if type(c[1]) == str
if isinstance(c[1], str)
else c[1]
).replace(tzinfo=_tz_sh)
)
@ -161,7 +161,7 @@ class DoubanImporter(Task):
self.import_review_sheet(self.review_data[name], name)
self.message = f"豆瓣标记和评论导入完成,共处理{self.metadata['total']}篇,已存在{self.metadata['skipped']}篇,新增{self.metadata['imported']}篇。"
if len(self.metadata["failed_urls"]) > 0:
self.message += f'导入时未能处理{len(self.metadata["failed_urls"])}个网址。'
self.message += f"导入时未能处理{len(self.metadata['failed_urls'])}个网址。"
self.save()
def import_mark_sheet(self, worksheet, shelf_type, sheet_name):
@ -188,7 +188,7 @@ class DoubanImporter(Task):
comment = cells[7] if len(cells) >= 8 else None
self.metadata["processed"] += 1
try:
if type(time) == str:
if isinstance(time, str):
time = datetime.strptime(time, "%Y-%m-%d %H:%M:%S")
time = time.replace(tzinfo=_tz_sh)
except Exception:
@ -248,7 +248,7 @@ class DoubanImporter(Task):
content = cells[6]
self.metadata["processed"] += 1
if time:
if type(time) == str:
if isinstance(time, str):
time = datetime.strptime(time, "%Y-%m-%d %H:%M:%S")
time = time.replace(tzinfo=_tz_sh)
else:
@ -271,7 +271,7 @@ class DoubanImporter(Task):
def get_item_by_url(self, url):
item = None
if not url:
logger.warning(f"URL empty")
logger.warning("URL empty")
return None
try:
site = SiteManager.get_site_by_url(url)

View file

@ -75,7 +75,7 @@ class GoodreadsImporter(Task):
collection.append_item(book["book"], note=book["review"])
total += 1
collection.save()
self.message = f'Imported {total} books from Goodreads as a Collection {shelf["title"]}.'
self.message = f"Imported {total} books from Goodreads as a Collection {shelf['title']}."
elif match_profile:
uid = match_profile[1]
shelves = {
@ -103,7 +103,7 @@ class GoodreadsImporter(Task):
)
):
print(
f'Skip {shelf_type}/{book["book"]} bc it was marked {mark.shelf_type}'
f"Skip {shelf_type}/{book['book']} bc it was marked {mark.shelf_type}"
)
else:
mark.update(

View file

@ -28,13 +28,13 @@ class Command(BaseCommand):
if options["export"]:
self.process_export(options["export"])
self.stderr.write(self.style.SUCCESS(f"Done."))
self.stderr.write(self.style.SUCCESS("Done."))
def process_export(self, collection_uuid):
try:
collection = Collection.objects.get(uid=get_uuid_or_404(collection_uuid))
except Collection.DoesNotExist:
self.stderr.write(self.style.ERROR(f"Collection not found."))
self.stderr.write(self.style.ERROR("Collection not found."))
return
self.stderr.write(self.style.SUCCESS(f"Exporting {collection}"))
data = {

View file

@ -99,12 +99,12 @@ class Command(BaseCommand):
)
def integrity(self):
self.stdout.write(f"Checking deleted items with remaining journals...")
self.stdout.write("Checking deleted items with remaining journals...")
for i in Item.objects.filter(is_deleted=True):
if i.journal_exists():
self.stdout.write(f"! {i} : {i.absolute_url}?skipcheck=1")
self.stdout.write(f"Checking merged items with remaining journals...")
self.stdout.write("Checking merged items with remaining journals...")
for i in Item.objects.filter(merged_to_item__isnull=False):
if i.journal_exists():
self.stdout.write(f"! {i} : {i.absolute_url}?skipcheck=1")
@ -143,14 +143,14 @@ class Command(BaseCommand):
match action:
case "integrity":
self.integrity()
self.stdout.write(self.style.SUCCESS(f"Done."))
self.stdout.write(self.style.SUCCESS("Done."))
case "purge":
for pcls in [Content, ListMember]:
for cls in pcls.__subclasses__():
self.stdout.write(f"Cleaning up {cls}...")
cls.objects.filter(visibility=99).delete()
self.stdout.write(self.style.SUCCESS(f"Done."))
self.stdout.write(self.style.SUCCESS("Done."))
case "idx-destroy":
if yes or input(_CONFIRM).upper().startswith("Y"):

View file

@ -1,6 +1,6 @@
from auditlog.context import set_actor
from django.core.management.base import BaseCommand
from django.db.models import Count, F, Q
from django.db.models import Count
from django.utils.translation import gettext_lazy as t
from catalog.models import *

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("takahe", "0001_initial"),
("journal", "0015_use_identity_support_remote_piece"),

View file

@ -4,7 +4,6 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("journal", "0016_piecepost_piece_posts_piecepost_unique_piece_post"),
]

View file

@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("takahe", "0001_initial"),
("journal", "0017_alter_piece_options_and_more"),

View file

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("journal", "0018_shelflogentrypost_shelflogentry_posts_and_more"),
]

View file

@ -12,7 +12,6 @@ WHERE a.ctid < b.ctid
class Migration(migrations.Migration):
dependencies = [
("journal", "0019_alter_collection_edited_time_and_more"),
]

View file

@ -4,7 +4,6 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("users", "0019_task"),
("journal", "0021_pieceinteraction_pieceinteraction_unique_interaction"),

View file

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("journal", "0023_debris"),
]

View file

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("journal", "0025_pin_tags"),
]

View file

@ -33,6 +33,7 @@ from .utils import (
__all__ = [
"Collection",
"CollectionMember",
"Content",
"FeaturedCollection",
"Comment",
"JournalIndex",

View file

@ -105,8 +105,6 @@ class Collection(List):
)
def save(self, *args, **kwargs):
from takahe.utils import Takahe
if getattr(self, "catalog_item", None) is None:
self.catalog_item = CatalogCollection()
if (

View file

@ -1,5 +1,5 @@
from functools import cached_property
from typing import TYPE_CHECKING, Self
from typing import TYPE_CHECKING
import django.dispatch
from django.db import models

View file

@ -1,7 +1,6 @@
from django.contrib.contenttypes.models import ContentType
from django.db import connection, models
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from users.models import APIdentity

View file

@ -2,13 +2,10 @@ import re
from functools import cached_property
from typing import Any, override
from deepmerge import always_merger
from django.db import models
from django.utils.translation import gettext_lazy as _
from loguru import logger
from catalog.models import Item
from takahe.utils import Takahe
from .common import Content
from .renderers import render_text

View file

@ -3,8 +3,7 @@ from typing import Any
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.db.models import Avg, Count, Q
from django.utils.translation import gettext_lazy as _
from django.db.models import Avg, Count
from catalog.models import Item
from takahe.utils import Takahe

View file

@ -1,6 +1,6 @@
from datetime import datetime
from functools import cached_property
from typing import TYPE_CHECKING, Any, override
from typing import TYPE_CHECKING, Any
from django.conf import settings
from django.db import connection, models

View file

@ -1,15 +1,12 @@
import re
from datetime import timedelta
from functools import cached_property
from typing import TYPE_CHECKING
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
from django.db import connection, models
from django.db.models import Avg, Count, F, Q
from django.core.validators import RegexValidator
from django.db import models
from django.db.models import Count, F
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from catalog.collection.models import Collection as CatalogCollection
from catalog.models import Item
from users.models import APIdentity

View file

@ -1,7 +1,6 @@
from auditlog.context import set_actor
from django.db import transaction
from django.db.utils import IntegrityError
from django.utils.translation import gettext_lazy as _
from loguru import logger
from catalog.models import Item

View file

@ -1,5 +1,4 @@
from django import template
from django.template.defaultfilters import stringfilter
from django.utils.translation import ngettext
from journal.models import Collection

View file

@ -1,8 +1,6 @@
from django import template
from django.urls import reverse
from journal.models.mark import Mark
from takahe.utils import Takahe
register = template.Library()

View file

@ -32,3 +32,48 @@ from .review import ReviewFeed, review_edit, review_retrieve, user_review_list
from .search import search
from .tag import user_tag_edit, user_tag_list, user_tag_member_list
from .wrapped import WrappedShareView, WrappedView
__all__ = [
"add_to_collection",
"collection_add_featured",
"collection_append_item",
"collection_edit",
"collection_move_item",
"collection_remove_featured",
"collection_remove_item",
"collection_retrieve",
"collection_retrieve_items",
"collection_retrieve_redirect",
"collection_share",
"collection_update_item_note",
"collection_update_member_order",
"user_collection_list",
"user_liked_collection_list",
"piece_delete",
"comment",
"mark",
"mark_log",
"user_mark_list",
"wish",
"note_edit",
"piece_replies",
"post_boost",
"post_delete",
"post_like",
"post_replies",
"post_reply",
"post_unlike",
"profile",
"user_calendar_data",
"ReviewFeed",
"review_edit",
"review_retrieve",
"user_review_list",
"search",
"user_tag_edit",
"user_tag_list",
"user_tag_member_list",
"WrappedShareView",
"WrappedView",
]

View file

@ -2,7 +2,6 @@ import datetime
from django.contrib.auth.decorators import login_required
from django.core.exceptions import BadRequest, PermissionDenied
from django.core.paginator import Paginator
from django.db.models import F, Min, OuterRef, Subquery
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse

View file

@ -1,11 +1,10 @@
from datetime import datetime
from django import forms
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
from django.core.exceptions import BadRequest, PermissionDenied
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect, render
from django.shortcuts import get_object_or_404, render
from django.utils import timezone
from django.utils.dateparse import parse_datetime
from django.utils.translation import gettext as _
@ -15,8 +14,8 @@ from loguru import logger
from catalog.models import *
from common.utils import AuthedHttpRequest, get_uuid_or_404
from ..models import Comment, Mark, ShelfManager, ShelfType, TagManager
from .common import render_list, render_relogin, target_identity_required
from ..models import Comment, Mark, ShelfManager, ShelfType
from .common import render_list, render_relogin
PAGE_SIZE = 10

View file

@ -1,8 +1,8 @@
from django import forms
from django.contrib.auth.decorators import login_required
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect, render
from django.core.exceptions import BadRequest
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.utils.translation import gettext_lazy as _
from django.views.decorators.http import require_http_methods

View file

@ -1,12 +1,12 @@
from django.contrib.auth.decorators import login_required
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
from django.core.exceptions import BadRequest, PermissionDenied
from django.http import Http404
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils.translation import gettext as _
from django.views.decorators.http import require_http_methods
from common.utils import AuthedHttpRequest, get_uuid_or_404, target_identity_required
from common.utils import AuthedHttpRequest, get_uuid_or_404
from takahe.utils import Takahe
from ..forms import *

View file

@ -1,6 +1,6 @@
from django.contrib.auth.decorators import login_required
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect, render
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import redirect, render
from django.urls import reverse
from django.utils.translation import gettext as _
from django.views.decorators.http import require_http_methods

View file

@ -1,3 +1 @@
from django.contrib import admin
# Register your models here.

View file

@ -1,5 +1,3 @@
from os import link
from django.db import models

View file

@ -1,3 +1 @@
from django.test import TestCase
# Create your tests here.

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