Skip to content

Commit b48e2ed

Browse files
committed
Merge branch 'master' into fix-484
2 parents c8c83d1 + 50b1c99 commit b48e2ed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+786
-529
lines changed

.github/workflows/package.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,17 @@ jobs:
129129
user: __token__
130130
password: ${{ secrets.PYPI_API_TOKEN }}
131131
skip_existing: false
132+
133+
release:
134+
environment: GitHub Releases
135+
runs-on: ubuntu-latest
136+
if: "startsWith(github.ref, 'refs/tags/v')"
137+
name: Release
138+
needs: upload
139+
steps:
140+
- name: Checkout code
141+
uses: actions/checkout@v1
142+
- name: Release a Changelog
143+
uses: rasmus-saks/[email protected]
144+
with:
145+
github-token: '${{ secrets.GITHUB_TOKEN }}'

.github/workflows/test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ jobs:
88
test:
99
runs-on: ubuntu-latest
1010
strategy:
11+
fail-fast: false
1112
matrix:
1213
python-version:
1314
- 2.7

CHANGELOG.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,33 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
88

99
## Unreleased
1010

11+
12+
## [2.4.16] - 2022-05-02
13+
14+
### Changed
15+
16+
- Make `fs.zipfs._ZipExtFile` use the seeking mechanism implemented
17+
in the Python standard library in Python version 3.7 and later
18+
([#527](https://github.com/PyFilesystem/pyfilesystem2/pull/527)).
19+
- Mark `fs.zipfs.ReadZipFS` as a case-sensitive filesystem
20+
([#527](https://github.com/PyFilesystem/pyfilesystem2/pull/527)).
21+
- Optimized moving files between filesystems with syspaths.
22+
([#523](https://github.com/PyFilesystem/pyfilesystem2/pull/523)).
23+
- Fixed `fs.move.move_file` to clean up the copy on the destination in case of errors.
24+
- `fs.opener.manage_fs` with `writeable=True` will now raise a `ResourceReadOnly`
25+
exception if the managed filesystem is not writeable.
26+
- Marked filesystems wrapped with `fs.wrap.WrapReadOnly` as read-only.
27+
28+
29+
## [2.4.15] - 2022-02-07
30+
1131
### Changed
1232

1333
- Support more lenient usernames and group names in FTP servers
1434
([#507](https://github.com/PyFilesystem/pyfilesystem2/pull/507)).
1535
Closes [#506](https://github.com/PyFilesystem/pyfilesystem2/issues/506).
36+
- Removed dependency on pytz ([#518](https://github.com/PyFilesystem/pyfilesystem2/pull/518)).
37+
Closes [#516](https://github.com/PyFilesystem/pyfilesystem2/issues/518).
1638

1739
### Fixed
1840

@@ -21,6 +43,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2143
resources, causing `MemoryFS.scandir` to use the old name.
2244
([#510](https://github.com/PyFilesystem/pyfilesystem2/pull/510)).
2345
Closes [#509](https://github.com/PyFilesystem/pyfilesystem2/issues/509).
46+
- Make `WrapFS.move` and `WrapFS.movedir` use the delegate FS methods instead
47+
of `fs.move` functions, which was causing optimized implementation of
48+
`movedir` to be always skipped.
49+
([#511](https://github.com/PyFilesystem/pyfilesystem2/pull/511)).
2450

2551

2652
## [2.4.14] - 2021-11-16

CONTRIBUTORS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Many thanks to the following developers for contributing to this project:
1414
- [Diego Argueta](https://github.com/dargueta)
1515
- [Eelke van den Bos](https://github.com/eelkevdbos)
1616
- [Egor Namakonov](https://github.com/fresheed)
17+
- [Felix Yan](https://github.com/felixonmars)
1718
- [@FooBarQuaxx](https://github.com/FooBarQuaxx)
1819
- [Geoff Jukes](https://github.com/geoffjukes)
1920
- [George Macon](https://github.com/gmacon)
@@ -27,6 +28,7 @@ Many thanks to the following developers for contributing to this project:
2728
- [Martin Durant](https://github.com/martindurant)
2829
- [Martin Larralde](https://github.com/althonos)
2930
- [Masaya Nakamura](https://github.com/mashabow)
31+
- [Matthew Gamble](https://github.com/djmattyg007)
3032
- [Morten Engelhardt Olsen](https://github.com/xoriath)
3133
- [@mrg0029](https://github.com/mrg0029)
3234
- [Nathan Goldbaum](https://github.com/ngoldbaum)
@@ -38,6 +40,7 @@ Many thanks to the following developers for contributing to this project:
3840
- [Silvan Spross](https://github.com/sspross)
3941
- [@sqwishy](https://github.com/sqwishy)
4042
- [Sven Schliesing](https://github.com/muffl0n)
43+
- [Thomas Feldmann](https://github.com/tfeldmann)
4144
- [Tim Gates](https://github.com/timgates42/)
4245
- [@tkossak](https://github.com/tkossak)
4346
- [Todd Levi](https://github.com/televi)

docs/source/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@
1313
# serve to show the default.
1414

1515
import sys
16-
import os
17-
1816

17+
import os
1918
import sphinx_rtd_theme
2019

2120
html_theme = "sphinx_rtd_theme"
@@ -72,6 +71,7 @@
7271
# built documents.
7372
#
7473
from fs import __version__
74+
7575
# The short X.Y version.
7676
version = '.'.join(__version__.split('.')[:2])
7777
# The full version, including alpha/beta/rc tags.

docs/source/interface.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ The following is a complete list of methods on PyFilesystem objects.
2020
* :meth:`~fs.base.FS.getdetails` Get details info namespace for a resource.
2121
* :meth:`~fs.base.FS.getinfo` Get info regarding a file or directory.
2222
* :meth:`~fs.base.FS.getmeta` Get meta information for a resource.
23-
* :meth:`~fs.base.FS.getmodified` Get info regarding the last modified time of a resource.
23+
* :meth:`~fs.base.FS.getmodified` Get the last modified time of a resource.
2424
* :meth:`~fs.base.FS.getospath` Get path with encoding expected by the OS.
2525
* :meth:`~fs.base.FS.getsize` Get the size of a file.
2626
* :meth:`~fs.base.FS.getsyspath` Get the system path of a resource, if one exists.

examples/count_py.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from fs import open_fs
1212
from fs.filesize import traditional
1313

14-
1514
fs_url = sys.argv[1]
1615
count = 0
1716

examples/find_dups.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
88
"""
99

10-
from collections import defaultdict
1110
import sys
1211

13-
from fs import open_fs
12+
from collections import defaultdict
1413

14+
from fs import open_fs
1515

1616
hashes = defaultdict(list)
1717
with open_fs(sys.argv[1]) as fs:

examples/rm_pyc.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
from fs import open_fs
1313

14-
1514
with open_fs(sys.argv[1]) as fs:
1615
count = fs.glob("**/*.pyc").remove()
1716
print(f"{count} .pyc files remove")

examples/upload.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
1313
"""
1414

15-
import os
1615
import sys
1716

17+
import os
18+
1819
from fs import open_fs
1920

2021
_, file_path, fs_url = sys.argv

fs/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33

44
__import__("pkg_resources").declare_namespace(__name__) # type: ignore
55

6+
from . import path
7+
from ._fscompat import fsdecode, fsencode
68
from ._version import __version__
79
from .enums import ResourceType, Seek
810
from .opener import open_fs
9-
from ._fscompat import fsencode, fsdecode
10-
from . import path
1111

1212
__all__ = ["__version__", "ResourceType", "Seek", "open_fs"]

fs/_bulk.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,21 @@
66

77
from __future__ import unicode_literals
88

9-
import threading
109
import typing
1110

11+
import threading
1212
from six.moves.queue import Queue
1313

1414
from .copy import copy_file_internal, copy_modified_time
1515
from .errors import BulkCopyFailed
1616
from .tools import copy_file_data
1717

1818
if typing.TYPE_CHECKING:
19-
from .base import FS
19+
from typing import IO, List, Optional, Text, Tuple, Type
20+
2021
from types import TracebackType
21-
from typing import List, Optional, Text, Type, IO, Tuple
22+
23+
from .base import FS
2224

2325

2426
class _Worker(threading.Thread):

fs/_fscompat.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import six
22

33
try:
4-
from os import fsencode, fsdecode
4+
from os import fsdecode, fsencode
55
except ImportError:
6-
from backports.os import fsencode, fsdecode # type: ignore
6+
from backports.os import fsdecode, fsencode # type: ignore
77

88
try:
99
from os import fspath

fs/_ftp_parse.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
from __future__ import absolute_import
2-
from __future__ import print_function
3-
from __future__ import unicode_literals
1+
from __future__ import absolute_import, print_function, unicode_literals
42

5-
import unicodedata
6-
import datetime
73
import re
84
import time
5+
import unicodedata
6+
from datetime import datetime
97

10-
from pytz import UTC
8+
try:
9+
from datetime import timezone
10+
except ImportError:
11+
from ._tzcompat import timezone # type: ignore
1112

1213
from .enums import ResourceType
1314
from .permissions import Permissions
1415

15-
16-
EPOCH_DT = datetime.datetime.fromtimestamp(0, UTC)
16+
EPOCH_DT = datetime.fromtimestamp(0, timezone.utc)
1717

1818

1919
RE_LINUX = re.compile(
@@ -98,7 +98,7 @@ def _parse_time(t, formats):
9898
day = _t.tm_mday
9999
hour = _t.tm_hour
100100
minutes = _t.tm_min
101-
dt = datetime.datetime(year, month, day, hour, minutes, tzinfo=UTC)
101+
dt = datetime(year, month, day, hour, minutes, tzinfo=timezone.utc)
102102

103103
epoch_time = (dt - EPOCH_DT).total_seconds()
104104
return epoch_time

fs/_pathcompat.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# mypy: ignore-errors
2+
try:
3+
from os.path import commonpath
4+
except ImportError:
5+
# Return the longest common sub-path of the sequence of paths given as input.
6+
# The paths are not normalized before comparing them (this is the
7+
# responsibility of the caller). Any trailing separator is stripped from the
8+
# returned path.
9+
10+
def commonpath(paths):
11+
"""Given a sequence of path names, returns the longest common sub-path."""
12+
13+
if not paths:
14+
raise ValueError("commonpath() arg is an empty sequence")
15+
16+
paths = tuple(paths)
17+
if isinstance(paths[0], bytes):
18+
sep = b"/"
19+
curdir = b"."
20+
else:
21+
sep = "/"
22+
curdir = "."
23+
24+
split_paths = [path.split(sep) for path in paths]
25+
26+
try:
27+
(isabs,) = set(p[:1] == sep for p in paths)
28+
except ValueError:
29+
raise ValueError("Can't mix absolute and relative paths")
30+
31+
split_paths = [[c for c in s if c and c != curdir] for s in split_paths]
32+
s1 = min(split_paths)
33+
s2 = max(split_paths)
34+
common = s1
35+
for i, c in enumerate(s1):
36+
if c != s2[i]:
37+
common = s1[:i]
38+
break
39+
40+
prefix = sep if isabs else sep[:0]
41+
return prefix + sep.join(common)

fs/_typing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
44
"""
55
import sys
6-
import six
76

7+
import six
88

99
_PY = sys.version_info
1010

fs/_tzcompat.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Compatibility shim for python2's lack of datetime.timezone.
2+
3+
This is the example code from the Python 2 documentation:
4+
https://docs.python.org/2.7/library/datetime.html#tzinfo-objects
5+
"""
6+
7+
from datetime import timedelta, tzinfo
8+
9+
ZERO = timedelta(0)
10+
11+
12+
class UTC(tzinfo):
13+
"""UTC"""
14+
15+
def utcoffset(self, dt):
16+
return ZERO
17+
18+
def tzname(self, dt):
19+
return "UTC"
20+
21+
def dst(self, dt):
22+
return ZERO
23+
24+
25+
utc = UTC()
26+
27+
28+
class timezone:
29+
utc = utc

fs/_url_tools.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import typing
2+
3+
import platform
14
import re
25
import six
3-
import platform
4-
import typing
56

67
if typing.TYPE_CHECKING:
78
from typing import Text

fs/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Version, used in module and setup.py.
22
"""
3-
__version__ = "2.4.14"
3+
__version__ = "2.4.16"

fs/appfs.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99

1010
# see http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx
1111

12-
import abc
1312
import typing
1413

14+
import abc
1515
import six
16+
from appdirs import AppDirs
1617

17-
from .osfs import OSFS
1818
from ._repr import make_repr
19-
from appdirs import AppDirs
19+
from .osfs import OSFS
2020

2121
if typing.TYPE_CHECKING:
2222
from typing import Optional, Text

0 commit comments

Comments
 (0)