mirror of
https://github.com/Hopiu/django-notifications.git
synced 2026-03-16 21:30:24 +00:00
Fix test matrix
This commit is contained in:
parent
30cf195d36
commit
bb41d39a63
20 changed files with 716 additions and 664 deletions
105
.github/workflows/ci.yml
vendored
Normal file
105
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
# Based on
|
||||
# https://pypi.org/project/tox-gh-actions/
|
||||
|
||||
---
|
||||
name: Test the application.
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
code-check:
|
||||
name: Code checking
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- name: Install poetry
|
||||
run: pipx install poetry
|
||||
- name: Set python version for poetry
|
||||
run: poetry env use python3.11
|
||||
- name: Install dependencies
|
||||
run: poetry install -E lint
|
||||
- name: Run Isort
|
||||
run: poetry run -v -- isort -c notifications/ sample_website/
|
||||
- name: Run Black
|
||||
run: poetry run -v -- black --check notifications/ sample_website/
|
||||
- name: Run Pylint
|
||||
run: poetry run -vvv -- pylint --rcfile=pyproject.toml --recursive=y -v notifications/ sample_website/
|
||||
- name: Run Bandit
|
||||
run: poetry run -v -- bandit -c pyproject.toml -r notifications/ sample_website/
|
||||
- name: Run Mypy
|
||||
run: poetry run -v -- mypy
|
||||
|
||||
test:
|
||||
name: Testing
|
||||
runs-on: ubuntu-latest
|
||||
needs: code-check
|
||||
strategy:
|
||||
max-parallel: 4
|
||||
matrix:
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
|
||||
django-version: ["3.2.0", "4.0.0", "4.1.0", "4.2.0"]
|
||||
exclude:
|
||||
- python-version: "3.11"
|
||||
django-version: ["3.2", "4.0.0"]
|
||||
- python-version: "3.12"
|
||||
django-version: ["3.2", "4.0.0", "4.1.0"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install poetry
|
||||
run: pipx install poetry
|
||||
- name: Set python version for poetry
|
||||
run: poetry env use python${{ matrix.python-version }}
|
||||
- name: Install Django
|
||||
run: poetry add --lock django@~${{ matrix.django-version }}
|
||||
- name: Install dependencies
|
||||
run: poetry install -E test
|
||||
- name: Run tests
|
||||
run: poetry run -- pytest
|
||||
env:
|
||||
COVERAGE_FILE: ".coverage.${{ matrix.python-version }}.${{ matrix.django-version }}"
|
||||
- name: Store coverage file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: coverage-${{ matrix.python-version }}-${{ matrix.django-version }}
|
||||
path: .coverage.${{ matrix.python-version }}.${{ matrix.django-version }}
|
||||
|
||||
|
||||
coverage:
|
||||
name: Coverage
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
id: download
|
||||
with:
|
||||
pattern: coverage-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Coverage comment
|
||||
id: coverage_comment
|
||||
uses: py-cov-action/python-coverage-comment-action@v3
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
MERGE_COVERAGE_FILES: true
|
||||
|
||||
- name: Store Pull Request comment to be posted
|
||||
uses: actions/upload-artifact@v4
|
||||
if: steps.coverage_comment.outputs.COMMENT_FILE_WRITTEN == 'true'
|
||||
with:
|
||||
name: python-coverage-comment-action
|
||||
path: python-coverage-comment-action.txt
|
||||
32
.github/workflows/coverage.yml
vendored
Normal file
32
.github/workflows/coverage.yml
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
name: Post coverage comment
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["CI"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Coverage
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
|
||||
permissions:
|
||||
# Gives the action the necessary permissions for publishing new
|
||||
# comments in pull requests.
|
||||
pull-requests: write
|
||||
# Gives the action the necessary permissions for editing existing
|
||||
# comments (to avoid publishing multiple comments in the same PR)
|
||||
contents: write
|
||||
# Gives the action the necessary permissions for looking up the
|
||||
# workflow that launched this workflow, and download the related
|
||||
# artifact that contains the comment to be published
|
||||
actions: read
|
||||
steps:
|
||||
# DO NOT run actions/checkout here, for security reasons
|
||||
# For details, refer to https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
|
||||
- name: Post comment
|
||||
uses: py-cov-action/python-coverage-comment-action@v3
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_PR_RUN_ID: ${{ github.event.workflow_run.id }}
|
||||
87
.github/workflows/test.yml
vendored
87
.github/workflows/test.yml
vendored
|
|
@ -1,87 +0,0 @@
|
|||
# Based on
|
||||
# https://pypi.org/project/tox-gh-actions/
|
||||
|
||||
---
|
||||
name: Test the application.
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
code-check:
|
||||
name: Code checking
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- name: Install poetry
|
||||
run: pipx install poetry
|
||||
- name: Install dependencies
|
||||
run: poetry install
|
||||
- name: Run Pylint
|
||||
run: poetry run -v -- pylint --rcfile=pyproject.toml notifications/ sample_website/
|
||||
- name: Run Bandit
|
||||
run: poetry run -v -- bandit -c pyproject.toml -r notifications/ sample_website/
|
||||
|
||||
|
||||
test:
|
||||
name: Testing
|
||||
runs-on: ubuntu-latest
|
||||
needs: code-check
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install poetry
|
||||
run: pipx install poetry
|
||||
- name: Install dependencies
|
||||
run: poetry install
|
||||
- name: Run tests
|
||||
run: poetry run pytest
|
||||
env:
|
||||
COVERAGE_FILE: ".coverage.${{ matrix.python_version }}"
|
||||
- name: Store coverage file
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage
|
||||
path: .coverage.${{ matrix.python_version }}
|
||||
|
||||
|
||||
coverage:
|
||||
name: Coverage
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
id: download
|
||||
with:
|
||||
name: 'coverage'
|
||||
|
||||
- name: Coverage comment
|
||||
id: coverage_comment
|
||||
uses: py-cov-action/python-coverage-comment-action@v3
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
MERGE_COVERAGE_FILES: true
|
||||
|
||||
- name: Store Pull Request comment to be posted
|
||||
uses: actions/upload-artifact@v3
|
||||
if: steps.coverage_comment.outputs.COMMENT_FILE_WRITTEN == 'true'
|
||||
with:
|
||||
name: python-coverage-comment-action
|
||||
path: python-coverage-comment-action.txt
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -16,3 +16,4 @@ settings.json
|
|||
.pytest_cache
|
||||
.vscode
|
||||
coverage.xml
|
||||
TODO.md
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ repos:
|
|||
rev: v2.17.4
|
||||
hooks:
|
||||
- id: pylint
|
||||
name: pylint
|
||||
entry: poetry run pylint
|
||||
entry: poetry run -- pylint
|
||||
language: system
|
||||
args: ["--rcfile=pyproject.toml"]
|
||||
|
||||
|
|
@ -30,3 +29,8 @@ repos:
|
|||
hooks:
|
||||
- id: bandit
|
||||
args: ["-c", "pyproject.toml"]
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.9.0
|
||||
hooks:
|
||||
- id: mypy
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# Changelog
|
||||
|
||||
## 2.0.0
|
||||
- Migrated to Github CI
|
||||
- Added docker environment and migrated to Poetry and pyproject.toml
|
||||
- Added verbose_name migration
|
||||
- Migrated from `jsonfield` to Django `JSONField`
|
||||
|
|
|
|||
45
CONTRIBUTING.md
Normal file
45
CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# Creating the development environment
|
||||
|
||||
1. Install [Pyenv](https://github.com/pyenv/pyenv?tab=readme-ov-file#installation)
|
||||
2. Install [PipX](https://github.com/pypa/pipx?tab=readme-ov-file#install-pipx)
|
||||
3. Install [Poetry](https://python-poetry.org/docs/#installing-with-pipx) with **PipX**
|
||||
4. install [Tox](https://tox.wiki/en/latest/installation.html#via-pipx) with **PipX**
|
||||
5. Install necessary python versions
|
||||
|
||||
`pyenv install --skip-existing 3.8 3.9 3.10 3.11 3.12`
|
||||
|
||||
6. Set python versions as local
|
||||
|
||||
`pyenv local 3.12 3.11 3.10 3.9 3.8`
|
||||
|
||||
7. Ensure poetry config
|
||||
|
||||
`poetry config virtualenvs.create true`
|
||||
|
||||
`poetry config virtualenvs.prefer-active-python true`
|
||||
8. Install the lib and dependencies with poetry
|
||||
|
||||
`poetry install --all-extras`
|
||||
|
||||
9. Initialize pre-commit
|
||||
|
||||
`poetry run pre-commit install`
|
||||
|
||||
|
||||
|
||||
# Running tests
|
||||
To run the tests you can use any of the commands bellow:
|
||||
|
||||
1. `make tests` To run all tests over all environment combinations
|
||||
2. `make test-latest` To run all tests over the latest enviroment possible
|
||||
|
||||
# Running code quality tools
|
||||
To options to run the linters are:
|
||||
|
||||
1. `make isort`
|
||||
2. `make black`
|
||||
3. `make pylint`
|
||||
4. `make bandit`
|
||||
5. `make mypy`
|
||||
|
||||
To run all linters over all files: `make lint`
|
||||
24
Makefile
24
Makefile
|
|
@ -1,14 +1,18 @@
|
|||
up:
|
||||
docker-compose up --remove-orphans
|
||||
|
||||
tests:
|
||||
poetry run python -m tox run-parallel
|
||||
tox run-parallel -p auto
|
||||
|
||||
test-latest:
|
||||
tox run -e py3.11-django42
|
||||
|
||||
server:
|
||||
poetry run python manage.py runserver 0.0.0.0:8000
|
||||
|
||||
run: server
|
||||
|
||||
makemigrations:
|
||||
migrations:
|
||||
poetry run python manage.py makemigrations
|
||||
|
||||
migrate:
|
||||
|
|
@ -17,8 +21,20 @@ migrate:
|
|||
shell:
|
||||
poetry run python manage.py shell
|
||||
|
||||
isort:
|
||||
poetry run pre-commit run --all-files isort
|
||||
|
||||
black:
|
||||
poetry run pre-commit run --all-files black
|
||||
|
||||
pylint:
|
||||
poetry run pylint --django-settings-module="notifications.settings" notifications/
|
||||
poetry run pre-commit run --all-files pylint
|
||||
|
||||
bandit:
|
||||
poetry run bandit -c pyproject.toml -r notifications/
|
||||
poetry run pre-commit run --all-files bandit
|
||||
|
||||
mypy:
|
||||
poetry run pre-commit run --all-files mypy
|
||||
|
||||
lint:
|
||||
poetry run pre-commit run --all-files
|
||||
|
|
|
|||
|
|
@ -20,4 +20,4 @@ RUN pyenv local system 3.8 3.9 3.10
|
|||
RUN apt-get --purge autoremove -y gnupg; \
|
||||
rm -rf /var/cache/apt/lists;
|
||||
|
||||
ENTRYPOINT poetry install && poetry run pre-commit install && /bin/bash
|
||||
ENTRYPOINT poetry install && poetry run -- pre-commit install && /bin/bash
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ class NotificationAdmin(admin.ModelAdmin):
|
|||
return qs.prefetch_related("actor")
|
||||
|
||||
@admin.action(description=gettext_lazy("Mark selected notifications as unread"))
|
||||
def mark_unread(self, request: HttpRequest, queryset: NotificationQuerySet): # pylint: disable=unused-argument
|
||||
def mark_unread(self, request: HttpRequest, queryset: NotificationQuerySet):
|
||||
queryset.update(unread=True)
|
||||
|
||||
@admin.action(description=gettext_lazy("Mark selected notifications as read"))
|
||||
def mark_read(self, request: HttpRequest, queryset: NotificationQuerySet): # pylint: disable=unused-argument
|
||||
def mark_read(self, request: HttpRequest, queryset: NotificationQuerySet):
|
||||
queryset.update(unread=False)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from typing import Union
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||
|
|
@ -130,7 +131,7 @@ class AbstractNotification(models.Model):
|
|||
return _("%(actor)s %(verb)s %(action_object)s %(timesince)s ago") % ctx
|
||||
return _("%(actor)s %(verb)s %(timesince)s ago") % ctx
|
||||
|
||||
def timesince(self, now: None | datetime.datetime = None) -> str:
|
||||
def timesince(self, now: Union[None, datetime.datetime] = None) -> str:
|
||||
"""
|
||||
Shortcut for the ``django.utils.timesince.timesince`` function of the
|
||||
current timestamp.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Type
|
||||
from typing import Type, Union
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db import models
|
||||
|
|
@ -46,7 +46,7 @@ class NotificationQuerySet(models.QuerySet):
|
|||
# in this case, to improve query performance, don't filter by 'deleted' field
|
||||
return self.filter(unread=False)
|
||||
|
||||
def mark_all_as_read(self, recipient: None | Type[AbstractUser] = None) -> int:
|
||||
def mark_all_as_read(self, recipient: Union[None, Type[AbstractUser]] = None) -> int:
|
||||
"""Mark as read any unread messages in the current queryset.
|
||||
|
||||
Optionally, filter these by recipient first.
|
||||
|
|
@ -59,7 +59,7 @@ class NotificationQuerySet(models.QuerySet):
|
|||
|
||||
return qset.update(unread=False)
|
||||
|
||||
def mark_all_as_unread(self, recipient: None | Type[AbstractUser] = None) -> int:
|
||||
def mark_all_as_unread(self, recipient: Union[None, Type[AbstractUser]] = None) -> int:
|
||||
"""Mark as unread any read messages in the current queryset.
|
||||
|
||||
Optionally, filter these by recipient first.
|
||||
|
|
@ -81,7 +81,7 @@ class NotificationQuerySet(models.QuerySet):
|
|||
assert_soft_delete()
|
||||
return self.filter(deleted=False)
|
||||
|
||||
def mark_all_as_deleted(self, recipient: None | Type[AbstractUser] = None) -> int:
|
||||
def mark_all_as_deleted(self, recipient: Union[None, Type[AbstractUser]] = None) -> int:
|
||||
"""Mark current queryset as deleted.
|
||||
Optionally, filter by recipient first.
|
||||
"""
|
||||
|
|
@ -92,7 +92,7 @@ class NotificationQuerySet(models.QuerySet):
|
|||
|
||||
return qset.update(deleted=True)
|
||||
|
||||
def mark_all_as_active(self, recipient: None | Type[AbstractUser] = None) -> int:
|
||||
def mark_all_as_active(self, recipient: Union[None, Type[AbstractUser]] = None) -> int:
|
||||
"""Mark current queryset as active(un-deleted).
|
||||
Optionally, filter by recipient first.
|
||||
"""
|
||||
|
|
@ -103,13 +103,13 @@ class NotificationQuerySet(models.QuerySet):
|
|||
|
||||
return qset.update(deleted=False)
|
||||
|
||||
def mark_as_unsent(self, recipient: None | Type[AbstractUser] = None) -> int:
|
||||
def mark_as_unsent(self, recipient: Union[None, Type[AbstractUser]] = None) -> int:
|
||||
qset = self.sent()
|
||||
if recipient:
|
||||
qset = qset.filter(recipient=recipient)
|
||||
return qset.update(emailed=False)
|
||||
|
||||
def mark_as_sent(self, recipient: None | Type[AbstractUser] = None) -> int:
|
||||
def mark_as_sent(self, recipient: Union[None, Type[AbstractUser]] = None) -> int:
|
||||
qset = self.unsent()
|
||||
if recipient:
|
||||
qset = qset.filter(recipient=recipient)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
""" Django notifications settings file """
|
||||
# -*- coding: utf-8 -*-
|
||||
from typing import Any, TypedDict
|
||||
from typing import Any, TypedDict, Union
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
|
|
@ -39,15 +39,17 @@ class NotificationSettings:
|
|||
apps, and test helpers like `override_settings` may not work as expected.
|
||||
"""
|
||||
|
||||
def __init__(self, defaults: None | NotificationDefaultsType = None):
|
||||
self._user_settings = None
|
||||
self.defaults = defaults or NotificationDefaultsType(**NOTIFICATION_DEFAULTS)
|
||||
def __init__(self, defaults: Union[None, NotificationDefaultsType] = None):
|
||||
self._user_settings: Union[NotificationDefaultsType, None] = None
|
||||
self.defaults = defaults or NotificationDefaultsType(**NOTIFICATION_DEFAULTS) # type: ignore[typeddict-item]
|
||||
self._cached_attrs: set[str] = set()
|
||||
|
||||
@property
|
||||
def user_settings(self) -> NotificationDefaultsType:
|
||||
if not self._user_settings:
|
||||
self._user_settings = NotificationDefaultsType(**getattr(settings, "DJANGO_NOTIFICATIONS_CONFIG") or {})
|
||||
self._user_settings = NotificationDefaultsType(
|
||||
**getattr(settings, "DJANGO_NOTIFICATIONS_CONFIG") or {}
|
||||
) # type: ignore[typeddict-item]
|
||||
return self._user_settings
|
||||
|
||||
def __getattr__(self, attr: str) -> NotificationDefaultsType:
|
||||
|
|
@ -56,10 +58,10 @@ class NotificationSettings:
|
|||
|
||||
try:
|
||||
# Check if present in user settings
|
||||
val = self.user_settings[attr]
|
||||
val = self.user_settings[attr] # type: ignore[literal-required]
|
||||
except KeyError:
|
||||
# Fall back to defaults
|
||||
val = self.defaults[attr]
|
||||
val = self.defaults[attr] # type: ignore[literal-required]
|
||||
|
||||
# Cache the result
|
||||
self._cached_attrs.add(attr)
|
||||
|
|
@ -73,7 +75,9 @@ class NotificationSettings:
|
|||
self._user_settings = None
|
||||
|
||||
|
||||
notification_settings = NotificationSettings(NOTIFICATION_DEFAULTS)
|
||||
notification_settings = NotificationSettings(
|
||||
NotificationDefaultsType(**NOTIFICATION_DEFAULTS) # type: ignore[typeddict-item]
|
||||
)
|
||||
|
||||
|
||||
def reload_notification_settings(*args: Any, **kwargs: Any): # pylint: disable=unused-argument
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ DATABASES = {
|
|||
}
|
||||
|
||||
MIDDLEWARE = (
|
||||
"debug_toolbar.middleware.DebugToolbarMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ when you run "manage.py test".
|
|||
Replace this with more appropriate tests for your application.
|
||||
"""
|
||||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=too-many-lines,missing-docstring
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
|
@ -107,7 +106,7 @@ class NotificationManagersTest(TestCase):
|
|||
# only check types for now
|
||||
self.assertEqual(type(result[1][0]), Notification)
|
||||
|
||||
def test_notify_send_return_val_group(self): # pylint: disable=invalid-name
|
||||
def test_notify_send_return_val_group(self):
|
||||
results = notify.send(self.from_user, recipient=self.to_group, verb="commented", action_object=self.from_user)
|
||||
for result in results:
|
||||
if result[0] is notify_handler:
|
||||
|
|
@ -137,7 +136,7 @@ class NotificationManagersTest(TestCase):
|
|||
Notification.objects.filter(recipient=self.to_user).mark_all_as_read()
|
||||
self.assertEqual(self.to_user.notifications.unread().count(), 0)
|
||||
|
||||
@override_settings(DJANGO_NOTIFICATIONS_CONFIG={"SOFT_DELETE": True}) # pylint: disable=invalid-name
|
||||
@override_settings(DJANGO_NOTIFICATIONS_CONFIG={"SOFT_DELETE": True})
|
||||
def test_mark_all_as_read_manager_with_soft_delete(self):
|
||||
# even soft-deleted notifications should be marked as read
|
||||
# refer: https://github.com/django-notifications/django-notifications/issues/126
|
||||
|
|
@ -155,7 +154,7 @@ class NotificationManagersTest(TestCase):
|
|||
Notification.objects.filter(recipient=self.to_user).mark_all_as_unread()
|
||||
self.assertEqual(Notification.objects.unread().count(), self.message_count)
|
||||
|
||||
def test_mark_all_deleted_manager_without_soft_delete(self): # pylint: disable=invalid-name
|
||||
def test_mark_all_deleted_manager_without_soft_delete(self):
|
||||
self.assertRaises(ImproperlyConfigured, Notification.objects.active)
|
||||
self.assertRaises(ImproperlyConfigured, Notification.objects.active)
|
||||
self.assertRaises(ImproperlyConfigured, Notification.objects.mark_all_as_deleted)
|
||||
|
|
@ -295,7 +294,7 @@ class NotificationTestPages(TestCase):
|
|||
self.assertEqual(len(response.context["notifications"]), len(self.to_user.notifications.unread()))
|
||||
self.assertEqual(len(response.context["notifications"]), self.message_count - 1)
|
||||
|
||||
@override_settings(DJANGO_NOTIFICATIONS_CONFIG={"SOFT_DELETE": True}) # pylint: disable=invalid-name
|
||||
@override_settings(DJANGO_NOTIFICATIONS_CONFIG={"SOFT_DELETE": True})
|
||||
def test_soft_delete_messages_manager(self):
|
||||
self.login("to", "pwd")
|
||||
|
||||
|
|
@ -439,7 +438,7 @@ class NotificationTestPages(TestCase):
|
|||
self.assertEqual(data["all_list"][0]["verb"], "commented")
|
||||
self.assertEqual(data["all_list"][0]["slug"], data["all_list"][0]["id"])
|
||||
|
||||
def test_unread_list_api_mark_as_read(self): # pylint: disable=invalid-name
|
||||
def test_unread_list_api_mark_as_read(self):
|
||||
self.login("to", "pwd")
|
||||
num_requested = 3
|
||||
response = self.client.get(
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@ from typing import NewType
|
|||
|
||||
from django.contrib.auth.base_user import AbstractBaseUser
|
||||
|
||||
AbstractUser = NewType("AbstractUser", AbstractBaseUser)
|
||||
AbstractUser = NewType("AbstractUser", AbstractBaseUser) # type: ignore[valid-newtype]
|
||||
|
|
|
|||
900
poetry.lock
generated
900
poetry.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -52,8 +52,8 @@ classifiers = [
|
|||
|
||||
"Framework :: Django",
|
||||
"Framework :: Django :: 3.2",
|
||||
"Framework :: Django :: 4.0",
|
||||
"Framework :: Django :: 4.1",
|
||||
"Framework :: Django :: 4.2",
|
||||
"Framework :: Django :: 5.0",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
|
|
@ -61,10 +61,11 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Topic :: Communications :: Notification",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Topic :: Communications",
|
||||
"Topic :: Internet",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"Topic :: Software Development :: Libraries",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"Topic :: Utilities",
|
||||
]
|
||||
packages = [
|
||||
|
|
@ -81,28 +82,50 @@ include = [
|
|||
]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.8.1"
|
||||
python = "^3.8"
|
||||
django = ">3.2"
|
||||
swapper = "^1"
|
||||
bandit = { version = "^1", optional = true }
|
||||
black = { version = "^23", optional = true }
|
||||
coverage = {version = "^7.2.7", optional = true }
|
||||
django-debug-toolbar = {version = "^4", optional = true }
|
||||
django-test-migrations = {version = "^1.3.0", optional = true }
|
||||
factory-boy = {version = "^3.2.1", optional = true }
|
||||
isort = {version = "^5", optional = true }
|
||||
mypy = {version = "^1", optional = true }
|
||||
pre-commit = {version = "^3", optional = true }
|
||||
psycopg2-binary = {version = "^2.9.6", optional = true }
|
||||
pylint = {version = "^2", optional = true }
|
||||
pylint-django = {version = "^2", optional = true }
|
||||
pytest = {version = "^7", optional = true }
|
||||
pytest-cov = {version = "^4", optional = true }
|
||||
pytest-django = {version = "^4", optional = true }
|
||||
pytest-xdist = {version = "^3.3.1", optional = true }
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
black = "^23"
|
||||
bandit = "^1"
|
||||
coverage = {extras = ["toml"], version = "^7.2.7"}
|
||||
django-debug-toolbar = "^4"
|
||||
isort = "^5"
|
||||
mypy = "^1" ### TODO
|
||||
pre-commit = "^3"
|
||||
pylint = "^2"
|
||||
pylint-django = "^2"
|
||||
pytest = "^7"
|
||||
pytest-cov = "^4"
|
||||
pytest-django = "^4"
|
||||
tox = "^4"
|
||||
psycopg2-binary = "^2.9.6"
|
||||
django-test-migrations = "^1.3.0"
|
||||
factory-boy = "^3.2.1"
|
||||
pytest-xdist = "^3.3.1"
|
||||
[tool.poetry.extras]
|
||||
dev = [
|
||||
"django-debug-toolbar",
|
||||
"pre-commit",
|
||||
"psycopg2-binary",
|
||||
]
|
||||
lint = [
|
||||
"bandit",
|
||||
"black",
|
||||
"isort",
|
||||
"mypy",
|
||||
"pylint",
|
||||
"pylint-django",
|
||||
]
|
||||
test = [
|
||||
"coverage",
|
||||
"django-test",
|
||||
"django-test-migrations",
|
||||
"factory-boy",
|
||||
"pytest",
|
||||
"pytest-cov",
|
||||
"pytest-django",
|
||||
"pytest-xdist",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
|
|
@ -118,9 +141,10 @@ ignore-paths = [
|
|||
]
|
||||
jobs = 0
|
||||
django-settings-module = "notifications.settings"
|
||||
fail-on=[
|
||||
"useless-suppression",
|
||||
]
|
||||
# fail-on=[ # TODO: Investigate why the Pylint results are different in different platforms (macOS and GH actions)
|
||||
# "useless-suppression",
|
||||
# ]
|
||||
|
||||
|
||||
[tool.pylint.DESIGN]
|
||||
max-locals = 20
|
||||
|
|
@ -132,18 +156,25 @@ enable = [
|
|||
"useless-suppression",
|
||||
]
|
||||
disable = [
|
||||
"fixme",
|
||||
"missing-function-docstring",
|
||||
"missing-class-docstring",
|
||||
"missing-module-docstring",
|
||||
"fixme",
|
||||
"too-few-public-methods",
|
||||
]
|
||||
|
||||
[tool.pylint.FORMAT]
|
||||
max-line-length = 120
|
||||
|
||||
[tool.pylint.TYPECHECK]
|
||||
ignored-modules = [
|
||||
"pytest",
|
||||
"factory",
|
||||
]
|
||||
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
extend-exclude = "migrations/"
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
|
|
@ -180,8 +211,15 @@ testpaths = [
|
|||
]
|
||||
DJANGO_SETTINGS_MODULE = "notifications.tests.settings_for_tests"
|
||||
django_debug_mode = "keep"
|
||||
show_locals=true
|
||||
|
||||
[tool.coverage.run]
|
||||
relative_files = true
|
||||
parallel = true
|
||||
branch = true
|
||||
|
||||
[tool.mypy]
|
||||
files = "**/*.py"
|
||||
exclude = "migration/*"
|
||||
ignore_missing_imports=true
|
||||
no_namespace_packages=true
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
from django.contrib import admin
|
||||
from django.urls import include, path
|
||||
|
||||
from .views import live_tester, make_notification
|
||||
from sample_website.views import live_tester, make_notification
|
||||
|
||||
urlpatterns = [
|
||||
path("__debug__/", include("debug_toolbar.urls")),
|
||||
|
|
|
|||
26
tox.ini
26
tox.ini
|
|
@ -1,23 +1,21 @@
|
|||
# -- FILE: tox.ini
|
||||
[tox]
|
||||
min_version = 4.0
|
||||
isolated_build = true
|
||||
skip_missing_interpreters = False
|
||||
envlist =
|
||||
python{3.8,3.9,3.10,3.11}-django{32,40,41}
|
||||
|
||||
[gh-actions]
|
||||
python =
|
||||
3.8: python3.8
|
||||
3.9: python3.9
|
||||
3.10: python3.10
|
||||
3.11: python3.11
|
||||
envlist =
|
||||
py3.8-django{32,40,41,42}
|
||||
py3.9-django{32,40,41,42}
|
||||
py3.10-django{32,40,41,42}
|
||||
py3.11-django{41,42}
|
||||
py3.12-django{42}
|
||||
|
||||
[testenv]
|
||||
commands =
|
||||
coverage run --branch --source=notifications manage.py test
|
||||
allowlist_externals = bash
|
||||
deps =
|
||||
coverage
|
||||
django32: Django>=3.2,<4.0
|
||||
django40: Django>=4.0,<4.1
|
||||
django41: Django>=4.1,<4.2
|
||||
django42: Django>=4.2,<4.3
|
||||
extras = test
|
||||
package = editable
|
||||
commands =
|
||||
pytest -v
|
||||
|
|
|
|||
Loading…
Reference in a new issue