Skip to content

Commit b7fc1d8

Browse files
authored
Merge pull request #3 from althonos/master
Update webdavfs to new fs standards
2 parents f88a8cc + ff062cb commit b7fc1d8

File tree

13 files changed

+402
-269
lines changed

13 files changed

+402
-269
lines changed

.gitignore

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
env/
12+
build/
13+
develop-eggs/
14+
dist/
15+
downloads/
16+
eggs/
17+
.eggs/
18+
lib/
19+
lib64/
20+
parts/
21+
sdist/
22+
var/
23+
*.egg-info/
24+
.installed.cfg
25+
*.egg
26+
27+
# PyInstaller
28+
# Usually these files are written by a python script from a template
29+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
30+
*.manifest
31+
*.spec
32+
33+
# Installer logs
34+
pip-log.txt
35+
pip-delete-this-directory.txt
36+
37+
# Unit test / coverage reports
38+
htmlcov/
39+
.tox/
40+
.coverage
41+
.coverage.*
42+
.cache
43+
nosetests.xml
44+
coverage.xml
45+
*,cover
46+
.hypothesis/
47+
48+
# Translations
49+
*.mo
50+
*.pot
51+
52+
# Django stuff:
53+
*.log
54+
local_settings.py
55+
56+
# Flask stuff:
57+
instance/
58+
.webassets-cache
59+
60+
# Scrapy stuff:
61+
.scrapy
62+
63+
# Sphinx documentation
64+
docs/_build/
65+
66+
# PyBuilder
67+
target/
68+
69+
# IPython Notebook
70+
.ipynb_checkpoints
71+
72+
# pyenv
73+
.python-version
74+
75+
# celery beat schedule file
76+
celerybeat-schedule
77+
78+
# dotenv
79+
.env
80+
81+
# virtualenv
82+
venv/
83+
ENV/
84+
85+
# Spyder project settings
86+
.spyderproject
87+
88+
# Rope project settings
89+
.ropeproject
90+
91+
# Codacy token
92+
.codacy.token

.travis.yml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
language: python
2-
dist: trusty
3-
sudo: required
2+
sudo: false
43

54
cache: pip
65

@@ -14,12 +13,16 @@ python:
1413
- "3.5"
1514
- "3.6"
1615

16+
before_install:
17+
# Pull docker images early for a more responsive nosetests run
18+
- echo zopyx/basex-86 zopyx/existdb-22 zopyx/existdb-30 | xargs -n1 docker pull
19+
1720
install:
18-
- make install
21+
- pip install -U pip setuptools wheel
22+
- pip install .
23+
24+
script:
25+
- python setup.py test
1926

2027
after_success:
2128
- coveralls
22-
23-
# command to run tests
24-
script:
25-
- make test test-existdb-22 test-basex

Makefile

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,15 @@ release:
55

66
install:
77
virtualenv .
8-
bin/pip install -U pip
9-
bin/pip install -U setuptools
10-
bin/python setup.py develop
8+
bin/pip install -U pip setuptools
9+
bin/pip install -e .
1110

12-
test:
13-
bin/pip install nose
14-
/usr/bin/python -c "import os; os.system('docker rm -f existdb30')"
15-
docker run -d -p 127.0.0.1:10080:8080 --name existdb30 zopyx/existdb-30
16-
sleep 30
17-
FS_WEBDAV_URL=http://admin:admin@localhost:10080/exist/webdav/db bin/nosetests -v webdavfs
11+
pull:
12+
docker pull zopyx/basex-86
13+
docker pull zopyx/existdb-22
14+
docker pull zopyx/existdb-30
1815

19-
test-existdb-22:
20-
bin/pip install nose
21-
/usr/bin/python -c "import os; os.system('docker rm -f existdb22')"
22-
docker run -d -p 127.0.0.1:10082:8080 --name existdb22 zopyx/existdb-22
23-
sleep 30
24-
FS_WEBDAV_URL=http://admin:admin@localhost:10082/exist/webdav/db bin/nosetests -v webdavfs
25-
26-
test-basex:
27-
bin/pip install nose
28-
/usr/bin/python -c "import os; os.system('docker rm -f basex')"
29-
docker run -d -p 127.0.0.1:10081:8080 --name basex zopyx/basex-86
30-
sleep 10
31-
FS_WEBDAV_URL=http://admin:admin@localhost:10081/webdav/ bin/nosetests -v webdavfs
16+
test: pull
17+
bin/pip install nose docker
18+
bin/nosetests -v webdavfs
3219

README.rst

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,24 @@ Supported Python versions
1515
Usage
1616
-----
1717

18+
Use the ``fs.open_fs`` method with the ``webdav://`` protocol:
19+
20+
.. code:: python
21+
22+
>>> import fs
23+
>>> handle = fs.open_fs('webdav://admin:[email protected]:22082/exist/webdav/db')
24+
25+
or use the public constructor of the ``WebDAVFS`` class:
26+
1827
.. code:: python
1928
20-
> from webdavfs.webdavfs import WebDAVFS
21-
> url = 'http://zopyx.com:22082'
22-
> creds = dict(login='admin', password='admin')
23-
> root = '/exist/webdav/db'
24-
> handle = WebDAVFS(url, cred, root)
25-
> handle.makedir('foo')
26-
> print(handle.listdir('.'))
29+
>>> from webdavfs.webdavfs import WebDAVFS
30+
>>> url = 'http://zopyx.com:22082'
31+
>>> creds = dict(login='admin', password='admin')
32+
>>> root = '/exist/webdav/db'
33+
>>> handle = WebDAVFS(url, cred, root)
34+
>>> handle.makedir('foo')
35+
>>> print(handle.listdir('.'))
2736
....
2837
2938
Repository
@@ -47,6 +56,7 @@ Author and contributors
4756
- Yuriy Homyakov
4857
- Semyon Gaivoronskiy
4958
- Andreas Jung
59+
- `Martin Larralde <https://github.com/althonos>`_
5060

5161

5262
License

setup.cfg

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[alias]
2+
test = nosetests
3+
4+
[nosetests]
5+
verbosity = 2

setup.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,27 @@
2424
HISTORY = f.read()
2525

2626
REQUIREMENTS = [
27-
"fs>=2.0.0",
27+
"fs~=2.0.7",
2828
"webdavclient2",
29-
"furl"
3029
]
3130

3231
setup(
3332
author="Andreas Jung and others",
3433
author_email="[email protected]",
3534
classifiers=CLASSIFIERS,
3635
description="WebDAV support for pyfilesystem2",
36+
entry_points={
37+
'fs.opener': 'webdav = webdavfs.opener:WebDAVOpener'
38+
},
3739
install_requires=REQUIREMENTS,
3840
license="BSD",
3941
long_description=DESCRIPTION + "\n" + HISTORY,
4042
name='fs.webdavfs',
4143
packages=find_packages(exclude=("tests",)),
4244
platforms=['any'],
43-
test_suite="nose.collector",
45+
setup_requires=['nose'],
46+
tests_require=['docker'],
47+
test_suite='webdavfs.tests',
4448
url="http://pypi.python.org/pypi/fs.webdavfs/",
4549
version="0.2.1"
4650
)
47-
48-

webdavfs/opener.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# coding: utf-8
2+
"""Defines the WebDAVFS opener."""
3+
4+
from __future__ import absolute_import
5+
from __future__ import unicode_literals
6+
7+
from fs.opener.base import Opener
8+
9+
__author__ = "Martin Larralde <[email protected]>"
10+
11+
class WebDAVOpener(Opener):
12+
protocols = ['webdav']
13+
14+
def open_fs(self, fs_url, parse_result, writeable, create, cwd):
15+
from .webdavfs import WebDAVFS
16+
from fs.subfs import ClosingSubFS
17+
18+
webdav_host, _, dir_path = parse_result.resource.partition('/')
19+
webdav_host, _, webdav_port = webdav_host.partition(':')
20+
webdav_port = int(webdav_port) if webdav_port.isdigit() else 80
21+
22+
return WebDAVFS(
23+
url='http://{}:{}'.format(webdav_host, webdav_port),
24+
credentials={
25+
'login': parse_result.username,
26+
'password': parse_result.password
27+
},
28+
root=dir_path,
29+
)

webdavfs/tests/base.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# coding: utf-8
2+
from __future__ import absolute_import
3+
from __future__ import unicode_literals
4+
5+
import uuid
6+
import fs
7+
8+
9+
#@attr('slow')
10+
class _TestWebDAVFS(object):
11+
"""Test WebDAVFS implementation."""
12+
13+
webdav_url = NotImplemented
14+
15+
def setUp(self):
16+
self.test_root = '{}'.format(uuid.uuid4())
17+
self.fs = self.make_fs()
18+
19+
def make_fs(self):
20+
with fs.open_fs(self.webdav_url) as handle:
21+
if handle.exists(self.test_root):
22+
handle.rmdir(self.test_root, recursive=True)
23+
handle.makedir(self.test_root)
24+
return fs.open_fs('/'.join([self.webdav_url, self.test_root]))
25+
26+
def destroy_fs(self, fs):
27+
for item in fs.client.list('/'):
28+
fs.client.clean(item)
29+
super(_TestWebDAVFS, self).destroy_fs(fs)
30+
31+
def test_directories_mkdir_removedir(self):
32+
for i in range(5):
33+
self.fs.makedir(u'{}'.format(i))
34+
for i in range(5):
35+
self.fs.removedir(u'{}'.format(i))

webdavfs/tests/test_docker.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# coding: utf-8
2+
from __future__ import unicode_literals
3+
from __future__ import absolute_import
4+
5+
import re
6+
import time
7+
import unittest
8+
import fs.test
9+
import docker
10+
11+
from .base import _TestWebDAVFS
12+
13+
14+
class _TestDocker(_TestWebDAVFS, fs.test.FSTestCases):
15+
"""Test WebDAVFS implementation using docker images."""
16+
17+
server_image = NotImplemented
18+
19+
@classmethod
20+
def serverStarted(cls):
21+
regex = re.compile(b'Server [hw]as started')
22+
cls.webdav_container.update()
23+
return regex.search(cls.webdav_container.logs()) is not None
24+
25+
@classmethod
26+
def startServer(cls):
27+
cls.webdav_container = cls.docker_client.containers.run(
28+
cls.server_image, detach=True, tty=True,
29+
ports={'8080/tcp': ('127.0.0.1', 10080)}
30+
)
31+
while not cls.serverStarted():
32+
time.sleep(1)
33+
34+
@classmethod
35+
def stopServer(cls):
36+
cls.webdav_container.kill()
37+
cls.webdav_container.remove()
38+
39+
@classmethod
40+
def setUpClass(cls):
41+
cls.docker_client = docker.from_env(version='auto')
42+
cls.startServer()
43+
44+
@classmethod
45+
def tearDownClass(cls):
46+
cls.stopServer()
47+
time.sleep(20)
48+
49+
50+
class TestExistDB30(_TestDocker, unittest.TestCase):
51+
server_image = 'zopyx/existdb-30'
52+
webdav_url = 'webdav://admin:admin@localhost:10080/exist/webdav/db'
53+
54+
class TestExistDB22(_TestDocker, unittest.TestCase):
55+
server_image = 'zopyx/existdb-22'
56+
webdav_url = 'webdav://admin:admin@localhost:10080/exist/webdav/db'
57+
58+
class TestBaseX86(_TestDocker, unittest.TestCase):
59+
server_image = 'zopyx/basex-86'
60+
webdav_url = 'webdav://admin:admin@localhost:10080/webdav'

webdavfs/tests/test_server.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# coding: utf-8
2+
from __future__ import unicode_literals
3+
from __future__ import absolute_import
4+
5+
import os
6+
import unittest
7+
import fs.test
8+
9+
from .base import _TestWebDAVFS
10+
11+
12+
@unittest.skipUnless(
13+
os.getenv('WEBDAVFS_USE_SERVERS', 'false').lower() == 'true',
14+
'Set WEBDAVFS_USE_SERVERS to True to enable tests against real servers')
15+
class _TestServer(_TestWebDAVFS):
16+
"""Test WebDAVFS implementation using actual servers."""
17+
18+
19+
class TestServerFull(_TestServer, fs.test.FSTestCases, unittest.TestCase):
20+
webdav_url = 'webdav://admin:[email protected]:20082/exist/webdav/db'
21+
22+
23+
class TestServerCommons(_TestServer, unittest.TestCase):
24+
webdav_url = 'webdav://admin:[email protected]:22082/exist/webdav/db'

0 commit comments

Comments
 (0)