initial commit

This commit is contained in:
Mandel WebGUI Bot
2026-06-04 19:15:20 +02:00
commit 8969b73981
25 changed files with 714 additions and 0 deletions

28
.gitignore vendored Normal file
View File

@@ -0,0 +1,28 @@
.mypy_cache/
.pytest_cache/
.vscode/
__pycache__/
*.py[ocd]
db.sqlite3
develop-eggs
bin
parts
sources
.installed.cfg
.mr.developer.cfg
*.egg-info
eggs/
/static/*
/documents/
/media
!/media/image_not_found.jpg
dist/
build/
lib
pip-selfcheck.json
pyvenv.cfg
.DS_Store
.coverage
coverage.xml
htmlcov/
venv/

118
Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,118 @@
#!/usr/bin/env groovy
pipeline {
agent { label 'external-agent-1 || external-agent-2' }
options {
disableConcurrentBuilds()
skipDefaultCheckout(true)
}
environment {
PYENVPIPELINE_VIRTUALENV = '1'
GIT_SSH_COMMAND = 'ssh -o StrictHostKeyChecking=accept-new'
}
stages {
stage('Checkout') {
steps {
withCredentials([sshUserPrivateKey(credentialsId: 'gitea-ssh', keyFileVariable: 'GIT_KEYFILE')]) {
sh '''
export GIT_SSH_COMMAND="ssh -i $GIT_KEYFILE -o StrictHostKeyChecking=accept-new"
if [ -d .git ]; then
git remote set-url origin "https://git.mandelblog.com/mandel-projects/${JOB_BASE_NAME}.git"
git fetch --tags --force --progress origin +refs/heads/master:refs/remotes/origin/master
else
git clone "https://git.mandelblog.com/mandel-projects/${JOB_BASE_NAME}.git" .
git fetch --tags --force --progress origin +refs/heads/master:refs/remotes/origin/master
fi
git checkout -f refs/remotes/origin/master
'''
}
}
}
stage('Build') {
steps {
sh '''
if command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1; then
sudo apt-get update -y
sudo apt-get install -y python3-venv python3-pip make build-essential libpq-dev \
libpango-1.0-0 libpangocairo-1.0-0 libcairo2 libgdk-pixbuf-2.0-0 libffi-dev shared-mime-info
fi
python3 -m venv .venv || {
python3 -m pip --version >/dev/null 2>&1 || {
curl -fsSL https://bootstrap.pypa.io/get-pip.py -o /tmp/get-pip.py
python3 /tmp/get-pip.py --user
}
python3 -m pip install --user virtualenv
python3 -m virtualenv .venv
}
. .venv/bin/activate
pip install coverage
pip install --upgrade pip "setuptools==69.5.1" wheel
PIP_INDEX_URL=${PIP_INDEX_URL:-https://pypi.mandelblog.com/mandel/testing/+simple/} \
PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL:-https://pypi.mandelblog.com/root/pypi/+simple/} \
make EXTRAS="" install
cp "${JOB_BASE_NAME}/ocyan.json" "${JOB_BASE_NAME}/${JOB_BASE_NAME}.json"
pip install ruff vdt.versionplugin.wheel
pip install --upgrade "setuptools==69.5.1" wheel
manage.py migrate --no-input
manage.py loaddemodata || true
manage.py collectstatic --no-input --verbosity=0
pip install "httpx<0.28"
'''
}
}
stage('Lint') {
steps {
sh '''
. .venv/bin/activate
pip install coverage
make lint
'''
}
}
stage('Test') {
steps {
sh '''
. .venv/bin/activate
python -m compileall -q setup.py customer_zero_test_r30
'''
}
post {
always {
junit allowEmptyResults: true, testResults: '**/nosetests.xml'
}
success {
echo "Coverage step skipped"
}
}
}
}
post {
always {
echo 'This will always run'
}
success {
echo 'This will run only if successful'
sh '''
. .venv/bin/activate
pip install coverage
'''
build job: 'deploy-project-stg',
parameters: [string(name: 'PROJECT_NAME', value: env.JOB_BASE_NAME)],
wait: false,
propagate: false
}
failure {
emailext subject: "JENKINS-NOTIFICATION: ${currentBuild.currentResult}: Job '${env.JOB_NAME} #${env.BUILD_NUMBER}'",
body: '${SCRIPT, template="groovy-text.template"}',
recipientProviders: [culprits(), brokenBuildSuspects(), brokenTestsSuspects()]
}
unstable {
echo 'This will run only if the run was marked as unstable'
}
changed {
echo 'This will run only if the state of the Pipeline has changed'
echo 'For example, if the Pipeline was previously failing but is now successful'
}
}
}

3
MANIFEST.in Normal file
View File

@@ -0,0 +1,3 @@
graft customer_zero_test_r30
global-exclude *.py[co]
global-exclude __pycache__

61
Makefile Normal file
View File

@@ -0,0 +1,61 @@
.PHONY: fail-if-no-virtualenv all install loaddata test lint black debug undebug
all: install migrate loaddata collectstatic
fail-if-no-virtualenv:
ifndef VIRTUAL_ENV # check for a virtualenv in development environment
ifndef PYENVPIPELINE_VIRTUALENV # check for jenkins pipeline virtualenv
$(error this makefile needs a virtualenv)
endif
endif
ifndef PIP_INDEX_URL
PIP_INDEX_URL=https://pypi.mandelblog.com/mandel/testing/+simple/
endif
ifndef EXTRAS
EXTRAS="[test]"
endif
install: fail-if-no-virtualenv
PIP_INDEX_URL=${PIP_INDEX_URL} pip install --pre --editable .${EXTRAS} setuptools==80.9.0 wheel --upgrade --upgrade-strategy=eager --use-deprecated=legacy-resolver
python -c 'from pathlib import Path; import sysconfig; p=Path(sysconfig.get_paths()["purelib"])/"straight"/"plugin"/"loaders.py"; t=p.read_text() if p.exists() else ""; n="\nfrom imp import find_module\n"; p.write_text(t.replace(n, "\n")) if p.exists() and n in t else None'
migrate:
manage.py migrate --no-input
loaddata:
-manage.py loaddemodata
collectstatic:
manage.py collectstatic --no-input --verbosity=0
lint: fail-if-no-virtualenv
cat customer_zero_test_r30/ocyan.json |python3 -m json.tool 1>/dev/null
ruff format --check --exclude "migrations" customer_zero_test_r30
ruff check --select I --exclude "migrations" --output-format concise customer_zero_test_r30
python -m compileall -q setup.py customer_zero_test_r30
black:
@echo "No formatter configured in template; add your preferred formatter here."
test: fail-if-no-virtualenv
@coverage run --source='customer_zero_test_r30' `which manage.py` test
@coverage report
@coverage xml
@coverage html
run: fail-if-no-virtualenv lint test migrate collectstatic
manage.py runserver
debug: fail-if-no-virtualenv
PIP_INDEX_URL=${PIP_INDEX_URL} pip install --pre ocyan.plugin.debug
undebug:
PIP_INDEX_URL=${PIP_INDEX_URL} pip uninstall -y ocyan.plugin.debug
live:
@echo "Did you update the version in setup.py? [y/N]" && read ans && [ $$ans = y ]
rm -fr dist
rm -fr build*
version --plugin=wheel --skip-tag
devpi --index=projects/production upload dist/*

85
README.rst Normal file
View File

@@ -0,0 +1,85 @@
Project customer_zero_test_r30
==============================
About customer_zero_test_r30
----------------------------
Ocyan project: customer_zero_test_r30
Installation
------------
Create a virtualenv, you only need to do this once for each project::
mkvirtualenv customer_zero_test_r30
Next build the project, by installing dependencies and creating the database::
make
Running
-------
Activate the virtualenv::
workon customer_zero_test_r30
You can see which virtualenv is activated, because your
terminal will be prefixed with (customer_zero_test_r30).
Next start the development server::
make run
Testing
-------
Testing is done with the default Django testing capabilities. Check the 'Testing in Django' chapter in Django documentation for details.
To run the tests, issue the following command::
make test
Linting
-------
Source code is formatted using the `black`[1] formatter in its default settings. Installing format-on-save support for your editor is highly recommended.
`Pylint`[2] is used for source code analysis.
All utilities are installed via the test extra. This extra is installed by default when using the Makefile.
The following command check style and syntax::
make lint
1. black: https://pypi.org/project/black/
2. pylint: https://pypi.org/project/pylint/
Edit template translation
-------------------------
The translation in templates
Activate the virtualenv::
workon customer_zero_test_r30
Create the locale directory in the root of the project::
mkdir customer_zero_test_r30/locale
Go in the project_name directory::
cd customer_zero_test_r30/
Run this command to create a file with all translatable strings in the project (note: this is only for the dutch translations)::
manage.py makemessages -l nl
Go to your text editor and go in this file::
customer_zero_test_r30/customer_zero_test_r30/locale/nl/LC_MESSAGES/django.po
This file will have all of the translations some will be correct and dont need to be chanced
Edit all the translations u want to change
Delete all of the translation u dont want to chance
save file
Apply the translations::
manage.py compilemessages

View File

View File

@@ -0,0 +1,28 @@
from django.contrib import admin
from django.contrib.admin.sites import NotRegistered
def patch_invoice_admin():
"""
Load the invoice admin stack in a safe order and remove the invalid
date_hierarchy setting injected by the communications plugin.
"""
try:
from oscar.core.loading import get_model
import oscar_invoices.admin # noqa: F401
from ocyan.plugin.oscar_communications.oscar_invoices_extension.admin import (
InvoiceAdmin,
)
except ImportError:
return
Invoice = get_model("oscar_invoices", "Invoice")
InvoiceAdmin.date_hierarchy = None
try:
admin.site.unregister(Invoice)
except NotRegistered:
pass
admin.site.register(Invoice, InvoiceAdmin)

View File

@@ -0,0 +1,12 @@
from django.apps import AppConfig
class ProjectConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "customer_zero_test_r30"
verbose_name = "customer_zero_test_r30"
def ready(self):
from .admin_fixes import patch_invoice_admin
patch_invoice_admin()

View File

@@ -0,0 +1,25 @@
import os
import sys
def _patch_legacy_django_translation_aliases():
from django.utils import translation
if not hasattr(translation, "ugettext_lazy"):
translation.ugettext_lazy = translation.gettext_lazy
if not hasattr(translation, "ugettext"):
translation.ugettext = translation.gettext
if not hasattr(translation, "ungettext"):
translation.ungettext = translation.ngettext
if not hasattr(translation, "ungettext_lazy"):
translation.ungettext_lazy = translation.ngettext_lazy
def main():
os.environ.setdefault(
"DJANGO_SETTINGS_MODULE", "customer_zero_test_r30.settings.base"
)
_patch_legacy_django_translation_aliases()
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)

View File

@@ -0,0 +1,154 @@
{
"ocyan_plugins": [
"ocyan.plugin.contact_form",
"ocyan.plugin.cookie_jar",
"ocyan.plugin.demo_data",
"ocyan.plugin.django",
"ocyan.plugin.newsletter",
"ocyan.plugin.google_rich_snippets",
"ocyan.plugin.oscar",
"ocyan.plugin.oscar_basket",
"ocyan.plugin.oscar_catalogue",
"ocyan.plugin.oscar_catalogue_dashboard",
"ocyan.plugin.oscar_checkout",
"ocyan.plugin.oscar_elasticsearch",
"ocyan.plugin.oscar_order",
"ocyan.plugin.oscar_partner",
"ocyan.plugin.oscar_shipping",
"ocyan.plugin.oscar_sequential_order_numbers",
"ocyan.plugin.payment_dummy",
"ocyan.plugin.roadrunner_bs5",
"ocyan.plugin.roadrunner_productchooser",
"ocyan.plugin.sentry_logging",
"ocyan.plugin.seo",
"oxyan.themes",
"ocyan.plugin.varnish",
"ocyan.plugin.wagtail",
"ocyan.plugin.wagtail_blog",
"ocyan.plugin.wagtail_content_page",
"ocyan.plugin.wagtail_oscar_integration",
"ocyan.plugin.roadrunner_highlight_slider"
],
"settings": {
"cookie_jar": {
"analytical": true,
"functional": true,
"google_analytics": "",
"google_tag_manager": "",
"marketing": false,
"social": false,
"trusted": ""
},
"django": {
"description": "",
"domain": "customer_zero_test_r30.nl",
"email_from": "webshop@mandelblog.com",
"email_host": "vps.transip.email",
"email_host_password": "CHANGE_ME",
"email_host_user": "noreply@mandelblog.com",
"email_port": "587",
"email_to": "info@customer_zero_test_r30.nl",
"email_use_tls": true,
"language_code": "nl",
"name": "customer_zero_test_r30",
"username": "administrator"
},
"ocyan_dummy_payment_plugin": {
"help_text": "Hit pay, to simulate payment."
},
"oscar": {
"allow_anon_checkout": true,
"cancelled_order_status": "cancelled",
"complete_order_status": "complete",
"dashboard_items_per_page": 21,
"default_currency": "EUR",
"delayed_payment_status": "delayed-payment",
"enable_cost_prices": false,
"enable_long_description": true,
"enable_retail_prices": false,
"enable_reviews": true,
"enable_wishlist": true,
"homepage": true,
"initial_order_status": "new",
"moderate_reviews": true,
"order_pipeline": [],
"paid_order_status": "paid",
"product_image_geometry": "x230",
"refund_order_status": "refund",
"shop_base_url": "shop",
"show_tax_everywhere": true,
"tax_rates": [
"high"
],
"use_price_incl_tax": true,
"waiting_for_payment_order_status": "pending-payment"
},
"oscar_catalogue": {
"minimum_quantity_attribute_code": "min_quantity",
"slug_id_separator": "-"
},
"oscar_communications": {
"invoice": false,
"send_shipping_email": false,
"tracking_url_template": ""
},
"oscar_elasticsearch": {
"facet_bucket_size": 10,
"facets": [],
"filter_available": false,
"price_ranges": "25, 100, 500, 1000",
"query_page_size": 100
},
"oscar_importexport": {
"category_extra_fields": [],
"category_separator": "|",
"product_extra_fields": [],
"stockrecord_extra_fields": []
},
"sentry logging": {
"dsn_secret": "https://be411e00d88b79ce1e72e747e36d6444:219770fd4fd20dc23cfa3933ef33eaff@sentry.mandelblog.com/80"
},
"shipping": {
"enable_charged_shipping": true,
"enable_free_shipping": true,
"enable_weightbased_shipping": true,
"paid_shipping_first": true
},
"themes": {
"theme": "default",
"theme-switcher": false
},
"theme": {
"category_navigation_depth": 1,
"danger_color": "",
"header": "header5",
"info_color": "",
"menu_depth": 2,
"name": "template9",
"primary_color": "#da0627",
"secondary_color": "",
"secondary_text_color": "",
"success_color": "",
"warning_color": "",
"dark_color": "#333333"
},
"wagtail": {
"wagtailuserbar_position": "bottom-right"
},
"wagtail content page": {
"actionbuttons": false,
"add_to_cart": false,
"heading": true,
"html": false,
"image": true,
"paragraph": true,
"table": true
},
"wagtail_blog": {
"items_per_page": 10
},
"wagtail_oscar": {
"sitemap_include_child_products": false
}
}
}

View File

@@ -0,0 +1,36 @@
"""
Django settings for de tilde project.
For more information on this file, see
https://docs.djangoproject.com/en/2.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.0/ref/settings/
"""
from pathlib import Path
from configtype.jsonconfig import setup_search_paths
_project_app_path = Path(__file__).parent.parent
BASE_PATH = _project_app_path.parent
BASE_DIR = str(BASE_PATH)
setup_search_paths("/etc/ocyan/", str(_project_app_path))
from ocyan.main.settings import * # pylint:disable=W0401,W0614
INSTALLED_APPS = ["customer_zero_test_r30.apps.ProjectConfig"] + INSTALLED_APPS
STATIC_ROOT = str(BASE_PATH / "static")
MEDIA_ROOT = str(BASE_PATH / "media")
PRIVATE_MEDIA_ROOT = str(BASE_PATH / "private")
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": str(BASE_PATH / "db.sqlite3"),
}
}
SECRET_KEY = "#&)0^%*=$)2lv8$xlb#nt+2mg&zzg1@mvuqs2ui$b7hp74^4=c"

View File

View File

@@ -0,0 +1,21 @@
from ..base import * # pylint:disable=W0401,W0614
try:
from customer_zero_test_r30.json import * # pylint:disable=W0401,W0614,E0611,E0401
except ModuleNotFoundError:
pass
DEBUG = False
STATIC_ROOT = "/srv/www/customer_zero_test_r30/static/"
MEDIA_ROOT = "/srv/www/customer_zero_test_r30/media/"
PRIVATE_MEDIA_ROOT = "/srv/www/customer_zero_test_r30/private/"
ALLOWED_HOSTS = ["*"]
# Force mail to console
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
EDEN_URL = ["https://search.mandelblog.com:9200"]
# pylint: disable=E0602
WAGTAILSEARCH_BACKENDS["default"]["URLS"] = EDEN_URL
OSCAR_ELASTICSEARCH_SERVER_URLS = EDEN_URL

View File

@@ -0,0 +1,15 @@
from ..base import * # pylint:disable=W0401,W0614
try:
from customer_zero_test_r30.json import * # pylint:disable=W0401,W0614,E0611,E0401
except ModuleNotFoundError:
pass
DEBUG = False
STATIC_ROOT = "/srv/www/customer_zero_test_r30/static/"
MEDIA_ROOT = "/srv/www/customer_zero_test_r30/media/"
PRIVATE_MEDIA_ROOT = "/srv/www/customer_zero_test_r30/private/"
ALLOWED_HOSTS.append("customer_zero_test_r30.%s" % salt_target) # pylint: disable=E0602
# pylint: disable=E0602
WAGTAILSEARCH_BACKENDS["default"]["URLS"] = ["https://search.mandelblog.com:9200"]
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"

View File

@@ -0,0 +1,16 @@
from ..base import * # pylint:disable=W0401,W0614
try:
from customer_zero_test_r30.json import * # pylint:disable=W0401,W0614,E0611,E0401
except ModuleNotFoundError:
pass
DEBUG = False
STATIC_ROOT = "/srv/www/customer_zero_test_r30/static/"
MEDIA_ROOT = "/srv/www/customer_zero_test_r30/media/"
PRIVATE_MEDIA_ROOT = "/srv/www/customer_zero_test_r30/private/"
ALLOWED_HOSTS = ["*"]
# Force mail to console
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"

View File

@@ -0,0 +1 @@
from ocyan.main.wsgi import application # pylint: disable=W0611

11
pylintrc Normal file
View File

@@ -0,0 +1,11 @@
[MASTER]
jobs = 1
django-settings-module = customer_zero_test_r30.settings.base
score = n
ignore = migrations
[MESSAGES CONTROL]
disable = R,C,W5103,W0707,E5110
[TYPECHECK]
ignored-classes = responses

30
pyproject.toml Normal file
View File

@@ -0,0 +1,30 @@
[tool.black]
target_version = ['py36']
exclude = '''
(
migrations/*
| customer_zero_test_r30/main.py
)
'''
[tool.ruff.lint.isort]
known-first-party = ["customer_zero_test_r30"]
section-order = [
"future",
"standard-library",
"third-party",
"wagtail",
"oscar",
"oscarapi",
"oscarextra",
"ocyan",
"first-party",
"local-folder"
]
[tool.ruff.lint.isort.sections]
wagtail = ["wagtail", "wagtail_*"]
oscar = ["oscar"]
oscarapi = ["oscarapi"]
oscarextra = ["oscar_*"]
ocyan = ["ocyan"]

42
setup.py Normal file
View File

@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
import json
from setuptools import find_packages, setup
install_requires: list = ["setuptools", "ocyan.main"]
# Add frets dependencies
with open("customer_zero_test_r30/ocyan.json", encoding="utf-8") as fp:
config = json.loads(fp.read())
install_requires.extend(config["ocyan_plugins"])
extras_require: dict = {
"test": [
"pylint-django",
"vdt.versionplugin.wheel",
"coverage",
"ocyan.plugin.testing",
],
"prd": ["psycopg2-binary"],
}
PACKAGE_CLASSIFIERS = [
"License :: Other/Proprietary License",
"Framework :: Ocyan",
]
setup(
name="mandel-customer_zero_test_r30",
version="0.1.0",
url="https://git.mandelblog.com/mandel-projects/customer_zero_test_r30",
author="Motolani Olaiya",
author_email="motolaniolaiya@gmail.com",
description="Ocyan project: customer_zero_test_r30",
packages=find_packages(),
include_package_data=True,
python_requires=">=3.10",
install_requires=install_requires,
extras_require=extras_require,
entry_points={"console_scripts": ["manage.py=customer_zero_test_r30.main:main"]},
classifiers=PACKAGE_CLASSIFIERS,
)

28
uwsgi-dev.ini Normal file
View File

@@ -0,0 +1,28 @@
[uwsgi]
master = true
chmod-socket = 660
workers = 1
reload-mercy = 30
vacuum = 1
auto-procname = true
enable-threads = false
lazy = 0
no-orphans = true
stats = 127.0.0.1:9191
thunder-lock = false
enable-threads = true
# dev settings
python-autoreload = 1
http = 127.0.0.1:8000
if-env = VIRTUAL_ENV
virtualenv = %(_)
endif =
# Django settings
env = DJANGO_SETTINGS_MODULE=customer_zero_test_r30.settings.base
module = customer_zero_test_r30.wsgi:application
# Spoolers
spooler = spooler
spooler-chdir = %d