photo-objects 0.5.0__py3-none-any.whl → 0.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,20 +30,25 @@ class PhotoSizeDimensions:
30
30
  max_width: int = None
31
31
  max_height: int = None
32
32
  max_aspect_ratio: float = None
33
+ image_format: str = None
33
34
 
34
35
 
35
36
  DEFAULT_SM = dict(
36
37
  max_width=512,
37
38
  max_height=512,
38
- max_aspect_ratio=1.5
39
+ max_aspect_ratio=1.5,
40
+ image_format='WEBP'
39
41
  )
40
42
  DEFAULT_MD = dict(
41
- max_width=2048,
42
- max_height=2048
43
+ max_width=1024,
44
+ max_height=1024,
45
+ max_aspect_ratio=1.5,
46
+ image_format="JPEG"
43
47
  )
44
48
  DEFAULT_LG = dict(
45
- max_width=4096,
46
- max_height=4096
49
+ max_width=2048,
50
+ max_height=2048,
51
+ image_format='WEBP'
47
52
  )
48
53
 
49
54
 
@@ -2,6 +2,7 @@ from dataclasses import asdict
2
2
  from io import BytesIO
3
3
  import json
4
4
  import mimetypes
5
+ import re
5
6
  import urllib3
6
7
 
7
8
  from minio import Minio, S3Error
@@ -60,8 +61,30 @@ def photo_path(album_key, photo_key, size_key):
60
61
  return f"{size_key}/{album_key}/{photo_key}"
61
62
 
62
63
 
63
- def put_photo(album_key, photo_key, size_key, photo_file):
64
- content_type = mimetypes.guess_type(photo_key)[0]
64
+ def _photo_filename(photo_key: str, image_format: str = None) -> str:
65
+ if image_format:
66
+ filename = re.sub(r'\.[^.]+$', '', photo_key)
67
+ return f"{filename}.{image_format.lower()}"
68
+
69
+ return photo_key
70
+
71
+
72
+ def photo_content_headers(
73
+ photo_key: str,
74
+ image_format: str = None,
75
+ ) -> tuple[str, dict[str, str]]:
76
+ filename = _photo_filename(photo_key, image_format)
77
+
78
+ content_type = mimetypes.guess_type(filename, strict=False)[0]
79
+ headers = {
80
+ "Content-Disposition": f"inline; filename={filename}"
81
+ }
82
+
83
+ return content_type, headers
84
+
85
+
86
+ def put_photo(album_key, photo_key, size_key, photo_file, image_format=None):
87
+ content_type, headers = photo_content_headers(photo_key, image_format)
65
88
 
66
89
  client, bucket = _objsto_access()
67
90
  return client.put_object(
@@ -71,6 +94,7 @@ def put_photo(album_key, photo_key, size_key, photo_file):
71
94
  length=-1,
72
95
  part_size=10 * MEGABYTE,
73
96
  content_type=content_type,
97
+ metadata=headers
74
98
  )
75
99
 
76
100
 
@@ -91,14 +91,23 @@ def get_img(request: HttpRequest, album_key: str, photo_key: str):
91
91
  404 if code == "NoSuchKey" else 500,
92
92
  ).json_response
93
93
 
94
- sizes = photo_sizes()
94
+ size_params = getattr(photo_sizes(), size)
95
95
  # TODO: handle error
96
96
  scaled_photo = scale_photo(
97
- original_photo, photo_key, **asdict(getattr(sizes, size)))
97
+ original_photo, photo_key, **asdict(size_params))
98
98
 
99
99
  # TODO: handle error
100
100
  scaled_photo.seek(0)
101
- objsto.put_photo(album_key, photo_key, size, scaled_photo)
101
+ objsto.put_photo(
102
+ album_key,
103
+ photo_key,
104
+ size,
105
+ scaled_photo,
106
+ size_params.image_format)
107
+
108
+ content_type, headers = objsto.photo_content_headers(
109
+ photo_key, size_params.image_format)
102
110
 
103
111
  scaled_photo.seek(0)
104
- return HttpResponse(scaled_photo.read(), content_type=content_type)
112
+ return HttpResponse(
113
+ scaled_photo.read(), content_type=content_type, headers=headers)
photo_objects/img.py CHANGED
@@ -66,7 +66,10 @@ def _read_camera_setup_and_settings(image: Image) -> dict:
66
66
  raise e
67
67
 
68
68
 
69
- def _image_format(filename):
69
+ def _image_format(image_format, filename):
70
+ if image_format:
71
+ return image_format
72
+
70
73
  image_format = filename.split('.')[-1].upper()
71
74
 
72
75
  if image_format == "JPG":
@@ -131,7 +134,8 @@ def scale_photo(
131
134
  filename,
132
135
  max_width=None,
133
136
  max_height=None,
134
- max_aspect_ratio=None):
137
+ max_aspect_ratio=None,
138
+ image_format=None):
135
139
  image = Image.open(photo_file)
136
140
  width, height = image.size
137
141
 
@@ -164,5 +168,5 @@ def scale_photo(
164
168
  resized = image.resize(new_size, Image.Resampling.LANCZOS)
165
169
 
166
170
  b = BytesIO()
167
- resized.save(b, _image_format(filename))
171
+ resized.save(b, _image_format(image_format, filename))
168
172
  return b
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: photo-objects
3
- Version: 0.5.0
3
+ Version: 0.6.0
4
4
  Summary: Application for storing photos in S3 compatible object-storage.
5
5
  Author: Toni Kangas
6
6
  License: MIT License
@@ -1,16 +1,16 @@
1
1
  photo_objects/__init__.py,sha256=I1508w_ntomEqTFQgC74SurhxVXfCiDWZLRsny2f59g,60
2
2
  photo_objects/config.py,sha256=0-Aeo-z-d_fxx-cjAjxSwPJZUgYaAi7NTodiErlxIXo,861
3
3
  photo_objects/error.py,sha256=7afLYjxM0EaYioxVw_XUqHTvfSMSuQPUwwle0OVlaDY,45
4
- photo_objects/img.py,sha256=8FNxKFBVuSyxO_jA3W3PMag3bZ7sEXYKG78rpgxq71Q,4515
4
+ photo_objects/img.py,sha256=2HVGS2g7rS2hnomozYL92oxrcN6zjDTHvWNr-UAqtGQ,4620
5
5
  photo_objects/utils.py,sha256=sYliXid-bv2EgNA97woRaOnWU75yZFq7fuqzWaseiDg,139
6
6
  photo_objects/django/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  photo_objects/django/admin.py,sha256=ubYfhsWQ85_2moYGZCVneLQ2DVEetbVpvBNisIrtuhw,170
8
8
  photo_objects/django/apps.py,sha256=Apqu6o6fpoxda18NQgKupvQRvTAZxVviIK_-dUR3rck,1444
9
- photo_objects/django/conf.py,sha256=s5lUbSLpjRWKlE2eYqAZmz60q4Oe10-e7JbIERPa6qI,2463
9
+ photo_objects/django/conf.py,sha256=ZpeIulEc1tpr8AO52meNKOF30Xf5osbDtDyHvQRtkx4,2593
10
10
  photo_objects/django/context_processors.py,sha256=DLhLZHAvGlrpxYegaLiKEx9X7rpyZUFiAnAVF9jjkFA,165
11
11
  photo_objects/django/forms.py,sha256=XiCNqjVqPDn_aV4nGM1z5NfLKHd6_ipm7y0YRt3sXgY,6505
12
12
  photo_objects/django/models.py,sha256=M40ZFSIX3WgyVXfHQY9SXQOY0s3fpFqfCxNV3CBD5M8,5753
13
- photo_objects/django/objsto.py,sha256=5z4F8pft01WKLBipyE3Ro9Ac9AvWbuV_rG9Iiour90E,3588
13
+ photo_objects/django/objsto.py,sha256=B7DxPWuqFaPFXPLhsHCFlqIzYl7EXLxcHde6zJDe89A,4238
14
14
  photo_objects/django/signals.py,sha256=Q_Swjl_9z6B6zP-97D_ep5zGSAEgmQfwUz0utMDY93A,1624
15
15
  photo_objects/django/urls.py,sha256=pCUTxg4xSd3ZD8BZVjULb9QpJQ03Ek6-sKoVnYG3-OY,1975
16
16
  photo_objects/django/api/__init__.py,sha256=BnEHlm3mwyBy-1xhk-NFasgZa4fjCDjtfkBUoH0puPY,62
@@ -43,7 +43,7 @@ photo_objects/django/views/utils.py,sha256=oP9B6QtHPaukX97rqIlCHxanduktPGFVSCGkG
43
43
  photo_objects/django/views/api/__init__.py,sha256=SxK-b7MgMtD9VRMz46rDV5qtm6AvkRcg3Moa1AWl5pY,108
44
44
  photo_objects/django/views/api/album.py,sha256=EZMOkxYzLSWr9wwXnd4yAO64JtXZq2k3FYohiNMFbGQ,1602
45
45
  photo_objects/django/views/api/auth.py,sha256=EN_ExegzmLN-bhSzu3L9-6UE9qodPd7_ZRLilzrvc8Y,819
46
- photo_objects/django/views/api/photo.py,sha256=FQCqcnPwSaEJ9MVggQF09E4WD1wVFmLZnT_pFFpWGvA,3502
46
+ photo_objects/django/views/api/photo.py,sha256=iWDTBWrzztIKcfW7G6vh1eYTuH2JW129iOLSHjTfXCE,3743
47
47
  photo_objects/django/views/api/utils.py,sha256=uQzKdSKHRAux5OZzqgWQr0gsK_FeweQP0cg_67OWA_Y,264
48
48
  photo_objects/django/views/ui/__init__.py,sha256=N3ro5KggdV-JnfyHwoStX73b3SbVbpcsMuQNlxntVJs,92
49
49
  photo_objects/django/views/ui/album.py,sha256=PmVXAmqVjKLAie1NyB-qXO3eLqOmhIA8PTAGJewgxko,4738
@@ -51,8 +51,8 @@ photo_objects/django/views/ui/configuration.py,sha256=oX6SV0TFBpbaxfp4cXIdSL41YJ
51
51
  photo_objects/django/views/ui/photo.py,sha256=Zo-HE-CzMSLFEtDTL1ds1HnXi3ORsIym4iWa_ZMCPpc,6299
52
52
  photo_objects/django/views/ui/users.py,sha256=nb73cnzuV98QkJb0j8F2hqPgOGFIWpUFTFu6dXMeVwM,722
53
53
  photo_objects/django/views/ui/utils.py,sha256=YV_YcUbX-zUkdFnBlezPChR6aPDhZJ9loSOHBSzF6Cc,273
54
- photo_objects-0.5.0.dist-info/licenses/LICENSE,sha256=V3w6hTjXfP65F4r_mejveHcV5igHrblxao3-2RlfVlA,1068
55
- photo_objects-0.5.0.dist-info/METADATA,sha256=9fsj7gKM1NHpOblwzeKWpDkKh4ygJ_HmfafdEQa1aik,3605
56
- photo_objects-0.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
57
- photo_objects-0.5.0.dist-info/top_level.txt,sha256=SZeL8mhf-WMGdhRtTGFvZc3aIRBboQls9O0cFDMGdQ0,14
58
- photo_objects-0.5.0.dist-info/RECORD,,
54
+ photo_objects-0.6.0.dist-info/licenses/LICENSE,sha256=V3w6hTjXfP65F4r_mejveHcV5igHrblxao3-2RlfVlA,1068
55
+ photo_objects-0.6.0.dist-info/METADATA,sha256=zaLGXBdjS2a4m9TXnbLG36LtT1EqCtmEFdloP2Dub_U,3605
56
+ photo_objects-0.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
57
+ photo_objects-0.6.0.dist-info/top_level.txt,sha256=SZeL8mhf-WMGdhRtTGFvZc3aIRBboQls9O0cFDMGdQ0,14
58
+ photo_objects-0.6.0.dist-info/RECORD,,