Gentoo Archives: gentoo-commits

From: "Michał Górny" <mgorny@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/gentoo:master commit in: dev-python/pyfakefs/files/, dev-python/pyfakefs/
Date: Wed, 02 Jun 2021 16:12:48
Message-Id: 1622650357.e9107ff787011fc48d4d8a48499242f4d4f7c889.mgorny@gentoo
1 commit: e9107ff787011fc48d4d8a48499242f4d4f7c889
2 Author: Michał Górny <mgorny <AT> gentoo <DOT> org>
3 AuthorDate: Wed Jun 2 15:23:48 2021 +0000
4 Commit: Michał Górny <mgorny <AT> gentoo <DOT> org>
5 CommitDate: Wed Jun 2 16:12:37 2021 +0000
6 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=e9107ff7
7
8 dev-python/pyfakefs: Enable py3.10
9
10 Signed-off-by: Michał Górny <mgorny <AT> gentoo.org>
11
12 .../pyfakefs/files/pyfakefs-4.4.0-py310.patch | 265 +++++++++++++++++++++
13 dev-python/pyfakefs/pyfakefs-4.4.0.ebuild | 6 +-
14 2 files changed, 270 insertions(+), 1 deletion(-)
15
16 diff --git a/dev-python/pyfakefs/files/pyfakefs-4.4.0-py310.patch b/dev-python/pyfakefs/files/pyfakefs-4.4.0-py310.patch
17 new file mode 100644
18 index 00000000000..6ef35df7d1f
19 --- /dev/null
20 +++ b/dev-python/pyfakefs/files/pyfakefs-4.4.0-py310.patch
21 @@ -0,0 +1,265 @@
22 +From a8a70bb7746ba24aa60c9915311e1ff5b402146c Mon Sep 17 00:00:00 2001
23 +From: Carl Montanari <8515611+carlmontanari@××××××××××××××××××××.com>
24 +Date: Thu, 13 May 2021 22:44:45 -0700
25 +Subject: [PATCH] Add support for Python 3.10 beta1 (#594)
26 +
27 +- add Python 3.10-beta1 to CI
28 +- adapt fake pathlib, fix pathlib.Path methods link_to, getcwd, lchmod
29 +- handle dummy encoding "locale" introduced in Python 3.10
30 +- do not test extra dependencies with Python 3.10 (some are not available)
31 +---
32 + pyfakefs/fake_filesystem.py | 15 ++++---
33 + pyfakefs/fake_pathlib.py | 64 ++++++++++++++++++++++-------
34 + pyfakefs/helpers.py | 9 ++++
35 + pyfakefs/tests/fake_pathlib_test.py | 27 +++++++++---
36 + 6 files changed, 109 insertions(+), 32 deletions(-)
37 +
38 +diff --git a/pyfakefs/fake_filesystem.py b/pyfakefs/fake_filesystem.py
39 +index 1e9bfc8..971dc93 100644
40 +--- a/pyfakefs/fake_filesystem.py
41 ++++ b/pyfakefs/fake_filesystem.py
42 +@@ -114,7 +114,7 @@ from pyfakefs.fake_scandir import scandir, walk
43 + from pyfakefs.helpers import (
44 + FakeStatResult, BinaryBufferIO, TextBufferIO,
45 + is_int_type, is_byte_string, is_unicode_string,
46 +- make_string_path, IS_WIN, to_string, matching_string
47 ++ make_string_path, IS_WIN, to_string, matching_string, real_encoding
48 + )
49 + from pyfakefs import __version__ # noqa: F401 for upwards compatibility
50 +
51 +@@ -293,7 +293,7 @@ class FakeFile:
52 + if st_mode >> 12 == 0:
53 + st_mode |= S_IFREG
54 + self.stat_result.st_mode = st_mode
55 +- self.encoding = encoding
56 ++ self.encoding = real_encoding(encoding)
57 + self.errors = errors or 'strict'
58 + self._byte_contents = self._encode_contents(contents)
59 + self.stat_result.st_size = (
60 +@@ -430,7 +430,7 @@ class FakeFile:
61 + OSError: if `st_size` is not a non-negative integer,
62 + or if it exceeds the available file system space.
63 + """
64 +- self.encoding = encoding
65 ++ self.encoding = real_encoding(encoding)
66 + changed = self._set_initial_contents(contents)
67 + if self._side_effect is not None:
68 + self._side_effect(self)
69 +@@ -1177,9 +1177,12 @@ class FakeFilesystem:
70 + OSError: if the filesystem object doesn't exist.
71 + """
72 + # stat should return the tuple representing return value of os.stat
73 +- file_object = self.resolve(
74 +- entry_path, follow_symlinks,
75 +- allow_fd=True, check_read_perm=False)
76 ++ try:
77 ++ file_object = self.resolve(
78 ++ entry_path, follow_symlinks,
79 ++ allow_fd=True, check_read_perm=False)
80 ++ except TypeError:
81 ++ file_object = self.resolve(entry_path)
82 + if not is_root():
83 + # make sure stat raises if a parent dir is not readable
84 + parent_dir = file_object.parent_dir
85 +diff --git a/pyfakefs/fake_pathlib.py b/pyfakefs/fake_pathlib.py
86 +index b43b178..09933fa 100644
87 +--- a/pyfakefs/fake_pathlib.py
88 ++++ b/pyfakefs/fake_pathlib.py
89 +@@ -53,8 +53,8 @@ def init_module(filesystem):
90 +
91 + def _wrap_strfunc(strfunc):
92 + @functools.wraps(strfunc)
93 +- def _wrapped(pathobj, *args):
94 +- return strfunc(pathobj.filesystem, str(pathobj), *args)
95 ++ def _wrapped(pathobj, *args, **kwargs):
96 ++ return strfunc(pathobj.filesystem, str(pathobj), *args, **kwargs)
97 +
98 + return staticmethod(_wrapped)
99 +
100 +@@ -94,19 +94,24 @@ class _FakeAccessor(accessor):
101 +
102 + listdir = _wrap_strfunc(FakeFilesystem.listdir)
103 +
104 +- chmod = _wrap_strfunc(FakeFilesystem.chmod)
105 +-
106 + if use_scandir:
107 + scandir = _wrap_strfunc(fake_scandir.scandir)
108 +
109 + if hasattr(os, "lchmod"):
110 + lchmod = _wrap_strfunc(lambda fs, path, mode: FakeFilesystem.chmod(
111 + fs, path, mode, follow_symlinks=False))
112 ++ chmod = _wrap_strfunc(FakeFilesystem.chmod)
113 + else:
114 +- def lchmod(self, pathobj, mode):
115 ++ def lchmod(self, pathobj, *args, **kwargs):
116 + """Raises not implemented for Windows systems."""
117 + raise NotImplementedError("lchmod() not available on this system")
118 +
119 ++ def chmod(self, pathobj, *args, **kwargs):
120 ++ if "follow_symlinks" in kwargs and not kwargs["follow_symlinks"]:
121 ++ raise NotImplementedError(
122 ++ "lchmod() not available on this system")
123 ++ return pathobj.filesystem.chmod(str(pathobj), *args, **kwargs)
124 ++
125 + mkdir = _wrap_strfunc(FakeFilesystem.makedir)
126 +
127 + unlink = _wrap_strfunc(FakeFilesystem.remove)
128 +@@ -124,13 +129,21 @@ class _FakeAccessor(accessor):
129 + FakeFilesystem.create_symlink(fs, file_path, link_target,
130 + create_missing_dirs=False))
131 +
132 +- if sys.version_info >= (3, 8):
133 ++ if (3, 8) <= sys.version_info < (3, 10):
134 + link_to = _wrap_binary_strfunc(
135 + lambda fs, file_path, link_target:
136 + FakeFilesystem.link(fs, file_path, link_target))
137 +
138 +- if sys.version_info >= (3, 9):
139 +- readlink = _wrap_strfunc(FakeFilesystem.readlink)
140 ++ if sys.version_info >= (3, 10):
141 ++ link = _wrap_binary_strfunc(
142 ++ lambda fs, file_path, link_target:
143 ++ FakeFilesystem.link(fs, file_path, link_target))
144 ++
145 ++ # this will use the fake filesystem because os is patched
146 ++ def getcwd(self):
147 ++ return os.getcwd()
148 ++
149 ++ readlink = _wrap_strfunc(FakeFilesystem.readlink)
150 +
151 + utime = _wrap_strfunc(FakeFilesystem.utime)
152 +
153 +@@ -461,19 +474,42 @@ class FakePath(pathlib.Path):
154 + cls = (FakePathlibModule.WindowsPath
155 + if cls.filesystem.is_windows_fs
156 + else FakePathlibModule.PosixPath)
157 +- self = cls._from_parts(args, init=True)
158 ++ self = cls._from_parts(args)
159 + return self
160 +
161 +- def _path(self):
162 +- """Returns the underlying path string as used by the fake filesystem.
163 +- """
164 +- return str(self)
165 ++ @classmethod
166 ++ def _from_parts(cls, args, init=False): # pylint: disable=unused-argument
167 ++ # Overwritten to call _init to set the fake accessor,
168 ++ # which is not done since Python 3.10
169 ++ self = object.__new__(cls)
170 ++ self._init()
171 ++ drv, root, parts = self._parse_args(args)
172 ++ self._drv = drv
173 ++ self._root = root
174 ++ self._parts = parts
175 ++ return self
176 ++
177 ++ @classmethod
178 ++ def _from_parsed_parts(cls, drv, root, parts):
179 ++ # Overwritten to call _init to set the fake accessor,
180 ++ # which is not done since Python 3.10
181 ++ self = object.__new__(cls)
182 ++ self._init()
183 ++ self._drv = drv
184 ++ self._root = root
185 ++ self._parts = parts
186 ++ return self
187 +
188 + def _init(self, template=None):
189 + """Initializer called from base class."""
190 + self._accessor = _fake_accessor
191 + self._closed = False
192 +
193 ++ def _path(self):
194 ++ """Returns the underlying path string as used by the fake filesystem.
195 ++ """
196 ++ return str(self)
197 ++
198 + @classmethod
199 + def cwd(cls):
200 + """Return a new path pointing to the current working directory
201 +@@ -722,7 +758,7 @@ class RealPath(pathlib.Path):
202 + if cls is RealPathlibModule.Path:
203 + cls = (RealPathlibModule.WindowsPath if os.name == 'nt'
204 + else RealPathlibModule.PosixPath)
205 +- self = cls._from_parts(args, init=True)
206 ++ self = cls._from_parts(args)
207 + return self
208 +
209 +
210 +diff --git a/pyfakefs/helpers.py b/pyfakefs/helpers.py
211 +index aa3959d..08962fc 100644
212 +--- a/pyfakefs/helpers.py
213 ++++ b/pyfakefs/helpers.py
214 +@@ -57,6 +57,15 @@ def to_string(path):
215 + return path
216 +
217 +
218 ++def real_encoding(encoding):
219 ++ """Since Python 3.10, the new function ``io.text_encoding`` returns
220 ++ "locale" as the encoding if None is defined. This will be handled
221 ++ as no encoding in pyfakefs."""
222 ++ if sys.version_info >= (3, 10):
223 ++ return encoding if encoding != "locale" else None
224 ++ return encoding
225 ++
226 ++
227 + def matching_string(matched, string):
228 + """Return the string as byte or unicode depending
229 + on the type of matched, assuming string is an ASCII string.
230 +diff --git a/pyfakefs/tests/fake_pathlib_test.py b/pyfakefs/tests/fake_pathlib_test.py
231 +index 5dcc57f..efea509 100644
232 +--- a/pyfakefs/tests/fake_pathlib_test.py
233 ++++ b/pyfakefs/tests/fake_pathlib_test.py
234 +@@ -378,10 +378,11 @@ class FakePathlibFileObjectPropertyTest(RealPathlibTestCase):
235 + # we get stat.S_IFLNK | 0o755 under MacOs
236 + self.assertEqual(link_stat.st_mode, stat.S_IFLNK | 0o777)
237 +
238 +- @unittest.skipIf(sys.platform == 'darwin',
239 +- 'Different behavior under MacOs')
240 + def test_lchmod(self):
241 + self.skip_if_symlink_not_supported()
242 ++ if (sys.version_info >= (3, 10) and self.use_real_fs() and
243 ++ 'chmod' not in os.supports_follow_symlinks):
244 ++ raise unittest.SkipTest('follow_symlinks not available for chmod')
245 + file_stat = self.os.stat(self.file_path)
246 + link_stat = self.os.lstat(self.file_link_path)
247 + if not hasattr(os, "lchmod"):
248 +@@ -390,8 +391,9 @@ class FakePathlibFileObjectPropertyTest(RealPathlibTestCase):
249 + else:
250 + self.path(self.file_link_path).lchmod(0o444)
251 + self.assertEqual(file_stat.st_mode, stat.S_IFREG | 0o666)
252 +- # we get stat.S_IFLNK | 0o755 under MacOs
253 +- self.assertEqual(link_stat.st_mode, stat.S_IFLNK | 0o444)
254 ++ # the exact mode depends on OS and Python version
255 ++ self.assertEqual(link_stat.st_mode & 0o777700,
256 ++ stat.S_IFLNK | 0o700)
257 +
258 + def test_resolve(self):
259 + self.create_dir(self.make_path('antoine', 'docs'))
260 +@@ -968,7 +970,22 @@ class FakePathlibUsageInOsFunctionsTest(RealPathlibTestCase):
261 + def test_stat(self):
262 + path = self.make_path('foo', 'bar', 'baz')
263 + self.create_file(path, contents='1234567')
264 +- self.assertEqual(self.os.stat(path), self.os.stat(self.path(path)))
265 ++ self.assertEqual(self.os.stat(path), self.path(path).stat())
266 ++
267 ++ @unittest.skipIf(sys.version_info < (3, 10), "New in Python 3.10")
268 ++ def test_stat_follow_symlinks(self):
269 ++ self.check_posix_only()
270 ++ directory = self.make_path('foo')
271 ++ base_name = 'bar'
272 ++ file_path = self.path(self.os.path.join(directory, base_name))
273 ++ link_path = self.path(self.os.path.join(directory, 'link'))
274 ++ contents = "contents"
275 ++ self.create_file(file_path, contents=contents)
276 ++ self.create_symlink(link_path, base_name)
277 ++ self.assertEqual(len(contents),
278 ++ link_path.stat(follow_symlinks=True)[stat.ST_SIZE])
279 ++ self.assertEqual(len(base_name),
280 ++ link_path.stat(follow_symlinks=False)[stat.ST_SIZE])
281 +
282 + def test_utime(self):
283 + path = self.make_path('some_file')
284 +--
285 +2.31.1
286 +
287
288 diff --git a/dev-python/pyfakefs/pyfakefs-4.4.0.ebuild b/dev-python/pyfakefs/pyfakefs-4.4.0.ebuild
289 index e7a85e83b59..5e06b22143d 100644
290 --- a/dev-python/pyfakefs/pyfakefs-4.4.0.ebuild
291 +++ b/dev-python/pyfakefs/pyfakefs-4.4.0.ebuild
292 @@ -3,7 +3,7 @@
293
294 EAPI=7
295
296 -PYTHON_COMPAT=( python3_{7..9} pypy3 )
297 +PYTHON_COMPAT=( python3_{7..10} pypy3 )
298 DISTUTILS_IN_SOURCE_BUILD=1
299
300 inherit distutils-r1
301 @@ -18,6 +18,10 @@ KEYWORDS="~alpha amd64 arm arm64 hppa ~ia64 ~mips ppc ppc64 ~riscv ~s390 sparc x
302
303 distutils_enable_tests pytest
304
305 +PATCHES=(
306 + "${FILESDIR}"/${P}-py310.patch
307 +)
308 +
309 python_test() {
310 "${EPYTHON}" -m pyfakefs.tests.all_tests -v || die "tests failed under ${EPYTHON}"
311 }