diff --git a/.github/workflows/django.yml b/.github/workflows/django.yml index 5bfb557..a562e71 100644 --- a/.github/workflows/django.yml +++ b/.github/workflows/django.yml @@ -6,25 +6,37 @@ on: pull_request: branches: [ main ] +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest + timeout-minutes: 15 strategy: + fail-fast: false max-parallel: 4 matrix: python-version: ['3.12', '3.13', '3.14', '3.15'] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v7 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} + cache: pip + cache-dependency-path: | + requirements.txt + requirements_tests.txt + requirements_lint.txt - name: Install Dependencies run: | - pip --disable-pip-version-check install --no-compile -r requirements_tests.txt + python -m pip --disable-pip-version-check install --no-compile -r requirements_tests.txt + python -m pip check - name: Run Tests run: | - pytest --cov=testapp --cov=tpay_module --cov-report term-missing - flake8 . + python -m pytest --cov=testapp --cov=tpay_module --cov-report term-missing + - name: Lint + run: python -m flake8 . diff --git a/.gitignore b/.gitignore index d88a8a9..c610caf 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ settings_local.py .coverage build dist -*.egg-info \ No newline at end of file +*.egg-info +__pycache__/ +.pytest_cache/ diff --git a/README.md b/README.md index ba876e7..724a841 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,20 @@ path('tpay-ipn/', TPayIpnHandler.as_view(), name='tpay_ipn'), Then, write code that will handle payments using TPayModule class. The examples will be providen soon (how to create transaction and et cetera). +### Running checks: +Install the test and lint dependencies, then run the same checks as GitHub Actions: + +```sh +python -m pip install -r requirements_tests.txt +python -m pip check +python -m pytest --cov=testapp --cov=tpay_module --cov-report term-missing +python -m flake8 . +``` + +CI tests Python 3.12, 3.13, 3.14, and 3.15 with Django 5.2 LTS. +Django 5.2 officially supports Python through 3.14; Python 3.15 is additionally tested here. +`requirements_dev.txt` includes these dependencies plus optional development tools. + ### Django available custom settings: `TPAY_CLIENT_ID` - client ID from tpay settings. `TPAY_CLIENT_SECRET` - secret from tpay settings. diff --git a/requirements.txt b/requirements.txt index 69f8900..6f6e7f8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ -requests==2.32.3 -Django==5.1.2 -django-money==3.0.0 -django-rosetta==0.9.9 -legacy-cgi==2.6.1 +requests==2.34.2 +Django==5.2.18 +django-money==3.6.2 +django-rosetta==0.10.3 diff --git a/requirements_dev.txt b/requirements_dev.txt index 68f2bd6..6dd139b 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,25 +1,12 @@ --r requirements.txt +-r requirements_tests.txt codecov==2.1.13 coloredlogs==14.0 -coverage==7.6.3 django-naomi==0.8 -flake8-blind-except==0.1.1 -flake8-commas==4.0.0 -flake8-docstrings==1.5.0 -flake8-isort==5.0.3 -flake8-pep3101==1.3.0 -flake8-quotes==3.2.0 -flake8-string-format==0.3.0 -flake8==5.0.4 -ipython==7.16.3 -isort==5.7.0 -mock==4.0.3 -parameterized==0.8.1 -pydocstyle==5.1.1 +ipython==9.17.1 python-coveralls==2.9.3 -sphinx==3.3.0 -autopep8==1.5.4 +sphinx==9.1.0 +autopep8==2.3.2 pypiserver==1.5.0 hyperframe==6.0.1 h2==4.1.0 diff --git a/requirements_lint.txt b/requirements_lint.txt new file mode 100644 index 0000000..8b47643 --- /dev/null +++ b/requirements_lint.txt @@ -0,0 +1,10 @@ +flake8==7.4.1 +flake8-blind-except==0.2.1 +flake8-commas==4.0.0 +flake8-docstrings==1.7.0 +flake8-isort==7.0.0 +flake8-pep3101==3.0.0 +flake8-quotes==3.4.0 +flake8-string-format==0.4.0 +isort==9.0.2 +pydocstyle==6.3.0 diff --git a/requirements_tests.txt b/requirements_tests.txt index d0bab8c..1f63d1b 100644 --- a/requirements_tests.txt +++ b/requirements_tests.txt @@ -1,8 +1,12 @@ --r requirements_dev.txt +-r requirements.txt +-r requirements_lint.txt -factory_boy==3.3.1 -pytest-cov==5.0.0 -pytest-django==4.9.0 -pytest==8.3.3 -freezegun==1.5.1 -django-silk==5.2.0 +coverage==7.16.2 +factory_boy==3.3.3 +pytest-cov==7.1.0 +pytest-django==4.14.0 +pytest==9.1.1 +freezegun==1.5.5 +mock==5.2.0 +parameterized==0.9.0 +django-silk==5.6.0 diff --git a/setup.cfg b/setup.cfg index 9d3801a..f846539 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,7 +10,7 @@ license = BSD-3-Clause classifiers = Environment :: Web Environment Framework :: Django - Framework :: Django :: 5.1.2 + Framework :: Django :: 5.2 Intended Audience :: Developers License :: OSI Approved :: BSD License Operating System :: OS Independent @@ -21,10 +21,12 @@ classifiers = Programming Language :: Python :: 3.11 Programming Language :: Python :: 3.12 Programming Language :: Python :: 3.13 + Programming Language :: Python :: 3.14 + Programming Language :: Python :: 3.15 Topic :: Internet :: WWW/HTTP Topic :: Internet :: WWW/HTTP :: Dynamic Content [options] include_package_data = true -packages = find: \ No newline at end of file +packages = find: diff --git a/setup.py b/setup.py index a269730..9249966 100644 --- a/setup.py +++ b/setup.py @@ -11,8 +11,8 @@ ], ), install_requires=[ - 'requests==2.32.3', - 'django==5.1.2', - 'django-money==3.0.0', + 'requests==2.34.2', + 'django==5.2.18', + 'django-money==3.6.2', ], ) diff --git a/tpay_module/tests/test_views.py b/tpay_module/tests/test_views.py index 7b751ab..e1c9eea 100644 --- a/tpay_module/tests/test_views.py +++ b/tpay_module/tests/test_views.py @@ -1,6 +1,5 @@ """Test TPay views.""" # Standard Library -import cgi import hashlib import random import string @@ -54,8 +53,7 @@ def test_tpay_ipn_handler_no_secure_code(self): # noqa: D102 'tr_paid': 0.01, 'tr_status': TPayIPNForm.SUCCESS_STATUS, }) - charset = cgi.parse_header( - response.headers['Content-Type'])[1]['charset'] + charset = response.charset self.assertEqual(response.status_code, 200) self.assertEqual(response.content.decode(charset), 'FALSE') @@ -74,8 +72,7 @@ def test_tpay_ipn_handler_wrong_md5(self): # noqa: D102 'tr_status': TPayIPNForm.SUCCESS_STATUS, 'md5sum': md5sum, }) - charset = cgi.parse_header( - response.headers['Content-Type'])[1]['charset'] + charset = response.charset self.assertEqual(response.status_code, 200) self.assertEqual(response.content.decode(charset), 'FALSE') @@ -84,7 +81,7 @@ def test_tpay_ipn_request_successful(self): """Test tpay ipn if request is empty.""" url = reverse('tpay_ipn') payment = TPayPaymentFactory() - get_price = '{:.2f}'.format(payment.price.amount) # noqa: P101 + get_price = f'{payment.price.amount:.2f}' payment_part = f'{get_price}{payment.number}' data_id = random.randint(1000000000, 9999999999) data_tr_id = random.randint(1000000000, 9999999999) @@ -100,8 +97,7 @@ def test_tpay_ipn_request_successful(self): 'tr_status': TPayIPNForm.SUCCESS_STATUS, 'md5sum': md5sum, }) - charset = cgi.parse_header( - response.headers['Content-Type'])[1]['charset'] + charset = response.charset self.assertEqual(response.status_code, 200) payment.refresh_from_db() self.assertTrue(payment.is_finished) diff --git a/tpay_module/tpay_api.py b/tpay_module/tpay_api.py index e112233..2509642 100644 --- a/tpay_module/tpay_api.py +++ b/tpay_module/tpay_api.py @@ -135,7 +135,7 @@ def create_transaction( user, ) return response_data - except BaseException: # noqa: D104 + except BaseException: # noqa: B902 pass return {} @@ -154,7 +154,7 @@ def pay_for_card_payment(self, transaction_id, card_data): json=data, headers=self.get_headers(), ).json() return response_data - except BaseException: + except BaseException: # noqa: B902 pass return {} @@ -173,7 +173,7 @@ def pay_by_saved_card(self, transaction_id, card_token): json=data, headers=self.get_headers(), ).json() return response_data - except BaseException: + except BaseException: # noqa: B902 pass return {} @@ -185,7 +185,7 @@ def get_transaction(self, transaction_id): json={}, headers=self.get_headers(), ).json() return response_data - except BaseException: + except BaseException: # noqa: B902 pass return {} @@ -204,7 +204,7 @@ def get_all_transactions(self, limit=None, from_dt=None, to_dt=None): json=filter_data, headers=self.get_headers(), ).json() return response_data - except BaseException: + except BaseException: # noqa: B902 pass return {} diff --git a/tpay_module/views.py b/tpay_module/views.py index 62acec8..af9d0f4 100644 --- a/tpay_module/views.py +++ b/tpay_module/views.py @@ -48,7 +48,7 @@ def post(self, request, *args, **kwargs): # noqa: D102 probable_md5 = hashlib.md5( f'{id_part}{payment_part}{secure_code}'.encode('utf-8'), ).hexdigest() - get_price = '{:.2f}'.format(float(request.POST['tr_paid'])) # noqa: P101 + get_price = f"{float(request.POST['tr_paid']):.2f}" price_check = Decimal(get_price) == payment.price.amount md5_check = data['md5sum'] == probable_md5 if price_check and md5_check and not payment.is_finished: