Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-jupyter-core for
openSUSE:Factory checked in at 2021-10-25 15:17:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-jupyter-core (Old)
and /work/SRC/openSUSE:Factory/.python-jupyter-core.new.1890 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-jupyter-core"
Mon Oct 25 15:17:03 2021 rev:7 rq:925907 version:4.8.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-jupyter-core/python-jupyter-core.changes
2021-02-11 12:48:14.093562912 +0100
+++
/work/SRC/openSUSE:Factory/.python-jupyter-core.new.1890/python-jupyter-core.changes
2021-10-25 15:17:35.385681498 +0200
@@ -1,0 +2,20 @@
+Sun Oct 17 17:28:20 UTC 2021 - Ben Greiner <[email protected]>
+
+- Update to version 4.8.1
+ * Print an error message instead of an exception when a command
+ is not found (PR #218)
+ * Return canonical path when using %APPDATA% on Windows (PR #222)
+ * Print full usage on missing or invalid commands (PR #225)
+ * Remove dependency on pywin32 package on PyPy (PR #230)
+ * Update packages listed in jupyter --version (PR #232)
+ * Inherit base aliases/flags from traitlets Application,
+ including --show-config from traitlets 5 (PR #233)
+ * Trigger warning when trying to check hidden file status on PyPy
+ (PR #238)
+
+-------------------------------------------------------------------
+Tue Oct 5 15:35:48 UTC 2021 - Stefan Schubert <[email protected]>
+
+- Use libalternatives instead of update-alternatives.
+
+-------------------------------------------------------------------
Old:
----
jupyter_core-4.7.1.tar.gz
New:
----
jupyter_core-4.8.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-jupyter-core.spec ++++++
--- /var/tmp/diff_new_pack.1CGsPR/_old 2021-10-25 15:17:35.933681841 +0200
+++ /var/tmp/diff_new_pack.1CGsPR/_new 2021-10-25 15:17:35.937681843 +0200
@@ -1,5 +1,5 @@
#
-# spec file for package python-jupyter-core
+# spec file
#
# Copyright (c) 2021 SUSE LLC
#
@@ -16,6 +16,13 @@
#
+#
+%if 0%{?suse_version} > 1500
+%bcond_without libalternatives
+%else
+%bcond_with libalternatives
+%endif
+
%global flavor @BUILD_FLAVOR@%{nil}
%if "%{flavor}" == "test"
%define psuffix -test
@@ -24,11 +31,10 @@
%define psuffix %{nil}
%bcond_with test
%endif
-%bcond_without python2
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%define skip_python2 1
Name: python-jupyter-core%{psuffix}
-Version: 4.7.1
+Version: 4.8.1
Release: 0
Summary: Base package on which Jupyter projects rely
License: BSD-3-Clause
@@ -40,11 +46,16 @@
BuildRequires: %{python_module traitlets}
BuildRequires: fdupes
BuildRequires: jupyter-jupyter_core-filesystem
-BuildRequires: python-rpm-macros
+BuildRequires: python-rpm-macros >= 20210929
Requires: jupyter-jupyter_core-filesystem
Requires: python-traitlets
+%if %{with libalternatives}
+BuildRequires: alts
+Requires: alts
+%else
Requires(post): update-alternatives
-Requires(postun): update-alternatives
+Requires(postun):update-alternatives
+%endif
Recommends: python-ipython
Provides: python-jupyter_core = %{version}-%{release}
Obsoletes: python-jupyter_core < %{version}-%{release}
@@ -57,6 +68,7 @@
BuildArch: noarch
%if %{with test}
BuildRequires: %{python_module jupyter-core}
+BuildRequires: %{python_module pytest-timeout}
BuildRequires: %{python_module pytest}
%endif
%python_subpackages
@@ -101,6 +113,11 @@
popd
%endif
+%pre
+# removing old update-alternatives entries
+# If libalternatives is used: Removing old update-alternatives entries.
+%python_libalternatives_reset_alternative jupyter
+
%post
%python_install_alternative jupyter jupyter-migrate jupyter-troubleshoot
++++++ jupyter_core-4.7.1.tar.gz -> jupyter_core-4.8.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-4.7.1/PKG-INFO
new/jupyter_core-4.8.1/PKG-INFO
--- old/jupyter_core-4.7.1/PKG-INFO 2021-01-31 19:30:07.000000000 +0100
+++ new/jupyter_core-4.8.1/PKG-INFO 2021-09-17 03:21:05.841862400 +0200
@@ -1,13 +1,13 @@
Metadata-Version: 2.1
Name: jupyter_core
-Version: 4.7.1
+Version: 4.8.1
Summary: Jupyter core package. A base package on which Jupyter projects rely.
Home-page: https://jupyter.org
Author: Jupyter Development Team
Author-email: [email protected]
-License: BSD
-Description: There is no reason to install this package on its own.
+License: BSD-3-Clause
Platform: UNKNOWN
+Classifier: Framework :: Jupyter
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Intended Audience :: Science/Research
@@ -16,3 +16,7 @@
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.6
Description-Content-Type: text/plain
+License-File: COPYING.md
+
+There is no reason to install this package on its own.
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-4.7.1/dev-requirements.txt
new/jupyter_core-4.8.1/dev-requirements.txt
--- old/jupyter_core-4.7.1/dev-requirements.txt 2020-11-02 16:52:35.000000000
+0100
+++ new/jupyter_core-4.8.1/dev-requirements.txt 2021-09-17 02:11:12.000000000
+0200
@@ -1,2 +1,4 @@
-pytest
ipykernel
+pytest
+pytest-cov
+pytest-timeout
Binary files old/jupyter_core-4.7.1/docs/.DS_Store and
new/jupyter_core-4.8.1/docs/.DS_Store differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-4.7.1/docs/changelog.rst
new/jupyter_core-4.8.1/docs/changelog.rst
--- old/jupyter_core-4.7.1/docs/changelog.rst 2021-01-31 19:25:32.000000000
+0100
+++ new/jupyter_core-4.8.1/docs/changelog.rst 2021-09-17 02:11:12.000000000
+0200
@@ -1,6 +1,28 @@
Changes in jupyter-core
=======================
+4.8
+---
+
+4.8.0
+~~~~~
+
+`on
+GitHub <https://github.com/jupyter/jupyter_core/releases/tag/4.8.0>`__
+
+See the `jupyter_core
+4.8 <https://github.com/jupyter/jupyter_core/milestone/20?closed=1>`__
+milestone on GitHub for the full list of pull requests and issues closed.
+
+jupyter-core now has experimental support for PyPy (Python 3.7). Some features
are known not to work due to limitations in PyPy, such as hidden file detection
on Windows.
+
+- Print an error message instead of an exception when a command is not found
(:ghpull:`218`)
+- Return canonical path when using ``%APPDATA%`` on Windows (:ghpull:`222`)
+- Print full usage on missing or invalid commands (:ghpull:`225`)
+- Remove dependency on ``pywin32`` package on PyPy (:ghpull:`230`)
+- Update packages listed in ``jupyter --version`` (:ghpull:`232`)
+- Inherit base aliases/flags from traitlets Application, including
``--show-config`` from traitlets 5 (:ghpull:`233`)
+- Trigger warning when trying to check hidden file status on PyPy
(:ghpull:`238`)
4.7
---
@@ -17,7 +39,7 @@
~~~~~
`on
-GitHub <https://github.com/jupyter/jupyter_core/releases/tag/4.7>`__
+GitHub <https://github.com/jupyter/jupyter_core/releases/tag/4.7.0>`__
See the `jupyter_core
4.7 <https://github.com/jupyter/jupyter_core/milestone/19?closed=1>`__
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-4.7.1/jupyter_core/application.py
new/jupyter_core-4.8.1/jupyter_core/application.py
--- old/jupyter_core-4.7.1/jupyter_core/application.py 2020-11-02
16:52:35.000000000 +0100
+++ new/jupyter_core-4.8.1/jupyter_core/application.py 2021-09-17
02:11:12.000000000 +0200
@@ -27,12 +27,21 @@
# aliases and flags
-base_aliases = {
+base_aliases = {}
+if isinstance(Application.aliases, dict):
+ # traitlets 5
+ base_aliases.update(Application.aliases)
+_jupyter_aliases = {
'log-level' : 'Application.log_level',
'config' : 'JupyterApp.config_file',
}
+base_aliases.update(_jupyter_aliases)
-base_flags = {
+base_flags = {}
+if isinstance(Application.flags, dict):
+ # traitlets 5
+ base_flags.update(Application.flags)
+_jupyter_flags = {
'debug': ({'Application' : {'log_level' : logging.DEBUG}},
"set log level to logging.DEBUG (maximize logging output)"),
'generate-config': ({'JupyterApp': {'generate_config': True}},
@@ -40,6 +49,7 @@
'y': ({'JupyterApp': {'answer_yes': True}},
"Answer yes to any questions instead of prompting."),
}
+base_flags.update(_jupyter_flags)
class NoStart(Exception):
"""Exception to raise when an application shouldn't start"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-4.7.1/jupyter_core/command.py
new/jupyter_core-4.8.1/jupyter_core/command.py
--- old/jupyter_core-4.7.1/jupyter_core/command.py 2020-11-02
16:52:35.000000000 +0100
+++ new/jupyter_core-4.8.1/jupyter_core/command.py 2021-09-17
02:11:12.000000000 +0200
@@ -37,10 +37,10 @@
parser = JupyterParser(
description="Jupyter: Interactive Computing",
)
- group = parser.add_mutually_exclusive_group(required=True)
+ group = parser.add_mutually_exclusive_group(required=False)
# don't use argparse's version action because it prints to stderr on py2
group.add_argument('--version', action='store_true',
- help="show the jupyter command's version and exit")
+ help="show the versions of core jupyter packages and exit")
group.add_argument('subcommand', type=str, nargs='?', help='the subcommand
to launch')
group.add_argument('--config-dir', action='store_true',
@@ -122,12 +122,12 @@
abs_path = which(jupyter_subcommand, path=search_path)
if abs_path is None:
raise Exception(
- 'Jupyter command `{}` not found.'.format(jupyter_subcommand)
+ '\nJupyter command `{}` not found.'.format(jupyter_subcommand)
)
if not os.access(abs_path, os.X_OK):
raise Exception(
- 'Jupyter command `{}` is not
executable.'.format(jupyter_subcommand)
+ '\nJupyter command `{}` is not
executable.'.format(jupyter_subcommand)
)
return abs_path
@@ -184,26 +184,31 @@
args, opts = parser.parse_known_args()
subcommand = args.subcommand
if args.version:
- print('{:<17}:'.format('jupyter core'), __version__)
- for package, name in [
- ('notebook', 'jupyter-notebook'),
- ('qtconsole', 'qtconsole'),
- ('IPython', 'ipython'),
- ('ipykernel', 'ipykernel'),
- ('jupyter_client', 'jupyter client'),
- ('jupyterlab', 'jupyter lab'),
- ('nbconvert', 'nbconvert'),
- ('ipywidgets', 'ipywidgets'),
- ('nbformat', 'nbformat'),
- ('traitlets', 'traitlets'),
+ print("Selected Jupyter core packages...")
+ for package in [
+ 'IPython',
+ 'ipykernel',
+ 'ipywidgets',
+ 'jupyter_client',
+ 'jupyter_core',
+ 'jupyter_server',
+ 'jupyterlab',
+ 'nbclient',
+ 'nbconvert',
+ 'nbformat',
+ 'notebook',
+ 'qtconsole',
+ 'traitlets',
]:
- version = None
try:
- mod = __import__(package)
- version = mod.__version__
+ if package == 'jupyter_core': # We're already here
+ version = __version__
+ else:
+ mod = __import__(package)
+ version = mod.__version__
except ImportError:
version = 'not installed'
- print('{:<17}:'.format(name), version)
+ print('{:<17}:'.format(package), version)
return
if args.json and not args.paths:
sys.exit("--json is only used with --paths")
@@ -279,10 +284,17 @@
return
if not subcommand:
- parser.print_usage(file=sys.stderr)
- sys.exit("subcommand is required")
+ parser.print_help(file=sys.stderr)
+ sys.exit("\nPlease specify a subcommand or one of the optional
arguments.")
- command = _jupyter_abspath(subcommand)
+ try:
+ command = _jupyter_abspath(subcommand)
+ except Exception as e:
+ parser.print_help(file=sys.stderr)
+ # special-case alias of "jupyter help" to "jupyter --help"
+ if subcommand == "help":
+ return
+ sys.exit(e)
try:
_execvp(command, sys.argv[1:])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-4.7.1/jupyter_core/paths.py
new/jupyter_core-4.8.1/jupyter_core/paths.py
--- old/jupyter_core-4.7.1/jupyter_core/paths.py 2021-01-31
17:51:47.000000000 +0100
+++ new/jupyter_core-4.8.1/jupyter_core/paths.py 2021-09-17
02:11:12.000000000 +0200
@@ -14,6 +14,7 @@
import errno
import tempfile
import warnings
+from pathlib import Path
from contextlib import contextmanager
@@ -37,7 +38,7 @@
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 = str(Path(homedir).resolve())
return homedir
_dtemps = {}
@@ -90,7 +91,7 @@
elif os.name == 'nt':
appdata = os.environ.get('APPDATA', None)
if appdata:
- return pjoin(appdata, 'jupyter')
+ return str(Path(appdata, 'jupyter').resolve())
else:
return pjoin(jupyter_config_dir(), 'data')
else:
@@ -267,8 +268,15 @@
return False
raise
- if stat_res.st_file_attributes & stat.FILE_ATTRIBUTE_HIDDEN:
- return True
+ try:
+ if stat_res.st_file_attributes & stat.FILE_ATTRIBUTE_HIDDEN:
+ return True
+ except AttributeError:
+ # allow AttributeError on PyPy for Windows
+ # 'stat_result' object has no attribute 'st_file_attributes'
+ # https://foss.heptapod.net/pypy/pypy/-/issues/3469
+ warnings.warn("hidden files are not detectable on this system, so no
file will be marked as hidden.")
+ pass
return False
@@ -384,7 +392,11 @@
fname : unicode
The path to the file to secure
"""
- import win32api
+ try:
+ import win32api
+ except ImportError:
+ return _win32_restrict_file_to_user_ctypes(fname)
+
import win32security
import ntsecuritycon as con
@@ -403,6 +415,400 @@
win32security.SetFileSecurity(fname,
win32security.DACL_SECURITY_INFORMATION, sd)
+def _win32_restrict_file_to_user_ctypes(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 ctypes
+ from ctypes import wintypes
+
+ advapi32 = ctypes.WinDLL('advapi32', use_last_error=True)
+ secur32 = ctypes.WinDLL('secur32', use_last_error=True)
+
+ NameSamCompatible = 2
+ WinBuiltinAdministratorsSid = 26
+ DACL_SECURITY_INFORMATION = 4
+ ACL_REVISION = 2
+ ERROR_INSUFFICIENT_BUFFER = 122
+ ERROR_MORE_DATA = 234
+
+ SYNCHRONIZE = 0x100000
+ DELETE = 0x00010000
+ STANDARD_RIGHTS_REQUIRED = 0xF0000
+ STANDARD_RIGHTS_READ = 0x20000
+ STANDARD_RIGHTS_WRITE = 0x20000
+ FILE_READ_DATA = 1
+ FILE_READ_EA = 8
+ FILE_READ_ATTRIBUTES = 128
+ FILE_WRITE_DATA = 2
+ FILE_APPEND_DATA = 4
+ FILE_WRITE_EA = 16
+ FILE_WRITE_ATTRIBUTES = 256
+ FILE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF
+ FILE_GENERIC_READ = (
+ STANDARD_RIGHTS_READ
+ | FILE_READ_DATA
+ | FILE_READ_ATTRIBUTES
+ | FILE_READ_EA
+ | SYNCHRONIZE
+ )
+ FILE_GENERIC_WRITE = (
+ STANDARD_RIGHTS_WRITE
+ | FILE_WRITE_DATA
+ | FILE_WRITE_ATTRIBUTES
+ | FILE_WRITE_EA
+ | FILE_APPEND_DATA
+ | SYNCHRONIZE
+ )
+
+ class ACL(ctypes.Structure):
+ _fields_ = [
+ ('AclRevision', wintypes.BYTE),
+ ('Sbz1', wintypes.BYTE),
+ ('AclSize', wintypes.WORD),
+ ('AceCount', wintypes.WORD),
+ ('Sbz2', wintypes.WORD),
+ ]
+
+ PSID = ctypes.c_void_p
+ PACL = ctypes.POINTER(ACL)
+ PSECURITY_DESCRIPTOR = ctypes.POINTER(wintypes.BYTE)
+
+ def _nonzero_success(result, func, args):
+ if not result:
+ raise ctypes.WinError(ctypes.get_last_error())
+ return args
+
+ secur32.GetUserNameExW.errcheck = _nonzero_success
+ secur32.GetUserNameExW.restype = wintypes.BOOL
+ secur32.GetUserNameExW.argtypes = (
+ ctypes.c_int, # EXTENDED_NAME_FORMAT NameFormat
+ wintypes.LPWSTR, # LPWSTR lpNameBuffer,
+ wintypes.PULONG, # PULONG nSize
+ )
+
+ advapi32.CreateWellKnownSid.errcheck = _nonzero_success
+ advapi32.CreateWellKnownSid.restype = wintypes.BOOL
+ advapi32.CreateWellKnownSid.argtypes = (
+ wintypes.DWORD, # WELL_KNOWN_SID_TYPE WellKnownSidType
+ PSID, # PSID DomainSid
+ PSID, # PSID pSid
+ wintypes.PDWORD, # DWORD *cbSid
+ )
+
+ advapi32.LookupAccountNameW.errcheck = _nonzero_success
+ advapi32.LookupAccountNameW.restype = wintypes.BOOL
+ advapi32.LookupAccountNameW.argtypes = (
+ wintypes.LPWSTR, # LPCWSTR lpSystemName
+ wintypes.LPWSTR, # LPCWSTR lpAccountName
+ PSID, # PSID Sid
+ wintypes.LPDWORD, # LPDWORD cbSid
+ wintypes.LPWSTR, # LPCWSTR ReferencedDomainName
+ wintypes.LPDWORD, # LPDWORD cchReferencedDomainName
+ wintypes.LPDWORD, # PSID_NAME_USE peUse
+ )
+
+ advapi32.AddAccessAllowedAce.errcheck = _nonzero_success
+ advapi32.AddAccessAllowedAce.restype = wintypes.BOOL
+ advapi32.AddAccessAllowedAce.argtypes = (
+ PACL, # PACL pAcl
+ wintypes.DWORD, # DWORD dwAceRevision
+ wintypes.DWORD, # DWORD AccessMask
+ PSID, # PSID pSid
+ )
+
+ advapi32.SetSecurityDescriptorDacl.errcheck = _nonzero_success
+ advapi32.SetSecurityDescriptorDacl.restype = wintypes.BOOL
+ advapi32.SetSecurityDescriptorDacl.argtypes = (
+ PSECURITY_DESCRIPTOR, # PSECURITY_DESCRIPTOR pSecurityDescriptor
+ wintypes.BOOL, # BOOL bDaclPresent
+ PACL, # PACL pDacl
+ wintypes.BOOL, # BOOL bDaclDefaulted
+ )
+
+ advapi32.GetFileSecurityW.errcheck = _nonzero_success
+ advapi32.GetFileSecurityW.restype = wintypes.BOOL
+ advapi32.GetFileSecurityW.argtypes = (
+ wintypes.LPCWSTR, # LPCWSTR lpFileName
+ wintypes.DWORD, # SECURITY_INFORMATION RequestedInformation
+ PSECURITY_DESCRIPTOR, # PSECURITY_DESCRIPTOR pSecurityDescriptor
+ wintypes.DWORD, # DWORD nLength
+ wintypes.LPDWORD, # LPDWORD lpnLengthNeeded
+ )
+
+ advapi32.SetFileSecurityW.errcheck = _nonzero_success
+ advapi32.SetFileSecurityW.restype = wintypes.BOOL
+ advapi32.SetFileSecurityW.argtypes = (
+ wintypes.LPCWSTR, # LPCWSTR lpFileName
+ wintypes.DWORD, # SECURITY_INFORMATION SecurityInformation
+ PSECURITY_DESCRIPTOR, # PSECURITY_DESCRIPTOR pSecurityDescriptor
+ )
+
+ advapi32.MakeAbsoluteSD.errcheck = _nonzero_success
+ advapi32.MakeAbsoluteSD.restype = wintypes.BOOL
+ advapi32.MakeAbsoluteSD.argtypes = (
+ PSECURITY_DESCRIPTOR, # pSelfRelativeSecurityDescriptor
+ PSECURITY_DESCRIPTOR, # pAbsoluteSecurityDescriptor
+ wintypes.LPDWORD, # LPDWORD lpdwAbsoluteSecurityDescriptorSize
+ PACL, # PACL pDacl
+ wintypes.LPDWORD, # LPDWORD lpdwDaclSize
+ PACL, # PACL pSacl
+ wintypes.LPDWORD, # LPDWORD lpdwSaclSize
+ PSID, # PSID pOwner
+ wintypes.LPDWORD, # LPDWORD lpdwOwnerSize
+ PSID, # PSID pPrimaryGroup
+ wintypes.LPDWORD, # LPDWORD lpdwPrimaryGroupSize
+ )
+
+ advapi32.MakeSelfRelativeSD.errcheck = _nonzero_success
+ advapi32.MakeSelfRelativeSD.restype = wintypes.BOOL
+ advapi32.MakeSelfRelativeSD.argtypes = (
+ PSECURITY_DESCRIPTOR, # pAbsoluteSecurityDescriptor
+ PSECURITY_DESCRIPTOR, # pSelfRelativeSecurityDescriptor
+ wintypes.LPDWORD, # LPDWORD lpdwBufferLength
+ )
+
+ advapi32.InitializeAcl.errcheck = _nonzero_success
+ advapi32.InitializeAcl.restype = wintypes.BOOL
+ advapi32.InitializeAcl.argtypes = (
+ PACL, # PACL pAcl,
+ wintypes.DWORD, # DWORD nAclLength,
+ wintypes.DWORD, # DWORD dwAclRevision
+ )
+
+ def CreateWellKnownSid(WellKnownSidType):
+ # return a SID for predefined aliases
+ pSid = (ctypes.c_char * 1)()
+ cbSid = wintypes.DWORD()
+ try:
+ advapi32.CreateWellKnownSid(
+ WellKnownSidType, None, pSid, ctypes.byref(cbSid)
+ )
+ except OSError as e:
+ if e.winerror != ERROR_INSUFFICIENT_BUFFER:
+ raise
+ pSid = (ctypes.c_char * cbSid.value)()
+ advapi32.CreateWellKnownSid(
+ WellKnownSidType, None, pSid, ctypes.byref(cbSid)
+ )
+ return pSid[:]
+
+ def GetUserNameEx(NameFormat):
+ # return the user or other security principal associated with
+ # the calling thread
+ nSize = ctypes.pointer(ctypes.c_ulong(0))
+ try:
+ secur32.GetUserNameExW(NameFormat, None, nSize)
+ except WindowsError as e:
+ if e.winerror != ERROR_MORE_DATA:
+ raise
+ if not nSize.contents.value:
+ return None
+ lpNameBuffer = ctypes.create_unicode_buffer(nSize.contents.value)
+ secur32.GetUserNameExW(NameFormat, lpNameBuffer, nSize)
+ return lpNameBuffer.value
+
+ def LookupAccountName(lpSystemName, lpAccountName):
+ # return a security identifier (SID) for an account on a system
+ # and the name of the domain on which the account was found
+ cbSid = wintypes.DWORD(0)
+ cchReferencedDomainName = wintypes.DWORD(0)
+ peUse = wintypes.DWORD(0)
+ try:
+ advapi32.LookupAccountNameW(
+ lpSystemName,
+ lpAccountName,
+ None,
+ ctypes.byref(cbSid),
+ None,
+ ctypes.byref(cchReferencedDomainName),
+ ctypes.byref(peUse),
+ )
+ except WindowsError as e:
+ if e.winerror != ERROR_INSUFFICIENT_BUFFER:
+ raise
+ Sid = ctypes.create_unicode_buffer('', cbSid.value)
+ pSid = ctypes.cast(ctypes.pointer(Sid), wintypes.LPVOID)
+ lpReferencedDomainName = ctypes.create_unicode_buffer(
+ '', cchReferencedDomainName.value + 1
+ )
+ success = advapi32.LookupAccountNameW(
+ lpSystemName,
+ lpAccountName,
+ pSid,
+ ctypes.byref(cbSid),
+ lpReferencedDomainName,
+ ctypes.byref(cchReferencedDomainName),
+ ctypes.byref(peUse),
+ )
+ if not success:
+ raise ctypes.WinError()
+ return pSid, lpReferencedDomainName.value, peUse.value
+
+ def AddAccessAllowedAce(pAcl, dwAceRevision, AccessMask, pSid):
+ # add an access-allowed access control entry (ACE)
+ # to an access control list (ACL)
+ advapi32.AddAccessAllowedAce(pAcl, dwAceRevision, AccessMask, pSid)
+
+ def GetFileSecurity(lpFileName, RequestedInformation):
+ # return information about the security of a file or directory
+ nLength = wintypes.DWORD(0)
+ try:
+ advapi32.GetFileSecurityW(
+ lpFileName,
+ RequestedInformation,
+ None,
+ 0,
+ ctypes.byref(nLength),
+ )
+ except WindowsError as e:
+ if e.winerror != ERROR_INSUFFICIENT_BUFFER:
+ raise
+ if not nLength.value:
+ return None
+ pSecurityDescriptor = (wintypes.BYTE * nLength.value)()
+ advapi32.GetFileSecurityW(
+ lpFileName,
+ RequestedInformation,
+ pSecurityDescriptor,
+ nLength,
+ ctypes.byref(nLength),
+ )
+ return pSecurityDescriptor
+
+ def SetFileSecurity(lpFileName, RequestedInformation, pSecurityDescriptor):
+ # set the security of a file or directory object
+ advapi32.SetFileSecurityW(
+ lpFileName, RequestedInformation, pSecurityDescriptor
+ )
+
+ def SetSecurityDescriptorDacl(
+ pSecurityDescriptor, bDaclPresent, pDacl, bDaclDefaulted
+ ):
+ # set information in a discretionary access control list (DACL)
+ advapi32.SetSecurityDescriptorDacl(
+ pSecurityDescriptor, bDaclPresent, pDacl, bDaclDefaulted
+ )
+
+ def MakeAbsoluteSD(pSelfRelativeSecurityDescriptor):
+ # return a security descriptor in absolute format
+ # by using a security descriptor in self-relative format as a template
+ pAbsoluteSecurityDescriptor = None
+ lpdwAbsoluteSecurityDescriptorSize = wintypes.DWORD(0)
+ pDacl = None
+ lpdwDaclSize = wintypes.DWORD(0)
+ pSacl = None
+ lpdwSaclSize = wintypes.DWORD(0)
+ pOwner = None
+ lpdwOwnerSize = wintypes.DWORD(0)
+ pPrimaryGroup = None
+ lpdwPrimaryGroupSize = wintypes.DWORD(0)
+ try:
+ advapi32.MakeAbsoluteSD(
+ pSelfRelativeSecurityDescriptor,
+ pAbsoluteSecurityDescriptor,
+ ctypes.byref(lpdwAbsoluteSecurityDescriptorSize),
+ pDacl,
+ ctypes.byref(lpdwDaclSize),
+ pSacl,
+ ctypes.byref(lpdwSaclSize),
+ pOwner,
+ ctypes.byref(lpdwOwnerSize),
+ pPrimaryGroup,
+ ctypes.byref(lpdwPrimaryGroupSize),
+ )
+ except WindowsError as e:
+ if e.winerror != ERROR_INSUFFICIENT_BUFFER:
+ raise
+ pAbsoluteSecurityDescriptor = (
+ wintypes.BYTE * lpdwAbsoluteSecurityDescriptorSize.value
+ )()
+ pDaclData = (wintypes.BYTE * lpdwDaclSize.value)()
+ pDacl = ctypes.cast(pDaclData, PACL).contents
+ pSaclData = (wintypes.BYTE * lpdwSaclSize.value)()
+ pSacl = ctypes.cast(pSaclData, PACL).contents
+ pOwnerData = (wintypes.BYTE * lpdwOwnerSize.value)()
+ pOwner = ctypes.cast(pOwnerData, PSID)
+ pPrimaryGroupData = (wintypes.BYTE * lpdwPrimaryGroupSize.value)()
+ pPrimaryGroup = ctypes.cast(pPrimaryGroupData, PSID)
+ advapi32.MakeAbsoluteSD(
+ pSelfRelativeSecurityDescriptor,
+ pAbsoluteSecurityDescriptor,
+ ctypes.byref(lpdwAbsoluteSecurityDescriptorSize),
+ pDacl,
+ ctypes.byref(lpdwDaclSize),
+ pSacl,
+ ctypes.byref(lpdwSaclSize),
+ pOwner,
+ lpdwOwnerSize,
+ pPrimaryGroup,
+ ctypes.byref(lpdwPrimaryGroupSize),
+ )
+ return pAbsoluteSecurityDescriptor
+
+ def MakeSelfRelativeSD(pAbsoluteSecurityDescriptor):
+ # return a security descriptor in self-relative format
+ # by using a security descriptor in absolute format as a template
+ pSelfRelativeSecurityDescriptor = None
+ lpdwBufferLength = wintypes.DWORD(0)
+ try:
+ advapi32.MakeSelfRelativeSD(
+ pAbsoluteSecurityDescriptor,
+ pSelfRelativeSecurityDescriptor,
+ ctypes.byref(lpdwBufferLength),
+ )
+ except WindowsError as e:
+ if e.winerror != ERROR_INSUFFICIENT_BUFFER:
+ raise
+ pSelfRelativeSecurityDescriptor = (
+ wintypes.BYTE * lpdwBufferLength.value
+ )()
+ advapi32.MakeSelfRelativeSD(
+ pAbsoluteSecurityDescriptor,
+ pSelfRelativeSecurityDescriptor,
+ ctypes.byref(lpdwBufferLength),
+ )
+ return pSelfRelativeSecurityDescriptor
+
+ def NewAcl():
+ # return a new, initialized ACL (access control list) structure
+ nAclLength = 32767 # TODO: calculate this: ctypes.sizeof(ACL) + ?
+ acl_data = ctypes.create_string_buffer(nAclLength)
+ pAcl = ctypes.cast(acl_data, PACL).contents
+ advapi32.InitializeAcl(pAcl, nAclLength, ACL_REVISION)
+ return pAcl
+
+ SidAdmins = CreateWellKnownSid(WinBuiltinAdministratorsSid)
+ SidUser = LookupAccountName('', GetUserNameEx(NameSamCompatible))[0]
+
+ Acl = NewAcl()
+ AddAccessAllowedAce(Acl, ACL_REVISION, FILE_ALL_ACCESS, SidAdmins)
+ AddAccessAllowedAce(
+ Acl,
+ ACL_REVISION,
+ FILE_GENERIC_READ | FILE_GENERIC_WRITE | DELETE,
+ SidUser,
+ )
+
+ SelfRelativeSD = GetFileSecurity(fname, DACL_SECURITY_INFORMATION)
+ AbsoluteSD = MakeAbsoluteSD(SelfRelativeSD)
+ SetSecurityDescriptorDacl(AbsoluteSD, 1, Acl, 0)
+ SelfRelativeSD = MakeSelfRelativeSD(AbsoluteSD)
+
+ SetFileSecurity(fname, DACL_SECURITY_INFORMATION, SelfRelativeSD)
+
+
def get_file_mode(fname):
"""Retrieves the file mode corresponding to fname in a filesystem-tolerant
manner.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-4.7.1/jupyter_core/tests/mocking.py
new/jupyter_core-4.8.1/jupyter_core/tests/mocking.py
--- old/jupyter_core-4.7.1/jupyter_core/tests/mocking.py 2020-10-30
15:38:29.000000000 +0100
+++ new/jupyter_core-4.8.1/jupyter_core/tests/mocking.py 2021-09-17
02:11:12.000000000 +0200
@@ -29,8 +29,3 @@
patch.object(os, 'name', 'posix'),
patch.object(sys, 'platform', 'linux2'),
)
-
-windows = MultiPatch(
- patch.object(os, 'name', 'nt'),
- patch.object(sys, 'platform', 'win32'),
-)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/jupyter_core-4.7.1/jupyter_core/tests/test_command.py
new/jupyter_core-4.8.1/jupyter_core/tests/test_command.py
--- old/jupyter_core-4.7.1/jupyter_core/tests/test_command.py 2020-11-02
16:52:35.000000000 +0100
+++ new/jupyter_core-4.8.1/jupyter_core/tests/test_command.py 2021-09-17
02:11:12.000000000 +0200
@@ -4,7 +4,7 @@
import os
import sys
import sysconfig
-from subprocess import check_output, CalledProcessError
+from subprocess import check_output, PIPE, CalledProcessError
from unittest.mock import patch
import pytest
@@ -21,7 +21,7 @@
"""Get output of a jupyter command"""
if not isinstance(cmd, list):
cmd = [cmd]
- return check_output([sys.executable, '-m', 'jupyter_core'] +
cmd).decode('utf8').strip()
+ return check_output([sys.executable, '-m', 'jupyter_core'] + cmd,
stderr=PIPE).decode('utf8').strip()
def write_executable(path, source):
@@ -109,8 +109,10 @@
def test_subcommand_not_found():
- with pytest.raises(CalledProcessError):
+ with pytest.raises(CalledProcessError) as excinfo:
get_jupyter_output('nonexistant-subcommand')
+ stderr = excinfo.value.stderr.decode('utf8')
+ assert 'Jupyter command `jupyter-nonexistant-subcommand` not found.' in
stderr
@patch.object(sys, 'argv', [__file__] + sys.argv[1:])
def test_subcommand_list(tmpdir):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-4.7.1/jupyter_core/tests/test_paths.py
new/jupyter_core-4.8.1/jupyter_core/tests/test_paths.py
--- old/jupyter_core-4.7.1/jupyter_core/tests/test_paths.py 2021-01-31
17:51:47.000000000 +0100
+++ new/jupyter_core-4.8.1/jupyter_core/tests/test_paths.py 2021-09-17
03:20:27.000000000 +0200
@@ -10,7 +10,9 @@
import tempfile
from unittest.mock import patch
import pytest
+import subprocess
import sys
+import warnings
from jupyter_core import paths
from jupyter_core.paths import (
@@ -19,7 +21,7 @@
secure_write, is_hidden, is_file_hidden
)
-from .mocking import darwin, windows, linux
+from .mocking import darwin, linux
pjoin = os.path.join
@@ -36,8 +38,6 @@
'XDG_RUNTIME_DIR': '',
})
-appdata = patch.dict('os.environ', {'APPDATA': 'appdata'})
-
no_config_env = patch.dict('os.environ', {
'JUPYTER_CONFIG_DIR': '',
'JUPYTER_DATA_DIR': '',
@@ -50,7 +50,7 @@
def realpath(path):
- return os.path.realpath(os.path.expanduser(path))
+ return os.path.abspath(os.path.realpath(os.path.expanduser(path)))
home_jupyter = realpath('~/.jupyter')
@@ -65,6 +65,7 @@
assert not paths.envset(f"FOO_{v}")
assert not paths.envset("THIS_VARIABLE_SHOULD_NOT_BE_SET")
[email protected](sys.platform == "win32", reason="does not run on windows")
def test_config_dir_darwin():
with darwin, no_config_env:
config = jupyter_config_dir()
@@ -74,23 +75,24 @@
config = jupyter_config_dir()
assert config == jupyter_config_env
-
[email protected](sys.platform != "win32", reason="only run on windows")
def test_config_dir_windows():
- with windows, no_config_env:
+ with no_config_env:
config = jupyter_config_dir()
assert config == home_jupyter
- with windows, config_env:
+ with config_env:
config = jupyter_config_dir()
assert config == jupyter_config_env
[email protected](sys.platform == "win32", reason="does not run on windows")
def test_config_dir_linux():
- with windows, no_config_env:
+ with linux, no_config_env:
config = jupyter_config_dir()
assert config == home_jupyter
- with windows, config_env:
+ with linux, config_env:
config = jupyter_config_dir()
assert config == jupyter_config_env
@@ -102,6 +104,7 @@
assert data == data_env
[email protected](sys.platform == "win32", reason="does not run on windows")
def test_data_dir_darwin():
with darwin:
data = jupyter_data_dir()
@@ -112,18 +115,18 @@
data = jupyter_data_dir()
assert data == realpath('~/Library/Jupyter')
-
[email protected](sys.platform != "win32", reason="only run on windows")
def test_data_dir_windows():
- with windows, appdata:
- data = jupyter_data_dir()
- assert data == pjoin('appdata', 'jupyter')
+ data = jupyter_data_dir()
+ assert data == realpath(pjoin(os.environ.get('APPDATA', None), 'jupyter'))
- with windows, appdata, xdg:
+ with xdg:
# windows should ignore xdg
data = jupyter_data_dir()
- assert data == pjoin('appdata', 'jupyter')
+ assert data == realpath(pjoin(os.environ.get('APPDATA', None), 'jupyter'))
[email protected](sys.platform == "win32", reason="does not run on windows")
def test_data_dir_linux():
with linux, no_xdg:
data = jupyter_data_dir()
@@ -141,6 +144,7 @@
assert runtime == rtd_env
[email protected](sys.platform == "win32", reason="does not run on windows")
def test_runtime_dir_darwin():
with darwin:
runtime = jupyter_runtime_dir()
@@ -151,18 +155,18 @@
runtime = jupyter_runtime_dir()
assert runtime == realpath('~/Library/Jupyter/runtime')
-
[email protected](sys.platform != "win32", reason="only run on windows")
def test_runtime_dir_windows():
- with windows, appdata:
- runtime = jupyter_runtime_dir()
- assert runtime == pjoin('appdata', 'jupyter', 'runtime')
+ runtime = jupyter_runtime_dir()
+ assert runtime == realpath(pjoin(os.environ.get('APPDATA', None),
'jupyter', 'runtime'))
- with windows, appdata, xdg:
+ with xdg:
# windows should ignore xdg
runtime = jupyter_runtime_dir()
- assert runtime == pjoin('appdata', 'jupyter', 'runtime')
+ assert runtime == realpath(pjoin(os.environ.get('APPDATA', None),
'jupyter', 'runtime'))
[email protected](sys.platform == "win32", reason="does not run on windows")
def test_runtime_dir_linux():
with linux, no_xdg:
runtime = jupyter_runtime_dir()
@@ -256,18 +260,53 @@
assert not is_file_hidden(subdir56, os.stat(subdir56))
[email protected](sys.platform != "win32", reason="only run on windows")
-def test_is_hidden_win32():
[email protected](
+ not (sys.platform == "win32" and (("__pypy__" not in sys.modules) or
(sys.implementation.version >= (7, 3, 6)))),
+ reason="only run on windows/cpython or pypy >= 7.3.6:
https://foss.heptapod.net/pypy/pypy/-/issues/3469"
+)
+def test_is_hidden_win32_cpython():
import ctypes
with tempfile.TemporaryDirectory() as root:
subdir1 = os.path.join(root, 'subdir')
os.makedirs(subdir1)
assert not is_hidden(subdir1, root)
- r = ctypes.windll.kernel32.SetFileAttributesW(subdir1, 0x02)
- print(r) # Helps debugging
+ subprocess.check_call(["attrib", "+h", subdir1])
assert is_hidden(subdir1, root)
assert is_file_hidden(subdir1)
[email protected](
+ not (sys.platform == "win32" and "__pypy__" in sys.modules and
sys.implementation.version < (7, 3, 6)),
+ reason="only run on windows/pypy < 7.3.6:
https://foss.heptapod.net/pypy/pypy/-/issues/3469"
+)
+def test_is_hidden_win32_pypy():
+ import ctypes
+ with tempfile.TemporaryDirectory() as root:
+ subdir1 = os.path.join(root, 'subdir')
+ os.makedirs(subdir1)
+ assert not is_hidden(subdir1, root)
+ subprocess.check_call(["attrib", "+h", subdir1])
+
+ with warnings.catch_warnings(record=True) as w:
+ # Cause all warnings to always be triggered.
+ warnings.simplefilter("always")
+ # Trigger a warning.
+ assert not is_hidden(subdir1, root)
+ # Verify the warning was triggered
+ assert len(w) == 1
+ assert issubclass(w[-1].category, UserWarning)
+ assert "hidden files are not detectable on this system" in
str(w[-1].message)
+
+ with warnings.catch_warnings(record=True) as w:
+ # Cause all warnings to always be triggered.
+ warnings.simplefilter("always")
+ # Trigger a warning.
+ assert not is_file_hidden(subdir1)
+ # Verify the warning was triggered
+ assert len(w) == 1
+ assert issubclass(w[-1].category, UserWarning)
+ assert "hidden files are not detectable on this system" in
str(w[-1].message)
+
+
@pytest.mark.skipif(sys.platform != "win32", reason="only runs on windows")
def test_secure_write_win32():
@@ -289,8 +328,7 @@
def check_user_only_permissions(fname):
# Windows has it's own permissions ACL patterns
- import win32api
- username = win32api.GetUserName().lower()
+ username = os.environ["USERNAME"].lower()
permissions = fetch_win32_permissions(fname)
print(permissions) # for easier debugging
assert username in permissions
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-4.7.1/jupyter_core/version.py
new/jupyter_core-4.8.1/jupyter_core/version.py
--- old/jupyter_core-4.7.1/jupyter_core/version.py 2021-01-31
19:28:26.000000000 +0100
+++ new/jupyter_core-4.8.1/jupyter_core/version.py 2021-09-17
03:20:43.000000000 +0200
@@ -11,7 +11,7 @@
'serial'
])
-version_info = VersionInfo(4, 7, 1, 'final', 0)
+version_info = VersionInfo(4, 8, 1, 'final', 0)
_specifier_ = {'alpha': 'a', 'beta': 'b', 'candidate': 'rc', 'final': '',
'dev': 'dev'}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-4.7.1/jupyter_core.egg-info/PKG-INFO
new/jupyter_core-4.8.1/jupyter_core.egg-info/PKG-INFO
--- old/jupyter_core-4.7.1/jupyter_core.egg-info/PKG-INFO 2021-01-31
19:30:07.000000000 +0100
+++ new/jupyter_core-4.8.1/jupyter_core.egg-info/PKG-INFO 2021-09-17
03:21:05.000000000 +0200
@@ -1,13 +1,13 @@
Metadata-Version: 2.1
Name: jupyter-core
-Version: 4.7.1
+Version: 4.8.1
Summary: Jupyter core package. A base package on which Jupyter projects rely.
Home-page: https://jupyter.org
Author: Jupyter Development Team
Author-email: [email protected]
-License: BSD
-Description: There is no reason to install this package on its own.
+License: BSD-3-Clause
Platform: UNKNOWN
+Classifier: Framework :: Jupyter
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Intended Audience :: Science/Research
@@ -16,3 +16,7 @@
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.6
Description-Content-Type: text/plain
+License-File: COPYING.md
+
+There is no reason to install this package on its own.
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-4.7.1/jupyter_core.egg-info/SOURCES.txt
new/jupyter_core-4.8.1/jupyter_core.egg-info/SOURCES.txt
--- old/jupyter_core-4.7.1/jupyter_core.egg-info/SOURCES.txt 2021-01-31
19:30:07.000000000 +0100
+++ new/jupyter_core-4.8.1/jupyter_core.egg-info/SOURCES.txt 2021-09-17
03:21:05.000000000 +0200
@@ -6,7 +6,6 @@
jupyter.py
setup.cfg
setup.py
-docs/.DS_Store
docs/Makefile
docs/changelog.rst
docs/conf.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/jupyter_core-4.7.1/jupyter_core.egg-info/requires.txt
new/jupyter_core-4.8.1/jupyter_core.egg-info/requires.txt
--- old/jupyter_core-4.7.1/jupyter_core.egg-info/requires.txt 2021-01-31
19:30:07.000000000 +0100
+++ new/jupyter_core-4.8.1/jupyter_core.egg-info/requires.txt 2021-09-17
03:21:05.000000000 +0200
@@ -1,4 +1,4 @@
traitlets
-[:sys_platform == "win32"]
+[:sys_platform == "win32" and platform_python_implementation != "PyPy"]
pywin32>=1.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/jupyter_core-4.7.1/setup.cfg
new/jupyter_core-4.8.1/setup.cfg
--- old/jupyter_core-4.7.1/setup.cfg 2021-01-31 19:30:07.000000000 +0100
+++ new/jupyter_core-4.8.1/setup.cfg 2021-09-17 03:21:05.842677000 +0200
@@ -7,9 +7,10 @@
author = Jupyter Development Team
author_email = [email protected]
url = https://jupyter.org
-license = BSD
+license = BSD-3-Clause
license_file = COPYING.md
classifiers =
+ Framework :: Jupyter
Intended Audience :: Developers
Intended Audience :: System Administrators
Intended Audience :: Science/Research
@@ -24,7 +25,7 @@
python_requires = >=3.6
install_requires =
traitlets
- pywin32>=1.0 ; sys_platform == 'win32'
+ pywin32>=1.0 ; sys_platform == 'win32' and
platform_python_implementation != 'PyPy'
[options.entry_points]
console_scripts =
++++++ use_rpms_paths.patch ++++++
--- /var/tmp/diff_new_pack.1CGsPR/_old 2021-10-25 15:17:36.053681916 +0200
+++ /var/tmp/diff_new_pack.1CGsPR/_new 2021-10-25 15:17:36.053681916 +0200
@@ -9,7 +9,7 @@
--- a/jupyter_core/paths.py
+++ b/jupyter_core/paths.py
-@@ -117,10 +117,7 @@
+@@ -124,10 +124,7 @@ if os.name == 'nt':
else: # PROGRAMDATA is not defined by default on XP.
SYSTEM_JUPYTER_PATH = [os.path.join(sys.prefix, 'share', 'jupyter')]
else:
@@ -21,7 +21,7 @@
ENV_JUPYTER_PATH = [os.path.join(sys.prefix, 'share', 'jupyter')]
-@@ -169,10 +166,7 @@
+@@ -186,10 +183,7 @@ if os.name == 'nt':
else: # PROGRAMDATA is not defined by default on XP.
SYSTEM_CONFIG_PATH = []
else: