This is essentially a retroactive PEP: the issue came up too latein the 2.1 release process to solicit wide opinion before decidingwhat to do, and can’t be put off until 2.2 without also delayingthe Cygwin and MacOS X ports.
File systems vary across platforms in whether or not they preservethe case of filenames, and in whether or not the platform Clibrary file-opening functions do or don’t insist oncase-sensitive matches:
case-preservingcase-destroying+-------------------+------------------+case-sensitive|mostUnixflavors|brrrrrrrrrr|+-------------------+------------------+case-insensitive|Windows|someunfortunate||MacOSXHFS+|networkschemes||Cygwin||||OpenVMS|+-------------------+------------------+
In the upper left box, if you create “fiLe” it’s stored as “fiLe”,and onlyopen("fiLe") will open it (open("file") will not, norwill the 14 other variations on that theme).
In the lower right box, if you create “fiLe”, there’s no tellingwhat it’s stored as – but most likely as “FILE” – and any of the16 obvious variations onopen("FilE") will open it.
The lower left box is a mix: creating “fiLe” stores “fiLe” in theplatform directory, but you don’t have to match case when openingit; any of the 16 obvious variations onopen("FILe") work.
NONE OF THAT IS CHANGING! Python will continue to follow platformconventions w.r.t. whether case is preserved when creating a file,and w.r.t. whetheropen() requires a case-sensitive match. Inpractice, you should always code as if matches werecase-sensitive, else your program won’t be portable.
What’s proposed is to change the semantics of Python “import”statements, and thereonly in the lower left box.
Support for MacOSX HFS+, and for Cygwin, is new in 2.1, so nothingis changing there. What’s changing is Windows behavior. Here arethe current rules for import on Windows:
FiLe.py andfile.py onsys.path, and doimportfile
then if Python findsFiLe.py first, it raises aNameError.It doesnot go on to findfile.py; indeed, it’s impossible toimport any but the first case-insensitive match onsys.path,and then only if case matches exactly in the firstcase-insensitive match.
sys.path is for a file whose name is entirely in upper case(FILE.PY orFILE.PYC orFILE.PYO), then the import silentlygrabs that, no matter what mixture of case was used in theimport statement. This is apparently to cater to miserable oldfilesystems that really fit in the lower right box. But thisexception is unique to Windows, for reasons that may or may notexist.PYTHONCASEOKexists, Python silently grabs the first case-insensitive matchof any kind.So these Windows rules are pretty complicated, and neither matchthe Unix rules nor provide semantics natural for the nativefilesystem. That makes them hard to explain to Unixor Windowsusers. Nevertheless, they’ve worked fine for years, and inisolation there’s no compelling reason to change them.
However, that was before the MacOSX HFS+ and Cygwin ports arrived.They also have case-preserving case-insensitive filesystems, butthe people doing the ports despised the Windows rules. Indeed, apatch to make HFS+ act like Unix for imports got past a reviewerand into the code base, which incidentally made Cygwin also actlike Unix (but this met the unbounded approval of the Cygwinfolks, so they sure didn’t complain – they had patches of theirown pending to do this, but the reviewer for those balked).
At a higher level, we want to keep Python consistent, by followingthe same rules onall platforms with case-preservingcase-insensitive filesystems.
The proposed new semantics for the lower left box:
PYTHONCASEOK environment variable exists, same asbefore: silently accept the first case-insensitive match of anykind; raiseImportError if none found.sys.path for the first case-sensitive match; raiseImportError if none found.#B is the same rule as is used on Unix, so this will improvecross-platform portability. That’s good. #B is also the rule the Macand Cygwin folks want (and wanted enough to implement themselves,multiple times, which is a powerful argument in PythonLand). Itcan’t cause any existing non-exceptional Windows import to fail,because any existing non-exceptional Windows import finds acase-sensitive match first in the path – and it still will. Anexceptional Windows import currently blows up with aNameError orImportError, in which latter case it still will, or in whichformer case will continue searching, and either succeed or blow upwith anImportError.
#A is needed to cater to case-destroying filesystems mounted on Windows,andmay also be used by people so enamored of “natural” Windowsbehavior that they’re willing to set an environment variable toget it. I don’t intend to implement #A for Unix too, but that’sjust because I’m not clear on how Icould do so efficiently (I’mnot going to slow imports under Unix just for theoretical purity).
The potential damage is here: #2 (matching onALLCAPS.PY) isproposed to be dropped. Case-destroying filesystems are avanishing breed, and support for them is ugly. We’re alreadysupporting (and will continue to support)PYTHONCASEOK for theirbenefit, but they don’t deserve multiple hacks in 2001.
Source:https://github.com/python/peps/blob/main/peps/pep-0235.rst
Last modified:2025-02-01 08:59:27 GMT