Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-django-push-notifications for openSUSE:Factory checked in at 2022-05-12 22:59:44 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-django-push-notifications (Old) and /work/SRC/openSUSE:Factory/.python-django-push-notifications.new.1538 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-django-push-notifications" Thu May 12 22:59:44 2022 rev:3 rq:976289 version:3.0.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-django-push-notifications/python-django-push-notifications.changes 2021-12-26 15:53:41.204102998 +0100 +++ /work/SRC/openSUSE:Factory/.python-django-push-notifications.new.1538/python-django-push-notifications.changes 2022-05-12 23:00:09.340780314 +0200 @@ -1,0 +2,32 @@ +Wed May 11 10:11:10 UTC 2022 - pgaj...@suse.com + +- version update to 3.0.0 + * #567 Fixes crash on bulk_send test message operation from admin by @DataGreed in #568 + * Updated README: added info about APNS_AUTH_KEY_PATH, APNS_AUTH_KEY_ID, APNS_TEAM_ID by @DataGreed in #566 + * Add some details to APNS settings description by @scherbakovx in #575 + * Django 4.0 warnings by @jheld in #585 + * Run tests on python3.9 by @bertonha in #589 + * add mutable_content to fcm by @paradizer in #582 + * Improve efficiency of ORM lookups by @code-review-doctor in #598 + * Drop python 2.x and django before 2.2 by @sevdog in #599 + * Migrate to GitHub Actions. by @jezdez in #607 + * Mention WebPushDevice in README by @Tyilo in #608 + * Make push optional dependecies by @sevdog in #600 + * fix: Remove python3.5 deps by @bertonha in #621 + * Spelling error & convert string to be translatable by @Andrew-Chen-Wang in #614 + * ++Enable sending image in GCM notifications by @ashishnitinpatil in #624 + * [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in #625 + * Change feature detection logic for database field by @sevdog in #612 + * Add Edge support to webpush by @simonkern in #631 + * chore: test on Django 4.0 by @bertonha in #638 + * chore: test only active Django versions by @bertonha in #639 + * chore: dry tests, use newer DRF on tests by @bertonha in #641 + * [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in #635 + * More robust handling of userAgentData, fix WebPushDeviceAdmin by @simonkern in #643 + * [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in #644 + * Add missing migration for #614 by @simonkern in #645 + * Jazzband: Synced file(s) with jazzband/.github by @jazzband-bot in #626 + * Show coverage badge in README. by @shimakaze-git in #651 +- python-mock is not required for build + +------------------------------------------------------------------- Old: ---- django-push-notifications-2.0.0.tar.gz New: ---- django-push-notifications-3.0.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-django-push-notifications.spec ++++++ --- /var/tmp/diff_new_pack.bilt6Q/_old 2022-05-12 23:00:09.872781028 +0200 +++ /var/tmp/diff_new_pack.bilt6Q/_new 2022-05-12 23:00:09.876781033 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-django-push-notifications # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-django-push-notifications -Version: 2.0.0 +Version: 3.0.0 Release: 0 Summary: Django package to send push notifications to mobile devices License: MIT @@ -34,12 +34,14 @@ # SECTION test requirements BuildRequires: %{python_module Django >= 1.11} BuildRequires: %{python_module apns2} -BuildRequires: %{python_module djangorestframework >= 3.7} BuildRequires: %{python_module django-codemod} -BuildRequires: %{python_module mock} +BuildRequires: %{python_module djangorestframework >= 3.7} +BuildRequires: %{python_module pip} +BuildRequires: %{python_module pytest-cov} BuildRequires: %{python_module pytest-django} BuildRequires: %{python_module pytest} BuildRequires: %{python_module pywebpush >= 1.3.0} +BuildRequires: %{python_module wheel} # /SECTION %python_subpackages @@ -52,10 +54,10 @@ djcodemod run --removed-in 4.0 push_notifications/{admin,fields,models}.py %build -%python_build +%pyproject_wheel %install -%python_install +%pyproject_install %python_expand %fdupes %{buildroot}%{$python_sitelib} %check ++++++ django-push-notifications-2.0.0.tar.gz -> django-push-notifications-3.0.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/.github/workflows/release.yml new/django-push-notifications-3.0.0/.github/workflows/release.yml --- old/django-push-notifications-2.0.0/.github/workflows/release.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/django-push-notifications-3.0.0/.github/workflows/release.yml 2022-02-14 03:43:49.000000000 +0100 @@ -0,0 +1,40 @@ +name: Release + +on: + push: + tags: + - '*' + +jobs: + build: + if: github.repository == 'jazzband/django-push-notifications' + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.8 + + - name: Install dependencies + run: | + python -m pip install -U pip + python -m pip install -U setuptools twine wheel + + - name: Build package + run: | + python setup.py --version + python setup.py sdist --format=gztar bdist_wheel + twine check dist/* + + - name: Upload packages to Jazzband + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + uses: pypa/gh-action-pypi-publish@master + with: + user: jazzband + password: ${{ secrets.JAZZBAND_RELEASE_KEY }} + repository_url: https://jazzband.co/projects/django-push-notifications/upload diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/.github/workflows/test.yml new/django-push-notifications-3.0.0/.github/workflows/test.yml --- old/django-push-notifications-2.0.0/.github/workflows/test.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/django-push-notifications-3.0.0/.github/workflows/test.yml 2022-02-14 03:43:49.000000000 +0100 @@ -0,0 +1,48 @@ +name: Test + +on: [push, pull_request] + +jobs: + build: + name: build (Python ${{ matrix.python-version }}, Django ${{ matrix.django-version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ['3.6', '3.7', '3.8', '3.9'] + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Get pip cache dir + id: pip-cache + run: | + echo "::set-output name=dir::$(pip cache dir)" + + - name: Cache + uses: actions/cache@v2 + with: + path: ${{ steps.pip-cache.outputs.dir }} + key: + ${{ matrix.python-version }}-v1-${{ hashFiles('**/setup.cfg') }}-${{ hashFiles('**/tox.ini') }} + restore-keys: | + ${{ matrix.python-version }}-v1- + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install --upgrade tox tox-gh-actions + + - name: Tox tests + run: | + tox -v + + - name: Upload coverage + uses: codecov/codecov-action@v1 + with: + name: Python ${{ matrix.python-version }} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/.gitignore new/django-push-notifications-3.0.0/.gitignore --- old/django-push-notifications-2.0.0/.gitignore 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/.gitignore 2022-02-14 03:43:49.000000000 +0100 @@ -16,3 +16,11 @@ # tox .tox *.egg-info/ +.eggs + +# coverage +.coverage +coverage.xml + +# vscode files +.vscode/* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/.pre-commit-config.yaml new/django-push-notifications-3.0.0/.pre-commit-config.yaml --- old/django-push-notifications-2.0.0/.pre-commit-config.yaml 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/.pre-commit-config.yaml 2022-02-14 03:43:49.000000000 +0100 @@ -2,13 +2,13 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.4.0 + rev: v4.1.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - id: check-added-large-files - repo: https://github.com/asottile/pyupgrade - rev: v1.25.2 + rev: v2.31.0 hooks: - id: pyupgrade diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/.travis.yml new/django-push-notifications-3.0.0/.travis.yml --- old/django-push-notifications-2.0.0/.travis.yml 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/.travis.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,38 +0,0 @@ -# https://travis-ci.org/jazzband/django-push-notifications -sudo: false -language: python -python: -- 3.5 -- 3.6 -- 3.7 -- 3.8 -cache: pip -dist: xenial -install: travis_retry pip install tox-travis -script: tox -stages: -- test -- name: deploy - if: repo = jazzband/django-push-notifications AND tag IS present -jobs: - include: - - stage: test - - stage: deploy - install: skip - script: skip - python: 3.7 - env: skip - deploy: - provider: pypi - user: jazzband - server: https://jazzband.co/projects/django-push-notifications/upload - distributions: sdist bdist_wheel - password: - secure: ICRZGeqLWsqEtg9Iz62SHGOktUQEN+8h4wp0RKJJhcPIj59aKJNV+ET1wM+Xsh6OgpX2Ddy2AF7vD7pDP8kbWyCVyQNeK2/Ejo9SC7tVaVUIf5VAFXmkMymlAwUc6lKYrLW2Ls4PEqvSKikHcHp20pna6jJvg0Msa11j/KYP9eM= - on: - tags: true - repo: jazzband/django-push-notifications -notifications: - email: - on_failure: always - on_success: change diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/CODE_OF_CONDUCT.md new/django-push-notifications-3.0.0/CODE_OF_CONDUCT.md --- old/django-push-notifications-2.0.0/CODE_OF_CONDUCT.md 1970-01-01 01:00:00.000000000 +0100 +++ new/django-push-notifications-3.0.0/CODE_OF_CONDUCT.md 2022-02-14 03:43:49.000000000 +0100 @@ -0,0 +1,46 @@ +# Code of Conduct + +As contributors and maintainers of the Jazzband projects, and in the interest of +fostering an open and welcoming community, we pledge to respect all people who +contribute through reporting issues, posting feature requests, updating documentation, +submitting pull requests or patches, and other activities. + +We are committed to making participation in the Jazzband a harassment-free experience +for everyone, regardless of the level of experience, gender, gender identity and +expression, sexual orientation, disability, personal appearance, body size, race, +ethnicity, age, religion, or nationality. + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery +- Personal attacks +- Trolling or insulting/derogatory comments +- Public or private harassment +- Publishing other's private information, such as physical or electronic addresses, + without explicit permission +- Other unethical or unprofessional conduct + +The Jazzband roadies have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are not +aligned to this Code of Conduct, or to ban temporarily or permanently any contributor +for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +By adopting this Code of Conduct, the roadies commit themselves to fairly and +consistently applying these principles to every aspect of managing the jazzband +projects. Roadies who do not follow or enforce the Code of Conduct may be permanently +removed from the Jazzband roadies. + +This code of conduct applies both within project spaces and in public spaces when an +individual is representing the project or its community. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by +contacting the roadies at `road...@jazzband.co`. All complaints will be reviewed and +investigated and will result in a response that is deemed necessary and appropriate to +the circumstances. Roadies are obligated to maintain confidentiality with regard to the +reporter of an incident. + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version +1.3.0, available at [https://contributor-covenant.org/version/1/3/0/][version] + +[homepage]: https://contributor-covenant.org +[version]: https://contributor-covenant.org/version/1/3/0/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/README.rst new/django-push-notifications-3.0.0/README.rst --- old/django-push-notifications-2.0.0/README.rst 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/README.rst 2022-02-14 03:43:49.000000000 +0100 @@ -1,15 +1,21 @@ django-push-notifications ========================= -.. image:: https://travis-ci.org/jazzband/django-push-notifications.svg?branch=master - :target: https://travis-ci.org/jazzband/django-push-notifications .. image:: https://jazzband.co/static/img/badge.svg - :target: https://jazzband.co/ - :alt: Jazzband + :target: https://jazzband.co/ + :alt: Jazzband -A minimal Django app that implements Device models that can send messages through APNS, FCM/GCM and WNS. +.. image:: https://github.com/jazzband/django-push-notifications/workflows/Test/badge.svg + :target: https://github.com/jazzband/django-push-notifications/actions + :alt: GitHub Actions -The app implements three models: ``GCMDevice``, ``APNSDevice`` and ``WNSDevice``. Those models share the same attributes: +.. image:: https://codecov.io/gh/jazzband/django-push-notifications/branch/master/graph/badge.svg?token=PcC594rhI4 + :target: https://codecov.io/gh/jazzband/django-push-notifications + :alt: Code coverage + +A minimal Django app that implements Device models that can send messages through APNS, FCM/GCM, WNS and WebPush. + +The app implements four models: ``GCMDevice``, ``APNSDevice``, ``WNSDevice`` and ``WebPushDevice``. Those models share the same attributes: - ``name`` (optional): A name for the device. - ``active`` (default True): A boolean that determines whether the device will be sent notifications. - ``user`` (optional): A foreign key to auth.User, if you wish to link the device to a specific user. @@ -18,18 +24,19 @@ The app also implements an admin panel, through which you can test single and bulk notifications. Select one or more -FCM/GCM, APNS or WNS devices and in the action dropdown, select "Send test message" or "Send test message in bulk", accordingly. +FCM/GCM, APNS, WNS or WebPush devices and in the action dropdown, select "Send test message" or "Send test message in bulk", accordingly. Note that sending a non-bulk test message to more than one device will just iterate over the devices and send multiple single messages. UPDATE_ON_DUPLICATE_REG_ID: Transform create of an existing Device (based on registration id) into a update. See below Update of device with duplicate registration ID for more details. Dependencies ------------ -- Python 3.5+ -- Django 1.11+ +- Python 3.6+ +- Django 2.2+ - For the API module, Django REST Framework 3.7+ is required. -- For WebPush (WP), pywebpush 1.3.0+ is required. py-vapid 1.3.0+ is required for generating the WebPush private key; however this +- For WebPush (WP), pywebpush 1.3.0+ is required (optional). py-vapid 1.3.0+ is required for generating the WebPush private key; however this step does not need to occur on the application server. +- For Apple Push (APNS), apns2 0.3+ is required (optional). Setup ----- @@ -37,7 +44,7 @@ .. code-block:: shell - $ pip install django-push-notifications + $ pip install django-push-notifications[WP,APNS] Edit your settings.py file: @@ -67,6 +74,7 @@ If you are planning on running your project with ``APNS_USE_SANDBOX=True``, then make sure you have set the *development* certificate as your ``APNS_CERTIFICATE``. Otherwise the app will not be able to connect to the correct host. See settings_ for details. + For more information about how to generate certificates, see `docs/APNS <https://github.com/jazzband/django-push-notifications/blob/master/docs/APNS.rst>`_. You can learn more about APNS certificates `here <https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html>`_. @@ -91,10 +99,13 @@ **APNS settings** -- ``APNS_CERTIFICATE``: Absolute path to your APNS certificate file. Certificates with passphrases are not supported. Read more about `Generation of an APNS PEM file <https://github.com/jazzband/django-push-notifications/blob/master/docs/APNS.rst>`_. +- ``APNS_CERTIFICATE``: Absolute path to your APNS certificate file. Certificates with passphrases are not supported. If iOS application was build with "Release" flag, you need to use production certificate, otherwise debug. Read more about `Generation of an APNS PEM file <https://github.com/jazzband/django-push-notifications/blob/master/docs/APNS.rst>`_. +- ``APNS_AUTH_KEY_PATH``: Absolute path to your APNS signing key file for `Token-Based Authentication <https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_token-based_connection_to_apns>`_ . Use this instead of ``APNS_CERTIFICATE`` if you are using ``.p8`` signing key certificate. +- ``APNS_AUTH_KEY_ID``: The 10-character Key ID you obtained from your Apple developer account +- ``APNS_TEAM_ID``: 10-character Team ID you use for developing your company???s apps for iOS. - ``APNS_TOPIC``: The topic of the remote notification, which is typically the bundle ID for your app. If you omit this header and your APNs certificate does not specify multiple topics, the APNs server uses the certificate???s Subject as the default topic. - ``APNS_USE_ALTERNATIVE_PORT``: Use port 2197 for APNS, instead of default port 443. -- ``APNS_USE_SANDBOX``: Use 'api.development.push.apple.com', instead of default host 'api.push.apple.com'. +- ``APNS_USE_SANDBOX``: Use 'api.development.push.apple.com', instead of default host 'api.push.apple.com'. Default value depends on ``DEBUG`` setting of your environment: if ``DEBUG`` is True and you use production certificate, you should explicitly set ``APNS_USE_SANDBOX`` to False. **FCM/GCM settings** @@ -183,7 +194,49 @@ } return outputArray; } - function loadVersionBrowser (userAgent) { + + function loadVersionBrowser () { + if ("userAgentData" in navigator) { + // navigator.userAgentData is not available in + // Firefox and Safari + const uaData = navigator.userAgentData; + // Outputs of navigator.userAgentData.brands[n].brand are e.g. + // Chrome: 'Google Chrome' + // Edge: 'Microsoft Edge' + // Opera: 'Opera' + let browsername; + let browserversion; + let chromeVersion = null; + for (var i = 0; i < uaData.brands.length; i++) { + let brand = uaData.brands[i].brand; + browserversion = uaData.brands[i].version; + if (brand.match(/opera|chrome|edge|safari|firefox|msie|trident/i) !== null) { + // If we have a chrome match, save the match, but try to find another match + // E.g. Edge can also produce a false Chrome match. + if (brand.match(/chrome/i) !== null) { + chromeVersion = browserversion; + } + // If this is not a chrome match return immediately + else { + browsername = brand.substr(brand.indexOf(' ')+1); + return { + name: browsername, + version: browserversion + } + } + } + } + // No non-Chrome match was found. If we have a chrome match, return it. + if (chromeVersion !== null) { + return { + name: "chrome", + version: chromeVersion + } + } + } + // If no userAgentData is not present, or if no match via userAgentData was found, + // try to extract the browser name and version from userAgent + const userAgent = navigator.userAgent; var ua = userAgent, tem, M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; if (/trident/i.test(M[1])) { tem = /\brv[ :]+(\d+)/g.exec(ua) || []; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/__init__.py new/django-push-notifications-3.0.0/push_notifications/__init__.py --- old/django-push-notifications-2.0.0/push_notifications/__init__.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/__init__.py 2022-02-14 03:43:49.000000000 +0100 @@ -1,4 +1,8 @@ -import pkg_resources +try: + # Python 3.8+ + import importlib.metadata as importlib_metadata +except ImportError: + # <Python 3.7 and lower + import importlib_metadata - -__version__ = pkg_resources.require("django-push-notifications")[0].version +__version__ = importlib_metadata.version("django-push-notifications") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/admin.py new/django-push-notifications-3.0.0/push_notifications/admin.py --- old/django-push-notifications-2.0.0/push_notifications/admin.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/admin.py 2022-02-14 03:43:49.000000000 +0100 @@ -1,13 +1,11 @@ from django.apps import apps from django.contrib import admin, messages -from django.utils.encoding import force_text -from django.utils.translation import ugettext_lazy as _ +from django.utils.encoding import force_str +from django.utils.translation import gettext_lazy as _ -from .apns import APNSServerError -from .gcm import GCMError +from .exceptions import APNSServerError, GCMError, WebPushError from .models import APNSDevice, GCMDevice, WebPushDevice, WNSDevice from .settings import PUSH_NOTIFICATIONS_SETTINGS as SETTINGS -from .webpush import WebPushError User = apps.get_model(*SETTINGS["USER_MODEL"].split(".")) @@ -45,7 +43,7 @@ except APNSServerError as e: errors.append(e.status) except WebPushError as e: - errors.append(force_text(e)) + errors.append(force_str(e)) if bulk: break @@ -57,13 +55,21 @@ if "error" in r["results"][0]: errors.append(r["results"][0]["error"]) else: - try: - errors = [r["error"] for r in ret[0][0]["results"] if "error" in r] - except TypeError: - for entry in ret[0][0]: - errors = errors + [r["error"] for r in entry["results"] if "error" in r] - except IndexError: - pass + if "results" in ret[0][0]: + try: + errors = [r["error"] for r in ret[0][0]["results"] if "error" in r] + except TypeError: + for entry in ret[0][0]: + errors = errors + [r["error"] for r in entry["results"] if "error" in r] + except IndexError: + pass + else: + # different format, e.g.: + # [{'some_token1': 'Success', + # 'some_token2': 'BadDeviceToken'}] + for key, value in ret[0][0].items(): + if value.lower() != "success": + errors.append(value) if errors: self.message_user( request, _("Some messages could not be processed: %r" % (", ".join(errors))), @@ -73,14 +79,24 @@ if bulk: # When the queryset exceeds the max_recipients value, the # send_message method returns a list of dicts, one per chunk - try: - success = ret[0][0]["success"] - except TypeError: - success = 0 - for entry in ret[0][0]: - success = success + entry["success"] - if success == 0: - return + if "results" in ret[0][0]: + try: + success = ret[0][0]["success"] + except TypeError: + success = 0 + for entry in ret[0][0]: + success = success + entry["success"] + if success == 0: + return + else: + # different format, e.g.: + # [{'some_token1': 'Success', + # 'some_token2': 'BadDeviceToken'}] + success = [] + for key, value in ret[0][0].items(): + if value.lower() == "success": + success.append(key) + elif len(errors) == len(ret): return if errors: @@ -117,7 +133,17 @@ list_filter = ("active", "cloud_message_type") +class WebPushDeviceAdmin(DeviceAdmin): + list_display = ("__str__", "browser", "user", "active", "date_created") + list_filter = ("active", "browser") + + if hasattr(User, "USERNAME_FIELD"): + search_fields = ("name", "registration_id", "user__%s" % (User.USERNAME_FIELD)) + else: + search_fields = ("name", "registration_id") + + admin.site.register(APNSDevice, DeviceAdmin) admin.site.register(GCMDevice, GCMDeviceAdmin) admin.site.register(WNSDevice, DeviceAdmin) -admin.site.register(WebPushDevice, DeviceAdmin) +admin.site.register(WebPushDevice, WebPushDeviceAdmin) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/api/rest_framework.py new/django-push-notifications-3.0.0/push_notifications/api/rest_framework.py --- old/django-push-notifications-2.0.0/push_notifications/api/rest_framework.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/api/rest_framework.py 2022-02-14 03:43:49.000000000 +0100 @@ -132,7 +132,7 @@ # Mixins -class DeviceViewSetMixin(object): +class DeviceViewSetMixin: lookup_field = "registration_id" def create(self, request, *args, **kwargs): @@ -168,7 +168,7 @@ return super(DeviceViewSetMixin, self).perform_update(serializer) -class AuthorizedMixin(object): +class AuthorizedMixin: permission_classes = (permissions.IsAuthenticated, IsOwner) def get_queryset(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/apns.py new/django-push-notifications-3.0.0/push_notifications/apns.py --- old/django-push-notifications-2.0.0/push_notifications/apns.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/apns.py 2022-02-14 03:43:49.000000000 +0100 @@ -13,21 +13,7 @@ from . import models from .conf import get_manager -from .exceptions import NotificationError - - -class APNSError(NotificationError): - pass - - -class APNSUnsupportedPriority(APNSError): - pass - - -class APNSServerError(APNSError): - def __init__(self, status): - super(APNSServerError, self).__init__(status) - self.status = status +from .exceptions import APNSError, APNSUnsupportedPriority, APNSServerError def _apns_create_socket(creds=None, application_id=None): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/compat.py new/django-push-notifications-3.0.0/push_notifications/compat.py --- old/django-push-notifications-2.0.0/push_notifications/compat.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/compat.py 2022-02-14 03:43:49.000000000 +0100 @@ -1,10 +1,4 @@ # flake8:noqa - -try: - from urllib.error import HTTPError - from urllib.parse import urlencode - from urllib.request import Request, urlopen -except ImportError: - # Python 2 support - from urllib2 import HTTPError, Request, urlopen - from urllib import urlencode +from urllib.error import HTTPError +from urllib.parse import urlencode +from urllib.request import Request, urlopen diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/conf/app.py new/django-push-notifications-3.0.0/push_notifications/conf/app.py --- old/django-push-notifications-2.0.0/push_notifications/conf/app.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/conf/app.py 2022-02-14 03:43:49.000000000 +0100 @@ -231,6 +231,7 @@ application_config.setdefault("POST_URL", { "CHROME": "https://fcm.googleapis.com/fcm/send", "OPERA": "https://fcm.googleapis.com/fcm/send", + "EDGE": "https://wns2-par02p.notify.windows.com/w", "FIREFOX": "https://updates.push.services.mozilla.com/wpush/v2", }) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/conf/base.py new/django-push-notifications-3.0.0/push_notifications/conf/base.py --- old/django-push-notifications-2.0.0/push_notifications/conf/base.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/conf/base.py 2022-02-14 03:43:49.000000000 +0100 @@ -1,7 +1,7 @@ from django.core.exceptions import ImproperlyConfigured -class BaseConfig(object): +class BaseConfig: def has_auth_token_creds(self, application_id=None): raise NotImplementedError diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/conf/legacy.py new/django-push-notifications-3.0.0/push_notifications/conf/legacy.py --- old/django-push-notifications-2.0.0/push_notifications/conf/legacy.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/conf/legacy.py 2022-02-14 03:43:49.000000000 +0100 @@ -9,7 +9,7 @@ ] -class empty(object): +class empty: pass diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/exceptions.py new/django-push-notifications-3.0.0/push_notifications/exceptions.py --- old/django-push-notifications-2.0.0/push_notifications/exceptions.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/exceptions.py 2022-02-14 03:43:49.000000000 +0100 @@ -1,2 +1,27 @@ class NotificationError(Exception): pass + + +# APNS +class APNSError(NotificationError): + pass + + +class APNSUnsupportedPriority(APNSError): + pass + + +class APNSServerError(APNSError): + def __init__(self, status): + super().__init__(status) + self.status = status + + +# GCM +class GCMError(NotificationError): + pass + + +# Web Push +class WebPushError(NotificationError): + pass diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/fields.py new/django-push-notifications-3.0.0/push_notifications/fields.py --- old/django-push-notifications-2.0.0/push_notifications/fields.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/fields.py 2022-02-14 03:43:49.000000000 +0100 @@ -4,7 +4,7 @@ from django import forms from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator from django.db import connection, models -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ __all__ = ["HexadecimalField", "HexIntegerField"] @@ -14,16 +14,14 @@ hex_re = re.compile(r"^(([0-9A-f])|(0x[0-9A-f]))+$") -signed_integer_engines = [ - "django.db.backends.postgresql", - "django.db.backends.postgresql_psycopg2", - "django.contrib.gis.db.backends.postgis", - "django.db.backends.sqlite3" +signed_integer_vendors = [ + "postgresql", + "sqlite", ] def _using_signed_storage(): - return connection.settings_dict["ENGINE"] in signed_integer_engines + return connection.vendor in signed_integer_vendors def _signed_to_unsigned_integer(value): @@ -79,10 +77,9 @@ ] def db_type(self, connection): - engine = connection.settings_dict["ENGINE"] - if "mysql" in engine: + if "mysql" == connection.vendor: return "bigint unsigned" - elif "sqlite" in engine: + elif "sqlite" == connection.vendor: return "UNSIGNED BIG INT" else: return super(HexIntegerField, self).db_type(connection=connection) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/gcm.py new/django-push-notifications-3.0.0/push_notifications/gcm.py --- old/django-push-notifications-2.0.0/push_notifications/gcm.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/gcm.py 2022-02-14 03:43:49.000000000 +0100 @@ -11,7 +11,7 @@ from .compat import Request, urlopen from .conf import get_manager -from .exceptions import NotificationError +from .exceptions import GCMError from .models import GCMDevice @@ -22,18 +22,13 @@ ] FCM_OPTIONS_KEYS = [ "collapse_key", "priority", "content_available", "delay_while_idle", "time_to_live", - "restricted_package_name", "dry_run" + "restricted_package_name", "dry_run", "mutable_content" ] FCM_NOTIFICATIONS_PAYLOAD_KEYS = [ - "title", "body", "icon", "sound", "badge", "color", "tag", "click_action", + "title", "body", "icon", "image", "sound", "badge", "color", "tag", "click_action", "body_loc_key", "body_loc_args", "title_loc_key", "title_loc_args", "android_channel_id" ] - -class GCMError(NotificationError): - pass - - def _chunks(l, n): """ Yield successive chunks from list \a l with a minimum size \a n diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/migrations/0008_webpush_add_edge.py new/django-push-notifications-3.0.0/push_notifications/migrations/0008_webpush_add_edge.py --- old/django-push-notifications-2.0.0/push_notifications/migrations/0008_webpush_add_edge.py 1970-01-01 01:00:00.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/migrations/0008_webpush_add_edge.py 2022-02-14 03:43:49.000000000 +0100 @@ -0,0 +1,18 @@ +# Generated by Django 3.2.8 on 2021-11-12 09:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('push_notifications', '0007_uniquesetting'), + ] + + operations = [ + migrations.AlterField( + model_name='webpushdevice', + name='browser', + field=models.CharField(choices=[('CHROME', 'Chrome'), ('FIREFOX', 'Firefox'), ('OPERA', 'Opera'), ('EDGE', 'Edge')], default='CHROME', help_text='Currently only support to Chrome, Firefox, Edge and Opera browsers', max_length=10, verbose_name='Browser'), + ), + ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/migrations/0009_alter_apnsdevice_device_id.py new/django-push-notifications-3.0.0/push_notifications/migrations/0009_alter_apnsdevice_device_id.py --- old/django-push-notifications-2.0.0/push_notifications/migrations/0009_alter_apnsdevice_device_id.py 1970-01-01 01:00:00.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/migrations/0009_alter_apnsdevice_device_id.py 2022-02-14 03:43:49.000000000 +0100 @@ -0,0 +1,18 @@ +# Generated by Django 3.2.9 on 2022-01-10 09:03 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('push_notifications', '0008_webpush_add_edge'), + ] + + operations = [ + migrations.AlterField( + model_name='apnsdevice', + name='device_id', + field=models.UUIDField(blank=True, db_index=True, help_text='UUID / UIDevice.identifierForVendor()', null=True, verbose_name='Device ID'), + ), + ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/models.py new/django-push-notifications-3.0.0/push_notifications/models.py --- old/django-push-notifications-2.0.0/push_notifications/models.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/models.py 2022-02-14 03:43:49.000000000 +0100 @@ -1,5 +1,5 @@ from django.db import models -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from .fields import HexIntegerField from .settings import PUSH_NOTIFICATIONS_SETTINGS as SETTINGS @@ -14,6 +14,7 @@ ("CHROME", "Chrome"), ("FIREFOX", "Firefox"), ("OPERA", "Opera"), + ("EDGE", "Edge") ) @@ -56,7 +57,7 @@ class GCMDeviceQuerySet(models.query.QuerySet): def send_message(self, message, **kwargs): - if self: + if self.exists(): from .gcm import send_message as gcm_send_message data = kwargs.pop("extra", {}) @@ -121,7 +122,7 @@ class APNSDeviceQuerySet(models.query.QuerySet): def send_message(self, message, creds=None, **kwargs): - if self: + if self.exists(): from .apns import apns_send_bulk_message app_ids = self.filter(active=True).order_by("application_id")\ @@ -145,7 +146,7 @@ class APNSDevice(Device): device_id = models.UUIDField( verbose_name=_("Device ID"), blank=True, null=True, db_index=True, - help_text="UDID / UIDevice.identifierForVendor()" + help_text=_("UUID / UIDevice.identifierForVendor()") ) registration_id = models.CharField( verbose_name=_("Registration ID"), max_length=200, unique=SETTINGS["UNIQUE_REG_ID"] @@ -240,7 +241,7 @@ browser = models.CharField( verbose_name=_("Browser"), max_length=10, choices=BROWSER_TYPES, default=BROWSER_TYPES[0][0], - help_text=_("Currently only support to Chrome, Firefox and Opera browsers") + help_text=_("Currently only support to Chrome, Firefox, Edge and Opera browsers") ) objects = WebPushDeviceManager() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/settings.py new/django-push-notifications-3.0.0/push_notifications/settings.py --- old/django-push-notifications-2.0.0/push_notifications/settings.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/settings.py 2022-02-14 03:43:49.000000000 +0100 @@ -41,6 +41,7 @@ "CHROME": PUSH_NOTIFICATIONS_SETTINGS["FCM_POST_URL"], "OPERA": PUSH_NOTIFICATIONS_SETTINGS["FCM_POST_URL"], "FIREFOX": "https://updates.push.services.mozilla.com/wpush/v2", + "EDGE": "https://wns2-par02p.notify.windows.com/w", }) PUSH_NOTIFICATIONS_SETTINGS.setdefault("WP_PRIVATE_KEY", None) PUSH_NOTIFICATIONS_SETTINGS.setdefault("WP_CLAIMS", None) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/push_notifications/webpush.py new/django-push-notifications-3.0.0/push_notifications/webpush.py --- old/django-push-notifications-2.0.0/push_notifications/webpush.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/push_notifications/webpush.py 2022-02-14 03:43:49.000000000 +0100 @@ -1,11 +1,7 @@ from pywebpush import WebPushException, webpush from .conf import get_manager -from .exceptions import NotificationError - - -class WebPushError(NotificationError): - pass +from .exceptions import WebPushError def get_subscription_info(application_id, uri, browser, auth, p256dh): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/pyproject.toml new/django-push-notifications-3.0.0/pyproject.toml --- old/django-push-notifications-2.0.0/pyproject.toml 1970-01-01 01:00:00.000000000 +0100 +++ new/django-push-notifications-3.0.0/pyproject.toml 2022-02-14 03:43:49.000000000 +0100 @@ -0,0 +1,6 @@ +[build-system] +requires = ["setuptools>=30.3.0", "wheel", "setuptools_scm"] + +[tool.pytest.ini_options] +minversion = "6.0" +addopts = "--cov push_notifications --cov-append --cov-branch --cov-report term-missing --cov-report=xml" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/setup.cfg new/django-push-notifications-3.0.0/setup.cfg --- old/django-push-notifications-2.0.0/setup.cfg 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/setup.cfg 2022-02-14 03:43:49.000000000 +0100 @@ -1,6 +1,5 @@ [metadata] name = django-push-notifications -version = 2.0.0 description = Send push notifications to mobile devices through GCM, APNS or WNS and to WebPush (Chrome, Firefox and Opera) in Django author = Jerome Leclanche author_email = jer...@leclan.ch @@ -10,32 +9,40 @@ Development Status :: 5 - Production/Stable Environment :: Web Environment Framework :: Django - Framework :: Django :: 1.11 - Framework :: Django :: 2.0 - Framework :: Django :: 2.1 Framework :: Django :: 2.2 Framework :: Django :: 3.0 + Framework :: Django :: 3.1 + Framework :: Django :: 3.2 + Framework :: Django :: 4.0 Intended Audience :: Developers License :: OSI Approved :: MIT License Programming Language :: Python Programming Language :: Python :: 3 - Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 Topic :: Internet :: WWW/HTTP Topic :: System :: Networking [options] +python_requires = >= 3.6 packages = find: install_requires = - apns2>=0.3.0,<0.6.0;python_version<"3.5" - apns2>=0.3.0;python_version>="3.5" + Django>=2.2 + +setup_requires = + setuptools_scm + +[options.extras_require] +APNS = + apns2>=0.3.0 + importlib-metadata;python_version < "3.8" pywebpush>=1.3.0 - Django>=1.11 + Django>=2.2 + +WP = pywebpush>=1.3.0 + [options.packages.find] exclude = tests - -[bdist_wheel] -universal = 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/setup.py new/django-push-notifications-3.0.0/setup.py --- old/django-push-notifications-2.0.0/setup.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/setup.py 2022-02-14 03:43:49.000000000 +0100 @@ -1,6 +1,4 @@ #!/usr/bin/env python - from setuptools import setup - -setup() +setup(use_scm_version={"version_scheme": "post-release"}) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/tests/_mock.py new/django-push-notifications-3.0.0/tests/_mock.py --- old/django-push-notifications-2.0.0/tests/_mock.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/tests/_mock.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,4 +0,0 @@ -try: - from unittest import mock # noqa -except ImportError: - from mock import mock # noqa diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/tests/test_apns_models.py new/django-push-notifications-3.0.0/tests/test_apns_models.py --- old/django-push-notifications-2.0.0/tests/test_apns_models.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/tests/test_apns_models.py 2022-02-14 03:43:49.000000000 +0100 @@ -1,13 +1,13 @@ +from unittest import mock + from apns2.client import NotificationPriority from apns2.errors import BadTopic, PayloadTooLarge, Unregistered from django.conf import settings from django.test import TestCase, override_settings -from push_notifications.apns import APNSError +from push_notifications.exceptions import APNSError from push_notifications.models import APNSDevice -from ._mock import mock - class APNSModelTestCase(TestCase): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/tests/test_apns_push_payload.py new/django-push-notifications-3.0.0/tests/test_apns_push_payload.py --- old/django-push-notifications-2.0.0/tests/test_apns_push_payload.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/tests/test_apns_push_payload.py 2022-02-14 03:43:49.000000000 +0100 @@ -1,9 +1,10 @@ +from unittest import mock + from apns2.client import NotificationPriority from django.test import TestCase -from push_notifications.apns import APNSUnsupportedPriority, _apns_send - -from ._mock import mock +from push_notifications.apns import _apns_send +from push_notifications.exceptions import APNSUnsupportedPriority class APNSPushPayloadTest(TestCase): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/tests/test_gcm_push_payload.py new/django-push-notifications-3.0.0/tests/test_gcm_push_payload.py --- old/django-push-notifications-2.0.0/tests/test_gcm_push_payload.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/tests/test_gcm_push_payload.py 2022-02-14 03:43:49.000000000 +0100 @@ -1,8 +1,9 @@ +from unittest import mock + from django.test import TestCase from push_notifications.gcm import send_bulk_message, send_message -from ._mock import mock from .responses import GCM_JSON, GCM_JSON_MULTIPLE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/tests/test_legacy_config.py new/django-push-notifications-3.0.0/tests/test_legacy_config.py --- old/django-push-notifications-2.0.0/tests/test_legacy_config.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/tests/test_legacy_config.py 2022-02-14 03:43:49.000000000 +0100 @@ -2,7 +2,8 @@ from django.test import TestCase from push_notifications.conf import LegacyConfig, get_manager -from push_notifications.webpush import WebPushError, webpush_send_message +from push_notifications.exceptions import WebPushError +from push_notifications.webpush import webpush_send_message class LegacyConfigTestCase(TestCase): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/tests/test_models.py new/django-push-notifications-3.0.0/tests/test_models.py --- old/django-push-notifications-2.0.0/tests/test_models.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/tests/test_models.py 2022-02-14 03:43:49.000000000 +0100 @@ -1,4 +1,5 @@ import json +from unittest import mock from django.test import TestCase from django.utils import timezone @@ -8,7 +9,6 @@ from push_notifications.models import APNSDevice, GCMDevice from . import responses -from ._mock import mock class GCMModelTestCase(TestCase): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/tests/test_wns.py new/django-push-notifications-3.0.0/tests/test_wns.py --- old/django-push-notifications-2.0.0/tests/test_wns.py 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/tests/test_wns.py 2022-02-14 03:43:49.000000000 +0100 @@ -1,3 +1,4 @@ +from unittest import mock import xml.etree.ElementTree as ET from django.test import TestCase @@ -6,8 +7,6 @@ dict_to_xml_schema, wns_send_bulk_message, wns_send_message ) -from ._mock import mock - class WNSSendMessageTestCase(TestCase): def setUp(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-push-notifications-2.0.0/tox.ini new/django-push-notifications-3.0.0/tox.ini --- old/django-push-notifications-2.0.0/tox.ini 2020-03-10 12:03:47.000000000 +0100 +++ new/django-push-notifications-3.0.0/tox.ini 2022-02-14 03:43:49.000000000 +0100 @@ -1,37 +1,52 @@ [tox] +skipsdist = True +usedevelop = true envlist = - py{35,36,37,38}-django{111,20,21,22}-apns{030,060} - py{36,37,38}-django30-apns{030,060} - py37-flake8 + py{36,37,38,39}-dj{22,32} + py{38,39}-dj{40,main} + flake8 + +[gh-actions] +python = + 3.6: py36 + 3.7: py37 + 3.8: py38 + 3.9: py39, flake8 + +[gh-actions:env] +DJANGO = + 2.2: dj22 + 3.2: dj32 + 4.0: dj40 + main: djmain [testenv] +usedevelop = true setenv = - PYTHONWARNINGS = all - DJANGO_SETTINGS_MODULE = tests.settings - PYTHONPATH = {toxinidir} + PYTHONWARNINGS = all + DJANGO_SETTINGS_MODULE = tests.settings + PYTHONPATH = {toxinidir} commands = - pytest - pytest --ds=tests.settings_unique tests/tst_unique.py + pytest + pytest --ds=tests.settings_unique tests/tst_unique.py deps = - pytest - pytest-django - mock - pywebpush - djangorestframework>=3.7 - django111: Django>=1.11,<2.0 - django20: Django>=2.0,<2.1 - django21: Django>=2.1,<2.2 - django22: Django>=2.2,<3.0 - django30: Django>=3.0,<3.1 - apns030: apns2>=0.3.0,<0.6.0 - apns060: apns2>=0.6.0 + apns2 + pytest + pytest-cov + pytest-django + pywebpush + djangorestframework + dj22: Django>=2.2,<3.0 + dj32: Django>=3.2,<3.3 + dj40: Django>=4.0,<4.1 + djmain: https://github.com/django/django/archive/main.tar.gz -[testenv:py37-flake8] +[testenv:flake8] commands = flake8 --exit-zero deps = - flake8==3.5.0 - flake8-isort - flake8-quotes + flake8 + flake8-isort + flake8-quotes [flake8] ignore = W191,E503