Skip to content

Commit

Permalink
msys mingw prefer unix sep if MSYSTEM
Browse files Browse the repository at this point in the history
Co-authored-by: Алексей <alexey.pawlow@gmail.com>
Co-authored-by: Christoph Reiter <reiter.christoph@gmail.com>
  • Loading branch information
3 people authored and naveen521kk committed Jul 1, 2021
1 parent db3e499 commit 8264c28
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 37 deletions.
6 changes: 6 additions & 0 deletions Include/pylifecycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ PyAPI_FUNC(int) Py_IsInitialized(void);
PyAPI_FUNC(PyThreadState *) Py_NewInterpreter(void);
PyAPI_FUNC(void) Py_EndInterpreter(PyThreadState *);

PyAPI_FUNC(wchar_t) Py_GetSepW(const wchar_t *);
PyAPI_FUNC(char) Py_GetSepA(const char *);

PyAPI_FUNC(void) Py_NormalizeSepsW(wchar_t *);
PyAPI_FUNC(void) Py_NormalizeSepsA(char *);


/* Py_PyAtExit is for the atexit module, Py_AtExit is for low-level
* exit functions.
Expand Down
79 changes: 45 additions & 34 deletions Lib/ntpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
curdir = '.'
pardir = '..'
extsep = '.'
sep = '\\'
pathsep = ';'
altsep = '/'
defpath = '.;C:\\bin'
devnull = 'nul'

Expand All @@ -23,6 +21,15 @@
import genericpath
from genericpath import *

if sys.platform == "win32" and "MSYSTEM" in os.environ:
sep = '/'
altsep = '\\'
else:
sep = '\\'
altsep = '/'
bsep = str.encode(sep)
baltsep = str.encode(altsep)

__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
"basename","dirname","commonprefix","getsize","getmtime",
"getatime","getctime", "islink","exists","lexists","isdir","isfile",
Expand All @@ -33,9 +40,27 @@

def _get_bothseps(path):
if isinstance(path, bytes):
return b'\\/'
return bsep+baltsep
else:
return sep+altsep

def _get_sep(path):
if isinstance(path, bytes):
return bsep
else:
return sep

def _get_altsep(path):
if isinstance(path, bytes):
return baltsep
else:
return '\\/'
return altsep

def _get_colon(path):
if isinstance(path, bytes):
return b':'
else:
return ':'

# Normalize the case of a pathname and map slashes to backslashes.
# Other normalizations (such as optimizing '../' away) are not done
Expand All @@ -47,9 +72,9 @@ def normcase(s):
Makes all characters lowercase and all slashes into backslashes."""
s = os.fspath(s)
if isinstance(s, bytes):
return s.replace(b'/', b'\\').lower()
return s.replace(baltsep, bsep).lower()
else:
return s.replace('/', '\\').lower()
return s.replace(altsep, sep).lower()


# Return whether a path is absolute.
Expand All @@ -76,14 +101,9 @@ def isabs(s):
# Join two (or more) paths.
def join(path, *paths):
path = os.fspath(path)
if isinstance(path, bytes):
sep = b'\\'
seps = b'\\/'
colon = b':'
else:
sep = '\\'
seps = '\\/'
colon = ':'
sep = _get_sep(path)
seps = _get_bothseps(path)
colon = _get_colon(path)
try:
if not paths:
path[:0] + sep #23780: Ensure compatible data type even if p is null.
Expand Down Expand Up @@ -142,14 +162,9 @@ def splitdrive(p):
"""
p = os.fspath(p)
if len(p) >= 2:
if isinstance(p, bytes):
sep = b'\\'
altsep = b'/'
colon = b':'
else:
sep = '\\'
altsep = '/'
colon = ':'
sep = _get_sep(p)
altsep = _get_altsep(p)
colon = _get_colon(p)
normp = p.replace(altsep, sep)
if (normp[0:2] == sep*2) and (normp[2:3] != sep):
# is a UNC path:
Expand Down Expand Up @@ -203,9 +218,9 @@ def split(p):
def splitext(p):
p = os.fspath(p)
if isinstance(p, bytes):
return genericpath._splitext(p, b'\\', b'/', b'.')
return genericpath._splitext(p, bsep, baltsep, b'.')
else:
return genericpath._splitext(p, '\\', '/', '.')
return genericpath._splitext(p, sep, altsep, '.')
splitext.__doc__ = genericpath._splitext.__doc__


Expand Down Expand Up @@ -450,15 +465,13 @@ def expandvars(path):
def normpath(path):
"""Normalize path, eliminating double slashes, etc."""
path = os.fspath(path)
sep = _get_sep(path)
altsep = _get_altsep(path)
if isinstance(path, bytes):
sep = b'\\'
altsep = b'/'
curdir = b'.'
pardir = b'..'
special_prefixes = (b'\\\\.\\', b'\\\\?\\')
else:
sep = '\\'
altsep = '/'
curdir = '.'
pardir = '..'
special_prefixes = ('\\\\.\\', '\\\\?\\')
Expand Down Expand Up @@ -668,6 +681,7 @@ def realpath(path):
# strip the prefix anyway.
if ex.winerror == initial_winerror:
path = spath
path = normpath(path)
return path


Expand All @@ -678,12 +692,11 @@ def realpath(path):
def relpath(path, start=None):
"""Return a relative version of a path"""
path = os.fspath(path)
sep = _get_sep(path)
if isinstance(path, bytes):
sep = b'\\'
curdir = b'.'
pardir = b'..'
else:
sep = '\\'
curdir = '.'
pardir = '..'

Expand Down Expand Up @@ -738,13 +751,11 @@ def commonpath(paths):
raise ValueError('commonpath() arg is an empty sequence')

paths = tuple(map(os.fspath, paths))
sep = _get_sep(paths[0])
altsep = _get_altsep(paths[0])
if isinstance(paths[0], bytes):
sep = b'\\'
altsep = b'/'
curdir = b'.'
else:
sep = '\\'
altsep = '/'
curdir = '.'

try:
Expand Down
2 changes: 2 additions & 0 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -3759,6 +3759,7 @@ posix_getcwd(int use_bytes)
return PyErr_SetFromWindowsErr(0);
}

Py_NormalizeSepsW(wbuf2);
PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
if (wbuf2 != wbuf) {
PyMem_RawFree(wbuf2);
Expand Down Expand Up @@ -4322,6 +4323,7 @@ os__getfinalpathname_impl(PyObject *module, path_t *path)
target_path = tmp;
}

Py_NormalizeSepsW(target_path);
result = PyUnicode_FromWideChar(target_path, result_length);
if (result && path->narrow) {
Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
Expand Down
4 changes: 2 additions & 2 deletions Python/initconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ static const char usage_6[] =
"PYTHONDEVMODE: enable the development mode.\n"
"PYTHONPYCACHEPREFIX: root directory for bytecode cache (pyc) files.\n";

#if defined(MS_WINDOWS)
#if defined(_MSC_VER)
# define PYTHONHOMEHELP "<prefix>\\python{major}{minor}"
#else
# define PYTHONHOMEHELP "<prefix>/lib/pythonX.X"
Expand Down Expand Up @@ -1187,7 +1187,7 @@ config_init_program_name(PyConfig *config)
}

/* Last fall back: hardcoded name */
#ifdef MS_WINDOWS
#ifdef _MSC_VER
const wchar_t *default_program_name = L"python";
#else
const wchar_t *default_program_name = L"python3";
Expand Down
109 changes: 109 additions & 0 deletions Python/pathconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,114 @@
extern "C" {
#endif

#ifdef __MINGW32__
#define wcstok wcstok_s
#include <windows.h>
#endif

char
Py_GetSepA(const char *name)
{
char* msystem = (char*)2; /* So that non Windows use / as sep */
static char sep = '\0';
#ifdef _WIN32
/* https://msdn.microsoft.com/en-gb/library/windows/desktop/aa365247%28v=vs.85%29.aspx
* The "\\?\" prefix .. indicate that the path should be passed to the system with minimal
* modification, which means that you cannot use forward slashes to represent path separators
*/
if (name != NULL && memcmp(name, "\\\\?\\", sizeof("\\\\?\\") - sizeof(char)) == 0)
{
return '\\';
}
#endif
if (sep != '\0')
return sep;
#if defined(__MINGW32__)
msystem = Py_GETENV("MSYSTEM");
#endif
if (msystem != NULL)
sep = '/';
else
sep = '\\';
return sep;
}

static char
Py_GetAltSepA(const char *name)
{
char sep = Py_GetSepA(name);
if (sep == '/')
return '\\';
return '/';
}

void
Py_NormalizeSepsA(char *name)
{
char sep = Py_GetSepA(name);
char altsep = Py_GetAltSepA(name);
char* seps;
if (strlen(name) > 1 && name[1] == ':') {
name[0] = toupper(name[0]);
}
seps = strchr(name, altsep);
while(seps) {
*seps = sep;
seps = strchr(seps, altsep);
}
}

wchar_t
Py_GetSepW(const wchar_t *name)
{
char* msystem = (char*)2; /* So that non Windows use / as sep */
static wchar_t sep = L'\0';
#ifdef _WIN32
/* https://msdn.microsoft.com/en-gb/library/windows/desktop/aa365247%28v=vs.85%29.aspx
* The "\\?\" prefix .. indicate that the path should be passed to the system with minimal
* modification, which means that you cannot use forward slashes to represent path separators
*/
if (name != NULL && memcmp(name, L"\\\\?\\", sizeof(L"\\\\?\\") - sizeof(wchar_t)) == 0)
{
return L'\\';
}
#endif
if (sep != L'\0')
return sep;
#if defined(__MINGW32__)
msystem = Py_GETENV("MSYSTEM");
#endif
if (msystem != NULL)
sep = L'/';
else
sep = L'\\';
return sep;
}

static wchar_t
Py_GetAltSepW(const wchar_t *name)
{
char sep = Py_GetSepW(name);
if (sep == L'/')
return L'\\';
return L'/';
}

void
Py_NormalizeSepsW(wchar_t *name)
{
wchar_t sep = Py_GetSepW(name);
wchar_t altsep = Py_GetAltSepW(name);
wchar_t* seps;
if (wcslen(name) > 1 && name[1] == L':') {
name[0] = towupper(name[0]);
}
seps = wcschr(name, altsep);
while(seps) {
*seps = sep;
seps = wcschr(seps, altsep);
}
}

_PyPathConfig _Py_path_config = _PyPathConfig_INIT;

Expand Down Expand Up @@ -541,6 +649,7 @@ _Py_SetProgramFullPath(const wchar_t *program_full_path)
if (_Py_path_config.program_full_path == NULL) {
path_out_of_memory(__func__);
}
Py_NormalizeSepsW(_Py_path_config.program_name);
}


Expand Down
2 changes: 1 addition & 1 deletion Python/traceback.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *
filepath = PyBytes_AS_STRING(filebytes);

/* Search tail of filename in sys.path before giving up */
tail = strrchr(filepath, SEP);
tail = strrchr(filepath, Py_GetSepA(filepath));
if (tail == NULL)
tail = filepath;
else
Expand Down

0 comments on commit 8264c28

Please sign in to comment.