Compare commits

..

8 commits

Author SHA1 Message Date
Alex Jordan
a3c75b7155 Fixes ezhov-evgeny#43 - local certificate options ignored
If the webdav_cert_path and webdav_key_path options are set, they
should be passed to the call to requests in Client.execute_request
as the cert parameter.
2020-04-06 15:40:35 -07:00
Evgeny Ezhov
39afefffc5 Fixed #49: Remove tailing slashes in web_hostname 2020-04-05 17:56:56 -07:00
Evgeny Ezhov
eeaf66a278 Update Travis CI config for SonarQube 2020-04-05 17:15:34 -07:00
Martin
af64110364 Fix request calling to use session's auth. 2020-04-05 11:43:51 -07:00
Evgeny Ezhov
3aab20b02a Bump version to 3.14.1 before publish 2020-02-23 17:43:12 -08:00
Evgeny Ezhov
0ac3c5e55f Small refactoring 2020-02-19 16:49:52 -08:00
Daniel Loader
3c5ba516af Add Oauth2 Bearer Token support
Basic implementation of authenticating with token instead of basic auth, as the auth=(login,password) flag on requests sends junk authentication as it overrides the bearer authentication header with a base64 encoded blank string.
2020-02-19 16:49:52 -08:00
Evgeny Ezhov
f64efedd96 Fixed issue #40 - error during coping and moving files with cyrillic names 2020-02-18 16:56:36 -08:00
11 changed files with 66 additions and 12 deletions

View file

@ -4,8 +4,7 @@ dist: xenial
addons:
sonarcloud:
organization: "ezhov-evgeny"
token:
secure: f0f714f3bea6bd103e3eb82724ef3bb0d3b54d1d
token: f0f714f3bea6bd103e3eb82724ef3bb0d3b54d1d
services:
- docker

View file

@ -298,6 +298,10 @@ res1.write_async(local_path="~/Downloads/file1", callback)
Release Notes
-------------
**Version 3.14.1**
* Fixed issue during coping and moving files with cyrillic names
* Support OAuth2 bearer tokens by https://github.com/danielloader
**Version 3.14**
* Override methods for customizing communication with WebDAV servers
* Support multiple clients simultaneously

View file

@ -6,7 +6,7 @@ from setuptools import setup, find_packages
from setuptools.command.install import install as InstallCommand
from setuptools.command.test import test as TestCommand
version = "3.14"
version = "3.14.1"
requirements = "libxml2-dev libxslt-dev python-dev"

View file

@ -13,6 +13,7 @@ class BaseClientTestCase(unittest.TestCase):
remote_path_dir = 'test_dir'
remote_path_dir2 = 'test_dir2'
remote_inner_path_dir = 'test_dir/inner'
inner_dir_name = 'inner'
local_base_dir = 'tests/'
local_file = 'test.txt'
local_file_path = local_base_dir + 'test.txt'

View file

@ -208,10 +208,10 @@ class ClientTestCase(BaseClientTestCase):
self._prepare_for_downloading(True)
self.client.pull(self.remote_path_dir, self.local_path_dir)
self.assertTrue(path.exists(self.local_path_dir), 'Expected the directory is downloaded.')
self.assertTrue(path.exists(self.local_path_dir + os.path.sep + 'inner'), 'Expected the directory is downloaded.')
self.assertTrue(path.exists(self.local_path_dir + os.path.sep + 'inner'), 'Expected the directory is downloaded.')
self.assertTrue(path.exists(self.local_path_dir + os.path.sep + self.inner_dir_name), 'Expected the directory is downloaded.')
self.assertTrue(path.exists(self.local_path_dir + os.path.sep + self.inner_dir_name), 'Expected the directory is downloaded.')
self.assertTrue(path.isdir(self.local_path_dir), 'Expected this is a directory.')
self.assertTrue(path.isdir(self.local_path_dir + os.path.sep + 'inner'), 'Expected this is a directory.')
self.assertTrue(path.isdir(self.local_path_dir + os.path.sep + self.inner_dir_name), 'Expected this is a directory.')
self.assertTrue(path.exists(self.local_path_dir + os.path.sep + self.local_file),
'Expected the file is downloaded')
self.assertTrue(path.isfile(self.local_path_dir + os.path.sep + self.local_file),

View file

@ -0,0 +1,23 @@
import os
import unittest
from tests.test_client_it import ClientTestCase
class MultiClientTestCase(ClientTestCase):
remote_path_file = 'директория/тестовый.txt'
remote_path_file2 = 'директория/тестовый2.txt'
remote_inner_path_file = 'директория/вложенная/тестовый.txt'
remote_path_dir = 'директория'
remote_path_dir2 = 'директория2'
remote_inner_path_dir = 'директория/вложенная'
inner_dir_name = 'вложенная'
local_base_dir = 'tests/'
local_file = 'тестовый.txt'
local_file_path = local_base_dir + 'тестовый.txt'
local_path_dir = local_base_dir + 'res/директория'
pulled_file = local_path_dir + os.sep + local_file
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1,26 @@
import unittest
from tests.test_client_it import ClientTestCase
class TailingSlashClientTestCase(ClientTestCase):
options = {
'webdav_hostname': 'http://localhost:8585/',
'webdav_login': 'alice',
'webdav_password': 'secret1234',
'webdav_override_methods': {
'check': 'GET'
}
}
def test_list_inner(self):
self._prepare_for_downloading(True)
file_list = self.client.list(self.remote_inner_path_dir)
self.assertIsNotNone(file_list, 'List of files should not be None')
def test_hostname_no_tailing_slash(self):
self.assertEqual('5', self.client.webdav.hostname[-1])
if __name__ == '__main__':
unittest.main()

View file

@ -0,0 +1 @@
test content for testing of webdav client

View file

@ -177,7 +177,7 @@ class Client(object):
headers.extend(headers_ext)
if self.webdav.token:
webdav_token = "Authorization: OAuth {token}".format(token=self.webdav.token)
webdav_token = "Authorization: Bearer {token}".format(token=self.webdav.token)
headers.append(webdav_token)
return dict([map(lambda s: s.strip(), i.split(':', 1)) for i in headers])
@ -214,9 +214,10 @@ class Client(object):
response = self.session.request(
method=self.requests[action],
url=self.get_url(path),
auth=(self.webdav.login, self.webdav.password),
auth=(self.webdav.login, self.webdav.password) if (not self.webdav.token and not self.session.auth) else None,
headers=self.get_headers(action, headers_ext),
timeout=self.timeout,
cert=(self.webdav.cert_path, self.webdav.key_path) if (self.webdav.cert_path and self.webdav.key_path) else None,
data=data,
stream=True,
verify=self.verify
@ -535,7 +536,7 @@ class Client(object):
raise RemoteParentNotFound(urn_to.path())
headers = [
"Destination: {url}".format(url=self.get_url(urn_to))
"Destination: {url}".format(url=self.get_url(urn_to.quote()))
]
if self.is_dir(urn_from.path()):
headers.append("Depth: {depth}".format(depth=depth))
@ -558,7 +559,7 @@ class Client(object):
if not self.check(urn_to.parent()):
raise RemoteParentNotFound(urn_to.path())
header_destination = "Destination: {path}".format(path=self.get_url(urn_to))
header_destination = "Destination: {path}".format(path=self.get_url(urn_to.quote()))
header_overwrite = "Overwrite: {flag}".format(flag="T" if overwrite else "F")
self.execute_request(action='move', path=urn_from.quote(), headers_ext=[header_destination, header_overwrite])

View file

@ -50,6 +50,7 @@ class WebDAVSettings(ConnectionSettings):
self.root = Urn(self.root).quote() if self.root else ''
self.root = self.root.rstrip(Urn.separate)
self.hostname = self.hostname.rstrip(Urn.separate)
def is_valid(self):
if not self.hostname:

View file

@ -34,13 +34,11 @@ class Urn(object):
return self._path
def filename(self):
path_split = self._path.split(Urn.separate)
name = path_split[-2] + Urn.separate if path_split[-1] == '' else path_split[-1]
return unquote(name)
def parent(self):
path_split = self._path.split(Urn.separate)
nesting_level = self.nesting_level()
parent_path_split = path_split[:nesting_level]