From 1619d072f13442306b94d6f2162d5c582f1ba21a Mon Sep 17 00:00:00 2001 From: mrroot5 Date: Mon, 6 Oct 2025 13:08:51 +0200 Subject: [PATCH 1/8] Added deprecations command to makefile --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index df604a5..28ba729 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: shell, test, dev, start, build, migrate, shell_plus PROJECT_NAME=django_atomic_transactions -DOCKER_COMPOSE=docker-compose -p ${PROJECT_NAME} -f environment/docker-compose.yml +DOCKER_COMPOSE=docker compose -p ${PROJECT_NAME} -f environment/docker-compose.yml DOCKER_COMPOSE_RUN_WEB=${DOCKER_COMPOSE} run --rm default: build @@ -27,6 +27,9 @@ uvicorn: test: build ${DOCKER_COMPOSE_RUN_WEB} web python manage.py test --failfast api +deprecations: build migrate + ${DOCKER_COMPOSE_RUN_WEB} web python -Wa manage.py test --failfast api + shell: ${DOCKER_COMPOSE_RUN_WEB} web ash From 86f17a77d55d79720e5dde73379971e84d37722e Mon Sep 17 00:00:00 2001 From: mrroot5 Date: Mon, 6 Oct 2025 13:09:11 +0200 Subject: [PATCH 2/8] Fixed assertDictContainsSubset deprecation warning --- src/api/tests.py | 106 +++++++++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 35 deletions(-) diff --git a/src/api/tests.py b/src/api/tests.py index ce9f804..1597161 100644 --- a/src/api/tests.py +++ b/src/api/tests.py @@ -1,15 +1,14 @@ -from typing import Optional, List - import re +from typing import List, Optional + from django.contrib.auth.models import User from django.test import TransactionTestCase +from faker import Faker from rest_framework.reverse import reverse from rest_framework.test import APITestCase from api.models import ClientAccount, ClientWallet, ClientWalletTransaction -from faker import Faker - # api.tests.ClientAccountApiTests.test_create_regular_user_and_sign_in class CommonApiTests(APITestCase): @@ -31,11 +30,6 @@ def create_user_auth( user.save() return user - # group, is_created = Group.objects.get_or_create(name='testgroup') - # user.groups.add(group) - # for perm in Permission.objects.all(): - # group.permissions.add(perm) - def create_client_account( self, name: Optional[str] = default_user_username, surname: Optional[str] = default_user_username, @@ -62,18 +56,6 @@ def create_client_transaction( amount=amount, client_wallet_account=client_wallet, **kwargs ) - # def create_user_auth(cls): - # user, is_created = User.objects.get_or_create(username='testuser') - # user.set_password('aaa') - # user.is_staff = True - # user.is_active = True - # user.is_superuser = True - # user.save() - # - # group, is_created = Group.objects.get_or_create(name='testgroup') - # user.groups.add(group) - # for perm in Permission.objects.all(): - # group.permissions.add(perm) def set_url(self, name: str, kwargs: object = None) -> None: self.url = reverse(name, kwargs=kwargs) @@ -128,7 +110,11 @@ def test_create_regular_user_and_sign_in(self): self.set_url('api:user_api-list') response = self.client.post(self.url, data=payload, format='json') self.assertEqual(201, response.status_code) - self.assertDictContainsSubset(response_data, response.json()) + + response_data_unique_items = set(response_data.items()) + response_json_unique_items = set(response.json().items()) + self.assertTrue(response_data_unique_items.issubset(response_json_unique_items)) + self.assertTrue( self.client.login(username=payload.get('username'), password=payload.get('password')), msg='Login error' @@ -151,7 +137,11 @@ def test_create_staff_user_and_sign_in(self): self.set_url('api:user_api-list') response = self.client.post(self.url, data=payload, format='json') self.assertEqual(201, response.status_code) - self.assertDictContainsSubset(response_data, response.json()) + + response_data_unique_items = set(response_data.items()) + response_json_unique_items = set(response.json().items()) + self.assertTrue(response_data_unique_items.issubset(response_json_unique_items)) + self.assertTrue( self.client.login(username=payload.get('username'), password=payload.get('password')), msg='Login error' @@ -183,7 +173,10 @@ def test_update_regular_user(self): self.set_url('api:user_api-detail', kwargs=api_url_params) response = self.client.patch(self.url, data=payload, format='json') self.assertEqual(200, response.status_code) - self.assertDictContainsSubset(response_data, response.json()) + + response_data_unique_items = set(response_data.items()) + response_json_unique_items = set(response.json().items()) + self.assertTrue(response_data_unique_items.issubset(response_json_unique_items)) def test_update_staff_user(self): username_password = self.fake.unique.name().lower().replace(' ', '_') @@ -212,7 +205,10 @@ def test_update_staff_user(self): response = self.client.patch(self.url, data=payload, format='json') self.assertEqual(200, response.status_code) - self.assertDictContainsSubset(response_data, response.json()) + + response_data_unique_items = set(response_data.items()) + response_json_unique_items = set(response.json().items()) + self.assertTrue(response_data_unique_items.issubset(response_json_unique_items)) class ClientAccountApiTests(CommonApiTests): @@ -261,7 +257,11 @@ def test_create_as_regular_user(self): self.set_url('api:client_api-list') response = self.client.post(self.url, data=payload, format='json') self.assertEqual(201, response.status_code) - self.assertDictContainsSubset(payload, response.json()) + + payload_unique_items = set(payload.items()) + response_json_unique_items = set(response.json().items()) + self.assertTrue(payload_unique_items.issubset(response_json_unique_items)) + self.assertTrue(ClientAccount.objects.get(user_account=user.id)) self.client.logout() @@ -283,7 +283,11 @@ def test_create_a_regular_user_as_staff_user(self): self.set_url('api:client_api-list') response = self.client.post(self.url, data=payload, format='json') self.assertEqual(201, response.status_code) - self.assertDictContainsSubset(payload, response.json()) + + payload_unique_items = set(payload.items()) + response_json_unique_items = set(response.json().items()) + self.assertTrue(payload_unique_items.issubset(response_json_unique_items)) + self.client.logout() def test_partial_update(self): @@ -298,7 +302,11 @@ def test_partial_update(self): self.set_url('api:client_api-detail', kwargs=api_url_params) response = self.client.patch(self.url, data=payload, format='json') self.assertEqual(200, response.status_code) - self.assertDictContainsSubset(payload, response.json()) + + payload_unique_items = set(payload.items()) + response_json_unique_items = set(response.json().items()) + self.assertTrue(payload_unique_items.issubset(response_json_unique_items)) + self.client.logout() def test_staff_updates_regular_user_account(self): @@ -313,7 +321,11 @@ def test_staff_updates_regular_user_account(self): self.set_url('api:client_api-detail', kwargs=api_url_params) response = self.client.patch(self.url, data=payload, format='json') self.assertEqual(200, response.status_code) - self.assertDictContainsSubset(payload, response.json()) + + payload_unique_items = set(payload.items()) + response_json_unique_items = set(response.json().items()) + self.assertTrue(payload_unique_items.issubset(response_json_unique_items)) + self.client.logout() def test_regular_user_can_not_update_staff_account(self): @@ -418,7 +430,11 @@ def test_create_regular_user_wallets_as_regular_user(self): self.set_url(f'{self.api_reverse_url}-list') response = self.client.post(self.url, data=payload, format='json') self.assertEqual(201, response.status_code) - self.assertDictContainsSubset(response_data, response.json()) + + response_data_unique_items = set(response_data.items()) + response_json_unique_items = set(response.json().items()) + self.assertTrue(response_data_unique_items.issubset(response_json_unique_items)) + print(f'{num_iterations} wallets done') self.client.logout() @@ -464,7 +480,11 @@ def test_create_regular_user_wallets_as_staff_user(self): self.set_url(f'{self.api_reverse_url}-list') response = self.client.post(self.url, data=payload, format='json') self.assertEqual(201, response.status_code) - self.assertDictContainsSubset(response_data, response.json()) + + response_data_unique_items = set(response_data.items()) + response_json_unique_items = set(response.json().items()) + self.assertTrue(response_data_unique_items.issubset(response_json_unique_items)) + print(f'{num_iterations} transactions done') self.client.logout() @@ -494,7 +514,11 @@ def test_create_staff_user_wallets_as_staff_user(self): self.set_url(f'{self.api_reverse_url}-list') response = self.client.post(self.url, data=payload, format='json') self.assertEqual(201, response.status_code) - self.assertDictContainsSubset(response_data, response.json()) + + response_data_unique_items = set(response_data.items()) + response_json_unique_items = set(response.json().items()) + self.assertTrue(response_data_unique_items.issubset(response_json_unique_items)) + print(f'{num_iterations} transactions done') self.client.logout() @@ -660,7 +684,11 @@ def test_create_regular_user_transactions_as_regular_user(self): self.set_url('api:client_wallet_transaction_api-list') response = self.client.post(self.url, data=payload, format='json') self.assertEqual(201, response.status_code) - self.assertDictContainsSubset(response_data, response.json()) + + response_data_unique_items = set(response_data.items()) + response_json_unique_items = set(response.json().items()) + self.assertTrue(response_data_unique_items.issubset(response_json_unique_items)) + print(f'{num_iterations} transactions done') self.client.logout() @@ -720,7 +748,11 @@ def test_create_regular_user_transactions_as_staff_user(self): self.set_url('api:client_wallet_transaction_api-list') response = self.client.post(self.url, data=payload, format='json') self.assertEqual(201, response.status_code) - self.assertDictContainsSubset(response_data, response.json()) + + response_data_unique_items = set(response_data.items()) + response_json_unique_items = set(response.json().items()) + self.assertTrue(response_data_unique_items.issubset(response_json_unique_items)) + print(f'{num_iterations} transactions done') self.client.logout() @@ -760,7 +792,11 @@ def test_create_staff_user_transactions_as_staff_user(self): self.set_url('api:client_wallet_transaction_api-list') response = self.client.post(self.url, data=payload, format='json') self.assertEqual(201, response.status_code) - self.assertDictContainsSubset(response_data, response.json()) + + response_data_unique_items = set(response_data.items()) + response_json_unique_items = set(response.json().items()) + self.assertTrue(response_data_unique_items.issubset(response_json_unique_items)) + print(f'{num_iterations} transactions done') self.client.logout() From de8bcc8b9b3adf9f0531ec5882ffe0969b9c4867 Mon Sep 17 00:00:00 2001 From: mrroot5 Date: Mon, 6 Oct 2025 13:09:36 +0200 Subject: [PATCH 3/8] Generated openapi schema --- src/api/serializers.py | 4 +- src/openapi-schema.yml | 696 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 699 insertions(+), 1 deletion(-) create mode 100644 src/openapi-schema.yml diff --git a/src/api/serializers.py b/src/api/serializers.py index 3ad0d3d..0553edb 100644 --- a/src/api/serializers.py +++ b/src/api/serializers.py @@ -26,7 +26,9 @@ class ClientAccountSerializer(serializers.ModelSerializer): def __init__(self, instance=None, data=empty, **kwargs): super().__init__(instance, data, **kwargs) - if self.context.get('request').user.is_staff: + request = self.context.get('request') + + if request and request.user.is_staff: self.Meta.exclude = () else: self.Meta.exclude = ('user_account',) diff --git a/src/openapi-schema.yml b/src/openapi-schema.yml new file mode 100644 index 0000000..cf8aa1f --- /dev/null +++ b/src/openapi-schema.yml @@ -0,0 +1,696 @@ +openapi: 3.0.2 +info: + title: 'Wallet Django' + version: '' + how_to: 'https://www.django-rest-framework.org/api-guide/schemas/#generating-an-openapi-schema' +paths: + /api/v1/user/: + get: + operationId: listUsers + description: 'Anonymous users could create their own accounts. + + Only staff users could see the users list. + + Regular users could only see their own accounts' + parameters: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + description: '' + tags: + - api + post: + operationId: createUser + description: 'Anonymous users could create their own accounts. + + Only staff users could see the users list. + + Regular users could only see their own accounts' + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/User' + multipart/form-data: + schema: + $ref: '#/components/schemas/User' + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: '' + tags: + - api + /api/v1/user/{id}/: + get: + operationId: retrieveUser + description: 'Anonymous users could create their own accounts. + + Only staff users could see the users list. + + Regular users could only see their own accounts' + parameters: + - name: id + in: path + required: true + description: '' + schema: + type: string + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: '' + tags: + - api + put: + operationId: updateUser + description: 'Anonymous users could create their own accounts. + + Only staff users could see the users list. + + Regular users could only see their own accounts' + parameters: + - name: id + in: path + required: true + description: '' + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/User' + multipart/form-data: + schema: + $ref: '#/components/schemas/User' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: '' + tags: + - api + patch: + operationId: partialUpdateUser + description: 'Anonymous users could create their own accounts. + + Only staff users could see the users list. + + Regular users could only see their own accounts' + parameters: + - name: id + in: path + required: true + description: '' + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/User' + multipart/form-data: + schema: + $ref: '#/components/schemas/User' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: '' + tags: + - api + /api/v1/client/: + get: + operationId: listClientAccounts + description: Regular users could only interact with their own accounts. + parameters: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClientAccount' + description: '' + tags: + - api + post: + operationId: createClientAccount + description: Regular users could only interact with their own accounts. + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ClientAccount' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ClientAccount' + multipart/form-data: + schema: + $ref: '#/components/schemas/ClientAccount' + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/ClientAccount' + description: '' + tags: + - api + /api/v1/client/{id}/: + get: + operationId: retrieveClientAccount + description: Regular users could only interact with their own accounts. + parameters: + - name: id + in: path + required: true + description: '' + schema: + type: string + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/ClientAccount' + description: '' + tags: + - api + put: + operationId: updateClientAccount + description: Regular users could only interact with their own accounts. + parameters: + - name: id + in: path + required: true + description: '' + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ClientAccount' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ClientAccount' + multipart/form-data: + schema: + $ref: '#/components/schemas/ClientAccount' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/ClientAccount' + description: '' + tags: + - api + patch: + operationId: partialUpdateClientAccount + description: Regular users could only interact with their own accounts. + parameters: + - name: id + in: path + required: true + description: '' + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ClientAccount' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ClientAccount' + multipart/form-data: + schema: + $ref: '#/components/schemas/ClientAccount' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/ClientAccount' + description: '' + tags: + - api + delete: + operationId: destroyClientAccount + description: Regular users could only interact with their own accounts. + parameters: + - name: id + in: path + required: true + description: '' + schema: + type: string + responses: + '204': + description: '' + tags: + - api + /api/v1/client_wallet/: + get: + operationId: listClientWallets + description: Regular users could only interact with their own wallets. + parameters: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClientWallet' + description: '' + tags: + - api + post: + operationId: createClientWallet + description: Regular users could only interact with their own wallets. + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ClientWallet' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ClientWallet' + multipart/form-data: + schema: + $ref: '#/components/schemas/ClientWallet' + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/ClientWallet' + description: '' + tags: + - api + /api/v1/client_wallet/{id}/: + get: + operationId: retrieveClientWallet + description: Regular users could only interact with their own wallets. + parameters: + - name: id + in: path + required: true + description: '' + schema: + type: string + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/ClientWallet' + description: '' + tags: + - api + put: + operationId: updateClientWallet + description: Only allowed for superusers + parameters: + - name: id + in: path + required: true + description: '' + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ClientWallet' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ClientWallet' + multipart/form-data: + schema: + $ref: '#/components/schemas/ClientWallet' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/ClientWallet' + description: '' + tags: + - api + patch: + operationId: partialUpdateClientWallet + description: Regular users could only interact with their own wallets. + parameters: + - name: id + in: path + required: true + description: '' + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ClientWallet' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ClientWallet' + multipart/form-data: + schema: + $ref: '#/components/schemas/ClientWallet' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/ClientWallet' + description: '' + tags: + - api + delete: + operationId: destroyClientWallet + description: Regular users could only interact with their own wallets. + parameters: + - name: id + in: path + required: true + description: '' + schema: + type: string + responses: + '204': + description: '' + tags: + - api + /api/v1/client_wallet_transaction/: + get: + operationId: listClientWalletTransactions + description: Regular users could only interact with their own wallets. + parameters: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ClientWalletTransaction' + description: '' + tags: + - api + post: + operationId: createClientWalletTransaction + description: '* Docs + + ** Transaction atomic:' + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ClientWalletTransaction' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/ClientWalletTransaction' + multipart/form-data: + schema: + $ref: '#/components/schemas/ClientWalletTransaction' + responses: + '201': + content: + application/json: + schema: + $ref: '#/components/schemas/ClientWalletTransaction' + description: '' + tags: + - api + /api/v1/client_wallet_transaction/{id}/: + get: + operationId: retrieveClientWalletTransaction + description: Regular users could only interact with their own wallets. + parameters: + - name: id + in: path + required: true + description: '' + schema: + type: string + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/ClientWalletTransaction' + description: '' + tags: + - api + /api/v1/get_username/: + get: + operationId: listGetCurrentUserUsernames + description: Sample view to see your own username in JSON format. + parameters: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: {} + description: '' + tags: + - api + /api/v1/get_user_id/: + get: + operationId: listGetCurrentUserIds + description: Sample view to see your own user id in JSON format. + parameters: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: {} + description: '' + tags: + - api + /api/v1/get_client_id/: + get: + operationId: listGetCurrentClientIds + description: Sample view to see your own client account id in JSON format. + parameters: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: {} + description: '' + tags: + - api + /api/v1/get_num_accounts/: + get: + operationId: listGetNumClientAccounts + description: 'Sample view to see users with account in JSON format. + + It uses Django Aggregation.' + parameters: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: {} + description: '' + tags: + - api +components: + schemas: + User: + type: object + properties: + pk: + type: integer + readOnly: true + username: + type: string + description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_ + only. + pattern: ^[\w.@+-]+\z + maxLength: 150 + first_name: + type: string + maxLength: 150 + last_name: + type: string + maxLength: 150 + email: + type: string + format: email + maxLength: 254 + password: + type: string + writeOnly: true + maxLength: 128 + is_staff: + type: boolean + description: Designates whether the user can log into this admin site. + required: + - username + - password + ClientAccount: + type: object + properties: + id: + type: string + format: uuid + readOnly: true + city: + type: string + nullable: true + description: Ex. Aranjuez + maxLength: 100 + postal_code: + type: string + nullable: true + description: Ex. 28000 + maxLength: 100 + state: + type: string + nullable: true + description: Ex. Madrid + maxLength: 100 + public_username: + type: string + nullable: true + description: Ex. nickname + maxLength: 150 + date_created: + type: string + format: date-time + readOnly: true + last_update: + type: string + format: date-time + readOnly: true + name: + type: string + description: Ex. John + maxLength: 50 + surname: + type: string + description: Ex. Doe + maxLength: 100 + required: + - name + - surname + ClientWallet: + type: object + properties: + id: + type: string + format: uuid + readOnly: true + balance: + type: string + format: decimal + multipleOf: 0.01 + maximum: 1000000000000000000000000000000000000000000000000000000000000000 + minimum: -1000000000000000000000000000000000000000000000000000000000000000 + readOnly: true + description: Total ammount of money in this wallet + date_created: + type: string + format: date-time + readOnly: true + last_update: + type: string + format: date-time + readOnly: true + client_account: + type: string + required: + - client_account + ClientWalletTransaction: + type: object + properties: + id: + type: string + format: uuid + readOnly: true + description: + type: string + nullable: true + description: Transaction description + maxLength: 250 + amount: + type: string + format: decimal + multipleOf: 0.01 + maximum: 100000 + minimum: -100000 + done: + type: boolean + readOnly: true + description: It check if the transaction was completed + transaction_type: + enum: + - '0' + - '1' + - '2' + - '3' + type: string + readOnly: true + description: Add or substract money + error_msg: + type: string + nullable: true + description: 'Ex. Transaction error: negative balance' + maxLength: 250 + extra_info: + type: string + nullable: true + description: Extra info about this transaction + date_created: + type: string + format: date-time + readOnly: true + client_wallet_account: + type: string + required: + - amount + - client_wallet_account From f0dd457a2d82e258005c77ec7f02167aa42b744b Mon Sep 17 00:00:00 2001 From: mrroot5 Date: Mon, 6 Oct 2025 13:09:50 +0200 Subject: [PATCH 4/8] Readme typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 16a28a5..faec7e6 100644 --- a/README.md +++ b/README.md @@ -154,4 +154,4 @@ This will improve performance. ... Are you here yet? OK, nice one. I should invite you to a cup of coffee. -Just give me your wallet username and password to get in touch hehehe (yep, a simple joke). +Just give me your wallet username and password to get in touch hehehe (yep, a silly joke). From aa83329cd02bd244a9f5e466bb96d5626337c1d5 Mon Sep 17 00:00:00 2001 From: mrroot5 Date: Mon, 6 Oct 2025 13:09:57 +0200 Subject: [PATCH 5/8] Added flake8 file --- .flake8 | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..843f3d9 --- /dev/null +++ b/.flake8 @@ -0,0 +1,10 @@ +[flake8] +exclude = + .git, + .github + .vscode + __pycache__, + build + environment +max-complexity = 10 +max-line-length = 120 From 86f39135e7cb65bfa4e016cc7ce1a07207fbdd5b Mon Sep 17 00:00:00 2001 From: mrroot5 Date: Mon, 6 Oct 2025 13:10:10 +0200 Subject: [PATCH 6/8] 120 line length editorconfig file --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index cefa466..199a8ed 100644 --- a/.editorconfig +++ b/.editorconfig @@ -23,4 +23,4 @@ insert_final_newline = true indent_size = 2 # Python config [*.py] -max_line_length = 100 +max_line_length = 120 From 411d1619c20930f20f531b3f388a388f21348955 Mon Sep 17 00:00:00 2001 From: mrroot5 Date: Mon, 6 Oct 2025 13:17:54 +0200 Subject: [PATCH 7/8] Fix old docker-compose examples --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index faec7e6..019517f 100644 --- a/README.md +++ b/README.md @@ -8,14 +8,14 @@ Only superusers could change wallet balance. ## Requirements +### Old docker implementations + * docker engine >= 19.03. * docker-compose >= 1.27. -## Tested on +### New docker with docker-compose integrated -* Ubuntu 18.04 (Bionic). -* docker engine == 20.10.9. -* docker-compose == 1.28.4. +* docker version >= 28.3.3 ## How to use this project? @@ -69,12 +69,12 @@ make loaddata make tests ``` -### Using docker-compose +### Using docker compose #### Step 1: Build ```shell -docker-compose -p django_atomic_transactions -f environment/docker-compose.yml build +docker compose -p django_atomic_transactions -f environment/docker compose.yml build ``` #### Step 2: Migrate @@ -82,7 +82,7 @@ docker-compose -p django_atomic_transactions -f environment/docker-compose.yml b Apply django migrations: ```shell -docker-compose -p django_atomic_transactions -f environment/docker-compose.yml run --rm --service-ports web migrate +docker compose -p django_atomic_transactions -f environment/docker compose.yml run --rm --service-ports web migrate ``` #### Step 3: Run service @@ -92,7 +92,7 @@ docker-compose -p django_atomic_transactions -f environment/docker-compose.yml r Run django runserver command: ```shell -docker-compose -p django_atomic_transactions -f environment/docker-compose.yml run --rm --service-ports web dev +docker compose -p django_atomic_transactions -f environment/docker compose.yml run --rm --service-ports web dev ``` * **Uvicorn** @@ -100,7 +100,7 @@ docker-compose -p django_atomic_transactions -f environment/docker-compose.yml r Run uvicorn server: ```shell -docker-compose -p django_atomic_transactions -f environment/docker-compose.yml run --rm --service-ports web uvicorn +docker compose -p django_atomic_transactions -f environment/docker compose.yml run --rm --service-ports web uvicorn ``` #### Step 4: Load sample data @@ -108,13 +108,13 @@ docker-compose -p django_atomic_transactions -f environment/docker-compose.yml r Apply `initial_data.json` fixture. This action will erase all previous data: ```shell -docker-compose -p django_atomic_transactions -f environment/docker-compose.yml run --rm --service-ports web loaddata +docker compose -p django_atomic_transactions -f environment/docker compose.yml run --rm --service-ports web loaddata ``` #### Step 5: Run tests ```shell -docker-compose -p django_atomic_transactions -f environment/docker-compose.yml run --rm --service-ports web python manage.py test --failfast api +docker compose -p django_atomic_transactions -f environment/docker compose.yml run --rm --service-ports web python manage.py test --failfast api ``` ## Know issues From a16028940a2ba70c559b4318c0cd222106461b9b Mon Sep 17 00:00:00 2001 From: mrroot5 Date: Mon, 6 Oct 2025 16:04:16 +0200 Subject: [PATCH 8/8] Upgraded django dependencies for 3.2.25 --- environment/requirements/requirements.txt | 47 +++++++++++++---------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/environment/requirements/requirements.txt b/environment/requirements/requirements.txt index 15e1c1c..6b1f09a 100644 --- a/environment/requirements/requirements.txt +++ b/environment/requirements/requirements.txt @@ -1,20 +1,27 @@ -asgiref==3.4.1 -certifi==2021.10.8 -charset-normalizer==2.0.7 -click==8.0.3 -Django==3.2.8 -django-extensions==3.1.3 -django-filter==21.1 -djangorestframework==3.12.4 -h11==0.12.0 -idna==3.3 -pytz==2021.3 -requests==2.26.0 -sqlparse==0.4.2 -urllib3==1.26.7 -uvicorn==0.15.0 -psycopg2-binary==2.9.1 -Faker==9.3.1 -python-dateutil==2.8.2 -six==1.16.0 -text-unidecode==1.3 +asgiref==3.10.0 +backcall==0.2.0 +decorator==5.2.1 +Django==3.2.25 +django-extensions==3.2.3 +djangorestframework==3.15.1 +Faker==37.8.0 +flake8==4.0.1 +ipython==7.28.0 +jedi==0.19.2 +matplotlib-inline==0.1.7 +mccabe==0.6.1 +parso==0.8.5 +pexpect==4.9.0 +pickleshare==0.7.5 +prompt_toolkit==3.0.52 +psycopg2-binary==2.9.10 +ptyprocess==0.7.0 +pycodestyle==2.8.0 +pyflakes==2.4.0 +Pygments==2.19.2 +pytz==2025.2 +sqlparse==0.5.3 +traitlets==5.14.3 +typing_extensions==4.15.0 +tzdata==2025.2 +wcwidth==0.2.14