Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 50d8d37

Browse files
committed
Implement PEP 235: Import on Case-Insensitive Platforms.
http://python.sourceforge.net/peps/pep-0235.html Renamed check_case to case_ok. Substantial code rearrangement to get this stuff in one place in the file. Innermost loop of find_module() now much simpler and #ifdef-free, and I want to keep it that way (it's bad enough that the innermost loop is itself still in an #ifdef!). Windows semantics tested and are fine. Jason, Cygwin *should* be fine if and only if what you did before "worked" for case_ok. Jack, the semantics on your flavor of Mac have definitely changed (see the PEP), and need to be tested. The intent is that your flavor of Mac now work the same as everything else in the "lower left" box, including respecting PYTHONCASEOK. Steven, sorry, you did the most work here so far but you got screwed the worst. Happy to work with you on repairing it, but I don't understand anything about all your Mac variants. We need to add another branch (or two, three, ...?) inside case_ok. But we should not need to change anything else.
1 parent 6e7e485 commit 50d8d37

1 file changed

Lines changed: 87 additions & 138 deletions

File tree

Python/import.c

Lines changed: 87 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ open_exclusive(char *filename)
633633
#ifdef O_BINARY
634634
|O_BINARY /* necessary for Windows */
635635
#endif
636-
636+
637637
, 0666);
638638
if (fd < 0)
639639
return NULL;
@@ -830,13 +830,10 @@ extern FILE *PyWin_FindRegisteredModule(const char *, struct filedescr **,
830830
char *, int);
831831
#endif
832832

833-
#ifdef CHECK_IMPORT_CASE
834-
static int check_case(char *, int, int, char *);
835-
#endif
836-
833+
static int case_ok(char *, int, int, char *);
837834
static int find_init_module(char *); /* Forward */
838835

839-
#ifdef HAVE_DIRENT_H
836+
#if 0 /* XXX was #ifdef HAVE_DIRENT_H; resolve whether we really need this */
840837

841838
static int MatchFilename(char *pathname, char *filename);
842839

@@ -944,25 +941,25 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen,
944941
continue; /* v contains '\0' */
945942
#ifdef macintosh
946943
#ifdef INTERN_STRINGS
947-
/*
944+
/*
948945
** Speedup: each sys.path item is interned, and
949946
** FindResourceModule remembers which items refer to
950947
** folders (so we don't have to bother trying to look
951-
** into them for resources).
948+
** into them for resources).
952949
*/
953950
PyString_InternInPlace(&PyList_GET_ITEM(path, i));
954951
v = PyList_GET_ITEM(path, i);
955952
#endif
956953
if (PyMac_FindResourceModule((PyStringObject *)v, name, buf)) {
957954
static struct filedescr resfiledescr =
958955
{"", "", PY_RESOURCE};
959-
956+
960957
return &resfiledescr;
961958
}
962959
if (PyMac_FindCodeResourceModule((PyStringObject *)v, name, buf)) {
963960
static struct filedescr resfiledescr =
964961
{"", "", PY_CODERESOURCE};
965-
962+
966963
return &resfiledescr;
967964
}
968965
#endif
@@ -974,18 +971,17 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen,
974971
buf[len++] = SEP;
975972
strcpy(buf+len, name);
976973
len += namelen;
974+
975+
/* Check for package import (buf holds a directory name,
976+
and there's an __init__ module in that directory */
977977
#ifdef HAVE_STAT
978-
if (stat(buf, &statbuf) == 0) {
979-
if (S_ISDIR(statbuf.st_mode)) {
980-
if (find_init_module(buf)) {
981-
#ifdef CHECK_IMPORT_CASE
982-
if (!check_case(buf, len, namelen,
983-
name))
984-
return NULL;
985-
#endif
986-
return &fd_package;
987-
}
988-
}
978+
if (stat(buf, &statbuf) == 0 &&
979+
S_ISDIR(statbuf.st_mode) &&
980+
find_init_module(buf)) {
981+
if (case_ok(buf, len, namelen, name))
982+
return &fd_package;
983+
else
984+
return NULL;
989985
}
990986
#else
991987
/* XXX How are you going to test for directories? */
@@ -1000,27 +996,14 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen,
1000996
if (Py_VerboseFlag > 1)
1001997
PySys_WriteStderr("# trying %s\n", buf);
1002998
fp = fopen(buf, fdp->mode);
1003-
#ifdef HAVE_DIRENT_H
1004-
1005-
if (fp != NULL) { /* check case */
1006-
char *curpath = PyString_AsString(v);
1007-
char *nstart = buf + strlen(curpath);
1008-
if (*nstart == SEP)
1009-
nstart++;
1010-
if (MatchFilename(curpath, nstart)) {
1011-
break; /* Found */
999+
if (fp != NULL) {
1000+
if (case_ok(buf, len, namelen, name))
1001+
break;
1002+
else { /* continue search */
1003+
fclose(fp);
1004+
fp = NULL;
10121005
}
1013-
fclose(fp); /* No. Close & continue search */
1014-
fp = NULL;
1015-
if (Py_VerboseFlag > 1)
1016-
PySys_WriteStderr(
1017-
"# case mismatch for %s: %s\n",
1018-
name, buf);
10191006
}
1020-
#else /* !HAVE_DIRENT_H */
1021-
if (fp != NULL)
1022-
break;
1023-
#endif /* HAVE_DIRENT_H */
10241007
}
10251008
#endif /* !macintosh */
10261009
if (fp != NULL)
@@ -1031,62 +1014,62 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen,
10311014
"No module named %.200s", name);
10321015
return NULL;
10331016
}
1034-
#ifdef CHECK_IMPORT_CASE
1035-
if (!check_case(buf, len, namelen, name)) {
1036-
fclose(fp);
1037-
return NULL;
1038-
}
1039-
#endif
1040-
10411017
*p_fp = fp;
10421018
return fdp;
10431019
}
10441020

1045-
#ifdef CHECK_IMPORT_CASE
1046-
1021+
/* case_ok(buf, len, namelen, name)
1022+
* We've already done a successful stat() or fopen() on buf (a path of length
1023+
* len; can not assume there's a trailing null). name is the last component
1024+
* of then path (a string of length namelen, exclusive of trailing null).
1025+
* case_ok() is to return 1 if there's a case-sensitive match for
1026+
* name, else 0. case_ok() is also to return 1 if envar PYTHONCASEOK
1027+
* exists.
1028+
* case_ok() is used to implement case-sensitive import semantics even
1029+
* on platforms with case-insensitive filesystems. It's trivial to implement
1030+
* for case-sensitive filesystems. It's pretty much a cross-platform
1031+
* nightmare for systems with case-insensitive filesystems.
1032+
*/
1033+
1034+
/* First we may need a pile of platform-specific header files; the sequence
1035+
* of #if's here should match the sequence in the body of case_ok().
1036+
*/
10471037
#if defined(MS_WIN32) || defined(__CYGWIN__)
10481038
#include <windows.h>
10491039
#include <ctype.h>
1050-
1051-
static int
1052-
allcaps8x3(char *s)
1053-
{
1054-
/* Return 1 if s is an 8.3 filename in ALLCAPS */
1055-
char c;
1056-
char *dot = strchr(s, '.');
1057-
char *end = strchr(s, '\0');
1058-
if (dot != NULL) {
1059-
if (dot-s > 8)
1060-
return 0; /* More than 8 before '.' */
1061-
if (end-dot > 4)
1062-
return 0; /* More than 3 after '.' */
1063-
end = strchr(dot+1, '.');
1064-
if (end != NULL)
1065-
return 0; /* More than one dot */
1066-
}
1067-
else if (end-s > 8)
1068-
return 0; /* More than 8 and no dot */
1069-
while ((c = *s++)) {
1070-
if (islower(c))
1071-
return 0;
1072-
}
1073-
return 1;
1074-
}
1075-
10761040
#ifdef __CYGWIN__
10771041
#include <sys/cygwin.h>
10781042
#endif
10791043

1044+
#elif defined(DJGPP)
1045+
#include <dir.h>
1046+
1047+
#elif defined(macintosh)
1048+
#include <TextUtils.h>
1049+
#ifdef USE_GUSI1
1050+
#include "TFileSpec.h" /* for Path2FSSpec() */
1051+
#endif
1052+
1053+
#endif
1054+
10801055
static int
1081-
check_case(char *buf, int len, int namelen, char *name)
1056+
case_ok(char *buf, int len, int namelen, char *name)
10821057
{
1058+
/* Pick a platform-specific implementation; the sequence of #if's here should
1059+
* match the sequence just above.
1060+
*/
1061+
1062+
/* MS_WIN32 || __CYGWIN__ */
1063+
#if defined(MS_WIN32) || defined(__CYGWIN__)
10831064
WIN32_FIND_DATA data;
10841065
HANDLE h;
10851066
#ifdef __CYGWIN__
10861067
char tempbuf[MAX_PATH];
10871068
#endif
1069+
10881070
if (getenv("PYTHONCASEOK") != NULL)
10891071
return 1;
1072+
10901073
#ifdef __CYGWIN__
10911074
cygwin32_conv_to_win32_path(buf, tempbuf);
10921075
h = FindFirstFile(tempbuf, &data);
@@ -1100,35 +1083,33 @@ check_case(char *buf, int len, int namelen, char *name)
11001083
return 0;
11011084
}
11021085
FindClose(h);
1103-
if (allcaps8x3(data.cFileName)) {
1104-
/* Skip the test if the filename is ALL.CAPS. This can
1105-
happen in certain circumstances beyond our control,
1106-
e.g. when software is installed under NT on a FAT
1107-
filesystem and then the same FAT filesystem is used
1108-
under Windows 95. */
1086+
return strncmp(data.cFileName, name, namelen) == 0;
1087+
1088+
/* DJGPP */
1089+
#elif defined(DJGPP)
1090+
struct ffblk ffblk;
1091+
int done;
1092+
1093+
if (getenv("PYTHONCASEOK") != NULL)
11091094
return 1;
1110-
}
1111-
if (strncmp(data.cFileName, name, namelen) != 0) {
1112-
strcpy(buf+len-namelen, data.cFileName);
1095+
1096+
done = findfirst(buf, &ffblk, FA_ARCH|FA_RDONLY|FA_HIDDEN|FA_DIREC);
1097+
if (done) {
11131098
PyErr_Format(PyExc_NameError,
1114-
"Case mismatch for module name %.100s\n(filename %.300s)",
1099+
"Can't find file for module %.100s\n(filename %.300s)",
11151100
name, buf);
11161101
return 0;
11171102
}
1118-
return 1;
1119-
}
1120-
#endif /* MS_WIN32 */
1103+
return strncmp(ffblk.ff_name, name, namelen) == 0;
11211104

1122-
#ifdef macintosh
1123-
#include <TextUtils.h>
1124-
#ifdef USE_GUSI1
1125-
#include "TFileSpec.h" /* for Path2FSSpec() */
1126-
#endif
1127-
static int
1128-
check_case(char *buf, int len, int namelen, char *name)
1129-
{
1105+
/* macintosh */
1106+
#elif defined(macintosh)
11301107
FSSpec fss;
11311108
OSErr err;
1109+
1110+
if (getenv("PYTHONCASEOK") != NULL)
1111+
return 1;
1112+
11321113
#ifndef USE_GUSI1
11331114
err = FSMakeFSSpec(0, 0, Pstring(buf), &fss);
11341115
#else
@@ -1154,48 +1135,16 @@ check_case(char *buf, int len, int namelen, char *name)
11541135
name, buf);
11551136
return 0;
11561137
}
1157-
if (namelen > fss.name[0] ||
1158-
strncmp(name, (char *)fss.name+1, namelen) != 0) {
1159-
PyErr_Format(PyExc_NameError,
1160-
"Case mismatch for module name %.100s\n(filename %.300s)",
1161-
name, fss.name);
1162-
return 0;
1163-
}
1164-
return 1;
1165-
}
1166-
#endif /* macintosh */
1167-
1168-
#ifdef DJGPP
1169-
#include <dir.h>
1170-
1171-
static int
1172-
check_case(char *buf, int len, int namelen, char *name)
1173-
{
1174-
struct ffblk ffblk;
1175-
int done;
1176-
1177-
if (getenv("PYTHONCASEOK") != NULL)
1178-
return 1;
1179-
done = findfirst(buf, &ffblk, FA_ARCH|FA_RDONLY|FA_HIDDEN|FA_DIREC);
1180-
if (done) {
1181-
PyErr_Format(PyExc_NameError,
1182-
"Can't find file for module %.100s\n(filename %.300s)",
1183-
name, buf);
1184-
return 0;
1185-
}
1138+
return fss.name[0] >= namelen &&
1139+
strncmp(name, (char *)fss.name+1, namelen) == 0;
11861140

1187-
if (strncmp(ffblk.ff_name, name, namelen) != 0) {
1188-
strcpy(buf+len-namelen, ffblk.ff_name);
1189-
PyErr_Format(PyExc_NameError,
1190-
"Case mismatch for module name %.100s\n(filename %.300s)",
1191-
name, buf);
1192-
return 0;
1193-
}
1141+
/* assuming it's a case-sensitive filesystem, so there's nothing to do! */
1142+
#else
11941143
return 1;
1195-
}
1144+
11961145
#endif
1146+
}
11971147

1198-
#endif /* CHECK_IMPORT_CASE */
11991148

12001149
#ifdef HAVE_STAT
12011150
/* Helper to look for __init__.py or __init__.py[co] in potential package */
@@ -1754,7 +1703,7 @@ import_submodule(PyObject *mod, char *subname, char *fullname)
17541703
else: mod.__name__ + "." + subname == fullname
17551704
*/
17561705

1757-
if ((m = PyDict_GetItemString(modules, fullname)) != NULL) {
1706+
if ((m = PyDict_GetItemString(modules, fullname)) != NULL) {
17581707
Py_INCREF(m);
17591708
}
17601709
else {
@@ -1929,7 +1878,7 @@ PyImport_Import(PyObject *module_name)
19291878
Py_XDECREF(globals);
19301879
Py_XDECREF(builtins);
19311880
Py_XDECREF(import);
1932-
1881+
19331882
return r;
19341883
}
19351884

@@ -2006,7 +1955,7 @@ call_find_module(char *name, PyObject *path)
20061955
else {
20071956
fob = Py_None;
20081957
Py_INCREF(fob);
2009-
}
1958+
}
20101959
ret = Py_BuildValue("Os(ssi)",
20111960
fob, pathname, fdp->suffix, fdp->mode, fdp->type);
20121961
Py_DECREF(fob);

0 commit comments

Comments
 (0)