Skip to content

Commit 3dd9ca1

Browse files
committed
support custom filename in raw file upload
1 parent 0f37c4d commit 3dd9ca1

5 files changed

Lines changed: 10 additions & 5 deletions

File tree

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Changelog
66

77
**Improvements**:
88

9+
- Support custom filename in ``redmine.upload()``
910
- Support for ``get()`` and ``update()`` operations for ``/my/account`` endpoint which doesn't require admin
1011
privileges by using ``me`` as an id, i.e. ``redmine.user.get('me')`` or ``redmine.user.update('me',firstname='John')``
1112
(requires Redmine >= 4.1.0)

docs/advanced/working_with_files.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ Upload
2020

2121
:param f: (required). File path / stream that will be uploaded.
2222
:type f: string or file-like object
23+
:param filename: (optional). Filename for the file that will be uploaded.
2324
:return: dict with id and token string (Redmine >= 3.4.0) or dict with token string only (Redmine < 3.4.0)
2425

2526
.. code-block:: python
2627
27-
>>> data = redmine.upload('/usr/local/image.jpg')
28+
>>> data = redmine.upload('/usr/local/image.jpg', filename='beauty.jpg')
2829
>>> data
2930
{'id': 7167, 'token': '7167.ed1ccdb093229ca1bd0b043618d88743'}
3031

redminelib/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,20 @@ def session(self, **options):
8686
finally:
8787
self.engine = engine
8888

89-
def upload(self, f):
89+
def upload(self, f, filename=None):
9090
"""
9191
Uploads file from file path / file stream to Redmine and returns an assigned token.
9292
9393
:param f: (required). File path / stream that will be uploaded.
9494
:type f: string or file-like object
95+
:param filename: (optional). Filename for the file that will be uploaded.
9596
"""
9697
if self.ver is not None and LooseVersion(str(self.ver)) < LooseVersion('1.4.0'):
9798
raise exceptions.VersionMismatchError('File uploading')
9899

99100
url = '{0}/uploads.json'.format(self.url)
100101
headers = {'Content-Type': 'application/octet-stream'}
102+
params = {'filename': filename or ''}
101103

102104
# There're myriads of file-like object implementations here and there and some of them don't have
103105
# a "read" method, which is wrong, but that's what we have, on the other hand it looks like all of
@@ -127,7 +129,7 @@ def upload(self, f):
127129
stream = open(f, 'rb')
128130
close = True
129131

130-
response = self.engine.request('post', url, data=stream, headers=headers)
132+
response = self.engine.request('post', url, params=params, data=stream, headers=headers)
131133

132134
if close:
133135
stream.close()

redminelib/resources/base.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,8 @@ def decode(cls, attr, value, manager):
257257
if attr == 'uploads':
258258
for index, attachment in enumerate(value):
259259
if 'token' not in attachment:
260-
value[index]['token'] = manager.redmine.upload(attachment.pop('path', ''))['token']
260+
value[index]['token'] = manager.redmine.upload(
261+
attachment.pop('path', ''), filename=attachment.get('filename'))['token']
261262

262263
return attr, value
263264
elif attr == 'include' and isinstance(value, (list, tuple)):

tests/test_redmine.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def test_session_requests(self):
6262
def test_successful_file_upload(self):
6363
self.response.status_code = 201
6464
self.response.json.return_value = {'upload': {'id': 1, 'token': '123456'}}
65-
self.assertEqual(self.redmine.upload('foo')['token'], '123456')
65+
self.assertEqual(self.redmine.upload('foo', filename='foo.jpg')['token'], '123456')
6666

6767
def test_successful_filestream_upload(self):
6868
from io import StringIO

0 commit comments

Comments
 (0)