|
6 | 6 | import inspect
|
7 | 7 | import os
|
8 | 8 | from pathlib import Path, PosixPath, PurePosixPath, WindowsPath
|
| 9 | +import sys |
9 | 10 | from textwrap import dedent
|
10 | 11 | from typing import Any, IO, Iterable, Optional, TYPE_CHECKING, Union
|
11 | 12 | from urllib.parse import urlparse
|
@@ -221,36 +222,41 @@ def __fspath__(self):
|
221 | 222 | frame = inspect.currentframe().f_back
|
222 | 223 |
|
223 | 224 | # line number of the call for this frame
|
224 |
| - lineno = inspect.getframeinfo(frame).lineno |
| 225 | + lineno = frame.f_lineno |
225 | 226 |
|
226 | 227 | # get source lines and start of the entire function
|
227 | 228 | lines, start_lineno = inspect.getsourcelines(frame)
|
228 | 229 |
|
229 |
| - # in some contexts, start_lineno is 0, but should be 1-indexed |
| 230 | + # in some contexts like jupyter, start_lineno is 0, but should be 1-indexed |
230 | 231 | if start_lineno == 0:
|
231 | 232 | start_lineno = 1
|
232 | 233 |
|
233 |
| - # walk forward from this call until we find the line |
234 |
| - # that actually has "open" call on it |
235 |
| - if "open" not in lines[lineno - start_lineno]: |
236 |
| - lineno += 1 |
| 234 | + all_lines = "".join(lines) |
237 | 235 |
|
238 |
| - # 1-indexed line within this scope |
239 |
| - line_to_check = (lineno - start_lineno) + 1 |
| 236 | + if "open" in all_lines: |
| 237 | + # walk from this call until we find the line |
| 238 | + # that actually has "open" call on it |
| 239 | + # only needed on Python <= 3.7 |
| 240 | + if (sys.version_info.major, sys.version_info.minor) <= (3, 7): |
| 241 | + while "open" not in lines[lineno - start_lineno]: |
| 242 | + lineno -= 1 |
240 | 243 |
|
241 |
| - # Walk the AST of the previous frame source and see if we |
242 |
| - # ended up here from a call to the builtin open with and a writeable mode |
243 |
| - if any( |
244 |
| - _is_open_call_write_with_var(n, line_to_check) |
245 |
| - for n in ast.walk(ast.parse(dedent("".join(lines)))) |
246 |
| - ): |
247 |
| - raise BuiltInOpenWriteError( |
248 |
| - "Cannot use built-in open function with a CloudPath in a writeable mode. " |
249 |
| - "Changes would not be uploaded to the cloud; instead, " |
250 |
| - "please use the .open() method instead. " |
251 |
| - "NOTE: If you are sure and want to skip this check with " |
252 |
| - "set the env var CLOUDPATHLIB_CHECK_UNSAFE_OPEN=False" |
253 |
| - ) |
| 244 | + # 1-indexed line within this scope |
| 245 | + line_to_check = (lineno - start_lineno) + 1 |
| 246 | + |
| 247 | + # Walk the AST of the previous frame source and see if we |
| 248 | + # ended up here from a call to the builtin open with and a writeable mode |
| 249 | + if any( |
| 250 | + _is_open_call_write_with_var(n, line_to_check) |
| 251 | + for n in ast.walk(ast.parse(dedent(all_lines))) |
| 252 | + ): |
| 253 | + raise BuiltInOpenWriteError( |
| 254 | + "Cannot use built-in open function with a CloudPath in a writeable mode. " |
| 255 | + "Changes would not be uploaded to the cloud; instead, " |
| 256 | + "please use the .open() method instead. " |
| 257 | + "NOTE: If you are sure and want to skip this check with " |
| 258 | + "set the env var CLOUDPATHLIB_CHECK_UNSAFE_OPEN=False" |
| 259 | + ) |
254 | 260 |
|
255 | 261 | if self.is_file():
|
256 | 262 | self._refresh_cache(force_overwrite_from_cloud=False)
|
|
0 commit comments