Initial code dump
This is the initial code dump from Janik. I obtained express permission to license it under MIT, see the next commit.
This commit is contained in:
commit
9e0b8e5699
165
.gitignore
vendored
Normal file
165
.gitignore
vendored
Normal file
|
@ -0,0 +1,165 @@
|
|||
.direnv/
|
||||
result*
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm-project.org/#use-with-ide
|
||||
.pdm.toml
|
||||
.pdm-python
|
||||
.pdm-build/
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
76
0001-django-htmx-init-at-1.19.0.patch
Normal file
76
0001-django-htmx-init-at-1.19.0.patch
Normal file
|
@ -0,0 +1,76 @@
|
|||
From 572164ab51e22f82f4990a69988f09ae23743727 Mon Sep 17 00:00:00 2001
|
||||
From: "Janik H." <janik@aq0.de>
|
||||
Date: Tue, 17 Sep 2024 17:58:36 +0200
|
||||
Subject: [PATCH] django-htmx: init at 1.19.0
|
||||
|
||||
Change-Id: I67aed9c0ccfc26e06687e4c5e8c01b65b68a6c80
|
||||
---
|
||||
.../python-modules/django-htmx/default.nix | 42 +++++++++++++++++++
|
||||
pkgs/top-level/python-packages.nix | 2 +
|
||||
2 files changed, 44 insertions(+)
|
||||
create mode 100644 pkgs/development/python-modules/django-htmx/default.nix
|
||||
|
||||
diff --git a/pkgs/development/python-modules/django-htmx/default.nix b/pkgs/development/python-modules/django-htmx/default.nix
|
||||
new file mode 100644
|
||||
index 000000000000..24569bfc60c2
|
||||
--- /dev/null
|
||||
+++ b/pkgs/development/python-modules/django-htmx/default.nix
|
||||
@@ -0,0 +1,42 @@
|
||||
+{
|
||||
+ lib,
|
||||
+ buildPythonPackage,
|
||||
+ django,
|
||||
+ fetchFromGitHub,
|
||||
+ asgiref,
|
||||
+ setuptools,
|
||||
+ pythonOlder,
|
||||
+}:
|
||||
+
|
||||
+buildPythonPackage rec {
|
||||
+ pname = "django-htmx";
|
||||
+ version = "1.19.0";
|
||||
+ pyproject = true;
|
||||
+
|
||||
+ disabled = pythonOlder "3.8";
|
||||
+ doCheck = false;
|
||||
+
|
||||
+ src = fetchFromGitHub {
|
||||
+ owner = "adamchainz";
|
||||
+ repo = "django-htmx";
|
||||
+ rev = "refs/tags/${version}";
|
||||
+ hash = "sha256-nSutErUkFafKjBswhC+Lrn39MgCbCrzttAx1a+qt1so=";
|
||||
+ };
|
||||
+
|
||||
+ build-system = [ setuptools ];
|
||||
+
|
||||
+ dependencies = [
|
||||
+ asgiref
|
||||
+ django
|
||||
+ ];
|
||||
+
|
||||
+ pythonImportsCheck = [ "django_htmx" ];
|
||||
+
|
||||
+ meta = with lib; {
|
||||
+ description = "Some tools to make it easier to use htmx in your Django projects";
|
||||
+ homepage = "https://django-htmx.readthedocs.io/en/latest";
|
||||
+ changelog = "https://github.com/adamchainz/django-htmx/blob/${version}/docs/changelog.rst";
|
||||
+ license = licenses.bsd3;
|
||||
+ maintainers = with maintainers; [ derdennisop ];
|
||||
+ };
|
||||
+}
|
||||
diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix
|
||||
index 6e673f7f6a83..b5de543ef02e 100644
|
||||
--- a/pkgs/top-level/python-packages.nix
|
||||
+++ b/pkgs/top-level/python-packages.nix
|
||||
@@ -3371,6 +3371,8 @@ self: super: with self; {
|
||||
|
||||
django-hijack = callPackage ../development/python-modules/django-hijack { };
|
||||
|
||||
+ django-htmx = callPackage ../development/python-modules/django-htmx { };
|
||||
+
|
||||
django-i18nfield = callPackage ../development/python-modules/django-i18nfield { };
|
||||
|
||||
django-import-export = callPackage ../development/python-modules/django-import-export { };
|
||||
--
|
||||
2.46.0
|
||||
|
66
default.nix
Normal file
66
default.nix
Normal file
|
@ -0,0 +1,66 @@
|
|||
let
|
||||
pins = import ./npins;
|
||||
in {
|
||||
pkgs ? let
|
||||
rawPkgs = import pins.nixpkgs { };
|
||||
patchedNixpkgs = rawPkgs.applyPatches {
|
||||
name = "nixpkgs";
|
||||
src = pins.nixpkgs;
|
||||
patches = [
|
||||
(rawPkgs.fetchpatch {
|
||||
name = "python3Packages.django-simple-history: change to pyproject";
|
||||
url = "https://cl.forkos.org/changes/nixpkgs~203/revisions/1/patch?download";
|
||||
hash = "sha256-lR6hW+yJcmCyKafZU9c/XSUE1nwvjdq94I254lAZLTE=";
|
||||
decode = "base64 -d";
|
||||
})
|
||||
./0001-django-htmx-init-at-1.19.0.patch
|
||||
];
|
||||
};
|
||||
in import patchedNixpkgs { }
|
||||
}: rec {
|
||||
shell = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
npins
|
||||
gitFull
|
||||
pdm
|
||||
sqlite-interactive
|
||||
forkosIssueTracker
|
||||
];
|
||||
};
|
||||
htmx = pkgs.fetchurl {
|
||||
url = "https://unpkg.com/browse/htmx.org@1.9.12/dist/htmx.min.js";
|
||||
hash = "sha256-ruX9vUDsKIabkzupk4YAyEbSEk37QyOHjNneN9eyc4g=";
|
||||
};
|
||||
forkosIssueTracker = pkgs.python3.pkgs.buildPythonApplication {
|
||||
pname = "forkosissuetracker";
|
||||
version = "0.1.0";
|
||||
pyproject = true;
|
||||
|
||||
src = ./.;
|
||||
|
||||
disabled = pkgs.python3.pkgs.pythonOlder "3.12";
|
||||
|
||||
nativeBuildInputs = with pkgs.python3.pkgs; [ setuptools ];
|
||||
# nativeCheckInputs = with pkgs.python3.pkgs; [ pytestCheckHook ];
|
||||
|
||||
propagatedBuildInputs = with pkgs.python3.pkgs; [
|
||||
django_4
|
||||
djangorestframework
|
||||
social-auth-core
|
||||
social-auth-app-django
|
||||
django-simple-history
|
||||
django-htmx
|
||||
];
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/opt/forkosissuetracker
|
||||
cp -r . $out/opt/forkosissuetracker
|
||||
chmod +x $out/opt/forkosissuetracker/forkosissuetracker/manage.py
|
||||
makeWrapper $out/opt/forkosissuetracker/forkosissuetracker/manage.py $out/bin/forkosissuetracker \
|
||||
--prefix PYTHONPATH : "$PYTHONPATH"
|
||||
'';
|
||||
|
||||
|
||||
# pythonImportsCheck = [ "" ];
|
||||
};
|
||||
}
|
0
forkosissuetracker/forkosissuetracker/__init__.py
Normal file
0
forkosissuetracker/forkosissuetracker/__init__.py
Normal file
16
forkosissuetracker/forkosissuetracker/asgi.py
Normal file
16
forkosissuetracker/forkosissuetracker/asgi.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
"""
|
||||
ASGI config for forkosissuetracker project.
|
||||
|
||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'forkosissuetracker.settings')
|
||||
|
||||
application = get_asgi_application()
|
|
@ -0,0 +1,19 @@
|
|||
from django.core.management.base import BaseCommand, CommandError
|
||||
from issuetracker_app.models import
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Flush notifications from database"
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument("poll_ids", nargs="+", type=int)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
for poll_id in options["poll_ids"]:
|
||||
try:
|
||||
poll = Poll.objects.get(pk=poll_id)
|
||||
except Poll.DoesNotExist:
|
||||
raise CommandError('Poll "%s" does not exist' % poll_id)
|
||||
|
||||
poll.opened = False
|
||||
poll.save()
|
163
forkosissuetracker/forkosissuetracker/settings.py
Normal file
163
forkosissuetracker/forkosissuetracker/settings.py
Normal file
|
@ -0,0 +1,163 @@
|
|||
"""
|
||||
Django settings for forkosissuetracker project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 5.1.1.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.1/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/5.1/ref/settings/
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = 'django-insecure-uingtjtoyh($w843$3@l8k*hwx3nep^4_fy5gtk0l)a5t(fsu1'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = [
|
||||
]
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'rest_framework',
|
||||
'social_django',
|
||||
'simple_history',
|
||||
'issuetracker_app',
|
||||
'django_htmx',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'simple_history.middleware.HistoryRequestMiddleware',
|
||||
'django_htmx.middleware.HtmxMiddleware',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'forkosissuetracker.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [
|
||||
os.path.join(BASE_DIR, 'templates'),
|
||||
],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'social_django.context_processors.backends',
|
||||
'social_django.context_processors.login_redirect',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'forkosissuetracker.wsgi.application'
|
||||
|
||||
SECURE_SSL_REDIRECT = False
|
||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': BASE_DIR / 'db.sqlite3',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/5.1/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/5.1/howto/static-files/
|
||||
|
||||
STATIC_URL = 'static/'
|
||||
STATICFILES_DIRS = [BASE_DIR / "static"]
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
|
||||
'PAGE_SIZE': 20
|
||||
}
|
||||
|
||||
|
||||
# Django Auth
|
||||
|
||||
AUTHENTICATION_BACKENDS = [
|
||||
'social_core.backends.google.GoogleOAuth2',
|
||||
'social_core.backends.github.GithubOAuth2',
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
]
|
||||
|
||||
# Social Auth
|
||||
SOCIAL_AUTH_JSONFIELD_ENABLED = True
|
||||
SOCIAL_AUTH_ADMIN_USER_SEARCH_FIELDS = ['username', 'first_name', 'email']
|
||||
SOCIAL_AUTH_LOGIN_URL = '/'
|
||||
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/home/'
|
||||
|
||||
# TODO: replace with OIDC
|
||||
SOCIAL_AUTH_GITHUB_KEY = ''
|
||||
SOCIAL_AUTH_GITHUB_SECRET = ''
|
40
forkosissuetracker/forkosissuetracker/urls.py
Normal file
40
forkosissuetracker/forkosissuetracker/urls.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
"""
|
||||
URL configuration for forkosissuetracker project.
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/5.1/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
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.urls import include, path
|
||||
from django.contrib import admin
|
||||
from rest_framework import routers
|
||||
|
||||
from forkosissuetracker.views import login, home, logout
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
|
||||
# Wire up our API using automatic URL routing.
|
||||
# Additionally, we include login URLs for the browsable API.
|
||||
urlpatterns = [
|
||||
path('', login),
|
||||
path('', include('social_django.urls', namespace='social')),
|
||||
path('home/', home),
|
||||
path('logout/', logout),
|
||||
|
||||
path('issues/', include('issuetracker_app.urls')),
|
||||
|
||||
# API
|
||||
path('api/', include(router.urls)),
|
||||
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||
|
||||
path("admin/", admin.site.urls),
|
||||
]
|
1
forkosissuetracker/forkosissuetracker/views/__init__.py
Normal file
1
forkosissuetracker/forkosissuetracker/views/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
from .misc import *
|
18
forkosissuetracker/forkosissuetracker/views/misc.py
Normal file
18
forkosissuetracker/forkosissuetracker/views/misc.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
from django.shortcuts import redirect, render
|
||||
from django.contrib.auth import logout as auth_logout
|
||||
from django.contrib.auth.decorators import login_required
|
||||
# from django.template.context import RequestContext
|
||||
|
||||
|
||||
def login(request):
|
||||
return render(request, 'login.html')
|
||||
|
||||
|
||||
@login_required(login_url='/')
|
||||
def home(request):
|
||||
return render(request, 'home.html')
|
||||
|
||||
|
||||
def logout(request):
|
||||
auth_logout(request)
|
||||
return redirect('/')
|
16
forkosissuetracker/forkosissuetracker/wsgi.py
Normal file
16
forkosissuetracker/forkosissuetracker/wsgi.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
"""
|
||||
WSGI config for forkosissuetracker project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'forkosissuetracker.settings')
|
||||
|
||||
application = get_wsgi_application()
|
0
forkosissuetracker/issuetracker_app/__init__.py
Normal file
0
forkosissuetracker/issuetracker_app/__init__.py
Normal file
5
forkosissuetracker/issuetracker_app/admin.py
Normal file
5
forkosissuetracker/issuetracker_app/admin.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
from django.contrib import admin
|
||||
from issuetracker_app.models import Comment, Issue
|
||||
|
||||
admin.site.register(Issue)
|
||||
admin.site.register(Comment)
|
6
forkosissuetracker/issuetracker_app/apps.py
Normal file
6
forkosissuetracker/issuetracker_app/apps.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class IssuetrackerAppConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'issuetracker_app'
|
7
forkosissuetracker/issuetracker_app/forms.py
Normal file
7
forkosissuetracker/issuetracker_app/forms.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
from django import forms
|
||||
from .models import Comment
|
||||
|
||||
class NewCommentForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Comment
|
||||
fields = ['body']
|
27
forkosissuetracker/issuetracker_app/models.py
Normal file
27
forkosissuetracker/issuetracker_app/models.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
from django.db import models
|
||||
from simple_history.models import HistoricalRecords
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
class Issue(models.Model):
|
||||
author = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
title = models.CharField(max_length=128)
|
||||
description = models.CharField(max_length=2048)
|
||||
last_modified = models.DateTimeField(auto_now=True)
|
||||
history = HistoricalRecords()
|
||||
|
||||
def get_absolute_url(self):
|
||||
return f"/issues/{self.id}"
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.title}"
|
||||
|
||||
class Meta:
|
||||
ordering = ["last_modified"]
|
||||
|
||||
class Comment(models.Model):
|
||||
issue = models.ForeignKey(Issue, on_delete=models.CASCADE)
|
||||
author = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
body = models.CharField(max_length=2048)
|
||||
last_modified = models.DateTimeField(auto_now=True)
|
||||
history = HistoricalRecords()
|
||||
|
27
forkosissuetracker/issuetracker_app/templates/base.html
Normal file
27
forkosissuetracker/issuetracker_app/templates/base.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- <link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css"> -->
|
||||
<title>ForkOS Issues</title>
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
{% load static %}
|
||||
<script src="{% static 'htmx.min.js' %}" defer></script>
|
||||
<div>
|
||||
<h1 onclick="location.href='{% url 'index' %}'">
|
||||
ForkOS Issues
|
||||
</h1>
|
||||
</div>
|
||||
<div>
|
||||
{% block content %}
|
||||
This content will be replaced by different html code for each page.
|
||||
{% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
20
forkosissuetracker/issuetracker_app/templates/index.html
Normal file
20
forkosissuetracker/issuetracker_app/templates/index.html
Normal file
|
@ -0,0 +1,20 @@
|
|||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
{% if object_list %}
|
||||
<h3>All our issues</h3>
|
||||
{% endif %}
|
||||
<ul>
|
||||
{% for issue in object_list %}
|
||||
<li>
|
||||
<div
|
||||
role="button"
|
||||
onclick="location.href='{% url "issue-detail" issue.id %}'">
|
||||
{{ issue.title }} | {{ issue.author }}
|
||||
</div>
|
||||
</li>
|
||||
{% empty %}
|
||||
<h4>You have no lists!</h4>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,38 @@
|
|||
<h2>comment on the issue</h2>
|
||||
<div id="comments_section">
|
||||
{% if user.is_authenticated %}
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<div class="form-group">
|
||||
{{ comment_form }}
|
||||
<button class="btn btn-info" type="submit">Add comment <i class="fas fa-comments"></i></button>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<a class="btn btn-outline-info" href="{% url 'login' %}?next={{request.path}}">Log in to add a comment!</a><br>
|
||||
{% endif %}
|
||||
|
||||
{% if comments %}
|
||||
<strong class="text-secondary">
|
||||
{{ object.number_of_comments }} Comment{{ object.number_of_comments | pluralize }}
|
||||
</strong>
|
||||
<hr>
|
||||
<ul>
|
||||
{% for comment in comments %}
|
||||
<li>
|
||||
<div>
|
||||
<span>
|
||||
<strong class="text-info">{{ comment.author }} </strong>
|
||||
<small class="text-muted">{{ comment.last_modified }}</small>
|
||||
</span>
|
||||
<p>
|
||||
{{ comment.body | safe }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<strong class="text-secondary">No comments yet...</strong>
|
||||
{% endif %}
|
||||
</div>
|
|
@ -0,0 +1,4 @@
|
|||
<form method="post">{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="Save">
|
||||
</form>
|
|
@ -0,0 +1,4 @@
|
|||
<form method="post">{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="Update">
|
||||
</form>
|
3
forkosissuetracker/issuetracker_app/tests.py
Normal file
3
forkosissuetracker/issuetracker_app/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
25
forkosissuetracker/issuetracker_app/urls.py
Normal file
25
forkosissuetracker/issuetracker_app/urls.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path("", views.ListIssueView.as_view(), name="index"),
|
||||
|
||||
# CRUD patterns for ToDoItems
|
||||
|
||||
path("add/",
|
||||
views.IssueCreate.as_view(),
|
||||
name="issue-add",
|
||||
),
|
||||
|
||||
path(
|
||||
"<int:pk>/",
|
||||
# views.IssueUpdate.as_view(),
|
||||
# name="issue-update",
|
||||
views.IssueDetail.as_view(),
|
||||
name="issue-detail",
|
||||
|
||||
),
|
||||
]
|
||||
|
51
forkosissuetracker/issuetracker_app/views.py
Normal file
51
forkosissuetracker/issuetracker_app/views.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
from django.shortcuts import render
|
||||
from django.views.generic import DetailView, ListView, CreateView, UpdateView
|
||||
from .models import Comment, Issue
|
||||
from .forms import NewCommentForm
|
||||
|
||||
class ListIssueView(ListView):
|
||||
model = Issue
|
||||
template_name = "./index.html"
|
||||
|
||||
class IssueCreate(CreateView):
|
||||
model = Issue
|
||||
fields = ["title", "description"]
|
||||
template_name = "./issue_form.html"
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
new_issue = Issue(
|
||||
title=request.POST.get('title'),
|
||||
description=request.POST.get('description'),
|
||||
author=self.request.user
|
||||
)
|
||||
new_issue.save()
|
||||
return self.get(self, request, *args, **kwargs)
|
||||
|
||||
class IssueUpdate(UpdateView):
|
||||
model = Issue
|
||||
fields = [
|
||||
"title",
|
||||
"description",
|
||||
]
|
||||
template_name = "./issue_update.html"
|
||||
|
||||
class IssueDetail(DetailView):
|
||||
model = Issue
|
||||
template_name = "./issue_detail.html"
|
||||
def get_context_data(self, **kwargs):
|
||||
data = super().get_context_data(**kwargs)
|
||||
|
||||
comments_connected = Comment.objects.filter(issue = self.get_object()).order_by('-last_modified') # todo: change last_modified to the creation date
|
||||
data['comments'] = comments_connected
|
||||
if self.request.user.is_authenticated:
|
||||
data['comment_form'] = NewCommentForm(instance=self.request.user
|
||||
)
|
||||
|
||||
return data
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
new_comment = Comment(body=request.POST.get('body'),
|
||||
author=self.request.user,
|
||||
issue=self.get_object())
|
||||
new_comment.save()
|
||||
return self.get(self, request, *args, **kwargs)
|
22
forkosissuetracker/manage.py
Executable file
22
forkosissuetracker/manage.py
Executable file
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env python
|
||||
"""Django's command-line utility for administrative tasks."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
"""Run administrative tasks."""
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'forkosissuetracker.settings')
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
) from exc
|
||||
execute_from_command_line(sys.argv)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
65
forkosissuetracker/static/htmx.min.js
vendored
Normal file
65
forkosissuetracker/static/htmx.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
forkosissuetracker/templates/home.html
Normal file
2
forkosissuetracker/templates/home.html
Normal file
|
@ -0,0 +1,2 @@
|
|||
<h1>Welcome</h1>
|
||||
<p><a href="/logout">Logout</a>
|
8
forkosissuetracker/templates/login.html
Normal file
8
forkosissuetracker/templates/login.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
{% if user and not user.is_anonymous %}
|
||||
<a>Hello, {{ user.get_full_name }}!</a>
|
||||
<br>
|
||||
<a href="/issues">Issues</a>
|
||||
<a href="/logout">Logout</a>
|
||||
{% else %}
|
||||
<a href="{% url "social:begin" "github" %}">Login with github</a>
|
||||
{% endif %}
|
80
npins/default.nix
Normal file
80
npins/default.nix
Normal file
|
@ -0,0 +1,80 @@
|
|||
# Generated by npins. Do not modify; will be overwritten regularly
|
||||
let
|
||||
data = builtins.fromJSON (builtins.readFile ./sources.json);
|
||||
version = data.version;
|
||||
|
||||
mkSource =
|
||||
spec:
|
||||
assert spec ? type;
|
||||
let
|
||||
path =
|
||||
if spec.type == "Git" then
|
||||
mkGitSource spec
|
||||
else if spec.type == "GitRelease" then
|
||||
mkGitSource spec
|
||||
else if spec.type == "PyPi" then
|
||||
mkPyPiSource spec
|
||||
else if spec.type == "Channel" then
|
||||
mkChannelSource spec
|
||||
else
|
||||
builtins.throw "Unknown source type ${spec.type}";
|
||||
in
|
||||
spec // { outPath = path; };
|
||||
|
||||
mkGitSource =
|
||||
{
|
||||
repository,
|
||||
revision,
|
||||
url ? null,
|
||||
hash,
|
||||
branch ? null,
|
||||
...
|
||||
}:
|
||||
assert repository ? type;
|
||||
# At the moment, either it is a plain git repository (which has an url), or it is a GitHub/GitLab repository
|
||||
# In the latter case, there we will always be an url to the tarball
|
||||
if url != null then
|
||||
(builtins.fetchTarball {
|
||||
inherit url;
|
||||
sha256 = hash; # FIXME: check nix version & use SRI hashes
|
||||
})
|
||||
else
|
||||
assert repository.type == "Git";
|
||||
let
|
||||
urlToName =
|
||||
url: rev:
|
||||
let
|
||||
matched = builtins.match "^.*/([^/]*)(\\.git)?$" repository.url;
|
||||
|
||||
short = builtins.substring 0 7 rev;
|
||||
|
||||
appendShort = if (builtins.match "[a-f0-9]*" rev) != null then "-${short}" else "";
|
||||
in
|
||||
"${if matched == null then "source" else builtins.head matched}${appendShort}";
|
||||
name = urlToName repository.url revision;
|
||||
in
|
||||
builtins.fetchGit {
|
||||
url = repository.url;
|
||||
rev = revision;
|
||||
inherit name;
|
||||
# hash = hash;
|
||||
};
|
||||
|
||||
mkPyPiSource =
|
||||
{ url, hash, ... }:
|
||||
builtins.fetchurl {
|
||||
inherit url;
|
||||
sha256 = hash;
|
||||
};
|
||||
|
||||
mkChannelSource =
|
||||
{ url, hash, ... }:
|
||||
builtins.fetchTarball {
|
||||
inherit url;
|
||||
sha256 = hash;
|
||||
};
|
||||
in
|
||||
if version == 3 then
|
||||
builtins.mapAttrs (_: mkSource) data.pins
|
||||
else
|
||||
throw "Unsupported format version ${toString version} in sources.json. Try running `npins upgrade`"
|
11
npins/sources.json
Normal file
11
npins/sources.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"pins": {
|
||||
"nixpkgs": {
|
||||
"type": "Channel",
|
||||
"name": "nixpkgs-unstable",
|
||||
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-24.11pre674705.b833ff01a0d6/nixexprs.tar.xz",
|
||||
"hash": "12cda9rvpgjcsxykbcg5cxjaayhibjjabv6svacjc5n5kpcbx5sf"
|
||||
}
|
||||
},
|
||||
"version": 3
|
||||
}
|
334
pdm.lock
Normal file
334
pdm.lock
Normal file
|
@ -0,0 +1,334 @@
|
|||
# This file is @generated by PDM.
|
||||
# It is not intended for manual editing.
|
||||
|
||||
[metadata]
|
||||
groups = ["default"]
|
||||
strategy = ["inherit_metadata"]
|
||||
lock_version = "4.5.0"
|
||||
content_hash = "sha256:b80ed28bd741fd3fadad5fabd000d9da282328f90a0e97dfcd010b7006299768"
|
||||
|
||||
[[metadata.targets]]
|
||||
requires_python = "==3.12.*"
|
||||
|
||||
[[package]]
|
||||
name = "asgiref"
|
||||
version = "3.8.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "ASGI specs, helper code, and adapters"
|
||||
groups = ["default"]
|
||||
dependencies = [
|
||||
"typing-extensions>=4; python_version < \"3.11\"",
|
||||
]
|
||||
files = [
|
||||
{file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"},
|
||||
{file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2024.8.30"
|
||||
requires_python = ">=3.6"
|
||||
summary = "Python package for providing Mozilla's CA Bundle."
|
||||
groups = ["default"]
|
||||
files = [
|
||||
{file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"},
|
||||
{file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cffi"
|
||||
version = "1.17.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Foreign Function Interface for Python calling C code."
|
||||
groups = ["default"]
|
||||
marker = "platform_python_implementation != \"PyPy\""
|
||||
dependencies = [
|
||||
"pycparser",
|
||||
]
|
||||
files = [
|
||||
{file = "cffi-1.17.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc"},
|
||||
{file = "cffi-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59"},
|
||||
{file = "cffi-1.17.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb"},
|
||||
{file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195"},
|
||||
{file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e"},
|
||||
{file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828"},
|
||||
{file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150"},
|
||||
{file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a"},
|
||||
{file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885"},
|
||||
{file = "cffi-1.17.0-cp312-cp312-win32.whl", hash = "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492"},
|
||||
{file = "cffi-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2"},
|
||||
{file = "cffi-1.17.0.tar.gz", hash = "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.3.2"
|
||||
requires_python = ">=3.7.0"
|
||||
summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||
groups = ["default"]
|
||||
files = [
|
||||
{file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
|
||||
{file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cryptography"
|
||||
version = "43.0.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
||||
groups = ["default"]
|
||||
dependencies = [
|
||||
"cffi>=1.12; platform_python_implementation != \"PyPy\"",
|
||||
]
|
||||
files = [
|
||||
{file = "cryptography-43.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:8385d98f6a3bf8bb2d65a73e17ed87a3ba84f6991c155691c51112075f9ffc5d"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27e613d7077ac613e399270253259d9d53872aaf657471473ebfc9a52935c062"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68aaecc4178e90719e95298515979814bda0cbada1256a4485414860bd7ab962"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:de41fd81a41e53267cb020bb3a7212861da53a7d39f863585d13ea11049cf277"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f98bf604c82c416bc829e490c700ca1553eafdf2912a91e23a79d97d9801372a"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:61ec41068b7b74268fa86e3e9e12b9f0c21fcf65434571dbb13d954bceb08042"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:014f58110f53237ace6a408b5beb6c427b64e084eb451ef25a28308270086494"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-win32.whl", hash = "sha256:2bd51274dcd59f09dd952afb696bf9c61a7a49dfc764c04dd33ef7a6b502a1e2"},
|
||||
{file = "cryptography-43.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:666ae11966643886c2987b3b721899d250855718d6d9ce41b521252a17985f4d"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac119bb76b9faa00f48128b7f5679e1d8d437365c5d26f1c2c3f0da4ce1b553d"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bbcce1a551e262dfbafb6e6252f1ae36a248e615ca44ba302df077a846a8806"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58d4e9129985185a06d849aa6df265bdd5a74ca6e1b736a77959b498e0505b85"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:d03a475165f3134f773d1388aeb19c2d25ba88b6a9733c5c590b9ff7bbfa2e0c"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:511f4273808ab590912a93ddb4e3914dfd8a388fed883361b02dea3791f292e1"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:80eda8b3e173f0f247f711eef62be51b599b5d425c429b5d4ca6a05e9e856baa"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38926c50cff6f533f8a2dae3d7f19541432610d114a70808f0926d5aaa7121e4"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-win32.whl", hash = "sha256:a575913fb06e05e6b4b814d7f7468c2c660e8bb16d8d5a1faf9b33ccc569dd47"},
|
||||
{file = "cryptography-43.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:d75601ad10b059ec832e78823b348bfa1a59f6b8d545db3a24fd44362a1564cb"},
|
||||
{file = "cryptography-43.0.1.tar.gz", hash = "sha256:203e92a75716d8cfb491dc47c79e17d0d9207ccffcbcb35f598fbe463ae3444d"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "defusedxml"
|
||||
version = "0.8.0rc2"
|
||||
requires_python = ">=3.6"
|
||||
summary = "XML bomb protection for Python stdlib modules"
|
||||
groups = ["default"]
|
||||
files = [
|
||||
{file = "defusedxml-0.8.0rc2-py2.py3-none-any.whl", hash = "sha256:1c812964311154c3bf4aaf3bc1443b31ee13530b7f255eaaa062c0553c76103d"},
|
||||
{file = "defusedxml-0.8.0rc2.tar.gz", hash = "sha256:138c7d540a78775182206c7c97fe65b246a2f40b29471e1a2f1b0da76e7a3942"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django"
|
||||
version = "5.1.1"
|
||||
requires_python = ">=3.10"
|
||||
summary = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
|
||||
groups = ["default"]
|
||||
dependencies = [
|
||||
"asgiref<4,>=3.8.1",
|
||||
"sqlparse>=0.3.1",
|
||||
"tzdata; sys_platform == \"win32\"",
|
||||
]
|
||||
files = [
|
||||
{file = "Django-5.1.1-py3-none-any.whl", hash = "sha256:71603f27dac22a6533fb38d83072eea9ddb4017fead6f67f2562a40402d61c3f"},
|
||||
{file = "Django-5.1.1.tar.gz", hash = "sha256:021ffb7fdab3d2d388bc8c7c2434eb9c1f6f4d09e6119010bbb1694dda286bc2"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django-htmx"
|
||||
version = "1.19.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Extensions for using Django with htmx."
|
||||
groups = ["default"]
|
||||
dependencies = [
|
||||
"asgiref>=3.6",
|
||||
"django>=3.2",
|
||||
]
|
||||
files = [
|
||||
{file = "django_htmx-1.19.0-py3-none-any.whl", hash = "sha256:875a642814e52278c1728842436beda2001847a493ab79fd82da3fb46ead140f"},
|
||||
{file = "django_htmx-1.19.0.tar.gz", hash = "sha256:e7e17304e78e07f96eca0affc3ce1806edfdf3538bb7cb1912452b101f3e627d"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "djangorestframework"
|
||||
version = "3.15.2"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Web APIs for Django, made easy."
|
||||
groups = ["default"]
|
||||
dependencies = [
|
||||
"backports-zoneinfo; python_version < \"3.9\"",
|
||||
"django>=4.2",
|
||||
]
|
||||
files = [
|
||||
{file = "djangorestframework-3.15.2-py3-none-any.whl", hash = "sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20"},
|
||||
{file = "djangorestframework-3.15.2.tar.gz", hash = "sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.8"
|
||||
requires_python = ">=3.6"
|
||||
summary = "Internationalized Domain Names in Applications (IDNA)"
|
||||
groups = ["default"]
|
||||
files = [
|
||||
{file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"},
|
||||
{file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oauthlib"
|
||||
version = "3.2.2"
|
||||
requires_python = ">=3.6"
|
||||
summary = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic"
|
||||
groups = ["default"]
|
||||
files = [
|
||||
{file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"},
|
||||
{file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycparser"
|
||||
version = "2.22"
|
||||
requires_python = ">=3.8"
|
||||
summary = "C parser in Python"
|
||||
groups = ["default"]
|
||||
marker = "platform_python_implementation != \"PyPy\""
|
||||
files = [
|
||||
{file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"},
|
||||
{file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyjwt"
|
||||
version = "2.9.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "JSON Web Token implementation in Python"
|
||||
groups = ["default"]
|
||||
files = [
|
||||
{file = "PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850"},
|
||||
{file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python3-openid"
|
||||
version = "3.2.0"
|
||||
summary = "OpenID support for modern servers and consumers."
|
||||
groups = ["default"]
|
||||
dependencies = [
|
||||
"defusedxml",
|
||||
]
|
||||
files = [
|
||||
{file = "python3-openid-3.2.0.tar.gz", hash = "sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf"},
|
||||
{file = "python3_openid-3.2.0-py3-none-any.whl", hash = "sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.3"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Python HTTP for Humans."
|
||||
groups = ["default"]
|
||||
dependencies = [
|
||||
"certifi>=2017.4.17",
|
||||
"charset-normalizer<4,>=2",
|
||||
"idna<4,>=2.5",
|
||||
"urllib3<3,>=1.21.1",
|
||||
]
|
||||
files = [
|
||||
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
|
||||
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests-oauthlib"
|
||||
version = "2.0.0"
|
||||
requires_python = ">=3.4"
|
||||
summary = "OAuthlib authentication support for Requests."
|
||||
groups = ["default"]
|
||||
dependencies = [
|
||||
"oauthlib>=3.0.0",
|
||||
"requests>=2.0.0",
|
||||
]
|
||||
files = [
|
||||
{file = "requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9"},
|
||||
{file = "requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "social-auth-app-django"
|
||||
version = "5.4.2"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Python Social Authentication, Django integration."
|
||||
groups = ["default"]
|
||||
dependencies = [
|
||||
"Django>=3.2",
|
||||
"social-auth-core>=4.4.1",
|
||||
]
|
||||
files = [
|
||||
{file = "social-auth-app-django-5.4.2.tar.gz", hash = "sha256:c8832c6cf13da6ad76f5613bcda2647d89ae7cfbc5217fadd13477a3406feaa8"},
|
||||
{file = "social_auth_app_django-5.4.2-py3-none-any.whl", hash = "sha256:0c041a31707921aef9a930f143183c65d8c7b364381364a50f3f7c6fcc9d62f6"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "social-auth-core"
|
||||
version = "4.5.4"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Python social authentication made simple."
|
||||
groups = ["default"]
|
||||
dependencies = [
|
||||
"PyJWT>=2.7.0",
|
||||
"cryptography>=1.4",
|
||||
"defusedxml>=0.5.0rc1",
|
||||
"oauthlib>=1.0.3",
|
||||
"python3-openid>=3.0.10",
|
||||
"requests-oauthlib>=0.6.1",
|
||||
"requests>=2.9.1",
|
||||
]
|
||||
files = [
|
||||
{file = "social-auth-core-4.5.4.tar.gz", hash = "sha256:d3dbeb0999ffd0e68aa4bd73f2ac698a18133fd11b3fc890e1366f18c8889fac"},
|
||||
{file = "social_auth_core-4.5.4-py3-none-any.whl", hash = "sha256:33cf970a623c442376f9d4a86fb187579e4438649daa5b5be993d05e74d7b2db"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlparse"
|
||||
version = "0.5.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "A non-validating SQL parser."
|
||||
groups = ["default"]
|
||||
files = [
|
||||
{file = "sqlparse-0.5.1-py3-none-any.whl", hash = "sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4"},
|
||||
{file = "sqlparse-0.5.1.tar.gz", hash = "sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tzdata"
|
||||
version = "2024.1"
|
||||
requires_python = ">=2"
|
||||
summary = "Provider of IANA time zone data"
|
||||
groups = ["default"]
|
||||
marker = "sys_platform == \"win32\""
|
||||
files = [
|
||||
{file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"},
|
||||
{file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.2.2"
|
||||
requires_python = ">=3.8"
|
||||
summary = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
groups = ["default"]
|
||||
files = [
|
||||
{file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
|
||||
{file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
|
||||
]
|
20
pyproject.toml
Normal file
20
pyproject.toml
Normal file
|
@ -0,0 +1,20 @@
|
|||
[project]
|
||||
name = "forkos-issue-tracker"
|
||||
version = "0.1.0"
|
||||
description = "Default template for PDM package"
|
||||
authors = [
|
||||
{name = "Janik H.", email = "janik@aq0.de"},
|
||||
]
|
||||
dependencies = [
|
||||
"djangorestframework>=3.15.2",
|
||||
"social-auth-core>=4.5.4",
|
||||
"social-auth-app-django>=5.4.2",
|
||||
"django-htmx>=1.19.0",
|
||||
]
|
||||
requires-python = "==3.12.*"
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
|
||||
|
||||
[tool.pdm]
|
||||
distribution = false
|
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
Loading…
Reference in a new issue