Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion fs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Python filesystem abstraction layer.
"""

__import__("pkg_resources").declare_namespace(__name__) # type: ignore
__path__ = __import__("pkgutil").extend_path(__path__, __name__)

from . import path
from ._fscompat import fsdecode, fsencode
Expand Down
2 changes: 1 addition & 1 deletion fs/opener/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""

# Declare fs.opener as a namespace package
__import__("pkg_resources").declare_namespace(__name__) # type: ignore
__path__ = __import__("pkgutil").extend_path(__path__, __name__)

# Import opener modules so that `registry.install` if called on each opener
from . import appfs, ftpfs, memoryfs, osfs, tarfs, tempfs, zipfs
Expand Down
37 changes: 28 additions & 9 deletions fs/opener/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

from __future__ import absolute_import, print_function, unicode_literals

import sys
import typing

import collections
import contextlib
import pkg_resources

from ..errors import ResourceReadOnly
from .base import Opener
Expand All @@ -20,6 +20,29 @@

from ..base import FS

if sys.version_info >= (3, 8):
import importlib.metadata

if sys.version_info >= (3, 10):

def entrypoints(group, name=None):
ep = importlib.metadata.entry_points(group=group, name=name)
return tuple(n for n in ep)

else:

def entrypoints(group, name=None):
ep = importlib.metadata.entry_points()
if name:
return tuple(n for n in ep.get(group, ()) if n.name == name)
return ep.get(group, ())

else:
import pkg_resources

def entrypoints(group, name=None):
return tuple(pkg_resources.iter_entry_points(group, name))


class Registry(object):
"""A registry for `Opener` instances."""
Expand Down Expand Up @@ -74,10 +97,7 @@ def protocols(self):
"""`list`: the list of supported protocols."""
_protocols = list(self._protocols)
if self.load_extern:
_protocols.extend(
entry_point.name
for entry_point in pkg_resources.iter_entry_points("fs.opener")
)
_protocols.extend(n.name for n in entrypoints("fs.opener"))
_protocols = list(collections.OrderedDict.fromkeys(_protocols))
return _protocols

Expand All @@ -101,10 +121,9 @@ def get_opener(self, protocol):
"""
protocol = protocol or self.default_opener

if self.load_extern:
entry_point = next(
pkg_resources.iter_entry_points("fs.opener", protocol), None
)
ep = entrypoints("fs.opener", protocol)
if self.load_extern and ep:
entry_point = ep[0]
else:
entry_point = None

Expand Down
3 changes: 1 addition & 2 deletions fs/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1082,8 +1082,7 @@ def test_remove(self):
self.fs.makedirs("foo/bar/baz/")

error_msg = "resource 'foo/bar/egg/test.txt' not found"
assertRaisesRegex = getattr(self, "assertRaisesRegex", self.assertRaisesRegexp)
with assertRaisesRegex(errors.ResourceNotFound, error_msg):
with six.assertRaisesRegex(self, errors.ResourceNotFound, error_msg):
self.fs.remove("foo/bar/egg/test.txt")

def test_removedir(self):
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ setup_requires =
setuptools >=38.3.0
install_requires =
appdirs~=1.4.3
setuptools
setuptools ; python_version < '3.8'
six ~=1.10
enum34 ~=1.1.6 ; python_version < '3.4'
typing ~=3.6 ; python_version < '3.6'
Expand Down
6 changes: 3 additions & 3 deletions tests/test_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def test_move_file_overwrite(self, _, fs_url):
self.assertFalse(src.exists("target.txt"))
self.assertFalse(dst.exists("file.txt"))
self.assertTrue(dst.exists("target.txt"))
self.assertEquals(dst.readtext("target.txt"), "source content")
self.assertEqual(dst.readtext("target.txt"), "source content")

@parameterized.expand([("temp", "temp://"), ("mem", "mem://")])
def test_move_file_overwrite_itself(self, _, fs_url):
Expand All @@ -177,7 +177,7 @@ def test_move_file_overwrite_itself(self, _, fs_url):
tmp.writetext("file.txt", "content")
fs.move.move_file(tmp, "file.txt", tmp, "file.txt")
self.assertTrue(tmp.exists("file.txt"))
self.assertEquals(tmp.readtext("file.txt"), "content")
self.assertEqual(tmp.readtext("file.txt"), "content")

@parameterized.expand([("temp", "temp://"), ("mem", "mem://")])
def test_move_file_overwrite_itself_relpath(self, _, fs_url):
Expand All @@ -188,7 +188,7 @@ def test_move_file_overwrite_itself_relpath(self, _, fs_url):
new_dir.writetext("file.txt", "content")
fs.move.move_file(tmp, "dir/../dir/file.txt", tmp, "dir/file.txt")
self.assertTrue(tmp.exists("dir/file.txt"))
self.assertEquals(tmp.readtext("dir/file.txt"), "content")
self.assertEqual(tmp.readtext("dir/file.txt"), "content")

@parameterized.expand([(True,), (False,)])
def test_move_file_cleanup_on_error(self, cleanup):
Expand Down
81 changes: 59 additions & 22 deletions tests/test_opener.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import sys

import os
import pkg_resources
import shutil
import tempfile
import unittest
Expand All @@ -21,6 +20,11 @@
except ImportError:
import mock

if sys.version_info >= (3, 8):
import importlib.metadata
else:
import pkg_resources


class TestParse(unittest.TestCase):
def test_registry_repr(self):
Expand Down Expand Up @@ -111,14 +115,25 @@ def test_protocols(self):

def test_registry_protocols(self):
# Check registry.protocols list the names of all available extension
extensions = [
pkg_resources.EntryPoint("proto1", "mod1"),
pkg_resources.EntryPoint("proto2", "mod2"),
]
m = mock.MagicMock(return_value=extensions)
with mock.patch.object(
sys.modules["pkg_resources"], "iter_entry_points", new=m
):
if sys.version_info >= (3, 8):
extensions = (
importlib.metadata.EntryPoint("proto1", "mod1", "fs.opener"),
importlib.metadata.EntryPoint("proto2", "mod2", "fs.opener"),
)
if sys.version_info >= (3, 10):
m = mock.MagicMock(return_value=extensions)
else:
m = mock.MagicMock(return_value={"fs.opener": extensions})
patch = mock.patch("importlib.metadata.entry_points", m)
else:
extensions = [
pkg_resources.EntryPoint("proto1", "mod1"),
pkg_resources.EntryPoint("proto2", "mod2"),
]
m = mock.MagicMock(return_value=extensions)
patch = mock.patch("pkg_resources.iter_entry_points", m)

with patch:
self.assertIn("proto1", opener.registry.protocols)
self.assertIn("proto2", opener.registry.protocols)

Expand All @@ -129,11 +144,20 @@ def test_unknown_protocol(self):
def test_entry_point_load_error(self):

entry_point = mock.MagicMock()
entry_point.name = "test"
entry_point.load.side_effect = ValueError("some error")

iter_entry_points = mock.MagicMock(return_value=iter([entry_point]))

with mock.patch("pkg_resources.iter_entry_points", iter_entry_points):
if sys.version_info >= (3, 8):
if sys.version_info >= (3, 10):
entry_points = mock.MagicMock(return_value=tuple([entry_point]))
else:
entry_points = mock.MagicMock(return_value={"fs.opener": [entry_point]})
patch = mock.patch("importlib.metadata.entry_points", entry_points)
else:
iter_entry_points = mock.MagicMock(return_value=iter([entry_point]))
patch = mock.patch("pkg_resources.iter_entry_points", iter_entry_points)

with patch:
with self.assertRaises(errors.EntryPointError) as ctx:
opener.open_fs("test://")
self.assertEqual(
Expand All @@ -145,10 +169,19 @@ class NotAnOpener(object):
pass

entry_point = mock.MagicMock()
entry_point.name = "test"
entry_point.load = mock.MagicMock(return_value=NotAnOpener)
iter_entry_points = mock.MagicMock(return_value=iter([entry_point]))

with mock.patch("pkg_resources.iter_entry_points", iter_entry_points):
if sys.version_info >= (3, 8):
if sys.version_info >= (3, 10):
entry_points = mock.MagicMock(return_value=tuple([entry_point]))
else:
entry_points = mock.MagicMock(return_value={"fs.opener": [entry_point]})
patch = mock.patch("importlib.metadata.entry_points", entry_points)
else:
iter_entry_points = mock.MagicMock(return_value=iter([entry_point]))
patch = mock.patch("pkg_resources.iter_entry_points", iter_entry_points)
with patch:
with self.assertRaises(errors.EntryPointError) as ctx:
opener.open_fs("test://")
self.assertEqual("entry point did not return an opener", str(ctx.exception))
Expand All @@ -162,10 +195,20 @@ def open_fs(self, *args, **kwargs):
pass

entry_point = mock.MagicMock()
entry_point.name = "test"
entry_point.load = mock.MagicMock(return_value=BadOpener)
iter_entry_points = mock.MagicMock(return_value=iter([entry_point]))

with mock.patch("pkg_resources.iter_entry_points", iter_entry_points):
if sys.version_info >= (3, 8):
if sys.version_info >= (3, 10):
entry_points = mock.MagicMock(return_value=tuple([entry_point]))
else:
entry_points = mock.MagicMock(return_value={"fs.opener": [entry_point]})
patch = mock.patch("importlib.metadata.entry_points", entry_points)
else:
iter_entry_points = mock.MagicMock(return_value=iter([entry_point]))
patch = mock.patch("pkg_resources.iter_entry_points", iter_entry_points)

with patch:
with self.assertRaises(errors.EntryPointError) as ctx:
opener.open_fs("test://")
self.assertEqual(
Expand Down Expand Up @@ -215,12 +258,6 @@ def setUp(self):
def tearDown(self):
shutil.rmtree(self.tmpdir)

def test_repr(self):
# Check __repr__ works
for entry_point in pkg_resources.iter_entry_points("fs.opener"):
_opener = entry_point.load()
repr(_opener())

def test_open_osfs(self):
fs = opener.open_fs("osfs://.")
self.assertIsInstance(fs, OSFS)
Expand Down