Compare commits
19 Commits
d5836d2dbc
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| d8068894bf | |||
| 8095aa76ef | |||
| 381f83af7e | |||
| a43f42b4e4 | |||
| 3359cd63ce | |||
| f425673953 | |||
| f5c04f9d58 | |||
| f6e8758541 | |||
| 7aeb92913c | |||
| 286f1cb57b | |||
| aca7042c56 | |||
| 2abad89208 | |||
| cb3af725b3 | |||
| dd5bccf708 | |||
| 2fd139de55 | |||
| 14fe0ded02 | |||
| c751602eca | |||
| f609f2adbf | |||
| b40a7d9030 |
6
.coveragerc
Normal file
6
.coveragerc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[run]
|
||||||
|
source = .
|
||||||
|
omit = */test*,*000*,*conftest.py,*apps.py,*manage.py,*__init__.py,*asgi*,*wsgi*,*admin.py,*urls.py,*settings.py
|
||||||
|
|
||||||
|
[report]
|
||||||
|
omit = */test*,*000*,*conftest.py,*apps.py,*manage.py,*__init__.py,*asgi*,*wsgi*,*admin.py,*urls.py,*settings.py
|
||||||
32
Dockerfile
Normal file
32
Dockerfile
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
RUN apt update && apt install -y nginx
|
||||||
|
|
||||||
|
RUN pip install poetry
|
||||||
|
|
||||||
|
WORKDIR /OCLettings2
|
||||||
|
|
||||||
|
COPY pyproject.toml poetry.lock ./
|
||||||
|
|
||||||
|
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
RUN poetry config virtualenvs.create false && \
|
||||||
|
poetry install --no-interaction --no-ansi --no-root && \
|
||||||
|
poetry add gunicorn
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
RUN rm -rf /var/www/html* && \
|
||||||
|
mkdir -p /run/nginx
|
||||||
|
|
||||||
|
RUN poetry run python manage.py collectstatic --noinput
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
CMD service nginx start && \
|
||||||
|
poetry run gunicorn --bind 127.0.0.1:8000 --env DJANGO_SETTINGS_MODULE=oc_lettings_site.settings oc_lettings_site.wsgi
|
||||||
|
#CMD ["poetry", "run", "gunicorn", "--bind", "0.0.0.0:8080", "--env", "DJANGO_SETTINGS_MODULE=oc_lettings_site.settings", "oc_lettings_site.wsgi"]
|
||||||
|
|
||||||
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
# Register your models here.
|
|
||||||
@@ -3,6 +3,17 @@ from django.core.validators import MaxValueValidator, MinLengthValidator
|
|||||||
|
|
||||||
|
|
||||||
class Address(models.Model):
|
class Address(models.Model):
|
||||||
|
"""
|
||||||
|
Model of details for a physical location of a property
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""
|
||||||
|
Fix the plural displayed in admin
|
||||||
|
"""
|
||||||
|
verbose_name_plural = "Addresses"
|
||||||
|
|
||||||
|
|
||||||
number = models.PositiveIntegerField(validators=[MaxValueValidator(9999)])
|
number = models.PositiveIntegerField(validators=[MaxValueValidator(9999)])
|
||||||
street = models.CharField(max_length=64)
|
street = models.CharField(max_length=64)
|
||||||
city = models.CharField(max_length=64)
|
city = models.CharField(max_length=64)
|
||||||
@@ -11,13 +22,18 @@ class Address(models.Model):
|
|||||||
country_iso_code = models.CharField(max_length=3, validators=[MinLengthValidator(3)])
|
country_iso_code = models.CharField(max_length=3, validators=[MinLengthValidator(3)])
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
""" Display object with basic address """
|
||||||
return f'{self.number} {self.street}'
|
return f'{self.number} {self.street}'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Letting(models.Model):
|
class Letting(models.Model):
|
||||||
|
"""
|
||||||
|
Model of an announce for a property to rent
|
||||||
|
"""
|
||||||
title = models.CharField(max_length=256)
|
title = models.CharField(max_length=256)
|
||||||
address = models.OneToOneField(Address, on_delete=models.CASCADE)
|
address = models.OneToOneField(Address, on_delete=models.CASCADE)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
""" display object with title """
|
||||||
return self.title
|
return self.title
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
# Create your tests here.
|
|
||||||
@@ -1,16 +1,35 @@
|
|||||||
from django.shortcuts import render
|
from django.shortcuts import render, redirect
|
||||||
from lettings.models import Letting
|
from lettings.models import Letting
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
|
"""
|
||||||
|
letting's index page. Retrieve all objects in db then give list to template
|
||||||
|
:param request; None
|
||||||
|
:return: render and display template HTML
|
||||||
|
"""
|
||||||
lettings_list = Letting.objects.all()
|
lettings_list = Letting.objects.all()
|
||||||
context = {'lettings_list': lettings_list}
|
context = {'lettings_list': lettings_list}
|
||||||
return render(request, 'lettings/index.html', context)
|
return render(request, 'lettings/index.html', context)
|
||||||
|
|
||||||
|
|
||||||
def letting(request, letting_id):
|
def letting(request, letting_id):
|
||||||
|
"""
|
||||||
|
display detail of a particular Letting object
|
||||||
|
:param request: None
|
||||||
|
:return: render and display template HTML
|
||||||
|
"""
|
||||||
|
try:
|
||||||
letting = Letting.objects.get(id=letting_id)
|
letting = Letting.objects.get(id=letting_id)
|
||||||
context = {
|
context = {
|
||||||
'title': letting.title,
|
'title': letting.title,
|
||||||
'address': letting.address,
|
'address': letting.address,
|
||||||
}
|
}
|
||||||
return render(request, 'lettings/letting.html', context)
|
return render(request, 'lettings/letting.html', context)
|
||||||
|
except ValueError:
|
||||||
|
logger.error(f"letting id : {letting_id} not found")
|
||||||
|
return redirect('lettings_index')
|
||||||
|
|||||||
22
nginx/nginx.conf
Normal file
22
nginx/nginx.conf
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
upstream django {
|
||||||
|
server 127.0.0.1:8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
location /static/ {
|
||||||
|
alias /OCLettings2/staticfiles/;
|
||||||
|
expires 30d;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://django;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Binary file not shown.
@@ -2,6 +2,7 @@ import os
|
|||||||
|
|
||||||
from django.core.asgi import get_asgi_application
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'oc_lettings_site.settings')
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE',
|
||||||
|
'oc_lettings_site.settings')
|
||||||
|
|
||||||
application = get_asgi_application()
|
application = get_asgi_application()
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
import os
|
import os
|
||||||
|
import sentry_sdk
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from dotenv import load_dotenv, dotenv_values
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
@@ -10,12 +14,12 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
|||||||
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
SECRET_KEY = 'fp$9^593hsriajg$_%=5trot9g!1qa@ew(o-1#@=&4%=hp46(s'
|
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = True
|
DEBUG = False
|
||||||
|
|
||||||
ALLOWED_HOSTS = []
|
ALLOWED_HOSTS = ["*"]
|
||||||
|
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
@@ -79,16 +83,20 @@ DATABASES = {
|
|||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
'NAME': 'django.contrib.auth.password_validation.'
|
||||||
|
'UserAttributeSimilarityValidator',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
'NAME': 'django.contrib.auth.password_validation.'
|
||||||
|
'MinimumLengthValidator',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
'NAME': 'django.contrib.auth.password_validation.'
|
||||||
|
'CommonPasswordValidator',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
'NAME': 'django.contrib.auth.password_validation.'
|
||||||
|
'NumericPasswordValidator',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -113,4 +121,11 @@ USE_TZ = True
|
|||||||
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
|
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
STATICFILES_DIRS = [BASE_DIR / "static",]
|
STATICFILES_DIRS = [BASE_DIR / "static"]
|
||||||
|
|
||||||
|
# Config Sentry
|
||||||
|
sentry_sdk.init(
|
||||||
|
dsn=os.getenv("SENTRY_URL"),
|
||||||
|
send_default_pii=True,
|
||||||
|
enable_logs=True,
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
def test_dummy():
|
|
||||||
assert 1
|
|
||||||
@@ -1,46 +1,10 @@
|
|||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from lettings.models import Letting
|
|
||||||
from profiles.models import Profile
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque molestie quam lobortis leo consectetur ullamcorper non id est. Praesent dictum, nulla eget feugiat sagittis, sem mi convallis eros,
|
|
||||||
# vitae dapibus nisi lorem dapibus sem. Maecenas pharetra purus ipsum, eget consequat ipsum lobortis quis. Phasellus eleifend ex auctor venenatis tempus.
|
|
||||||
# Aliquam vitae erat ac orci placerat luctus. Nullam elementum urna nisi, pellentesque iaculis enim cursus in. Praesent volutpat porttitor magna, non finibus neque cursus id.
|
|
||||||
def index(request):
|
def index(request):
|
||||||
|
"""
|
||||||
|
Main index of app, home page
|
||||||
|
:param request: None
|
||||||
|
:return: render and display homepage
|
||||||
|
"""
|
||||||
return render(request, 'index.html')
|
return render(request, 'index.html')
|
||||||
|
|
||||||
# Aenean leo magna, vestibulum et tincidunt fermentum, consectetur quis velit. Sed non placerat massa. Integer est nunc, pulvinar a
|
|
||||||
# tempor et, bibendum id arcu. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Cras eget scelerisque
|
|
||||||
def lettings_index(request):
|
|
||||||
lettings_list = Letting.objects.all()
|
|
||||||
context = {'lettings_list': lettings_list}
|
|
||||||
return render(request, 'lettings_index.html', context)
|
|
||||||
|
|
||||||
|
|
||||||
#Cras ultricies dignissim purus, vitae hendrerit ex varius non. In accumsan porta nisl id eleifend. Praesent dignissim, odio eu consequat pretium, purus urna vulputate arcu, vitae efficitur
|
|
||||||
# lacus justo nec purus. Aenean finibus faucibus lectus at porta. Maecenas auctor, est ut luctus congue, dui enim mattis enim, ac condimentum velit libero in magna. Suspendisse potenti. In tempus a nisi sed laoreet.
|
|
||||||
# Suspendisse porta dui eget sem accumsan interdum. Ut quis urna pellentesque justo mattis ullamcorper ac non tellus. In tristique mauris eu velit fermentum, tempus pharetra est luctus. Vivamus consequat aliquam libero, eget bibendum lorem. Sed non dolor risus. Mauris condimentum auctor elementum. Donec quis nisi ligula. Integer vehicula tincidunt enim, ac lacinia augue pulvinar sit amet.
|
|
||||||
def letting(request, letting_id):
|
|
||||||
letting = Letting.objects.get(id=letting_id)
|
|
||||||
context = {
|
|
||||||
'title': letting.title,
|
|
||||||
'address': letting.address,
|
|
||||||
}
|
|
||||||
return render(request, 'letting.html', context)
|
|
||||||
|
|
||||||
# Sed placerat quam in pulvinar commodo. Nullam laoreet consectetur ex, sed consequat libero pulvinar eget. Fusc
|
|
||||||
# faucibus, urna quis auctor pharetra, massa dolor cursus neque, quis dictum lacus d
|
|
||||||
def profiles_index(request):
|
|
||||||
profiles_list = Profile.objects.all()
|
|
||||||
context = {'profiles_list': profiles_list}
|
|
||||||
return render(request, 'profiles_index.html', context)
|
|
||||||
|
|
||||||
# Aliquam sed metus eget nisi tincidunt ornare accumsan eget lac
|
|
||||||
# laoreet neque quis, pellentesque dui. Nullam facilisis pharetra vulputate. Sed tincidunt, dolor id facilisis fringilla, eros leo tristique lacus,
|
|
||||||
# it. Nam aliquam dignissim congue. Pellentesque habitant morbi tristique senectus et netus et males
|
|
||||||
def profile(request, username):
|
|
||||||
profile = Profile.objects.get(user__username=username)
|
|
||||||
context = {'profile': profile}
|
|
||||||
return render(request, 'profile.html', context)
|
|
||||||
|
|||||||
434
poetry.lock
generated
434
poetry.lock
generated
@@ -12,9 +12,6 @@ files = [
|
|||||||
{file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"},
|
{file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
|
tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
|
||||||
|
|
||||||
@@ -49,6 +46,56 @@ docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-
|
|||||||
tests = ["attrs[tests-no-zope]", "zope.interface"]
|
tests = ["attrs[tests-no-zope]", "zope.interface"]
|
||||||
tests-no-zope = ["cloudpickle ; platform_python_implementation == \"CPython\"", "cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990) ; platform_python_implementation == \"CPython\"", "mypy (>=0.971,<0.990) ; platform_python_implementation == \"CPython\"", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version < \"3.11\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version < \"3.11\"", "pytest-xdist[psutil]", "pytest-xdist[psutil]"]
|
tests-no-zope = ["cloudpickle ; platform_python_implementation == \"CPython\"", "cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990) ; platform_python_implementation == \"CPython\"", "mypy (>=0.971,<0.990) ; platform_python_implementation == \"CPython\"", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version < \"3.11\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version < \"3.11\"", "pytest-xdist[psutil]", "pytest-xdist[psutil]"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "beautifulsoup4"
|
||||||
|
version = "4.13.5"
|
||||||
|
description = "Screen-scraping library"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7.0"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "beautifulsoup4-4.13.5-py3-none-any.whl", hash = "sha256:642085eaa22233aceadff9c69651bc51e8bf3f874fb6d7104ece2beb24b47c4a"},
|
||||||
|
{file = "beautifulsoup4-4.13.5.tar.gz", hash = "sha256:5e70131382930e7c3de33450a2f54a63d5e4b19386eab43a5b34d594268f3695"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
soupsieve = ">1.2"
|
||||||
|
typing-extensions = ">=4.0.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
cchardet = ["cchardet"]
|
||||||
|
chardet = ["chardet"]
|
||||||
|
charset-normalizer = ["charset-normalizer"]
|
||||||
|
html5lib = ["html5lib"]
|
||||||
|
lxml = ["lxml"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bs4"
|
||||||
|
version = "0.0.2"
|
||||||
|
description = "Dummy package for Beautiful Soup (beautifulsoup4)"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "bs4-0.0.2-py2.py3-none-any.whl", hash = "sha256:abf8742c0805ef7f662dce4b51cca104cffe52b835238afc169142ab9b3fbccc"},
|
||||||
|
{file = "bs4-0.0.2.tar.gz", hash = "sha256:a48685c58f50fe127722417bae83fe6badf500d54b55f7e39ffe43b798653925"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
beautifulsoup4 = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "certifi"
|
||||||
|
version = "2025.8.3"
|
||||||
|
description = "Python package for providing Mozilla's CA Bundle."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"},
|
||||||
|
{file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorama"
|
name = "colorama"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
@@ -62,6 +109,110 @@ files = [
|
|||||||
{file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
|
{file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "coverage"
|
||||||
|
version = "7.10.6"
|
||||||
|
description = "Code coverage measurement for Python"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "coverage-7.10.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:70e7bfbd57126b5554aa482691145f798d7df77489a177a6bef80de78860a356"},
|
||||||
|
{file = "coverage-7.10.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e41be6f0f19da64af13403e52f2dec38bbc2937af54df8ecef10850ff8d35301"},
|
||||||
|
{file = "coverage-7.10.6-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c61fc91ab80b23f5fddbee342d19662f3d3328173229caded831aa0bd7595460"},
|
||||||
|
{file = "coverage-7.10.6-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10356fdd33a7cc06e8051413140bbdc6f972137508a3572e3f59f805cd2832fd"},
|
||||||
|
{file = "coverage-7.10.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:80b1695cf7c5ebe7b44bf2521221b9bb8cdf69b1f24231149a7e3eb1ae5fa2fb"},
|
||||||
|
{file = "coverage-7.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2e4c33e6378b9d52d3454bd08847a8651f4ed23ddbb4a0520227bd346382bbc6"},
|
||||||
|
{file = "coverage-7.10.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c8a3ec16e34ef980a46f60dc6ad86ec60f763c3f2fa0db6d261e6e754f72e945"},
|
||||||
|
{file = "coverage-7.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7d79dabc0a56f5af990cc6da9ad1e40766e82773c075f09cc571e2076fef882e"},
|
||||||
|
{file = "coverage-7.10.6-cp310-cp310-win32.whl", hash = "sha256:86b9b59f2b16e981906e9d6383eb6446d5b46c278460ae2c36487667717eccf1"},
|
||||||
|
{file = "coverage-7.10.6-cp310-cp310-win_amd64.whl", hash = "sha256:e132b9152749bd33534e5bd8565c7576f135f157b4029b975e15ee184325f528"},
|
||||||
|
{file = "coverage-7.10.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c706db3cabb7ceef779de68270150665e710b46d56372455cd741184f3868d8f"},
|
||||||
|
{file = "coverage-7.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e0c38dc289e0508ef68ec95834cb5d2e96fdbe792eaccaa1bccac3966bbadcc"},
|
||||||
|
{file = "coverage-7.10.6-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:752a3005a1ded28f2f3a6e8787e24f28d6abe176ca64677bcd8d53d6fe2ec08a"},
|
||||||
|
{file = "coverage-7.10.6-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:689920ecfd60f992cafca4f5477d55720466ad2c7fa29bb56ac8d44a1ac2b47a"},
|
||||||
|
{file = "coverage-7.10.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec98435796d2624d6905820a42f82149ee9fc4f2d45c2c5bc5a44481cc50db62"},
|
||||||
|
{file = "coverage-7.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b37201ce4a458c7a758ecc4efa92fa8ed783c66e0fa3c42ae19fc454a0792153"},
|
||||||
|
{file = "coverage-7.10.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2904271c80898663c810a6b067920a61dd8d38341244a3605bd31ab55250dad5"},
|
||||||
|
{file = "coverage-7.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5aea98383463d6e1fa4e95416d8de66f2d0cb588774ee20ae1b28df826bcb619"},
|
||||||
|
{file = "coverage-7.10.6-cp311-cp311-win32.whl", hash = "sha256:e3fb1fa01d3598002777dd259c0c2e6d9d5e10e7222976fc8e03992f972a2cba"},
|
||||||
|
{file = "coverage-7.10.6-cp311-cp311-win_amd64.whl", hash = "sha256:f35ed9d945bece26553d5b4c8630453169672bea0050a564456eb88bdffd927e"},
|
||||||
|
{file = "coverage-7.10.6-cp311-cp311-win_arm64.whl", hash = "sha256:99e1a305c7765631d74b98bf7dbf54eeea931f975e80f115437d23848ee8c27c"},
|
||||||
|
{file = "coverage-7.10.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5b2dd6059938063a2c9fee1af729d4f2af28fd1a545e9b7652861f0d752ebcea"},
|
||||||
|
{file = "coverage-7.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:388d80e56191bf846c485c14ae2bc8898aa3124d9d35903fef7d907780477634"},
|
||||||
|
{file = "coverage-7.10.6-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:90cb5b1a4670662719591aa92d0095bb41714970c0b065b02a2610172dbf0af6"},
|
||||||
|
{file = "coverage-7.10.6-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:961834e2f2b863a0e14260a9a273aff07ff7818ab6e66d2addf5628590c628f9"},
|
||||||
|
{file = "coverage-7.10.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf9a19f5012dab774628491659646335b1928cfc931bf8d97b0d5918dd58033c"},
|
||||||
|
{file = "coverage-7.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:99c4283e2a0e147b9c9cc6bc9c96124de9419d6044837e9799763a0e29a7321a"},
|
||||||
|
{file = "coverage-7.10.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:282b1b20f45df57cc508c1e033403f02283adfb67d4c9c35a90281d81e5c52c5"},
|
||||||
|
{file = "coverage-7.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cdbe264f11afd69841bd8c0d83ca10b5b32853263ee62e6ac6a0ab63895f972"},
|
||||||
|
{file = "coverage-7.10.6-cp312-cp312-win32.whl", hash = "sha256:a517feaf3a0a3eca1ee985d8373135cfdedfbba3882a5eab4362bda7c7cf518d"},
|
||||||
|
{file = "coverage-7.10.6-cp312-cp312-win_amd64.whl", hash = "sha256:856986eadf41f52b214176d894a7de05331117f6035a28ac0016c0f63d887629"},
|
||||||
|
{file = "coverage-7.10.6-cp312-cp312-win_arm64.whl", hash = "sha256:acf36b8268785aad739443fa2780c16260ee3fa09d12b3a70f772ef100939d80"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ffea0575345e9ee0144dfe5701aa17f3ba546f8c3bb48db62ae101afb740e7d6"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:95d91d7317cde40a1c249d6b7382750b7e6d86fad9d8eaf4fa3f8f44cf171e80"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3e23dd5408fe71a356b41baa82892772a4cefcf758f2ca3383d2aa39e1b7a003"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0f3f56e4cb573755e96a16501a98bf211f100463d70275759e73f3cbc00d4f27"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:db4a1d897bbbe7339946ffa2fe60c10cc81c43fab8b062d3fcb84188688174a4"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d8fd7879082953c156d5b13c74aa6cca37f6a6f4747b39538504c3f9c63d043d"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:28395ca3f71cd103b8c116333fa9db867f3a3e1ad6a084aa3725ae002b6583bc"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:61c950fc33d29c91b9e18540e1aed7d9f6787cc870a3e4032493bbbe641d12fc"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313-win32.whl", hash = "sha256:160c00a5e6b6bdf4e5984b0ef21fc860bc94416c41b7df4d63f536d17c38902e"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313-win_amd64.whl", hash = "sha256:628055297f3e2aa181464c3808402887643405573eb3d9de060d81531fa79d32"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313-win_arm64.whl", hash = "sha256:df4ec1f8540b0bcbe26ca7dd0f541847cc8a108b35596f9f91f59f0c060bfdd2"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c9a8b7a34a4de3ed987f636f71881cd3b8339f61118b1aa311fbda12741bff0b"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8dd5af36092430c2b075cee966719898f2ae87b636cefb85a653f1d0ba5d5393"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b0353b0f0850d49ada66fdd7d0c7cdb0f86b900bb9e367024fd14a60cecc1e27"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d6b9ae13d5d3e8aeca9ca94198aa7b3ebbc5acfada557d724f2a1f03d2c0b0df"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:675824a363cc05781b1527b39dc2587b8984965834a748177ee3c37b64ffeafb"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:692d70ea725f471a547c305f0d0fc6a73480c62fb0da726370c088ab21aed282"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:851430a9a361c7a8484a36126d1d0ff8d529d97385eacc8dfdc9bfc8c2d2cbe4"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d9369a23186d189b2fc95cc08b8160ba242057e887d766864f7adf3c46b2df21"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313t-win32.whl", hash = "sha256:92be86fcb125e9bda0da7806afd29a3fd33fdf58fba5d60318399adf40bf37d0"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6b3039e2ca459a70c79523d39347d83b73f2f06af5624905eba7ec34d64d80b5"},
|
||||||
|
{file = "coverage-7.10.6-cp313-cp313t-win_arm64.whl", hash = "sha256:3fb99d0786fe17b228eab663d16bee2288e8724d26a199c29325aac4b0319b9b"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6008a021907be8c4c02f37cdc3ffb258493bdebfeaf9a839f9e71dfdc47b018e"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5e75e37f23eb144e78940b40395b42f2321951206a4f50e23cfd6e8a198d3ceb"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0f7cb359a448e043c576f0da00aa8bfd796a01b06aa610ca453d4dde09cc1034"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c68018e4fc4e14b5668f1353b41ccf4bc83ba355f0e1b3836861c6f042d89ac1"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cd4b2b0707fc55afa160cd5fc33b27ccbf75ca11d81f4ec9863d5793fc6df56a"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4cec13817a651f8804a86e4f79d815b3b28472c910e099e4d5a0e8a3b6a1d4cb"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f2a6a8e06bbda06f78739f40bfb56c45d14eb8249d0f0ea6d4b3d48e1f7c695d"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:081b98395ced0d9bcf60ada7661a0b75f36b78b9d7e39ea0790bb4ed8da14747"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314-win32.whl", hash = "sha256:6937347c5d7d069ee776b2bf4e1212f912a9f1f141a429c475e6089462fcecc5"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314-win_amd64.whl", hash = "sha256:adec1d980fa07e60b6ef865f9e5410ba760e4e1d26f60f7e5772c73b9a5b0713"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314-win_arm64.whl", hash = "sha256:a80f7aef9535442bdcf562e5a0d5a5538ce8abe6bb209cfbf170c462ac2c2a32"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:0de434f4fbbe5af4fa7989521c655c8c779afb61c53ab561b64dcee6149e4c65"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6e31b8155150c57e5ac43ccd289d079eb3f825187d7c66e755a055d2c85794c6"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:98cede73eb83c31e2118ae8d379c12e3e42736903a8afcca92a7218e1f2903b0"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f863c08f4ff6b64fa8045b1e3da480f5374779ef187f07b82e0538c68cb4ff8e"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b38261034fda87be356f2c3f42221fdb4171c3ce7658066ae449241485390d5"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e93b1476b79eae849dc3872faeb0bf7948fd9ea34869590bc16a2a00b9c82a7"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ff8a991f70f4c0cf53088abf1e3886edcc87d53004c7bb94e78650b4d3dac3b5"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ac765b026c9f33044419cbba1da913cfb82cca1b60598ac1c7a5ed6aac4621a0"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314t-win32.whl", hash = "sha256:441c357d55f4936875636ef2cfb3bee36e466dcf50df9afbd398ce79dba1ebb7"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314t-win_amd64.whl", hash = "sha256:073711de3181b2e204e4870ac83a7c4853115b42e9cd4d145f2231e12d670930"},
|
||||||
|
{file = "coverage-7.10.6-cp314-cp314t-win_arm64.whl", hash = "sha256:137921f2bac5559334ba66122b753db6dc5d1cf01eb7b64eb412bb0d064ef35b"},
|
||||||
|
{file = "coverage-7.10.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90558c35af64971d65fbd935c32010f9a2f52776103a259f1dee865fe8259352"},
|
||||||
|
{file = "coverage-7.10.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8953746d371e5695405806c46d705a3cd170b9cc2b9f93953ad838f6c1e58612"},
|
||||||
|
{file = "coverage-7.10.6-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c83f6afb480eae0313114297d29d7c295670a41c11b274e6bca0c64540c1ce7b"},
|
||||||
|
{file = "coverage-7.10.6-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7eb68d356ba0cc158ca535ce1381dbf2037fa8cb5b1ae5ddfc302e7317d04144"},
|
||||||
|
{file = "coverage-7.10.6-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5b15a87265e96307482746d86995f4bff282f14b027db75469c446da6127433b"},
|
||||||
|
{file = "coverage-7.10.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fc53ba868875bfbb66ee447d64d6413c2db91fddcfca57025a0e7ab5b07d5862"},
|
||||||
|
{file = "coverage-7.10.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:efeda443000aa23f276f4df973cb82beca682fd800bb119d19e80504ffe53ec2"},
|
||||||
|
{file = "coverage-7.10.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9702b59d582ff1e184945d8b501ffdd08d2cee38d93a2206aa5f1365ce0b8d78"},
|
||||||
|
{file = "coverage-7.10.6-cp39-cp39-win32.whl", hash = "sha256:2195f8e16ba1a44651ca684db2ea2b2d4b5345da12f07d9c22a395202a05b23c"},
|
||||||
|
{file = "coverage-7.10.6-cp39-cp39-win_amd64.whl", hash = "sha256:f32ff80e7ef6a5b5b606ea69a36e97b219cd9dc799bcf2963018a4d8f788cfbf"},
|
||||||
|
{file = "coverage-7.10.6-py3-none-any.whl", hash = "sha256:92c4ecf6bf11b2e85fd4d8204814dc26e6a19f0c9d938c207c5cb0eadfcabbe3"},
|
||||||
|
{file = "coverage-7.10.6.tar.gz", hash = "sha256:f644a3ae5933a552a29dbb9aa2f90c677a875f80ebea028e5a52a4f429044b90"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
toml = ["tomli ; python_full_version <= \"3.11.0a6\""]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django"
|
name = "django"
|
||||||
version = "3.0"
|
version = "3.0"
|
||||||
@@ -83,6 +234,31 @@ sqlparse = ">=0.2.2"
|
|||||||
argon2 = ["argon2-cffi (>=16.1.0)"]
|
argon2 = ["argon2-cffi (>=16.1.0)"]
|
||||||
bcrypt = ["bcrypt"]
|
bcrypt = ["bcrypt"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "django-pytest"
|
||||||
|
version = "0.2.0"
|
||||||
|
description = "django test runner to use py.test tests"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "django-pytest-0.2.0.tar.gz", hash = "sha256:de21f20f9e7eb941529d75078b18192506a9f6d4ae80f86fbe2f3bcac8e09d71"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dotenv"
|
||||||
|
version = "0.9.9"
|
||||||
|
description = "Deprecated package"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "dotenv-0.9.9-py2.py3-none-any.whl", hash = "sha256:29cf74a087b31dafdb5a446b6d7e11cbce8ed2741540e2339c69fbef92c94ce9"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
python-dotenv = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "entrypoints"
|
name = "entrypoints"
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
@@ -113,28 +289,6 @@ mccabe = ">=0.6.0,<0.7.0"
|
|||||||
pycodestyle = ">=2.5.0,<2.6.0"
|
pycodestyle = ">=2.5.0,<2.6.0"
|
||||||
pyflakes = ">=2.1.0,<2.2.0"
|
pyflakes = ">=2.1.0,<2.2.0"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "importlib-metadata"
|
|
||||||
version = "4.8.3"
|
|
||||||
description = "Read metadata from Python packages"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
groups = ["main"]
|
|
||||||
markers = "python_version < \"3.8\""
|
|
||||||
files = [
|
|
||||||
{file = "importlib_metadata-4.8.3-py3-none-any.whl", hash = "sha256:65a9576a5b2d58ca44d133c42a241905cc45e34d2c06fd5ba2bafa221e5d7b5e"},
|
|
||||||
{file = "importlib_metadata-4.8.3.tar.gz", hash = "sha256:766abffff765960fcc18003801f7044eb6755ffae4521c8e8ce8e83b9c9b0668"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
|
|
||||||
zipp = ">=0.5"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"]
|
|
||||||
perf = ["ipython"]
|
|
||||||
testing = ["flufl.flake8", "importlib-resources (>=1.3) ; python_version < \"3.9\"", "packaging", "pep517", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7) ; platform_python_implementation != \"PyPy\"", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy ; platform_python_implementation != \"PyPy\"", "pytest-perf (>=0.9.2)"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iniconfig"
|
name = "iniconfig"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
@@ -161,37 +315,31 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "packaging"
|
name = "packaging"
|
||||||
version = "21.3"
|
version = "25.0"
|
||||||
description = "Core utilities for Python packages"
|
description = "Core utilities for Python packages"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
|
{file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"},
|
||||||
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
|
{file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pluggy"
|
name = "pluggy"
|
||||||
version = "1.0.0"
|
version = "1.6.0"
|
||||||
description = "plugin and hook calling mechanisms for python"
|
description = "plugin and hook calling mechanisms for python"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.9"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
|
{file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"},
|
||||||
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
|
{file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["pre-commit", "tox"]
|
dev = ["pre-commit", "tox"]
|
||||||
testing = ["pytest", "pytest-benchmark"]
|
testing = ["coverage", "pytest", "pytest-benchmark"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "py"
|
name = "py"
|
||||||
@@ -229,21 +377,6 @@ files = [
|
|||||||
{file = "pyflakes-2.1.1.tar.gz", hash = "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2"},
|
{file = "pyflakes-2.1.1.tar.gz", hash = "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pyparsing"
|
|
||||||
version = "3.0.7"
|
|
||||||
description = "Python parsing module"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
groups = ["main"]
|
|
||||||
files = [
|
|
||||||
{file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"},
|
|
||||||
{file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
diagrams = ["jinja2", "railroad-diagrams"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest"
|
name = "pytest"
|
||||||
version = "7.0.1"
|
version = "7.0.1"
|
||||||
@@ -260,7 +393,6 @@ files = [
|
|||||||
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
|
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
|
||||||
attrs = ">=19.2.0"
|
attrs = ">=19.2.0"
|
||||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||||
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
|
|
||||||
iniconfig = "*"
|
iniconfig = "*"
|
||||||
packaging = "*"
|
packaging = "*"
|
||||||
pluggy = ">=0.12,<2.0"
|
pluggy = ">=0.12,<2.0"
|
||||||
@@ -270,6 +402,26 @@ tomli = ">=1.0.0"
|
|||||||
[package.extras]
|
[package.extras]
|
||||||
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
|
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pytest-cov"
|
||||||
|
version = "6.3.0"
|
||||||
|
description = "Pytest plugin for measuring coverage."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "pytest_cov-6.3.0-py3-none-any.whl", hash = "sha256:440db28156d2468cafc0415b4f8e50856a0d11faefa38f30906048fe490f1749"},
|
||||||
|
{file = "pytest_cov-6.3.0.tar.gz", hash = "sha256:35c580e7800f87ce892e687461166e1ac2bcb8fb9e13aea79032518d6e503ff2"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
coverage = {version = ">=7.5", extras = ["toml"]}
|
||||||
|
pluggy = ">=1.2"
|
||||||
|
pytest = ">=6.2.5"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest-django"
|
name = "pytest-django"
|
||||||
version = "3.9.0"
|
version = "3.9.0"
|
||||||
@@ -289,6 +441,21 @@ pytest = ">=3.6"
|
|||||||
docs = ["sphinx", "sphinx-rtd-theme"]
|
docs = ["sphinx", "sphinx-rtd-theme"]
|
||||||
testing = ["Django", "django-configurations (>=2.0)", "six"]
|
testing = ["Django", "django-configurations (>=2.0)", "six"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python-dotenv"
|
||||||
|
version = "1.1.1"
|
||||||
|
description = "Read key-value pairs from a .env file and set them as environment variables"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc"},
|
||||||
|
{file = "python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
cli = ["click (>=5.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytz"
|
name = "pytz"
|
||||||
version = "2025.2"
|
version = "2025.2"
|
||||||
@@ -301,6 +468,89 @@ files = [
|
|||||||
{file = "pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3"},
|
{file = "pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sentry-sdk"
|
||||||
|
version = "2.37.1"
|
||||||
|
description = "Python client for Sentry (https://sentry.io)"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "sentry_sdk-2.37.1-py2.py3-none-any.whl", hash = "sha256:baaaea6608ed3a639766a69ded06b254b106d32ad9d180bdbe58f3db9364592b"},
|
||||||
|
{file = "sentry_sdk-2.37.1.tar.gz", hash = "sha256:531751da91aa62a909b42a7be155b41f6bb0de9df6ae98441d23b95de2f98475"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
certifi = "*"
|
||||||
|
django = {version = ">=1.8", optional = true, markers = "extra == \"django\""}
|
||||||
|
urllib3 = ">=1.26.11"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
aiohttp = ["aiohttp (>=3.5)"]
|
||||||
|
anthropic = ["anthropic (>=0.16)"]
|
||||||
|
arq = ["arq (>=0.23)"]
|
||||||
|
asyncpg = ["asyncpg (>=0.23)"]
|
||||||
|
beam = ["apache-beam (>=2.12)"]
|
||||||
|
bottle = ["bottle (>=0.12.13)"]
|
||||||
|
celery = ["celery (>=3)"]
|
||||||
|
celery-redbeat = ["celery-redbeat (>=2)"]
|
||||||
|
chalice = ["chalice (>=1.16.0)"]
|
||||||
|
clickhouse-driver = ["clickhouse-driver (>=0.2.0)"]
|
||||||
|
django = ["django (>=1.8)"]
|
||||||
|
falcon = ["falcon (>=1.4)"]
|
||||||
|
fastapi = ["fastapi (>=0.79.0)"]
|
||||||
|
flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"]
|
||||||
|
grpcio = ["grpcio (>=1.21.1)", "protobuf (>=3.8.0)"]
|
||||||
|
http2 = ["httpcore[http2] (==1.*)"]
|
||||||
|
httpx = ["httpx (>=0.16.0)"]
|
||||||
|
huey = ["huey (>=2)"]
|
||||||
|
huggingface-hub = ["huggingface_hub (>=0.22)"]
|
||||||
|
langchain = ["langchain (>=0.0.210)"]
|
||||||
|
langgraph = ["langgraph (>=0.6.6)"]
|
||||||
|
launchdarkly = ["launchdarkly-server-sdk (>=9.8.0)"]
|
||||||
|
litestar = ["litestar (>=2.0.0)"]
|
||||||
|
loguru = ["loguru (>=0.5)"]
|
||||||
|
openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"]
|
||||||
|
openfeature = ["openfeature-sdk (>=0.7.1)"]
|
||||||
|
opentelemetry = ["opentelemetry-distro (>=0.35b0)"]
|
||||||
|
opentelemetry-experimental = ["opentelemetry-distro"]
|
||||||
|
pure-eval = ["asttokens", "executing", "pure_eval"]
|
||||||
|
pymongo = ["pymongo (>=3.1)"]
|
||||||
|
pyspark = ["pyspark (>=2.4.4)"]
|
||||||
|
quart = ["blinker (>=1.1)", "quart (>=0.16.1)"]
|
||||||
|
rq = ["rq (>=0.6)"]
|
||||||
|
sanic = ["sanic (>=0.8)"]
|
||||||
|
sqlalchemy = ["sqlalchemy (>=1.2)"]
|
||||||
|
starlette = ["starlette (>=0.19.1)"]
|
||||||
|
starlite = ["starlite (>=1.48)"]
|
||||||
|
statsig = ["statsig (>=0.55.3)"]
|
||||||
|
tornado = ["tornado (>=6)"]
|
||||||
|
unleash = ["UnleashClient (>=6.0.1)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "six"
|
||||||
|
version = "1.17.0"
|
||||||
|
description = "Python 2 and 3 compatibility utilities"
|
||||||
|
optional = false
|
||||||
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"},
|
||||||
|
{file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "soupsieve"
|
||||||
|
version = "2.8"
|
||||||
|
description = "A modern CSS selector implementation for Beautiful Soup."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c"},
|
||||||
|
{file = "soupsieve-2.8.tar.gz", hash = "sha256:e2dd4a40a628cb5f28f6d4b0db8800b8f581b65bb380b97de22ba5ca8d72572f"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlparse"
|
name = "sqlparse"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
@@ -320,47 +570,77 @@ test = ["pytest", "pytest-cov"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tomli"
|
name = "tomli"
|
||||||
version = "1.2.3"
|
version = "2.2.1"
|
||||||
description = "A lil' TOML parser"
|
description = "A lil' TOML parser"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "tomli-1.2.3-py3-none-any.whl", hash = "sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"},
|
{file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
|
||||||
{file = "tomli-1.2.3.tar.gz", hash = "sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f"},
|
{file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"},
|
||||||
|
{file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"},
|
||||||
|
{file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"},
|
||||||
|
{file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"},
|
||||||
|
{file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"},
|
||||||
|
{file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typing-extensions"
|
name = "typing-extensions"
|
||||||
version = "4.1.1"
|
version = "4.15.0"
|
||||||
description = "Backported and Experimental Type Hints for Python 3.6+"
|
description = "Backported and Experimental Type Hints for Python 3.9+"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.9"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "python_version < \"3.8\""
|
|
||||||
files = [
|
files = [
|
||||||
{file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"},
|
{file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"},
|
||||||
{file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"},
|
{file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zipp"
|
name = "urllib3"
|
||||||
version = "3.6.0"
|
version = "2.5.0"
|
||||||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.9"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "python_version < \"3.8\""
|
|
||||||
files = [
|
files = [
|
||||||
{file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"},
|
{file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"},
|
||||||
{file = "zipp-3.6.0.tar.gz", hash = "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832"},
|
{file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"]
|
brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""]
|
||||||
testing = ["func-timeout", "jaraco.itertools", "pytest (>=4.6)", "pytest-black (>=0.3.7) ; platform_python_implementation != \"PyPy\"", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy ; platform_python_implementation != \"PyPy\""]
|
h2 = ["h2 (>=4,<5)"]
|
||||||
|
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||||
|
zstd = ["zstandard (>=0.18.0)"]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.1"
|
lock-version = "2.1"
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.9, <4.0"
|
||||||
content-hash = "dc98175b1ff18844811121b4489b45c63c3890bbc11145325f802073521b7b71"
|
content-hash = "ff2e5437fe8f89479484f9df2dea16b0893c8dcee4f7641cf7af85becf2d1379"
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
# Register your models here.
|
|
||||||
@@ -3,9 +3,11 @@ from django.contrib.auth.models import User
|
|||||||
|
|
||||||
|
|
||||||
class Profile(models.Model):
|
class Profile(models.Model):
|
||||||
|
"""
|
||||||
|
Model of a user of the service
|
||||||
|
"""
|
||||||
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
||||||
favorite_city = models.CharField(max_length=64, blank=True)
|
favorite_city = models.CharField(max_length=64, blank=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.user.username
|
return self.user.username
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
# Create your tests here.
|
|
||||||
@@ -1,13 +1,32 @@
|
|||||||
from django.shortcuts import render
|
from django.shortcuts import render, redirect
|
||||||
from profiles.models import Profile
|
from profiles.models import Profile
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
|
"""
|
||||||
|
Display the list of all profiles
|
||||||
|
:param request: None
|
||||||
|
:return: render and display template as HTML
|
||||||
|
"""
|
||||||
profiles_list = Profile.objects.all()
|
profiles_list = Profile.objects.all()
|
||||||
context = {'profiles_list': profiles_list}
|
context = {'profiles_list': profiles_list}
|
||||||
return render(request, 'profiles/index.html', context)
|
return render(request, 'profiles/index.html', context)
|
||||||
|
|
||||||
|
|
||||||
def profile(request, username):
|
def profile(request, username):
|
||||||
|
"""
|
||||||
|
Display the detail of a give profile
|
||||||
|
:param request: None
|
||||||
|
:return: render and display template as HTML
|
||||||
|
"""
|
||||||
|
try:
|
||||||
profile = Profile.objects.get(user__username=username)
|
profile = Profile.objects.get(user__username=username)
|
||||||
context = {'profile': profile}
|
context = {'profile': profile}
|
||||||
return render(request, 'profiles/profile.html', context)
|
return render(request, 'profiles/profile.html', context)
|
||||||
|
except (ValueError, Profile.DoesNotExist):
|
||||||
|
logger.error(f"Username : {username} doesn't exist")
|
||||||
|
return redirect('profiles_index')
|
||||||
@@ -6,11 +6,17 @@ authors = [
|
|||||||
{name = "Your Name",email = "you@example.com"}
|
{name = "Your Name",email = "you@example.com"}
|
||||||
]
|
]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.6"
|
requires-python = ">=3.9, <4.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"django (==3.0)",
|
"django (==3.0)",
|
||||||
"flake8 (==3.7.0)",
|
"flake8 (==3.7.0)",
|
||||||
"pytest-django (==3.9.0)"
|
"pytest-django (==3.9.0)",
|
||||||
|
"django-pytest (>=0.2.0,<0.3.0)",
|
||||||
|
"six (>=1.17.0,<2.0.0)",
|
||||||
|
"pytest-cov (>=6.3.0,<7.0.0)",
|
||||||
|
"bs4 (>=0.0.2,<0.0.3)",
|
||||||
|
"sentry-sdk[django] (>=2.37.1,<3.0.0)",
|
||||||
|
"dotenv (>=0.9.9,<0.10.0)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
2
pytest.ini
Normal file
2
pytest.ini
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[pytest]
|
||||||
|
DJANGO_SETTINGS_MODULE = oc_lettings_site.settings
|
||||||
25
templates/404.html
Normal file
25
templates/404.html
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}404 Not Found{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="container px-5 py-5 text-center">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<h1 class="page-header-ui-title mb-3 display-6">Error - 404</h1>
|
||||||
|
<h2 class="page-header-ui-title mb-3 display-6">Page Not Found</h2>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container px-5 py-5 text-center">
|
||||||
|
<div class="justify-content-center">
|
||||||
|
<p>An error has occurred</p>
|
||||||
|
<a class="btn fw-500 ms-lg-4 btn-primary px-10" href="{% url 'index' %}">
|
||||||
|
Back Home
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
24
templates/500.html
Normal file
24
templates/500.html
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}404 Not Found{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="container px-5 py-5 text-center">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<h1 class="page-header-ui-title mb-3 display-6">Error - 500</h1>
|
||||||
|
<h2 class="page-header-ui-title mb-3 display-6">Server Issue</h2>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container px-5 py-5 text-center">
|
||||||
|
<div class="justify-content-center">
|
||||||
|
<a class="btn fw-500 ms-lg-4 btn-primary px-10" href="{% url 'index' %}">
|
||||||
|
Back Home
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% load static %}
|
|
||||||
{% block title %}{{ title }}{% endblock title %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<div class="container px-5 py-5 text-center">
|
|
||||||
<div class="row justify-content-center">
|
|
||||||
<div class="col-lg-8">
|
|
||||||
<h1 class="page-header-ui-title mb-3 display-6">{{ title }}</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container px-5 py-5 text-center">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="icon-stack icon-stack-lg bg-primary text-white mb-3"><i data-feather="home"></i></div>
|
|
||||||
<p>{{ address.number }} {{ address.street }}</p>
|
|
||||||
<p>{{ address.city }}, {{ address.state }} {{ address.zip_code }}</p>
|
|
||||||
<p>{{ address.country_iso_code }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container px-5 py-5 text-center">
|
|
||||||
<div class="justify-content-center">
|
|
||||||
<a class="btn fw-500 ms-lg-4 btn-primary px-10" href="{% url 'lettings_index' %}">
|
|
||||||
<i class="ms-2" data-feather="arrow-right"></i>
|
|
||||||
Back
|
|
||||||
</a>
|
|
||||||
<a class="btn fw-500 ms-lg-4 btn-primary px-10" href="{% url 'index' %}">
|
|
||||||
Home
|
|
||||||
</a>
|
|
||||||
<a class="btn fw-500 ms-lg-4 btn-primary px-10" href="{% url 'profiles_index' %}">
|
|
||||||
Profiles
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% block title %}Lettings{% endblock title %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
|
|
||||||
<div class="container px-5 py-5 text-center">
|
|
||||||
<div class="row justify-content-center">
|
|
||||||
<div class="col-lg-8">
|
|
||||||
<h1 class="page-header-ui-title mb-3 display-6">Lettings</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container px-5">
|
|
||||||
<div class="row gx-5 justify-content-center">
|
|
||||||
<div class="col-lg-10">
|
|
||||||
<hr class="mb-0" />
|
|
||||||
{% if lettings_list %}
|
|
||||||
<ul class="list-group list-group-flush list-group-careers">
|
|
||||||
{% for letting in lettings_list %}
|
|
||||||
<li class="list-group-item">
|
|
||||||
<a href="{% url 'letting' letting_id=letting.id %}">{{ letting.title }}</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
{% else %}
|
|
||||||
<p>No lettings are available.</p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container px-5 py-5 text-center">
|
|
||||||
<div class="justify-content-center">
|
|
||||||
<a class="btn fw-500 ms-lg-4 btn-primary px-10" href="{% url 'index' %}">
|
|
||||||
Home
|
|
||||||
</a>
|
|
||||||
<a class="btn fw-500 ms-lg-4 btn-primary px-10" href="{% url 'profiles_index' %}">
|
|
||||||
Profiles
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% block title %}{{ profile.user.username }}{% endblock title %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="container px-5 py-5 text-center">
|
|
||||||
<div class="row justify-content-center">
|
|
||||||
<div class="col-lg-8">
|
|
||||||
<h1 class="page-header-ui-title mb-3 display-6">{{ profile.user.username }}</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container px-5 py-5 text-center">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="icon-stack icon-stack-lg bg-primary text-white mb-3"><i data-feather="user"></i></div>
|
|
||||||
<p><strong>First name :</strong> {{ profile.user.first_name }}</p>
|
|
||||||
<p><strong>Last name :</strong> {{ profile.user.last_name }}</p>
|
|
||||||
<p><strong>Email :</strong> {{ profile.user.email }}</p>
|
|
||||||
<p><strong>Favorite city :</strong> {{ profile.favorite_city }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container px-5 py-5 text-center">
|
|
||||||
<div class="justify-content-center">
|
|
||||||
<a class="btn fw-500 ms-lg-4 btn-primary px-10" href="{% url 'profiles_index' %}">
|
|
||||||
<i class="ms-2" data-feather="arrow-left"></i>
|
|
||||||
Back
|
|
||||||
</a>
|
|
||||||
<a class="btn fw-500 ms-lg-4 btn-primary px-10" href="{% url 'index' %}">
|
|
||||||
Home
|
|
||||||
</a>
|
|
||||||
<a class="btn fw-500 ms-lg-4 btn-primary px-10" href="{% url 'lettings_index' %}">
|
|
||||||
Lettings
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% block title %}Profiles{% endblock title %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="container px-5 py-5 text-center">
|
|
||||||
<div class="row justify-content-center">
|
|
||||||
<div class="col-lg-8">
|
|
||||||
<h1 class="page-header-ui-title mb-3 display-6">Profiles</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container px-5">
|
|
||||||
<div class="row gx-5 justify-content-center">
|
|
||||||
<div class="col-lg-10">
|
|
||||||
<hr class="mb-0" />
|
|
||||||
{% if profiles_list %}
|
|
||||||
<ul class="list-group list-group-flush list-group-careers">
|
|
||||||
{% for profile in profiles_list %}
|
|
||||||
<li class="list-group-item">
|
|
||||||
<a href="{% url 'profile' username=profile.user.username %}">{{ profile.user.username }}</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
{% else %}
|
|
||||||
<p>No profiles are available.</p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container px-5 py-5 text-center">
|
|
||||||
<div class="justify-content-center">
|
|
||||||
<a class="btn fw-500 ms-lg-4 btn-primary px-10" href="{% url 'index' %}">
|
|
||||||
Home
|
|
||||||
</a>
|
|
||||||
<a class="btn fw-500 ms-lg-4 btn-primary px-10" href="{% url 'lettings_index' %}">
|
|
||||||
Lettings
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
BIN
tests/.coverage
Normal file
BIN
tests/.coverage
Normal file
Binary file not shown.
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
83
tests/conftest.py
Normal file
83
tests/conftest.py
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import pytest
|
||||||
|
from lettings.models import Address, Letting
|
||||||
|
from profiles.models import Profile
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def sample_address():
|
||||||
|
"""
|
||||||
|
creates temporary Addresses objects in test DB
|
||||||
|
:return: tuple of Address
|
||||||
|
"""
|
||||||
|
address1 = Address.objects.create(
|
||||||
|
number=22,
|
||||||
|
street="Quality Street",
|
||||||
|
city="New-York",
|
||||||
|
state="New-York",
|
||||||
|
zip_code=10010,
|
||||||
|
country_iso_code="US"
|
||||||
|
)
|
||||||
|
address2 = Address.objects.create(
|
||||||
|
number=18,
|
||||||
|
street="Rue Cocotte",
|
||||||
|
city="Paris",
|
||||||
|
state="Ile-de-France",
|
||||||
|
zip_code=75000,
|
||||||
|
country_iso_code="FR"
|
||||||
|
)
|
||||||
|
return address1, address2
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def sample_letting(sample_address):
|
||||||
|
"""
|
||||||
|
creates temporary Letting objects in test DB
|
||||||
|
:return: tuple of Lettings
|
||||||
|
"""
|
||||||
|
letting = Letting.objects.create(
|
||||||
|
title="Pretty thing",
|
||||||
|
address=sample_address[0],
|
||||||
|
)
|
||||||
|
letting2 = Letting.objects.create(
|
||||||
|
title="Ugly thing",
|
||||||
|
address=sample_address[1],
|
||||||
|
)
|
||||||
|
|
||||||
|
return letting, letting2
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def sample_profile():
|
||||||
|
"""
|
||||||
|
creates temporary Profile objects in test DB
|
||||||
|
:return: tuple of Profiles
|
||||||
|
"""
|
||||||
|
user = User.objects.create(
|
||||||
|
username='TestUser',
|
||||||
|
password='password',
|
||||||
|
)
|
||||||
|
user2 = User.objects.create(
|
||||||
|
username='TestUser2',
|
||||||
|
password='password2',
|
||||||
|
)
|
||||||
|
user3 = User.objects.create(
|
||||||
|
username='TestUser3',
|
||||||
|
password='password2',
|
||||||
|
)
|
||||||
|
profile = Profile.objects.create(
|
||||||
|
user=user,
|
||||||
|
favorite_city="Paris",
|
||||||
|
)
|
||||||
|
profile2 = Profile.objects.create(
|
||||||
|
user=user2,
|
||||||
|
favorite_city="Marseilles",
|
||||||
|
)
|
||||||
|
profile3 = Profile.objects.create(
|
||||||
|
user=user3,
|
||||||
|
favorite_city="Rennes",
|
||||||
|
)
|
||||||
|
return profile, profile2, profile3
|
||||||
0
tests/unit/__init__.py
Normal file
0
tests/unit/__init__.py
Normal file
0
tests/unit/lettings/__init__.py
Normal file
0
tests/unit/lettings/__init__.py
Normal file
15
tests/unit/lettings/test_models.py
Normal file
15
tests/unit/lettings/test_models.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_address_str(sample_address):
|
||||||
|
""" test if Address objects are well created """
|
||||||
|
assert str(sample_address[0]) == "22 Quality Street"
|
||||||
|
assert str(sample_address[1]) == "18 Rue Cocotte"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_letting_str2(sample_letting):
|
||||||
|
""" test if Letting objects are well created """
|
||||||
|
assert str(sample_letting[0]) == "Pretty thing"
|
||||||
|
assert str(sample_letting[1]) == "Ugly thing"
|
||||||
21
tests/unit/lettings/test_urls.py
Normal file
21
tests/unit/lettings/test_urls.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import pytest
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.test import Client
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_should_get_200_on_lettings_index():
|
||||||
|
""" test the server's response """
|
||||||
|
c = Client()
|
||||||
|
url = reverse('lettings_index')
|
||||||
|
response = c.get(url)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_should_get_200_on_letting_detail(sample_letting):
|
||||||
|
c = Client()
|
||||||
|
url = reverse('letting', kwargs={'letting_id':1})
|
||||||
|
response = c.get(url)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
19
tests/unit/lettings/test_views.py
Normal file
19
tests/unit/lettings/test_views.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import pytest
|
||||||
|
from lettings.models import Address, Letting
|
||||||
|
|
||||||
|
from django.test import Client
|
||||||
|
from django.urls import reverse
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_view_should_display_right_len_list(sample_letting):
|
||||||
|
"""
|
||||||
|
test if the list displayed contains the right amount of objects
|
||||||
|
created in fixture
|
||||||
|
"""
|
||||||
|
c = Client()
|
||||||
|
url = reverse('lettings_index')
|
||||||
|
response = c.get(url)
|
||||||
|
soup = BeautifulSoup(response.content, 'html.parser')
|
||||||
|
li_tags = soup.find_all('li')
|
||||||
|
assert len(li_tags) == 2
|
||||||
0
tests/unit/oc_lettings_site/__init__.py
Normal file
0
tests/unit/oc_lettings_site/__init__.py
Normal file
18
tests/unit/oc_lettings_site/test_urls.py
Normal file
18
tests/unit/oc_lettings_site/test_urls.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
from django.urls import reverse, resolve
|
||||||
|
from oc_lettings_site.views import index
|
||||||
|
from django.test import Client
|
||||||
|
|
||||||
|
|
||||||
|
def test_server_should_answer_200():
|
||||||
|
""" test the server's response on home """
|
||||||
|
c = Client()
|
||||||
|
url = reverse('index')
|
||||||
|
response = c.get(url)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
|
def test_home_url():
|
||||||
|
""" test the home url """
|
||||||
|
url = reverse('index')
|
||||||
|
assert resolve(url).view_name == 'index'
|
||||||
|
assert resolve(url).func, index()
|
||||||
10
tests/unit/oc_lettings_site/test_view.py
Normal file
10
tests/unit/oc_lettings_site/test_view.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from django.test import Client
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
|
||||||
|
def test_view_should_reply_title_on_home():
|
||||||
|
""" test the content display (title) """
|
||||||
|
c = Client()
|
||||||
|
url = reverse('index')
|
||||||
|
response = c.get(url)
|
||||||
|
assert "Welcome to Holiday Homes</h1>" in response.content.decode()
|
||||||
0
tests/unit/profiles/__init__.py
Normal file
0
tests/unit/profiles/__init__.py
Normal file
16
tests/unit/profiles/test_models.py
Normal file
16
tests/unit/profiles/test_models.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import pytest
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from profiles.models import Profile
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_str_profile():
|
||||||
|
user = User.objects.create(
|
||||||
|
username='TestUser',
|
||||||
|
password='password',
|
||||||
|
)
|
||||||
|
profile = Profile.objects.create(
|
||||||
|
user=user,
|
||||||
|
favorite_city="Paris",
|
||||||
|
)
|
||||||
|
assert str(profile) == "TestUser"
|
||||||
22
tests/unit/profiles/test_urls.py
Normal file
22
tests/unit/profiles/test_urls.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import pytest
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.test import Client
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_should_get_200_on_profile_index():
|
||||||
|
""" test the server's response on profile index page """
|
||||||
|
c = Client()
|
||||||
|
url = reverse('profiles_index')
|
||||||
|
response = c.get(url)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_should_get_200_on_profile_detail(sample_profile):
|
||||||
|
""" test the server's response on a profile detail page """
|
||||||
|
c = Client()
|
||||||
|
url = reverse('profile', kwargs={'username': "TestUser"})
|
||||||
|
response = c.get(url)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
18
tests/unit/profiles/test_views.py
Normal file
18
tests/unit/profiles/test_views.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import pytest
|
||||||
|
from django.test import Client
|
||||||
|
from django.urls import reverse
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_view_should_display_right_len_list(sample_profile):
|
||||||
|
"""
|
||||||
|
test that html page displays the right amount of objects
|
||||||
|
created by fixture
|
||||||
|
"""
|
||||||
|
c = Client()
|
||||||
|
url = reverse('profiles_index')
|
||||||
|
response = c.get(url)
|
||||||
|
soup = BeautifulSoup(response.content, 'html.parser')
|
||||||
|
li_tags = soup.find_all('li')
|
||||||
|
assert len(li_tags) == 3
|
||||||
Reference in New Issue
Block a user