thumbor-libs-blackhand 0.1.6__py3-none-any.whl → 0.5.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.
Files changed (23) hide show
  1. thumbor_libs_blackhand/loaders/__init__.py +2 -4
  2. thumbor_libs_blackhand/loaders/mongodb_loader.py +2 -4
  3. thumbor_libs_blackhand/loaders/spec_http_or_specb_loader.py +2 -3
  4. thumbor_libs_blackhand/loaders/specb_file_fallback_file_loader.py +2 -4
  5. thumbor_libs_blackhand/metrics/__init__.py +2 -4
  6. thumbor_libs_blackhand/mongodb/pool_result_storage.py +60 -0
  7. thumbor_libs_blackhand/result_storages/__init__.py +4 -0
  8. thumbor_libs_blackhand/result_storages/hybrid_result_storage.py +213 -0
  9. thumbor_libs_blackhand/result_storages/mongodb_result_storage_v3.py +196 -0
  10. thumbor_libs_blackhand/result_storages/mongodb_result_storage_v4.py +209 -0
  11. thumbor_libs_blackhand/result_storages/mongodb_result_storage_v5.py +178 -0
  12. thumbor_libs_blackhand/storages/__init__.py +4 -0
  13. thumbor_libs_blackhand/storages/mongodb_webp_storage.py +5 -12
  14. thumbor_libs_blackhand/url_signers/__init__.py +2 -4
  15. thumbor_libs_blackhand/url_signers/base64_hmac_sha1_trim.py +3 -3
  16. thumbor_libs_blackhand-0.5.0.dist-info/LICENSE +21 -0
  17. {thumbor_libs_blackhand-0.1.6.dist-info → thumbor_libs_blackhand-0.5.0.dist-info}/METADATA +7 -4
  18. thumbor_libs_blackhand-0.5.0.dist-info/RECORD +20 -0
  19. {thumbor_libs_blackhand-0.1.6.dist-info → thumbor_libs_blackhand-0.5.0.dist-info}/WHEEL +1 -1
  20. thumbor_libs_blackhand/result_storages/mongodb_webp_result_storage.py +0 -117
  21. thumbor_libs_blackhand-0.1.6.dist-info/LICENSE +0 -674
  22. thumbor_libs_blackhand-0.1.6.dist-info/RECORD +0 -16
  23. {thumbor_libs_blackhand-0.1.6.dist-info → thumbor_libs_blackhand-0.5.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,209 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Blackhand library for Thumbor
3
+ # Licensed under the MIT license:
4
+ # http://www.opensource.org/licenses/mit-license
5
+
6
+ from urllib import parse #, request; error
7
+ #from motor.motor_tornado import MotorGridFSBucket
8
+ #from pymongo.errors import PyMongoError
9
+ from thumbor_libs_blackhand.mongodb.pool_result_storage import MongoConnector
10
+ from datetime import datetime, timedelta
11
+ from thumbor.result_storages import BaseStorage, ResultStorageResult
12
+ from thumbor.engines import BaseEngine
13
+ from thumbor.utils import logger
14
+ from bson.binary import Binary
15
+ import pytz
16
+ import re
17
+
18
+
19
+ class Storage(BaseStorage):
20
+
21
+ def __init__(self, context):
22
+ BaseStorage.__init__(self, context)
23
+ self.database, self.storage = self.__conn__()
24
+ super(Storage, self).__init__(context)
25
+
26
+
27
+
28
+ def __conn__(self):
29
+ '''Return the MongoDB params.
30
+ :returns: MongoDB DB and Collection
31
+ :rtype: pymongo.database.Database, pymongo.database.Collection
32
+ '''
33
+
34
+ password = parse.quote_plus(self.context.config.MONGO_RESULT_STORAGE_SERVER_PASSWORD)
35
+ user = parse.quote_plus(self.context.config.MONGO_RESULT_STORAGE_SERVER_USER)
36
+ if not self.context.config.MONGO_RESULT_STORAGE_SERVER_REPLICASET:
37
+ uric = ('mongodb://'+ user +':' + password + '@' + self.context.config.MONGO_RESULT_STORAGE_SERVER_HOSTS
38
+ + '/?authSource=' + self.context.config.MONGO_RESULT_STORAGE_SERVER_DB)
39
+ else:
40
+ uric = ('mongodb://'+ user +':' + password + '@' + self.context.config.MONGO_RESULT_STORAGE_SERVER_HOSTS
41
+ + '/?authSource=' + self.context.config.MONGO_RESULT_STORAGE_SERVER_DB
42
+ + "&replicaSet=" + self.context.config.MONGO_RESULT_STORAGE_SERVER_REPLICASET
43
+ + "&readPreference=" + self.context.config.MONGO_RESULT_STORAGE_SERVER_READ_PREFERENCE)
44
+
45
+ db_name = self.context.config.MONGO_RESULT_STORAGE_SERVER_DB
46
+ col_name = self.context.config.MONGO_RESULT_STORAGE_SERVER_COLLECTION
47
+ host = None
48
+ port = None
49
+
50
+ try:
51
+ uri = self.context.config.MONGO_RESULT_STORAGE_URI
52
+ except AttributeError:
53
+ uri=uric
54
+
55
+ try:
56
+ host = self.context.config.MONGO_RESULT_STORAGE_SERVER_HOST
57
+ port = self.context.config.MONGO_RESULT_STORAGE_SERVER_PORT
58
+ except AttributeError:
59
+ host=None
60
+ port=None
61
+
62
+ mongo_conn = MongoConnector(
63
+ db_name=db_name,
64
+ col_name=col_name,
65
+ uri=uri,
66
+ host=host,
67
+ port=port,
68
+ )
69
+
70
+ database = mongo_conn.db_conn
71
+ storage = mongo_conn.col_conn
72
+
73
+ return database, storage
74
+
75
+ @property
76
+ def is_auto_webp(self):
77
+ '''Return if webp.
78
+ :return: If the file is a webp
79
+ :rettype: boolean
80
+ '''
81
+
82
+ return self.context.config.AUTO_WEBP \
83
+ and self.context.request.accepts_webp
84
+
85
+ def get_key_from_request(self):
86
+ '''Return a path key for the current request url.
87
+ :return: The storage key for the current url
88
+ :rettype: string
89
+ '''
90
+
91
+ path = f"result:{self.context.request.url}"
92
+
93
+ if self.is_auto_webp:
94
+ return f'{path}/webp'
95
+
96
+ return path
97
+
98
+
99
+ def get_max_age(self):
100
+
101
+ return self.context.config.RESULT_STORAGE_EXPIRATION_SECONDS
102
+
103
+
104
+ async def put(self, image_bytes):
105
+ key = self.get_key_from_request()
106
+ #max_age = self.get_max_age()
107
+ #result_ttl = self.get_max_age()
108
+ ref_img = ''
109
+ ref_img = re.findall(r'/[a-zA-Z0-9]{24}(?:$|/)', key)
110
+ if ref_img:
111
+ ref_img2 = ref_img[0].replace('/','')
112
+ else:
113
+ ref_img2 = 'undef'
114
+
115
+
116
+ if self.context.config.get("MONGO_STORE_METADATA", False):
117
+ metadata = dict(self.context.headers)
118
+ else:
119
+ metadata = {}
120
+
121
+ try:
122
+ listeProduit = self.context.config.PRODUIT
123
+ produit=''
124
+ for s in listeProduit:
125
+ if key.find(s) >= 1:
126
+ produit=s.replace('/', '')
127
+ break
128
+ else:
129
+ produit="info"
130
+ except AttributeError:
131
+ produit = 'undef'
132
+
133
+ doc = {
134
+ 'path': key,
135
+ 'created_at': datetime.utcnow(),
136
+ 'data': Binary(image_bytes),
137
+ 'metadata': metadata,
138
+ 'content_type': BaseEngine.get_mimetype(image_bytes),
139
+ 'ref_id': ref_img2,
140
+ 'content_length' : len(image_bytes),
141
+ 'produit': produit
142
+ }
143
+ doc_cpm = dict(doc)
144
+
145
+ await self.storage.insert_one(doc_cpm)
146
+ #return self.context.request.url
147
+ return key
148
+
149
+ async def get(self):
150
+ key = self.get_key_from_request()
151
+ logger.debug("[RESULT_STORAGE] image not found at %s", key)
152
+
153
+
154
+ age = datetime.utcnow() - timedelta(
155
+ seconds=self.get_max_age()
156
+ )
157
+ stored = await self.storage.find_one({
158
+ 'path': key,
159
+ 'created_at': {
160
+ '$gte': age
161
+ },
162
+ }, {
163
+ 'ref_id': True,
164
+ 'created_at': True,
165
+ 'metadata': True,
166
+ 'content_type': True,
167
+ 'data' : True,
168
+ 'content_length': True,
169
+ })
170
+
171
+
172
+ if not stored:
173
+ return None
174
+
175
+ try:
176
+ #self.context.config.MONGO_RESULT_STORAGE_MAXCACHESIZE
177
+ dedup = self.context.config.MONGO_RESULT_STORAGE_DEDUP
178
+ except:
179
+ dedup = False
180
+
181
+ if not dedup:
182
+ logger.debug("Deduplication OFF")
183
+ else:
184
+ filter={
185
+ 'path': key
186
+ }
187
+ sort=list({
188
+ 'created_at': -1
189
+ }.items())
190
+ skip=1
191
+ obj = self.storage.find(filter=filter, skip=skip)
192
+ async for doc in obj:
193
+ logger.info("Deduplication %s", key)
194
+ self.storage.delete_one({"_id": doc["_id"]})
195
+
196
+
197
+ metadata = stored['metadata']
198
+ metadata['LastModified'] = stored['created_at'].replace(
199
+ tzinfo=pytz.utc
200
+ )
201
+ metadata['Cache-Control'] = "max-age=60,public"
202
+ metadata['ContentLength'] = stored['content_length']
203
+ metadata['ContentType'] = stored['content_type']
204
+
205
+ return ResultStorageResult(
206
+ buffer=stored['data'],
207
+ metadata=metadata,
208
+ successful=True
209
+ )
@@ -0,0 +1,178 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Blackhand library for Thumbor
3
+ # Licensed under the MIT license:
4
+ # http://www.opensource.org/licenses/mit-license
5
+
6
+ from urllib import parse #, request; error
7
+ from thumbor_libs_blackhand.mongodb.pool_result_storage import MongoConnector
8
+ from datetime import datetime, timedelta
9
+ from thumbor.result_storages import BaseStorage, ResultStorageResult
10
+ from thumbor.engines import BaseEngine
11
+ from thumbor.utils import logger
12
+ from bson.binary import Binary
13
+ import pytz
14
+ import re
15
+
16
+
17
+ class Storage(BaseStorage):
18
+
19
+ def __init__(self, context):
20
+ BaseStorage.__init__(self, context)
21
+ self.database, self.storage = self.__conn__()
22
+ super(Storage, self).__init__(context)
23
+
24
+ def __conn__(self):
25
+ try:
26
+ uri = self.context.config.MONGO_RESULT_STORAGE_SERVER_URI
27
+ db_name=self.context.config.MONGO_RESULT_STORAGE_SERVER_DB
28
+ col_name=self.context.config.MONGO_RESULT_STORAGE_SERVER_COLLECTION
29
+ except AttributeError:
30
+ logger.error("[RESULT_STORAGE] Parametres databases incomplet")
31
+
32
+ mongo_conn = MongoConnector(
33
+ db_name=db_name,
34
+ col_name=col_name,
35
+ uri=uri,
36
+ )
37
+
38
+ database = mongo_conn.db_conn
39
+ storage = mongo_conn.col_conn
40
+
41
+ return database, storage
42
+
43
+
44
+ @property
45
+ def is_auto_webp(self):
46
+ '''Return if webp.
47
+ :return: If the file is a webp
48
+ :rettype: boolean
49
+ '''
50
+
51
+ return self.context.config.AUTO_WEBP \
52
+ and self.context.request.accepts_webp
53
+
54
+ def get_key_from_request(self):
55
+ '''Return a path key for the current request url.
56
+ :return: The storage key for the current url
57
+ :rettype: string
58
+ '''
59
+
60
+ path = f"result:{self.context.request.url}"
61
+
62
+ if self.is_auto_webp:
63
+ return f'{path}/webp'
64
+
65
+ return path
66
+
67
+
68
+ def get_max_age(self):
69
+
70
+ return self.context.config.RESULT_STORAGE_EXPIRATION_SECONDS
71
+
72
+
73
+ async def put(self, image_bytes):
74
+ key = self.get_key_from_request()
75
+ #max_age = self.get_max_age()
76
+ #result_ttl = self.get_max_age()
77
+ ref_img = ''
78
+ ref_img = re.findall(r'/[a-zA-Z0-9]{24}(?:$|/)', key)
79
+ if ref_img:
80
+ ref_img2 = ref_img[0].replace('/','')
81
+ else:
82
+ ref_img2 = 'undef'
83
+
84
+
85
+ if self.context.config.get("MONGO_STORE_METADATA", False):
86
+ metadata = dict(self.context.headers)
87
+ else:
88
+ metadata = {}
89
+
90
+ try:
91
+ listeProduit = self.context.config.PRODUIT
92
+ produit=''
93
+ for s in listeProduit:
94
+ if key.find(s) >= 1:
95
+ produit=s.replace('/', '')
96
+ break
97
+ else:
98
+ produit="info"
99
+ except AttributeError:
100
+ produit = 'undef'
101
+
102
+ doc = {
103
+ 'path': key,
104
+ 'created_at': datetime.utcnow(),
105
+ 'data': Binary(image_bytes),
106
+ 'metadata': metadata,
107
+ 'content_type': BaseEngine.get_mimetype(image_bytes),
108
+ 'ref_id': ref_img2,
109
+ 'content_length' : len(image_bytes),
110
+ 'produit': produit
111
+ }
112
+ doc_cpm = dict(doc)
113
+
114
+ await self.storage.insert_one(doc_cpm)
115
+ #return self.context.request.url
116
+ return key
117
+
118
+ async def get(self):
119
+ key = self.get_key_from_request()
120
+ logger.debug("[RESULT_STORAGE] image not found at %s", key)
121
+
122
+ print(key)
123
+ age = datetime.utcnow() - timedelta(
124
+ seconds=self.get_max_age()
125
+ )
126
+ stored = await self.storage.find_one({
127
+ 'path': key,
128
+ 'created_at': {
129
+ '$gte': age
130
+ },
131
+ }, {
132
+ 'ref_id': True,
133
+ 'created_at': True,
134
+ 'metadata': True,
135
+ 'content_type': True,
136
+ 'data' : True,
137
+ 'content_length': True,
138
+ })
139
+
140
+
141
+ if not stored:
142
+ return None
143
+
144
+ try:
145
+ #self.context.config.MONGO_RESULT_STORAGE_MAXCACHESIZE
146
+ dedup = self.context.config.MONGO_RESULT_STORAGE_DEDUP
147
+ except:
148
+ dedup = False
149
+
150
+ if not dedup:
151
+ logger.debug("Deduplication OFF")
152
+ else:
153
+ filter={
154
+ 'path': key
155
+ }
156
+ sort=list({
157
+ 'created_at': -1
158
+ }.items())
159
+ skip=1
160
+ obj = self.storage.find(filter=filter, skip=skip)
161
+ async for doc in obj:
162
+ logger.info("Deduplication %s", key)
163
+ self.storage.delete_one({"_id": doc["_id"]})
164
+
165
+
166
+ metadata = stored['metadata']
167
+ metadata['LastModified'] = stored['created_at'].replace(
168
+ tzinfo=pytz.utc
169
+ )
170
+ metadata['Cache-Control'] = "max-age=60,public"
171
+ metadata['ContentLength'] = stored['content_length']
172
+ metadata['ContentType'] = stored['content_type']
173
+
174
+ return ResultStorageResult(
175
+ buffer=stored['data'],
176
+ metadata=metadata,
177
+ successful=True
178
+ )
@@ -0,0 +1,4 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Blackhand library for Thumbor
3
+ # Licensed under the MIT license:
4
+ # http://www.opensource.org/licenses/mit-license
@@ -1,12 +1,11 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # Blackhand library for Thumbor
3
- # Licensed under the GNU/GPL license:
4
- # https://fsf.org/
3
+ # Licensed under the MIT license:
4
+ # http://www.opensource.org/licenses/mit-license
5
5
  import re
6
6
  import gridfs
7
- import urllib.request, urllib.parse, urllib.error
7
+ #import urllib.request, urllib.parse, urllib.error
8
8
  from datetime import datetime, timedelta
9
- from io import StringIO
10
9
  from thumbor.storages import BaseStorage
11
10
  from pymongo.mongo_client import MongoClient
12
11
  from pymongo.server_api import ServerApi
@@ -61,9 +60,7 @@ class Storage(BaseStorage):
61
60
  return pasplit[0]
62
61
 
63
62
  def truepath(self, path):
64
- pasplit = path.split("/")
65
- # cas du // vide a gerer
66
- pasplitf = re.search('^[a-z0-9A-Z]+', pasplit[0]).group(0)
63
+ pasplit = path.split("/")
67
64
  if pasplit[0]:
68
65
  pasplitf = re.search('^[a-z0-9A-Z]+', pasplit[0]).group(0)
69
66
  return pasplitf
@@ -73,7 +70,6 @@ class Storage(BaseStorage):
73
70
  def get_crypto(self, path):
74
71
  db, storage = self.__conn__()
75
72
  tpath = self.truepath(path)
76
- pasplit = path.split("/")
77
73
  crypto = db.storage.find_one({'path': tpath})
78
74
  if crypto:
79
75
  return crypto.get('crypto')
@@ -82,7 +78,6 @@ class Storage(BaseStorage):
82
78
 
83
79
  async def get_detector_data(self, path):
84
80
  db, storage = self.__conn__()
85
- pasplit = path.split("/")
86
81
  tpath = self.truepath(path)
87
82
  doc = db.storage.find_one({'path': tpath})
88
83
  if doc:
@@ -96,9 +91,7 @@ class Storage(BaseStorage):
96
91
  stored = db.storage.find_one({'path': tpath})
97
92
  if not stored:
98
93
  return None
99
- # if self.__is_expired(stored):
100
- #self.remove(path)
101
- # return None
94
+
102
95
  fs = gridfs.GridFS(db)
103
96
  contents = fs.get(stored['file_id']).read()
104
97
  return bytes(contents)
@@ -1,6 +1,4 @@
1
- #!/usr/bin/python
2
1
  # -*- coding: utf-8 -*-
3
-
4
2
  # Blackhand library for Thumbor
5
- # Licensed under the GNU/GPL license:
6
- # https://fsf.org/
3
+ # Licensed under the MIT license:
4
+ # http://www.opensource.org/licenses/mit-license
@@ -1,12 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # Blackhand library for Thumbor
3
- # Licensed under the GNU/GPL license:
4
- # https://fsf.org/
3
+ # Licensed under the MIT license:
4
+ # http://www.opensource.org/licenses/mit-license
5
5
  import base64
6
6
  import hashlib
7
7
  import hmac
8
8
  from thumbor.url_signers import BaseUrlSigner
9
- from thumbor.utils import deprecated, logger
9
+ #from thumbor.utils import deprecated, logger
10
10
 
11
11
 
12
12
  class UrlSigner(BaseUrlSigner):
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Blackhand.org
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,22 +1,25 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: thumbor-libs-blackhand
3
- Version: 0.1.6
3
+ Version: 0.5.0
4
4
  Summary: libs thumbor
5
5
  Home-page: https://github.com/Bkhand/thumbor_libs_blackhand
6
6
  Author: Bertrand Thill
7
7
  Author-email: github@blackhand.org
8
8
  License: GNU
9
9
  Keywords: thumbor,fallback,images,nfs,mongodb
10
+ Platform: UNKNOWN
10
11
  Classifier: Development Status :: 4 - Beta
11
12
  Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
13
+ Classifier: License :: OSI Approved :: MIT License
13
14
  Classifier: Natural Language :: French
14
15
  Classifier: Operating System :: POSIX :: Linux
15
- Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.11
16
17
  Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
17
18
  Classifier: Topic :: Multimedia :: Graphics :: Presentation
18
19
  License-File: LICENSE
19
- Requires-Dist: thumbor (>=7.1.0)
20
+ Requires-Dist: thumbor (>=7.7.0)
20
21
  Requires-Dist: pymongo (>=4.2.0)
21
22
 
22
23
  This module enable mongodb support and fallback for thumbor.
24
+
25
+
@@ -0,0 +1,20 @@
1
+ thumbor_libs_blackhand/loaders/__init__.py,sha256=5izS_bmGrlIsSPAU1JYYvHuAaq2qHHanGXr_dPPtyuo,138
2
+ thumbor_libs_blackhand/loaders/mongodb_loader.py,sha256=6K5RlY48THkws-LVF10xF_ISU98OGjRMVzY1jnjudXg,1910
3
+ thumbor_libs_blackhand/loaders/spec_http_or_specb_loader.py,sha256=jxrf7JdlQsWHtUpPNtDvLk9IrJFPqhX4brwCdPTgkKs,533
4
+ thumbor_libs_blackhand/loaders/specb_file_fallback_file_loader.py,sha256=842cYNbJjoROspnIGbIyIMXmjaa0EjmsfK-Aa0Lnkgo,2521
5
+ thumbor_libs_blackhand/metrics/__init__.py,sha256=5izS_bmGrlIsSPAU1JYYvHuAaq2qHHanGXr_dPPtyuo,138
6
+ thumbor_libs_blackhand/mongodb/pool_result_storage.py,sha256=ZHARWEFGacLXjtxqVxVmwFGOS94w0SkhkwC96VM00LE,1781
7
+ thumbor_libs_blackhand/result_storages/__init__.py,sha256=5izS_bmGrlIsSPAU1JYYvHuAaq2qHHanGXr_dPPtyuo,138
8
+ thumbor_libs_blackhand/result_storages/hybrid_result_storage.py,sha256=wFUzMeZxPzU_BvFjNJWZPh7bCla0x-s7Iwj6TiFOgDE,6672
9
+ thumbor_libs_blackhand/result_storages/mongodb_result_storage_v3.py,sha256=e1wIBcLx6lN_gDDPaJTelQdKyB3zyxPQPjCMLugx-uY,6075
10
+ thumbor_libs_blackhand/result_storages/mongodb_result_storage_v4.py,sha256=rTGtpfVZamErPfCA-z3-3vgf5uP_HDH3f3Sq8WOg19w,6462
11
+ thumbor_libs_blackhand/result_storages/mongodb_result_storage_v5.py,sha256=_wElwxgrF-QYLc5VyKMdUxsknc403QihGwP1AFaVQ4U,5068
12
+ thumbor_libs_blackhand/storages/__init__.py,sha256=5izS_bmGrlIsSPAU1JYYvHuAaq2qHHanGXr_dPPtyuo,138
13
+ thumbor_libs_blackhand/storages/mongodb_webp_storage.py,sha256=QSLAkoiqXRQXDq-2HUWGUTsz9hNyatKQg7_LB6ikN6o,4401
14
+ thumbor_libs_blackhand/url_signers/__init__.py,sha256=5izS_bmGrlIsSPAU1JYYvHuAaq2qHHanGXr_dPPtyuo,138
15
+ thumbor_libs_blackhand/url_signers/base64_hmac_sha1_trim.py,sha256=4TNCfNqBRRQgTo90N3Ej2SDo2jYzzDm31hOFrk0BsVc,583
16
+ thumbor_libs_blackhand-0.5.0.dist-info/LICENSE,sha256=H3K2DdEDDUNhtBvyWkPh8SodWqMuiOefZWwdDxA98VE,1079
17
+ thumbor_libs_blackhand-0.5.0.dist-info/METADATA,sha256=C7NPwUArCyGScWcXtJO_xI9VJMTvZmc4UrF35wliD0k,831
18
+ thumbor_libs_blackhand-0.5.0.dist-info/WHEEL,sha256=ewwEueio1C2XeHTvT17n8dZUJgOvyCWCt0WVNLClP9o,92
19
+ thumbor_libs_blackhand-0.5.0.dist-info/top_level.txt,sha256=qs2ZPZFH1pQYGF-qqZzRbRbPHdtBugtefP7mUslef90,23
20
+ thumbor_libs_blackhand-0.5.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.1)
2
+ Generator: bdist_wheel (0.37.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,117 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # Blackhand library for Thumbor
3
- # Licensed under the GNU/GPL license:
4
- # https://fsf.org/
5
- import bson
6
- import time
7
- import urllib.request, urllib.parse, urllib.error
8
- import re
9
- from datetime import datetime, timedelta
10
- from io import StringIO
11
- from thumbor.result_storages import BaseStorage
12
- from thumbor.utils import logger
13
- from bson.binary import Binary
14
- from pymongo.mongo_client import MongoClient
15
- from pymongo.server_api import ServerApi
16
- from sys import getsizeof
17
-
18
-
19
- class Storage(BaseStorage):
20
- @property
21
- def is_auto_webp(self):
22
- return self.context.config.AUTO_WEBP and self.context.request.accepts_webp
23
-
24
-
25
- def __conn__(self):
26
- #server_api = ServerApi('1', strict=True)
27
- #client = MongoClient(self.context.config.MONGO_RESULT_STORAGE_URI) #, server_api=server_api)
28
- #db = client[self.context.config.MONGO_RESULT_STORAGE_SERVER_DB]
29
- #storage = self.context.config.MONGO_RESULT_STORAGE_SERVER_COLLECTION
30
- #return db, storage
31
-
32
- password = urllib.parse.quote_plus(self.context.config.MONGO_RESULT_STORAGE_SERVER_PASSWORD)
33
- user = urllib.parse.quote_plus(self.context.config.MONGO_RESULT_STORAGE_SERVER_USER)
34
- if not self.context.config.MONGO_RESULT_STORAGE_SERVER_REPLICASET:
35
- uri = 'mongodb://'+ user +':' + password + '@' + self.context.config.MONGO_RESULT_STORAGE_SERVER_HOST + '/?authSource=' + self.context.config.MONGO_RESULT_STORAGE_SERVER_DB
36
- else:
37
- uri = 'mongodb://'+ user +':' + password + '@' + self.context.config.MONGO_RESULT_STORAGE_SERVER_HOST + '/?authSource=' + self.context.config.MONGO_RESULT_STORAGE_SERVER_DB + "&replicaSet=" + self.context.config.MONGO_RESULT_STORAGE_SERVER_REPLICASET + "&readPreference=" + self.context.config.MONGO_RESULT_STORAGE_SERVER_READ_PREFERENCE
38
- client = MongoClient(uri)
39
- db = client[self.context.config.MONGO_RESULT_STORAGE_SERVER_DB]
40
- storage = self.context.config.MONGO_RESULT_STORAGE_SERVER_COLLECTION
41
- return db, storage
42
-
43
-
44
- def get_max_age(self):
45
- default_ttl = self.context.config.RESULT_STORAGE_EXPIRATION_SECONDS
46
- if self.context.request.max_age == 0:
47
- return self.context.request.max_age
48
- return default_ttl
49
-
50
-
51
- def get_key_from_request(self):
52
- path = "result:%s" % self.context.request.url
53
- return path
54
-
55
-
56
- async def put(self, image_bytes):
57
- db, storage = self.__conn__()
58
- key = self.get_key_from_request()
59
- max_age = self.get_max_age()
60
- result_ttl = self.get_max_age()
61
- ref_img = ''
62
- ref_img = re.findall(r'/[a-zA-Z0-9]{24}(?:$|/)', key)
63
- if ref_img:
64
- ref_img2 = ref_img[0].replace('/','')
65
- else:
66
- ref_img2 = 'undef'
67
-
68
- if self.is_auto_webp:
69
- content_t = 'webp'
70
- else:
71
- content_t = 'default'
72
- doc = {
73
- 'path': key,
74
- 'created_at': datetime.utcnow(),
75
- 'data': Binary(image_bytes),
76
- 'content-type': content_t,
77
- 'ref_id': ref_img2
78
- }
79
- doc_cpm = dict(doc)
80
-
81
- try:
82
- self.context.config.MONGO_RESULT_STORAGE_MAXCACHESIZE
83
- maxs = self.context.config.MONGO_RESULT_STORAGE_MAXCACHESIZE
84
- except:
85
- maxs = 16000000
86
-
87
- amd = getsizeof(bytes)
88
- if amd > maxs:
89
- logger.warning(u"OVERSIZE %s: %s > %s pas de mise en cache possible", key, amd, maxs)
90
- return None
91
- else:
92
- db[storage].insert_one(doc_cpm)
93
- return key
94
-
95
- #if result_ttl > 0:
96
- # ref = datetime.utcnow() + timedelta(
97
- # seconds=result_ttl
98
- # )
99
- # doc_cpm['expire'] = ref
100
- #db[storage].insert_one(doc_cpm)
101
- #return key
102
-
103
-
104
- async def get(self):
105
- db, storage = self.__conn__()
106
- key = self.get_key_from_request()
107
- logger.debug("[RESULT_STORAGE] image not found at %s", key)
108
-
109
- #if self.is_auto_webp:
110
- # result = db.storage.find_one({'path': key }) #, 'content-type': "webp"})
111
- #else:
112
- result = db[storage].find_one({'path': key }) #, 'content-type': "default"})
113
-
114
- if not result:
115
- return None
116
- tosend = result['data']
117
- return tosend