Uploaded Test files
This commit is contained in:
parent
f584ad9d97
commit
2e81cb7d99
16627 changed files with 2065359 additions and 102444 deletions
458
venv/Lib/site-packages/jupyter_core/paths.py
Normal file
458
venv/Lib/site-packages/jupyter_core/paths.py
Normal file
|
@ -0,0 +1,458 @@
|
|||
# encoding: utf-8
|
||||
"""Path utility functions."""
|
||||
|
||||
# Copyright (c) Jupyter Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
# Derived from IPython.utils.path, which is
|
||||
# Copyright (c) IPython Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import stat
|
||||
import errno
|
||||
import tempfile
|
||||
import warnings
|
||||
from ipython_genutils import py3compat
|
||||
|
||||
from contextlib import contextmanager
|
||||
from distutils.util import strtobool
|
||||
from ipython_genutils import py3compat
|
||||
|
||||
pjoin = os.path.join
|
||||
|
||||
# UF_HIDDEN is a stat flag not defined in the stat module.
|
||||
# It is used by BSD to indicate hidden files.
|
||||
UF_HIDDEN = getattr(stat, 'UF_HIDDEN', 32768)
|
||||
|
||||
|
||||
def get_home_dir():
|
||||
"""Get the real path of the home directory"""
|
||||
homedir = os.path.expanduser('~')
|
||||
# Next line will make things work even when /home/ is a symlink to
|
||||
# /usr/home as it is on FreeBSD, for example
|
||||
homedir = os.path.realpath(homedir)
|
||||
homedir = py3compat.str_to_unicode(homedir, encoding=sys.getfilesystemencoding())
|
||||
return homedir
|
||||
|
||||
_dtemps = {}
|
||||
def _mkdtemp_once(name):
|
||||
"""Make or reuse a temporary directory.
|
||||
|
||||
If this is called with the same name in the same process, it will return
|
||||
the same directory.
|
||||
"""
|
||||
try:
|
||||
return _dtemps[name]
|
||||
except KeyError:
|
||||
d = _dtemps[name] = tempfile.mkdtemp(prefix=name + '-')
|
||||
return d
|
||||
|
||||
def jupyter_config_dir():
|
||||
"""Get the Jupyter config directory for this platform and user.
|
||||
|
||||
Returns JUPYTER_CONFIG_DIR if defined, else ~/.jupyter
|
||||
"""
|
||||
|
||||
env = os.environ
|
||||
home_dir = get_home_dir()
|
||||
|
||||
if env.get('JUPYTER_NO_CONFIG'):
|
||||
return _mkdtemp_once('jupyter-clean-cfg')
|
||||
|
||||
if env.get('JUPYTER_CONFIG_DIR'):
|
||||
return env['JUPYTER_CONFIG_DIR']
|
||||
|
||||
return pjoin(home_dir, '.jupyter')
|
||||
|
||||
|
||||
def jupyter_data_dir():
|
||||
"""Get the config directory for Jupyter data files.
|
||||
|
||||
These are non-transient, non-configuration files.
|
||||
|
||||
Returns JUPYTER_DATA_DIR if defined, else a platform-appropriate path.
|
||||
"""
|
||||
env = os.environ
|
||||
|
||||
if env.get('JUPYTER_DATA_DIR'):
|
||||
return env['JUPYTER_DATA_DIR']
|
||||
|
||||
home = get_home_dir()
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
return os.path.join(home, 'Library', 'Jupyter')
|
||||
elif os.name == 'nt':
|
||||
appdata = os.environ.get('APPDATA', None)
|
||||
if appdata:
|
||||
return pjoin(appdata, 'jupyter')
|
||||
else:
|
||||
return pjoin(jupyter_config_dir(), 'data')
|
||||
else:
|
||||
# Linux, non-OS X Unix, AIX, etc.
|
||||
xdg = env.get("XDG_DATA_HOME", None)
|
||||
if not xdg:
|
||||
xdg = pjoin(home, '.local', 'share')
|
||||
return pjoin(xdg, 'jupyter')
|
||||
|
||||
|
||||
def jupyter_runtime_dir():
|
||||
"""Return the runtime dir for transient jupyter files.
|
||||
|
||||
Returns JUPYTER_RUNTIME_DIR if defined.
|
||||
|
||||
The default is now (data_dir)/runtime on all platforms;
|
||||
we no longer use XDG_RUNTIME_DIR after various problems.
|
||||
"""
|
||||
env = os.environ
|
||||
|
||||
if env.get('JUPYTER_RUNTIME_DIR'):
|
||||
return env['JUPYTER_RUNTIME_DIR']
|
||||
|
||||
return pjoin(jupyter_data_dir(), 'runtime')
|
||||
|
||||
|
||||
if os.name == 'nt':
|
||||
programdata = os.environ.get('PROGRAMDATA', None)
|
||||
if programdata:
|
||||
SYSTEM_JUPYTER_PATH = [pjoin(programdata, 'jupyter')]
|
||||
else: # PROGRAMDATA is not defined by default on XP.
|
||||
SYSTEM_JUPYTER_PATH = [os.path.join(sys.prefix, 'share', 'jupyter')]
|
||||
else:
|
||||
SYSTEM_JUPYTER_PATH = [
|
||||
"/usr/local/share/jupyter",
|
||||
"/usr/share/jupyter",
|
||||
]
|
||||
|
||||
ENV_JUPYTER_PATH = [os.path.join(sys.prefix, 'share', 'jupyter')]
|
||||
|
||||
|
||||
def jupyter_path(*subdirs):
|
||||
"""Return a list of directories to search for data files
|
||||
|
||||
JUPYTER_PATH environment variable has highest priority.
|
||||
|
||||
If ``*subdirs`` are given, that subdirectory will be added to each element.
|
||||
|
||||
Examples:
|
||||
|
||||
>>> jupyter_path()
|
||||
['~/.local/jupyter', '/usr/local/share/jupyter']
|
||||
>>> jupyter_path('kernels')
|
||||
['~/.local/jupyter/kernels', '/usr/local/share/jupyter/kernels']
|
||||
"""
|
||||
|
||||
paths = []
|
||||
# highest priority is env
|
||||
if os.environ.get('JUPYTER_PATH'):
|
||||
paths.extend(
|
||||
p.rstrip(os.sep)
|
||||
for p in os.environ['JUPYTER_PATH'].split(os.pathsep)
|
||||
)
|
||||
# then user dir
|
||||
paths.append(jupyter_data_dir())
|
||||
# then sys.prefix
|
||||
for p in ENV_JUPYTER_PATH:
|
||||
if p not in SYSTEM_JUPYTER_PATH:
|
||||
paths.append(p)
|
||||
# finally, system
|
||||
paths.extend(SYSTEM_JUPYTER_PATH)
|
||||
|
||||
# add subdir, if requested
|
||||
if subdirs:
|
||||
paths = [ pjoin(p, *subdirs) for p in paths ]
|
||||
return paths
|
||||
|
||||
|
||||
if os.name == 'nt':
|
||||
programdata = os.environ.get('PROGRAMDATA', None)
|
||||
if programdata:
|
||||
SYSTEM_CONFIG_PATH = [os.path.join(programdata, 'jupyter')]
|
||||
else: # PROGRAMDATA is not defined by default on XP.
|
||||
SYSTEM_CONFIG_PATH = []
|
||||
else:
|
||||
SYSTEM_CONFIG_PATH = [
|
||||
"/usr/local/etc/jupyter",
|
||||
"/etc/jupyter",
|
||||
]
|
||||
|
||||
ENV_CONFIG_PATH = [os.path.join(sys.prefix, 'etc', 'jupyter')]
|
||||
|
||||
|
||||
def jupyter_config_path():
|
||||
"""Return the search path for Jupyter config files as a list."""
|
||||
paths = [jupyter_config_dir()]
|
||||
if os.environ.get('JUPYTER_NO_CONFIG'):
|
||||
return paths
|
||||
|
||||
# highest priority is env
|
||||
if os.environ.get('JUPYTER_CONFIG_PATH'):
|
||||
paths.extend(
|
||||
p.rstrip(os.sep)
|
||||
for p in os.environ['JUPYTER_CONFIG_PATH'].split(os.pathsep)
|
||||
)
|
||||
|
||||
# then sys.prefix
|
||||
for p in ENV_CONFIG_PATH:
|
||||
if p not in SYSTEM_CONFIG_PATH:
|
||||
paths.append(p)
|
||||
paths.extend(SYSTEM_CONFIG_PATH)
|
||||
return paths
|
||||
|
||||
|
||||
def exists(path):
|
||||
"""Replacement for `os.path.exists` which works for host mapped volumes
|
||||
on Windows containers
|
||||
"""
|
||||
try:
|
||||
os.lstat(path)
|
||||
except OSError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def is_file_hidden_win(abs_path, stat_res=None):
|
||||
"""Is a file hidden?
|
||||
|
||||
This only checks the file itself; it should be called in combination with
|
||||
checking the directory containing the file.
|
||||
|
||||
Use is_hidden() instead to check the file and its parent directories.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
abs_path : unicode
|
||||
The absolute path to check.
|
||||
stat_res : os.stat_result, optional
|
||||
Ignored on Windows, exists for compatibility with POSIX version of the
|
||||
function.
|
||||
"""
|
||||
if os.path.basename(abs_path).startswith('.'):
|
||||
return True
|
||||
|
||||
win32_FILE_ATTRIBUTE_HIDDEN = 0x02
|
||||
import ctypes
|
||||
try:
|
||||
attrs = ctypes.windll.kernel32.GetFileAttributesW(
|
||||
py3compat.cast_unicode(abs_path)
|
||||
)
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
if attrs > 0 and attrs & win32_FILE_ATTRIBUTE_HIDDEN:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def is_file_hidden_posix(abs_path, stat_res=None):
|
||||
"""Is a file hidden?
|
||||
|
||||
This only checks the file itself; it should be called in combination with
|
||||
checking the directory containing the file.
|
||||
|
||||
Use is_hidden() instead to check the file and its parent directories.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
abs_path : unicode
|
||||
The absolute path to check.
|
||||
stat_res : os.stat_result, optional
|
||||
The result of calling stat() on abs_path. If not passed, this function
|
||||
will call stat() internally.
|
||||
"""
|
||||
if os.path.basename(abs_path).startswith('.'):
|
||||
return True
|
||||
|
||||
if stat_res is None or stat.S_ISLNK(stat_res.st_mode):
|
||||
try:
|
||||
stat_res = os.stat(abs_path)
|
||||
except OSError as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
return False
|
||||
raise
|
||||
|
||||
# check that dirs can be listed
|
||||
if stat.S_ISDIR(stat_res.st_mode):
|
||||
# use x-access, not actual listing, in case of slow/large listings
|
||||
if not os.access(abs_path, os.X_OK | os.R_OK):
|
||||
return True
|
||||
|
||||
# check UF_HIDDEN
|
||||
if getattr(stat_res, 'st_flags', 0) & UF_HIDDEN:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
if sys.platform == 'win32':
|
||||
is_file_hidden = is_file_hidden_win
|
||||
else:
|
||||
is_file_hidden = is_file_hidden_posix
|
||||
|
||||
|
||||
def is_hidden(abs_path, abs_root=''):
|
||||
"""Is a file hidden or contained in a hidden directory?
|
||||
|
||||
This will start with the rightmost path element and work backwards to the
|
||||
given root to see if a path is hidden or in a hidden directory. Hidden is
|
||||
determined by either name starting with '.' or the UF_HIDDEN flag as
|
||||
reported by stat.
|
||||
|
||||
If abs_path is the same directory as abs_root, it will be visible even if
|
||||
that is a hidden folder. This only checks the visibility of files
|
||||
and directories *within* abs_root.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
abs_path : unicode
|
||||
The absolute path to check for hidden directories.
|
||||
abs_root : unicode
|
||||
The absolute path of the root directory in which hidden directories
|
||||
should be checked for.
|
||||
"""
|
||||
if os.path.normpath(abs_path) == os.path.normpath(abs_root):
|
||||
return False
|
||||
|
||||
if is_file_hidden(abs_path):
|
||||
return True
|
||||
|
||||
if not abs_root:
|
||||
abs_root = abs_path.split(os.sep, 1)[0] + os.sep
|
||||
inside_root = abs_path[len(abs_root):]
|
||||
if any(part.startswith('.') for part in inside_root.split(os.sep)):
|
||||
return True
|
||||
|
||||
# check UF_HIDDEN on any location up to root.
|
||||
# is_file_hidden() already checked the file, so start from its parent dir
|
||||
path = os.path.dirname(abs_path)
|
||||
while path and path.startswith(abs_root) and path != abs_root:
|
||||
if not exists(path):
|
||||
path = os.path.dirname(path)
|
||||
continue
|
||||
try:
|
||||
# may fail on Windows junctions
|
||||
st = os.lstat(path)
|
||||
except OSError:
|
||||
return True
|
||||
if getattr(st, 'st_flags', 0) & UF_HIDDEN:
|
||||
return True
|
||||
path = os.path.dirname(path)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def win32_restrict_file_to_user(fname):
|
||||
"""Secure a windows file to read-only access for the user.
|
||||
Follows guidance from win32 library creator:
|
||||
http://timgolden.me.uk/python/win32_how_do_i/add-security-to-a-file.html
|
||||
|
||||
This method should be executed against an already generated file which
|
||||
has no secrets written to it yet.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
fname : unicode
|
||||
The path to the file to secure
|
||||
"""
|
||||
import win32api
|
||||
import win32security
|
||||
import ntsecuritycon as con
|
||||
|
||||
# everyone, _domain, _type = win32security.LookupAccountName("", "Everyone")
|
||||
admins = win32security.CreateWellKnownSid(win32security.WinBuiltinAdministratorsSid)
|
||||
user, _domain, _type = win32security.LookupAccountName("", win32api.GetUserNameEx(win32api.NameSamCompatible))
|
||||
|
||||
sd = win32security.GetFileSecurity(fname, win32security.DACL_SECURITY_INFORMATION)
|
||||
|
||||
dacl = win32security.ACL()
|
||||
# dacl.AddAccessAllowedAce(win32security.ACL_REVISION, con.FILE_ALL_ACCESS, everyone)
|
||||
dacl.AddAccessAllowedAce(win32security.ACL_REVISION, con.FILE_GENERIC_READ | con.FILE_GENERIC_WRITE, user)
|
||||
dacl.AddAccessAllowedAce(win32security.ACL_REVISION, con.FILE_ALL_ACCESS, admins)
|
||||
|
||||
sd.SetSecurityDescriptorDacl(1, dacl, 0)
|
||||
win32security.SetFileSecurity(fname, win32security.DACL_SECURITY_INFORMATION, sd)
|
||||
|
||||
|
||||
def get_file_mode(fname):
|
||||
"""Retrieves the file mode corresponding to fname in a filesystem-tolerant manner.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
fname : unicode
|
||||
The path to the file to get mode from
|
||||
|
||||
"""
|
||||
# Some filesystems (e.g., CIFS) auto-enable the execute bit on files. As a result, we
|
||||
# should tolerate the execute bit on the file's owner when validating permissions - thus
|
||||
# the missing least significant bit on the third octal digit. In addition, we also tolerate
|
||||
# the sticky bit being set, so the lsb from the fourth octal digit is also removed.
|
||||
return stat.S_IMODE(os.stat(fname).st_mode) & 0o6677 # Use 4 octal digits since S_IMODE does the same
|
||||
|
||||
|
||||
allow_insecure_writes = strtobool(os.getenv('JUPYTER_ALLOW_INSECURE_WRITES', 'false'))
|
||||
|
||||
|
||||
@contextmanager
|
||||
def secure_write(fname, binary=False):
|
||||
"""Opens a file in the most restricted pattern available for
|
||||
writing content. This limits the file mode to `0o0600` and yields
|
||||
the resulting opened filed handle.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
fname : unicode
|
||||
The path to the file to write
|
||||
|
||||
binary: boolean
|
||||
Indicates that the file is binary
|
||||
"""
|
||||
mode = 'wb' if binary else 'w'
|
||||
open_flag = os.O_CREAT | os.O_WRONLY | os.O_TRUNC
|
||||
try:
|
||||
os.remove(fname)
|
||||
except (IOError, OSError):
|
||||
# Skip any issues with the file not existing
|
||||
pass
|
||||
|
||||
if os.name == 'nt':
|
||||
if allow_insecure_writes:
|
||||
# Mounted file systems can have a number of failure modes inside this block.
|
||||
# For windows machines in insecure mode we simply skip this to avoid failures :/
|
||||
issue_insecure_write_warning()
|
||||
else:
|
||||
# Python on windows does not respect the group and public bits for chmod, so we need
|
||||
# to take additional steps to secure the contents.
|
||||
# Touch file pre-emptively to avoid editing permissions in open files in Windows
|
||||
fd = os.open(fname, open_flag, 0o0600)
|
||||
os.close(fd)
|
||||
open_flag = os.O_WRONLY | os.O_TRUNC
|
||||
win32_restrict_file_to_user(fname)
|
||||
|
||||
with os.fdopen(os.open(fname, open_flag, 0o0600), mode) as f:
|
||||
if os.name != 'nt':
|
||||
# Enforce that the file got the requested permissions before writing
|
||||
file_mode = get_file_mode(fname)
|
||||
if 0o0600 != file_mode:
|
||||
if allow_insecure_writes:
|
||||
issue_insecure_write_warning()
|
||||
else:
|
||||
raise RuntimeError("Permissions assignment failed for secure file: '{file}'."
|
||||
" Got '{permissions}' instead of '0o0600'."
|
||||
.format(file=fname, permissions=oct(file_mode)))
|
||||
yield f
|
||||
|
||||
|
||||
def issue_insecure_write_warning():
|
||||
def format_warning(msg, *args, **kwargs):
|
||||
return str(msg) + '\n'
|
||||
|
||||
warnings.formatwarning = format_warning
|
||||
warnings.warn("WARNING: Insecure writes have been enabled via environment variable "
|
||||
"'JUPYTER_ALLOW_INSECURE_WRITES'! If this is not intended, remove the "
|
||||
"variable or set its value to 'False'.")
|
Loading…
Add table
Add a link
Reference in a new issue