the filename contains at least a rudimentary pathname.
(The bad part is that we need to call getcwd() because only a prefix
of ".\\" is not enough -- we prefix the drive letter.)
and lists; if the size is negative, raise an exception. Also raise an
exception when an undefined type is found -- all this to increase the
chance that garbage input causes an exception instead of a core dump.
swapped arguments].
Also make sure that no use of a function pointer gotten from a
tp_as_sequence or tp_as_mapping structure is made without checking it
for NULL first.
the code here becomes much simpler. In particular: abs(), divmod(),
pow(), int(), long(), float(), len(), tuple(), list().
Also make sure that no use of a function pointer gotten from a
tp_as_sequence or tp_as_mapping structure is made without checking it
for NULL first.
A few other cosmetic things, such as properly reindenting slice().
old value in a temporary and XDECREF it only after then new value has
been set. This prevents the (unlikely) case where the destructor of
the member uses the containing object -- it would find it in an
undefined state.
because the path through the code would notice that sys.__path__ did
not exist and it would fall back to the default path (builtins +
sys.path) instead of failing). No longer.
Date: Thu, 14 Sep 1995 12:18:20 -0400
From: Alan Morse <alan@dvcorp.com>
To: python-list@cwi.nl
Subject: getargs bug in 1.2 and 1.3 BETA
We have found a bug in the part of the getargs code that we added
and submitted, and which was incorporated into 1.1.
The parsing of "O?" format specifiers is not handled correctly;
there is no "else" for the "if" and therefore it can never fail.
What's worse, the advancing of the varargs pointer is not
handled properly, so from then on it is out of sync, wreaking
all sorts of havoc. (If it had failed properly, then the out-of-sync
varargs would not have been an issue.)
Below is the context diff for the change.
Note that I have made a few stylistic changes beyond adding the
else case, namely:
1) Making the "O" case follow the convention established by the other
format specifiers of getting all their vararg arguments before
performing the test, rather than getting some before and some after
the test passes.
2) Making the logic of the tests parallel, so the "if" part indicates
that the format is accepted and the "else" part indicates that the
format has failed. They were inconsistent with each other and with the
the other format specifiers.
-Alan Morse (amorse@dvcorp.com)
to the table of built-in modules. This should normally be called
*before* Py_Initialize(). When the malloc() or realloc() call fails,
-1 is returned and the existing table is unchanged.
After a similar function by Just van Rossum.
int PyImport_ExtendInittab(struct _inittab *newtab);
int PyImport_AppendInittab(char *name, void (*initfunc)());
Adapted from code submitted by Just van Rossum.
PySys_WriteStdout(format, ...)
PySys_WriteStderr(format, ...)
The first function writes to sys.stdout; the second to sys.stderr. When
there is a problem, they write to the real (C level) stdout or stderr;
no exceptions are raised (but a pending exception may be cleared when a
new exception is caught).
Both take a printf-style format string as their first argument followed
by a variable length argument list determined by the format string.
*** WARNING ***
The format should limit the total size of the formatted output string to
1000 bytes. In particular, this means that no unrestricted "%s" formats
should occur; these should be limited using "%.<N>s where <N> is a
decimal number calculated so that <N> plus the maximum size of other
formatted text does not exceed 1000 bytes. Also watch out for "%f",
which can print hundreds of digits for very large numbers.
PyThreadState_GetDict() returns a dictionary that can be used to hold such
state; the caller should pick a unique key and store its state there. If
PyThreadState_GetDict() returns NULL, an exception has been raised (most
likely MemoryError) and the caller should pass on the exception. */
PyObject *
PyThreadState_GetDict()
Frozen packages are indicated by a negative size (the code string
is the __import__.py file). A frozen package module has its __path__
set to a string, the package name.
time can be in PyImport_ImportModuleEx(). Recursive calls from the
same thread are okay.
Potential problems:
- The lock should really be part of the interpreter state rather than
global, but that would require modifying more files, and I first want
to figure out whether this works at all.
- One could argue that the lock should be per module -- however that
would be complicated to implement. We would have to have a linked
list of locks per module name, *or* invent a new object type to
represent a lock, so we can store the locks in the module or in a
separate dictionary. Both seem unwarranted. The one situation where
this can cause problems is when loading a module takes a long time,
e.g. when the module's initialization code interacts with the user --
during that time, no other threads can run. I say, "too bad."
(modified) and use that.
Some differences in the cleanup algorithm:
- Clear __main__ before the other modules.
- Delete more sys variables: including ps1, ps2, exitfunc, argv, and
even path -- this will prevent new imports!
- Restore stdin, stdout, stderr from __stdin__, __stdout__,
__stderr__, effectively deleting hooks that the user might have
installed -- so their (the hooks') destructors will run.
This is an option for OS-es with case-insensitive but case-preserving
filesystems. It is currently supported for Win32 and MacOS. To
enable it, #define CHECK_IMPORT_CASE in your platform specific
config.h. It is enabled by default on those systems where it is
supported. On Win32, it can be disabled at runtime by setting the
environment variable PYTHONCASEOK (to any value).
When enabled, the feature checks that the case of the requested module
name matches that of the filename found in the filesystem, and raises
a NameError exception when they don't match.
pass it the true file. This is used to set __file__ properly, instead
of believing what the code object carries with it. (If the pointer
is NULL, the code object's co_filename is still used.)
- Add Py_FrozenFlag, intended to suppress error messages fron
getpath.c in frozen binaries.
- Add Py_GetPythonHome() and Py_SetPythonHome(), intended to allow
embedders to force a different PYTHONHOME.
- Add new interface PyErr_PrintEx(flag); same as PyErr_Print() but
flag determines whether sys.last_* are set or not. PyErr_Print()
now simply calls PyErr_PrintEx(1).
(1) Explicitly clear __builtin__._ and sys.{last,exc}_* before
clearing anything else. These are common places where user values
hide and people complain when their destructors fail. Since the
modules containing them are deleted *last* of all, they would come too
late in the normal destruction order. Sigh.
(2) Add some debugging aid to cleanup (after a suggestion by Marc
Lemburg) -- print the names of the modules being cleaned, and (when
-vv is used) print the names of the variables being cleared.
now implement the following finalization strategy.
1. Whenever this code deletes a module, its directory is cleared
carefully, as follows:
- set all names to None that begin with exactly one underscore
- set all names to None that don't begin with two underscores
- clear the directory
2. Modules are deleted in the following order:
- modules with a reference count of 1, except __builtin__ or __sys__
- repeat until no more are found with a reference count of 1
- __main__ if it's still there
- all remaining modules except __builtin__ or sys
- sys
_ __builtin__
This is a bit of a hack: when the shared library is loaded, the module
name is "package.module", but the module calls Py_InitModule*() with just
"module" for the name. The shared library loader squirrels away the true
name of the module in _Py_PackageContext, and Py_InitModule*() will
substitute this (if the name actually matches).
1) The __builtins__ variable in the __main__ module is set to the
__builtin__ module instead of its __dict__.
2) Get rid of the SIGHUP and SIGTERM handlers. They can't be made to
work reliably when threads may be in use, they are Unix specific, and
Python programmers can now program this functionality is a safer way
using the signal module.
Setting interp->builtins to the __builtin__ module instead of to its
dictionary had the unfortunate side effect of always running in
restricted execution mode :-(
I will check in a different way of setting __main__.__builtins__ to
the __builtin__ module later.
Also, there was a typo -- a comment was unfinished, and as a result
some finalizations were not being executed.
In Bart Simpson style,
I Will Not Check In Untested Changes.
I Will Not Check In Untested Changes.
I Will Not Check In Untested Changes.
I Will Not Check In Untested Changes.
I Will Not Check In Untested Changes.
I Will Not Check In Untested Changes.
I Will Not Check In Untested Changes.
I Will Not Check In Untested Changes.
I Will Not Check In Untested Changes.
I Will Not Check In Untested Changes.
- The interp->builtins variable (and hence, __main__.__builtins__) is
once again initialized to the built-in *module* instead of its
dictionary.
- The finalization order is once again changed. Signals are finalized
relatively early, because (1) it DECREF's the signal handlers, and if
a signal handler happens to be a bound method, deleting it could cause
problems when there's no current thread around, and (2) we don't want
to risk executing signal handlers during finalization.
__init__.py (or __init__.pyc/.pyo, whichever applies) is considered a
package. All other subdirectories are left alone. Should make Konrad
Hinsen happy!
tstate swapping. Only the acquiring and releasing of the lock is
conditional (twice, under ``#ifdef WITH_THREAD'' and inside ``if
(interpreter_lock)'').
but annoying memory leak. This was introduced when PyExc_Exception
was added; the loop above populating the PyExc_StandardError exception
tuple started at index 1 in bltin_exc, but PyExc_Exception was added
at index 0, so PyExc_StandardError was getting inserted in itself!
How else can a tuple include itself?!
Change the loop to start at index 2.
This was a *fun* one! :-)