diff --git a/lockbox/common/apps.py b/lockbox/common/apps.py index e283781..01cca2f 100644 --- a/lockbox/common/apps.py +++ b/lockbox/common/apps.py @@ -1,6 +1,4 @@ -from django.apps import ( - AppConfig, -) +from django.apps import AppConfig class CommonConfig(AppConfig): diff --git a/lockbox/common/constants.py b/lockbox/common/constants.py index 5300fa0..c80c872 100644 --- a/lockbox/common/constants.py +++ b/lockbox/common/constants.py @@ -3,18 +3,21 @@ import re CONTENT_RANGE_HEADER = "HTTP_CONTENT_RANGE" CONTENT_RANGE_HEADER_PATTERN = re.compile(r"^bytes (?P\d+)-(?P\d+)$") + class UPLOAD_STATUS_TYPES: UPLOADING = "uploading" COMPLETED = "completed" ABANDONED = "abandoned" ERROR = "error" + class UPLOAD_ERROR_CODES: FILE_MISSING = "file_missing" CHUNK_MISMATCH = "chunk_mismatch" # Config + CONFIG_KEYS = { "ABANDONED_DELTA_MINUTES": { "description": "Date created + this delta at which a file is marked as abandoned", @@ -42,7 +45,7 @@ CONFIG_KEYS = { "verbose_name": "Max upload size in bytes", "native_type": int, "sensitive": False, - "default": 1024 * 1024 * 30, # 200 MB + "default": 1024 * 1024 * 30, # 200 MB }, "ENABLE_BROWSABLE_API": { "description": "REST Framework browsable API is enabled (Always enabled if DEBUG is true)", diff --git a/lockbox/common/utils.py b/lockbox/common/utils.py index bd8e8f1..6aae915 100644 --- a/lockbox/common/utils.py +++ b/lockbox/common/utils.py @@ -15,9 +15,11 @@ class Config(NamedTuple): value: Any source: str + def normalize_string(string, form="NFKC"): return normalize(form, string) + def cast_to_native_type(key, value, native_type): if native_type == list: diff --git a/lockbox/common/views_api.py b/lockbox/common/views_api.py index 74885b2..8318d37 100644 --- a/lockbox/common/views_api.py +++ b/lockbox/common/views_api.py @@ -1,15 +1,15 @@ +from common.constants import CONFIG_KEYS +from common.serializers import ConfigSerializer +from common.utils import get_config from rest_framework import status from rest_framework.decorators import api_view from rest_framework.response import Response -from common.constants import CONFIG_KEYS -from common.serializers import ConfigSerializer -from common.utils import get_config - def get_all_configs(): return [get_config(key, value_only=False)._asdict() for key in CONFIG_KEYS] + @api_view(["GET"]) def configs(request, key=None): if key: diff --git a/lockbox/lockbox/settings.py b/lockbox/lockbox/settings.py index 68080c3..bcd3b90 100644 --- a/lockbox/lockbox/settings.py +++ b/lockbox/lockbox/settings.py @@ -132,4 +132,4 @@ AUTH_USER_MODEL = 'user.LockboxUser' REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', 'PAGE_SIZE': 50 -} \ No newline at end of file +} diff --git a/lockbox/lockbox/setup.py b/lockbox/lockbox/setup.py index 4900290..a881b85 100644 --- a/lockbox/lockbox/setup.py +++ b/lockbox/lockbox/setup.py @@ -3,8 +3,10 @@ from pathlib import Path # TODO: LOG MEEEEE # TODO: Figure out file owner in system, permissions, GUID # Whats the default path if not provided? // docker volume + + def validate_paths(media_path): - try: - Path(media_path).mkdir(exist_ok=True) - except Exception as e: - raise e \ No newline at end of file + try: + Path(media_path).mkdir(exist_ok=True) + except Exception as e: + raise e diff --git a/lockbox/storage/admin.py b/lockbox/storage/admin.py index 04d250f..3179186 100644 --- a/lockbox/storage/admin.py +++ b/lockbox/storage/admin.py @@ -1,9 +1,9 @@ from django.contrib import admin - from storage.models import File class FileAdmin(admin.ModelAdmin): readonly_fields = File.readonly_fields + admin.site.register(File, FileAdmin) diff --git a/lockbox/storage/models.py b/lockbox/storage/models.py index 263e7e3..85053b4 100644 --- a/lockbox/storage/models.py +++ b/lockbox/storage/models.py @@ -1,13 +1,14 @@ from datetime import timedelta +from hashlib import md5 from pathlib import Path -from common.constants import UPLOAD_STATUS_TYPES, UPLOAD_ERROR_CODES + +from common.constants import UPLOAD_ERROR_CODES, UPLOAD_STATUS_TYPES from common.models import LockboxBase from common.utils import get_config, get_max_size_chunk_bytes +from django.conf import settings from django.db import models, transaction from django.utils import timezone from django.utils.translation import gettext_lazy as _ -from django.conf import settings -from hashlib import md5 class UploadError(Exception): diff --git a/lockbox/storage/urls.py b/lockbox/storage/urls.py index d55f170..74a859c 100644 --- a/lockbox/storage/urls.py +++ b/lockbox/storage/urls.py @@ -1,7 +1,5 @@ from django.urls import include, path from rest_framework.routers import SimpleRouter -from rest_framework_nested.routers import NestedSimpleRouter - from storage import views_api, views_client router = SimpleRouter() diff --git a/lockbox/storage/views_api.py b/lockbox/storage/views_api.py index 895f77c..2acf61c 100644 --- a/lockbox/storage/views_api.py +++ b/lockbox/storage/views_api.py @@ -1,19 +1,11 @@ -from common.constants import ( - CONTENT_RANGE_HEADER, - CONTENT_RANGE_HEADER_PATTERN -) - -# from common.utils import get_config +from common.constants import CONTENT_RANGE_HEADER, CONTENT_RANGE_HEADER_PATTERN +from django.core.exceptions import ValidationError from rest_framework import status from rest_framework.decorators import action -from rest_framework.response import Response -from rest_framework.viewsets import ModelViewSet from rest_framework.exceptions import NotFound from rest_framework.exceptions import ValidationError as UserValidationError -from rest_framework.parsers import FileUploadParser - -from django.core.exceptions import ValidationError - +from rest_framework.response import Response +from rest_framework.viewsets import ModelViewSet from storage.models import File, UploadError from storage.serializers import FileSerializer @@ -36,14 +28,14 @@ class FileModelViewSet(ModelViewSet): chunk_data = self.get_content_range(request) if not chunk_data: raise UserValidationError( - f"Missing content range headers" + "Missing content-range headers" ) chunk_file = request.FILES["Content"] if chunk_file.size > file.max_size_chunk_bytes: raise UserValidationError( f"Chunk size is greater than files max chunk size: {chunk_file.size} > {file.max_size_chunk_bytes}") - + range_size = chunk_data["end_bytes"] - chunk_data["start_bytes"] if chunk_file.size != range_size: raise UserValidationError( @@ -61,11 +53,11 @@ class FileModelViewSet(ModelViewSet): content_range = request.META.get(CONTENT_RANGE_HEADER, None) if not content_range: return None - + match = CONTENT_RANGE_HEADER_PATTERN.match(content_range) if not match: return None - + return { "start_bytes": int(match.group('start')), "end_bytes": int(match.group('end')), diff --git a/lockbox/storage/views_client.py b/lockbox/storage/views_client.py index 3ae393b..3053b18 100644 --- a/lockbox/storage/views_client.py +++ b/lockbox/storage/views_client.py @@ -1,7 +1,7 @@ -from common.utils import get_config from django.shortcuts import render from django.views import View + # Static view class FileUploadView(View): def get(self, request): diff --git a/lockbox/user/admin.py b/lockbox/user/admin.py index 6f3349b..fc94117 100644 --- a/lockbox/user/admin.py +++ b/lockbox/user/admin.py @@ -1,9 +1,9 @@ from django.contrib import admin - from user.models import LockboxUser class LockboxUserAdmin(admin.ModelAdmin): readonly_fields = LockboxUser.readonly_fields + admin.site.register(LockboxUser, LockboxUserAdmin) diff --git a/lockbox/user/tests/test_user.py b/lockbox/user/tests/test_user.py index e7a9a41..83d9664 100644 --- a/lockbox/user/tests/test_user.py +++ b/lockbox/user/tests/test_user.py @@ -1,5 +1,4 @@ import pytest - from user.models import LockboxUser @@ -11,4 +10,4 @@ class TestUser: def test_stub(self): user = LockboxUser.objects.create(alias="TestUser", username="meow") loaded_user = LockboxUser.objects.filter(alias="TestUser").first() - assert user.lid == loaded_user.lid + assert user.lid == loaded_user.lid diff --git a/poetry.lock b/poetry.lock index e7d5573..891bf02 100644 --- a/poetry.lock +++ b/poetry.lock @@ -201,6 +201,20 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "isort" +version = "5.13.2" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, +] + +[package.extras] +colors = ["colorama (>=0.4.6)"] + [[package]] name = "mccabe" version = "0.7.0" @@ -373,4 +387,4 @@ brotli = ["brotli"] [metadata] lock-version = "2.0" python-versions = "~3.12" -content-hash = "d8ff6440e16bd3eb499933ec438f2490a91e8caab975ab40505a64daab72cf9e" +content-hash = "155d31f2edffb6e6ea604c7a1115fa072072a5370e012eea577644e0a337f0b0" diff --git a/pyproject.toml b/pyproject.toml index 652adac..999fe64 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,7 @@ pytest = "^8.0.0" pytest-django = "^4.8.0" pytest-cov = "^4.1.0" flake8-pyproject = "^1.2.3" +isort = "^5.13.2" [tool.pytest.ini_options] diff --git a/requirements_test.txt b/requirements_test.txt index e45a05f..ea3deac 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -7,6 +7,7 @@ drf-nested-routers==0.93.5 ; python_version >= "3.12" and python_version < "3.13 flake8-pyproject==1.2.3 ; python_version >= "3.12" and python_version < "3.13" flake8==7.1.1 ; python_version >= "3.12" and python_version < "3.13" iniconfig==2.0.0 ; python_version >= "3.12" and python_version < "3.13" +isort==5.13.2 ; python_version >= "3.12" and python_version < "3.13" mccabe==0.7.0 ; python_version >= "3.12" and python_version < "3.13" packaging==24.1 ; python_version >= "3.12" and python_version < "3.13" pluggy==1.5.0 ; python_version >= "3.12" and python_version < "3.13" diff --git a/scripts/drone/lint.sh b/scripts/drone/lint.sh index 82c0f43..5ae9cd2 100755 --- a/scripts/drone/lint.sh +++ b/scripts/drone/lint.sh @@ -1,2 +1,2 @@ -printf "\n\n|| Starting ruff check ||\n\n" -ruff check --config=./pyproject.toml \ No newline at end of file +printf "\n\n|| Starting lint check ||\n\n" +flake8 \ No newline at end of file