Skip to content

Commit 5d3d350

Browse files
author
Bartek Kwiecien
committed
Merge branch 'release/3.1.0'
2 parents 0977155 + fec6dd1 commit 5d3d350

15 files changed

+97
-73
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Filestack-Python Changelog
22

3+
### 3.1.0 (April 14th, 2020)
4+
- Transformations added: auto_image, minify_js, minify_css
5+
- Added configurable CNAME
6+
- Fixed path param in store task
7+
38
### 3.0.1 (July 22nd, 2019)
49
- Added enhance presets
510
- Set filelink security when uploading from url

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.0.1
1+
3.1.0

filestack/__init__.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,33 @@
1-
__version__ = '3.0.1'
1+
__version__ = '3.1.0'
2+
3+
4+
class CFG:
5+
API_URL = 'https://www.filestackapi.com/api'
6+
DEFAULT_CHUNK_SIZE = 5 * 1024 ** 2
7+
DEFAULT_UPLOAD_MIMETYPE = 'application/octet-stream'
8+
9+
HEADERS = {
10+
'User-Agent': 'filestack-python {}'.format(__version__),
11+
'Filestack-Source': 'Python-{}'.format(__version__)
12+
}
13+
14+
def __init__(self):
15+
self.CNAME = ''
16+
17+
@property
18+
def CDN_URL(self):
19+
return 'https://cdn.{}'.format(self.CNAME or 'filestackcontent.com')
20+
21+
@property
22+
def MULTIPART_START_URL(self):
23+
return 'https://upload.{}/multipart/start'.format(
24+
self.CNAME or 'filestackapi.com'
25+
)
26+
27+
28+
config = CFG()
29+
30+
231
from .models.client import Client
332
from .models.filelink import Filelink
433
from .models.security import Security

filestack/config.py

Lines changed: 0 additions & 15 deletions
This file was deleted.

filestack/mixins/common.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ def store(self, filename=None, location=None, path=None, container=None,
6464
Returns:
6565
:class:`filestack.Filelink`: new Filelink object
6666
"""
67+
if path:
68+
path = '"{}"'.format(path)
6769
instance = self._add_transform_task('store', locals())
6870
response = requests.post(instance.url)
6971
return filestack.models.Filelink(handle=response.json()['handle'])

filestack/mixins/imagetransformation.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ def pdf_info(self, colorinfo=None):
126126
def pdf_convert(self, pageorientation=None, pageformat=None, pages=None):
127127
return self._add_transform_task('pdfconvert', locals())
128128

129+
def minify_js(self, gzip=None, use_babel_polyfill=None, keep_fn_name=None, keep_class_name=None,
130+
mangle=None, merge_vars=None, remove_console=None, remove_undefined=None, targets=None):
131+
return self._add_transform_task('minify_js', locals())
132+
133+
def minify_css(self, level=None, gzip=None):
134+
return self._add_transform_task('minify_css', locals())
135+
129136
def av_convert(self, *, preset=None, force=None, title=None, extname=None, filename=None,
130137
width=None, height=None, upscale=None, aspect_mode=None, two_pass=None,
131138
video_bitrate=None, fps=None, keyframe_interval=None, location=None,
@@ -143,6 +150,9 @@ def av_convert(self, *, preset=None, force=None, title=None, extname=None, filen
143150
new_transform.url, uuid, timestamp, apikey=new_transform.apikey, security=new_transform.security
144151
)
145152

153+
def auto_image(self):
154+
return self._add_transform_task('auto_image', locals())
155+
146156
def _add_transform_task(self, transformation, params):
147157
if isinstance(self, filestack.models.Transformation):
148158
instance = self

filestack/models/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class Client:
2525
def __init__(self, apikey, storage='S3', security=None):
2626
"""
2727
Args:
28-
apikey (str): The path of the file to wrap
28+
apikey (str): your Filestack API key
2929
storage (str): default storage to be used for uploads (one of S3, `gcs`, dropbox, azure)
3030
security (:class:`filestack.Security`): Security object that will be used by default
3131
for all API calls
@@ -109,7 +109,7 @@ def zip(self, destination_path, files, security=None):
109109

110110
def upload_url(self, url, store_params=None, security=None):
111111
"""
112-
Uploads local file from external url
112+
Uploads file from external url
113113
114114
Args:
115115
url (str): file URL

filestack/uploads/external_url.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import base64
12
from collections import OrderedDict
23

34
from filestack.utils import requests
@@ -24,7 +25,8 @@ def build_store_task(store_params):
2425

2526
def upload_external_url(url, apikey, store_params=None, security=None):
2627
store_task = build_store_task(store_params or {})
27-
url_elements = [config.CDN_URL, apikey, store_task, url]
28+
encoded_url = 'b64://{}'.format(base64.urlsafe_b64encode(url.encode()).decode())
29+
url_elements = [config.CDN_URL, apikey, store_task, encoded_url]
2830

2931
if security is not None:
3032
url_elements.insert(3, security.as_url_string())

filestack/uploads/intelligent_ingestion.py

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
import mimetypes
55
import hashlib
66
import logging
7-
import time
87
import functools
9-
from multiprocessing.pool import ThreadPool
108
import threading
9+
from urllib3.util.retry import Retry
10+
from multiprocessing.pool import ThreadPool
1111

1212
from base64 import b64encode
1313

@@ -143,17 +143,12 @@ def upload(apikey, filepath, file_obj, storage, params=None, security=None):
143143
payload['store']['workflows'] = params['workflows']
144144

145145
complete_url = 'https://{}/multipart/complete'.format(start_response['location_url'])
146-
for wait_time in (0, 1, 2, 3, 5):
147-
time.sleep(wait_time)
148-
complete_response = requests.post(complete_url, json=payload, headers=config.HEADERS)
149-
log.debug('Complete response: %s. Content: %s', complete_response, complete_response.content)
150-
if complete_response.status_code == 200:
151-
break
152-
else:
153-
log.error(
154-
'Did not receive a correct complete response: %s. Content %s',
155-
complete_response, complete_response.content
156-
)
157-
raise
158-
159-
return complete_response.json()
146+
session = requests.Session()
147+
retries = Retry(total=7, backoff_factor=0.2, status_forcelist=[202], method_whitelist=frozenset(['POST']))
148+
session.mount('http://', requests.adapters.HTTPAdapter(max_retries=retries))
149+
response = session.post(complete_url, json=payload, headers=config.HEADERS)
150+
if response.status_code != 200:
151+
log.error('Did not receive a correct complete response: %s. Content %s', response, response.content)
152+
raise Exception('Invalid complete response: {}'.format(response.content))
153+
154+
return response.json()

filestack/uploads/multipart.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ def bytes(self):
3333

3434

3535
def multipart_request(url, payload, params=None, security=None):
36-
3736
for key in ('path', 'location', 'region', 'container', 'access'):
3837
if key in params:
3938
payload['store'][key] = params[key]

0 commit comments

Comments
 (0)