Format files required by Jenkins lint

This commit is contained in:
2026-04-10 18:15:50 +02:00
parent ea011b2993
commit 034a804e02
9 changed files with 82 additions and 42 deletions

View File

@@ -211,7 +211,9 @@ def _get_attribute_text(product, code: str) -> str:
def _set_attribute_text(product, attribute, text: str) -> None: def _set_attribute_text(product, attribute, text: str) -> None:
ProductAttributeValue = get_model("catalogue", "ProductAttributeValue") ProductAttributeValue = get_model("catalogue", "ProductAttributeValue")
value_field = ( value_field = (
"value_richtext" if getattr(attribute, "type", "text") == "richtext" else "value_text" "value_richtext"
if getattr(attribute, "type", "text") == "richtext"
else "value_text"
) )
value, _created = ProductAttributeValue.objects.get_or_create( value, _created = ProductAttributeValue.objects.get_or_create(
product=product, product=product,
@@ -240,7 +242,9 @@ def get_idea_full_description(product) -> str:
def get_unlockable_description(product, user) -> tuple[str, bool]: def get_unlockable_description(product, user) -> tuple[str, bool]:
unlocked = user_has_unlocked_idea(user, product) unlocked = user_has_unlocked_idea(user, product)
if unlocked: if unlocked:
return get_idea_full_description(product) or get_idea_short_description(product), True return get_idea_full_description(product) or get_idea_short_description(
product
), True
return get_idea_short_description(product), False return get_idea_short_description(product), False
@@ -261,7 +265,9 @@ def user_has_unlocked_idea(user, product) -> bool:
"delayed-payment", "delayed-payment",
} }
paid_statuses = { paid_statuses = {
status.strip().lower() for status in paid_statuses if isinstance(status, str) and status.strip() status.strip().lower()
for status in paid_statuses
if isinstance(status, str) and status.strip()
} }
status_match = Line.objects.filter( status_match = Line.objects.filter(
@@ -398,7 +404,9 @@ def seed_idea_marketplace_products(
) )
if hasattr(Product, "STANDALONE") and hasattr(product, "structure"): if hasattr(Product, "STANDALONE") and hasattr(product, "structure"):
product.structure = Product.STANDALONE product.structure = Product.STANDALONE
if hasattr(product, "is_public") and not getattr(product, "is_public", False): if hasattr(product, "is_public") and not getattr(
product, "is_public", False
):
product.is_public = True product.is_public = True
product.save() product.save()
created += 1 created += 1
@@ -413,7 +421,9 @@ def seed_idea_marketplace_products(
if hasattr(product, "slug") and product.slug != slugify(item.title): if hasattr(product, "slug") and product.slug != slugify(item.title):
product.slug = slugify(item.title) product.slug = slugify(item.title)
dirty_fields.append("slug") dirty_fields.append("slug")
if hasattr(product, "is_public") and not getattr(product, "is_public", False): if hasattr(product, "is_public") and not getattr(
product, "is_public", False
):
product.is_public = True product.is_public = True
dirty_fields.append("is_public") dirty_fields.append("is_public")
if dirty_fields: if dirty_fields:
@@ -431,7 +441,9 @@ def seed_idea_marketplace_products(
demo_filter = Q() demo_filter = Q()
for marker in DEMO_MARKERS: for marker in DEMO_MARKERS:
demo_filter |= Q(title__icontains=marker) | Q(slug__icontains=marker) demo_filter |= Q(title__icontains=marker) | Q(slug__icontains=marker)
demo_queryset = Product.objects.filter(demo_filter).exclude(title__in=keep_titles) demo_queryset = Product.objects.filter(demo_filter).exclude(
title__in=keep_titles
)
# Also purge any non-canonical products lingering in the Idea Product class # Also purge any non-canonical products lingering in the Idea Product class
# or explicitly grouped under the Digital Ideas category. # or explicitly grouped under the Digital Ideas category.
non_canonical_ideas_queryset = ( non_canonical_ideas_queryset = (

View File

@@ -33,7 +33,9 @@ def get_declared_plugins() -> list[str]:
def get_declared_payment_apps(installed_apps: list[str] | None = None) -> list[str]: def get_declared_payment_apps(installed_apps: list[str] | None = None) -> list[str]:
declared_plugins = [plugin for plugin in get_declared_plugins() if "payment" in plugin.lower()] declared_plugins = [
plugin for plugin in get_declared_plugins() if "payment" in plugin.lower()
]
if declared_plugins: if declared_plugins:
return declared_plugins return declared_plugins
installed_apps = installed_apps or list(settings.INSTALLED_APPS) installed_apps = installed_apps or list(settings.INSTALLED_APPS)

View File

@@ -115,9 +115,7 @@ def _update_homepage_stream(page) -> bool:
return False return False
page.body = StreamValue(page.body.stream_block, stream_data, is_lazy=True) page.body = StreamValue(page.body.stream_block, stream_data, is_lazy=True)
page.search_description = ( page.search_description = "Idea marketplace with premium plans. Preview each strategy and unlock full implementation after purchase."
"Idea marketplace with premium plans. Preview each strategy and unlock full implementation after purchase."
)
page.save() page.save()
return True return True
@@ -131,7 +129,9 @@ def _purge_demo_pages() -> int:
| Q(search_description__icontains=marker) | Q(search_description__icontains=marker)
) )
candidate_ids = set( candidate_ids = set(
Page.objects.exclude(depth__lte=2).filter(marker_filter).values_list("id", flat=True) Page.objects.exclude(depth__lte=2)
.filter(marker_filter)
.values_list("id", flat=True)
) )
candidate_ids.update( candidate_ids.update(
Page.objects.exclude(depth__lte=2) Page.objects.exclude(depth__lte=2)

View File

@@ -73,7 +73,9 @@ class Command(BaseCommand):
top_level_products = Product.objects.filter(parent__isnull=True) top_level_products = Product.objects.filter(parent__isnull=True)
if keep_only_ideas: if keep_only_ideas:
products_to_delete = top_level_products.exclude(title__in=IDEA_PRODUCT_TITLES) products_to_delete = top_level_products.exclude(
title__in=IDEA_PRODUCT_TITLES
)
else: else:
products_to_delete = top_level_products.filter(product_filter).exclude( products_to_delete = top_level_products.filter(product_filter).exclude(
title__in=IDEA_PRODUCT_TITLES title__in=IDEA_PRODUCT_TITLES
@@ -83,13 +85,17 @@ class Command(BaseCommand):
Page.objects.live() Page.objects.live()
.public() .public()
.filter(depth__gt=2) .filter(depth__gt=2)
.filter(Q(slug__in=DEMO_PAGE_SLUGS) | _build_demo_text_filter(("title", "slug"))) .filter(
Q(slug__in=DEMO_PAGE_SLUGS) | _build_demo_text_filter(("title", "slug"))
)
) )
product_preview = list(products_to_delete.values_list("id", "title")[:30]) product_preview = list(products_to_delete.values_list("id", "title")[:30])
page_preview = list(pages_to_delete.values_list("id", "slug", "title")[:30]) page_preview = list(pages_to_delete.values_list("id", "slug", "title")[:30])
self.stdout.write(f"Products matched for deletion: {products_to_delete.count()}") self.stdout.write(
f"Products matched for deletion: {products_to_delete.count()}"
)
for item in product_preview: for item in product_preview:
self.stdout.write(f" - product#{item[0]}: {item[1]}") self.stdout.write(f" - product#{item[0]}: {item[1]}")
if products_to_delete.count() > len(product_preview): if products_to_delete.count() > len(product_preview):
@@ -102,7 +108,9 @@ class Command(BaseCommand):
self.stdout.write(" - ...") self.stdout.write(" - ...")
if dry_run: if dry_run:
self.stdout.write(self.style.WARNING("Dry run completed. No data was deleted.")) self.stdout.write(
self.style.WARNING("Dry run completed. No data was deleted.")
)
return return
deleted_products = products_to_delete.count() deleted_products = products_to_delete.count()

View File

@@ -47,8 +47,13 @@ class Command(BaseCommand):
if config_path.exists(): if config_path.exists():
with config_path.open("r", encoding="utf-8") as handle: with config_path.open("r", encoding="utf-8") as handle:
config_payload = json.load(handle) config_payload = json.load(handle)
config_plugins = [str(plugin) for plugin in config_payload.get("ocyan_plugins", [])] config_plugins = [
if any("demodata" in "".join(ch for ch in str(plugin).lower() if ch.isalnum()) for plugin in config_plugins): str(plugin) for plugin in config_payload.get("ocyan_plugins", [])
]
if any(
"demodata" in "".join(ch for ch in str(plugin).lower() if ch.isalnum())
for plugin in config_plugins
):
raise CommandError( raise CommandError(
"Demo data plugin detected in ocyan.json. Remove it before launch." "Demo data plugin detected in ocyan.json. Remove it before launch."
) )
@@ -70,7 +75,9 @@ class Command(BaseCommand):
if currency != "EUR": if currency != "EUR":
raise CommandError(f"OSCAR_DEFAULT_CURRENCY must be EUR, got '{currency}'.") raise CommandError(f"OSCAR_DEFAULT_CURRENCY must be EUR, got '{currency}'.")
product_class = ProductClass.objects.filter(name=IDEA_PRODUCT_CLASS_NAME).first() product_class = ProductClass.objects.filter(
name=IDEA_PRODUCT_CLASS_NAME
).first()
if product_class is None: if product_class is None:
raise CommandError(f"Missing ProductClass '{IDEA_PRODUCT_CLASS_NAME}'.") raise CommandError(f"Missing ProductClass '{IDEA_PRODUCT_CLASS_NAME}'.")
if product_class.requires_shipping: if product_class.requires_shipping:
@@ -93,12 +100,14 @@ class Command(BaseCommand):
found_titles = set(found_products.values_list("title", flat=True)) found_titles = set(found_products.values_list("title", flat=True))
missing_titles = sorted(expected_titles - found_titles) missing_titles = sorted(expected_titles - found_titles)
if missing_titles: if missing_titles:
raise CommandError(f"Missing seeded idea products: {', '.join(missing_titles)}.") raise CommandError(
f"Missing seeded idea products: {', '.join(missing_titles)}."
)
non_public_idea_titles = list( non_public_idea_titles = list(
found_products.filter(title__in=expected_titles, is_public=False).values_list( found_products.filter(
"title", flat=True title__in=expected_titles, is_public=False
) ).values_list("title", flat=True)
) )
if non_public_idea_titles: if non_public_idea_titles:
raise CommandError( raise CommandError(
@@ -122,9 +131,7 @@ class Command(BaseCommand):
missing_stockrecords: list[str] = [] missing_stockrecords: list[str] = []
for product in found_products.filter(title__in=expected_titles): for product in found_products.filter(title__in=expected_titles):
stockrecord = ( stockrecord = (
StockRecord.objects.filter(product=product) StockRecord.objects.filter(product=product).order_by("id").first()
.order_by("id")
.first()
) )
if stockrecord is None: if stockrecord is None:
missing_stockrecords.append(product.title) missing_stockrecords.append(product.title)
@@ -187,7 +194,9 @@ class Command(BaseCommand):
.values_list("title", "slug")[:10] .values_list("title", "slug")[:10]
) )
if live_demo_pages: if live_demo_pages:
formatted = ", ".join(f"{title} ({slug})" for title, slug in live_demo_pages) formatted = ", ".join(
f"{title} ({slug})" for title, slug in live_demo_pages
)
raise CommandError( raise CommandError(
"Demo-like pages are still live/public. Purge them before launch. " "Demo-like pages are still live/public. Purge them before launch. "
f"Examples: {formatted}" f"Examples: {formatted}"

View File

@@ -27,6 +27,7 @@ INSTALLED_APPS = [
"mandelstudio", "mandelstudio",
] + INSTALLED_APPS ] + INSTALLED_APPS
# Never allow demo-data plugins in this production project context. # Never allow demo-data plugins in this production project context.
def _is_demo_data_app(app_label: str) -> bool: def _is_demo_data_app(app_label: str) -> bool:
normalized = "".join(ch for ch in app_label.lower() if ch.isalnum()) normalized = "".join(ch for ch in app_label.lower() if ch.isalnum())

View File

@@ -7,7 +7,9 @@ from ocyan.plugin.wagtail_oscar_integration.constants import CACHE_DURATION
from ocyan.plugin.wagtail_oscar_integration.sitemap import CategorySitemap from ocyan.plugin.wagtail_oscar_integration.sitemap import CategorySitemap
from ocyan.plugin.wagtail_oscar_integration.sitemap import ProductSitemap from ocyan.plugin.wagtail_oscar_integration.sitemap import ProductSitemap
from ocyan.plugin.wagtail_oscar_integration.sitemap import ShopSitemap from ocyan.plugin.wagtail_oscar_integration.sitemap import ShopSitemap
from ocyan.plugin.wagtail_oscar_integration.sitemap import WagtailSitemap as BaseWagtailSitemap from ocyan.plugin.wagtail_oscar_integration.sitemap import (
WagtailSitemap as BaseWagtailSitemap,
)
class WagtailSitemap(BaseWagtailSitemap): class WagtailSitemap(BaseWagtailSitemap):
@@ -15,8 +17,8 @@ class WagtailSitemap(BaseWagtailSitemap):
page_ids = [] page_ids = []
for locale in Locale.objects.all(): for locale in Locale.objects.all():
translated_root_page = self.get_wagtail_site().root_page.get_translation_or_none( translated_root_page = (
locale self.get_wagtail_site().root_page.get_translation_or_none(locale)
) )
if translated_root_page is None: if translated_root_page is None:
continue continue

View File

@@ -19,7 +19,11 @@ def _fallback_locale_url(language_code: str) -> str:
def _is_translatable_page(page) -> bool: def _is_translatable_page(page) -> bool:
return page is not None and hasattr(page, "translation_key") and hasattr(page, "locale") return (
page is not None
and hasattr(page, "translation_key")
and hasattr(page, "locale")
)
def _translated_pages(page): def _translated_pages(page):
@@ -46,15 +50,16 @@ def _build_absolute_url(request, path: str | None, page=None) -> str:
@register.simple_tag @register.simple_tag
def page_language_options(page): def page_language_options(page):
labels = { labels = {
_normalize_language_code(code): label _normalize_language_code(code): label for code, label in settings.LANGUAGES
for code, label in settings.LANGUAGES
} }
if not _is_translatable_page(page): if not _is_translatable_page(page):
return [ return [
{ {
"code": _normalize_language_code(code), "code": _normalize_language_code(code),
"label": labels.get(_normalize_language_code(code), _normalize_language_code(code)), "label": labels.get(
_normalize_language_code(code), _normalize_language_code(code)
),
"url": _fallback_locale_url(code), "url": _fallback_locale_url(code),
} }
for code, _label in settings.LANGUAGES for code, _label in settings.LANGUAGES
@@ -69,7 +74,9 @@ def page_language_options(page):
{ {
"code": language_code, "code": language_code,
"label": labels.get(language_code, language_code), "label": labels.get(language_code, language_code),
"url": translated_page.url if translated_page is not None else _fallback_locale_url(language_code), "url": translated_page.url
if translated_page is not None
else _fallback_locale_url(language_code),
} }
) )
return options return options
@@ -103,7 +110,9 @@ def page_hreflang_links(context):
links.append( links.append(
{ {
"code": language_code, "code": language_code,
"url": _build_absolute_url(request, translated_page.url, translated_page), "url": _build_absolute_url(
request, translated_page.url, translated_page
),
} }
) )

View File

@@ -17,10 +17,7 @@ def localized_footer_content(context):
language_code = getattr(request, "LANGUAGE_CODE", None) language_code = getattr(request, "LANGUAGE_CODE", None)
if not language_code: if not language_code:
return None return None
return ( return LocalizedFooterContent.objects.filter(
LocalizedFooterContent.objects.filter( site=site,
site=site, locale__language_code=language_code,
locale__language_code=language_code, ).first()
)
.first()
)